blob: 3e3afeeb909a1bef8857704f525d0d04fa97407f [file] [log] [blame]
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001// Copyright 2012 the V8 project authors. All rights reserved.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
verwaest@chromium.org662436e2013-08-28 08:41:27 +000028#include <climits>
29#include <csignal>
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000030#include <string>
31#include <map>
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000032
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000033#include "v8.h"
34
verwaest@chromium.org662436e2013-08-28 08:41:27 +000035#if V8_OS_POSIX
36#include <unistd.h> // NOLINT
37#endif
38
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000039#include "api.h"
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +000040#include "arguments.h"
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000041#include "cctest.h"
machenbach@chromium.orgc1789ee2013-07-05 07:09:57 +000042#include "compilation-cache.h"
43#include "cpu-profiler.h"
44#include "execution.h"
45#include "isolate.h"
46#include "objects.h"
ager@chromium.org5b2fbee2010-09-08 06:38:15 +000047#include "parser.h"
machenbach@chromium.orgc1789ee2013-07-05 07:09:57 +000048#include "platform.h"
49#include "snapshot.h"
erik.corry@gmail.com4a6c3272010-11-18 12:04:40 +000050#include "unicode-inl.h"
machenbach@chromium.orgc1789ee2013-07-05 07:09:57 +000051#include "utils.h"
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +000052#include "vm-state.h"
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000053
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +000054static const bool kLogThreading = false;
ager@chromium.orgc4c92722009-11-18 14:12:51 +000055
danno@chromium.orgd3c42102013-08-01 16:58:23 +000056using ::v8::Boolean;
57using ::v8::BooleanObject;
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +000058using ::v8::Context;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000059using ::v8::Extension;
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +000060using ::v8::Function;
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000061using ::v8::FunctionTemplate;
62using ::v8::Handle;
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +000063using ::v8::HandleScope;
64using ::v8::Local;
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000065using ::v8::Message;
66using ::v8::MessageCallback;
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +000067using ::v8::Object;
68using ::v8::ObjectTemplate;
69using ::v8::Persistent;
70using ::v8::Script;
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000071using ::v8::StackTrace;
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +000072using ::v8::String;
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000073using ::v8::TryCatch;
74using ::v8::Undefined;
danno@chromium.orgca29dd82013-04-26 11:59:48 +000075using ::v8::UniqueId;
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +000076using ::v8::V8;
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000077using ::v8::Value;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000078
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000079
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000080#define THREADED_PROFILED_TEST(Name) \
81 static void Test##Name(); \
82 TEST(Name##WithProfiler) { \
83 RunWithProfiler(&Test##Name); \
84 } \
85 THREADED_TEST(Name)
machenbach@chromium.org528ce022013-09-23 14:09:36 +000086
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000087
88void RunWithProfiler(void (*test)()) {
89 LocalContext env;
90 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000091 v8::Local<v8::String> profile_name =
92 v8::String::NewFromUtf8(env->GetIsolate(), "my_profile1");
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000093 v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler();
94
95 cpu_profiler->StartCpuProfiling(profile_name);
96 (*test)();
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000097 reinterpret_cast<i::CpuProfiler*>(cpu_profiler)->DeleteAllProfiles();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000098}
99
100
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +0000101static void ExpectString(const char* code, const char* expected) {
102 Local<Value> result = CompileRun(code);
103 CHECK(result->IsString());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +0000104 String::Utf8Value utf8(result);
105 CHECK_EQ(expected, *utf8);
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +0000106}
107
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000108
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000109static void ExpectInt32(const char* code, int expected) {
110 Local<Value> result = CompileRun(code);
111 CHECK(result->IsInt32());
112 CHECK_EQ(expected, result->Int32Value());
113}
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +0000114
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000115
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +0000116static void ExpectBoolean(const char* code, bool expected) {
117 Local<Value> result = CompileRun(code);
118 CHECK(result->IsBoolean());
119 CHECK_EQ(expected, result->BooleanValue());
120}
121
122
kmillikin@chromium.org9155e252010-05-26 13:27:57 +0000123static void ExpectTrue(const char* code) {
124 ExpectBoolean(code, true);
125}
126
127
ager@chromium.orgea4f62e2010-08-16 16:28:43 +0000128static void ExpectFalse(const char* code) {
129 ExpectBoolean(code, false);
130}
131
132
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +0000133static void ExpectObject(const char* code, Local<Value> expected) {
134 Local<Value> result = CompileRun(code);
135 CHECK(result->Equals(expected));
136}
137
138
ager@chromium.orgea4f62e2010-08-16 16:28:43 +0000139static void ExpectUndefined(const char* code) {
140 Local<Value> result = CompileRun(code);
141 CHECK(result->IsUndefined());
142}
143
144
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000145static int signature_callback_count;
jkummerow@chromium.org2c9426b2013-09-05 16:31:13 +0000146static Local<Value> signature_expected_receiver;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000147static void IncrementingSignatureCallback(
148 const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000149 ApiTestFuzzer::Fuzz();
150 signature_callback_count++;
jkummerow@chromium.org2c9426b2013-09-05 16:31:13 +0000151 CHECK_EQ(signature_expected_receiver, args.Holder());
152 CHECK_EQ(signature_expected_receiver, args.This());
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000153 v8::Handle<v8::Array> result =
154 v8::Array::New(args.GetIsolate(), args.Length());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000155 for (int i = 0; i < args.Length(); i++)
ulan@chromium.org0f13e742014-01-03 15:51:11 +0000156 result->Set(v8::Integer::New(args.GetIsolate(), i), args[i]);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000157 args.GetReturnValue().Set(result);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000158}
159
160
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000161static void SignatureCallback(
162 const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000163 ApiTestFuzzer::Fuzz();
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000164 v8::Handle<v8::Array> result =
165 v8::Array::New(args.GetIsolate(), args.Length());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000166 for (int i = 0; i < args.Length(); i++) {
ulan@chromium.org0f13e742014-01-03 15:51:11 +0000167 result->Set(v8::Integer::New(args.GetIsolate(), i), args[i]);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000168 }
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000169 args.GetReturnValue().Set(result);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000170}
171
172
dslomov@chromium.org639bac02013-09-09 11:58:54 +0000173// Tests that call v8::V8::Dispose() cannot be threaded.
174TEST(InitializeAndDisposeOnce) {
175 CHECK(v8::V8::Initialize());
176 CHECK(v8::V8::Dispose());
177}
178
179
180// Tests that call v8::V8::Dispose() cannot be threaded.
181TEST(InitializeAndDisposeMultiple) {
182 for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
183 for (int i = 0; i < 3; ++i) CHECK(v8::V8::Initialize());
184 for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
185 // TODO(mstarzinger): This should fail gracefully instead of asserting.
186 // for (int i = 0; i < 3; ++i) CHECK(v8::V8::Initialize());
187 for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
188}
189
190
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000191THREADED_TEST(Handles) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000192 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000193 Local<Context> local_env;
194 {
195 LocalContext env;
196 local_env = env.local();
197 }
198
199 // Local context should still be live.
200 CHECK(!local_env.IsEmpty());
201 local_env->Enter();
202
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +0000203 v8::Handle<v8::Primitive> undef = v8::Undefined(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000204 CHECK(!undef.IsEmpty());
205 CHECK(undef->IsUndefined());
206
207 const char* c_source = "1 + 2 + 3";
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000208 Local<String> source = String::NewFromUtf8(CcTest::isolate(), c_source);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000209 Local<Script> script = Script::Compile(source);
210 CHECK_EQ(6, script->Run()->Int32Value());
211
212 local_env->Exit();
213}
214
215
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000216THREADED_TEST(IsolateOfContext) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000217 v8::HandleScope scope(CcTest::isolate());
218 v8::Handle<Context> env = Context::New(CcTest::isolate());
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000219
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000220 CHECK(!env->GetIsolate()->InContext());
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000221 CHECK(env->GetIsolate() == CcTest::isolate());
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000222 env->Enter();
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000223 CHECK(env->GetIsolate()->InContext());
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000224 CHECK(env->GetIsolate() == CcTest::isolate());
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000225 env->Exit();
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000226 CHECK(!env->GetIsolate()->InContext());
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000227 CHECK(env->GetIsolate() == CcTest::isolate());
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000228}
229
230
dslomov@chromium.org639bac02013-09-09 11:58:54 +0000231static void TestSignature(const char* loop_js, Local<Value> receiver) {
232 i::ScopedVector<char> source(200);
233 i::OS::SNPrintF(source,
234 "for (var i = 0; i < 10; i++) {"
235 " %s"
236 "}",
237 loop_js);
238 signature_callback_count = 0;
239 signature_expected_receiver = receiver;
240 bool expected_to_throw = receiver.IsEmpty();
241 v8::TryCatch try_catch;
242 CompileRun(source.start());
243 CHECK_EQ(expected_to_throw, try_catch.HasCaught());
244 if (!expected_to_throw) {
245 CHECK_EQ(10, signature_callback_count);
246 } else {
247 CHECK_EQ(v8_str("TypeError: Illegal invocation"),
248 try_catch.Exception()->ToString());
249 }
250}
251
252
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000253THREADED_TEST(ReceiverSignature) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000254 LocalContext env;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +0000255 v8::Isolate* isolate = env->GetIsolate();
256 v8::HandleScope scope(isolate);
dslomov@chromium.org639bac02013-09-09 11:58:54 +0000257 // Setup templates.
hpayer@chromium.org4f99be92013-12-18 16:23:55 +0000258 v8::Handle<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(isolate);
259 v8::Handle<v8::Signature> sig = v8::Signature::New(isolate, fun);
dslomov@chromium.org639bac02013-09-09 11:58:54 +0000260 v8::Handle<v8::FunctionTemplate> callback_sig =
261 v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +0000262 isolate, IncrementingSignatureCallback, Local<Value>(), sig);
dslomov@chromium.org639bac02013-09-09 11:58:54 +0000263 v8::Handle<v8::FunctionTemplate> callback =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +0000264 v8::FunctionTemplate::New(isolate, IncrementingSignatureCallback);
265 v8::Handle<v8::FunctionTemplate> sub_fun = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000266 sub_fun->Inherit(fun);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +0000267 v8::Handle<v8::FunctionTemplate> unrel_fun =
268 v8::FunctionTemplate::New(isolate);
dslomov@chromium.org639bac02013-09-09 11:58:54 +0000269 // Install properties.
270 v8::Handle<v8::ObjectTemplate> fun_proto = fun->PrototypeTemplate();
271 fun_proto->Set(v8_str("prop_sig"), callback_sig);
272 fun_proto->Set(v8_str("prop"), callback);
273 fun_proto->SetAccessorProperty(
274 v8_str("accessor_sig"), callback_sig, callback_sig);
275 fun_proto->SetAccessorProperty(v8_str("accessor"), callback, callback);
276 // Instantiate templates.
277 Local<Value> fun_instance = fun->InstanceTemplate()->NewInstance();
278 Local<Value> sub_fun_instance = sub_fun->InstanceTemplate()->NewInstance();
279 // Setup global variables.
280 env->Global()->Set(v8_str("Fun"), fun->GetFunction());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000281 env->Global()->Set(v8_str("UnrelFun"), unrel_fun->GetFunction());
dslomov@chromium.org639bac02013-09-09 11:58:54 +0000282 env->Global()->Set(v8_str("fun_instance"), fun_instance);
283 env->Global()->Set(v8_str("sub_fun_instance"), sub_fun_instance);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000284 CompileRun(
dslomov@chromium.org639bac02013-09-09 11:58:54 +0000285 "var accessor_sig_key = 'accessor_sig';"
286 "var accessor_key = 'accessor';"
287 "var prop_sig_key = 'prop_sig';"
288 "var prop_key = 'prop';"
289 ""
290 "function copy_props(obj) {"
291 " var keys = [accessor_sig_key, accessor_key, prop_sig_key, prop_key];"
292 " var source = Fun.prototype;"
293 " for (var i in keys) {"
294 " var key = keys[i];"
295 " var desc = Object.getOwnPropertyDescriptor(source, key);"
296 " Object.defineProperty(obj, key, desc);"
297 " }"
298 "}"
299 ""
300 "var obj = {};"
301 "copy_props(obj);"
302 "var unrel = new UnrelFun();"
303 "copy_props(unrel);");
304 // Test with and without ICs
305 const char* test_objects[] = {
306 "fun_instance", "sub_fun_instance", "obj", "unrel" };
307 unsigned bad_signature_start_offset = 2;
308 for (unsigned i = 0; i < ARRAY_SIZE(test_objects); i++) {
309 i::ScopedVector<char> source(200);
310 i::OS::SNPrintF(
311 source, "var test_object = %s; test_object", test_objects[i]);
312 Local<Value> test_object = CompileRun(source.start());
313 TestSignature("test_object.prop();", test_object);
314 TestSignature("test_object.accessor;", test_object);
315 TestSignature("test_object[accessor_key];", test_object);
316 TestSignature("test_object.accessor = 1;", test_object);
317 TestSignature("test_object[accessor_key] = 1;", test_object);
318 if (i >= bad_signature_start_offset) test_object = Local<Value>();
319 TestSignature("test_object.prop_sig();", test_object);
320 TestSignature("test_object.accessor_sig;", test_object);
321 TestSignature("test_object[accessor_sig_key];", test_object);
322 TestSignature("test_object.accessor_sig = 1;", test_object);
323 TestSignature("test_object[accessor_sig_key] = 1;", test_object);
324 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000325}
326
327
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000328THREADED_TEST(ArgumentSignature) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000329 LocalContext env;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +0000330 v8::Isolate* isolate = env->GetIsolate();
331 v8::HandleScope scope(isolate);
332 v8::Handle<v8::FunctionTemplate> cons = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000333 cons->SetClassName(v8_str("Cons"));
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000334 v8::Handle<v8::Signature> sig = v8::Signature::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +0000335 isolate, v8::Handle<v8::FunctionTemplate>(), 1, &cons);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000336 v8::Handle<v8::FunctionTemplate> fun =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +0000337 v8::FunctionTemplate::New(isolate,
338 SignatureCallback,
339 v8::Handle<Value>(),
340 sig);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000341 env->Global()->Set(v8_str("Cons"), cons->GetFunction());
342 env->Global()->Set(v8_str("Fun1"), fun->GetFunction());
343
344 v8::Handle<Value> value1 = CompileRun("Fun1(4) == '';");
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000345 CHECK(value1->IsTrue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000346
347 v8::Handle<Value> value2 = CompileRun("Fun1(new Cons()) == '[object Cons]';");
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000348 CHECK(value2->IsTrue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000349
350 v8::Handle<Value> value3 = CompileRun("Fun1() == '';");
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000351 CHECK(value3->IsTrue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000352
hpayer@chromium.org4f99be92013-12-18 16:23:55 +0000353 v8::Handle<v8::FunctionTemplate> cons1 = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000354 cons1->SetClassName(v8_str("Cons1"));
hpayer@chromium.org4f99be92013-12-18 16:23:55 +0000355 v8::Handle<v8::FunctionTemplate> cons2 = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000356 cons2->SetClassName(v8_str("Cons2"));
hpayer@chromium.org4f99be92013-12-18 16:23:55 +0000357 v8::Handle<v8::FunctionTemplate> cons3 = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000358 cons3->SetClassName(v8_str("Cons3"));
359
360 v8::Handle<v8::FunctionTemplate> args[3] = { cons1, cons2, cons3 };
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000361 v8::Handle<v8::Signature> wsig = v8::Signature::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +0000362 isolate, v8::Handle<v8::FunctionTemplate>(), 3, args);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000363 v8::Handle<v8::FunctionTemplate> fun2 =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +0000364 v8::FunctionTemplate::New(isolate,
365 SignatureCallback,
366 v8::Handle<Value>(),
367 wsig);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000368
369 env->Global()->Set(v8_str("Cons1"), cons1->GetFunction());
370 env->Global()->Set(v8_str("Cons2"), cons2->GetFunction());
371 env->Global()->Set(v8_str("Cons3"), cons3->GetFunction());
372 env->Global()->Set(v8_str("Fun2"), fun2->GetFunction());
373 v8::Handle<Value> value4 = CompileRun(
374 "Fun2(new Cons1(), new Cons2(), new Cons3()) =="
375 "'[object Cons1],[object Cons2],[object Cons3]'");
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000376 CHECK(value4->IsTrue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000377
378 v8::Handle<Value> value5 = CompileRun(
379 "Fun2(new Cons1(), new Cons2(), 5) == '[object Cons1],[object Cons2],'");
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000380 CHECK(value5->IsTrue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000381
382 v8::Handle<Value> value6 = CompileRun(
383 "Fun2(new Cons3(), new Cons2(), new Cons1()) == ',[object Cons2],'");
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000384 CHECK(value6->IsTrue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000385
386 v8::Handle<Value> value7 = CompileRun(
387 "Fun2(new Cons1(), new Cons2(), new Cons3(), 'd') == "
388 "'[object Cons1],[object Cons2],[object Cons3],d';");
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000389 CHECK(value7->IsTrue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000390
391 v8::Handle<Value> value8 = CompileRun(
392 "Fun2(new Cons1(), new Cons2()) == '[object Cons1],[object Cons2]'");
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000393 CHECK(value8->IsTrue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000394}
395
396
397THREADED_TEST(HulIgennem) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000398 LocalContext env;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +0000399 v8::Isolate* isolate = env->GetIsolate();
400 v8::HandleScope scope(isolate);
401 v8::Handle<v8::Primitive> undef = v8::Undefined(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000402 Local<String> undef_str = undef->ToString();
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000403 char* value = i::NewArray<char>(undef_str->Utf8Length() + 1);
404 undef_str->WriteUtf8(value);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000405 CHECK_EQ(0, strcmp(value, "undefined"));
406 i::DeleteArray(value);
407}
408
409
410THREADED_TEST(Access) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000411 LocalContext env;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +0000412 v8::Isolate* isolate = env->GetIsolate();
413 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +0000414 Local<v8::Object> obj = v8::Object::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000415 Local<Value> foo_before = obj->Get(v8_str("foo"));
416 CHECK(foo_before->IsUndefined());
417 Local<String> bar_str = v8_str("bar");
418 obj->Set(v8_str("foo"), bar_str);
419 Local<Value> foo_after = obj->Get(v8_str("foo"));
420 CHECK(!foo_after->IsUndefined());
421 CHECK(foo_after->IsString());
422 CHECK_EQ(bar_str, foo_after);
423}
424
425
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000426THREADED_TEST(AccessElement) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000427 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000428 v8::HandleScope scope(env->GetIsolate());
ulan@chromium.org0f13e742014-01-03 15:51:11 +0000429 Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000430 Local<Value> before = obj->Get(1);
431 CHECK(before->IsUndefined());
432 Local<String> bar_str = v8_str("bar");
433 obj->Set(1, bar_str);
434 Local<Value> after = obj->Get(1);
435 CHECK(!after->IsUndefined());
436 CHECK(after->IsString());
437 CHECK_EQ(bar_str, after);
438
439 Local<v8::Array> value = CompileRun("[\"a\", \"b\"]").As<v8::Array>();
440 CHECK_EQ(v8_str("a"), value->Get(0));
441 CHECK_EQ(v8_str("b"), value->Get(1));
442}
443
444
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000445THREADED_TEST(Script) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000446 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000447 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000448 const char* c_source = "1 + 2 + 3";
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000449 Local<String> source = String::NewFromUtf8(env->GetIsolate(), c_source);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000450 Local<Script> script = Script::Compile(source);
451 CHECK_EQ(6, script->Run()->Int32Value());
452}
453
454
455static uint16_t* AsciiToTwoByteString(const char* source) {
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000456 int array_length = i::StrLength(source) + 1;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000457 uint16_t* converted = i::NewArray<uint16_t>(array_length);
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000458 for (int i = 0; i < array_length; i++) converted[i] = source[i];
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000459 return converted;
460}
461
462
463class TestResource: public String::ExternalStringResource {
464 public:
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000465 explicit TestResource(uint16_t* data, int* counter = NULL)
466 : data_(data), length_(0), counter_(counter) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000467 while (data[length_]) ++length_;
468 }
469
470 ~TestResource() {
471 i::DeleteArray(data_);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000472 if (counter_ != NULL) ++*counter_;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000473 }
474
475 const uint16_t* data() const {
476 return data_;
477 }
478
479 size_t length() const {
480 return length_;
481 }
482 private:
483 uint16_t* data_;
484 size_t length_;
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000485 int* counter_;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000486};
487
488
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000489class TestAsciiResource: public String::ExternalAsciiStringResource {
490 public:
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000491 explicit TestAsciiResource(const char* data, int* counter = NULL)
492 : data_(data), length_(strlen(data)), counter_(counter) { }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000493
494 ~TestAsciiResource() {
495 i::DeleteArray(data_);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000496 if (counter_ != NULL) ++*counter_;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000497 }
498
499 const char* data() const {
500 return data_;
501 }
502
503 size_t length() const {
504 return length_;
505 }
506 private:
ager@chromium.org5ec48922009-05-05 07:25:34 +0000507 const char* data_;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000508 size_t length_;
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000509 int* counter_;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000510};
511
512
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000513THREADED_TEST(ScriptUsingStringResource) {
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000514 int dispose_count = 0;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000515 const char* c_source = "1 + 2 * 3";
516 uint16_t* two_byte_source = AsciiToTwoByteString(c_source);
517 {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000518 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000519 v8::HandleScope scope(env->GetIsolate());
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000520 TestResource* resource = new TestResource(two_byte_source, &dispose_count);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000521 Local<String> source = String::NewExternal(env->GetIsolate(), resource);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000522 Local<Script> script = Script::Compile(source);
523 Local<Value> value = script->Run();
524 CHECK(value->IsNumber());
525 CHECK_EQ(7, value->Int32Value());
526 CHECK(source->IsExternal());
527 CHECK_EQ(resource,
528 static_cast<TestResource*>(source->GetExternalStringResource()));
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000529 String::Encoding encoding = String::UNKNOWN_ENCODING;
530 CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
531 source->GetExternalStringResourceBase(&encoding));
532 CHECK_EQ(String::TWO_BYTE_ENCODING, encoding);
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000533 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000534 CHECK_EQ(0, dispose_count);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000535 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000536 CcTest::i_isolate()->compilation_cache()->Clear();
537 CcTest::heap()->CollectAllAvailableGarbage();
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000538 CHECK_EQ(1, dispose_count);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000539}
540
541
542THREADED_TEST(ScriptUsingAsciiStringResource) {
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000543 int dispose_count = 0;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000544 const char* c_source = "1 + 2 * 3";
545 {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000546 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000547 v8::HandleScope scope(env->GetIsolate());
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000548 TestAsciiResource* resource = new TestAsciiResource(i::StrDup(c_source),
549 &dispose_count);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000550 Local<String> source = String::NewExternal(env->GetIsolate(), resource);
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000551 CHECK(source->IsExternalAscii());
552 CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
553 source->GetExternalAsciiStringResource());
554 String::Encoding encoding = String::UNKNOWN_ENCODING;
555 CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
556 source->GetExternalStringResourceBase(&encoding));
557 CHECK_EQ(String::ASCII_ENCODING, encoding);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000558 Local<Script> script = Script::Compile(source);
559 Local<Value> value = script->Run();
560 CHECK(value->IsNumber());
561 CHECK_EQ(7, value->Int32Value());
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000562 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000563 CHECK_EQ(0, dispose_count);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000564 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000565 CcTest::i_isolate()->compilation_cache()->Clear();
566 CcTest::heap()->CollectAllAvailableGarbage();
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000567 CHECK_EQ(1, dispose_count);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000568}
569
570
ager@chromium.org6f10e412009-02-13 10:11:16 +0000571THREADED_TEST(ScriptMakingExternalString) {
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000572 int dispose_count = 0;
ager@chromium.org6f10e412009-02-13 10:11:16 +0000573 uint16_t* two_byte_source = AsciiToTwoByteString("1 + 2 * 3");
574 {
ager@chromium.org6f10e412009-02-13 10:11:16 +0000575 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000576 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000577 Local<String> source =
578 String::NewFromTwoByte(env->GetIsolate(), two_byte_source);
ager@chromium.org5c838252010-02-19 08:53:10 +0000579 // Trigger GCs so that the newly allocated string moves to old gen.
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000580 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
581 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000582 CHECK_EQ(source->IsExternal(), false);
583 CHECK_EQ(source->IsExternalAscii(), false);
584 String::Encoding encoding = String::UNKNOWN_ENCODING;
585 CHECK_EQ(NULL, source->GetExternalStringResourceBase(&encoding));
586 CHECK_EQ(String::ASCII_ENCODING, encoding);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000587 bool success = source->MakeExternal(new TestResource(two_byte_source,
588 &dispose_count));
ager@chromium.org6f10e412009-02-13 10:11:16 +0000589 CHECK(success);
590 Local<Script> script = Script::Compile(source);
591 Local<Value> value = script->Run();
592 CHECK(value->IsNumber());
593 CHECK_EQ(7, value->Int32Value());
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000594 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000595 CHECK_EQ(0, dispose_count);
ager@chromium.org6f10e412009-02-13 10:11:16 +0000596 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000597 CcTest::i_isolate()->compilation_cache()->Clear();
598 CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000599 CHECK_EQ(1, dispose_count);
ager@chromium.org6f10e412009-02-13 10:11:16 +0000600}
601
602
603THREADED_TEST(ScriptMakingExternalAsciiString) {
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000604 int dispose_count = 0;
ager@chromium.org6f10e412009-02-13 10:11:16 +0000605 const char* c_source = "1 + 2 * 3";
606 {
ager@chromium.org6f10e412009-02-13 10:11:16 +0000607 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000608 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org6f10e412009-02-13 10:11:16 +0000609 Local<String> source = v8_str(c_source);
ager@chromium.org5c838252010-02-19 08:53:10 +0000610 // Trigger GCs so that the newly allocated string moves to old gen.
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000611 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
612 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
ager@chromium.org6f10e412009-02-13 10:11:16 +0000613 bool success = source->MakeExternal(
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000614 new TestAsciiResource(i::StrDup(c_source), &dispose_count));
ager@chromium.org6f10e412009-02-13 10:11:16 +0000615 CHECK(success);
616 Local<Script> script = Script::Compile(source);
617 Local<Value> value = script->Run();
618 CHECK(value->IsNumber());
619 CHECK_EQ(7, value->Int32Value());
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000620 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000621 CHECK_EQ(0, dispose_count);
ager@chromium.org6f10e412009-02-13 10:11:16 +0000622 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000623 CcTest::i_isolate()->compilation_cache()->Clear();
624 CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000625 CHECK_EQ(1, dispose_count);
ager@chromium.org6f10e412009-02-13 10:11:16 +0000626}
627
628
ager@chromium.org5c838252010-02-19 08:53:10 +0000629TEST(MakingExternalStringConditions) {
ager@chromium.org5c838252010-02-19 08:53:10 +0000630 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000631 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org5c838252010-02-19 08:53:10 +0000632
633 // Free some space in the new space so that we can check freshness.
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000634 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
635 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
ager@chromium.org5c838252010-02-19 08:53:10 +0000636
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000637 uint16_t* two_byte_string = AsciiToTwoByteString("s1");
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000638 Local<String> small_string =
639 String::NewFromTwoByte(env->GetIsolate(), two_byte_string);
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000640 i::DeleteArray(two_byte_string);
641
ager@chromium.org5c838252010-02-19 08:53:10 +0000642 // We should refuse to externalize newly created small string.
643 CHECK(!small_string->CanMakeExternal());
644 // Trigger GCs so that the newly allocated string moves to old gen.
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000645 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
646 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
ager@chromium.org5c838252010-02-19 08:53:10 +0000647 // Old space strings should be accepted.
648 CHECK(small_string->CanMakeExternal());
649
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000650 two_byte_string = AsciiToTwoByteString("small string 2");
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000651 small_string = String::NewFromTwoByte(env->GetIsolate(), two_byte_string);
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000652 i::DeleteArray(two_byte_string);
653
ager@chromium.org5c838252010-02-19 08:53:10 +0000654 // We should refuse externalizing newly created small string.
655 CHECK(!small_string->CanMakeExternal());
656 for (int i = 0; i < 100; i++) {
657 String::Value value(small_string);
658 }
659 // Frequently used strings should be accepted.
660 CHECK(small_string->CanMakeExternal());
661
662 const int buf_size = 10 * 1024;
663 char* buf = i::NewArray<char>(buf_size);
664 memset(buf, 'a', buf_size);
665 buf[buf_size - 1] = '\0';
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000666
667 two_byte_string = AsciiToTwoByteString(buf);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000668 Local<String> large_string =
669 String::NewFromTwoByte(env->GetIsolate(), two_byte_string);
ager@chromium.org5c838252010-02-19 08:53:10 +0000670 i::DeleteArray(buf);
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000671 i::DeleteArray(two_byte_string);
ager@chromium.org5c838252010-02-19 08:53:10 +0000672 // Large strings should be immediately accepted.
673 CHECK(large_string->CanMakeExternal());
674}
675
676
677TEST(MakingExternalAsciiStringConditions) {
ager@chromium.org5c838252010-02-19 08:53:10 +0000678 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000679 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org5c838252010-02-19 08:53:10 +0000680
681 // Free some space in the new space so that we can check freshness.
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000682 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
683 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
ager@chromium.org5c838252010-02-19 08:53:10 +0000684
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000685 Local<String> small_string = String::NewFromUtf8(env->GetIsolate(), "s1");
ager@chromium.org5c838252010-02-19 08:53:10 +0000686 // We should refuse to externalize newly created small string.
687 CHECK(!small_string->CanMakeExternal());
688 // Trigger GCs so that the newly allocated string moves to old gen.
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000689 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
690 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
ager@chromium.org5c838252010-02-19 08:53:10 +0000691 // Old space strings should be accepted.
692 CHECK(small_string->CanMakeExternal());
693
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000694 small_string = String::NewFromUtf8(env->GetIsolate(), "small string 2");
ager@chromium.org5c838252010-02-19 08:53:10 +0000695 // We should refuse externalizing newly created small string.
696 CHECK(!small_string->CanMakeExternal());
697 for (int i = 0; i < 100; i++) {
698 String::Value value(small_string);
699 }
700 // Frequently used strings should be accepted.
701 CHECK(small_string->CanMakeExternal());
702
703 const int buf_size = 10 * 1024;
704 char* buf = i::NewArray<char>(buf_size);
705 memset(buf, 'a', buf_size);
706 buf[buf_size - 1] = '\0';
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000707 Local<String> large_string = String::NewFromUtf8(env->GetIsolate(), buf);
ager@chromium.org5c838252010-02-19 08:53:10 +0000708 i::DeleteArray(buf);
709 // Large strings should be immediately accepted.
710 CHECK(large_string->CanMakeExternal());
711}
712
713
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000714TEST(MakingExternalUnalignedAsciiString) {
715 LocalContext env;
716 v8::HandleScope scope(env->GetIsolate());
717
718 CompileRun("function cons(a, b) { return a + b; }"
719 "function slice(a) { return a.substring(1); }");
720 // Create a cons string that will land in old pointer space.
721 Local<String> cons = Local<String>::Cast(CompileRun(
722 "cons('abcdefghijklm', 'nopqrstuvwxyz');"));
723 // Create a sliced string that will land in old pointer space.
724 Local<String> slice = Local<String>::Cast(CompileRun(
725 "slice('abcdefghijklmnopqrstuvwxyz');"));
726
727 // Trigger GCs so that the newly allocated string moves to old gen.
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000728 SimulateFullSpace(CcTest::heap()->old_pointer_space());
729 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
730 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000731
732 // Turn into external string with unaligned resource data.
733 int dispose_count = 0;
734 const char* c_cons = "_abcdefghijklmnopqrstuvwxyz";
735 bool success = cons->MakeExternal(
736 new TestAsciiResource(i::StrDup(c_cons) + 1, &dispose_count));
737 CHECK(success);
738 const char* c_slice = "_bcdefghijklmnopqrstuvwxyz";
739 success = slice->MakeExternal(
740 new TestAsciiResource(i::StrDup(c_slice) + 1, &dispose_count));
741 CHECK(success);
742
743 // Trigger GCs and force evacuation.
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000744 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
745 CcTest::heap()->CollectAllGarbage(i::Heap::kReduceMemoryFootprintMask);
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000746}
747
748
ager@chromium.org6f10e412009-02-13 10:11:16 +0000749THREADED_TEST(UsingExternalString) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000750 i::Factory* factory = CcTest::i_isolate()->factory();
ager@chromium.orge2902be2009-06-08 12:21:35 +0000751 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000752 v8::HandleScope scope(CcTest::isolate());
ager@chromium.orge2902be2009-06-08 12:21:35 +0000753 uint16_t* two_byte_string = AsciiToTwoByteString("test string");
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000754 Local<String> string = String::NewExternal(
755 CcTest::isolate(), new TestResource(two_byte_string));
ager@chromium.orge2902be2009-06-08 12:21:35 +0000756 i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
757 // Trigger GCs so that the newly allocated string moves to old gen.
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000758 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
759 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000760 i::Handle<i::String> isymbol =
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000761 factory->InternalizedStringFromString(istring);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000762 CHECK(isymbol->IsInternalizedString());
ager@chromium.orge2902be2009-06-08 12:21:35 +0000763 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000764 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
765 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org6f10e412009-02-13 10:11:16 +0000766}
767
768
769THREADED_TEST(UsingExternalAsciiString) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000770 i::Factory* factory = CcTest::i_isolate()->factory();
ager@chromium.orge2902be2009-06-08 12:21:35 +0000771 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000772 v8::HandleScope scope(CcTest::isolate());
ager@chromium.orge2902be2009-06-08 12:21:35 +0000773 const char* one_byte_string = "test string";
774 Local<String> string = String::NewExternal(
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000775 CcTest::isolate(), new TestAsciiResource(i::StrDup(one_byte_string)));
ager@chromium.orge2902be2009-06-08 12:21:35 +0000776 i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
777 // Trigger GCs so that the newly allocated string moves to old gen.
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000778 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
779 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000780 i::Handle<i::String> isymbol =
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000781 factory->InternalizedStringFromString(istring);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000782 CHECK(isymbol->IsInternalizedString());
ager@chromium.orge2902be2009-06-08 12:21:35 +0000783 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000784 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
785 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org6f10e412009-02-13 10:11:16 +0000786}
787
788
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000789THREADED_TEST(ScavengeExternalString) {
svenpanne@chromium.org83130cf2012-11-30 10:13:25 +0000790 i::FLAG_stress_compaction = false;
791 i::FLAG_gc_global = false;
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000792 int dispose_count = 0;
lrn@chromium.orgc34f5802010-04-28 12:53:43 +0000793 bool in_new_space = false;
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000794 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000795 v8::HandleScope scope(CcTest::isolate());
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000796 uint16_t* two_byte_string = AsciiToTwoByteString("test string");
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000797 Local<String> string = String::NewExternal(
798 CcTest::isolate(), new TestResource(two_byte_string, &dispose_count));
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000799 i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000800 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
801 in_new_space = CcTest::heap()->InNewSpace(*istring);
802 CHECK(in_new_space || CcTest::heap()->old_data_space()->Contains(*istring));
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000803 CHECK_EQ(0, dispose_count);
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000804 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000805 CcTest::heap()->CollectGarbage(
806 in_new_space ? i::NEW_SPACE : i::OLD_DATA_SPACE);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000807 CHECK_EQ(1, dispose_count);
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000808}
809
810
811THREADED_TEST(ScavengeExternalAsciiString) {
svenpanne@chromium.org83130cf2012-11-30 10:13:25 +0000812 i::FLAG_stress_compaction = false;
813 i::FLAG_gc_global = false;
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000814 int dispose_count = 0;
lrn@chromium.orgc34f5802010-04-28 12:53:43 +0000815 bool in_new_space = false;
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000816 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000817 v8::HandleScope scope(CcTest::isolate());
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000818 const char* one_byte_string = "test string";
819 Local<String> string = String::NewExternal(
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000820 CcTest::isolate(),
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000821 new TestAsciiResource(i::StrDup(one_byte_string), &dispose_count));
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000822 i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000823 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
824 in_new_space = CcTest::heap()->InNewSpace(*istring);
825 CHECK(in_new_space || CcTest::heap()->old_data_space()->Contains(*istring));
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000826 CHECK_EQ(0, dispose_count);
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000827 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000828 CcTest::heap()->CollectGarbage(
829 in_new_space ? i::NEW_SPACE : i::OLD_DATA_SPACE);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000830 CHECK_EQ(1, dispose_count);
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000831}
832
833
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000834class TestAsciiResourceWithDisposeControl: public TestAsciiResource {
835 public:
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000836 // Only used by non-threaded tests, so it can use static fields.
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000837 static int dispose_calls;
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000838 static int dispose_count;
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000839
840 TestAsciiResourceWithDisposeControl(const char* data, bool dispose)
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000841 : TestAsciiResource(data, &dispose_count),
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000842 dispose_(dispose) { }
843
844 void Dispose() {
845 ++dispose_calls;
846 if (dispose_) delete this;
847 }
848 private:
849 bool dispose_;
850};
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000851
852
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000853int TestAsciiResourceWithDisposeControl::dispose_count = 0;
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000854int TestAsciiResourceWithDisposeControl::dispose_calls = 0;
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000855
856
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000857TEST(ExternalStringWithDisposeHandling) {
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000858 const char* c_source = "1 + 2 * 3";
859
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000860 // Use a stack allocated external string resource allocated object.
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000861 TestAsciiResourceWithDisposeControl::dispose_count = 0;
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000862 TestAsciiResourceWithDisposeControl::dispose_calls = 0;
863 TestAsciiResourceWithDisposeControl res_stack(i::StrDup(c_source), false);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000864 {
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000865 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000866 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000867 Local<String> source = String::NewExternal(env->GetIsolate(), &res_stack);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000868 Local<Script> script = Script::Compile(source);
869 Local<Value> value = script->Run();
870 CHECK(value->IsNumber());
871 CHECK_EQ(7, value->Int32Value());
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000872 CcTest::heap()->CollectAllAvailableGarbage();
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000873 CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000874 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000875 CcTest::i_isolate()->compilation_cache()->Clear();
876 CcTest::heap()->CollectAllAvailableGarbage();
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000877 CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_calls);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000878 CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000879
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000880 // Use a heap allocated external string resource allocated object.
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000881 TestAsciiResourceWithDisposeControl::dispose_count = 0;
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000882 TestAsciiResourceWithDisposeControl::dispose_calls = 0;
883 TestAsciiResource* res_heap =
884 new TestAsciiResourceWithDisposeControl(i::StrDup(c_source), true);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000885 {
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000886 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000887 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000888 Local<String> source = String::NewExternal(env->GetIsolate(), res_heap);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000889 Local<Script> script = Script::Compile(source);
890 Local<Value> value = script->Run();
891 CHECK(value->IsNumber());
892 CHECK_EQ(7, value->Int32Value());
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000893 CcTest::heap()->CollectAllAvailableGarbage();
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000894 CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000895 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000896 CcTest::i_isolate()->compilation_cache()->Clear();
897 CcTest::heap()->CollectAllAvailableGarbage();
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000898 CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_calls);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000899 CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_count);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000900}
901
902
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000903THREADED_TEST(StringConcat) {
904 {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000905 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000906 v8::HandleScope scope(env->GetIsolate());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000907 const char* one_byte_string_1 = "function a_times_t";
908 const char* two_byte_string_1 = "wo_plus_b(a, b) {return ";
909 const char* one_byte_extern_1 = "a * 2 + b;} a_times_two_plus_b(4, 8) + ";
910 const char* two_byte_extern_1 = "a_times_two_plus_b(4, 8) + ";
911 const char* one_byte_string_2 = "a_times_two_plus_b(4, 8) + ";
912 const char* two_byte_string_2 = "a_times_two_plus_b(4, 8) + ";
913 const char* two_byte_extern_2 = "a_times_two_plus_b(1, 2);";
914 Local<String> left = v8_str(one_byte_string_1);
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000915
916 uint16_t* two_byte_source = AsciiToTwoByteString(two_byte_string_1);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000917 Local<String> right =
918 String::NewFromTwoByte(env->GetIsolate(), two_byte_source);
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000919 i::DeleteArray(two_byte_source);
920
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000921 Local<String> source = String::Concat(left, right);
922 right = String::NewExternal(
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000923 env->GetIsolate(), new TestAsciiResource(i::StrDup(one_byte_extern_1)));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000924 source = String::Concat(source, right);
925 right = String::NewExternal(
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000926 env->GetIsolate(),
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000927 new TestResource(AsciiToTwoByteString(two_byte_extern_1)));
928 source = String::Concat(source, right);
929 right = v8_str(one_byte_string_2);
930 source = String::Concat(source, right);
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000931
932 two_byte_source = AsciiToTwoByteString(two_byte_string_2);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000933 right = String::NewFromTwoByte(env->GetIsolate(), two_byte_source);
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000934 i::DeleteArray(two_byte_source);
935
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000936 source = String::Concat(source, right);
937 right = String::NewExternal(
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000938 env->GetIsolate(),
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000939 new TestResource(AsciiToTwoByteString(two_byte_extern_2)));
940 source = String::Concat(source, right);
941 Local<Script> script = Script::Compile(source);
942 Local<Value> value = script->Run();
943 CHECK(value->IsNumber());
944 CHECK_EQ(68, value->Int32Value());
945 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000946 CcTest::i_isolate()->compilation_cache()->Clear();
947 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
948 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000949}
950
951
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000952THREADED_TEST(GlobalProperties) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000953 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000954 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000955 v8::Handle<v8::Object> global = env->Global();
956 global->Set(v8_str("pi"), v8_num(3.1415926));
957 Local<Value> pi = global->Get(v8_str("pi"));
958 CHECK_EQ(3.1415926, pi->NumberValue());
959}
960
961
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +0000962template<typename T>
dslomov@chromium.orgb752d402013-06-18 11:54:54 +0000963static void CheckReturnValue(const T& t, i::Address callback) {
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +0000964 v8::ReturnValue<v8::Value> rv = t.GetReturnValue();
965 i::Object** o = *reinterpret_cast<i::Object***>(&rv);
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000966 CHECK_EQ(CcTest::isolate(), t.GetIsolate());
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +0000967 CHECK_EQ(t.GetIsolate(), rv.GetIsolate());
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +0000968 CHECK((*o)->IsTheHole() || (*o)->IsUndefined());
verwaest@chromium.org8a00e822013-06-10 15:11:22 +0000969 // Verify reset
970 bool is_runtime = (*o)->IsTheHole();
971 rv.Set(true);
972 CHECK(!(*o)->IsTheHole() && !(*o)->IsUndefined());
973 rv.Set(v8::Handle<v8::Object>());
974 CHECK((*o)->IsTheHole() || (*o)->IsUndefined());
975 CHECK_EQ(is_runtime, (*o)->IsTheHole());
dslomov@chromium.orgb752d402013-06-18 11:54:54 +0000976
977 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(t.GetIsolate());
978 // If CPU profiler is active check that when API callback is invoked
979 // VMState is set to EXTERNAL.
980 if (isolate->cpu_profiler()->is_profiling()) {
981 CHECK_EQ(i::EXTERNAL, isolate->current_vm_state());
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +0000982 CHECK(isolate->external_callback_scope());
983 CHECK_EQ(callback, isolate->external_callback_scope()->callback());
dslomov@chromium.orgb752d402013-06-18 11:54:54 +0000984 }
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +0000985}
986
dslomov@chromium.orgb752d402013-06-18 11:54:54 +0000987
988static void handle_callback_impl(const v8::FunctionCallbackInfo<Value>& info,
989 i::Address callback) {
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +0000990 ApiTestFuzzer::Fuzz();
dslomov@chromium.orgb752d402013-06-18 11:54:54 +0000991 CheckReturnValue(info, callback);
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +0000992 info.GetReturnValue().Set(v8_str("bad value"));
993 info.GetReturnValue().Set(v8_num(102));
994}
995
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000996
dslomov@chromium.orgb752d402013-06-18 11:54:54 +0000997static void handle_callback(const v8::FunctionCallbackInfo<Value>& info) {
998 return handle_callback_impl(info, FUNCTION_ADDR(handle_callback));
999}
1000
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001001
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00001002static void handle_callback_2(const v8::FunctionCallbackInfo<Value>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001003 return handle_callback_impl(info, FUNCTION_ADDR(handle_callback_2));
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00001004}
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001005
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001006static void construct_callback(
1007 const v8::FunctionCallbackInfo<Value>& info) {
1008 ApiTestFuzzer::Fuzz();
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001009 CheckReturnValue(info, FUNCTION_ADDR(construct_callback));
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001010 info.This()->Set(v8_str("x"), v8_num(1));
1011 info.This()->Set(v8_str("y"), v8_num(2));
1012 info.GetReturnValue().Set(v8_str("bad value"));
1013 info.GetReturnValue().Set(info.This());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +00001014}
1015
1016
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001017static void Return239Callback(
1018 Local<String> name, const v8::PropertyCallbackInfo<Value>& info) {
1019 ApiTestFuzzer::Fuzz();
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001020 CheckReturnValue(info, FUNCTION_ADDR(Return239Callback));
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001021 info.GetReturnValue().Set(v8_str("bad value"));
1022 info.GetReturnValue().Set(v8_num(239));
1023}
1024
1025
1026template<typename Handler>
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00001027static void TestFunctionTemplateInitializer(Handler handler,
1028 Handler handler_2) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001029 // Test constructor calls.
1030 {
1031 LocalContext env;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001032 v8::Isolate* isolate = env->GetIsolate();
1033 v8::HandleScope scope(isolate);
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001034
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001035 Local<v8::FunctionTemplate> fun_templ =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001036 v8::FunctionTemplate::New(isolate, handler);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001037 Local<Function> fun = fun_templ->GetFunction();
1038 env->Global()->Set(v8_str("obj"), fun);
1039 Local<Script> script = v8_compile("obj()");
1040 for (int i = 0; i < 30; i++) {
1041 CHECK_EQ(102, script->Run()->Int32Value());
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001042 }
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001043 }
1044 // Use SetCallHandler to initialize a function template, should work like
1045 // the previous one.
1046 {
1047 LocalContext env;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001048 v8::Isolate* isolate = env->GetIsolate();
1049 v8::HandleScope scope(isolate);
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001050
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001051 Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(isolate);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001052 fun_templ->SetCallHandler(handler_2);
1053 Local<Function> fun = fun_templ->GetFunction();
1054 env->Global()->Set(v8_str("obj"), fun);
1055 Local<Script> script = v8_compile("obj()");
1056 for (int i = 0; i < 30; i++) {
1057 CHECK_EQ(102, script->Run()->Int32Value());
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001058 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001059 }
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001060}
1061
1062
1063template<typename Constructor, typename Accessor>
1064static void TestFunctionTemplateAccessor(Constructor constructor,
1065 Accessor accessor) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001066 LocalContext env;
1067 v8::HandleScope scope(env->GetIsolate());
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001068
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001069 Local<v8::FunctionTemplate> fun_templ =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001070 v8::FunctionTemplate::New(env->GetIsolate(), constructor);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001071 fun_templ->SetClassName(v8_str("funky"));
1072 fun_templ->InstanceTemplate()->SetAccessor(v8_str("m"), accessor);
1073 Local<Function> fun = fun_templ->GetFunction();
1074 env->Global()->Set(v8_str("obj"), fun);
1075 Local<Value> result = v8_compile("(new obj()).toString()")->Run();
1076 CHECK_EQ(v8_str("[object funky]"), result);
1077 CompileRun("var obj_instance = new obj();");
1078 Local<Script> script;
1079 script = v8_compile("obj_instance.x");
1080 for (int i = 0; i < 30; i++) {
1081 CHECK_EQ(1, script->Run()->Int32Value());
1082 }
1083 script = v8_compile("obj_instance.m");
1084 for (int i = 0; i < 30; i++) {
1085 CHECK_EQ(239, script->Run()->Int32Value());
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001086 }
1087}
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001088
ager@chromium.orgb61a0d12010-10-13 08:35:23 +00001089
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001090THREADED_PROFILED_TEST(FunctionTemplate) {
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00001091 TestFunctionTemplateInitializer(handle_callback, handle_callback_2);
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001092 TestFunctionTemplateAccessor(construct_callback, Return239Callback);
1093}
1094
1095
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001096static void SimpleCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
1097 ApiTestFuzzer::Fuzz();
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001098 CheckReturnValue(info, FUNCTION_ADDR(SimpleCallback));
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001099 info.GetReturnValue().Set(v8_num(51423 + info.Length()));
1100}
1101
1102
1103template<typename Callback>
1104static void TestSimpleCallback(Callback callback) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001105 LocalContext env;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00001106 v8::Isolate* isolate = env->GetIsolate();
1107 v8::HandleScope scope(isolate);
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001108
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00001109 v8::Handle<v8::ObjectTemplate> object_template =
1110 v8::ObjectTemplate::New(isolate);
1111 object_template->Set(isolate, "callback",
1112 v8::FunctionTemplate::New(isolate, callback));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001113 v8::Local<v8::Object> object = object_template->NewInstance();
1114 (*env)->Global()->Set(v8_str("callback_object"), object);
1115 v8::Handle<v8::Script> script;
1116 script = v8_compile("callback_object.callback(17)");
1117 for (int i = 0; i < 30; i++) {
1118 CHECK_EQ(51424, script->Run()->Int32Value());
1119 }
1120 script = v8_compile("callback_object.callback(17, 24)");
1121 for (int i = 0; i < 30; i++) {
1122 CHECK_EQ(51425, script->Run()->Int32Value());
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001123 }
1124}
1125
1126
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001127THREADED_PROFILED_TEST(SimpleCallback) {
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001128 TestSimpleCallback(SimpleCallback);
1129}
1130
1131
1132template<typename T>
1133void FastReturnValueCallback(const v8::FunctionCallbackInfo<v8::Value>& info);
1134
1135// constant return values
danno@chromium.org1fd77d52013-06-07 16:01:45 +00001136static int32_t fast_return_value_int32 = 471;
1137static uint32_t fast_return_value_uint32 = 571;
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001138static const double kFastReturnValueDouble = 2.7;
1139// variable return values
1140static bool fast_return_value_bool = false;
ulan@chromium.org837a67e2013-06-11 15:39:48 +00001141enum ReturnValueOddball {
1142 kNullReturnValue,
1143 kUndefinedReturnValue,
1144 kEmptyStringReturnValue
1145};
1146static ReturnValueOddball fast_return_value_void;
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00001147static bool fast_return_value_object_is_empty = false;
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001148
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001149// Helper function to avoid compiler error: insufficient contextual information
1150// to determine type when applying FUNCTION_ADDR to a template function.
1151static i::Address address_of(v8::FunctionCallback callback) {
1152 return FUNCTION_ADDR(callback);
1153}
1154
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001155template<>
1156void FastReturnValueCallback<int32_t>(
1157 const v8::FunctionCallbackInfo<v8::Value>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001158 CheckReturnValue(info, address_of(FastReturnValueCallback<int32_t>));
danno@chromium.org1fd77d52013-06-07 16:01:45 +00001159 info.GetReturnValue().Set(fast_return_value_int32);
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001160}
1161
1162template<>
1163void FastReturnValueCallback<uint32_t>(
1164 const v8::FunctionCallbackInfo<v8::Value>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001165 CheckReturnValue(info, address_of(FastReturnValueCallback<uint32_t>));
danno@chromium.org1fd77d52013-06-07 16:01:45 +00001166 info.GetReturnValue().Set(fast_return_value_uint32);
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001167}
1168
1169template<>
1170void FastReturnValueCallback<double>(
1171 const v8::FunctionCallbackInfo<v8::Value>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001172 CheckReturnValue(info, address_of(FastReturnValueCallback<double>));
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +00001173 info.GetReturnValue().Set(kFastReturnValueDouble);
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001174}
1175
1176template<>
1177void FastReturnValueCallback<bool>(
1178 const v8::FunctionCallbackInfo<v8::Value>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001179 CheckReturnValue(info, address_of(FastReturnValueCallback<bool>));
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +00001180 info.GetReturnValue().Set(fast_return_value_bool);
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001181}
1182
1183template<>
1184void FastReturnValueCallback<void>(
1185 const v8::FunctionCallbackInfo<v8::Value>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001186 CheckReturnValue(info, address_of(FastReturnValueCallback<void>));
ulan@chromium.org837a67e2013-06-11 15:39:48 +00001187 switch (fast_return_value_void) {
1188 case kNullReturnValue:
1189 info.GetReturnValue().SetNull();
1190 break;
1191 case kUndefinedReturnValue:
1192 info.GetReturnValue().SetUndefined();
1193 break;
1194 case kEmptyStringReturnValue:
1195 info.GetReturnValue().SetEmptyString();
1196 break;
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001197 }
1198}
1199
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +00001200template<>
1201void FastReturnValueCallback<Object>(
1202 const v8::FunctionCallbackInfo<v8::Value>& info) {
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00001203 v8::Handle<v8::Object> object;
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001204 if (!fast_return_value_object_is_empty) {
1205 object = Object::New(info.GetIsolate());
1206 }
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00001207 info.GetReturnValue().Set(object);
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +00001208}
1209
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001210template<typename T>
1211Handle<Value> TestFastReturnValues() {
1212 LocalContext env;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00001213 v8::Isolate* isolate = env->GetIsolate();
1214 v8::EscapableHandleScope scope(isolate);
1215 v8::Handle<v8::ObjectTemplate> object_template =
1216 v8::ObjectTemplate::New(isolate);
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001217 v8::FunctionCallback callback = &FastReturnValueCallback<T>;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00001218 object_template->Set(isolate, "callback",
1219 v8::FunctionTemplate::New(isolate, callback));
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001220 v8::Local<v8::Object> object = object_template->NewInstance();
1221 (*env)->Global()->Set(v8_str("callback_object"), object);
machenbach@chromium.orgafbdadc2013-12-09 16:12:18 +00001222 return scope.Escape(CompileRun("callback_object.callback()"));
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001223}
1224
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001225
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001226THREADED_PROFILED_TEST(FastReturnValues) {
danno@chromium.org1fd77d52013-06-07 16:01:45 +00001227 LocalContext env;
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001228 v8::HandleScope scope(CcTest::isolate());
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001229 v8::Handle<v8::Value> value;
danno@chromium.org1fd77d52013-06-07 16:01:45 +00001230 // check int32_t and uint32_t
1231 int32_t int_values[] = {
1232 0, 234, -723,
1233 i::Smi::kMinValue, i::Smi::kMaxValue
1234 };
1235 for (size_t i = 0; i < ARRAY_SIZE(int_values); i++) {
1236 for (int modifier = -1; modifier <= 1; modifier++) {
1237 int int_value = int_values[i] + modifier;
1238 // check int32_t
1239 fast_return_value_int32 = int_value;
1240 value = TestFastReturnValues<int32_t>();
1241 CHECK(value->IsInt32());
1242 CHECK(fast_return_value_int32 == value->Int32Value());
1243 // check uint32_t
1244 fast_return_value_uint32 = static_cast<uint32_t>(int_value);
1245 value = TestFastReturnValues<uint32_t>();
1246 CHECK(value->IsUint32());
1247 CHECK(fast_return_value_uint32 == value->Uint32Value());
1248 }
1249 }
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001250 // check double
1251 value = TestFastReturnValues<double>();
1252 CHECK(value->IsNumber());
1253 CHECK_EQ(kFastReturnValueDouble, value->ToNumber()->Value());
1254 // check bool values
1255 for (int i = 0; i < 2; i++) {
1256 fast_return_value_bool = i == 0;
1257 value = TestFastReturnValues<bool>();
1258 CHECK(value->IsBoolean());
1259 CHECK_EQ(fast_return_value_bool, value->ToBoolean()->Value());
1260 }
1261 // check oddballs
ulan@chromium.org837a67e2013-06-11 15:39:48 +00001262 ReturnValueOddball oddballs[] = {
1263 kNullReturnValue,
1264 kUndefinedReturnValue,
1265 kEmptyStringReturnValue
1266 };
1267 for (size_t i = 0; i < ARRAY_SIZE(oddballs); i++) {
1268 fast_return_value_void = oddballs[i];
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001269 value = TestFastReturnValues<void>();
ulan@chromium.org837a67e2013-06-11 15:39:48 +00001270 switch (fast_return_value_void) {
1271 case kNullReturnValue:
1272 CHECK(value->IsNull());
1273 break;
1274 case kUndefinedReturnValue:
1275 CHECK(value->IsUndefined());
1276 break;
1277 case kEmptyStringReturnValue:
1278 CHECK(value->IsString());
1279 CHECK_EQ(0, v8::String::Cast(*value)->Length());
1280 break;
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001281 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001282 }
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00001283 // check handles
1284 fast_return_value_object_is_empty = false;
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +00001285 value = TestFastReturnValues<Object>();
1286 CHECK(value->IsObject());
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00001287 fast_return_value_object_is_empty = true;
1288 value = TestFastReturnValues<Object>();
1289 CHECK(value->IsUndefined());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001290}
1291
1292
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001293THREADED_TEST(FunctionTemplateSetLength) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001294 LocalContext env;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001295 v8::Isolate* isolate = env->GetIsolate();
1296 v8::HandleScope scope(isolate);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001297 {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001298 Local<v8::FunctionTemplate> fun_templ =
1299 v8::FunctionTemplate::New(isolate,
1300 handle_callback,
1301 Handle<v8::Value>(),
1302 Handle<v8::Signature>(),
1303 23);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001304 Local<Function> fun = fun_templ->GetFunction();
1305 env->Global()->Set(v8_str("obj"), fun);
1306 Local<Script> script = v8_compile("obj.length");
1307 CHECK_EQ(23, script->Run()->Int32Value());
1308 }
1309 {
1310 Local<v8::FunctionTemplate> fun_templ =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001311 v8::FunctionTemplate::New(isolate, handle_callback);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001312 fun_templ->SetLength(22);
1313 Local<Function> fun = fun_templ->GetFunction();
1314 env->Global()->Set(v8_str("obj"), fun);
1315 Local<Script> script = v8_compile("obj.length");
1316 CHECK_EQ(22, script->Run()->Int32Value());
1317 }
1318 {
1319 // Without setting length it defaults to 0.
1320 Local<v8::FunctionTemplate> fun_templ =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001321 v8::FunctionTemplate::New(isolate, handle_callback);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001322 Local<Function> fun = fun_templ->GetFunction();
1323 env->Global()->Set(v8_str("obj"), fun);
1324 Local<Script> script = v8_compile("obj.length");
1325 CHECK_EQ(0, script->Run()->Int32Value());
1326 }
1327}
1328
1329
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001330static void* expected_ptr;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001331static void callback(const v8::FunctionCallbackInfo<v8::Value>& args) {
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00001332 void* ptr = v8::External::Cast(*args.Data())->Value();
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001333 CHECK_EQ(expected_ptr, ptr);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001334 args.GetReturnValue().Set(true);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001335}
1336
1337
1338static void TestExternalPointerWrapping() {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001339 LocalContext env;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001340 v8::Isolate* isolate = env->GetIsolate();
1341 v8::HandleScope scope(isolate);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001342
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00001343 v8::Handle<v8::Value> data =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001344 v8::External::New(isolate, expected_ptr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001345
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001346 v8::Handle<v8::Object> obj = v8::Object::New(isolate);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001347 obj->Set(v8_str("func"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001348 v8::FunctionTemplate::New(isolate, callback, data)->GetFunction());
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001349 env->Global()->Set(v8_str("obj"), obj);
1350
1351 CHECK(CompileRun(
1352 "function foo() {\n"
1353 " for (var i = 0; i < 13; i++) obj.func();\n"
1354 "}\n"
1355 "foo(), true")->BooleanValue());
1356}
1357
1358
1359THREADED_TEST(ExternalWrap) {
1360 // Check heap allocated object.
1361 int* ptr = new int;
1362 expected_ptr = ptr;
1363 TestExternalPointerWrapping();
1364 delete ptr;
1365
1366 // Check stack allocated object.
1367 int foo;
1368 expected_ptr = &foo;
1369 TestExternalPointerWrapping();
1370
1371 // Check not aligned addresses.
1372 const int n = 100;
1373 char* s = new char[n];
1374 for (int i = 0; i < n; i++) {
1375 expected_ptr = s + i;
1376 TestExternalPointerWrapping();
1377 }
1378
1379 delete[] s;
1380
1381 // Check several invalid addresses.
1382 expected_ptr = reinterpret_cast<void*>(1);
1383 TestExternalPointerWrapping();
1384
1385 expected_ptr = reinterpret_cast<void*>(0xdeadbeef);
1386 TestExternalPointerWrapping();
1387
1388 expected_ptr = reinterpret_cast<void*>(0xdeadbeef + 1);
1389 TestExternalPointerWrapping();
1390
1391#if defined(V8_HOST_ARCH_X64)
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001392 // Check a value with a leading 1 bit in x64 Smi encoding.
1393 expected_ptr = reinterpret_cast<void*>(0x400000000);
1394 TestExternalPointerWrapping();
1395
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001396 expected_ptr = reinterpret_cast<void*>(0xdeadbeefdeadbeef);
1397 TestExternalPointerWrapping();
1398
1399 expected_ptr = reinterpret_cast<void*>(0xdeadbeefdeadbeef + 1);
1400 TestExternalPointerWrapping();
1401#endif
1402}
1403
1404
sgjesse@chromium.org900d3b72009-08-07 11:24:25 +00001405THREADED_TEST(FindInstanceInPrototypeChain) {
sgjesse@chromium.org900d3b72009-08-07 11:24:25 +00001406 LocalContext env;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001407 v8::Isolate* isolate = env->GetIsolate();
1408 v8::HandleScope scope(isolate);
sgjesse@chromium.org900d3b72009-08-07 11:24:25 +00001409
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001410 Local<v8::FunctionTemplate> base = v8::FunctionTemplate::New(isolate);
1411 Local<v8::FunctionTemplate> derived = v8::FunctionTemplate::New(isolate);
1412 Local<v8::FunctionTemplate> other = v8::FunctionTemplate::New(isolate);
sgjesse@chromium.org900d3b72009-08-07 11:24:25 +00001413 derived->Inherit(base);
1414
1415 Local<v8::Function> base_function = base->GetFunction();
1416 Local<v8::Function> derived_function = derived->GetFunction();
1417 Local<v8::Function> other_function = other->GetFunction();
1418
1419 Local<v8::Object> base_instance = base_function->NewInstance();
1420 Local<v8::Object> derived_instance = derived_function->NewInstance();
1421 Local<v8::Object> derived_instance2 = derived_function->NewInstance();
1422 Local<v8::Object> other_instance = other_function->NewInstance();
1423 derived_instance2->Set(v8_str("__proto__"), derived_instance);
1424 other_instance->Set(v8_str("__proto__"), derived_instance2);
1425
1426 // base_instance is only an instance of base.
1427 CHECK_EQ(base_instance,
1428 base_instance->FindInstanceInPrototypeChain(base));
1429 CHECK(base_instance->FindInstanceInPrototypeChain(derived).IsEmpty());
1430 CHECK(base_instance->FindInstanceInPrototypeChain(other).IsEmpty());
1431
1432 // derived_instance is an instance of base and derived.
1433 CHECK_EQ(derived_instance,
1434 derived_instance->FindInstanceInPrototypeChain(base));
1435 CHECK_EQ(derived_instance,
1436 derived_instance->FindInstanceInPrototypeChain(derived));
1437 CHECK(derived_instance->FindInstanceInPrototypeChain(other).IsEmpty());
1438
1439 // other_instance is an instance of other and its immediate
1440 // prototype derived_instance2 is an instance of base and derived.
1441 // Note, derived_instance is an instance of base and derived too,
1442 // but it comes after derived_instance2 in the prototype chain of
1443 // other_instance.
1444 CHECK_EQ(derived_instance2,
1445 other_instance->FindInstanceInPrototypeChain(base));
1446 CHECK_EQ(derived_instance2,
1447 other_instance->FindInstanceInPrototypeChain(derived));
1448 CHECK_EQ(other_instance,
1449 other_instance->FindInstanceInPrototypeChain(other));
1450}
1451
1452
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001453THREADED_TEST(TinyInteger) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001454 LocalContext env;
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001455 v8::Isolate* isolate = env->GetIsolate();
1456 v8::HandleScope scope(isolate);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001457
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001458 int32_t value = 239;
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001459 Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001460 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001461
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001462 value_obj = v8::Integer::New(isolate, value);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001463 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001464}
1465
1466
1467THREADED_TEST(BigSmiInteger) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001468 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001469 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001470 v8::Isolate* isolate = CcTest::isolate();
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001471
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001472 int32_t value = i::Smi::kMaxValue;
1473 // We cannot add one to a Smi::kMaxValue without wrapping.
verwaest@chromium.org662436e2013-08-28 08:41:27 +00001474 if (i::SmiValuesAre31Bits()) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001475 CHECK(i::Smi::IsValid(value));
1476 CHECK(!i::Smi::IsValid(value + 1));
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001477
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001478 Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001479 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001480
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001481 value_obj = v8::Integer::New(isolate, value);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001482 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001483 }
1484}
1485
1486
1487THREADED_TEST(BigInteger) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001488 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001489 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001490 v8::Isolate* isolate = CcTest::isolate();
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001491
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001492 // We cannot add one to a Smi::kMaxValue without wrapping.
verwaest@chromium.org662436e2013-08-28 08:41:27 +00001493 if (i::SmiValuesAre31Bits()) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001494 // The casts allow this to compile, even if Smi::kMaxValue is 2^31-1.
1495 // The code will not be run in that case, due to the "if" guard.
1496 int32_t value =
1497 static_cast<int32_t>(static_cast<uint32_t>(i::Smi::kMaxValue) + 1);
1498 CHECK(value > i::Smi::kMaxValue);
1499 CHECK(!i::Smi::IsValid(value));
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001500
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001501 Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001502 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001503
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001504 value_obj = v8::Integer::New(isolate, value);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001505 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001506 }
1507}
1508
1509
1510THREADED_TEST(TinyUnsignedInteger) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001511 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001512 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001513 v8::Isolate* isolate = CcTest::isolate();
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001514
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001515 uint32_t value = 239;
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001516
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001517 Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001518 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001519
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001520 value_obj = v8::Integer::NewFromUnsigned(isolate, value);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001521 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001522}
1523
1524
1525THREADED_TEST(BigUnsignedSmiInteger) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001526 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001527 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001528 v8::Isolate* isolate = CcTest::isolate();
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001529
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001530 uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue);
1531 CHECK(i::Smi::IsValid(value));
1532 CHECK(!i::Smi::IsValid(value + 1));
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001533
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001534 Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001535 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001536
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001537 value_obj = v8::Integer::NewFromUnsigned(isolate, value);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001538 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001539}
1540
1541
1542THREADED_TEST(BigUnsignedInteger) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001543 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001544 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001545 v8::Isolate* isolate = CcTest::isolate();
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001546
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001547 uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue) + 1;
1548 CHECK(value > static_cast<uint32_t>(i::Smi::kMaxValue));
1549 CHECK(!i::Smi::IsValid(value));
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001550
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001551 Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001552 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001553
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001554 value_obj = v8::Integer::NewFromUnsigned(isolate, value);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001555 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001556}
1557
1558
1559THREADED_TEST(OutOfSignedRangeUnsignedInteger) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001560 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001561 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001562 v8::Isolate* isolate = CcTest::isolate();
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001563
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001564 uint32_t INT32_MAX_AS_UINT = (1U << 31) - 1;
1565 uint32_t value = INT32_MAX_AS_UINT + 1;
1566 CHECK(value > INT32_MAX_AS_UINT); // No overflow.
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001567
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001568 Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001569 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001570
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001571 value_obj = v8::Integer::NewFromUnsigned(isolate, value);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001572 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001573}
1574
1575
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001576THREADED_TEST(IsNativeError) {
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001577 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001578 v8::HandleScope scope(env->GetIsolate());
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001579 v8::Handle<Value> syntax_error = CompileRun(
1580 "var out = 0; try { eval(\"#\"); } catch(x) { out = x; } out; ");
1581 CHECK(syntax_error->IsNativeError());
1582 v8::Handle<Value> not_error = CompileRun("{a:42}");
1583 CHECK(!not_error->IsNativeError());
1584 v8::Handle<Value> not_object = CompileRun("42");
1585 CHECK(!not_object->IsNativeError());
1586}
1587
1588
1589THREADED_TEST(StringObject) {
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001590 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001591 v8::HandleScope scope(env->GetIsolate());
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001592 v8::Handle<Value> boxed_string = CompileRun("new String(\"test\")");
1593 CHECK(boxed_string->IsStringObject());
1594 v8::Handle<Value> unboxed_string = CompileRun("\"test\"");
1595 CHECK(!unboxed_string->IsStringObject());
1596 v8::Handle<Value> boxed_not_string = CompileRun("new Number(42)");
1597 CHECK(!boxed_not_string->IsStringObject());
1598 v8::Handle<Value> not_object = CompileRun("0");
1599 CHECK(!not_object->IsStringObject());
1600 v8::Handle<v8::StringObject> as_boxed = boxed_string.As<v8::StringObject>();
1601 CHECK(!as_boxed.IsEmpty());
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001602 Local<v8::String> the_string = as_boxed->ValueOf();
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001603 CHECK(!the_string.IsEmpty());
1604 ExpectObject("\"test\"", the_string);
1605 v8::Handle<v8::Value> new_boxed_string = v8::StringObject::New(the_string);
1606 CHECK(new_boxed_string->IsStringObject());
1607 as_boxed = new_boxed_string.As<v8::StringObject>();
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001608 the_string = as_boxed->ValueOf();
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001609 CHECK(!the_string.IsEmpty());
1610 ExpectObject("\"test\"", the_string);
1611}
1612
1613
1614THREADED_TEST(NumberObject) {
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001615 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001616 v8::HandleScope scope(env->GetIsolate());
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001617 v8::Handle<Value> boxed_number = CompileRun("new Number(42)");
1618 CHECK(boxed_number->IsNumberObject());
1619 v8::Handle<Value> unboxed_number = CompileRun("42");
1620 CHECK(!unboxed_number->IsNumberObject());
1621 v8::Handle<Value> boxed_not_number = CompileRun("new Boolean(false)");
1622 CHECK(!boxed_not_number->IsNumberObject());
1623 v8::Handle<v8::NumberObject> as_boxed = boxed_number.As<v8::NumberObject>();
1624 CHECK(!as_boxed.IsEmpty());
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001625 double the_number = as_boxed->ValueOf();
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001626 CHECK_EQ(42.0, the_number);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00001627 v8::Handle<v8::Value> new_boxed_number =
1628 v8::NumberObject::New(env->GetIsolate(), 43);
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001629 CHECK(new_boxed_number->IsNumberObject());
1630 as_boxed = new_boxed_number.As<v8::NumberObject>();
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001631 the_number = as_boxed->ValueOf();
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001632 CHECK_EQ(43.0, the_number);
1633}
1634
1635
1636THREADED_TEST(BooleanObject) {
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001637 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001638 v8::HandleScope scope(env->GetIsolate());
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001639 v8::Handle<Value> boxed_boolean = CompileRun("new Boolean(true)");
1640 CHECK(boxed_boolean->IsBooleanObject());
1641 v8::Handle<Value> unboxed_boolean = CompileRun("true");
1642 CHECK(!unboxed_boolean->IsBooleanObject());
1643 v8::Handle<Value> boxed_not_boolean = CompileRun("new Number(42)");
1644 CHECK(!boxed_not_boolean->IsBooleanObject());
1645 v8::Handle<v8::BooleanObject> as_boxed =
1646 boxed_boolean.As<v8::BooleanObject>();
1647 CHECK(!as_boxed.IsEmpty());
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001648 bool the_boolean = as_boxed->ValueOf();
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001649 CHECK_EQ(true, the_boolean);
1650 v8::Handle<v8::Value> boxed_true = v8::BooleanObject::New(true);
1651 v8::Handle<v8::Value> boxed_false = v8::BooleanObject::New(false);
1652 CHECK(boxed_true->IsBooleanObject());
1653 CHECK(boxed_false->IsBooleanObject());
1654 as_boxed = boxed_true.As<v8::BooleanObject>();
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001655 CHECK_EQ(true, as_boxed->ValueOf());
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001656 as_boxed = boxed_false.As<v8::BooleanObject>();
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001657 CHECK_EQ(false, as_boxed->ValueOf());
1658}
1659
1660
1661THREADED_TEST(PrimitiveAndWrappedBooleans) {
1662 LocalContext env;
1663 v8::HandleScope scope(env->GetIsolate());
1664
machenbach@chromium.org37be4082013-11-26 13:50:38 +00001665 Local<Value> primitive_false = Boolean::New(env->GetIsolate(), false);
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001666 CHECK(primitive_false->IsBoolean());
1667 CHECK(!primitive_false->IsBooleanObject());
1668 CHECK(!primitive_false->BooleanValue());
1669 CHECK(!primitive_false->IsTrue());
1670 CHECK(primitive_false->IsFalse());
1671
1672 Local<Value> false_value = BooleanObject::New(false);
1673 CHECK(!false_value->IsBoolean());
1674 CHECK(false_value->IsBooleanObject());
1675 CHECK(false_value->BooleanValue());
1676 CHECK(!false_value->IsTrue());
1677 CHECK(!false_value->IsFalse());
1678
1679 Local<BooleanObject> false_boolean_object = false_value.As<BooleanObject>();
1680 CHECK(!false_boolean_object->IsBoolean());
1681 CHECK(false_boolean_object->IsBooleanObject());
1682 // TODO(svenpanne) Uncomment when BooleanObject::BooleanValue() is deleted.
1683 // CHECK(false_boolean_object->BooleanValue());
1684 CHECK(!false_boolean_object->ValueOf());
1685 CHECK(!false_boolean_object->IsTrue());
1686 CHECK(!false_boolean_object->IsFalse());
1687
machenbach@chromium.org37be4082013-11-26 13:50:38 +00001688 Local<Value> primitive_true = Boolean::New(env->GetIsolate(), true);
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001689 CHECK(primitive_true->IsBoolean());
1690 CHECK(!primitive_true->IsBooleanObject());
1691 CHECK(primitive_true->BooleanValue());
1692 CHECK(primitive_true->IsTrue());
1693 CHECK(!primitive_true->IsFalse());
1694
1695 Local<Value> true_value = BooleanObject::New(true);
1696 CHECK(!true_value->IsBoolean());
1697 CHECK(true_value->IsBooleanObject());
1698 CHECK(true_value->BooleanValue());
1699 CHECK(!true_value->IsTrue());
1700 CHECK(!true_value->IsFalse());
1701
1702 Local<BooleanObject> true_boolean_object = true_value.As<BooleanObject>();
1703 CHECK(!true_boolean_object->IsBoolean());
1704 CHECK(true_boolean_object->IsBooleanObject());
1705 // TODO(svenpanne) Uncomment when BooleanObject::BooleanValue() is deleted.
1706 // CHECK(true_boolean_object->BooleanValue());
1707 CHECK(true_boolean_object->ValueOf());
1708 CHECK(!true_boolean_object->IsTrue());
1709 CHECK(!true_boolean_object->IsFalse());
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001710}
1711
1712
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001713THREADED_TEST(Number) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001714 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001715 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001716 double PI = 3.1415926;
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001717 Local<v8::Number> pi_obj = v8::Number::New(env->GetIsolate(), PI);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001718 CHECK_EQ(PI, pi_obj->NumberValue());
1719}
1720
1721
1722THREADED_TEST(ToNumber) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001723 LocalContext env;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00001724 v8::Isolate* isolate = CcTest::isolate();
1725 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001726 Local<String> str = v8_str("3.1415926");
1727 CHECK_EQ(3.1415926, str->NumberValue());
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00001728 v8::Handle<v8::Boolean> t = v8::True(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001729 CHECK_EQ(1.0, t->NumberValue());
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00001730 v8::Handle<v8::Boolean> f = v8::False(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001731 CHECK_EQ(0.0, f->NumberValue());
1732}
1733
1734
1735THREADED_TEST(Date) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001736 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001737 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001738 double PI = 3.1415926;
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00001739 Local<Value> date = v8::Date::New(env->GetIsolate(), PI);
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +00001740 CHECK_EQ(3.0, date->NumberValue());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001741 date.As<v8::Date>()->Set(v8_str("property"),
1742 v8::Integer::New(env->GetIsolate(), 42));
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +00001743 CHECK_EQ(42, date.As<v8::Date>()->Get(v8_str("property"))->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001744}
1745
1746
1747THREADED_TEST(Boolean) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001748 LocalContext env;
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001749 v8::Isolate* isolate = env->GetIsolate();
1750 v8::HandleScope scope(isolate);
1751 v8::Handle<v8::Boolean> t = v8::True(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001752 CHECK(t->Value());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001753 v8::Handle<v8::Boolean> f = v8::False(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001754 CHECK(!f->Value());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001755 v8::Handle<v8::Primitive> u = v8::Undefined(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001756 CHECK(!u->BooleanValue());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001757 v8::Handle<v8::Primitive> n = v8::Null(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001758 CHECK(!n->BooleanValue());
1759 v8::Handle<String> str1 = v8_str("");
1760 CHECK(!str1->BooleanValue());
1761 v8::Handle<String> str2 = v8_str("x");
1762 CHECK(str2->BooleanValue());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001763 CHECK(!v8::Number::New(isolate, 0)->BooleanValue());
1764 CHECK(v8::Number::New(isolate, -1)->BooleanValue());
1765 CHECK(v8::Number::New(isolate, 1)->BooleanValue());
1766 CHECK(v8::Number::New(isolate, 42)->BooleanValue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001767 CHECK(!v8_compile("NaN")->Run()->BooleanValue());
1768}
1769
1770
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001771static void DummyCallHandler(const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001772 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001773 args.GetReturnValue().Set(v8_num(13.4));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001774}
1775
1776
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001777static void GetM(Local<String> name,
1778 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001779 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001780 info.GetReturnValue().Set(v8_num(876));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001781}
1782
1783
1784THREADED_TEST(GlobalPrototype) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001785 v8::Isolate* isolate = CcTest::isolate();
1786 v8::HandleScope scope(isolate);
1787 v8::Handle<v8::FunctionTemplate> func_templ =
1788 v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001789 func_templ->PrototypeTemplate()->Set(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001790 isolate, "dummy", v8::FunctionTemplate::New(isolate, DummyCallHandler));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001791 v8::Handle<ObjectTemplate> templ = func_templ->InstanceTemplate();
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001792 templ->Set(isolate, "x", v8_num(200));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001793 templ->SetAccessor(v8_str("m"), GetM);
1794 LocalContext env(0, templ);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001795 v8::Handle<Script> script(v8_compile("dummy()"));
1796 v8::Handle<Value> result(script->Run());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001797 CHECK_EQ(13.4, result->NumberValue());
1798 CHECK_EQ(200, v8_compile("x")->Run()->Int32Value());
1799 CHECK_EQ(876, v8_compile("m")->Run()->Int32Value());
1800}
1801
1802
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001803THREADED_TEST(ObjectTemplate) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001804 v8::Isolate* isolate = CcTest::isolate();
1805 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00001806 Local<ObjectTemplate> templ1 = ObjectTemplate::New(isolate);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001807 templ1->Set(isolate, "x", v8_num(10));
1808 templ1->Set(isolate, "y", v8_num(13));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001809 LocalContext env;
1810 Local<v8::Object> instance1 = templ1->NewInstance();
1811 env->Global()->Set(v8_str("p"), instance1);
1812 CHECK(v8_compile("(p.x == 10)")->Run()->BooleanValue());
1813 CHECK(v8_compile("(p.y == 13)")->Run()->BooleanValue());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001814 Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(isolate);
1815 fun->PrototypeTemplate()->Set(isolate, "nirk", v8_num(123));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001816 Local<ObjectTemplate> templ2 = fun->InstanceTemplate();
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001817 templ2->Set(isolate, "a", v8_num(12));
1818 templ2->Set(isolate, "b", templ1);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001819 Local<v8::Object> instance2 = templ2->NewInstance();
1820 env->Global()->Set(v8_str("q"), instance2);
1821 CHECK(v8_compile("(q.nirk == 123)")->Run()->BooleanValue());
1822 CHECK(v8_compile("(q.a == 12)")->Run()->BooleanValue());
1823 CHECK(v8_compile("(q.b.x == 10)")->Run()->BooleanValue());
1824 CHECK(v8_compile("(q.b.y == 13)")->Run()->BooleanValue());
1825}
1826
1827
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001828static void GetFlabby(const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001829 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001830 args.GetReturnValue().Set(v8_num(17.2));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001831}
1832
1833
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001834static void GetKnurd(Local<String> property,
1835 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001836 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001837 info.GetReturnValue().Set(v8_num(15.2));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001838}
1839
1840
1841THREADED_TEST(DescriptorInheritance) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001842 v8::Isolate* isolate = CcTest::isolate();
1843 v8::HandleScope scope(isolate);
1844 v8::Handle<v8::FunctionTemplate> super = v8::FunctionTemplate::New(isolate);
1845 super->PrototypeTemplate()->Set(isolate, "flabby",
1846 v8::FunctionTemplate::New(isolate,
1847 GetFlabby));
1848 super->PrototypeTemplate()->Set(isolate, "PI", v8_num(3.14));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001849
1850 super->InstanceTemplate()->SetAccessor(v8_str("knurd"), GetKnurd);
1851
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001852 v8::Handle<v8::FunctionTemplate> base1 = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001853 base1->Inherit(super);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001854 base1->PrototypeTemplate()->Set(isolate, "v1", v8_num(20.1));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001855
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001856 v8::Handle<v8::FunctionTemplate> base2 = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001857 base2->Inherit(super);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001858 base2->PrototypeTemplate()->Set(isolate, "v2", v8_num(10.1));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001859
1860 LocalContext env;
1861
1862 env->Global()->Set(v8_str("s"), super->GetFunction());
1863 env->Global()->Set(v8_str("base1"), base1->GetFunction());
1864 env->Global()->Set(v8_str("base2"), base2->GetFunction());
1865
1866 // Checks right __proto__ chain.
1867 CHECK(CompileRun("base1.prototype.__proto__ == s.prototype")->BooleanValue());
1868 CHECK(CompileRun("base2.prototype.__proto__ == s.prototype")->BooleanValue());
1869
1870 CHECK(v8_compile("s.prototype.PI == 3.14")->Run()->BooleanValue());
1871
1872 // Instance accessor should not be visible on function object or its prototype
1873 CHECK(CompileRun("s.knurd == undefined")->BooleanValue());
1874 CHECK(CompileRun("s.prototype.knurd == undefined")->BooleanValue());
1875 CHECK(CompileRun("base1.prototype.knurd == undefined")->BooleanValue());
1876
1877 env->Global()->Set(v8_str("obj"),
1878 base1->GetFunction()->NewInstance());
1879 CHECK_EQ(17.2, v8_compile("obj.flabby()")->Run()->NumberValue());
1880 CHECK(v8_compile("'flabby' in obj")->Run()->BooleanValue());
1881 CHECK_EQ(15.2, v8_compile("obj.knurd")->Run()->NumberValue());
1882 CHECK(v8_compile("'knurd' in obj")->Run()->BooleanValue());
1883 CHECK_EQ(20.1, v8_compile("obj.v1")->Run()->NumberValue());
1884
1885 env->Global()->Set(v8_str("obj2"),
1886 base2->GetFunction()->NewInstance());
1887 CHECK_EQ(17.2, v8_compile("obj2.flabby()")->Run()->NumberValue());
1888 CHECK(v8_compile("'flabby' in obj2")->Run()->BooleanValue());
1889 CHECK_EQ(15.2, v8_compile("obj2.knurd")->Run()->NumberValue());
1890 CHECK(v8_compile("'knurd' in obj2")->Run()->BooleanValue());
1891 CHECK_EQ(10.1, v8_compile("obj2.v2")->Run()->NumberValue());
1892
1893 // base1 and base2 cannot cross reference to each's prototype
1894 CHECK(v8_compile("obj.v2")->Run()->IsUndefined());
1895 CHECK(v8_compile("obj2.v1")->Run()->IsUndefined());
1896}
1897
1898
1899int echo_named_call_count;
1900
1901
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001902static void EchoNamedProperty(Local<String> name,
1903 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001904 ApiTestFuzzer::Fuzz();
1905 CHECK_EQ(v8_str("data"), info.Data());
1906 echo_named_call_count++;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001907 info.GetReturnValue().Set(name);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001908}
1909
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001910
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001911// Helper functions for Interceptor/Accessor interaction tests
1912
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001913void SimpleAccessorGetter(Local<String> name,
1914 const v8::PropertyCallbackInfo<v8::Value>& info) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001915 Handle<Object> self = info.This();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001916 info.GetReturnValue().Set(
1917 self->Get(String::Concat(v8_str("accessor_"), name)));
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001918}
1919
1920void SimpleAccessorSetter(Local<String> name, Local<Value> value,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001921 const v8::PropertyCallbackInfo<void>& info) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001922 Handle<Object> self = info.This();
1923 self->Set(String::Concat(v8_str("accessor_"), name), value);
1924}
1925
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001926void EmptyInterceptorGetter(Local<String> name,
1927 const v8::PropertyCallbackInfo<v8::Value>& info) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001928}
1929
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001930void EmptyInterceptorSetter(Local<String> name,
1931 Local<Value> value,
1932 const v8::PropertyCallbackInfo<v8::Value>& info) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001933}
1934
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001935void InterceptorGetter(Local<String> name,
1936 const v8::PropertyCallbackInfo<v8::Value>& info) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001937 // Intercept names that start with 'interceptor_'.
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00001938 String::Utf8Value utf8(name);
1939 char* name_str = *utf8;
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001940 char prefix[] = "interceptor_";
1941 int i;
1942 for (i = 0; name_str[i] && prefix[i]; ++i) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001943 if (name_str[i] != prefix[i]) return;
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001944 }
1945 Handle<Object> self = info.This();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001946 info.GetReturnValue().Set(self->GetHiddenValue(v8_str(name_str + i)));
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001947}
1948
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001949void InterceptorSetter(Local<String> name,
1950 Local<Value> value,
1951 const v8::PropertyCallbackInfo<v8::Value>& info) {
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +00001952 // Intercept accesses that set certain integer values, for which the name does
1953 // not start with 'accessor_'.
1954 String::Utf8Value utf8(name);
1955 char* name_str = *utf8;
1956 char prefix[] = "accessor_";
1957 int i;
1958 for (i = 0; name_str[i] && prefix[i]; ++i) {
1959 if (name_str[i] != prefix[i]) break;
1960 }
1961 if (!prefix[i]) return;
1962
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001963 if (value->IsInt32() && value->Int32Value() < 10000) {
1964 Handle<Object> self = info.This();
1965 self->SetHiddenValue(name, value);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001966 info.GetReturnValue().Set(value);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001967 }
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001968}
1969
1970void AddAccessor(Handle<FunctionTemplate> templ,
1971 Handle<String> name,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001972 v8::AccessorGetterCallback getter,
1973 v8::AccessorSetterCallback setter) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001974 templ->PrototypeTemplate()->SetAccessor(name, getter, setter);
1975}
1976
1977void AddInterceptor(Handle<FunctionTemplate> templ,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001978 v8::NamedPropertyGetterCallback getter,
1979 v8::NamedPropertySetterCallback setter) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001980 templ->InstanceTemplate()->SetNamedPropertyHandler(getter, setter);
1981}
1982
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001983
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001984THREADED_TEST(EmptyInterceptorDoesNotShadowAccessors) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001985 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001986 Handle<FunctionTemplate> parent = FunctionTemplate::New(CcTest::isolate());
1987 Handle<FunctionTemplate> child = FunctionTemplate::New(CcTest::isolate());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001988 child->Inherit(parent);
1989 AddAccessor(parent, v8_str("age"),
1990 SimpleAccessorGetter, SimpleAccessorSetter);
1991 AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter);
1992 LocalContext env;
1993 env->Global()->Set(v8_str("Child"), child->GetFunction());
1994 CompileRun("var child = new Child;"
1995 "child.age = 10;");
1996 ExpectBoolean("child.hasOwnProperty('age')", false);
1997 ExpectInt32("child.age", 10);
1998 ExpectInt32("child.accessor_age", 10);
1999}
2000
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002001
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002002THREADED_TEST(EmptyInterceptorDoesNotShadowJSAccessors) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002003 v8::Isolate* isolate = CcTest::isolate();
2004 v8::HandleScope scope(isolate);
2005 Handle<FunctionTemplate> parent = FunctionTemplate::New(isolate);
2006 Handle<FunctionTemplate> child = FunctionTemplate::New(isolate);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002007 child->Inherit(parent);
2008 AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter);
2009 LocalContext env;
2010 env->Global()->Set(v8_str("Child"), child->GetFunction());
2011 CompileRun("var child = new Child;"
2012 "var parent = child.__proto__;"
2013 "Object.defineProperty(parent, 'age', "
2014 " {get: function(){ return this.accessor_age; }, "
2015 " set: function(v){ this.accessor_age = v; }, "
2016 " enumerable: true, configurable: true});"
2017 "child.age = 10;");
2018 ExpectBoolean("child.hasOwnProperty('age')", false);
2019 ExpectInt32("child.age", 10);
2020 ExpectInt32("child.accessor_age", 10);
2021}
2022
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002023
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002024THREADED_TEST(EmptyInterceptorDoesNotAffectJSProperties) {
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 "parent.name = 'Alice';");
2036 ExpectBoolean("child.hasOwnProperty('name')", false);
2037 ExpectString("child.name", "Alice");
2038 CompileRun("child.name = 'Bob';");
2039 ExpectString("child.name", "Bob");
2040 ExpectBoolean("child.hasOwnProperty('name')", true);
2041 ExpectString("parent.name", "Alice");
2042}
2043
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002044
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002045THREADED_TEST(SwitchFromInterceptorToAccessor) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002046 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002047 Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
danno@chromium.orgbf0c8202011-12-27 10:09:42 +00002048 AddAccessor(templ, v8_str("age"),
2049 SimpleAccessorGetter, SimpleAccessorSetter);
2050 AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
2051 LocalContext env;
2052 env->Global()->Set(v8_str("Obj"), templ->GetFunction());
2053 CompileRun("var obj = new Obj;"
2054 "function setAge(i){ obj.age = i; };"
2055 "for(var i = 0; i <= 10000; i++) setAge(i);");
2056 // All i < 10000 go to the interceptor.
2057 ExpectInt32("obj.interceptor_age", 9999);
2058 // The last i goes to the accessor.
2059 ExpectInt32("obj.accessor_age", 10000);
2060}
2061
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002062
danno@chromium.orgbf0c8202011-12-27 10:09:42 +00002063THREADED_TEST(SwitchFromAccessorToInterceptor) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002064 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002065 Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
danno@chromium.orgbf0c8202011-12-27 10:09:42 +00002066 AddAccessor(templ, v8_str("age"),
2067 SimpleAccessorGetter, SimpleAccessorSetter);
2068 AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
2069 LocalContext env;
2070 env->Global()->Set(v8_str("Obj"), templ->GetFunction());
2071 CompileRun("var obj = new Obj;"
2072 "function setAge(i){ obj.age = i; };"
2073 "for(var i = 20000; i >= 9999; i--) setAge(i);");
2074 // All i >= 10000 go to the accessor.
2075 ExpectInt32("obj.accessor_age", 10000);
2076 // The last i goes to the interceptor.
2077 ExpectInt32("obj.interceptor_age", 9999);
2078}
2079
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002080
danno@chromium.orgbf0c8202011-12-27 10:09:42 +00002081THREADED_TEST(SwitchFromInterceptorToAccessorWithInheritance) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002082 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002083 Handle<FunctionTemplate> parent = FunctionTemplate::New(CcTest::isolate());
2084 Handle<FunctionTemplate> child = FunctionTemplate::New(CcTest::isolate());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002085 child->Inherit(parent);
2086 AddAccessor(parent, v8_str("age"),
2087 SimpleAccessorGetter, SimpleAccessorSetter);
2088 AddInterceptor(child, InterceptorGetter, InterceptorSetter);
2089 LocalContext env;
2090 env->Global()->Set(v8_str("Child"), child->GetFunction());
2091 CompileRun("var child = new Child;"
2092 "function setAge(i){ child.age = i; };"
2093 "for(var i = 0; i <= 10000; i++) setAge(i);");
2094 // All i < 10000 go to the interceptor.
2095 ExpectInt32("child.interceptor_age", 9999);
2096 // The last i goes to the accessor.
2097 ExpectInt32("child.accessor_age", 10000);
2098}
2099
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002100
danno@chromium.orgbf0c8202011-12-27 10:09:42 +00002101THREADED_TEST(SwitchFromAccessorToInterceptorWithInheritance) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002102 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002103 Handle<FunctionTemplate> parent = FunctionTemplate::New(CcTest::isolate());
2104 Handle<FunctionTemplate> child = FunctionTemplate::New(CcTest::isolate());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002105 child->Inherit(parent);
2106 AddAccessor(parent, v8_str("age"),
2107 SimpleAccessorGetter, SimpleAccessorSetter);
2108 AddInterceptor(child, InterceptorGetter, InterceptorSetter);
2109 LocalContext env;
2110 env->Global()->Set(v8_str("Child"), child->GetFunction());
2111 CompileRun("var child = new Child;"
2112 "function setAge(i){ child.age = i; };"
2113 "for(var i = 20000; i >= 9999; i--) setAge(i);");
2114 // All i >= 10000 go to the accessor.
2115 ExpectInt32("child.accessor_age", 10000);
2116 // The last i goes to the interceptor.
2117 ExpectInt32("child.interceptor_age", 9999);
2118}
2119
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002120
danno@chromium.orgbf0c8202011-12-27 10:09:42 +00002121THREADED_TEST(SwitchFromInterceptorToJSAccessor) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002122 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002123 Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
danno@chromium.orgbf0c8202011-12-27 10:09:42 +00002124 AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
2125 LocalContext env;
2126 env->Global()->Set(v8_str("Obj"), templ->GetFunction());
2127 CompileRun("var obj = new Obj;"
2128 "function setter(i) { this.accessor_age = i; };"
2129 "function getter() { return this.accessor_age; };"
2130 "function setAge(i) { obj.age = i; };"
2131 "Object.defineProperty(obj, 'age', { get:getter, set:setter });"
2132 "for(var i = 0; i <= 10000; i++) setAge(i);");
2133 // All i < 10000 go to the interceptor.
2134 ExpectInt32("obj.interceptor_age", 9999);
2135 // The last i goes to the JavaScript accessor.
2136 ExpectInt32("obj.accessor_age", 10000);
2137 // The installed JavaScript getter is still intact.
2138 // This last part is a regression test for issue 1651 and relies on the fact
2139 // that both interceptor and accessor are being installed on the same object.
2140 ExpectInt32("obj.age", 10000);
2141 ExpectBoolean("obj.hasOwnProperty('age')", true);
2142 ExpectUndefined("Object.getOwnPropertyDescriptor(obj, 'age').value");
2143}
2144
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002145
danno@chromium.orgbf0c8202011-12-27 10:09:42 +00002146THREADED_TEST(SwitchFromJSAccessorToInterceptor) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002147 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002148 Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
danno@chromium.orgbf0c8202011-12-27 10:09:42 +00002149 AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
2150 LocalContext env;
2151 env->Global()->Set(v8_str("Obj"), templ->GetFunction());
2152 CompileRun("var obj = new Obj;"
2153 "function setter(i) { this.accessor_age = i; };"
2154 "function getter() { return this.accessor_age; };"
2155 "function setAge(i) { obj.age = i; };"
2156 "Object.defineProperty(obj, 'age', { get:getter, set:setter });"
2157 "for(var i = 20000; i >= 9999; i--) setAge(i);");
2158 // All i >= 10000 go to the accessor.
2159 ExpectInt32("obj.accessor_age", 10000);
2160 // The last i goes to the interceptor.
2161 ExpectInt32("obj.interceptor_age", 9999);
2162 // The installed JavaScript getter is still intact.
2163 // This last part is a regression test for issue 1651 and relies on the fact
2164 // that both interceptor and accessor are being installed on the same object.
2165 ExpectInt32("obj.age", 10000);
2166 ExpectBoolean("obj.hasOwnProperty('age')", true);
2167 ExpectUndefined("Object.getOwnPropertyDescriptor(obj, 'age').value");
2168}
2169
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002170
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002171THREADED_TEST(SwitchFromInterceptorToProperty) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002172 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002173 Handle<FunctionTemplate> parent = FunctionTemplate::New(CcTest::isolate());
2174 Handle<FunctionTemplate> child = FunctionTemplate::New(CcTest::isolate());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002175 child->Inherit(parent);
2176 AddInterceptor(child, InterceptorGetter, InterceptorSetter);
2177 LocalContext env;
2178 env->Global()->Set(v8_str("Child"), child->GetFunction());
2179 CompileRun("var child = new Child;"
2180 "function setAge(i){ child.age = i; };"
2181 "for(var i = 0; i <= 10000; i++) setAge(i);");
2182 // All i < 10000 go to the interceptor.
2183 ExpectInt32("child.interceptor_age", 9999);
2184 // The last i goes to child's own property.
2185 ExpectInt32("child.age", 10000);
2186}
2187
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002188
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002189THREADED_TEST(SwitchFromPropertyToInterceptor) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002190 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002191 Handle<FunctionTemplate> parent = FunctionTemplate::New(CcTest::isolate());
2192 Handle<FunctionTemplate> child = FunctionTemplate::New(CcTest::isolate());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002193 child->Inherit(parent);
2194 AddInterceptor(child, InterceptorGetter, InterceptorSetter);
2195 LocalContext env;
2196 env->Global()->Set(v8_str("Child"), child->GetFunction());
2197 CompileRun("var child = new Child;"
2198 "function setAge(i){ child.age = i; };"
2199 "for(var i = 20000; i >= 9999; i--) setAge(i);");
2200 // All i >= 10000 go to child's own property.
2201 ExpectInt32("child.age", 10000);
2202 // The last i goes to the interceptor.
2203 ExpectInt32("child.interceptor_age", 9999);
2204}
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002205
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002206
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002207THREADED_TEST(NamedPropertyHandlerGetter) {
2208 echo_named_call_count = 0;
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002209 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002210 v8::Handle<v8::FunctionTemplate> templ =
2211 v8::FunctionTemplate::New(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002212 templ->InstanceTemplate()->SetNamedPropertyHandler(EchoNamedProperty,
2213 0, 0, 0, 0,
2214 v8_str("data"));
2215 LocalContext env;
2216 env->Global()->Set(v8_str("obj"),
2217 templ->GetFunction()->NewInstance());
2218 CHECK_EQ(echo_named_call_count, 0);
2219 v8_compile("obj.x")->Run();
2220 CHECK_EQ(echo_named_call_count, 1);
2221 const char* code = "var str = 'oddle'; obj[str] + obj.poddle;";
2222 v8::Handle<Value> str = CompileRun(code);
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00002223 String::Utf8Value value(str);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002224 CHECK_EQ(*value, "oddlepoddle");
2225 // Check default behavior
2226 CHECK_EQ(v8_compile("obj.flob = 10;")->Run()->Int32Value(), 10);
2227 CHECK(v8_compile("'myProperty' in obj")->Run()->BooleanValue());
2228 CHECK(v8_compile("delete obj.myProperty")->Run()->BooleanValue());
2229}
2230
2231
2232int echo_indexed_call_count = 0;
2233
2234
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002235static void EchoIndexedProperty(
2236 uint32_t index,
2237 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002238 ApiTestFuzzer::Fuzz();
2239 CHECK_EQ(v8_num(637), info.Data());
2240 echo_indexed_call_count++;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002241 info.GetReturnValue().Set(v8_num(index));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002242}
2243
2244
2245THREADED_TEST(IndexedPropertyHandlerGetter) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002246 v8::Isolate* isolate = CcTest::isolate();
2247 v8::HandleScope scope(isolate);
2248 v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002249 templ->InstanceTemplate()->SetIndexedPropertyHandler(EchoIndexedProperty,
2250 0, 0, 0, 0,
2251 v8_num(637));
2252 LocalContext env;
2253 env->Global()->Set(v8_str("obj"),
2254 templ->GetFunction()->NewInstance());
2255 Local<Script> script = v8_compile("obj[900]");
2256 CHECK_EQ(script->Run()->Int32Value(), 900);
2257}
2258
2259
2260v8::Handle<v8::Object> bottom;
2261
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002262static void CheckThisIndexedPropertyHandler(
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002263 uint32_t index,
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002264 const v8::PropertyCallbackInfo<v8::Value>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002265 CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyHandler));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002266 ApiTestFuzzer::Fuzz();
2267 CHECK(info.This()->Equals(bottom));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002268}
2269
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002270static void CheckThisNamedPropertyHandler(
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002271 Local<String> name,
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002272 const v8::PropertyCallbackInfo<v8::Value>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002273 CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyHandler));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002274 ApiTestFuzzer::Fuzz();
2275 CHECK(info.This()->Equals(bottom));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002276}
2277
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002278void CheckThisIndexedPropertySetter(
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002279 uint32_t index,
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002280 Local<Value> value,
2281 const v8::PropertyCallbackInfo<v8::Value>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002282 CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertySetter));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002283 ApiTestFuzzer::Fuzz();
2284 CHECK(info.This()->Equals(bottom));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002285}
2286
2287
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002288void CheckThisNamedPropertySetter(
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002289 Local<String> property,
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002290 Local<Value> value,
2291 const v8::PropertyCallbackInfo<v8::Value>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002292 CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertySetter));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002293 ApiTestFuzzer::Fuzz();
2294 CHECK(info.This()->Equals(bottom));
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002295}
2296
2297void CheckThisIndexedPropertyQuery(
2298 uint32_t index,
2299 const v8::PropertyCallbackInfo<v8::Integer>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002300 CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyQuery));
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002301 ApiTestFuzzer::Fuzz();
2302 CHECK(info.This()->Equals(bottom));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002303}
2304
2305
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002306void CheckThisNamedPropertyQuery(
2307 Local<String> property,
2308 const v8::PropertyCallbackInfo<v8::Integer>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002309 CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyQuery));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002310 ApiTestFuzzer::Fuzz();
2311 CHECK(info.This()->Equals(bottom));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002312}
2313
2314
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002315void CheckThisIndexedPropertyDeleter(
2316 uint32_t index,
2317 const v8::PropertyCallbackInfo<v8::Boolean>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002318 CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyDeleter));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002319 ApiTestFuzzer::Fuzz();
2320 CHECK(info.This()->Equals(bottom));
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002321}
2322
2323
2324void CheckThisNamedPropertyDeleter(
2325 Local<String> property,
2326 const v8::PropertyCallbackInfo<v8::Boolean>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002327 CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyDeleter));
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002328 ApiTestFuzzer::Fuzz();
2329 CHECK(info.This()->Equals(bottom));
2330}
2331
2332
2333void CheckThisIndexedPropertyEnumerator(
2334 const v8::PropertyCallbackInfo<v8::Array>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002335 CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyEnumerator));
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002336 ApiTestFuzzer::Fuzz();
2337 CHECK(info.This()->Equals(bottom));
2338}
2339
2340
2341void CheckThisNamedPropertyEnumerator(
2342 const v8::PropertyCallbackInfo<v8::Array>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002343 CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyEnumerator));
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002344 ApiTestFuzzer::Fuzz();
2345 CHECK(info.This()->Equals(bottom));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002346}
2347
2348
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002349THREADED_PROFILED_TEST(PropertyHandlerInPrototype) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002350 LocalContext env;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002351 v8::Isolate* isolate = env->GetIsolate();
2352 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002353
2354 // Set up a prototype chain with three interceptors.
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002355 v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002356 templ->InstanceTemplate()->SetIndexedPropertyHandler(
2357 CheckThisIndexedPropertyHandler,
2358 CheckThisIndexedPropertySetter,
2359 CheckThisIndexedPropertyQuery,
2360 CheckThisIndexedPropertyDeleter,
2361 CheckThisIndexedPropertyEnumerator);
2362
2363 templ->InstanceTemplate()->SetNamedPropertyHandler(
2364 CheckThisNamedPropertyHandler,
2365 CheckThisNamedPropertySetter,
2366 CheckThisNamedPropertyQuery,
2367 CheckThisNamedPropertyDeleter,
2368 CheckThisNamedPropertyEnumerator);
2369
2370 bottom = templ->GetFunction()->NewInstance();
2371 Local<v8::Object> top = templ->GetFunction()->NewInstance();
2372 Local<v8::Object> middle = templ->GetFunction()->NewInstance();
2373
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00002374 bottom->SetPrototype(middle);
2375 middle->SetPrototype(top);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002376 env->Global()->Set(v8_str("obj"), bottom);
2377
2378 // Indexed and named get.
2379 Script::Compile(v8_str("obj[0]"))->Run();
2380 Script::Compile(v8_str("obj.x"))->Run();
2381
2382 // Indexed and named set.
2383 Script::Compile(v8_str("obj[1] = 42"))->Run();
2384 Script::Compile(v8_str("obj.y = 42"))->Run();
2385
2386 // Indexed and named query.
2387 Script::Compile(v8_str("0 in obj"))->Run();
2388 Script::Compile(v8_str("'x' in obj"))->Run();
2389
2390 // Indexed and named deleter.
2391 Script::Compile(v8_str("delete obj[0]"))->Run();
2392 Script::Compile(v8_str("delete obj.x"))->Run();
2393
2394 // Enumerators.
2395 Script::Compile(v8_str("for (var p in obj) ;"))->Run();
2396}
2397
2398
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002399static void PrePropertyHandlerGet(
2400 Local<String> key,
2401 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002402 ApiTestFuzzer::Fuzz();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002403 if (v8_str("pre")->Equals(key)) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002404 info.GetReturnValue().Set(v8_str("PrePropertyHandler: pre"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002405 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002406}
2407
2408
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002409static void PrePropertyHandlerQuery(
2410 Local<String> key,
2411 const v8::PropertyCallbackInfo<v8::Integer>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002412 if (v8_str("pre")->Equals(key)) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002413 info.GetReturnValue().Set(static_cast<int32_t>(v8::None));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002414 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002415}
2416
2417
2418THREADED_TEST(PrePropertyHandler) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002419 v8::Isolate* isolate = CcTest::isolate();
2420 v8::HandleScope scope(isolate);
2421 v8::Handle<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002422 desc->InstanceTemplate()->SetNamedPropertyHandler(PrePropertyHandlerGet,
2423 0,
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00002424 PrePropertyHandlerQuery);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002425 LocalContext env(NULL, desc->InstanceTemplate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002426 Script::Compile(v8_str(
2427 "var pre = 'Object: pre'; var on = 'Object: on';"))->Run();
2428 v8::Handle<Value> result_pre = Script::Compile(v8_str("pre"))->Run();
2429 CHECK_EQ(v8_str("PrePropertyHandler: pre"), result_pre);
2430 v8::Handle<Value> result_on = Script::Compile(v8_str("on"))->Run();
2431 CHECK_EQ(v8_str("Object: on"), result_on);
2432 v8::Handle<Value> result_post = Script::Compile(v8_str("post"))->Run();
2433 CHECK(result_post.IsEmpty());
2434}
2435
2436
ager@chromium.org870a0b62008-11-04 11:43:05 +00002437THREADED_TEST(UndefinedIsNotEnumerable) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00002438 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00002439 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org870a0b62008-11-04 11:43:05 +00002440 v8::Handle<Value> result = Script::Compile(v8_str(
2441 "this.propertyIsEnumerable(undefined)"))->Run();
2442 CHECK(result->IsFalse());
2443}
2444
2445
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002446v8::Handle<Script> call_recursively_script;
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00002447static const int kTargetRecursionDepth = 200; // near maximum
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002448
2449
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002450static void CallScriptRecursivelyCall(
2451 const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002452 ApiTestFuzzer::Fuzz();
2453 int depth = args.This()->Get(v8_str("depth"))->Int32Value();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002454 if (depth == kTargetRecursionDepth) return;
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002455 args.This()->Set(v8_str("depth"),
2456 v8::Integer::New(args.GetIsolate(), depth + 1));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002457 args.GetReturnValue().Set(call_recursively_script->Run());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002458}
2459
2460
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002461static void CallFunctionRecursivelyCall(
2462 const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002463 ApiTestFuzzer::Fuzz();
2464 int depth = args.This()->Get(v8_str("depth"))->Int32Value();
2465 if (depth == kTargetRecursionDepth) {
2466 printf("[depth = %d]\n", depth);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002467 return;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002468 }
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002469 args.This()->Set(v8_str("depth"),
2470 v8::Integer::New(args.GetIsolate(), depth + 1));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002471 v8::Handle<Value> function =
2472 args.This()->Get(v8_str("callFunctionRecursively"));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002473 args.GetReturnValue().Set(
2474 function.As<Function>()->Call(args.This(), 0, NULL));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002475}
2476
2477
2478THREADED_TEST(DeepCrossLanguageRecursion) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002479 v8::Isolate* isolate = CcTest::isolate();
2480 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00002481 v8::Handle<v8::ObjectTemplate> global = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002482 global->Set(v8_str("callScriptRecursively"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002483 v8::FunctionTemplate::New(isolate, CallScriptRecursivelyCall));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002484 global->Set(v8_str("callFunctionRecursively"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002485 v8::FunctionTemplate::New(isolate, CallFunctionRecursivelyCall));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002486 LocalContext env(NULL, global);
2487
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002488 env->Global()->Set(v8_str("depth"), v8::Integer::New(isolate, 0));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002489 call_recursively_script = v8_compile("callScriptRecursively()");
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00002490 call_recursively_script->Run();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002491 call_recursively_script = v8::Handle<Script>();
2492
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002493 env->Global()->Set(v8_str("depth"), v8::Integer::New(isolate, 0));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002494 Script::Compile(v8_str("callFunctionRecursively()"))->Run();
2495}
2496
2497
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002498static void ThrowingPropertyHandlerGet(
2499 Local<String> key,
2500 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002501 ApiTestFuzzer::Fuzz();
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00002502 info.GetReturnValue().Set(info.GetIsolate()->ThrowException(key));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002503}
2504
2505
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002506static void ThrowingPropertyHandlerSet(
2507 Local<String> key,
2508 Local<Value>,
2509 const v8::PropertyCallbackInfo<v8::Value>& info) {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00002510 info.GetIsolate()->ThrowException(key);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002511 info.GetReturnValue().SetUndefined(); // not the same as empty handle
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002512}
2513
2514
2515THREADED_TEST(CallbackExceptionRegression) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00002516 v8::Isolate* isolate = CcTest::isolate();
2517 v8::HandleScope scope(isolate);
2518 v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002519 obj->SetNamedPropertyHandler(ThrowingPropertyHandlerGet,
2520 ThrowingPropertyHandlerSet);
2521 LocalContext env;
2522 env->Global()->Set(v8_str("obj"), obj->NewInstance());
2523 v8::Handle<Value> otto = Script::Compile(v8_str(
2524 "try { with (obj) { otto; } } catch (e) { e; }"))->Run();
2525 CHECK_EQ(v8_str("otto"), otto);
2526 v8::Handle<Value> netto = Script::Compile(v8_str(
2527 "try { with (obj) { netto = 4; } } catch (e) { e; }"))->Run();
2528 CHECK_EQ(v8_str("netto"), netto);
2529}
2530
2531
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002532THREADED_TEST(FunctionPrototype) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002533 v8::Isolate* isolate = CcTest::isolate();
2534 v8::HandleScope scope(isolate);
2535 Local<v8::FunctionTemplate> Foo = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002536 Foo->PrototypeTemplate()->Set(v8_str("plak"), v8_num(321));
2537 LocalContext env;
2538 env->Global()->Set(v8_str("Foo"), Foo->GetFunction());
2539 Local<Script> script = Script::Compile(v8_str("Foo.prototype.plak"));
2540 CHECK_EQ(script->Run()->Int32Value(), 321);
2541}
2542
2543
2544THREADED_TEST(InternalFields) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002545 LocalContext env;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002546 v8::Isolate* isolate = env->GetIsolate();
2547 v8::HandleScope scope(isolate);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002548
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002549 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002550 Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
2551 instance_templ->SetInternalFieldCount(1);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002552 Local<v8::Object> obj = templ->GetFunction()->NewInstance();
2553 CHECK_EQ(1, obj->InternalFieldCount());
2554 CHECK(obj->GetInternalField(0)->IsUndefined());
2555 obj->SetInternalField(0, v8_num(17));
2556 CHECK_EQ(17, obj->GetInternalField(0)->Int32Value());
2557}
2558
2559
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002560THREADED_TEST(GlobalObjectInternalFields) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00002561 v8::Isolate* isolate = CcTest::isolate();
2562 v8::HandleScope scope(isolate);
2563 Local<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New(isolate);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002564 global_template->SetInternalFieldCount(1);
2565 LocalContext env(NULL, global_template);
2566 v8::Handle<v8::Object> global_proxy = env->Global();
2567 v8::Handle<v8::Object> global = global_proxy->GetPrototype().As<v8::Object>();
2568 CHECK_EQ(1, global->InternalFieldCount());
2569 CHECK(global->GetInternalField(0)->IsUndefined());
2570 global->SetInternalField(0, v8_num(17));
2571 CHECK_EQ(17, global->GetInternalField(0)->Int32Value());
2572}
2573
2574
danno@chromium.org169691d2013-07-15 08:01:13 +00002575THREADED_TEST(GlobalObjectHasRealIndexedProperty) {
2576 LocalContext env;
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002577 v8::HandleScope scope(CcTest::isolate());
danno@chromium.org169691d2013-07-15 08:01:13 +00002578
2579 v8::Local<v8::Object> global = env->Global();
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00002580 global->Set(0, v8::String::NewFromUtf8(CcTest::isolate(), "value"));
danno@chromium.org169691d2013-07-15 08:01:13 +00002581 CHECK(global->HasRealIndexedProperty(0));
2582}
2583
2584
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002585static void CheckAlignedPointerInInternalField(Handle<v8::Object> obj,
2586 void* value) {
2587 CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(value) & 0x1));
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00002588 obj->SetAlignedPointerInInternalField(0, value);
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002589 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00002590 CHECK_EQ(value, obj->GetAlignedPointerFromInternalField(0));
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002591}
2592
2593
2594THREADED_TEST(InternalFieldsAlignedPointers) {
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002595 LocalContext env;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002596 v8::Isolate* isolate = env->GetIsolate();
2597 v8::HandleScope scope(isolate);
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002598
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002599 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002600 Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
2601 instance_templ->SetInternalFieldCount(1);
2602 Local<v8::Object> obj = templ->GetFunction()->NewInstance();
2603 CHECK_EQ(1, obj->InternalFieldCount());
2604
2605 CheckAlignedPointerInInternalField(obj, NULL);
2606
2607 int* heap_allocated = new int[100];
2608 CheckAlignedPointerInInternalField(obj, heap_allocated);
2609 delete[] heap_allocated;
2610
2611 int stack_allocated[100];
2612 CheckAlignedPointerInInternalField(obj, stack_allocated);
2613
2614 void* huge = reinterpret_cast<void*>(~static_cast<uintptr_t>(1));
2615 CheckAlignedPointerInInternalField(obj, huge);
2616}
2617
2618
2619static void CheckAlignedPointerInEmbedderData(LocalContext* env,
2620 int index,
2621 void* value) {
2622 CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(value) & 0x1));
2623 (*env)->SetAlignedPointerInEmbedderData(index, value);
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002624 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002625 CHECK_EQ(value, (*env)->GetAlignedPointerFromEmbedderData(index));
2626}
2627
2628
2629static void* AlignedTestPointer(int i) {
2630 return reinterpret_cast<void*>(i * 1234);
2631}
2632
2633
2634THREADED_TEST(EmbedderDataAlignedPointers) {
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002635 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00002636 v8::HandleScope scope(env->GetIsolate());
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002637
2638 CheckAlignedPointerInEmbedderData(&env, 0, NULL);
2639
2640 int* heap_allocated = new int[100];
2641 CheckAlignedPointerInEmbedderData(&env, 1, heap_allocated);
2642 delete[] heap_allocated;
2643
2644 int stack_allocated[100];
2645 CheckAlignedPointerInEmbedderData(&env, 2, stack_allocated);
2646
2647 void* huge = reinterpret_cast<void*>(~static_cast<uintptr_t>(1));
2648 CheckAlignedPointerInEmbedderData(&env, 3, huge);
2649
2650 // Test growing of the embedder data's backing store.
2651 for (int i = 0; i < 100; i++) {
2652 env->SetAlignedPointerInEmbedderData(i, AlignedTestPointer(i));
2653 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002654 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002655 for (int i = 0; i < 100; i++) {
2656 CHECK_EQ(AlignedTestPointer(i), env->GetAlignedPointerFromEmbedderData(i));
2657 }
2658}
2659
2660
2661static void CheckEmbedderData(LocalContext* env,
2662 int index,
2663 v8::Handle<Value> data) {
2664 (*env)->SetEmbedderData(index, data);
2665 CHECK((*env)->GetEmbedderData(index)->StrictEquals(data));
2666}
2667
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002668
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002669THREADED_TEST(EmbedderData) {
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002670 LocalContext env;
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002671 v8::Isolate* isolate = env->GetIsolate();
2672 v8::HandleScope scope(isolate);
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002673
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00002674 CheckEmbedderData(
2675 &env, 3,
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002676 v8::String::NewFromUtf8(isolate, "The quick brown fox jumps"));
2677 CheckEmbedderData(&env, 2, v8::String::NewFromUtf8(isolate,
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00002678 "over the lazy dog."));
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002679 CheckEmbedderData(&env, 1, v8::Number::New(isolate, 1.2345));
2680 CheckEmbedderData(&env, 0, v8::Boolean::New(isolate, true));
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002681}
2682
2683
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002684THREADED_TEST(IdentityHash) {
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002685 LocalContext env;
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002686 v8::Isolate* isolate = env->GetIsolate();
2687 v8::HandleScope scope(isolate);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002688
2689 // Ensure that the test starts with an fresh heap to test whether the hash
2690 // code is based on the address.
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002691 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002692 Local<v8::Object> obj = v8::Object::New(isolate);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002693 int hash = obj->GetIdentityHash();
2694 int hash1 = obj->GetIdentityHash();
2695 CHECK_EQ(hash, hash1);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002696 int hash2 = v8::Object::New(isolate)->GetIdentityHash();
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002697 // Since the identity hash is essentially a random number two consecutive
2698 // objects should not be assigned the same hash code. If the test below fails
2699 // the random number generator should be evaluated.
2700 CHECK_NE(hash, hash2);
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002701 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002702 int hash3 = v8::Object::New(isolate)->GetIdentityHash();
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002703 // Make sure that the identity hash is not based on the initial address of
2704 // the object alone. If the test below fails the random number generator
2705 // should be evaluated.
2706 CHECK_NE(hash, hash3);
2707 int hash4 = obj->GetIdentityHash();
2708 CHECK_EQ(hash, hash4);
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002709
2710 // Check identity hashes behaviour in the presence of JS accessors.
2711 // Put a getter for 'v8::IdentityHash' on the Object's prototype:
2712 {
2713 CompileRun("Object.prototype['v8::IdentityHash'] = 42;\n");
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002714 Local<v8::Object> o1 = v8::Object::New(isolate);
2715 Local<v8::Object> o2 = v8::Object::New(isolate);
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002716 CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash());
2717 }
2718 {
2719 CompileRun(
2720 "function cnst() { return 42; };\n"
2721 "Object.prototype.__defineGetter__('v8::IdentityHash', cnst);\n");
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002722 Local<v8::Object> o1 = v8::Object::New(isolate);
2723 Local<v8::Object> o2 = v8::Object::New(isolate);
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002724 CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash());
2725 }
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002726}
2727
2728
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002729THREADED_TEST(SymbolProperties) {
2730 i::FLAG_harmony_symbols = true;
2731
2732 LocalContext env;
2733 v8::Isolate* isolate = env->GetIsolate();
2734 v8::HandleScope scope(isolate);
2735
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002736 v8::Local<v8::Object> obj = v8::Object::New(isolate);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002737 v8::Local<v8::Symbol> sym1 = v8::Symbol::New(isolate);
2738 v8::Local<v8::Symbol> sym2 = v8::Symbol::New(isolate, "my-symbol");
2739
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002740 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002741
2742 // Check basic symbol functionality.
2743 CHECK(sym1->IsSymbol());
2744 CHECK(sym2->IsSymbol());
2745 CHECK(!obj->IsSymbol());
2746
2747 CHECK(sym1->Equals(sym1));
2748 CHECK(sym2->Equals(sym2));
2749 CHECK(!sym1->Equals(sym2));
2750 CHECK(!sym2->Equals(sym1));
2751 CHECK(sym1->StrictEquals(sym1));
2752 CHECK(sym2->StrictEquals(sym2));
2753 CHECK(!sym1->StrictEquals(sym2));
2754 CHECK(!sym2->StrictEquals(sym1));
2755
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00002756 CHECK(sym2->Name()->Equals(v8::String::NewFromUtf8(isolate, "my-symbol")));
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002757
2758 v8::Local<v8::Value> sym_val = sym2;
2759 CHECK(sym_val->IsSymbol());
2760 CHECK(sym_val->Equals(sym2));
2761 CHECK(sym_val->StrictEquals(sym2));
2762 CHECK(v8::Symbol::Cast(*sym_val)->Equals(sym2));
2763
2764 v8::Local<v8::Value> sym_obj = v8::SymbolObject::New(isolate, sym2);
2765 CHECK(sym_obj->IsSymbolObject());
2766 CHECK(!sym2->IsSymbolObject());
2767 CHECK(!obj->IsSymbolObject());
2768 CHECK(sym_obj->Equals(sym2));
2769 CHECK(!sym_obj->StrictEquals(sym2));
2770 CHECK(v8::SymbolObject::Cast(*sym_obj)->Equals(sym_obj));
danno@chromium.orgd3c42102013-08-01 16:58:23 +00002771 CHECK(v8::SymbolObject::Cast(*sym_obj)->ValueOf()->Equals(sym2));
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002772
2773 // Make sure delete of a non-existent symbol property works.
2774 CHECK(obj->Delete(sym1));
2775 CHECK(!obj->Has(sym1));
2776
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002777 CHECK(obj->Set(sym1, v8::Integer::New(isolate, 1503)));
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002778 CHECK(obj->Has(sym1));
2779 CHECK_EQ(1503, obj->Get(sym1)->Int32Value());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002780 CHECK(obj->Set(sym1, v8::Integer::New(isolate, 2002)));
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002781 CHECK(obj->Has(sym1));
2782 CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
2783 CHECK_EQ(v8::None, obj->GetPropertyAttributes(sym1));
2784
2785 CHECK_EQ(0, obj->GetOwnPropertyNames()->Length());
2786 int num_props = obj->GetPropertyNames()->Length();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002787 CHECK(obj->Set(v8::String::NewFromUtf8(isolate, "bla"),
2788 v8::Integer::New(isolate, 20)));
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002789 CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
2790 CHECK_EQ(num_props + 1, obj->GetPropertyNames()->Length());
2791
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002792 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002793
2794 // Add another property and delete it afterwards to force the object in
2795 // slow case.
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002796 CHECK(obj->Set(sym2, v8::Integer::New(isolate, 2008)));
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002797 CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
2798 CHECK_EQ(2008, obj->Get(sym2)->Int32Value());
2799 CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
2800 CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
2801
2802 CHECK(obj->Has(sym1));
2803 CHECK(obj->Has(sym2));
2804 CHECK(obj->Delete(sym2));
2805 CHECK(obj->Has(sym1));
2806 CHECK(!obj->Has(sym2));
2807 CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
2808 CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00002809
2810 // Symbol properties are inherited.
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002811 v8::Local<v8::Object> child = v8::Object::New(isolate);
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00002812 child->SetPrototype(obj);
2813 CHECK(child->Has(sym1));
2814 CHECK_EQ(2002, child->Get(sym1)->Int32Value());
2815 CHECK_EQ(0, child->GetOwnPropertyNames()->Length());
2816}
2817
2818
2819THREADED_TEST(PrivateProperties) {
2820 LocalContext env;
2821 v8::Isolate* isolate = env->GetIsolate();
2822 v8::HandleScope scope(isolate);
2823
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002824 v8::Local<v8::Object> obj = v8::Object::New(isolate);
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00002825 v8::Local<v8::Private> priv1 = v8::Private::New(isolate);
2826 v8::Local<v8::Private> priv2 = v8::Private::New(isolate, "my-private");
2827
2828 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
2829
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00002830 CHECK(priv2->Name()->Equals(v8::String::NewFromUtf8(isolate, "my-private")));
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00002831
2832 // Make sure delete of a non-existent private symbol property works.
2833 CHECK(obj->DeletePrivate(priv1));
2834 CHECK(!obj->HasPrivate(priv1));
2835
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002836 CHECK(obj->SetPrivate(priv1, v8::Integer::New(isolate, 1503)));
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00002837 CHECK(obj->HasPrivate(priv1));
2838 CHECK_EQ(1503, obj->GetPrivate(priv1)->Int32Value());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002839 CHECK(obj->SetPrivate(priv1, v8::Integer::New(isolate, 2002)));
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00002840 CHECK(obj->HasPrivate(priv1));
2841 CHECK_EQ(2002, obj->GetPrivate(priv1)->Int32Value());
2842
2843 CHECK_EQ(0, obj->GetOwnPropertyNames()->Length());
2844 int num_props = obj->GetPropertyNames()->Length();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002845 CHECK(obj->Set(v8::String::NewFromUtf8(isolate, "bla"),
2846 v8::Integer::New(isolate, 20)));
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00002847 CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
2848 CHECK_EQ(num_props + 1, obj->GetPropertyNames()->Length());
2849
2850 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
2851
2852 // Add another property and delete it afterwards to force the object in
2853 // slow case.
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002854 CHECK(obj->SetPrivate(priv2, v8::Integer::New(isolate, 2008)));
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00002855 CHECK_EQ(2002, obj->GetPrivate(priv1)->Int32Value());
2856 CHECK_EQ(2008, obj->GetPrivate(priv2)->Int32Value());
2857 CHECK_EQ(2002, obj->GetPrivate(priv1)->Int32Value());
2858 CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
2859
2860 CHECK(obj->HasPrivate(priv1));
2861 CHECK(obj->HasPrivate(priv2));
2862 CHECK(obj->DeletePrivate(priv2));
2863 CHECK(obj->HasPrivate(priv1));
2864 CHECK(!obj->HasPrivate(priv2));
2865 CHECK_EQ(2002, obj->GetPrivate(priv1)->Int32Value());
2866 CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
2867
2868 // Private properties are inherited (for the time being).
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002869 v8::Local<v8::Object> child = v8::Object::New(isolate);
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00002870 child->SetPrototype(obj);
2871 CHECK(child->HasPrivate(priv1));
2872 CHECK_EQ(2002, child->GetPrivate(priv1)->Int32Value());
2873 CHECK_EQ(0, child->GetOwnPropertyNames()->Length());
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002874}
2875
2876
ulan@chromium.org837a67e2013-06-11 15:39:48 +00002877class ScopedArrayBufferContents {
2878 public:
2879 explicit ScopedArrayBufferContents(
2880 const v8::ArrayBuffer::Contents& contents)
2881 : contents_(contents) {}
2882 ~ScopedArrayBufferContents() { free(contents_.Data()); }
2883 void* Data() const { return contents_.Data(); }
2884 size_t ByteLength() const { return contents_.ByteLength(); }
2885 private:
2886 const v8::ArrayBuffer::Contents contents_;
2887};
2888
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002889template <typename T>
2890static void CheckInternalFieldsAreZero(v8::Handle<T> value) {
2891 CHECK_EQ(T::kInternalFieldCount, value->InternalFieldCount());
2892 for (int i = 0; i < value->InternalFieldCount(); i++) {
2893 CHECK_EQ(0, value->GetInternalField(i)->Int32Value());
2894 }
2895}
2896
ulan@chromium.org837a67e2013-06-11 15:39:48 +00002897
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002898THREADED_TEST(ArrayBuffer_ApiInternalToExternal) {
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002899 LocalContext env;
2900 v8::Isolate* isolate = env->GetIsolate();
2901 v8::HandleScope handle_scope(isolate);
2902
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00002903 Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, 1024);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002904 CheckInternalFieldsAreZero(ab);
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002905 CHECK_EQ(1024, static_cast<int>(ab->ByteLength()));
2906 CHECK(!ab->IsExternal());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002907 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002908
ulan@chromium.org837a67e2013-06-11 15:39:48 +00002909 ScopedArrayBufferContents ab_contents(ab->Externalize());
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002910 CHECK(ab->IsExternal());
2911
2912 CHECK_EQ(1024, static_cast<int>(ab_contents.ByteLength()));
2913 uint8_t* data = static_cast<uint8_t*>(ab_contents.Data());
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002914 ASSERT(data != NULL);
2915 env->Global()->Set(v8_str("ab"), ab);
2916
2917 v8::Handle<v8::Value> result = CompileRun("ab.byteLength");
2918 CHECK_EQ(1024, result->Int32Value());
2919
danno@chromium.orgf005df62013-04-30 16:36:45 +00002920 result = CompileRun("var u8 = new Uint8Array(ab);"
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002921 "u8[0] = 0xFF;"
2922 "u8[1] = 0xAA;"
2923 "u8.length");
2924 CHECK_EQ(1024, result->Int32Value());
2925 CHECK_EQ(0xFF, data[0]);
2926 CHECK_EQ(0xAA, data[1]);
2927 data[0] = 0xCC;
2928 data[1] = 0x11;
2929 result = CompileRun("u8[0] + u8[1]");
2930 CHECK_EQ(0xDD, result->Int32Value());
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002931}
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002932
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002933
2934THREADED_TEST(ArrayBuffer_JSInternalToExternal) {
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002935 LocalContext env;
2936 v8::Isolate* isolate = env->GetIsolate();
2937 v8::HandleScope handle_scope(isolate);
2938
2939
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00002940 v8::Local<v8::Value> result =
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002941 CompileRun("var ab1 = new ArrayBuffer(2);"
2942 "var u8_a = new Uint8Array(ab1);"
2943 "u8_a[0] = 0xAA;"
2944 "u8_a[1] = 0xFF; u8_a.buffer");
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00002945 Local<v8::ArrayBuffer> ab1 = Local<v8::ArrayBuffer>::Cast(result);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002946 CheckInternalFieldsAreZero(ab1);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002947 CHECK_EQ(2, static_cast<int>(ab1->ByteLength()));
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002948 CHECK(!ab1->IsExternal());
ulan@chromium.org837a67e2013-06-11 15:39:48 +00002949 ScopedArrayBufferContents ab1_contents(ab1->Externalize());
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002950 CHECK(ab1->IsExternal());
2951
2952 result = CompileRun("ab1.byteLength");
2953 CHECK_EQ(2, result->Int32Value());
2954 result = CompileRun("u8_a[0]");
2955 CHECK_EQ(0xAA, result->Int32Value());
2956 result = CompileRun("u8_a[1]");
2957 CHECK_EQ(0xFF, result->Int32Value());
2958 result = CompileRun("var u8_b = new Uint8Array(ab1);"
2959 "u8_b[0] = 0xBB;"
2960 "u8_a[0]");
2961 CHECK_EQ(0xBB, result->Int32Value());
2962 result = CompileRun("u8_b[1]");
2963 CHECK_EQ(0xFF, result->Int32Value());
2964
2965 CHECK_EQ(2, static_cast<int>(ab1_contents.ByteLength()));
2966 uint8_t* ab1_data = static_cast<uint8_t*>(ab1_contents.Data());
2967 CHECK_EQ(0xBB, ab1_data[0]);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002968 CHECK_EQ(0xFF, ab1_data[1]);
2969 ab1_data[0] = 0xCC;
2970 ab1_data[1] = 0x11;
2971 result = CompileRun("u8_a[0] + u8_a[1]");
2972 CHECK_EQ(0xDD, result->Int32Value());
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002973}
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002974
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002975
2976THREADED_TEST(ArrayBuffer_External) {
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002977 LocalContext env;
2978 v8::Isolate* isolate = env->GetIsolate();
2979 v8::HandleScope handle_scope(isolate);
2980
2981 i::ScopedVector<uint8_t> my_data(100);
2982 memset(my_data.start(), 0, 100);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00002983 Local<v8::ArrayBuffer> ab3 =
2984 v8::ArrayBuffer::New(isolate, my_data.start(), 100);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002985 CheckInternalFieldsAreZero(ab3);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002986 CHECK_EQ(100, static_cast<int>(ab3->ByteLength()));
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002987 CHECK(ab3->IsExternal());
2988
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002989 env->Global()->Set(v8_str("ab3"), ab3);
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002990
2991 v8::Handle<v8::Value> result = CompileRun("ab3.byteLength");
2992 CHECK_EQ(100, result->Int32Value());
2993
danno@chromium.orgf005df62013-04-30 16:36:45 +00002994 result = CompileRun("var u8_b = new Uint8Array(ab3);"
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002995 "u8_b[0] = 0xBB;"
2996 "u8_b[1] = 0xCC;"
2997 "u8_b.length");
2998 CHECK_EQ(100, result->Int32Value());
2999 CHECK_EQ(0xBB, my_data[0]);
3000 CHECK_EQ(0xCC, my_data[1]);
3001 my_data[0] = 0xCC;
3002 my_data[1] = 0x11;
3003 result = CompileRun("u8_b[0] + u8_b[1]");
3004 CHECK_EQ(0xDD, result->Int32Value());
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003005}
3006
3007
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003008static void CheckDataViewIsNeutered(v8::Handle<v8::DataView> dv) {
3009 CHECK_EQ(0, static_cast<int>(dv->ByteLength()));
3010 CHECK_EQ(0, static_cast<int>(dv->ByteOffset()));
3011}
3012
3013
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003014static void CheckIsNeutered(v8::Handle<v8::TypedArray> ta) {
3015 CHECK_EQ(0, static_cast<int>(ta->ByteLength()));
3016 CHECK_EQ(0, static_cast<int>(ta->Length()));
3017 CHECK_EQ(0, static_cast<int>(ta->ByteOffset()));
3018}
3019
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003020
3021static void CheckIsTypedArrayVarNeutered(const char* name) {
3022 i::ScopedVector<char> source(1024);
3023 i::OS::SNPrintF(source,
3024 "%s.byteLength == 0 && %s.byteOffset == 0 && %s.length == 0",
3025 name, name, name);
3026 CHECK(CompileRun(source.start())->IsTrue());
3027 v8::Handle<v8::TypedArray> ta =
3028 v8::Handle<v8::TypedArray>::Cast(CompileRun(name));
3029 CheckIsNeutered(ta);
3030}
3031
3032
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003033template <typename TypedArray, int kElementSize>
3034static Handle<TypedArray> CreateAndCheck(Handle<v8::ArrayBuffer> ab,
3035 int byteOffset,
3036 int length) {
3037 v8::Handle<TypedArray> ta = TypedArray::New(ab, byteOffset, length);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00003038 CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003039 CHECK_EQ(byteOffset, static_cast<int>(ta->ByteOffset()));
3040 CHECK_EQ(length, static_cast<int>(ta->Length()));
3041 CHECK_EQ(length * kElementSize, static_cast<int>(ta->ByteLength()));
3042 return ta;
3043}
3044
3045
3046THREADED_TEST(ArrayBuffer_NeuteringApi) {
3047 LocalContext env;
3048 v8::Isolate* isolate = env->GetIsolate();
3049 v8::HandleScope handle_scope(isolate);
3050
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00003051 v8::Handle<v8::ArrayBuffer> buffer = v8::ArrayBuffer::New(isolate, 1024);
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003052
3053 v8::Handle<v8::Uint8Array> u8a =
3054 CreateAndCheck<v8::Uint8Array, 1>(buffer, 1, 1023);
3055 v8::Handle<v8::Uint8ClampedArray> u8c =
3056 CreateAndCheck<v8::Uint8ClampedArray, 1>(buffer, 1, 1023);
3057 v8::Handle<v8::Int8Array> i8a =
3058 CreateAndCheck<v8::Int8Array, 1>(buffer, 1, 1023);
3059
3060 v8::Handle<v8::Uint16Array> u16a =
3061 CreateAndCheck<v8::Uint16Array, 2>(buffer, 2, 511);
3062 v8::Handle<v8::Int16Array> i16a =
3063 CreateAndCheck<v8::Int16Array, 2>(buffer, 2, 511);
3064
3065 v8::Handle<v8::Uint32Array> u32a =
3066 CreateAndCheck<v8::Uint32Array, 4>(buffer, 4, 255);
3067 v8::Handle<v8::Int32Array> i32a =
3068 CreateAndCheck<v8::Int32Array, 4>(buffer, 4, 255);
3069
3070 v8::Handle<v8::Float32Array> f32a =
3071 CreateAndCheck<v8::Float32Array, 4>(buffer, 4, 255);
3072 v8::Handle<v8::Float64Array> f64a =
3073 CreateAndCheck<v8::Float64Array, 8>(buffer, 8, 127);
3074
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003075 v8::Handle<v8::DataView> dv = v8::DataView::New(buffer, 1, 1023);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00003076 CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003077 CHECK_EQ(1, static_cast<int>(dv->ByteOffset()));
3078 CHECK_EQ(1023, static_cast<int>(dv->ByteLength()));
3079
ulan@chromium.org837a67e2013-06-11 15:39:48 +00003080 ScopedArrayBufferContents contents(buffer->Externalize());
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003081 buffer->Neuter();
3082 CHECK_EQ(0, static_cast<int>(buffer->ByteLength()));
3083 CheckIsNeutered(u8a);
3084 CheckIsNeutered(u8c);
3085 CheckIsNeutered(i8a);
3086 CheckIsNeutered(u16a);
3087 CheckIsNeutered(i16a);
3088 CheckIsNeutered(u32a);
3089 CheckIsNeutered(i32a);
3090 CheckIsNeutered(f32a);
3091 CheckIsNeutered(f64a);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003092 CheckDataViewIsNeutered(dv);
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003093}
3094
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00003095
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003096THREADED_TEST(ArrayBuffer_NeuteringScript) {
3097 LocalContext env;
3098 v8::Isolate* isolate = env->GetIsolate();
3099 v8::HandleScope handle_scope(isolate);
3100
3101 CompileRun(
3102 "var ab = new ArrayBuffer(1024);"
3103 "var u8a = new Uint8Array(ab, 1, 1023);"
3104 "var u8c = new Uint8ClampedArray(ab, 1, 1023);"
3105 "var i8a = new Int8Array(ab, 1, 1023);"
3106 "var u16a = new Uint16Array(ab, 2, 511);"
3107 "var i16a = new Int16Array(ab, 2, 511);"
3108 "var u32a = new Uint32Array(ab, 4, 255);"
3109 "var i32a = new Int32Array(ab, 4, 255);"
3110 "var f32a = new Float32Array(ab, 4, 255);"
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003111 "var f64a = new Float64Array(ab, 8, 127);"
3112 "var dv = new DataView(ab, 1, 1023);");
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003113
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00003114 v8::Handle<v8::ArrayBuffer> ab =
3115 Local<v8::ArrayBuffer>::Cast(CompileRun("ab"));
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003116
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003117 v8::Handle<v8::DataView> dv =
3118 v8::Handle<v8::DataView>::Cast(CompileRun("dv"));
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003119
ulan@chromium.org837a67e2013-06-11 15:39:48 +00003120 ScopedArrayBufferContents contents(ab->Externalize());
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003121 ab->Neuter();
3122 CHECK_EQ(0, static_cast<int>(ab->ByteLength()));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003123 CHECK_EQ(0, CompileRun("ab.byteLength")->Int32Value());
3124
3125 CheckIsTypedArrayVarNeutered("u8a");
3126 CheckIsTypedArrayVarNeutered("u8c");
3127 CheckIsTypedArrayVarNeutered("i8a");
3128 CheckIsTypedArrayVarNeutered("u16a");
3129 CheckIsTypedArrayVarNeutered("i16a");
3130 CheckIsTypedArrayVarNeutered("u32a");
3131 CheckIsTypedArrayVarNeutered("i32a");
3132 CheckIsTypedArrayVarNeutered("f32a");
3133 CheckIsTypedArrayVarNeutered("f64a");
3134
3135 CHECK(CompileRun("dv.byteLength == 0 && dv.byteOffset == 0")->IsTrue());
3136 CheckDataViewIsNeutered(dv);
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003137}
3138
3139
3140
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003141THREADED_TEST(HiddenProperties) {
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003142 LocalContext env;
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003143 v8::Isolate* isolate = env->GetIsolate();
3144 v8::HandleScope scope(isolate);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003145
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003146 v8::Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003147 v8::Local<v8::String> key = v8_str("api-test::hidden-key");
3148 v8::Local<v8::String> empty = v8_str("");
3149 v8::Local<v8::String> prop_name = v8_str("prop_name");
3150
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003151 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003152
kasperl@chromium.orgacae3782009-04-11 09:17:08 +00003153 // Make sure delete of a non-existent hidden value works
3154 CHECK(obj->DeleteHiddenValue(key));
3155
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003156 CHECK(obj->SetHiddenValue(key, v8::Integer::New(isolate, 1503)));
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003157 CHECK_EQ(1503, obj->GetHiddenValue(key)->Int32Value());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003158 CHECK(obj->SetHiddenValue(key, v8::Integer::New(isolate, 2002)));
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003159 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
3160
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003161 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003162
3163 // Make sure we do not find the hidden property.
3164 CHECK(!obj->Has(empty));
3165 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
3166 CHECK(obj->Get(empty)->IsUndefined());
3167 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003168 CHECK(obj->Set(empty, v8::Integer::New(isolate, 2003)));
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003169 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
3170 CHECK_EQ(2003, obj->Get(empty)->Int32Value());
3171
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003172 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003173
3174 // Add another property and delete it afterwards to force the object in
3175 // slow case.
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003176 CHECK(obj->Set(prop_name, v8::Integer::New(isolate, 2008)));
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003177 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
3178 CHECK_EQ(2008, obj->Get(prop_name)->Int32Value());
3179 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
3180 CHECK(obj->Delete(prop_name));
3181 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
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00003185 CHECK(obj->SetHiddenValue(key, Handle<Value>()));
3186 CHECK(obj->GetHiddenValue(key).IsEmpty());
3187
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003188 CHECK(obj->SetHiddenValue(key, v8::Integer::New(isolate, 2002)));
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003189 CHECK(obj->DeleteHiddenValue(key));
3190 CHECK(obj->GetHiddenValue(key).IsEmpty());
3191}
3192
3193
ricow@chromium.org9fe9cdf2011-09-27 08:04:16 +00003194THREADED_TEST(Regress97784) {
3195 // Regression test for crbug.com/97784
3196 // Messing with the Object.prototype should not have effect on
3197 // hidden properties.
ricow@chromium.org9fe9cdf2011-09-27 08:04:16 +00003198 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003199 v8::HandleScope scope(env->GetIsolate());
ricow@chromium.org9fe9cdf2011-09-27 08:04:16 +00003200
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003201 v8::Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
ricow@chromium.org9fe9cdf2011-09-27 08:04:16 +00003202 v8::Local<v8::String> key = v8_str("hidden");
3203
3204 CompileRun(
3205 "set_called = false;"
3206 "Object.defineProperty("
3207 " Object.prototype,"
3208 " 'hidden',"
3209 " {get: function() { return 45; },"
3210 " set: function() { set_called = true; }})");
3211
3212 CHECK(obj->GetHiddenValue(key).IsEmpty());
3213 // Make sure that the getter and setter from Object.prototype is not invoked.
3214 // If it did we would have full access to the hidden properties in
3215 // the accessor.
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003216 CHECK(obj->SetHiddenValue(key, v8::Integer::New(env->GetIsolate(), 42)));
ricow@chromium.org9fe9cdf2011-09-27 08:04:16 +00003217 ExpectFalse("set_called");
3218 CHECK_EQ(42, obj->GetHiddenValue(key)->Int32Value());
3219}
3220
3221
ager@chromium.orgc4c92722009-11-18 14:12:51 +00003222static bool interceptor_for_hidden_properties_called;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003223static void InterceptorForHiddenProperties(
3224 Local<String> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.orgc4c92722009-11-18 14:12:51 +00003225 interceptor_for_hidden_properties_called = true;
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00003226}
3227
3228
3229THREADED_TEST(HiddenPropertiesWithInterceptors) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00003230 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00003231 v8::Isolate* isolate = context->GetIsolate();
3232 v8::HandleScope scope(isolate);
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00003233
ager@chromium.orgc4c92722009-11-18 14:12:51 +00003234 interceptor_for_hidden_properties_called = false;
3235
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00003236 v8::Local<v8::String> key = v8_str("api-test::hidden-key");
3237
3238 // Associate an interceptor with an object and start setting hidden values.
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00003239 Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(isolate);
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00003240 Local<v8::ObjectTemplate> instance_templ = fun_templ->InstanceTemplate();
3241 instance_templ->SetNamedPropertyHandler(InterceptorForHiddenProperties);
3242 Local<v8::Function> function = fun_templ->GetFunction();
3243 Local<v8::Object> obj = function->NewInstance();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003244 CHECK(obj->SetHiddenValue(key, v8::Integer::New(isolate, 2302)));
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00003245 CHECK_EQ(2302, obj->GetHiddenValue(key)->Int32Value());
ager@chromium.orgc4c92722009-11-18 14:12:51 +00003246 CHECK(!interceptor_for_hidden_properties_called);
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00003247}
3248
3249
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003250THREADED_TEST(External) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003251 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003252 int x = 3;
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00003253 Local<v8::External> ext = v8::External::New(CcTest::isolate(), &x);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003254 LocalContext env;
3255 env->Global()->Set(v8_str("ext"), ext);
3256 Local<Value> reext_obj = Script::Compile(v8_str("this.ext"))->Run();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00003257 v8::Handle<v8::External> reext = reext_obj.As<v8::External>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003258 int* ptr = static_cast<int*>(reext->Value());
3259 CHECK_EQ(x, 3);
3260 *ptr = 10;
3261 CHECK_EQ(x, 10);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00003262
3263 // Make sure unaligned pointers are wrapped properly.
3264 char* data = i::StrDup("0123456789");
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00003265 Local<v8::Value> zero = v8::External::New(CcTest::isolate(), &data[0]);
3266 Local<v8::Value> one = v8::External::New(CcTest::isolate(), &data[1]);
3267 Local<v8::Value> two = v8::External::New(CcTest::isolate(), &data[2]);
3268 Local<v8::Value> three = v8::External::New(CcTest::isolate(), &data[3]);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00003269
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00003270 char* char_ptr = reinterpret_cast<char*>(v8::External::Cast(*zero)->Value());
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00003271 CHECK_EQ('0', *char_ptr);
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00003272 char_ptr = reinterpret_cast<char*>(v8::External::Cast(*one)->Value());
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00003273 CHECK_EQ('1', *char_ptr);
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00003274 char_ptr = reinterpret_cast<char*>(v8::External::Cast(*two)->Value());
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00003275 CHECK_EQ('2', *char_ptr);
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00003276 char_ptr = reinterpret_cast<char*>(v8::External::Cast(*three)->Value());
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00003277 CHECK_EQ('3', *char_ptr);
3278 i::DeleteArray(data);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003279}
3280
3281
3282THREADED_TEST(GlobalHandle) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003283 v8::Isolate* isolate = CcTest::isolate();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003284 v8::Persistent<String> global;
3285 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003286 v8::HandleScope scope(isolate);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003287 global.Reset(isolate, v8_str("str"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003288 }
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00003289 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003290 v8::HandleScope scope(isolate);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003291 CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00003292 }
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00003293 global.Reset();
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003294 {
3295 v8::HandleScope scope(isolate);
3296 global.Reset(isolate, v8_str("str"));
3297 }
3298 {
3299 v8::HandleScope scope(isolate);
3300 CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
3301 }
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00003302 global.Reset();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003303}
3304
3305
ulan@chromium.org57ff8812013-05-10 08:16:55 +00003306THREADED_TEST(ResettingGlobalHandle) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003307 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00003308 v8::Persistent<String> global;
3309 {
3310 v8::HandleScope scope(isolate);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003311 global.Reset(isolate, v8_str("str"));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00003312 }
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003313 v8::internal::GlobalHandles* global_handles =
3314 reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003315 int initial_handle_count = global_handles->global_handles_count();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00003316 {
3317 v8::HandleScope scope(isolate);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003318 CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00003319 }
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003320 {
3321 v8::HandleScope scope(isolate);
3322 global.Reset(isolate, v8_str("longer"));
3323 }
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003324 CHECK_EQ(global_handles->global_handles_count(), initial_handle_count);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003325 {
3326 v8::HandleScope scope(isolate);
3327 CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 6);
3328 }
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00003329 global.Reset();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003330 CHECK_EQ(global_handles->global_handles_count(), initial_handle_count - 1);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00003331}
3332
3333
3334THREADED_TEST(ResettingGlobalHandleToEmpty) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003335 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00003336 v8::Persistent<String> global;
3337 {
3338 v8::HandleScope scope(isolate);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003339 global.Reset(isolate, v8_str("str"));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00003340 }
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003341 v8::internal::GlobalHandles* global_handles =
3342 reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003343 int initial_handle_count = global_handles->global_handles_count();
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003344 {
3345 v8::HandleScope scope(isolate);
3346 CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
3347 }
ulan@chromium.org57ff8812013-05-10 08:16:55 +00003348 {
3349 v8::HandleScope scope(isolate);
3350 Local<String> empty;
3351 global.Reset(isolate, empty);
3352 }
3353 CHECK(global.IsEmpty());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003354 CHECK_EQ(global_handles->global_handles_count(), initial_handle_count - 1);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00003355}
3356
3357
machenbach@chromium.orgc86e8c22013-11-27 15:11:04 +00003358template<class T>
3359static v8::UniquePersistent<T> PassUnique(v8::UniquePersistent<T> unique) {
3360 return unique.Pass();
3361}
3362
3363
3364template<class T>
3365static v8::UniquePersistent<T> ReturnUnique(v8::Isolate* isolate,
3366 const v8::Persistent<T> & global) {
3367 v8::UniquePersistent<String> unique(isolate, global);
3368 return unique.Pass();
3369}
3370
3371
3372THREADED_TEST(UniquePersistent) {
3373 v8::Isolate* isolate = CcTest::isolate();
3374 v8::Persistent<String> global;
3375 {
3376 v8::HandleScope scope(isolate);
3377 global.Reset(isolate, v8_str("str"));
3378 }
3379 v8::internal::GlobalHandles* global_handles =
3380 reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
3381 int initial_handle_count = global_handles->global_handles_count();
3382 {
3383 v8::UniquePersistent<String> unique(isolate, global);
3384 CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
3385 // Test assignment via Pass
3386 {
3387 v8::UniquePersistent<String> copy = unique.Pass();
3388 CHECK(unique.IsEmpty());
3389 CHECK(copy == global);
3390 CHECK_EQ(initial_handle_count + 1,
3391 global_handles->global_handles_count());
3392 unique = copy.Pass();
3393 }
3394 // Test ctor via Pass
3395 {
3396 v8::UniquePersistent<String> copy(unique.Pass());
3397 CHECK(unique.IsEmpty());
3398 CHECK(copy == global);
3399 CHECK_EQ(initial_handle_count + 1,
3400 global_handles->global_handles_count());
3401 unique = copy.Pass();
3402 }
3403 // Test pass through function call
3404 {
3405 v8::UniquePersistent<String> copy = PassUnique(unique.Pass());
3406 CHECK(unique.IsEmpty());
3407 CHECK(copy == global);
3408 CHECK_EQ(initial_handle_count + 1,
3409 global_handles->global_handles_count());
3410 unique = copy.Pass();
3411 }
3412 CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
3413 }
3414 // Test pass from function call
3415 {
3416 v8::UniquePersistent<String> unique = ReturnUnique(isolate, global);
3417 CHECK(unique == global);
3418 CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
3419 }
3420 CHECK_EQ(initial_handle_count, global_handles->global_handles_count());
3421 global.Reset();
3422}
3423
3424
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003425THREADED_TEST(GlobalHandleUpcast) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003426 v8::Isolate* isolate = CcTest::isolate();
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003427 v8::HandleScope scope(isolate);
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00003428 v8::Local<String> local = v8::Local<String>::New(isolate, v8_str("str"));
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003429 v8::Persistent<String> global_string(isolate, local);
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003430 v8::Persistent<Value>& global_value =
3431 v8::Persistent<Value>::Cast(global_string);
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003432 CHECK(v8::Local<v8::Value>::New(isolate, global_value)->IsString());
3433 CHECK(global_string == v8::Persistent<String>::Cast(global_value));
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00003434 global_string.Reset();
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003435}
3436
3437
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +00003438THREADED_TEST(HandleEquality) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003439 v8::Isolate* isolate = CcTest::isolate();
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +00003440 v8::Persistent<String> global1;
3441 v8::Persistent<String> global2;
3442 {
3443 v8::HandleScope scope(isolate);
3444 global1.Reset(isolate, v8_str("str"));
3445 global2.Reset(isolate, v8_str("str2"));
3446 }
3447 CHECK_EQ(global1 == global1, true);
3448 CHECK_EQ(global1 != global1, false);
3449 {
3450 v8::HandleScope scope(isolate);
3451 Local<String> local1 = Local<String>::New(isolate, global1);
3452 Local<String> local2 = Local<String>::New(isolate, global2);
3453
3454 CHECK_EQ(global1 == local1, true);
3455 CHECK_EQ(global1 != local1, false);
3456 CHECK_EQ(local1 == global1, true);
3457 CHECK_EQ(local1 != global1, false);
3458
3459 CHECK_EQ(global1 == local2, false);
3460 CHECK_EQ(global1 != local2, true);
3461 CHECK_EQ(local2 == global1, false);
3462 CHECK_EQ(local2 != global1, true);
3463
3464 CHECK_EQ(local1 == local2, false);
3465 CHECK_EQ(local1 != local2, true);
3466
3467 Local<String> anotherLocal1 = Local<String>::New(isolate, global1);
3468 CHECK_EQ(local1 == anotherLocal1, true);
3469 CHECK_EQ(local1 != anotherLocal1, false);
3470 }
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00003471 global1.Reset();
3472 global2.Reset();
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +00003473}
3474
3475
mstarzinger@chromium.org32280cf2012-12-06 17:32:37 +00003476THREADED_TEST(LocalHandle) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003477 v8::HandleScope scope(CcTest::isolate());
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00003478 v8::Local<String> local =
3479 v8::Local<String>::New(CcTest::isolate(), v8_str("str"));
mstarzinger@chromium.org32280cf2012-12-06 17:32:37 +00003480 CHECK_EQ(local->Length(), 3);
3481}
3482
3483
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00003484class WeakCallCounter {
3485 public:
3486 explicit WeakCallCounter(int id) : id_(id), number_of_weak_calls_(0) { }
3487 int id() { return id_; }
3488 void increment() { number_of_weak_calls_++; }
3489 int NumberOfWeakCalls() { return number_of_weak_calls_; }
3490 private:
3491 int id_;
3492 int number_of_weak_calls_;
3493};
3494
3495
mstarzinger@chromium.org69008382013-10-18 10:34:25 +00003496template<typename T>
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003497struct WeakCallCounterAndPersistent {
3498 explicit WeakCallCounterAndPersistent(WeakCallCounter* counter)
3499 : counter(counter) {}
3500 WeakCallCounter* counter;
3501 v8::Persistent<T> handle;
3502};
3503
3504
3505template <typename T>
3506static void WeakPointerCallback(
3507 const v8::WeakCallbackData<T, WeakCallCounterAndPersistent<T> >& data) {
3508 CHECK_EQ(1234, data.GetParameter()->counter->id());
3509 data.GetParameter()->counter->increment();
3510 data.GetParameter()->handle.Reset();
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00003511}
3512
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00003513
mstarzinger@chromium.org69008382013-10-18 10:34:25 +00003514template<typename T>
3515static UniqueId MakeUniqueId(const Persistent<T>& p) {
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00003516 return UniqueId(reinterpret_cast<uintptr_t>(*v8::Utils::OpenPersistent(p)));
3517}
3518
3519
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003520THREADED_TEST(ApiObjectGroups) {
3521 LocalContext env;
3522 v8::Isolate* iso = env->GetIsolate();
3523 HandleScope scope(iso);
3524
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003525 WeakCallCounter counter(1234);
3526
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003527 WeakCallCounterAndPersistent<Value> g1s1(&counter);
3528 WeakCallCounterAndPersistent<Value> g1s2(&counter);
3529 WeakCallCounterAndPersistent<Value> g1c1(&counter);
3530 WeakCallCounterAndPersistent<Value> g2s1(&counter);
3531 WeakCallCounterAndPersistent<Value> g2s2(&counter);
3532 WeakCallCounterAndPersistent<Value> g2c1(&counter);
3533
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003534 {
3535 HandleScope scope(iso);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003536 g1s1.handle.Reset(iso, Object::New(iso));
3537 g1s2.handle.Reset(iso, Object::New(iso));
3538 g1c1.handle.Reset(iso, Object::New(iso));
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003539 g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback);
3540 g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback);
3541 g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003542
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003543 g2s1.handle.Reset(iso, Object::New(iso));
3544 g2s2.handle.Reset(iso, Object::New(iso));
3545 g2c1.handle.Reset(iso, Object::New(iso));
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003546 g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback);
3547 g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback);
3548 g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003549 }
3550
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003551 WeakCallCounterAndPersistent<Value> root(&counter);
3552 root.handle.Reset(iso, g1s1.handle); // make a root.
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003553
3554 // Connect group 1 and 2, make a cycle.
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003555 {
3556 HandleScope scope(iso);
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003557 CHECK(Local<Object>::New(iso, g1s2.handle.As<Object>())->
3558 Set(0, Local<Value>::New(iso, g2s2.handle)));
3559 CHECK(Local<Object>::New(iso, g2s1.handle.As<Object>())->
3560 Set(0, Local<Value>::New(iso, g1s1.handle)));
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003561 }
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003562
3563 {
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003564 UniqueId id1 = MakeUniqueId(g1s1.handle);
3565 UniqueId id2 = MakeUniqueId(g2s2.handle);
3566 iso->SetObjectGroupId(g1s1.handle, id1);
3567 iso->SetObjectGroupId(g1s2.handle, id1);
3568 iso->SetReferenceFromGroup(id1, g1c1.handle);
3569 iso->SetObjectGroupId(g2s1.handle, id2);
3570 iso->SetObjectGroupId(g2s2.handle, id2);
3571 iso->SetReferenceFromGroup(id2, g2c1.handle);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003572 }
3573 // Do a single full GC, ensure incremental marking is stopped.
3574 v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>(
3575 iso)->heap();
3576 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
3577
3578 // All object should be alive.
3579 CHECK_EQ(0, counter.NumberOfWeakCalls());
3580
3581 // Weaken the root.
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003582 root.handle.SetWeak(&root, &WeakPointerCallback);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003583 // But make children strong roots---all the objects (except for children)
3584 // should be collectable now.
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003585 g1c1.handle.ClearWeak();
3586 g2c1.handle.ClearWeak();
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003587
3588 // Groups are deleted, rebuild groups.
3589 {
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003590 UniqueId id1 = MakeUniqueId(g1s1.handle);
3591 UniqueId id2 = MakeUniqueId(g2s2.handle);
3592 iso->SetObjectGroupId(g1s1.handle, id1);
3593 iso->SetObjectGroupId(g1s2.handle, id1);
3594 iso->SetReferenceFromGroup(id1, g1c1.handle);
3595 iso->SetObjectGroupId(g2s1.handle, id2);
3596 iso->SetObjectGroupId(g2s2.handle, id2);
3597 iso->SetReferenceFromGroup(id2, g2c1.handle);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003598 }
3599
3600 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
3601
3602 // All objects should be gone. 5 global handles in total.
3603 CHECK_EQ(5, counter.NumberOfWeakCalls());
3604
3605 // And now make children weak again and collect them.
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003606 g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback);
3607 g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003608
3609 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
3610 CHECK_EQ(7, counter.NumberOfWeakCalls());
3611}
3612
3613
mstarzinger@chromium.org69008382013-10-18 10:34:25 +00003614THREADED_TEST(ApiObjectGroupsForSubtypes) {
3615 LocalContext env;
3616 v8::Isolate* iso = env->GetIsolate();
3617 HandleScope scope(iso);
3618
mstarzinger@chromium.org69008382013-10-18 10:34:25 +00003619 WeakCallCounter counter(1234);
3620
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003621 WeakCallCounterAndPersistent<Object> g1s1(&counter);
3622 WeakCallCounterAndPersistent<String> g1s2(&counter);
3623 WeakCallCounterAndPersistent<String> g1c1(&counter);
3624 WeakCallCounterAndPersistent<Object> g2s1(&counter);
3625 WeakCallCounterAndPersistent<String> g2s2(&counter);
3626 WeakCallCounterAndPersistent<String> g2c1(&counter);
3627
mstarzinger@chromium.org69008382013-10-18 10:34:25 +00003628 {
3629 HandleScope scope(iso);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003630 g1s1.handle.Reset(iso, Object::New(iso));
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003631 g1s2.handle.Reset(iso, String::NewFromUtf8(iso, "foo1"));
3632 g1c1.handle.Reset(iso, String::NewFromUtf8(iso, "foo2"));
3633 g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback);
3634 g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback);
3635 g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback);
mstarzinger@chromium.org69008382013-10-18 10:34:25 +00003636
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003637 g2s1.handle.Reset(iso, Object::New(iso));
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003638 g2s2.handle.Reset(iso, String::NewFromUtf8(iso, "foo3"));
3639 g2c1.handle.Reset(iso, String::NewFromUtf8(iso, "foo4"));
3640 g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback);
3641 g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback);
3642 g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback);
mstarzinger@chromium.org69008382013-10-18 10:34:25 +00003643 }
3644
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003645 WeakCallCounterAndPersistent<Value> root(&counter);
3646 root.handle.Reset(iso, g1s1.handle); // make a root.
mstarzinger@chromium.org69008382013-10-18 10:34:25 +00003647
3648 // Connect group 1 and 2, make a cycle.
3649 {
3650 HandleScope scope(iso);
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003651 CHECK(Local<Object>::New(iso, g1s1.handle)
3652 ->Set(0, Local<Object>::New(iso, g2s1.handle)));
3653 CHECK(Local<Object>::New(iso, g2s1.handle)
3654 ->Set(0, Local<Object>::New(iso, g1s1.handle)));
mstarzinger@chromium.org69008382013-10-18 10:34:25 +00003655 }
3656
3657 {
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003658 UniqueId id1 = MakeUniqueId(g1s1.handle);
3659 UniqueId id2 = MakeUniqueId(g2s2.handle);
3660 iso->SetObjectGroupId(g1s1.handle, id1);
3661 iso->SetObjectGroupId(g1s2.handle, id1);
3662 iso->SetReference(g1s1.handle, g1c1.handle);
3663 iso->SetObjectGroupId(g2s1.handle, id2);
3664 iso->SetObjectGroupId(g2s2.handle, id2);
3665 iso->SetReferenceFromGroup(id2, g2c1.handle);
mstarzinger@chromium.org69008382013-10-18 10:34:25 +00003666 }
3667 // Do a single full GC, ensure incremental marking is stopped.
3668 v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>(
3669 iso)->heap();
3670 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
3671
3672 // All object should be alive.
3673 CHECK_EQ(0, counter.NumberOfWeakCalls());
3674
3675 // Weaken the root.
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003676 root.handle.SetWeak(&root, &WeakPointerCallback);
mstarzinger@chromium.org69008382013-10-18 10:34:25 +00003677 // But make children strong roots---all the objects (except for children)
3678 // should be collectable now.
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003679 g1c1.handle.ClearWeak();
3680 g2c1.handle.ClearWeak();
mstarzinger@chromium.org69008382013-10-18 10:34:25 +00003681
3682 // Groups are deleted, rebuild groups.
3683 {
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003684 UniqueId id1 = MakeUniqueId(g1s1.handle);
3685 UniqueId id2 = MakeUniqueId(g2s2.handle);
3686 iso->SetObjectGroupId(g1s1.handle, id1);
3687 iso->SetObjectGroupId(g1s2.handle, id1);
3688 iso->SetReference(g1s1.handle, g1c1.handle);
3689 iso->SetObjectGroupId(g2s1.handle, id2);
3690 iso->SetObjectGroupId(g2s2.handle, id2);
3691 iso->SetReferenceFromGroup(id2, g2c1.handle);
mstarzinger@chromium.org69008382013-10-18 10:34:25 +00003692 }
3693
3694 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
3695
3696 // All objects should be gone. 5 global handles in total.
3697 CHECK_EQ(5, counter.NumberOfWeakCalls());
3698
3699 // And now make children weak again and collect them.
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003700 g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback);
3701 g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback);
mstarzinger@chromium.org69008382013-10-18 10:34:25 +00003702
3703 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
3704 CHECK_EQ(7, counter.NumberOfWeakCalls());
3705}
3706
3707
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003708THREADED_TEST(ApiObjectGroupsCycle) {
3709 LocalContext env;
3710 v8::Isolate* iso = env->GetIsolate();
3711 HandleScope scope(iso);
3712
3713 WeakCallCounter counter(1234);
3714
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003715 WeakCallCounterAndPersistent<Value> g1s1(&counter);
3716 WeakCallCounterAndPersistent<Value> g1s2(&counter);
3717 WeakCallCounterAndPersistent<Value> g2s1(&counter);
3718 WeakCallCounterAndPersistent<Value> g2s2(&counter);
3719 WeakCallCounterAndPersistent<Value> g3s1(&counter);
3720 WeakCallCounterAndPersistent<Value> g3s2(&counter);
3721 WeakCallCounterAndPersistent<Value> g4s1(&counter);
3722 WeakCallCounterAndPersistent<Value> g4s2(&counter);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003723
3724 {
3725 HandleScope scope(iso);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003726 g1s1.handle.Reset(iso, Object::New(iso));
3727 g1s2.handle.Reset(iso, Object::New(iso));
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003728 g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback);
3729 g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback);
3730 CHECK(g1s1.handle.IsWeak());
3731 CHECK(g1s2.handle.IsWeak());
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003732
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003733 g2s1.handle.Reset(iso, Object::New(iso));
3734 g2s2.handle.Reset(iso, Object::New(iso));
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003735 g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback);
3736 g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback);
3737 CHECK(g2s1.handle.IsWeak());
3738 CHECK(g2s2.handle.IsWeak());
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003739
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003740 g3s1.handle.Reset(iso, Object::New(iso));
3741 g3s2.handle.Reset(iso, Object::New(iso));
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003742 g3s1.handle.SetWeak(&g3s1, &WeakPointerCallback);
3743 g3s2.handle.SetWeak(&g3s2, &WeakPointerCallback);
3744 CHECK(g3s1.handle.IsWeak());
3745 CHECK(g3s2.handle.IsWeak());
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003746
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003747 g4s1.handle.Reset(iso, Object::New(iso));
3748 g4s2.handle.Reset(iso, Object::New(iso));
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003749 g4s1.handle.SetWeak(&g4s1, &WeakPointerCallback);
3750 g4s2.handle.SetWeak(&g4s2, &WeakPointerCallback);
3751 CHECK(g4s1.handle.IsWeak());
3752 CHECK(g4s2.handle.IsWeak());
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003753 }
3754
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003755 WeakCallCounterAndPersistent<Value> root(&counter);
3756 root.handle.Reset(iso, g1s1.handle); // make a root.
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003757
3758 // Connect groups. We're building the following cycle:
3759 // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other
3760 // groups.
3761 {
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003762 UniqueId id1 = MakeUniqueId(g1s1.handle);
3763 UniqueId id2 = MakeUniqueId(g2s1.handle);
3764 UniqueId id3 = MakeUniqueId(g3s1.handle);
3765 UniqueId id4 = MakeUniqueId(g4s1.handle);
3766 iso->SetObjectGroupId(g1s1.handle, id1);
3767 iso->SetObjectGroupId(g1s2.handle, id1);
3768 iso->SetReferenceFromGroup(id1, g2s1.handle);
3769 iso->SetObjectGroupId(g2s1.handle, id2);
3770 iso->SetObjectGroupId(g2s2.handle, id2);
3771 iso->SetReferenceFromGroup(id2, g3s1.handle);
3772 iso->SetObjectGroupId(g3s1.handle, id3);
3773 iso->SetObjectGroupId(g3s2.handle, id3);
3774 iso->SetReferenceFromGroup(id3, g4s1.handle);
3775 iso->SetObjectGroupId(g4s1.handle, id4);
3776 iso->SetObjectGroupId(g4s2.handle, id4);
3777 iso->SetReferenceFromGroup(id4, g1s1.handle);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003778 }
3779 // Do a single full GC
3780 v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>(
3781 iso)->heap();
3782 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
3783
3784 // All object should be alive.
3785 CHECK_EQ(0, counter.NumberOfWeakCalls());
3786
3787 // Weaken the root.
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003788 root.handle.SetWeak(&root, &WeakPointerCallback);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003789
3790 // Groups are deleted, rebuild groups.
3791 {
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003792 UniqueId id1 = MakeUniqueId(g1s1.handle);
3793 UniqueId id2 = MakeUniqueId(g2s1.handle);
3794 UniqueId id3 = MakeUniqueId(g3s1.handle);
3795 UniqueId id4 = MakeUniqueId(g4s1.handle);
3796 iso->SetObjectGroupId(g1s1.handle, id1);
3797 iso->SetObjectGroupId(g1s2.handle, id1);
3798 iso->SetReferenceFromGroup(id1, g2s1.handle);
3799 iso->SetObjectGroupId(g2s1.handle, id2);
3800 iso->SetObjectGroupId(g2s2.handle, id2);
3801 iso->SetReferenceFromGroup(id2, g3s1.handle);
3802 iso->SetObjectGroupId(g3s1.handle, id3);
3803 iso->SetObjectGroupId(g3s2.handle, id3);
3804 iso->SetReferenceFromGroup(id3, g4s1.handle);
3805 iso->SetObjectGroupId(g4s1.handle, id4);
3806 iso->SetObjectGroupId(g4s2.handle, id4);
3807 iso->SetReferenceFromGroup(id4, g1s1.handle);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003808 }
3809
3810 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
3811
3812 // All objects should be gone. 9 global handles in total.
3813 CHECK_EQ(9, counter.NumberOfWeakCalls());
3814}
3815
3816
mvstanton@chromium.orge4ac3ef2012-11-12 14:53:34 +00003817// TODO(mstarzinger): This should be a THREADED_TEST but causes failures
3818// on the buildbots, so was made non-threaded for the time being.
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003819TEST(ApiObjectGroupsCycleForScavenger) {
3820 i::FLAG_stress_compaction = false;
3821 i::FLAG_gc_global = false;
3822 LocalContext env;
3823 v8::Isolate* iso = env->GetIsolate();
3824 HandleScope scope(iso);
3825
3826 WeakCallCounter counter(1234);
3827
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003828 WeakCallCounterAndPersistent<Value> g1s1(&counter);
3829 WeakCallCounterAndPersistent<Value> g1s2(&counter);
3830 WeakCallCounterAndPersistent<Value> g2s1(&counter);
3831 WeakCallCounterAndPersistent<Value> g2s2(&counter);
3832 WeakCallCounterAndPersistent<Value> g3s1(&counter);
3833 WeakCallCounterAndPersistent<Value> g3s2(&counter);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003834
3835 {
3836 HandleScope scope(iso);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003837 g1s1.handle.Reset(iso, Object::New(iso));
3838 g1s2.handle.Reset(iso, Object::New(iso));
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003839 g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback);
3840 g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003841
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003842 g2s1.handle.Reset(iso, Object::New(iso));
3843 g2s2.handle.Reset(iso, Object::New(iso));
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003844 g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback);
3845 g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003846
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003847 g3s1.handle.Reset(iso, Object::New(iso));
3848 g3s2.handle.Reset(iso, Object::New(iso));
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003849 g3s1.handle.SetWeak(&g3s1, &WeakPointerCallback);
3850 g3s2.handle.SetWeak(&g3s2, &WeakPointerCallback);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003851 }
3852
3853 // Make a root.
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003854 WeakCallCounterAndPersistent<Value> root(&counter);
3855 root.handle.Reset(iso, g1s1.handle);
3856 root.handle.MarkPartiallyDependent();
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003857
3858 // Connect groups. We're building the following cycle:
3859 // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other
3860 // groups.
3861 {
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003862 HandleScope handle_scope(iso);
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003863 g1s1.handle.MarkPartiallyDependent();
3864 g1s2.handle.MarkPartiallyDependent();
3865 g2s1.handle.MarkPartiallyDependent();
3866 g2s2.handle.MarkPartiallyDependent();
3867 g3s1.handle.MarkPartiallyDependent();
3868 g3s2.handle.MarkPartiallyDependent();
3869 iso->SetObjectGroupId(g1s1.handle, UniqueId(1));
3870 iso->SetObjectGroupId(g1s2.handle, UniqueId(1));
3871 Local<Object>::New(iso, g1s1.handle.As<Object>())->Set(
3872 v8_str("x"), Local<Value>::New(iso, g2s1.handle));
3873 iso->SetObjectGroupId(g2s1.handle, UniqueId(2));
3874 iso->SetObjectGroupId(g2s2.handle, UniqueId(2));
3875 Local<Object>::New(iso, g2s1.handle.As<Object>())->Set(
3876 v8_str("x"), Local<Value>::New(iso, g3s1.handle));
3877 iso->SetObjectGroupId(g3s1.handle, UniqueId(3));
3878 iso->SetObjectGroupId(g3s2.handle, UniqueId(3));
3879 Local<Object>::New(iso, g3s1.handle.As<Object>())->Set(
3880 v8_str("x"), Local<Value>::New(iso, g1s1.handle));
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003881 }
3882
3883 v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>(
3884 iso)->heap();
3885 heap->CollectGarbage(i::NEW_SPACE);
3886
3887 // All objects should be alive.
3888 CHECK_EQ(0, counter.NumberOfWeakCalls());
3889
3890 // Weaken the root.
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003891 root.handle.SetWeak(&root, &WeakPointerCallback);
3892 root.handle.MarkPartiallyDependent();
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003893
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003894 // Groups are deleted, rebuild groups.
3895 {
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003896 HandleScope handle_scope(iso);
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003897 g1s1.handle.MarkPartiallyDependent();
3898 g1s2.handle.MarkPartiallyDependent();
3899 g2s1.handle.MarkPartiallyDependent();
3900 g2s2.handle.MarkPartiallyDependent();
3901 g3s1.handle.MarkPartiallyDependent();
3902 g3s2.handle.MarkPartiallyDependent();
3903 iso->SetObjectGroupId(g1s1.handle, UniqueId(1));
3904 iso->SetObjectGroupId(g1s2.handle, UniqueId(1));
3905 Local<Object>::New(iso, g1s1.handle.As<Object>())->Set(
3906 v8_str("x"), Local<Value>::New(iso, g2s1.handle));
3907 iso->SetObjectGroupId(g2s1.handle, UniqueId(2));
3908 iso->SetObjectGroupId(g2s2.handle, UniqueId(2));
3909 Local<Object>::New(iso, g2s1.handle.As<Object>())->Set(
3910 v8_str("x"), Local<Value>::New(iso, g3s1.handle));
3911 iso->SetObjectGroupId(g3s1.handle, UniqueId(3));
3912 iso->SetObjectGroupId(g3s2.handle, UniqueId(3));
3913 Local<Object>::New(iso, g3s1.handle.As<Object>())->Set(
3914 v8_str("x"), Local<Value>::New(iso, g1s1.handle));
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003915 }
3916
3917 heap->CollectGarbage(i::NEW_SPACE);
3918
3919 // All objects should be gone. 7 global handles in total.
3920 CHECK_EQ(7, counter.NumberOfWeakCalls());
3921}
3922
3923
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003924THREADED_TEST(ScriptException) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003925 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003926 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003927 Local<Script> script = Script::Compile(v8_str("throw 'panama!';"));
3928 v8::TryCatch try_catch;
3929 Local<Value> result = script->Run();
3930 CHECK(result.IsEmpty());
3931 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00003932 String::Utf8Value exception_value(try_catch.Exception());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003933 CHECK_EQ(*exception_value, "panama!");
3934}
3935
3936
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00003937TEST(TryCatchCustomException) {
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00003938 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003939 v8::HandleScope scope(env->GetIsolate());
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00003940 v8::TryCatch try_catch;
3941 CompileRun("function CustomError() { this.a = 'b'; }"
3942 "(function f() { throw new CustomError(); })();");
3943 CHECK(try_catch.HasCaught());
3944 CHECK(try_catch.Exception()->ToObject()->
3945 Get(v8_str("a"))->Equals(v8_str("b")));
3946}
3947
3948
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003949bool message_received;
3950
3951
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00003952static void check_message_0(v8::Handle<v8::Message> message,
3953 v8::Handle<Value> data) {
hpayer@chromium.org8432c912013-02-28 15:55:26 +00003954 CHECK_EQ(5.76, data->NumberValue());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003955 CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
ager@chromium.org65dad4b2009-04-23 08:48:43 +00003956 CHECK_EQ(7.56, message->GetScriptData()->NumberValue());
danno@chromium.orgd3c42102013-08-01 16:58:23 +00003957 CHECK(!message->IsSharedCrossOrigin());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003958 message_received = true;
3959}
3960
3961
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00003962THREADED_TEST(MessageHandler0) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003963 message_received = false;
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003964 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003965 CHECK(!message_received);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003966 LocalContext context;
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003967 v8::V8::AddMessageListener(check_message_0, v8_num(5.76));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003968 v8::ScriptOrigin origin =
3969 v8::ScriptOrigin(v8_str("6.75"));
ager@chromium.org65dad4b2009-04-23 08:48:43 +00003970 v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
3971 &origin);
3972 script->SetData(v8_str("7.56"));
3973 script->Run();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003974 CHECK(message_received);
3975 // clear out the message listener
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00003976 v8::V8::RemoveMessageListeners(check_message_0);
3977}
3978
3979
3980static void check_message_1(v8::Handle<v8::Message> message,
3981 v8::Handle<Value> data) {
3982 CHECK(data->IsNumber());
3983 CHECK_EQ(1337, data->Int32Value());
danno@chromium.orgd3c42102013-08-01 16:58:23 +00003984 CHECK(!message->IsSharedCrossOrigin());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00003985 message_received = true;
3986}
3987
3988
3989TEST(MessageHandler1) {
3990 message_received = false;
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003991 v8::HandleScope scope(CcTest::isolate());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00003992 CHECK(!message_received);
3993 v8::V8::AddMessageListener(check_message_1);
3994 LocalContext context;
3995 CompileRun("throw 1337;");
3996 CHECK(message_received);
3997 // clear out the message listener
3998 v8::V8::RemoveMessageListeners(check_message_1);
3999}
4000
4001
4002static void check_message_2(v8::Handle<v8::Message> message,
4003 v8::Handle<Value> data) {
4004 LocalContext context;
4005 CHECK(data->IsObject());
4006 v8::Local<v8::Value> hidden_property =
4007 v8::Object::Cast(*data)->GetHiddenValue(v8_str("hidden key"));
4008 CHECK(v8_str("hidden value")->Equals(hidden_property));
danno@chromium.orgd3c42102013-08-01 16:58:23 +00004009 CHECK(!message->IsSharedCrossOrigin());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00004010 message_received = true;
4011}
4012
4013
4014TEST(MessageHandler2) {
4015 message_received = false;
machenbach@chromium.org528ce022013-09-23 14:09:36 +00004016 v8::HandleScope scope(CcTest::isolate());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00004017 CHECK(!message_received);
4018 v8::V8::AddMessageListener(check_message_2);
4019 LocalContext context;
4020 v8::Local<v8::Value> error = v8::Exception::Error(v8_str("custom error"));
4021 v8::Object::Cast(*error)->SetHiddenValue(v8_str("hidden key"),
4022 v8_str("hidden value"));
4023 context->Global()->Set(v8_str("error"), error);
4024 CompileRun("throw error;");
4025 CHECK(message_received);
4026 // clear out the message listener
4027 v8::V8::RemoveMessageListeners(check_message_2);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004028}
4029
4030
danno@chromium.orgd3c42102013-08-01 16:58:23 +00004031static void check_message_3(v8::Handle<v8::Message> message,
4032 v8::Handle<Value> data) {
4033 CHECK(message->IsSharedCrossOrigin());
4034 CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
4035 message_received = true;
4036}
4037
4038
4039TEST(MessageHandler3) {
4040 message_received = false;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00004041 v8::Isolate* isolate = CcTest::isolate();
4042 v8::HandleScope scope(isolate);
danno@chromium.orgd3c42102013-08-01 16:58:23 +00004043 CHECK(!message_received);
4044 v8::V8::AddMessageListener(check_message_3);
4045 LocalContext context;
4046 v8::ScriptOrigin origin =
4047 v8::ScriptOrigin(v8_str("6.75"),
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004048 v8::Integer::New(isolate, 1),
4049 v8::Integer::New(isolate, 2),
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00004050 v8::True(isolate));
danno@chromium.orgd3c42102013-08-01 16:58:23 +00004051 v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
4052 &origin);
4053 script->Run();
4054 CHECK(message_received);
4055 // clear out the message listener
4056 v8::V8::RemoveMessageListeners(check_message_3);
4057}
4058
4059
4060static void check_message_4(v8::Handle<v8::Message> message,
4061 v8::Handle<Value> data) {
4062 CHECK(!message->IsSharedCrossOrigin());
4063 CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
4064 message_received = true;
4065}
4066
4067
4068TEST(MessageHandler4) {
4069 message_received = false;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00004070 v8::Isolate* isolate = CcTest::isolate();
4071 v8::HandleScope scope(isolate);
danno@chromium.orgd3c42102013-08-01 16:58:23 +00004072 CHECK(!message_received);
4073 v8::V8::AddMessageListener(check_message_4);
4074 LocalContext context;
4075 v8::ScriptOrigin origin =
4076 v8::ScriptOrigin(v8_str("6.75"),
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004077 v8::Integer::New(isolate, 1),
4078 v8::Integer::New(isolate, 2),
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00004079 v8::False(isolate));
danno@chromium.orgd3c42102013-08-01 16:58:23 +00004080 v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
4081 &origin);
4082 script->Run();
4083 CHECK(message_received);
4084 // clear out the message listener
4085 v8::V8::RemoveMessageListeners(check_message_4);
4086}
4087
4088
4089static void check_message_5a(v8::Handle<v8::Message> message,
4090 v8::Handle<Value> data) {
4091 CHECK(message->IsSharedCrossOrigin());
4092 CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
4093 message_received = true;
4094}
4095
4096
4097static void check_message_5b(v8::Handle<v8::Message> message,
4098 v8::Handle<Value> data) {
4099 CHECK(!message->IsSharedCrossOrigin());
4100 CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
4101 message_received = true;
4102}
4103
4104
4105TEST(MessageHandler5) {
4106 message_received = false;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00004107 v8::Isolate* isolate = CcTest::isolate();
4108 v8::HandleScope scope(isolate);
danno@chromium.orgd3c42102013-08-01 16:58:23 +00004109 CHECK(!message_received);
4110 v8::V8::AddMessageListener(check_message_5a);
4111 LocalContext context;
4112 v8::ScriptOrigin origin =
4113 v8::ScriptOrigin(v8_str("6.75"),
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004114 v8::Integer::New(isolate, 1),
4115 v8::Integer::New(isolate, 2),
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00004116 v8::True(isolate));
danno@chromium.orgd3c42102013-08-01 16:58:23 +00004117 v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
4118 &origin);
4119 script->Run();
4120 CHECK(message_received);
4121 // clear out the message listener
4122 v8::V8::RemoveMessageListeners(check_message_5a);
4123
4124 message_received = false;
4125 v8::V8::AddMessageListener(check_message_5b);
4126 origin =
4127 v8::ScriptOrigin(v8_str("6.75"),
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004128 v8::Integer::New(isolate, 1),
4129 v8::Integer::New(isolate, 2),
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00004130 v8::False(isolate));
danno@chromium.orgd3c42102013-08-01 16:58:23 +00004131 script = Script::Compile(v8_str("throw 'error'"),
4132 &origin);
4133 script->Run();
4134 CHECK(message_received);
4135 // clear out the message listener
4136 v8::V8::RemoveMessageListeners(check_message_5b);
4137}
4138
4139
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004140THREADED_TEST(GetSetProperty) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004141 LocalContext context;
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004142 v8::Isolate* isolate = context->GetIsolate();
4143 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004144 context->Global()->Set(v8_str("foo"), v8_num(14));
4145 context->Global()->Set(v8_str("12"), v8_num(92));
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004146 context->Global()->Set(v8::Integer::New(isolate, 16), v8_num(32));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004147 context->Global()->Set(v8_num(13), v8_num(56));
4148 Local<Value> foo = Script::Compile(v8_str("this.foo"))->Run();
4149 CHECK_EQ(14, foo->Int32Value());
4150 Local<Value> twelve = Script::Compile(v8_str("this[12]"))->Run();
4151 CHECK_EQ(92, twelve->Int32Value());
4152 Local<Value> sixteen = Script::Compile(v8_str("this[16]"))->Run();
4153 CHECK_EQ(32, sixteen->Int32Value());
4154 Local<Value> thirteen = Script::Compile(v8_str("this[13]"))->Run();
4155 CHECK_EQ(56, thirteen->Int32Value());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004156 CHECK_EQ(92,
4157 context->Global()->Get(v8::Integer::New(isolate, 12))->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004158 CHECK_EQ(92, context->Global()->Get(v8_str("12"))->Int32Value());
4159 CHECK_EQ(92, context->Global()->Get(v8_num(12))->Int32Value());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004160 CHECK_EQ(32,
4161 context->Global()->Get(v8::Integer::New(isolate, 16))->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004162 CHECK_EQ(32, context->Global()->Get(v8_str("16"))->Int32Value());
4163 CHECK_EQ(32, context->Global()->Get(v8_num(16))->Int32Value());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004164 CHECK_EQ(56,
4165 context->Global()->Get(v8::Integer::New(isolate, 13))->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004166 CHECK_EQ(56, context->Global()->Get(v8_str("13"))->Int32Value());
4167 CHECK_EQ(56, context->Global()->Get(v8_num(13))->Int32Value());
4168}
4169
4170
4171THREADED_TEST(PropertyAttributes) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004172 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004173 v8::HandleScope scope(context->GetIsolate());
rossberg@chromium.org717967f2011-07-20 13:44:42 +00004174 // none
4175 Local<String> prop = v8_str("none");
4176 context->Global()->Set(prop, v8_num(7));
4177 CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(prop));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004178 // read-only
rossberg@chromium.org717967f2011-07-20 13:44:42 +00004179 prop = v8_str("read_only");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004180 context->Global()->Set(prop, v8_num(7), v8::ReadOnly);
4181 CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
rossberg@chromium.org717967f2011-07-20 13:44:42 +00004182 CHECK_EQ(v8::ReadOnly, context->Global()->GetPropertyAttributes(prop));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004183 Script::Compile(v8_str("read_only = 9"))->Run();
4184 CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
4185 context->Global()->Set(prop, v8_num(10));
4186 CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
4187 // dont-delete
4188 prop = v8_str("dont_delete");
4189 context->Global()->Set(prop, v8_num(13), v8::DontDelete);
4190 CHECK_EQ(13, context->Global()->Get(prop)->Int32Value());
4191 Script::Compile(v8_str("delete dont_delete"))->Run();
4192 CHECK_EQ(13, context->Global()->Get(prop)->Int32Value());
rossberg@chromium.org717967f2011-07-20 13:44:42 +00004193 CHECK_EQ(v8::DontDelete, context->Global()->GetPropertyAttributes(prop));
4194 // dont-enum
4195 prop = v8_str("dont_enum");
4196 context->Global()->Set(prop, v8_num(28), v8::DontEnum);
4197 CHECK_EQ(v8::DontEnum, context->Global()->GetPropertyAttributes(prop));
4198 // absent
4199 prop = v8_str("absent");
4200 CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(prop));
4201 Local<Value> fake_prop = v8_num(1);
4202 CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(fake_prop));
4203 // exception
4204 TryCatch try_catch;
4205 Local<Value> exception =
4206 CompileRun("({ toString: function() { throw 'exception';} })");
4207 CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(exception));
4208 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00004209 String::Utf8Value exception_value(try_catch.Exception());
rossberg@chromium.org717967f2011-07-20 13:44:42 +00004210 CHECK_EQ("exception", *exception_value);
4211 try_catch.Reset();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004212}
4213
4214
4215THREADED_TEST(Array) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004216 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004217 v8::HandleScope scope(context->GetIsolate());
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00004218 Local<v8::Array> array = v8::Array::New(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004219 CHECK_EQ(0, array->Length());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004220 CHECK(array->Get(0)->IsUndefined());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004221 CHECK(!array->Has(0));
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004222 CHECK(array->Get(100)->IsUndefined());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004223 CHECK(!array->Has(100));
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004224 array->Set(2, v8_num(7));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004225 CHECK_EQ(3, array->Length());
4226 CHECK(!array->Has(0));
4227 CHECK(!array->Has(1));
4228 CHECK(array->Has(2));
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004229 CHECK_EQ(7, array->Get(2)->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004230 Local<Value> obj = Script::Compile(v8_str("[1, 2, 3]"))->Run();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004231 Local<v8::Array> arr = obj.As<v8::Array>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004232 CHECK_EQ(3, arr->Length());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004233 CHECK_EQ(1, arr->Get(0)->Int32Value());
4234 CHECK_EQ(2, arr->Get(1)->Int32Value());
4235 CHECK_EQ(3, arr->Get(2)->Int32Value());
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00004236 array = v8::Array::New(context->GetIsolate(), 27);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00004237 CHECK_EQ(27, array->Length());
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00004238 array = v8::Array::New(context->GetIsolate(), -27);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00004239 CHECK_EQ(0, array->Length());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004240}
4241
4242
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00004243void HandleF(const v8::FunctionCallbackInfo<v8::Value>& args) {
machenbach@chromium.orgafbdadc2013-12-09 16:12:18 +00004244 v8::EscapableHandleScope scope(args.GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004245 ApiTestFuzzer::Fuzz();
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00004246 Local<v8::Array> result = v8::Array::New(args.GetIsolate(), args.Length());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004247 for (int i = 0; i < args.Length(); i++)
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004248 result->Set(i, args[i]);
machenbach@chromium.orgafbdadc2013-12-09 16:12:18 +00004249 args.GetReturnValue().Set(scope.Escape(result));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004250}
4251
4252
4253THREADED_TEST(Vector) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00004254 v8::Isolate* isolate = CcTest::isolate();
4255 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004256 Local<ObjectTemplate> global = ObjectTemplate::New(isolate);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00004257 global->Set(v8_str("f"), v8::FunctionTemplate::New(isolate, HandleF));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004258 LocalContext context(0, global);
4259
4260 const char* fun = "f()";
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004261 Local<v8::Array> a0 = CompileRun(fun).As<v8::Array>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004262 CHECK_EQ(0, a0->Length());
4263
4264 const char* fun2 = "f(11)";
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004265 Local<v8::Array> a1 = CompileRun(fun2).As<v8::Array>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004266 CHECK_EQ(1, a1->Length());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004267 CHECK_EQ(11, a1->Get(0)->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004268
4269 const char* fun3 = "f(12, 13)";
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004270 Local<v8::Array> a2 = CompileRun(fun3).As<v8::Array>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004271 CHECK_EQ(2, a2->Length());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004272 CHECK_EQ(12, a2->Get(0)->Int32Value());
4273 CHECK_EQ(13, a2->Get(1)->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004274
4275 const char* fun4 = "f(14, 15, 16)";
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004276 Local<v8::Array> a3 = CompileRun(fun4).As<v8::Array>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004277 CHECK_EQ(3, a3->Length());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004278 CHECK_EQ(14, a3->Get(0)->Int32Value());
4279 CHECK_EQ(15, a3->Get(1)->Int32Value());
4280 CHECK_EQ(16, a3->Get(2)->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004281
4282 const char* fun5 = "f(17, 18, 19, 20)";
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004283 Local<v8::Array> a4 = CompileRun(fun5).As<v8::Array>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004284 CHECK_EQ(4, a4->Length());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004285 CHECK_EQ(17, a4->Get(0)->Int32Value());
4286 CHECK_EQ(18, a4->Get(1)->Int32Value());
4287 CHECK_EQ(19, a4->Get(2)->Int32Value());
4288 CHECK_EQ(20, a4->Get(3)->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004289}
4290
4291
4292THREADED_TEST(FunctionCall) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004293 LocalContext context;
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +00004294 v8::Isolate* isolate = context->GetIsolate();
4295 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004296 CompileRun(
4297 "function Foo() {"
4298 " var result = [];"
4299 " for (var i = 0; i < arguments.length; i++) {"
4300 " result.push(arguments[i]);"
4301 " }"
4302 " return result;"
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +00004303 "}"
4304 "function ReturnThisSloppy() {"
4305 " return this;"
4306 "}"
4307 "function ReturnThisStrict() {"
4308 " 'use strict';"
4309 " return this;"
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004310 "}");
4311 Local<Function> Foo =
4312 Local<Function>::Cast(context->Global()->Get(v8_str("Foo")));
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +00004313 Local<Function> ReturnThisSloppy =
4314 Local<Function>::Cast(context->Global()->Get(v8_str("ReturnThisSloppy")));
4315 Local<Function> ReturnThisStrict =
4316 Local<Function>::Cast(context->Global()->Get(v8_str("ReturnThisStrict")));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004317
4318 v8::Handle<Value>* args0 = NULL;
4319 Local<v8::Array> a0 = Local<v8::Array>::Cast(Foo->Call(Foo, 0, args0));
4320 CHECK_EQ(0, a0->Length());
4321
4322 v8::Handle<Value> args1[] = { v8_num(1.1) };
4323 Local<v8::Array> a1 = Local<v8::Array>::Cast(Foo->Call(Foo, 1, args1));
4324 CHECK_EQ(1, a1->Length());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004325 CHECK_EQ(1.1, a1->Get(v8::Integer::New(isolate, 0))->NumberValue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004326
4327 v8::Handle<Value> args2[] = { v8_num(2.2),
4328 v8_num(3.3) };
4329 Local<v8::Array> a2 = Local<v8::Array>::Cast(Foo->Call(Foo, 2, args2));
4330 CHECK_EQ(2, a2->Length());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004331 CHECK_EQ(2.2, a2->Get(v8::Integer::New(isolate, 0))->NumberValue());
4332 CHECK_EQ(3.3, a2->Get(v8::Integer::New(isolate, 1))->NumberValue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004333
4334 v8::Handle<Value> args3[] = { v8_num(4.4),
4335 v8_num(5.5),
4336 v8_num(6.6) };
4337 Local<v8::Array> a3 = Local<v8::Array>::Cast(Foo->Call(Foo, 3, args3));
4338 CHECK_EQ(3, a3->Length());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004339 CHECK_EQ(4.4, a3->Get(v8::Integer::New(isolate, 0))->NumberValue());
4340 CHECK_EQ(5.5, a3->Get(v8::Integer::New(isolate, 1))->NumberValue());
4341 CHECK_EQ(6.6, a3->Get(v8::Integer::New(isolate, 2))->NumberValue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004342
4343 v8::Handle<Value> args4[] = { v8_num(7.7),
4344 v8_num(8.8),
4345 v8_num(9.9),
4346 v8_num(10.11) };
4347 Local<v8::Array> a4 = Local<v8::Array>::Cast(Foo->Call(Foo, 4, args4));
4348 CHECK_EQ(4, a4->Length());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004349 CHECK_EQ(7.7, a4->Get(v8::Integer::New(isolate, 0))->NumberValue());
4350 CHECK_EQ(8.8, a4->Get(v8::Integer::New(isolate, 1))->NumberValue());
4351 CHECK_EQ(9.9, a4->Get(v8::Integer::New(isolate, 2))->NumberValue());
4352 CHECK_EQ(10.11, a4->Get(v8::Integer::New(isolate, 3))->NumberValue());
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +00004353
4354 Local<v8::Value> r1 = ReturnThisSloppy->Call(v8::Undefined(isolate), 0, NULL);
4355 CHECK(r1->StrictEquals(context->Global()));
4356 Local<v8::Value> r2 = ReturnThisSloppy->Call(v8::Null(isolate), 0, NULL);
4357 CHECK(r2->StrictEquals(context->Global()));
4358 Local<v8::Value> r3 = ReturnThisSloppy->Call(v8_num(42), 0, NULL);
4359 CHECK(r3->IsNumberObject());
4360 CHECK_EQ(42.0, r3.As<v8::NumberObject>()->ValueOf());
4361 Local<v8::Value> r4 = ReturnThisSloppy->Call(v8_str("hello"), 0, NULL);
4362 CHECK(r4->IsStringObject());
4363 CHECK(r4.As<v8::StringObject>()->ValueOf()->StrictEquals(v8_str("hello")));
4364 Local<v8::Value> r5 = ReturnThisSloppy->Call(v8::True(isolate), 0, NULL);
4365 CHECK(r5->IsBooleanObject());
4366 CHECK(r5.As<v8::BooleanObject>()->ValueOf());
4367
4368 Local<v8::Value> r6 = ReturnThisStrict->Call(v8::Undefined(isolate), 0, NULL);
4369 CHECK(r6->IsUndefined());
4370 Local<v8::Value> r7 = ReturnThisStrict->Call(v8::Null(isolate), 0, NULL);
4371 CHECK(r7->IsNull());
4372 Local<v8::Value> r8 = ReturnThisStrict->Call(v8_num(42), 0, NULL);
4373 CHECK(r8->StrictEquals(v8_num(42)));
4374 Local<v8::Value> r9 = ReturnThisStrict->Call(v8_str("hello"), 0, NULL);
4375 CHECK(r9->StrictEquals(v8_str("hello")));
4376 Local<v8::Value> r10 = ReturnThisStrict->Call(v8::True(isolate), 0, NULL);
4377 CHECK(r10->StrictEquals(v8::True(isolate)));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004378}
4379
4380
4381static const char* js_code_causing_out_of_memory =
4382 "var a = new Array(); while(true) a.push(a);";
4383
4384
4385// These tests run for a long time and prevent us from running tests
4386// that come after them so they cannot run in parallel.
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00004387TEST(OutOfMemory) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004388 // It's not possible to read a snapshot into a heap with different dimensions.
lrn@chromium.org32d961d2010-06-30 09:09:34 +00004389 if (i::Snapshot::IsEnabled()) return;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004390 // Set heap limits.
4391 static const int K = 1024;
4392 v8::ResourceConstraints constraints;
4393 constraints.set_max_young_space_size(256 * K);
machenbach@chromium.orgc1789ee2013-07-05 07:09:57 +00004394 constraints.set_max_old_space_size(5 * K * K);
machenbach@chromium.org7ff76072013-11-21 09:47:43 +00004395 v8::SetResourceConstraints(CcTest::isolate(), &constraints);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004396
4397 // Execute a script that causes out of memory.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004398 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004399 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004400 v8::V8::IgnoreOutOfMemoryException();
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00004401 Local<Script> script = Script::Compile(String::NewFromUtf8(
4402 context->GetIsolate(), js_code_causing_out_of_memory));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004403 Local<Value> result = script->Run();
4404
4405 // Check for out of memory state.
4406 CHECK(result.IsEmpty());
4407 CHECK(context->HasOutOfMemoryException());
4408}
4409
4410
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00004411void ProvokeOutOfMemory(const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004412 ApiTestFuzzer::Fuzz();
4413
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004414 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004415 v8::HandleScope scope(context->GetIsolate());
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00004416 Local<Script> script = Script::Compile(String::NewFromUtf8(
4417 context->GetIsolate(), js_code_causing_out_of_memory));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004418 Local<Value> result = script->Run();
4419
4420 // Check for out of memory state.
4421 CHECK(result.IsEmpty());
4422 CHECK(context->HasOutOfMemoryException());
4423
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00004424 args.GetReturnValue().Set(result);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004425}
4426
4427
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00004428TEST(OutOfMemoryNested) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004429 // It's not possible to read a snapshot into a heap with different dimensions.
lrn@chromium.org32d961d2010-06-30 09:09:34 +00004430 if (i::Snapshot::IsEnabled()) return;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004431 // Set heap limits.
4432 static const int K = 1024;
4433 v8::ResourceConstraints constraints;
4434 constraints.set_max_young_space_size(256 * K);
machenbach@chromium.orgc1789ee2013-07-05 07:09:57 +00004435 constraints.set_max_old_space_size(5 * K * K);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004436 v8::Isolate* isolate = CcTest::isolate();
4437 v8::SetResourceConstraints(isolate, &constraints);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004438
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004439 v8::HandleScope scope(isolate);
4440 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004441 templ->Set(v8_str("ProvokeOutOfMemory"),
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004442 v8::FunctionTemplate::New(isolate, ProvokeOutOfMemory));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004443 LocalContext context(0, templ);
4444 v8::V8::IgnoreOutOfMemoryException();
4445 Local<Value> result = CompileRun(
4446 "var thrown = false;"
4447 "try {"
4448 " ProvokeOutOfMemory();"
4449 "} catch (e) {"
4450 " thrown = true;"
4451 "}");
4452 // Check for out of memory state.
4453 CHECK(result.IsEmpty());
4454 CHECK(context->HasOutOfMemoryException());
4455}
4456
4457
yangguo@chromium.org49546742013-12-23 16:17:49 +00004458void OOMCallback(const char* location, const char* message) {
4459 exit(0);
4460}
4461
4462
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004463TEST(HugeConsStringOutOfMemory) {
4464 // It's not possible to read a snapshot into a heap with different dimensions.
lrn@chromium.org32d961d2010-06-30 09:09:34 +00004465 if (i::Snapshot::IsEnabled()) return;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004466 // Set heap limits.
4467 static const int K = 1024;
4468 v8::ResourceConstraints constraints;
4469 constraints.set_max_young_space_size(256 * K);
machenbach@chromium.orgc1789ee2013-07-05 07:09:57 +00004470 constraints.set_max_old_space_size(4 * K * K);
machenbach@chromium.org7ff76072013-11-21 09:47:43 +00004471 v8::SetResourceConstraints(CcTest::isolate(), &constraints);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004472
4473 // Execute a script that causes out of memory.
yangguo@chromium.org49546742013-12-23 16:17:49 +00004474 v8::V8::SetFatalErrorHandler(OOMCallback);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004475
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00004476 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004477 v8::HandleScope scope(context->GetIsolate());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00004478
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004479 // Build huge string. This should fail with out of memory exception.
yangguo@chromium.org49546742013-12-23 16:17:49 +00004480 CompileRun(
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004481 "var str = Array.prototype.join.call({length: 513}, \"A\").toUpperCase();"
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00004482 "for (var i = 0; i < 22; i++) { str = str + str; }");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004483
yangguo@chromium.org49546742013-12-23 16:17:49 +00004484 CHECK(false); // Should not return.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004485}
4486
4487
4488THREADED_TEST(ConstructCall) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004489 LocalContext context;
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004490 v8::Isolate* isolate = context->GetIsolate();
4491 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004492 CompileRun(
4493 "function Foo() {"
4494 " var result = [];"
4495 " for (var i = 0; i < arguments.length; i++) {"
4496 " result.push(arguments[i]);"
4497 " }"
4498 " return result;"
4499 "}");
4500 Local<Function> Foo =
4501 Local<Function>::Cast(context->Global()->Get(v8_str("Foo")));
4502
4503 v8::Handle<Value>* args0 = NULL;
4504 Local<v8::Array> a0 = Local<v8::Array>::Cast(Foo->NewInstance(0, args0));
4505 CHECK_EQ(0, a0->Length());
4506
4507 v8::Handle<Value> args1[] = { v8_num(1.1) };
4508 Local<v8::Array> a1 = Local<v8::Array>::Cast(Foo->NewInstance(1, args1));
4509 CHECK_EQ(1, a1->Length());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004510 CHECK_EQ(1.1, a1->Get(v8::Integer::New(isolate, 0))->NumberValue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004511
4512 v8::Handle<Value> args2[] = { v8_num(2.2),
4513 v8_num(3.3) };
4514 Local<v8::Array> a2 = Local<v8::Array>::Cast(Foo->NewInstance(2, args2));
4515 CHECK_EQ(2, a2->Length());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004516 CHECK_EQ(2.2, a2->Get(v8::Integer::New(isolate, 0))->NumberValue());
4517 CHECK_EQ(3.3, a2->Get(v8::Integer::New(isolate, 1))->NumberValue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004518
4519 v8::Handle<Value> args3[] = { v8_num(4.4),
4520 v8_num(5.5),
4521 v8_num(6.6) };
4522 Local<v8::Array> a3 = Local<v8::Array>::Cast(Foo->NewInstance(3, args3));
4523 CHECK_EQ(3, a3->Length());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004524 CHECK_EQ(4.4, a3->Get(v8::Integer::New(isolate, 0))->NumberValue());
4525 CHECK_EQ(5.5, a3->Get(v8::Integer::New(isolate, 1))->NumberValue());
4526 CHECK_EQ(6.6, a3->Get(v8::Integer::New(isolate, 2))->NumberValue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004527
4528 v8::Handle<Value> args4[] = { v8_num(7.7),
4529 v8_num(8.8),
4530 v8_num(9.9),
4531 v8_num(10.11) };
4532 Local<v8::Array> a4 = Local<v8::Array>::Cast(Foo->NewInstance(4, args4));
4533 CHECK_EQ(4, a4->Length());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004534 CHECK_EQ(7.7, a4->Get(v8::Integer::New(isolate, 0))->NumberValue());
4535 CHECK_EQ(8.8, a4->Get(v8::Integer::New(isolate, 1))->NumberValue());
4536 CHECK_EQ(9.9, a4->Get(v8::Integer::New(isolate, 2))->NumberValue());
4537 CHECK_EQ(10.11, a4->Get(v8::Integer::New(isolate, 3))->NumberValue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004538}
4539
4540
4541static void CheckUncle(v8::TryCatch* try_catch) {
4542 CHECK(try_catch->HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00004543 String::Utf8Value str_value(try_catch->Exception());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004544 CHECK_EQ(*str_value, "uncle?");
4545 try_catch->Reset();
4546}
4547
4548
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004549THREADED_TEST(ConversionNumber) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004550 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004551 v8::HandleScope scope(env->GetIsolate());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004552 // Very large number.
4553 CompileRun("var obj = Math.pow(2,32) * 1237;");
4554 Local<Value> obj = env->Global()->Get(v8_str("obj"));
4555 CHECK_EQ(5312874545152.0, obj->ToNumber()->Value());
4556 CHECK_EQ(0, obj->ToInt32()->Value());
4557 CHECK(0u == obj->ToUint32()->Value()); // NOLINT - no CHECK_EQ for unsigned.
4558 // Large number.
4559 CompileRun("var obj = -1234567890123;");
4560 obj = env->Global()->Get(v8_str("obj"));
4561 CHECK_EQ(-1234567890123.0, obj->ToNumber()->Value());
4562 CHECK_EQ(-1912276171, obj->ToInt32()->Value());
4563 CHECK(2382691125u == obj->ToUint32()->Value()); // NOLINT
4564 // Small positive integer.
4565 CompileRun("var obj = 42;");
4566 obj = env->Global()->Get(v8_str("obj"));
4567 CHECK_EQ(42.0, obj->ToNumber()->Value());
4568 CHECK_EQ(42, obj->ToInt32()->Value());
4569 CHECK(42u == obj->ToUint32()->Value()); // NOLINT
4570 // Negative integer.
4571 CompileRun("var obj = -37;");
4572 obj = env->Global()->Get(v8_str("obj"));
4573 CHECK_EQ(-37.0, obj->ToNumber()->Value());
4574 CHECK_EQ(-37, obj->ToInt32()->Value());
4575 CHECK(4294967259u == obj->ToUint32()->Value()); // NOLINT
4576 // Positive non-int32 integer.
4577 CompileRun("var obj = 0x81234567;");
4578 obj = env->Global()->Get(v8_str("obj"));
4579 CHECK_EQ(2166572391.0, obj->ToNumber()->Value());
4580 CHECK_EQ(-2128394905, obj->ToInt32()->Value());
4581 CHECK(2166572391u == obj->ToUint32()->Value()); // NOLINT
4582 // Fraction.
4583 CompileRun("var obj = 42.3;");
4584 obj = env->Global()->Get(v8_str("obj"));
4585 CHECK_EQ(42.3, obj->ToNumber()->Value());
4586 CHECK_EQ(42, obj->ToInt32()->Value());
4587 CHECK(42u == obj->ToUint32()->Value()); // NOLINT
4588 // Large negative fraction.
4589 CompileRun("var obj = -5726623061.75;");
4590 obj = env->Global()->Get(v8_str("obj"));
4591 CHECK_EQ(-5726623061.75, obj->ToNumber()->Value());
4592 CHECK_EQ(-1431655765, obj->ToInt32()->Value());
4593 CHECK(2863311531u == obj->ToUint32()->Value()); // NOLINT
4594}
4595
4596
4597THREADED_TEST(isNumberType) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004598 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004599 v8::HandleScope scope(env->GetIsolate());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004600 // Very large number.
4601 CompileRun("var obj = Math.pow(2,32) * 1237;");
4602 Local<Value> obj = env->Global()->Get(v8_str("obj"));
4603 CHECK(!obj->IsInt32());
4604 CHECK(!obj->IsUint32());
4605 // Large negative number.
4606 CompileRun("var obj = -1234567890123;");
4607 obj = env->Global()->Get(v8_str("obj"));
4608 CHECK(!obj->IsInt32());
4609 CHECK(!obj->IsUint32());
4610 // Small positive integer.
4611 CompileRun("var obj = 42;");
4612 obj = env->Global()->Get(v8_str("obj"));
4613 CHECK(obj->IsInt32());
4614 CHECK(obj->IsUint32());
4615 // Negative integer.
4616 CompileRun("var obj = -37;");
4617 obj = env->Global()->Get(v8_str("obj"));
4618 CHECK(obj->IsInt32());
4619 CHECK(!obj->IsUint32());
4620 // Positive non-int32 integer.
4621 CompileRun("var obj = 0x81234567;");
4622 obj = env->Global()->Get(v8_str("obj"));
4623 CHECK(!obj->IsInt32());
4624 CHECK(obj->IsUint32());
4625 // Fraction.
4626 CompileRun("var obj = 42.3;");
4627 obj = env->Global()->Get(v8_str("obj"));
4628 CHECK(!obj->IsInt32());
4629 CHECK(!obj->IsUint32());
4630 // Large negative fraction.
4631 CompileRun("var obj = -5726623061.75;");
4632 obj = env->Global()->Get(v8_str("obj"));
4633 CHECK(!obj->IsInt32());
4634 CHECK(!obj->IsUint32());
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00004635 // Positive zero
4636 CompileRun("var obj = 0.0;");
4637 obj = env->Global()->Get(v8_str("obj"));
4638 CHECK(obj->IsInt32());
4639 CHECK(obj->IsUint32());
4640 // Positive zero
4641 CompileRun("var obj = -0.0;");
4642 obj = env->Global()->Get(v8_str("obj"));
4643 CHECK(!obj->IsInt32());
4644 CHECK(!obj->IsUint32());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004645}
4646
4647
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004648THREADED_TEST(ConversionException) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004649 LocalContext env;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00004650 v8::Isolate* isolate = env->GetIsolate();
4651 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004652 CompileRun(
4653 "function TestClass() { };"
4654 "TestClass.prototype.toString = function () { throw 'uncle?'; };"
4655 "var obj = new TestClass();");
4656 Local<Value> obj = env->Global()->Get(v8_str("obj"));
4657
4658 v8::TryCatch try_catch;
4659
4660 Local<Value> to_string_result = obj->ToString();
4661 CHECK(to_string_result.IsEmpty());
4662 CheckUncle(&try_catch);
4663
4664 Local<Value> to_number_result = obj->ToNumber();
4665 CHECK(to_number_result.IsEmpty());
4666 CheckUncle(&try_catch);
4667
4668 Local<Value> to_integer_result = obj->ToInteger();
4669 CHECK(to_integer_result.IsEmpty());
4670 CheckUncle(&try_catch);
4671
4672 Local<Value> to_uint32_result = obj->ToUint32();
4673 CHECK(to_uint32_result.IsEmpty());
4674 CheckUncle(&try_catch);
4675
4676 Local<Value> to_int32_result = obj->ToInt32();
4677 CHECK(to_int32_result.IsEmpty());
4678 CheckUncle(&try_catch);
4679
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00004680 Local<Value> to_object_result = v8::Undefined(isolate)->ToObject();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004681 CHECK(to_object_result.IsEmpty());
4682 CHECK(try_catch.HasCaught());
4683 try_catch.Reset();
4684
4685 int32_t int32_value = obj->Int32Value();
4686 CHECK_EQ(0, int32_value);
4687 CheckUncle(&try_catch);
4688
4689 uint32_t uint32_value = obj->Uint32Value();
4690 CHECK_EQ(0, uint32_value);
4691 CheckUncle(&try_catch);
4692
4693 double number_value = obj->NumberValue();
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00004694 CHECK_NE(0, std::isnan(number_value));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004695 CheckUncle(&try_catch);
4696
4697 int64_t integer_value = obj->IntegerValue();
4698 CHECK_EQ(0.0, static_cast<double>(integer_value));
4699 CheckUncle(&try_catch);
4700}
4701
4702
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00004703void ThrowFromC(const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004704 ApiTestFuzzer::Fuzz();
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00004705 args.GetIsolate()->ThrowException(v8_str("konto"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004706}
4707
4708
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00004709void CCatcher(const v8::FunctionCallbackInfo<v8::Value>& args) {
4710 if (args.Length() < 1) {
4711 args.GetReturnValue().Set(false);
4712 return;
4713 }
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004714 v8::HandleScope scope(args.GetIsolate());
ager@chromium.org8bb60582008-12-11 12:02:20 +00004715 v8::TryCatch try_catch;
ager@chromium.org71daaf62009-04-01 07:22:49 +00004716 Local<Value> result = v8::Script::Compile(args[0]->ToString())->Run();
4717 CHECK(!try_catch.HasCaught() || result.IsEmpty());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00004718 args.GetReturnValue().Set(try_catch.HasCaught());
ager@chromium.org8bb60582008-12-11 12:02:20 +00004719}
4720
4721
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004722THREADED_TEST(APICatch) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004723 v8::Isolate* isolate = CcTest::isolate();
4724 v8::HandleScope scope(isolate);
4725 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004726 templ->Set(v8_str("ThrowFromC"),
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004727 v8::FunctionTemplate::New(isolate, ThrowFromC));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004728 LocalContext context(0, templ);
4729 CompileRun(
4730 "var thrown = false;"
4731 "try {"
4732 " ThrowFromC();"
4733 "} catch (e) {"
4734 " thrown = true;"
4735 "}");
4736 Local<Value> thrown = context->Global()->Get(v8_str("thrown"));
4737 CHECK(thrown->BooleanValue());
4738}
4739
4740
ager@chromium.org8bb60582008-12-11 12:02:20 +00004741THREADED_TEST(APIThrowTryCatch) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004742 v8::Isolate* isolate = CcTest::isolate();
4743 v8::HandleScope scope(isolate);
4744 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org8bb60582008-12-11 12:02:20 +00004745 templ->Set(v8_str("ThrowFromC"),
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004746 v8::FunctionTemplate::New(isolate, ThrowFromC));
ager@chromium.org8bb60582008-12-11 12:02:20 +00004747 LocalContext context(0, templ);
4748 v8::TryCatch try_catch;
4749 CompileRun("ThrowFromC();");
4750 CHECK(try_catch.HasCaught());
4751}
4752
4753
4754// Test that a try-finally block doesn't shadow a try-catch block
4755// when setting up an external handler.
ager@chromium.org71daaf62009-04-01 07:22:49 +00004756//
4757// BUG(271): Some of the exception propagation does not work on the
4758// ARM simulator because the simulator separates the C++ stack and the
4759// JS stack. This test therefore fails on the simulator. The test is
4760// not threaded to allow the threading tests to run on the simulator.
4761TEST(TryCatchInTryFinally) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004762 v8::Isolate* isolate = CcTest::isolate();
4763 v8::HandleScope scope(isolate);
4764 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org8bb60582008-12-11 12:02:20 +00004765 templ->Set(v8_str("CCatcher"),
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004766 v8::FunctionTemplate::New(isolate, CCatcher));
ager@chromium.org8bb60582008-12-11 12:02:20 +00004767 LocalContext context(0, templ);
4768 Local<Value> result = CompileRun("try {"
4769 " try {"
4770 " CCatcher('throw 7;');"
4771 " } finally {"
4772 " }"
4773 "} catch (e) {"
4774 "}");
4775 CHECK(result->IsTrue());
4776}
4777
4778
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00004779static void check_reference_error_message(
4780 v8::Handle<v8::Message> message,
4781 v8::Handle<v8::Value> data) {
4782 const char* reference_error = "Uncaught ReferenceError: asdf is not defined";
4783 CHECK(message->Get()->Equals(v8_str(reference_error)));
4784}
4785
4786
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00004787static void Fail(const v8::FunctionCallbackInfo<v8::Value>& args) {
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00004788 ApiTestFuzzer::Fuzz();
4789 CHECK(false);
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00004790}
4791
4792
4793// Test that overwritten methods are not invoked on uncaught exception
4794// formatting. However, they are invoked when performing normal error
4795// string conversions.
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00004796TEST(APIThrowMessageOverwrittenToString) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00004797 v8::Isolate* isolate = CcTest::isolate();
4798 v8::HandleScope scope(isolate);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00004799 v8::V8::AddMessageListener(check_reference_error_message);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004800 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00004801 templ->Set(v8_str("fail"), v8::FunctionTemplate::New(isolate, Fail));
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00004802 LocalContext context(NULL, templ);
4803 CompileRun("asdf;");
4804 CompileRun("var limit = {};"
4805 "limit.valueOf = fail;"
4806 "Error.stackTraceLimit = limit;");
4807 CompileRun("asdf");
4808 CompileRun("Array.prototype.pop = fail;");
4809 CompileRun("Object.prototype.hasOwnProperty = fail;");
4810 CompileRun("Object.prototype.toString = function f() { return 'Yikes'; }");
whesse@chromium.org7a392b32011-01-31 11:30:36 +00004811 CompileRun("Number.prototype.toString = function f() { return 'Yikes'; }");
4812 CompileRun("String.prototype.toString = function f() { return 'Yikes'; }");
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00004813 CompileRun("ReferenceError.prototype.toString ="
4814 " function() { return 'Whoops' }");
4815 CompileRun("asdf;");
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00004816 CompileRun("ReferenceError.prototype.constructor.name = void 0;");
4817 CompileRun("asdf;");
4818 CompileRun("ReferenceError.prototype.constructor = void 0;");
4819 CompileRun("asdf;");
ager@chromium.org0ee099b2011-01-25 14:06:47 +00004820 CompileRun("ReferenceError.prototype.__proto__ = new Object();");
4821 CompileRun("asdf;");
4822 CompileRun("ReferenceError.prototype = new Object();");
4823 CompileRun("asdf;");
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00004824 v8::Handle<Value> string = CompileRun("try { asdf; } catch(e) { e + ''; }");
4825 CHECK(string->Equals(v8_str("Whoops")));
ager@chromium.org378b34e2011-01-28 08:04:38 +00004826 CompileRun("ReferenceError.prototype.constructor = new Object();"
4827 "ReferenceError.prototype.constructor.name = 1;"
4828 "Number.prototype.toString = function() { return 'Whoops'; };"
4829 "ReferenceError.prototype.toString = Object.prototype.toString;");
4830 CompileRun("asdf;");
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00004831 v8::V8::RemoveMessageListeners(check_reference_error_message);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00004832}
4833
4834
danno@chromium.org59400602013-08-13 17:09:37 +00004835static void check_custom_error_tostring(
yangguo@chromium.org304cc332012-07-24 07:59:48 +00004836 v8::Handle<v8::Message> message,
4837 v8::Handle<v8::Value> data) {
4838 const char* uncaught_error = "Uncaught MyError toString";
4839 CHECK(message->Get()->Equals(v8_str(uncaught_error)));
4840}
4841
4842
4843TEST(CustomErrorToString) {
yangguo@chromium.org304cc332012-07-24 07:59:48 +00004844 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004845 v8::HandleScope scope(context->GetIsolate());
danno@chromium.org59400602013-08-13 17:09:37 +00004846 v8::V8::AddMessageListener(check_custom_error_tostring);
yangguo@chromium.org304cc332012-07-24 07:59:48 +00004847 CompileRun(
4848 "function MyError(name, message) { "
4849 " this.name = name; "
4850 " this.message = message; "
4851 "} "
4852 "MyError.prototype = Object.create(Error.prototype); "
4853 "MyError.prototype.toString = function() { "
4854 " return 'MyError toString'; "
4855 "}; "
4856 "throw new MyError('my name', 'my message'); ");
danno@chromium.org59400602013-08-13 17:09:37 +00004857 v8::V8::RemoveMessageListeners(check_custom_error_tostring);
4858}
4859
4860
4861static void check_custom_error_message(
4862 v8::Handle<v8::Message> message,
4863 v8::Handle<v8::Value> data) {
4864 const char* uncaught_error = "Uncaught MyError: my message";
4865 printf("%s\n", *v8::String::Utf8Value(message->Get()));
4866 CHECK(message->Get()->Equals(v8_str(uncaught_error)));
4867}
4868
4869
4870TEST(CustomErrorMessage) {
4871 LocalContext context;
4872 v8::HandleScope scope(context->GetIsolate());
4873 v8::V8::AddMessageListener(check_custom_error_message);
4874
4875 // Handlebars.
4876 CompileRun(
4877 "function MyError(msg) { "
4878 " this.name = 'MyError'; "
4879 " this.message = msg; "
4880 "} "
4881 "MyError.prototype = new Error(); "
4882 "throw new MyError('my message'); ");
4883
4884 // Closure.
4885 CompileRun(
4886 "function MyError(msg) { "
4887 " this.name = 'MyError'; "
4888 " this.message = msg; "
4889 "} "
4890 "inherits = function(childCtor, parentCtor) { "
4891 " function tempCtor() {}; "
4892 " tempCtor.prototype = parentCtor.prototype; "
4893 " childCtor.superClass_ = parentCtor.prototype; "
4894 " childCtor.prototype = new tempCtor(); "
4895 " childCtor.prototype.constructor = childCtor; "
4896 "}; "
4897 "inherits(MyError, Error); "
4898 "throw new MyError('my message'); ");
4899
4900 // Object.create.
4901 CompileRun(
4902 "function MyError(msg) { "
4903 " this.name = 'MyError'; "
4904 " this.message = msg; "
4905 "} "
4906 "MyError.prototype = Object.create(Error.prototype); "
4907 "throw new MyError('my message'); ");
4908
yangguo@chromium.org304cc332012-07-24 07:59:48 +00004909 v8::V8::RemoveMessageListeners(check_custom_error_message);
4910}
4911
4912
ager@chromium.org8bb60582008-12-11 12:02:20 +00004913static void receive_message(v8::Handle<v8::Message> message,
4914 v8::Handle<v8::Value> data) {
ager@chromium.org71daaf62009-04-01 07:22:49 +00004915 message->Get();
ager@chromium.org8bb60582008-12-11 12:02:20 +00004916 message_received = true;
4917}
4918
4919
4920TEST(APIThrowMessage) {
4921 message_received = false;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004922 v8::Isolate* isolate = CcTest::isolate();
4923 v8::HandleScope scope(isolate);
ager@chromium.org8bb60582008-12-11 12:02:20 +00004924 v8::V8::AddMessageListener(receive_message);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004925 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org8bb60582008-12-11 12:02:20 +00004926 templ->Set(v8_str("ThrowFromC"),
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004927 v8::FunctionTemplate::New(isolate, ThrowFromC));
ager@chromium.org8bb60582008-12-11 12:02:20 +00004928 LocalContext context(0, templ);
4929 CompileRun("ThrowFromC();");
4930 CHECK(message_received);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00004931 v8::V8::RemoveMessageListeners(receive_message);
ager@chromium.org8bb60582008-12-11 12:02:20 +00004932}
4933
4934
4935TEST(APIThrowMessageAndVerboseTryCatch) {
4936 message_received = false;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004937 v8::Isolate* isolate = CcTest::isolate();
4938 v8::HandleScope scope(isolate);
ager@chromium.org8bb60582008-12-11 12:02:20 +00004939 v8::V8::AddMessageListener(receive_message);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004940 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org8bb60582008-12-11 12:02:20 +00004941 templ->Set(v8_str("ThrowFromC"),
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004942 v8::FunctionTemplate::New(isolate, ThrowFromC));
ager@chromium.org8bb60582008-12-11 12:02:20 +00004943 LocalContext context(0, templ);
4944 v8::TryCatch try_catch;
4945 try_catch.SetVerbose(true);
ager@chromium.org71daaf62009-04-01 07:22:49 +00004946 Local<Value> result = CompileRun("ThrowFromC();");
ager@chromium.org8bb60582008-12-11 12:02:20 +00004947 CHECK(try_catch.HasCaught());
ager@chromium.org71daaf62009-04-01 07:22:49 +00004948 CHECK(result.IsEmpty());
ager@chromium.org8bb60582008-12-11 12:02:20 +00004949 CHECK(message_received);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00004950 v8::V8::RemoveMessageListeners(receive_message);
ager@chromium.org8bb60582008-12-11 12:02:20 +00004951}
4952
4953
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00004954TEST(APIStackOverflowAndVerboseTryCatch) {
4955 message_received = false;
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00004956 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004957 v8::HandleScope scope(context->GetIsolate());
4958 v8::V8::AddMessageListener(receive_message);
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00004959 v8::TryCatch try_catch;
4960 try_catch.SetVerbose(true);
4961 Local<Value> result = CompileRun("function foo() { foo(); } foo();");
4962 CHECK(try_catch.HasCaught());
4963 CHECK(result.IsEmpty());
4964 CHECK(message_received);
4965 v8::V8::RemoveMessageListeners(receive_message);
4966}
4967
4968
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004969THREADED_TEST(ExternalScriptException) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004970 v8::Isolate* isolate = CcTest::isolate();
4971 v8::HandleScope scope(isolate);
4972 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004973 templ->Set(v8_str("ThrowFromC"),
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004974 v8::FunctionTemplate::New(isolate, ThrowFromC));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004975 LocalContext context(0, templ);
4976
4977 v8::TryCatch try_catch;
4978 Local<Script> script
4979 = Script::Compile(v8_str("ThrowFromC(); throw 'panama';"));
4980 Local<Value> result = script->Run();
4981 CHECK(result.IsEmpty());
4982 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00004983 String::Utf8Value exception_value(try_catch.Exception());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004984 CHECK_EQ("konto", *exception_value);
4985}
4986
4987
4988
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00004989void CThrowCountDown(const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004990 ApiTestFuzzer::Fuzz();
4991 CHECK_EQ(4, args.Length());
4992 int count = args[0]->Int32Value();
4993 int cInterval = args[2]->Int32Value();
4994 if (count == 0) {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00004995 args.GetIsolate()->ThrowException(v8_str("FromC"));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00004996 return;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004997 } else {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00004998 Local<v8::Object> global =
4999 args.GetIsolate()->GetCurrentContext()->Global();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005000 Local<Value> fun = global->Get(v8_str("JSThrowCountDown"));
5001 v8::Handle<Value> argv[] = { v8_num(count - 1),
5002 args[1],
5003 args[2],
5004 args[3] };
5005 if (count % cInterval == 0) {
5006 v8::TryCatch try_catch;
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00005007 Local<Value> result = fun.As<Function>()->Call(global, 4, argv);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005008 int expected = args[3]->Int32Value();
5009 if (try_catch.HasCaught()) {
5010 CHECK_EQ(expected, count);
ager@chromium.org71daaf62009-04-01 07:22:49 +00005011 CHECK(result.IsEmpty());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00005012 CHECK(!CcTest::i_isolate()->has_scheduled_exception());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005013 } else {
5014 CHECK_NE(expected, count);
5015 }
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005016 args.GetReturnValue().Set(result);
5017 return;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005018 } else {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005019 args.GetReturnValue().Set(fun.As<Function>()->Call(global, 4, argv));
5020 return;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005021 }
5022 }
5023}
5024
5025
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005026void JSCheck(const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005027 ApiTestFuzzer::Fuzz();
5028 CHECK_EQ(3, args.Length());
5029 bool equality = args[0]->BooleanValue();
5030 int count = args[1]->Int32Value();
5031 int expected = args[2]->Int32Value();
5032 if (equality) {
5033 CHECK_EQ(count, expected);
5034 } else {
5035 CHECK_NE(count, expected);
5036 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005037}
5038
5039
ager@chromium.org8bb60582008-12-11 12:02:20 +00005040THREADED_TEST(EvalInTryFinally) {
ager@chromium.org8bb60582008-12-11 12:02:20 +00005041 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005042 v8::HandleScope scope(context->GetIsolate());
ager@chromium.org8bb60582008-12-11 12:02:20 +00005043 v8::TryCatch try_catch;
5044 CompileRun("(function() {"
5045 " try {"
5046 " eval('asldkf (*&^&*^');"
5047 " } finally {"
5048 " return;"
5049 " }"
5050 "})()");
5051 CHECK(!try_catch.HasCaught());
5052}
5053
5054
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005055// This test works by making a stack of alternating JavaScript and C
5056// activations. These activations set up exception handlers with regular
5057// intervals, one interval for C activations and another for JavaScript
5058// activations. When enough activations have been created an exception is
5059// thrown and we check that the right activation catches the exception and that
5060// no other activations do. The right activation is always the topmost one with
5061// a handler, regardless of whether it is in JavaScript or C.
5062//
5063// The notation used to describe a test case looks like this:
5064//
5065// *JS[4] *C[3] @JS[2] C[1] JS[0]
5066//
5067// Each entry is an activation, either JS or C. The index is the count at that
5068// level. Stars identify activations with exception handlers, the @ identifies
5069// the exception handler that should catch the exception.
ager@chromium.org71daaf62009-04-01 07:22:49 +00005070//
5071// BUG(271): Some of the exception propagation does not work on the
5072// ARM simulator because the simulator separates the C++ stack and the
5073// JS stack. This test therefore fails on the simulator. The test is
5074// not threaded to allow the threading tests to run on the simulator.
5075TEST(ExceptionOrder) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00005076 v8::Isolate* isolate = CcTest::isolate();
5077 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005078 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00005079 templ->Set(v8_str("check"), v8::FunctionTemplate::New(isolate, JSCheck));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005080 templ->Set(v8_str("CThrowCountDown"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00005081 v8::FunctionTemplate::New(isolate, CThrowCountDown));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005082 LocalContext context(0, templ);
5083 CompileRun(
5084 "function JSThrowCountDown(count, jsInterval, cInterval, expected) {"
5085 " if (count == 0) throw 'FromJS';"
5086 " if (count % jsInterval == 0) {"
5087 " try {"
5088 " var value = CThrowCountDown(count - 1,"
5089 " jsInterval,"
5090 " cInterval,"
5091 " expected);"
5092 " check(false, count, expected);"
5093 " return value;"
5094 " } catch (e) {"
5095 " check(true, count, expected);"
5096 " }"
5097 " } else {"
5098 " return CThrowCountDown(count - 1, jsInterval, cInterval, expected);"
5099 " }"
5100 "}");
5101 Local<Function> fun =
5102 Local<Function>::Cast(context->Global()->Get(v8_str("JSThrowCountDown")));
5103
5104 const int argc = 4;
5105 // count jsInterval cInterval expected
5106
5107 // *JS[4] *C[3] @JS[2] C[1] JS[0]
5108 v8::Handle<Value> a0[argc] = { v8_num(4), v8_num(2), v8_num(3), v8_num(2) };
5109 fun->Call(fun, argc, a0);
5110
5111 // JS[5] *C[4] JS[3] @C[2] JS[1] C[0]
5112 v8::Handle<Value> a1[argc] = { v8_num(5), v8_num(6), v8_num(1), v8_num(2) };
5113 fun->Call(fun, argc, a1);
5114
5115 // JS[6] @C[5] JS[4] C[3] JS[2] C[1] JS[0]
5116 v8::Handle<Value> a2[argc] = { v8_num(6), v8_num(7), v8_num(5), v8_num(5) };
5117 fun->Call(fun, argc, a2);
5118
5119 // @JS[6] C[5] JS[4] C[3] JS[2] C[1] JS[0]
5120 v8::Handle<Value> a3[argc] = { v8_num(6), v8_num(6), v8_num(7), v8_num(6) };
5121 fun->Call(fun, argc, a3);
5122
5123 // JS[6] *C[5] @JS[4] C[3] JS[2] C[1] JS[0]
5124 v8::Handle<Value> a4[argc] = { v8_num(6), v8_num(4), v8_num(5), v8_num(4) };
5125 fun->Call(fun, argc, a4);
5126
5127 // JS[6] C[5] *JS[4] @C[3] JS[2] C[1] JS[0]
5128 v8::Handle<Value> a5[argc] = { v8_num(6), v8_num(4), v8_num(3), v8_num(3) };
5129 fun->Call(fun, argc, a5);
5130}
5131
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00005132
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005133void ThrowValue(const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005134 ApiTestFuzzer::Fuzz();
5135 CHECK_EQ(1, args.Length());
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00005136 args.GetIsolate()->ThrowException(args[0]);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005137}
5138
5139
5140THREADED_TEST(ThrowValues) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00005141 v8::Isolate* isolate = CcTest::isolate();
5142 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005143 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00005144 templ->Set(v8_str("Throw"), v8::FunctionTemplate::New(isolate, ThrowValue));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005145 LocalContext context(0, templ);
5146 v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
5147 "function Run(obj) {"
5148 " try {"
5149 " Throw(obj);"
5150 " } catch (e) {"
5151 " return e;"
5152 " }"
5153 " return 'no exception';"
5154 "}"
5155 "[Run('str'), Run(1), Run(0), Run(null), Run(void 0)];"));
5156 CHECK_EQ(5, result->Length());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00005157 CHECK(result->Get(v8::Integer::New(isolate, 0))->IsString());
5158 CHECK(result->Get(v8::Integer::New(isolate, 1))->IsNumber());
5159 CHECK_EQ(1, result->Get(v8::Integer::New(isolate, 1))->Int32Value());
5160 CHECK(result->Get(v8::Integer::New(isolate, 2))->IsNumber());
5161 CHECK_EQ(0, result->Get(v8::Integer::New(isolate, 2))->Int32Value());
5162 CHECK(result->Get(v8::Integer::New(isolate, 3))->IsNull());
5163 CHECK(result->Get(v8::Integer::New(isolate, 4))->IsUndefined());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005164}
5165
5166
5167THREADED_TEST(CatchZero) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005168 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005169 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005170 v8::TryCatch try_catch;
5171 CHECK(!try_catch.HasCaught());
5172 Script::Compile(v8_str("throw 10"))->Run();
5173 CHECK(try_catch.HasCaught());
5174 CHECK_EQ(10, try_catch.Exception()->Int32Value());
5175 try_catch.Reset();
5176 CHECK(!try_catch.HasCaught());
5177 Script::Compile(v8_str("throw 0"))->Run();
5178 CHECK(try_catch.HasCaught());
5179 CHECK_EQ(0, try_catch.Exception()->Int32Value());
5180}
5181
5182
5183THREADED_TEST(CatchExceptionFromWith) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005184 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005185 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005186 v8::TryCatch try_catch;
5187 CHECK(!try_catch.HasCaught());
5188 Script::Compile(v8_str("var o = {}; with (o) { throw 42; }"))->Run();
5189 CHECK(try_catch.HasCaught());
5190}
5191
5192
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00005193THREADED_TEST(TryCatchAndFinallyHidingException) {
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00005194 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005195 v8::HandleScope scope(context->GetIsolate());
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00005196 v8::TryCatch try_catch;
5197 CHECK(!try_catch.HasCaught());
5198 CompileRun("function f(k) { try { this[k]; } finally { return 0; } };");
5199 CompileRun("f({toString: function() { throw 42; }});");
5200 CHECK(!try_catch.HasCaught());
5201}
5202
5203
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005204void WithTryCatch(const v8::FunctionCallbackInfo<v8::Value>& args) {
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00005205 v8::TryCatch try_catch;
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00005206}
5207
5208
5209THREADED_TEST(TryCatchAndFinally) {
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00005210 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00005211 v8::Isolate* isolate = context->GetIsolate();
5212 v8::HandleScope scope(isolate);
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00005213 context->Global()->Set(
5214 v8_str("native_with_try_catch"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00005215 v8::FunctionTemplate::New(isolate, WithTryCatch)->GetFunction());
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00005216 v8::TryCatch try_catch;
5217 CHECK(!try_catch.HasCaught());
5218 CompileRun(
5219 "try {\n"
5220 " throw new Error('a');\n"
5221 "} finally {\n"
5222 " native_with_try_catch();\n"
5223 "}\n");
5224 CHECK(try_catch.HasCaught());
5225}
5226
5227
mmassi@chromium.org49a44672012-12-04 13:52:03 +00005228static void TryCatchNestedHelper(int depth) {
5229 if (depth > 0) {
5230 v8::TryCatch try_catch;
5231 try_catch.SetVerbose(true);
5232 TryCatchNestedHelper(depth - 1);
5233 CHECK(try_catch.HasCaught());
5234 try_catch.ReThrow();
5235 } else {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00005236 CcTest::isolate()->ThrowException(v8_str("back"));
mmassi@chromium.org49a44672012-12-04 13:52:03 +00005237 }
5238}
5239
5240
5241TEST(TryCatchNested) {
5242 v8::V8::Initialize();
mmassi@chromium.org49a44672012-12-04 13:52:03 +00005243 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005244 v8::HandleScope scope(context->GetIsolate());
mmassi@chromium.org49a44672012-12-04 13:52:03 +00005245 v8::TryCatch try_catch;
5246 TryCatchNestedHelper(5);
5247 CHECK(try_catch.HasCaught());
5248 CHECK_EQ(0, strcmp(*v8::String::Utf8Value(try_catch.Exception()), "back"));
5249}
5250
5251
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +00005252void TryCatchMixedNestingCheck(v8::TryCatch* try_catch) {
5253 CHECK(try_catch->HasCaught());
5254 Handle<Message> message = try_catch->Message();
5255 Handle<Value> resource = message->GetScriptResourceName();
5256 CHECK_EQ(0, strcmp(*v8::String::Utf8Value(resource), "inner"));
5257 CHECK_EQ(0, strcmp(*v8::String::Utf8Value(message->Get()),
5258 "Uncaught Error: a"));
5259 CHECK_EQ(1, message->GetLineNumber());
5260 CHECK_EQ(6, message->GetStartColumn());
5261}
5262
5263
5264void TryCatchMixedNestingHelper(
5265 const v8::FunctionCallbackInfo<v8::Value>& args) {
5266 ApiTestFuzzer::Fuzz();
5267 v8::TryCatch try_catch;
5268 CompileRunWithOrigin("throw new Error('a');\n", "inner", 0, 0);
5269 CHECK(try_catch.HasCaught());
5270 TryCatchMixedNestingCheck(&try_catch);
5271 try_catch.ReThrow();
5272}
5273
5274
5275// This test ensures that an outer TryCatch in the following situation:
5276// C++/TryCatch -> JS -> C++/TryCatch -> JS w/ SyntaxError
5277// does not clobber the Message object generated for the inner TryCatch.
5278// This exercises the ability of TryCatch.ReThrow() to restore the
5279// inner pending Message before throwing the exception again.
5280TEST(TryCatchMixedNesting) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00005281 v8::Isolate* isolate = CcTest::isolate();
5282 v8::HandleScope scope(isolate);
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +00005283 v8::V8::Initialize();
5284 v8::TryCatch try_catch;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005285 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +00005286 templ->Set(v8_str("TryCatchMixedNestingHelper"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00005287 v8::FunctionTemplate::New(isolate, TryCatchMixedNestingHelper));
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +00005288 LocalContext context(0, templ);
5289 CompileRunWithOrigin("TryCatchMixedNestingHelper();\n", "outer", 1, 1);
5290 TryCatchMixedNestingCheck(&try_catch);
5291}
5292
5293
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005294THREADED_TEST(Equality) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005295 LocalContext context;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00005296 v8::Isolate* isolate = context->GetIsolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005297 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005298 // Check that equality works at all before relying on CHECK_EQ
5299 CHECK(v8_str("a")->Equals(v8_str("a")));
5300 CHECK(!v8_str("a")->Equals(v8_str("b")));
5301
5302 CHECK_EQ(v8_str("a"), v8_str("a"));
5303 CHECK_NE(v8_str("a"), v8_str("b"));
5304 CHECK_EQ(v8_num(1), v8_num(1));
5305 CHECK_EQ(v8_num(1.00), v8_num(1));
5306 CHECK_NE(v8_num(1), v8_num(2));
5307
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00005308 // Assume String is not internalized.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005309 CHECK(v8_str("a")->StrictEquals(v8_str("a")));
5310 CHECK(!v8_str("a")->StrictEquals(v8_str("b")));
5311 CHECK(!v8_str("5")->StrictEquals(v8_num(5)));
5312 CHECK(v8_num(1)->StrictEquals(v8_num(1)));
5313 CHECK(!v8_num(1)->StrictEquals(v8_num(2)));
machenbach@chromium.org3d079fe2013-09-25 08:19:55 +00005314 CHECK(v8_num(0.0)->StrictEquals(v8_num(-0.0)));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005315 Local<Value> not_a_number = v8_num(i::OS::nan_value());
5316 CHECK(!not_a_number->StrictEquals(not_a_number));
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00005317 CHECK(v8::False(isolate)->StrictEquals(v8::False(isolate)));
5318 CHECK(!v8::False(isolate)->StrictEquals(v8::Undefined(isolate)));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005319
ulan@chromium.org0f13e742014-01-03 15:51:11 +00005320 v8::Handle<v8::Object> obj = v8::Object::New(isolate);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00005321 v8::Persistent<v8::Object> alias(isolate, obj);
rossberg@chromium.org79e79022013-06-03 15:43:46 +00005322 CHECK(v8::Local<v8::Object>::New(isolate, alias)->StrictEquals(obj));
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00005323 alias.Reset();
machenbach@chromium.org3d079fe2013-09-25 08:19:55 +00005324
5325 CHECK(v8_str("a")->SameValue(v8_str("a")));
5326 CHECK(!v8_str("a")->SameValue(v8_str("b")));
5327 CHECK(!v8_str("5")->SameValue(v8_num(5)));
5328 CHECK(v8_num(1)->SameValue(v8_num(1)));
5329 CHECK(!v8_num(1)->SameValue(v8_num(2)));
5330 CHECK(!v8_num(0.0)->SameValue(v8_num(-0.0)));
5331 CHECK(not_a_number->SameValue(not_a_number));
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00005332 CHECK(v8::False(isolate)->SameValue(v8::False(isolate)));
5333 CHECK(!v8::False(isolate)->SameValue(v8::Undefined(isolate)));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005334}
5335
5336
5337THREADED_TEST(MultiRun) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005338 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005339 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005340 Local<Script> script = Script::Compile(v8_str("x"));
5341 for (int i = 0; i < 10; i++)
5342 script->Run();
5343}
5344
5345
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005346static void GetXValue(Local<String> name,
5347 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005348 ApiTestFuzzer::Fuzz();
5349 CHECK_EQ(info.Data(), v8_str("donut"));
5350 CHECK_EQ(name, v8_str("x"));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005351 info.GetReturnValue().Set(name);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005352}
5353
5354
5355THREADED_TEST(SimplePropertyRead) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005356 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005357 v8::Isolate* isolate = context->GetIsolate();
5358 v8::HandleScope scope(isolate);
5359 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005360 templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005361 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5362 Local<Script> script = Script::Compile(v8_str("obj.x"));
5363 for (int i = 0; i < 10; i++) {
5364 Local<Value> result = script->Run();
5365 CHECK_EQ(result, v8_str("x"));
5366 }
5367}
5368
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00005369
ager@chromium.org5c838252010-02-19 08:53:10 +00005370THREADED_TEST(DefinePropertyOnAPIAccessor) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005371 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005372 v8::Isolate* isolate = context->GetIsolate();
5373 v8::HandleScope scope(isolate);
5374 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +00005375 templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
ager@chromium.org5c838252010-02-19 08:53:10 +00005376 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5377
5378 // Uses getOwnPropertyDescriptor to check the configurable status
5379 Local<Script> script_desc
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00005380 = Script::Compile(v8_str("var prop = Object.getOwnPropertyDescriptor( "
ager@chromium.org5c838252010-02-19 08:53:10 +00005381 "obj, 'x');"
5382 "prop.configurable;"));
5383 Local<Value> result = script_desc->Run();
5384 CHECK_EQ(result->BooleanValue(), true);
5385
5386 // Redefine get - but still configurable
5387 Local<Script> script_define
5388 = Script::Compile(v8_str("var desc = { get: function(){return 42; },"
5389 " configurable: true };"
5390 "Object.defineProperty(obj, 'x', desc);"
5391 "obj.x"));
5392 result = script_define->Run();
5393 CHECK_EQ(result, v8_num(42));
5394
5395 // Check that the accessor is still configurable
5396 result = script_desc->Run();
5397 CHECK_EQ(result->BooleanValue(), true);
5398
5399 // Redefine to a non-configurable
5400 script_define
5401 = Script::Compile(v8_str("var desc = { get: function(){return 43; },"
5402 " configurable: false };"
5403 "Object.defineProperty(obj, 'x', desc);"
5404 "obj.x"));
5405 result = script_define->Run();
5406 CHECK_EQ(result, v8_num(43));
5407 result = script_desc->Run();
5408 CHECK_EQ(result->BooleanValue(), false);
5409
5410 // Make sure that it is not possible to redefine again
5411 v8::TryCatch try_catch;
5412 result = script_define->Run();
5413 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00005414 String::Utf8Value exception_value(try_catch.Exception());
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00005415 CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
ager@chromium.org5c838252010-02-19 08:53:10 +00005416}
5417
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00005418
ager@chromium.org5c838252010-02-19 08:53:10 +00005419THREADED_TEST(DefinePropertyOnDefineGetterSetter) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005420 v8::Isolate* isolate = CcTest::isolate();
5421 v8::HandleScope scope(isolate);
5422 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +00005423 templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
5424 LocalContext context;
5425 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5426
5427 Local<Script> script_desc = Script::Compile(v8_str("var prop ="
5428 "Object.getOwnPropertyDescriptor( "
5429 "obj, 'x');"
5430 "prop.configurable;"));
5431 Local<Value> result = script_desc->Run();
5432 CHECK_EQ(result->BooleanValue(), true);
5433
5434 Local<Script> script_define =
5435 Script::Compile(v8_str("var desc = {get: function(){return 42; },"
5436 " configurable: true };"
5437 "Object.defineProperty(obj, 'x', desc);"
5438 "obj.x"));
5439 result = script_define->Run();
5440 CHECK_EQ(result, v8_num(42));
5441
5442
5443 result = script_desc->Run();
5444 CHECK_EQ(result->BooleanValue(), true);
5445
5446
5447 script_define =
5448 Script::Compile(v8_str("var desc = {get: function(){return 43; },"
5449 " configurable: false };"
5450 "Object.defineProperty(obj, 'x', desc);"
5451 "obj.x"));
5452 result = script_define->Run();
5453 CHECK_EQ(result, v8_num(43));
5454 result = script_desc->Run();
5455
5456 CHECK_EQ(result->BooleanValue(), false);
5457
5458 v8::TryCatch try_catch;
5459 result = script_define->Run();
5460 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00005461 String::Utf8Value exception_value(try_catch.Exception());
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00005462 CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
ager@chromium.org5c838252010-02-19 08:53:10 +00005463}
5464
5465
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00005466static v8::Handle<v8::Object> GetGlobalProperty(LocalContext* context,
5467 char const* name) {
5468 return v8::Handle<v8::Object>::Cast((*context)->Global()->Get(v8_str(name)));
5469}
ager@chromium.org5c838252010-02-19 08:53:10 +00005470
5471
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00005472THREADED_TEST(DefineAPIAccessorOnObject) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005473 v8::Isolate* isolate = CcTest::isolate();
5474 v8::HandleScope scope(isolate);
5475 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00005476 LocalContext context;
5477
5478 context->Global()->Set(v8_str("obj1"), templ->NewInstance());
5479 CompileRun("var obj2 = {};");
5480
5481 CHECK(CompileRun("obj1.x")->IsUndefined());
5482 CHECK(CompileRun("obj2.x")->IsUndefined());
5483
5484 CHECK(GetGlobalProperty(&context, "obj1")->
5485 SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5486
5487 ExpectString("obj1.x", "x");
5488 CHECK(CompileRun("obj2.x")->IsUndefined());
5489
5490 CHECK(GetGlobalProperty(&context, "obj2")->
5491 SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5492
5493 ExpectString("obj1.x", "x");
5494 ExpectString("obj2.x", "x");
5495
5496 ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5497 ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5498
5499 CompileRun("Object.defineProperty(obj1, 'x',"
5500 "{ get: function() { return 'y'; }, configurable: true })");
5501
5502 ExpectString("obj1.x", "y");
5503 ExpectString("obj2.x", "x");
5504
5505 CompileRun("Object.defineProperty(obj2, 'x',"
5506 "{ get: function() { return 'y'; }, configurable: true })");
5507
5508 ExpectString("obj1.x", "y");
5509 ExpectString("obj2.x", "y");
5510
5511 ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5512 ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5513
5514 CHECK(GetGlobalProperty(&context, "obj1")->
5515 SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5516 CHECK(GetGlobalProperty(&context, "obj2")->
5517 SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5518
5519 ExpectString("obj1.x", "x");
5520 ExpectString("obj2.x", "x");
5521
5522 ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5523 ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5524
5525 // Define getters/setters, but now make them not configurable.
5526 CompileRun("Object.defineProperty(obj1, 'x',"
5527 "{ get: function() { return 'z'; }, configurable: false })");
5528 CompileRun("Object.defineProperty(obj2, 'x',"
5529 "{ get: function() { return 'z'; }, configurable: false })");
5530
5531 ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5532 ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5533
5534 ExpectString("obj1.x", "z");
5535 ExpectString("obj2.x", "z");
5536
5537 CHECK(!GetGlobalProperty(&context, "obj1")->
5538 SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5539 CHECK(!GetGlobalProperty(&context, "obj2")->
5540 SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5541
5542 ExpectString("obj1.x", "z");
5543 ExpectString("obj2.x", "z");
5544}
5545
5546
5547THREADED_TEST(DontDeleteAPIAccessorsCannotBeOverriden) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005548 v8::Isolate* isolate = CcTest::isolate();
5549 v8::HandleScope scope(isolate);
5550 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00005551 LocalContext context;
5552
5553 context->Global()->Set(v8_str("obj1"), templ->NewInstance());
5554 CompileRun("var obj2 = {};");
5555
5556 CHECK(GetGlobalProperty(&context, "obj1")->SetAccessor(
5557 v8_str("x"),
5558 GetXValue, NULL,
5559 v8_str("donut"), v8::DEFAULT, v8::DontDelete));
5560 CHECK(GetGlobalProperty(&context, "obj2")->SetAccessor(
5561 v8_str("x"),
5562 GetXValue, NULL,
5563 v8_str("donut"), v8::DEFAULT, v8::DontDelete));
5564
5565 ExpectString("obj1.x", "x");
5566 ExpectString("obj2.x", "x");
5567
5568 ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5569 ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5570
5571 CHECK(!GetGlobalProperty(&context, "obj1")->
5572 SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5573 CHECK(!GetGlobalProperty(&context, "obj2")->
5574 SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5575
5576 {
5577 v8::TryCatch try_catch;
5578 CompileRun("Object.defineProperty(obj1, 'x',"
5579 "{get: function() { return 'func'; }})");
5580 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00005581 String::Utf8Value exception_value(try_catch.Exception());
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00005582 CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00005583 }
5584 {
5585 v8::TryCatch try_catch;
5586 CompileRun("Object.defineProperty(obj2, 'x',"
5587 "{get: function() { return 'func'; }})");
5588 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00005589 String::Utf8Value exception_value(try_catch.Exception());
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00005590 CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00005591 }
5592}
5593
5594
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005595static void Get239Value(Local<String> name,
5596 const v8::PropertyCallbackInfo<v8::Value>& info) {
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00005597 ApiTestFuzzer::Fuzz();
5598 CHECK_EQ(info.Data(), v8_str("donut"));
5599 CHECK_EQ(name, v8_str("239"));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005600 info.GetReturnValue().Set(name);
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00005601}
5602
5603
5604THREADED_TEST(ElementAPIAccessor) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005605 v8::Isolate* isolate = CcTest::isolate();
5606 v8::HandleScope scope(isolate);
5607 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00005608 LocalContext context;
5609
5610 context->Global()->Set(v8_str("obj1"), templ->NewInstance());
5611 CompileRun("var obj2 = {};");
5612
5613 CHECK(GetGlobalProperty(&context, "obj1")->SetAccessor(
5614 v8_str("239"),
5615 Get239Value, NULL,
5616 v8_str("donut")));
5617 CHECK(GetGlobalProperty(&context, "obj2")->SetAccessor(
5618 v8_str("239"),
5619 Get239Value, NULL,
5620 v8_str("donut")));
5621
5622 ExpectString("obj1[239]", "239");
5623 ExpectString("obj2[239]", "239");
5624 ExpectString("obj1['239']", "239");
5625 ExpectString("obj2['239']", "239");
5626}
5627
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005628
5629v8::Persistent<Value> xValue;
5630
5631
5632static void SetXValue(Local<String> name,
5633 Local<Value> value,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005634 const v8::PropertyCallbackInfo<void>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005635 CHECK_EQ(value, v8_num(4));
5636 CHECK_EQ(info.Data(), v8_str("donut"));
5637 CHECK_EQ(name, v8_str("x"));
5638 CHECK(xValue.IsEmpty());
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00005639 xValue.Reset(info.GetIsolate(), value);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005640}
5641
5642
5643THREADED_TEST(SimplePropertyWrite) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005644 v8::Isolate* isolate = CcTest::isolate();
5645 v8::HandleScope scope(isolate);
5646 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005647 templ->SetAccessor(v8_str("x"), GetXValue, SetXValue, v8_str("donut"));
5648 LocalContext context;
5649 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5650 Local<Script> script = Script::Compile(v8_str("obj.x = 4"));
5651 for (int i = 0; i < 10; i++) {
5652 CHECK(xValue.IsEmpty());
5653 script->Run();
machenbach@chromium.org528ce022013-09-23 14:09:36 +00005654 CHECK_EQ(v8_num(4), Local<Value>::New(CcTest::isolate(), xValue));
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00005655 xValue.Reset();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005656 }
5657}
5658
5659
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00005660THREADED_TEST(SetterOnly) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005661 v8::Isolate* isolate = CcTest::isolate();
5662 v8::HandleScope scope(isolate);
5663 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00005664 templ->SetAccessor(v8_str("x"), NULL, SetXValue, v8_str("donut"));
5665 LocalContext context;
5666 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5667 Local<Script> script = Script::Compile(v8_str("obj.x = 4; obj.x"));
5668 for (int i = 0; i < 10; i++) {
5669 CHECK(xValue.IsEmpty());
5670 script->Run();
machenbach@chromium.org528ce022013-09-23 14:09:36 +00005671 CHECK_EQ(v8_num(4), Local<Value>::New(CcTest::isolate(), xValue));
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00005672 xValue.Reset();
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00005673 }
5674}
5675
5676
5677THREADED_TEST(NoAccessors) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005678 v8::Isolate* isolate = CcTest::isolate();
5679 v8::HandleScope scope(isolate);
5680 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00005681 templ->SetAccessor(v8_str("x"),
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005682 static_cast<v8::AccessorGetterCallback>(NULL),
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00005683 NULL,
5684 v8_str("donut"));
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00005685 LocalContext context;
5686 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5687 Local<Script> script = Script::Compile(v8_str("obj.x = 4; obj.x"));
5688 for (int i = 0; i < 10; i++) {
5689 script->Run();
5690 }
5691}
5692
5693
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005694static void XPropertyGetter(Local<String> property,
5695 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005696 ApiTestFuzzer::Fuzz();
5697 CHECK(info.Data()->IsUndefined());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005698 info.GetReturnValue().Set(property);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005699}
5700
5701
ager@chromium.orgeadaf222009-06-16 09:43:10 +00005702THREADED_TEST(NamedInterceptorPropertyRead) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005703 v8::Isolate* isolate = CcTest::isolate();
5704 v8::HandleScope scope(isolate);
5705 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005706 templ->SetNamedPropertyHandler(XPropertyGetter);
5707 LocalContext context;
5708 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5709 Local<Script> script = Script::Compile(v8_str("obj.x"));
5710 for (int i = 0; i < 10; i++) {
5711 Local<Value> result = script->Run();
5712 CHECK_EQ(result, v8_str("x"));
5713 }
5714}
5715
ager@chromium.orgeadaf222009-06-16 09:43:10 +00005716
ager@chromium.orgb26c50a2010-03-26 09:27:16 +00005717THREADED_TEST(NamedInterceptorDictionaryIC) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005718 v8::Isolate* isolate = CcTest::isolate();
5719 v8::HandleScope scope(isolate);
5720 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.orgb26c50a2010-03-26 09:27:16 +00005721 templ->SetNamedPropertyHandler(XPropertyGetter);
5722 LocalContext context;
5723 // Create an object with a named interceptor.
5724 context->Global()->Set(v8_str("interceptor_obj"), templ->NewInstance());
5725 Local<Script> script = Script::Compile(v8_str("interceptor_obj.x"));
5726 for (int i = 0; i < 10; i++) {
5727 Local<Value> result = script->Run();
5728 CHECK_EQ(result, v8_str("x"));
5729 }
5730 // Create a slow case object and a function accessing a property in
5731 // that slow case object (with dictionary probing in generated
5732 // code). Then force object with a named interceptor into slow-case,
5733 // pass it to the function, and check that the interceptor is called
5734 // instead of accessing the local property.
5735 Local<Value> result =
5736 CompileRun("function get_x(o) { return o.x; };"
5737 "var obj = { x : 42, y : 0 };"
5738 "delete obj.y;"
5739 "for (var i = 0; i < 10; i++) get_x(obj);"
5740 "interceptor_obj.x = 42;"
5741 "interceptor_obj.y = 10;"
5742 "delete interceptor_obj.y;"
5743 "get_x(interceptor_obj)");
5744 CHECK_EQ(result, v8_str("x"));
5745}
5746
5747
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00005748THREADED_TEST(NamedInterceptorDictionaryICMultipleContext) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00005749 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00005750 v8::HandleScope scope(isolate);
5751 v8::Local<Context> context1 = Context::New(isolate);
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00005752
5753 context1->Enter();
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005754 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00005755 templ->SetNamedPropertyHandler(XPropertyGetter);
5756 // Create an object with a named interceptor.
5757 v8::Local<v8::Object> object = templ->NewInstance();
5758 context1->Global()->Set(v8_str("interceptor_obj"), object);
5759
5760 // Force the object into the slow case.
5761 CompileRun("interceptor_obj.y = 0;"
5762 "delete interceptor_obj.y;");
5763 context1->Exit();
5764
5765 {
5766 // Introduce the object into a different context.
5767 // Repeat named loads to exercise ICs.
5768 LocalContext context2;
5769 context2->Global()->Set(v8_str("interceptor_obj"), object);
5770 Local<Value> result =
5771 CompileRun("function get_x(o) { return o.x; }"
5772 "interceptor_obj.x = 42;"
5773 "for (var i=0; i != 10; i++) {"
5774 " get_x(interceptor_obj);"
5775 "}"
5776 "get_x(interceptor_obj)");
5777 // Check that the interceptor was actually invoked.
5778 CHECK_EQ(result, v8_str("x"));
5779 }
5780
5781 // Return to the original context and force some object to the slow case
5782 // to cause the NormalizedMapCache to verify.
5783 context1->Enter();
5784 CompileRun("var obj = { x : 0 }; delete obj.x;");
5785 context1->Exit();
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00005786}
5787
5788
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005789static void SetXOnPrototypeGetter(
5790 Local<String> property,
5791 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.org5c838252010-02-19 08:53:10 +00005792 // Set x on the prototype object and do not handle the get request.
5793 v8::Handle<v8::Value> proto = info.Holder()->GetPrototype();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00005794 proto.As<v8::Object>()->Set(v8_str("x"),
5795 v8::Integer::New(info.GetIsolate(), 23));
ager@chromium.org5c838252010-02-19 08:53:10 +00005796}
5797
5798
5799// This is a regression test for http://crbug.com/20104. Map
5800// transitions should not interfere with post interceptor lookup.
5801THREADED_TEST(NamedInterceptorMapTransitionRead) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00005802 v8::Isolate* isolate = CcTest::isolate();
5803 v8::HandleScope scope(isolate);
5804 Local<v8::FunctionTemplate> function_template =
5805 v8::FunctionTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +00005806 Local<v8::ObjectTemplate> instance_template
5807 = function_template->InstanceTemplate();
5808 instance_template->SetNamedPropertyHandler(SetXOnPrototypeGetter);
5809 LocalContext context;
5810 context->Global()->Set(v8_str("F"), function_template->GetFunction());
5811 // Create an instance of F and introduce a map transition for x.
5812 CompileRun("var o = new F(); o.x = 23;");
5813 // Create an instance of F and invoke the getter. The result should be 23.
5814 Local<Value> result = CompileRun("o = new F(); o.x");
5815 CHECK_EQ(result->Int32Value(), 23);
5816}
5817
5818
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005819static void IndexedPropertyGetter(
5820 uint32_t index,
5821 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.orgeadaf222009-06-16 09:43:10 +00005822 ApiTestFuzzer::Fuzz();
5823 if (index == 37) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005824 info.GetReturnValue().Set(v8_num(625));
ager@chromium.orgeadaf222009-06-16 09:43:10 +00005825 }
ager@chromium.orgeadaf222009-06-16 09:43:10 +00005826}
5827
5828
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005829static void IndexedPropertySetter(
5830 uint32_t index,
5831 Local<Value> value,
5832 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.orgeadaf222009-06-16 09:43:10 +00005833 ApiTestFuzzer::Fuzz();
5834 if (index == 39) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005835 info.GetReturnValue().Set(value);
ager@chromium.orgeadaf222009-06-16 09:43:10 +00005836 }
ager@chromium.orgeadaf222009-06-16 09:43:10 +00005837}
5838
5839
5840THREADED_TEST(IndexedInterceptorWithIndexedAccessor) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005841 v8::Isolate* isolate = CcTest::isolate();
5842 v8::HandleScope scope(isolate);
5843 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.orgeadaf222009-06-16 09:43:10 +00005844 templ->SetIndexedPropertyHandler(IndexedPropertyGetter,
5845 IndexedPropertySetter);
5846 LocalContext context;
5847 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5848 Local<Script> getter_script = Script::Compile(v8_str(
5849 "obj.__defineGetter__(\"3\", function(){return 5;});obj[3];"));
5850 Local<Script> setter_script = Script::Compile(v8_str(
5851 "obj.__defineSetter__(\"17\", function(val){this.foo = val;});"
5852 "obj[17] = 23;"
5853 "obj.foo;"));
5854 Local<Script> interceptor_setter_script = Script::Compile(v8_str(
5855 "obj.__defineSetter__(\"39\", function(val){this.foo = \"hit\";});"
5856 "obj[39] = 47;"
5857 "obj.foo;")); // This setter should not run, due to the interceptor.
5858 Local<Script> interceptor_getter_script = Script::Compile(v8_str(
5859 "obj[37];"));
5860 Local<Value> result = getter_script->Run();
5861 CHECK_EQ(v8_num(5), result);
5862 result = setter_script->Run();
5863 CHECK_EQ(v8_num(23), result);
5864 result = interceptor_setter_script->Run();
5865 CHECK_EQ(v8_num(23), result);
5866 result = interceptor_getter_script->Run();
5867 CHECK_EQ(v8_num(625), result);
5868}
5869
5870
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005871static void UnboxedDoubleIndexedPropertyGetter(
ricow@chromium.org9fa09672011-07-25 11:05:35 +00005872 uint32_t index,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005873 const v8::PropertyCallbackInfo<v8::Value>& info) {
ricow@chromium.org9fa09672011-07-25 11:05:35 +00005874 ApiTestFuzzer::Fuzz();
5875 if (index < 25) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005876 info.GetReturnValue().Set(v8_num(index));
ricow@chromium.org9fa09672011-07-25 11:05:35 +00005877 }
ricow@chromium.org9fa09672011-07-25 11:05:35 +00005878}
5879
5880
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005881static void UnboxedDoubleIndexedPropertySetter(
ricow@chromium.org9fa09672011-07-25 11:05:35 +00005882 uint32_t index,
5883 Local<Value> value,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005884 const v8::PropertyCallbackInfo<v8::Value>& info) {
ricow@chromium.org9fa09672011-07-25 11:05:35 +00005885 ApiTestFuzzer::Fuzz();
5886 if (index < 25) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005887 info.GetReturnValue().Set(v8_num(index));
ricow@chromium.org9fa09672011-07-25 11:05:35 +00005888 }
ricow@chromium.org9fa09672011-07-25 11:05:35 +00005889}
5890
5891
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005892void UnboxedDoubleIndexedPropertyEnumerator(
5893 const v8::PropertyCallbackInfo<v8::Array>& info) {
ricow@chromium.org9fa09672011-07-25 11:05:35 +00005894 // Force the list of returned keys to be stored in a FastDoubleArray.
5895 Local<Script> indexed_property_names_script = Script::Compile(v8_str(
5896 "keys = new Array(); keys[125000] = 1;"
5897 "for(i = 0; i < 80000; i++) { keys[i] = i; };"
5898 "keys.length = 25; keys;"));
5899 Local<Value> result = indexed_property_names_script->Run();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005900 info.GetReturnValue().Set(Local<v8::Array>::Cast(result));
ricow@chromium.org9fa09672011-07-25 11:05:35 +00005901}
5902
5903
5904// Make sure that the the interceptor code in the runtime properly handles
5905// merging property name lists for double-array-backed arrays.
5906THREADED_TEST(IndexedInterceptorUnboxedDoubleWithIndexedAccessor) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005907 v8::Isolate* isolate = CcTest::isolate();
5908 v8::HandleScope scope(isolate);
5909 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ricow@chromium.org9fa09672011-07-25 11:05:35 +00005910 templ->SetIndexedPropertyHandler(UnboxedDoubleIndexedPropertyGetter,
5911 UnboxedDoubleIndexedPropertySetter,
5912 0,
5913 0,
5914 UnboxedDoubleIndexedPropertyEnumerator);
5915 LocalContext context;
5916 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5917 // When obj is created, force it to be Stored in a FastDoubleArray.
5918 Local<Script> create_unboxed_double_script = Script::Compile(v8_str(
5919 "obj[125000] = 1; for(i = 0; i < 80000; i+=2) { obj[i] = i; } "
5920 "key_count = 0; "
5921 "for (x in obj) {key_count++;};"
5922 "obj;"));
5923 Local<Value> result = create_unboxed_double_script->Run();
5924 CHECK(result->ToObject()->HasRealIndexedProperty(2000));
5925 Local<Script> key_count_check = Script::Compile(v8_str(
5926 "key_count;"));
5927 result = key_count_check->Run();
5928 CHECK_EQ(v8_num(40013), result);
5929}
5930
5931
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005932void NonStrictArgsIndexedPropertyEnumerator(
5933 const v8::PropertyCallbackInfo<v8::Array>& info) {
rossberg@chromium.org28a37082011-08-22 11:03:23 +00005934 // Force the list of returned keys to be stored in a Arguments object.
5935 Local<Script> indexed_property_names_script = Script::Compile(v8_str(
5936 "function f(w,x) {"
5937 " return arguments;"
5938 "}"
5939 "keys = f(0, 1, 2, 3);"
5940 "keys;"));
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00005941 Local<Object> result =
5942 Local<Object>::Cast(indexed_property_names_script->Run());
5943 // Have to populate the handle manually, as it's not Cast-able.
5944 i::Handle<i::JSObject> o =
5945 v8::Utils::OpenHandle<Object, i::JSObject>(result);
5946 i::Handle<i::JSArray> array(reinterpret_cast<i::JSArray*>(*o));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005947 info.GetReturnValue().Set(v8::Utils::ToLocal(array));
rossberg@chromium.org28a37082011-08-22 11:03:23 +00005948}
5949
5950
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005951static void NonStrictIndexedPropertyGetter(
rossberg@chromium.org28a37082011-08-22 11:03:23 +00005952 uint32_t index,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005953 const v8::PropertyCallbackInfo<v8::Value>& info) {
rossberg@chromium.org28a37082011-08-22 11:03:23 +00005954 ApiTestFuzzer::Fuzz();
5955 if (index < 4) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005956 info.GetReturnValue().Set(v8_num(index));
rossberg@chromium.org28a37082011-08-22 11:03:23 +00005957 }
rossberg@chromium.org28a37082011-08-22 11:03:23 +00005958}
5959
5960
5961// Make sure that the the interceptor code in the runtime properly handles
5962// merging property name lists for non-string arguments arrays.
5963THREADED_TEST(IndexedInterceptorNonStrictArgsWithIndexedAccessor) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005964 v8::Isolate* isolate = CcTest::isolate();
5965 v8::HandleScope scope(isolate);
5966 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
rossberg@chromium.org28a37082011-08-22 11:03:23 +00005967 templ->SetIndexedPropertyHandler(NonStrictIndexedPropertyGetter,
5968 0,
5969 0,
5970 0,
5971 NonStrictArgsIndexedPropertyEnumerator);
5972 LocalContext context;
5973 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5974 Local<Script> create_args_script =
5975 Script::Compile(v8_str(
5976 "var key_count = 0;"
5977 "for (x in obj) {key_count++;} key_count;"));
5978 Local<Value> result = create_args_script->Run();
5979 CHECK_EQ(v8_num(4), result);
5980}
5981
5982
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005983static void IdentityIndexedPropertyGetter(
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +00005984 uint32_t index,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005985 const v8::PropertyCallbackInfo<v8::Value>& info) {
5986 info.GetReturnValue().Set(index);
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +00005987}
5988
5989
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00005990THREADED_TEST(IndexedInterceptorWithGetOwnPropertyDescriptor) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005991 v8::Isolate* isolate = CcTest::isolate();
5992 v8::HandleScope scope(isolate);
5993 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00005994 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
5995
5996 LocalContext context;
5997 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5998
5999 // Check fast object case.
6000 const char* fast_case_code =
6001 "Object.getOwnPropertyDescriptor(obj, 0).value.toString()";
6002 ExpectString(fast_case_code, "0");
6003
6004 // Check slow case.
6005 const char* slow_case_code =
6006 "obj.x = 1; delete obj.x;"
6007 "Object.getOwnPropertyDescriptor(obj, 1).value.toString()";
6008 ExpectString(slow_case_code, "1");
6009}
6010
6011
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +00006012THREADED_TEST(IndexedInterceptorWithNoSetter) {
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);
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +00006016 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
6017
6018 LocalContext context;
6019 context->Global()->Set(v8_str("obj"), templ->NewInstance());
6020
6021 const char* code =
6022 "try {"
6023 " obj[0] = 239;"
6024 " for (var i = 0; i < 100; i++) {"
6025 " var v = obj[0];"
6026 " if (v != 0) throw 'Wrong value ' + v + ' at iteration ' + i;"
6027 " }"
6028 " 'PASSED'"
6029 "} catch(e) {"
6030 " e"
6031 "}";
6032 ExpectString(code, "PASSED");
6033}
6034
6035
ager@chromium.org5c838252010-02-19 08:53:10 +00006036THREADED_TEST(IndexedInterceptorWithAccessorCheck) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00006037 v8::Isolate* isolate = CcTest::isolate();
6038 v8::HandleScope scope(isolate);
6039 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +00006040 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
6041
6042 LocalContext context;
6043 Local<v8::Object> obj = templ->NewInstance();
6044 obj->TurnOnAccessCheck();
6045 context->Global()->Set(v8_str("obj"), obj);
6046
6047 const char* code =
6048 "try {"
6049 " for (var i = 0; i < 100; i++) {"
6050 " var v = obj[0];"
6051 " if (v != undefined) throw 'Wrong value ' + v + ' at iteration ' + i;"
6052 " }"
6053 " 'PASSED'"
6054 "} catch(e) {"
6055 " e"
6056 "}";
6057 ExpectString(code, "PASSED");
6058}
6059
6060
6061THREADED_TEST(IndexedInterceptorWithAccessorCheckSwitchedOn) {
6062 i::FLAG_allow_natives_syntax = true;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00006063 v8::Isolate* isolate = CcTest::isolate();
6064 v8::HandleScope scope(isolate);
6065 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +00006066 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
6067
6068 LocalContext context;
6069 Local<v8::Object> obj = templ->NewInstance();
6070 context->Global()->Set(v8_str("obj"), obj);
6071
6072 const char* code =
6073 "try {"
6074 " for (var i = 0; i < 100; i++) {"
6075 " var expected = i;"
6076 " if (i == 5) {"
6077 " %EnableAccessChecks(obj);"
6078 " expected = undefined;"
6079 " }"
6080 " var v = obj[i];"
6081 " if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
6082 " if (i == 5) %DisableAccessChecks(obj);"
6083 " }"
6084 " 'PASSED'"
6085 "} catch(e) {"
6086 " e"
6087 "}";
6088 ExpectString(code, "PASSED");
6089}
6090
6091
6092THREADED_TEST(IndexedInterceptorWithDifferentIndices) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00006093 v8::Isolate* isolate = CcTest::isolate();
6094 v8::HandleScope scope(isolate);
6095 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +00006096 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
6097
6098 LocalContext context;
6099 Local<v8::Object> obj = templ->NewInstance();
6100 context->Global()->Set(v8_str("obj"), obj);
6101
6102 const char* code =
6103 "try {"
6104 " for (var i = 0; i < 100; i++) {"
6105 " var v = obj[i];"
6106 " if (v != i) throw 'Wrong value ' + v + ' at iteration ' + i;"
6107 " }"
6108 " 'PASSED'"
6109 "} catch(e) {"
6110 " e"
6111 "}";
6112 ExpectString(code, "PASSED");
6113}
6114
6115
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +00006116THREADED_TEST(IndexedInterceptorWithNegativeIndices) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00006117 v8::Isolate* isolate = CcTest::isolate();
6118 v8::HandleScope scope(isolate);
6119 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +00006120 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
6121
6122 LocalContext context;
6123 Local<v8::Object> obj = templ->NewInstance();
6124 context->Global()->Set(v8_str("obj"), obj);
6125
6126 const char* code =
6127 "try {"
6128 " for (var i = 0; i < 100; i++) {"
6129 " var expected = i;"
6130 " var key = i;"
6131 " if (i == 25) {"
6132 " key = -1;"
6133 " expected = undefined;"
6134 " }"
6135 " if (i == 50) {"
6136 " /* probe minimal Smi number on 32-bit platforms */"
6137 " key = -(1 << 30);"
6138 " expected = undefined;"
6139 " }"
6140 " if (i == 75) {"
6141 " /* probe minimal Smi number on 64-bit platforms */"
6142 " key = 1 << 31;"
6143 " expected = undefined;"
6144 " }"
6145 " var v = obj[key];"
6146 " if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
6147 " }"
6148 " 'PASSED'"
6149 "} catch(e) {"
6150 " e"
6151 "}";
6152 ExpectString(code, "PASSED");
6153}
6154
6155
ager@chromium.org5c838252010-02-19 08:53:10 +00006156THREADED_TEST(IndexedInterceptorWithNotSmiLookup) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00006157 v8::Isolate* isolate = CcTest::isolate();
6158 v8::HandleScope scope(isolate);
6159 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +00006160 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
6161
6162 LocalContext context;
6163 Local<v8::Object> obj = templ->NewInstance();
6164 context->Global()->Set(v8_str("obj"), obj);
6165
6166 const char* code =
6167 "try {"
6168 " for (var i = 0; i < 100; i++) {"
6169 " var expected = i;"
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +00006170 " var key = i;"
ager@chromium.org5c838252010-02-19 08:53:10 +00006171 " if (i == 50) {"
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +00006172 " key = 'foobar';"
ager@chromium.org5c838252010-02-19 08:53:10 +00006173 " expected = undefined;"
6174 " }"
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +00006175 " var v = obj[key];"
ager@chromium.org5c838252010-02-19 08:53:10 +00006176 " if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
6177 " }"
6178 " 'PASSED'"
6179 "} catch(e) {"
6180 " e"
6181 "}";
6182 ExpectString(code, "PASSED");
6183}
6184
6185
6186THREADED_TEST(IndexedInterceptorGoingMegamorphic) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00006187 v8::Isolate* isolate = CcTest::isolate();
6188 v8::HandleScope scope(isolate);
6189 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +00006190 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
6191
6192 LocalContext context;
6193 Local<v8::Object> obj = templ->NewInstance();
6194 context->Global()->Set(v8_str("obj"), obj);
6195
6196 const char* code =
6197 "var original = obj;"
6198 "try {"
6199 " for (var i = 0; i < 100; i++) {"
6200 " var expected = i;"
6201 " if (i == 50) {"
6202 " obj = {50: 'foobar'};"
6203 " expected = 'foobar';"
6204 " }"
6205 " var v = obj[i];"
6206 " if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
6207 " if (i == 50) obj = original;"
6208 " }"
6209 " 'PASSED'"
6210 "} catch(e) {"
6211 " e"
6212 "}";
6213 ExpectString(code, "PASSED");
6214}
6215
6216
6217THREADED_TEST(IndexedInterceptorReceiverTurningSmi) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00006218 v8::Isolate* isolate = CcTest::isolate();
6219 v8::HandleScope scope(isolate);
6220 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +00006221 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
6222
6223 LocalContext context;
6224 Local<v8::Object> obj = templ->NewInstance();
6225 context->Global()->Set(v8_str("obj"), obj);
6226
6227 const char* code =
6228 "var original = obj;"
6229 "try {"
6230 " for (var i = 0; i < 100; i++) {"
6231 " var expected = i;"
6232 " if (i == 5) {"
6233 " obj = 239;"
6234 " expected = undefined;"
6235 " }"
6236 " var v = obj[i];"
6237 " if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
6238 " if (i == 5) obj = original;"
6239 " }"
6240 " 'PASSED'"
6241 "} catch(e) {"
6242 " e"
6243 "}";
6244 ExpectString(code, "PASSED");
6245}
6246
6247
6248THREADED_TEST(IndexedInterceptorOnProto) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00006249 v8::Isolate* isolate = CcTest::isolate();
6250 v8::HandleScope scope(isolate);
6251 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +00006252 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
6253
6254 LocalContext context;
6255 Local<v8::Object> obj = templ->NewInstance();
6256 context->Global()->Set(v8_str("obj"), obj);
6257
6258 const char* code =
6259 "var o = {__proto__: obj};"
6260 "try {"
6261 " for (var i = 0; i < 100; i++) {"
6262 " var v = o[i];"
6263 " if (v != i) throw 'Wrong value ' + v + ' at iteration ' + i;"
6264 " }"
6265 " 'PASSED'"
6266 "} catch(e) {"
6267 " e"
6268 "}";
6269 ExpectString(code, "PASSED");
6270}
6271
6272
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006273THREADED_TEST(MultiContexts) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00006274 v8::Isolate* isolate = CcTest::isolate();
6275 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00006276 v8::Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00006277 templ->Set(v8_str("dummy"), v8::FunctionTemplate::New(isolate,
6278 DummyCallHandler));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006279
6280 Local<String> password = v8_str("Password");
6281
6282 // Create an environment
6283 LocalContext context0(0, templ);
6284 context0->SetSecurityToken(password);
6285 v8::Handle<v8::Object> global0 = context0->Global();
6286 global0->Set(v8_str("custom"), v8_num(1234));
6287 CHECK_EQ(1234, global0->Get(v8_str("custom"))->Int32Value());
6288
6289 // Create an independent environment
6290 LocalContext context1(0, templ);
6291 context1->SetSecurityToken(password);
6292 v8::Handle<v8::Object> global1 = context1->Global();
6293 global1->Set(v8_str("custom"), v8_num(1234));
6294 CHECK_NE(global0, global1);
6295 CHECK_EQ(1234, global0->Get(v8_str("custom"))->Int32Value());
6296 CHECK_EQ(1234, global1->Get(v8_str("custom"))->Int32Value());
6297
6298 // Now create a new context with the old global
6299 LocalContext context2(0, templ, global1);
6300 context2->SetSecurityToken(password);
6301 v8::Handle<v8::Object> global2 = context2->Global();
6302 CHECK_EQ(global1, global2);
6303 CHECK_EQ(0, global1->Get(v8_str("custom"))->Int32Value());
6304 CHECK_EQ(0, global2->Get(v8_str("custom"))->Int32Value());
6305}
6306
6307
6308THREADED_TEST(FunctionPrototypeAcrossContexts) {
6309 // Make sure that functions created by cloning boilerplates cannot
6310 // communicate through their __proto__ field.
6311
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006312 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006313
6314 LocalContext env0;
6315 v8::Handle<v8::Object> global0 =
6316 env0->Global();
6317 v8::Handle<v8::Object> object0 =
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00006318 global0->Get(v8_str("Object")).As<v8::Object>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006319 v8::Handle<v8::Object> tostring0 =
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00006320 object0->Get(v8_str("toString")).As<v8::Object>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006321 v8::Handle<v8::Object> proto0 =
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00006322 tostring0->Get(v8_str("__proto__")).As<v8::Object>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006323 proto0->Set(v8_str("custom"), v8_num(1234));
6324
6325 LocalContext env1;
6326 v8::Handle<v8::Object> global1 =
6327 env1->Global();
6328 v8::Handle<v8::Object> object1 =
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00006329 global1->Get(v8_str("Object")).As<v8::Object>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006330 v8::Handle<v8::Object> tostring1 =
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00006331 object1->Get(v8_str("toString")).As<v8::Object>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006332 v8::Handle<v8::Object> proto1 =
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00006333 tostring1->Get(v8_str("__proto__")).As<v8::Object>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006334 CHECK(!proto1->Has(v8_str("custom")));
6335}
6336
6337
6338THREADED_TEST(Regress892105) {
6339 // Make sure that object and array literals created by cloning
6340 // boilerplates cannot communicate through their __proto__
6341 // field. This is rather difficult to check, but we try to add stuff
6342 // to Object.prototype and Array.prototype and create a new
6343 // environment. This should succeed.
6344
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006345 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006346
6347 Local<String> source = v8_str("Object.prototype.obj = 1234;"
6348 "Array.prototype.arr = 4567;"
6349 "8901");
6350
6351 LocalContext env0;
6352 Local<Script> script0 = Script::Compile(source);
6353 CHECK_EQ(8901.0, script0->Run()->NumberValue());
6354
6355 LocalContext env1;
6356 Local<Script> script1 = Script::Compile(source);
6357 CHECK_EQ(8901.0, script1->Run()->NumberValue());
6358}
6359
6360
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006361THREADED_TEST(UndetectableObject) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006362 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00006363 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006364
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00006365 Local<v8::FunctionTemplate> desc =
6366 v8::FunctionTemplate::New(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006367 desc->InstanceTemplate()->MarkAsUndetectable(); // undetectable
6368
6369 Local<v8::Object> obj = desc->GetFunction()->NewInstance();
6370 env->Global()->Set(v8_str("undetectable"), obj);
6371
6372 ExpectString("undetectable.toString()", "[object Object]");
6373 ExpectString("typeof undetectable", "undefined");
6374 ExpectString("typeof(undetectable)", "undefined");
6375 ExpectBoolean("typeof undetectable == 'undefined'", true);
6376 ExpectBoolean("typeof undetectable == 'object'", false);
6377 ExpectBoolean("if (undetectable) { true; } else { false; }", false);
6378 ExpectBoolean("!undetectable", true);
6379
6380 ExpectObject("true&&undetectable", obj);
6381 ExpectBoolean("false&&undetectable", false);
6382 ExpectBoolean("true||undetectable", true);
6383 ExpectObject("false||undetectable", obj);
6384
6385 ExpectObject("undetectable&&true", obj);
6386 ExpectObject("undetectable&&false", obj);
6387 ExpectBoolean("undetectable||true", true);
6388 ExpectBoolean("undetectable||false", false);
6389
6390 ExpectBoolean("undetectable==null", true);
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00006391 ExpectBoolean("null==undetectable", true);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006392 ExpectBoolean("undetectable==undefined", true);
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00006393 ExpectBoolean("undefined==undetectable", true);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006394 ExpectBoolean("undetectable==undetectable", true);
6395
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00006396
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006397 ExpectBoolean("undetectable===null", false);
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00006398 ExpectBoolean("null===undetectable", false);
6399 ExpectBoolean("undetectable===undefined", false);
6400 ExpectBoolean("undefined===undetectable", false);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006401 ExpectBoolean("undetectable===undetectable", true);
6402}
6403
6404
ager@chromium.org04921a82011-06-27 13:21:41 +00006405THREADED_TEST(VoidLiteral) {
ager@chromium.org04921a82011-06-27 13:21:41 +00006406 LocalContext env;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00006407 v8::Isolate* isolate = env->GetIsolate();
6408 v8::HandleScope scope(isolate);
ager@chromium.org04921a82011-06-27 13:21:41 +00006409
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00006410 Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
ager@chromium.org04921a82011-06-27 13:21:41 +00006411 desc->InstanceTemplate()->MarkAsUndetectable(); // undetectable
6412
6413 Local<v8::Object> obj = desc->GetFunction()->NewInstance();
6414 env->Global()->Set(v8_str("undetectable"), obj);
6415
6416 ExpectBoolean("undefined == void 0", true);
6417 ExpectBoolean("undetectable == void 0", true);
6418 ExpectBoolean("null == void 0", true);
6419 ExpectBoolean("undefined === void 0", true);
6420 ExpectBoolean("undetectable === void 0", false);
6421 ExpectBoolean("null === void 0", false);
6422
6423 ExpectBoolean("void 0 == undefined", true);
6424 ExpectBoolean("void 0 == undetectable", true);
6425 ExpectBoolean("void 0 == null", true);
6426 ExpectBoolean("void 0 === undefined", true);
6427 ExpectBoolean("void 0 === undetectable", false);
6428 ExpectBoolean("void 0 === null", false);
6429
6430 ExpectString("(function() {"
6431 " try {"
6432 " return x === void 0;"
6433 " } catch(e) {"
6434 " return e.toString();"
6435 " }"
6436 "})()",
6437 "ReferenceError: x is not defined");
6438 ExpectString("(function() {"
6439 " try {"
6440 " return void 0 === x;"
6441 " } catch(e) {"
6442 " return e.toString();"
6443 " }"
6444 "})()",
6445 "ReferenceError: x is not defined");
6446}
6447
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00006448
6449THREADED_TEST(ExtensibleOnUndetectable) {
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00006450 LocalContext env;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00006451 v8::Isolate* isolate = env->GetIsolate();
6452 v8::HandleScope scope(isolate);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00006453
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00006454 Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00006455 desc->InstanceTemplate()->MarkAsUndetectable(); // undetectable
6456
6457 Local<v8::Object> obj = desc->GetFunction()->NewInstance();
6458 env->Global()->Set(v8_str("undetectable"), obj);
6459
6460 Local<String> source = v8_str("undetectable.x = 42;"
6461 "undetectable.x");
6462
6463 Local<Script> script = Script::Compile(source);
6464
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006465 CHECK_EQ(v8::Integer::New(isolate, 42), script->Run());
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00006466
6467 ExpectBoolean("Object.isExtensible(undetectable)", true);
6468
6469 source = v8_str("Object.preventExtensions(undetectable);");
6470 script = Script::Compile(source);
6471 script->Run();
6472 ExpectBoolean("Object.isExtensible(undetectable)", false);
6473
6474 source = v8_str("undetectable.y = 2000;");
6475 script = Script::Compile(source);
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00006476 script->Run();
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00006477 ExpectBoolean("undetectable.y == undefined", true);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00006478}
6479
6480
6481
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006482THREADED_TEST(UndetectableString) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006483 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00006484 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006485
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00006486 Local<String> obj = String::NewFromUtf8(env->GetIsolate(), "foo",
6487 String::kUndetectableString);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006488 env->Global()->Set(v8_str("undetectable"), obj);
6489
6490 ExpectString("undetectable", "foo");
6491 ExpectString("typeof undetectable", "undefined");
6492 ExpectString("typeof(undetectable)", "undefined");
6493 ExpectBoolean("typeof undetectable == 'undefined'", true);
6494 ExpectBoolean("typeof undetectable == 'string'", false);
6495 ExpectBoolean("if (undetectable) { true; } else { false; }", false);
6496 ExpectBoolean("!undetectable", true);
6497
6498 ExpectObject("true&&undetectable", obj);
6499 ExpectBoolean("false&&undetectable", false);
6500 ExpectBoolean("true||undetectable", true);
6501 ExpectObject("false||undetectable", obj);
6502
6503 ExpectObject("undetectable&&true", obj);
6504 ExpectObject("undetectable&&false", obj);
6505 ExpectBoolean("undetectable||true", true);
6506 ExpectBoolean("undetectable||false", false);
6507
6508 ExpectBoolean("undetectable==null", true);
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00006509 ExpectBoolean("null==undetectable", true);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006510 ExpectBoolean("undetectable==undefined", true);
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00006511 ExpectBoolean("undefined==undetectable", true);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006512 ExpectBoolean("undetectable==undetectable", true);
6513
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00006514
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006515 ExpectBoolean("undetectable===null", false);
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00006516 ExpectBoolean("null===undetectable", false);
6517 ExpectBoolean("undetectable===undefined", false);
6518 ExpectBoolean("undefined===undetectable", false);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006519 ExpectBoolean("undetectable===undetectable", true);
6520}
6521
6522
vegorov@chromium.org7304bca2011-05-16 12:14:13 +00006523TEST(UndetectableOptimized) {
6524 i::FLAG_allow_natives_syntax = true;
vegorov@chromium.org7304bca2011-05-16 12:14:13 +00006525 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00006526 v8::HandleScope scope(env->GetIsolate());
vegorov@chromium.org7304bca2011-05-16 12:14:13 +00006527
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00006528 Local<String> obj = String::NewFromUtf8(env->GetIsolate(), "foo",
6529 String::kUndetectableString);
vegorov@chromium.org7304bca2011-05-16 12:14:13 +00006530 env->Global()->Set(v8_str("undetectable"), obj);
6531 env->Global()->Set(v8_str("detectable"), v8_str("bar"));
6532
6533 ExpectString(
6534 "function testBranch() {"
6535 " if (!%_IsUndetectableObject(undetectable)) throw 1;"
6536 " if (%_IsUndetectableObject(detectable)) throw 2;"
6537 "}\n"
6538 "function testBool() {"
6539 " var b1 = !%_IsUndetectableObject(undetectable);"
6540 " var b2 = %_IsUndetectableObject(detectable);"
6541 " if (b1) throw 3;"
6542 " if (b2) throw 4;"
6543 " return b1 == b2;"
6544 "}\n"
6545 "%OptimizeFunctionOnNextCall(testBranch);"
6546 "%OptimizeFunctionOnNextCall(testBool);"
6547 "for (var i = 0; i < 10; i++) {"
6548 " testBranch();"
6549 " testBool();"
6550 "}\n"
6551 "\"PASS\"",
6552 "PASS");
6553}
6554
6555
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006556template <typename T> static void USE(T) { }
6557
6558
machenbach@chromium.orgafbdadc2013-12-09 16:12:18 +00006559// The point of this test is type checking. We run it only so compilers
6560// don't complain about an unused function.
6561TEST(PersistentHandles) {
6562 LocalContext env;
6563 v8::Isolate* isolate = CcTest::isolate();
6564 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006565 Local<String> str = v8_str("foo");
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00006566 v8::Persistent<String> p_str(isolate, str);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00006567 p_str.Reset();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006568 Local<Script> scr = Script::Compile(v8_str(""));
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00006569 v8::Persistent<Script> p_scr(isolate, scr);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00006570 p_scr.Reset();
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00006571 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00006572 v8::Persistent<ObjectTemplate> p_templ(isolate, templ);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00006573 p_templ.Reset();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006574}
6575
6576
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00006577static void HandleLogDelegator(
6578 const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006579 ApiTestFuzzer::Fuzz();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006580}
6581
6582
6583THREADED_TEST(GlobalObjectTemplate) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006584 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006585 v8::HandleScope handle_scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00006586 Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006587 global_template->Set(v8_str("JSNI_Log"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00006588 v8::FunctionTemplate::New(isolate, HandleLogDelegator));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006589 v8::Local<Context> context = Context::New(isolate, 0, global_template);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006590 Context::Scope context_scope(context);
6591 Script::Compile(v8_str("JSNI_Log('LOG')"))->Run();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006592}
6593
6594
6595static const char* kSimpleExtensionSource =
6596 "function Foo() {"
6597 " return 4;"
6598 "}";
6599
6600
6601THREADED_TEST(SimpleExtensions) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006602 v8::HandleScope handle_scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006603 v8::RegisterExtension(new Extension("simpletest", kSimpleExtensionSource));
6604 const char* extension_names[] = { "simpletest" };
6605 v8::ExtensionConfiguration extensions(1, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006606 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006607 Context::New(CcTest::isolate(), &extensions);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006608 Context::Scope lock(context);
6609 v8::Handle<Value> result = Script::Compile(v8_str("Foo()"))->Run();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006610 CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 4));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006611}
6612
6613
danno@chromium.org412fa512012-09-14 13:28:26 +00006614THREADED_TEST(NullExtensions) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006615 v8::HandleScope handle_scope(CcTest::isolate());
danno@chromium.org412fa512012-09-14 13:28:26 +00006616 v8::RegisterExtension(new Extension("nulltest", NULL));
6617 const char* extension_names[] = { "nulltest" };
6618 v8::ExtensionConfiguration extensions(1, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006619 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006620 Context::New(CcTest::isolate(), &extensions);
danno@chromium.org412fa512012-09-14 13:28:26 +00006621 Context::Scope lock(context);
6622 v8::Handle<Value> result = Script::Compile(v8_str("1+3"))->Run();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006623 CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 4));
danno@chromium.org412fa512012-09-14 13:28:26 +00006624}
6625
6626
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00006627static const char* kEmbeddedExtensionSource =
6628 "function Ret54321(){return 54321;}~~@@$"
6629 "$%% THIS IS A SERIES OF NON-NULL-TERMINATED STRINGS.";
6630static const int kEmbeddedExtensionSourceValidLen = 34;
6631
6632
6633THREADED_TEST(ExtensionMissingSourceLength) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006634 v8::HandleScope handle_scope(CcTest::isolate());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00006635 v8::RegisterExtension(new Extension("srclentest_fail",
6636 kEmbeddedExtensionSource));
6637 const char* extension_names[] = { "srclentest_fail" };
6638 v8::ExtensionConfiguration extensions(1, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006639 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006640 Context::New(CcTest::isolate(), &extensions);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00006641 CHECK_EQ(0, *context);
6642}
6643
6644
6645THREADED_TEST(ExtensionWithSourceLength) {
6646 for (int source_len = kEmbeddedExtensionSourceValidLen - 1;
6647 source_len <= kEmbeddedExtensionSourceValidLen + 1; ++source_len) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006648 v8::HandleScope handle_scope(CcTest::isolate());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00006649 i::ScopedVector<char> extension_name(32);
6650 i::OS::SNPrintF(extension_name, "ext #%d", source_len);
6651 v8::RegisterExtension(new Extension(extension_name.start(),
6652 kEmbeddedExtensionSource, 0, 0,
6653 source_len));
6654 const char* extension_names[1] = { extension_name.start() };
6655 v8::ExtensionConfiguration extensions(1, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006656 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006657 Context::New(CcTest::isolate(), &extensions);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00006658 if (source_len == kEmbeddedExtensionSourceValidLen) {
6659 Context::Scope lock(context);
6660 v8::Handle<Value> result = Script::Compile(v8_str("Ret54321()"))->Run();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006661 CHECK_EQ(v8::Integer::New(CcTest::isolate(), 54321), result);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00006662 } else {
6663 // Anything but exactly the right length should fail to compile.
6664 CHECK_EQ(0, *context);
6665 }
6666 }
6667}
6668
6669
ager@chromium.org18ad94b2009-09-02 08:22:29 +00006670static const char* kEvalExtensionSource1 =
6671 "function UseEval1() {"
kasperl@chromium.org2d18d102009-04-15 13:27:32 +00006672 " var x = 42;"
6673 " return eval('x');"
6674 "}";
6675
6676
ager@chromium.org18ad94b2009-09-02 08:22:29 +00006677static const char* kEvalExtensionSource2 =
6678 "(function() {"
6679 " var x = 42;"
6680 " function e() {"
6681 " return eval('x');"
6682 " }"
6683 " this.UseEval2 = e;"
6684 "})()";
6685
6686
kasperl@chromium.org2d18d102009-04-15 13:27:32 +00006687THREADED_TEST(UseEvalFromExtension) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006688 v8::HandleScope handle_scope(CcTest::isolate());
ager@chromium.org18ad94b2009-09-02 08:22:29 +00006689 v8::RegisterExtension(new Extension("evaltest1", kEvalExtensionSource1));
6690 v8::RegisterExtension(new Extension("evaltest2", kEvalExtensionSource2));
6691 const char* extension_names[] = { "evaltest1", "evaltest2" };
6692 v8::ExtensionConfiguration extensions(2, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006693 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006694 Context::New(CcTest::isolate(), &extensions);
kasperl@chromium.org2d18d102009-04-15 13:27:32 +00006695 Context::Scope lock(context);
ager@chromium.org18ad94b2009-09-02 08:22:29 +00006696 v8::Handle<Value> result = Script::Compile(v8_str("UseEval1()"))->Run();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006697 CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 42));
ager@chromium.org18ad94b2009-09-02 08:22:29 +00006698 result = Script::Compile(v8_str("UseEval2()"))->Run();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006699 CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 42));
kasperl@chromium.org2d18d102009-04-15 13:27:32 +00006700}
6701
6702
ager@chromium.org18ad94b2009-09-02 08:22:29 +00006703static const char* kWithExtensionSource1 =
6704 "function UseWith1() {"
kasperl@chromium.org2d18d102009-04-15 13:27:32 +00006705 " var x = 42;"
6706 " with({x:87}) { return x; }"
6707 "}";
6708
6709
ager@chromium.org18ad94b2009-09-02 08:22:29 +00006710
6711static const char* kWithExtensionSource2 =
6712 "(function() {"
6713 " var x = 42;"
6714 " function e() {"
6715 " with ({x:87}) { return x; }"
6716 " }"
6717 " this.UseWith2 = e;"
6718 "})()";
6719
6720
kasperl@chromium.org2d18d102009-04-15 13:27:32 +00006721THREADED_TEST(UseWithFromExtension) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006722 v8::HandleScope handle_scope(CcTest::isolate());
ager@chromium.org18ad94b2009-09-02 08:22:29 +00006723 v8::RegisterExtension(new Extension("withtest1", kWithExtensionSource1));
6724 v8::RegisterExtension(new Extension("withtest2", kWithExtensionSource2));
6725 const char* extension_names[] = { "withtest1", "withtest2" };
6726 v8::ExtensionConfiguration extensions(2, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006727 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006728 Context::New(CcTest::isolate(), &extensions);
kasperl@chromium.org2d18d102009-04-15 13:27:32 +00006729 Context::Scope lock(context);
ager@chromium.org18ad94b2009-09-02 08:22:29 +00006730 v8::Handle<Value> result = Script::Compile(v8_str("UseWith1()"))->Run();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006731 CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 87));
ager@chromium.org18ad94b2009-09-02 08:22:29 +00006732 result = Script::Compile(v8_str("UseWith2()"))->Run();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006733 CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 87));
kasperl@chromium.org2d18d102009-04-15 13:27:32 +00006734}
6735
6736
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006737THREADED_TEST(AutoExtensions) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006738 v8::HandleScope handle_scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006739 Extension* extension = new Extension("autotest", kSimpleExtensionSource);
6740 extension->set_auto_enable(true);
6741 v8::RegisterExtension(extension);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006742 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006743 Context::New(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006744 Context::Scope lock(context);
6745 v8::Handle<Value> result = Script::Compile(v8_str("Foo()"))->Run();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006746 CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 4));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006747}
6748
6749
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00006750static const char* kSyntaxErrorInExtensionSource =
6751 "[";
6752
6753
6754// Test that a syntax error in an extension does not cause a fatal
6755// error but results in an empty context.
6756THREADED_TEST(SyntaxErrorExtensions) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006757 v8::HandleScope handle_scope(CcTest::isolate());
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00006758 v8::RegisterExtension(new Extension("syntaxerror",
6759 kSyntaxErrorInExtensionSource));
6760 const char* extension_names[] = { "syntaxerror" };
6761 v8::ExtensionConfiguration extensions(1, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006762 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006763 Context::New(CcTest::isolate(), &extensions);
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00006764 CHECK(context.IsEmpty());
6765}
6766
6767
6768static const char* kExceptionInExtensionSource =
6769 "throw 42";
6770
6771
6772// Test that an exception when installing an extension does not cause
6773// a fatal error but results in an empty context.
6774THREADED_TEST(ExceptionExtensions) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006775 v8::HandleScope handle_scope(CcTest::isolate());
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00006776 v8::RegisterExtension(new Extension("exception",
6777 kExceptionInExtensionSource));
6778 const char* extension_names[] = { "exception" };
6779 v8::ExtensionConfiguration extensions(1, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006780 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006781 Context::New(CcTest::isolate(), &extensions);
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00006782 CHECK(context.IsEmpty());
6783}
6784
6785
ager@chromium.org5b2fbee2010-09-08 06:38:15 +00006786static const char* kNativeCallInExtensionSource =
6787 "function call_runtime_last_index_of(x) {"
6788 " return %StringLastIndexOf(x, 'bob', 10);"
6789 "}";
6790
6791
6792static const char* kNativeCallTest =
6793 "call_runtime_last_index_of('bobbobboellebobboellebobbob');";
6794
6795// Test that a native runtime calls are supported in extensions.
6796THREADED_TEST(NativeCallInExtensions) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006797 v8::HandleScope handle_scope(CcTest::isolate());
ager@chromium.org5b2fbee2010-09-08 06:38:15 +00006798 v8::RegisterExtension(new Extension("nativecall",
6799 kNativeCallInExtensionSource));
6800 const char* extension_names[] = { "nativecall" };
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);
ager@chromium.org5b2fbee2010-09-08 06:38:15 +00006804 Context::Scope lock(context);
6805 v8::Handle<Value> result = Script::Compile(v8_str(kNativeCallTest))->Run();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006806 CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 3));
ager@chromium.org5b2fbee2010-09-08 06:38:15 +00006807}
6808
6809
whesse@chromium.org7b260152011-06-20 15:33:18 +00006810class NativeFunctionExtension : public Extension {
6811 public:
6812 NativeFunctionExtension(const char* name,
6813 const char* source,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00006814 v8::FunctionCallback fun = &Echo)
whesse@chromium.org7b260152011-06-20 15:33:18 +00006815 : Extension(name, source),
6816 function_(fun) { }
6817
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00006818 virtual v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate(
6819 v8::Isolate* isolate,
whesse@chromium.org7b260152011-06-20 15:33:18 +00006820 v8::Handle<v8::String> name) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00006821 return v8::FunctionTemplate::New(isolate, function_);
whesse@chromium.org7b260152011-06-20 15:33:18 +00006822 }
6823
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00006824 static void Echo(const v8::FunctionCallbackInfo<v8::Value>& args) {
6825 if (args.Length() >= 1) args.GetReturnValue().Set(args[0]);
whesse@chromium.org7b260152011-06-20 15:33:18 +00006826 }
6827 private:
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00006828 v8::FunctionCallback function_;
whesse@chromium.org7b260152011-06-20 15:33:18 +00006829};
6830
6831
6832THREADED_TEST(NativeFunctionDeclaration) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006833 v8::HandleScope handle_scope(CcTest::isolate());
whesse@chromium.org7b260152011-06-20 15:33:18 +00006834 const char* name = "nativedecl";
6835 v8::RegisterExtension(new NativeFunctionExtension(name,
6836 "native function foo();"));
6837 const char* extension_names[] = { name };
6838 v8::ExtensionConfiguration extensions(1, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006839 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006840 Context::New(CcTest::isolate(), &extensions);
whesse@chromium.org7b260152011-06-20 15:33:18 +00006841 Context::Scope lock(context);
6842 v8::Handle<Value> result = Script::Compile(v8_str("foo(42);"))->Run();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006843 CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 42));
whesse@chromium.org7b260152011-06-20 15:33:18 +00006844}
6845
6846
6847THREADED_TEST(NativeFunctionDeclarationError) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006848 v8::HandleScope handle_scope(CcTest::isolate());
lrn@chromium.org67e236d2011-06-23 10:18:16 +00006849 const char* name = "nativedeclerr";
whesse@chromium.org7b260152011-06-20 15:33:18 +00006850 // Syntax error in extension code.
6851 v8::RegisterExtension(new NativeFunctionExtension(name,
6852 "native\nfunction foo();"));
6853 const char* extension_names[] = { name };
6854 v8::ExtensionConfiguration extensions(1, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006855 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006856 Context::New(CcTest::isolate(), &extensions);
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00006857 CHECK(context.IsEmpty());
whesse@chromium.org7b260152011-06-20 15:33:18 +00006858}
6859
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00006860
whesse@chromium.org7b260152011-06-20 15:33:18 +00006861THREADED_TEST(NativeFunctionDeclarationErrorEscape) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006862 v8::HandleScope handle_scope(CcTest::isolate());
lrn@chromium.org67e236d2011-06-23 10:18:16 +00006863 const char* name = "nativedeclerresc";
whesse@chromium.org7b260152011-06-20 15:33:18 +00006864 // Syntax error in extension code - escape code in "native" means that
6865 // it's not treated as a keyword.
6866 v8::RegisterExtension(new NativeFunctionExtension(
6867 name,
6868 "nativ\\u0065 function foo();"));
6869 const char* extension_names[] = { name };
6870 v8::ExtensionConfiguration extensions(1, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006871 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006872 Context::New(CcTest::isolate(), &extensions);
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00006873 CHECK(context.IsEmpty());
whesse@chromium.org7b260152011-06-20 15:33:18 +00006874}
6875
6876
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006877static void CheckDependencies(const char* name, const char* expected) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006878 v8::HandleScope handle_scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006879 v8::ExtensionConfiguration config(1, &name);
6880 LocalContext context(&config);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00006881 CHECK_EQ(String::NewFromUtf8(CcTest::isolate(), expected),
6882 context->Global()->Get(v8_str("loaded")));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006883}
6884
6885
6886/*
6887 * Configuration:
6888 *
6889 * /-- B <--\
6890 * A <- -- D <-- E
6891 * \-- C <--/
6892 */
6893THREADED_TEST(ExtensionDependency) {
6894 static const char* kEDeps[] = { "D" };
6895 v8::RegisterExtension(new Extension("E", "this.loaded += 'E';", 1, kEDeps));
6896 static const char* kDDeps[] = { "B", "C" };
6897 v8::RegisterExtension(new Extension("D", "this.loaded += 'D';", 2, kDDeps));
6898 static const char* kBCDeps[] = { "A" };
6899 v8::RegisterExtension(new Extension("B", "this.loaded += 'B';", 1, kBCDeps));
6900 v8::RegisterExtension(new Extension("C", "this.loaded += 'C';", 1, kBCDeps));
6901 v8::RegisterExtension(new Extension("A", "this.loaded += 'A';"));
6902 CheckDependencies("A", "undefinedA");
6903 CheckDependencies("B", "undefinedAB");
6904 CheckDependencies("C", "undefinedAC");
6905 CheckDependencies("D", "undefinedABCD");
6906 CheckDependencies("E", "undefinedABCDE");
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006907 v8::HandleScope handle_scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006908 static const char* exts[2] = { "C", "E" };
6909 v8::ExtensionConfiguration config(2, exts);
6910 LocalContext context(&config);
6911 CHECK_EQ(v8_str("undefinedACBDE"), context->Global()->Get(v8_str("loaded")));
6912}
6913
6914
6915static const char* kExtensionTestScript =
6916 "native function A();"
6917 "native function B();"
6918 "native function C();"
6919 "function Foo(i) {"
6920 " if (i == 0) return A();"
6921 " if (i == 1) return B();"
6922 " if (i == 2) return C();"
6923 "}";
6924
6925
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00006926static void CallFun(const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006927 ApiTestFuzzer::Fuzz();
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00006928 if (args.IsConstructCall()) {
6929 args.This()->Set(v8_str("data"), args.Data());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00006930 args.GetReturnValue().SetNull();
6931 return;
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00006932 }
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00006933 args.GetReturnValue().Set(args.Data());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006934}
6935
6936
6937class FunctionExtension : public Extension {
6938 public:
6939 FunctionExtension() : Extension("functiontest", kExtensionTestScript) { }
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00006940 virtual v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate(
6941 v8::Isolate* isolate,
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006942 v8::Handle<String> name);
6943};
6944
6945
6946static int lookup_count = 0;
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00006947v8::Handle<v8::FunctionTemplate> FunctionExtension::GetNativeFunctionTemplate(
6948 v8::Isolate* isolate, v8::Handle<String> name) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006949 lookup_count++;
6950 if (name->Equals(v8_str("A"))) {
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006951 return v8::FunctionTemplate::New(
6952 isolate, CallFun, v8::Integer::New(isolate, 8));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006953 } else if (name->Equals(v8_str("B"))) {
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006954 return v8::FunctionTemplate::New(
6955 isolate, CallFun, v8::Integer::New(isolate, 7));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006956 } else if (name->Equals(v8_str("C"))) {
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006957 return v8::FunctionTemplate::New(
6958 isolate, CallFun, v8::Integer::New(isolate, 6));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006959 } else {
6960 return v8::Handle<v8::FunctionTemplate>();
6961 }
6962}
6963
6964
6965THREADED_TEST(FunctionLookup) {
6966 v8::RegisterExtension(new FunctionExtension());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006967 v8::HandleScope handle_scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006968 static const char* exts[1] = { "functiontest" };
6969 v8::ExtensionConfiguration config(1, exts);
6970 LocalContext context(&config);
6971 CHECK_EQ(3, lookup_count);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006972 CHECK_EQ(v8::Integer::New(CcTest::isolate(), 8),
6973 Script::Compile(v8_str("Foo(0)"))->Run());
6974 CHECK_EQ(v8::Integer::New(CcTest::isolate(), 7),
6975 Script::Compile(v8_str("Foo(1)"))->Run());
6976 CHECK_EQ(v8::Integer::New(CcTest::isolate(), 6),
6977 Script::Compile(v8_str("Foo(2)"))->Run());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006978}
6979
6980
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00006981THREADED_TEST(NativeFunctionConstructCall) {
6982 v8::RegisterExtension(new FunctionExtension());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006983 v8::HandleScope handle_scope(CcTest::isolate());
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00006984 static const char* exts[1] = { "functiontest" };
6985 v8::ExtensionConfiguration config(1, exts);
6986 LocalContext context(&config);
6987 for (int i = 0; i < 10; i++) {
6988 // Run a few times to ensure that allocation of objects doesn't
6989 // change behavior of a constructor function.
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006990 CHECK_EQ(v8::Integer::New(CcTest::isolate(), 8),
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00006991 Script::Compile(v8_str("(new A()).data"))->Run());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006992 CHECK_EQ(v8::Integer::New(CcTest::isolate(), 7),
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00006993 Script::Compile(v8_str("(new B()).data"))->Run());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006994 CHECK_EQ(v8::Integer::New(CcTest::isolate(), 6),
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00006995 Script::Compile(v8_str("(new C()).data"))->Run());
6996 }
6997}
6998
6999
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007000static const char* last_location;
7001static const char* last_message;
7002void StoringErrorCallback(const char* location, const char* message) {
7003 if (last_location == NULL) {
7004 last_location = location;
7005 last_message = message;
7006 }
7007}
7008
7009
7010// ErrorReporting creates a circular extensions configuration and
7011// tests that the fatal error handler gets called. This renders V8
7012// unusable and therefore this test cannot be run in parallel.
7013TEST(ErrorReporting) {
7014 v8::V8::SetFatalErrorHandler(StoringErrorCallback);
7015 static const char* aDeps[] = { "B" };
7016 v8::RegisterExtension(new Extension("A", "", 1, aDeps));
7017 static const char* bDeps[] = { "A" };
7018 v8::RegisterExtension(new Extension("B", "", 1, bDeps));
7019 last_location = NULL;
7020 v8::ExtensionConfiguration config(1, bDeps);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007021 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007022 Context::New(CcTest::isolate(), &config);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007023 CHECK(context.IsEmpty());
7024 CHECK_NE(last_location, NULL);
7025}
7026
7027
ager@chromium.org7c537e22008-10-16 08:43:32 +00007028static const char* js_code_causing_huge_string_flattening =
7029 "var str = 'X';"
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +00007030 "for (var i = 0; i < 30; i++) {"
ager@chromium.org7c537e22008-10-16 08:43:32 +00007031 " str = str + str;"
7032 "}"
7033 "str.match(/X/);";
7034
7035
ager@chromium.org7c537e22008-10-16 08:43:32 +00007036TEST(RegexpOutOfMemory) {
7037 // Execute a script that causes out of memory when flattening a string.
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007038 v8::HandleScope scope(CcTest::isolate());
ager@chromium.org7c537e22008-10-16 08:43:32 +00007039 v8::V8::SetFatalErrorHandler(OOMCallback);
7040 LocalContext context;
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00007041 Local<Script> script = Script::Compile(String::NewFromUtf8(
7042 CcTest::isolate(), js_code_causing_huge_string_flattening));
ager@chromium.org7c537e22008-10-16 08:43:32 +00007043 last_location = NULL;
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00007044 script->Run();
ager@chromium.org7c537e22008-10-16 08:43:32 +00007045
7046 CHECK(false); // Should not return.
7047}
7048
7049
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007050static void MissingScriptInfoMessageListener(v8::Handle<v8::Message> message,
7051 v8::Handle<Value> data) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00007052 CHECK(message->GetScriptResourceName()->IsUndefined());
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00007053 CHECK_EQ(v8::Undefined(CcTest::isolate()), message->GetScriptResourceName());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007054 message->GetLineNumber();
7055 message->GetSourceLine();
7056}
7057
7058
7059THREADED_TEST(ErrorWithMissingScriptInfo) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007060 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00007061 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007062 v8::V8::AddMessageListener(MissingScriptInfoMessageListener);
7063 Script::Compile(v8_str("throw Error()"))->Run();
7064 v8::V8::RemoveMessageListeners(MissingScriptInfoMessageListener);
7065}
7066
7067
7068int global_index = 0;
7069
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007070template<typename T>
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007071class Snorkel {
7072 public:
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007073 explicit Snorkel(v8::Persistent<T>* handle) : handle_(handle) {
7074 index_ = global_index++;
7075 }
7076 v8::Persistent<T>* handle_;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007077 int index_;
7078};
7079
7080class Whammy {
7081 public:
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00007082 explicit Whammy(v8::Isolate* isolate) : cursor_(0), isolate_(isolate) { }
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00007083 ~Whammy() { script_.Reset(); }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007084 v8::Handle<Script> getScript() {
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00007085 if (script_.IsEmpty()) script_.Reset(isolate_, v8_compile("({}).blammo"));
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00007086 return Local<Script>::New(isolate_, script_);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007087 }
7088
7089 public:
7090 static const int kObjectCount = 256;
7091 int cursor_;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00007092 v8::Isolate* isolate_;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007093 v8::Persistent<v8::Object> objects_[kObjectCount];
7094 v8::Persistent<Script> script_;
7095};
7096
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007097static void HandleWeakReference(
7098 const v8::WeakCallbackData<v8::Value, Snorkel<v8::Value> >& data) {
7099 data.GetParameter()->handle_->ClearWeak();
7100 delete data.GetParameter();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007101}
7102
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007103void WhammyPropertyGetter(Local<String> name,
7104 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007105 Whammy* whammy =
7106 static_cast<Whammy*>(v8::Handle<v8::External>::Cast(info.Data())->Value());
7107
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00007108 v8::Persistent<v8::Object>& prev = whammy->objects_[whammy->cursor_];
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007109
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007110 v8::Handle<v8::Object> obj = v8::Object::New(info.GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007111 if (!prev.IsEmpty()) {
rossberg@chromium.org79e79022013-06-03 15:43:46 +00007112 v8::Local<v8::Object>::New(info.GetIsolate(), prev)
7113 ->Set(v8_str("next"), obj);
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007114 prev.SetWeak<Value, Snorkel<Value> >(new Snorkel<Value>(&prev.As<Value>()),
7115 &HandleWeakReference);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007116 }
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00007117 whammy->objects_[whammy->cursor_].Reset(info.GetIsolate(), obj);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007118 whammy->cursor_ = (whammy->cursor_ + 1) % Whammy::kObjectCount;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007119 info.GetReturnValue().Set(whammy->getScript()->Run());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007120}
7121
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00007122
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007123THREADED_TEST(WeakReference) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00007124 v8::Isolate* isolate = CcTest::isolate();
7125 v8::HandleScope handle_scope(isolate);
7126 v8::Handle<v8::ObjectTemplate> templ= v8::ObjectTemplate::New(isolate);
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007127 Whammy* whammy = new Whammy(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007128 templ->SetNamedPropertyHandler(WhammyPropertyGetter,
7129 0, 0, 0, 0,
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00007130 v8::External::New(CcTest::isolate(), whammy));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007131 const char* extension_list[] = { "v8/gc" };
7132 v8::ExtensionConfiguration extensions(1, extension_list);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007133 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007134 Context::New(CcTest::isolate(), &extensions);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007135 Context::Scope context_scope(context);
7136
7137 v8::Handle<v8::Object> interceptor = templ->NewInstance();
7138 context->Global()->Set(v8_str("whammy"), interceptor);
7139 const char* code =
7140 "var last;"
7141 "for (var i = 0; i < 10000; i++) {"
7142 " var obj = whammy.length;"
7143 " if (last) last.next = obj;"
7144 " last = obj;"
7145 "}"
7146 "gc();"
7147 "4";
7148 v8::Handle<Value> result = CompileRun(code);
7149 CHECK_EQ(4.0, result->NumberValue());
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +00007150 delete whammy;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007151}
7152
7153
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007154struct FlagAndPersistent {
7155 bool flag;
7156 v8::Persistent<v8::Object> handle;
7157};
7158
7159
7160static void DisposeAndSetFlag(
7161 const v8::WeakCallbackData<v8::Object, FlagAndPersistent>& data) {
7162 data.GetParameter()->handle.Reset();
7163 data.GetParameter()->flag = true;
ager@chromium.orgc4c92722009-11-18 14:12:51 +00007164}
7165
ager@chromium.orgc4c92722009-11-18 14:12:51 +00007166
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007167THREADED_TEST(IndependentWeakHandle) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007168 v8::Isolate* iso = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007169 v8::HandleScope scope(iso);
7170 v8::Handle<Context> context = Context::New(iso);
ager@chromium.orgc4c92722009-11-18 14:12:51 +00007171 Context::Scope context_scope(context);
7172
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007173 FlagAndPersistent object_a, object_b;
ager@chromium.orgc4c92722009-11-18 14:12:51 +00007174
7175 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00007176 v8::HandleScope handle_scope(iso);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007177 object_a.handle.Reset(iso, v8::Object::New(iso));
7178 object_b.handle.Reset(iso, v8::Object::New(iso));
ager@chromium.orgc4c92722009-11-18 14:12:51 +00007179 }
7180
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007181 object_a.flag = false;
7182 object_b.flag = false;
7183 object_a.handle.SetWeak(&object_a, &DisposeAndSetFlag);
7184 object_b.handle.SetWeak(&object_b, &DisposeAndSetFlag);
7185 CHECK(!object_b.handle.IsIndependent());
7186 object_a.handle.MarkIndependent();
7187 object_b.handle.MarkIndependent();
7188 CHECK(object_b.handle.IsIndependent());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007189 CcTest::heap()->PerformScavenge();
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007190 CHECK(object_a.flag);
7191 CHECK(object_b.flag);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007192}
ager@chromium.orgc4c92722009-11-18 14:12:51 +00007193
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007194
7195static void InvokeScavenge() {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007196 CcTest::heap()->PerformScavenge();
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007197}
7198
7199
7200static void InvokeMarkSweep() {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007201 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007202}
7203
7204
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007205static void ForceScavenge(
7206 const v8::WeakCallbackData<v8::Object, FlagAndPersistent>& data) {
7207 data.GetParameter()->handle.Reset();
7208 data.GetParameter()->flag = true;
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007209 InvokeScavenge();
7210}
7211
7212
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007213static void ForceMarkSweep(
7214 const v8::WeakCallbackData<v8::Object, FlagAndPersistent>& data) {
7215 data.GetParameter()->handle.Reset();
7216 data.GetParameter()->flag = true;
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007217 InvokeMarkSweep();
7218}
7219
7220
7221THREADED_TEST(GCFromWeakCallbacks) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007222 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007223 v8::HandleScope scope(isolate);
7224 v8::Handle<Context> context = Context::New(isolate);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007225 Context::Scope context_scope(context);
7226
7227 static const int kNumberOfGCTypes = 2;
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007228 typedef v8::WeakCallbackData<v8::Object, FlagAndPersistent>::Callback
7229 Callback;
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007230 Callback gc_forcing_callback[kNumberOfGCTypes] =
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007231 {&ForceScavenge, &ForceMarkSweep};
7232
7233 typedef void (*GCInvoker)();
7234 GCInvoker invoke_gc[kNumberOfGCTypes] = {&InvokeScavenge, &InvokeMarkSweep};
7235
7236 for (int outer_gc = 0; outer_gc < kNumberOfGCTypes; outer_gc++) {
7237 for (int inner_gc = 0; inner_gc < kNumberOfGCTypes; inner_gc++) {
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007238 FlagAndPersistent object;
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007239 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00007240 v8::HandleScope handle_scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007241 object.handle.Reset(isolate, v8::Object::New(isolate));
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007242 }
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007243 object.flag = false;
7244 object.handle.SetWeak(&object, gc_forcing_callback[inner_gc]);
7245 object.handle.MarkIndependent();
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007246 invoke_gc[outer_gc]();
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007247 CHECK(object.flag);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007248 }
ager@chromium.orgc4c92722009-11-18 14:12:51 +00007249 }
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007250}
7251
7252
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007253static void RevivingCallback(
7254 const v8::WeakCallbackData<v8::Object, FlagAndPersistent>& data) {
7255 data.GetParameter()->handle.ClearWeak();
7256 data.GetParameter()->flag = true;
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007257}
7258
7259
7260THREADED_TEST(IndependentHandleRevival) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007261 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007262 v8::HandleScope scope(isolate);
7263 v8::Handle<Context> context = Context::New(isolate);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007264 Context::Scope context_scope(context);
7265
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007266 FlagAndPersistent object;
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007267 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00007268 v8::HandleScope handle_scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007269 v8::Local<v8::Object> o = v8::Object::New(isolate);
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007270 object.handle.Reset(isolate, o);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007271 o->Set(v8_str("x"), v8::Integer::New(isolate, 1));
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007272 v8::Local<String> y_str = v8_str("y");
rossberg@chromium.org79e79022013-06-03 15:43:46 +00007273 o->Set(y_str, y_str);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007274 }
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007275 object.flag = false;
7276 object.handle.SetWeak(&object, &RevivingCallback);
7277 object.handle.MarkIndependent();
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007278 CcTest::heap()->PerformScavenge();
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007279 CHECK(object.flag);
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007280 CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007281 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00007282 v8::HandleScope handle_scope(isolate);
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007283 v8::Local<v8::Object> o =
7284 v8::Local<v8::Object>::New(isolate, object.handle);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007285 v8::Local<String> y_str = v8_str("y");
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007286 CHECK_EQ(v8::Integer::New(isolate, 1), o->Get(v8_str("x")));
rossberg@chromium.org79e79022013-06-03 15:43:46 +00007287 CHECK(o->Get(y_str)->Equals(y_str));
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007288 }
ager@chromium.orgc4c92722009-11-18 14:12:51 +00007289}
7290
7291
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007292v8::Handle<Function> args_fun;
7293
7294
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007295static void ArgumentsTestCallback(
7296 const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007297 ApiTestFuzzer::Fuzz();
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00007298 v8::Isolate* isolate = args.GetIsolate();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007299 CHECK_EQ(args_fun, args.Callee());
7300 CHECK_EQ(3, args.Length());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007301 CHECK_EQ(v8::Integer::New(isolate, 1), args[0]);
7302 CHECK_EQ(v8::Integer::New(isolate, 2), args[1]);
7303 CHECK_EQ(v8::Integer::New(isolate, 3), args[2]);
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00007304 CHECK_EQ(v8::Undefined(isolate), args[3]);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00007305 v8::HandleScope scope(args.GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007306 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007307}
7308
7309
7310THREADED_TEST(Arguments) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00007311 v8::Isolate* isolate = CcTest::isolate();
7312 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00007313 v8::Handle<v8::ObjectTemplate> global = ObjectTemplate::New(isolate);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00007314 global->Set(v8_str("f"),
7315 v8::FunctionTemplate::New(isolate, ArgumentsTestCallback));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007316 LocalContext context(NULL, global);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00007317 args_fun = context->Global()->Get(v8_str("f")).As<Function>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007318 v8_compile("f(1, 2, 3)")->Run();
7319}
7320
7321
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007322static void NoBlockGetterX(Local<String> name,
7323 const v8::PropertyCallbackInfo<v8::Value>&) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007324}
7325
7326
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007327static void NoBlockGetterI(uint32_t index,
7328 const v8::PropertyCallbackInfo<v8::Value>&) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007329}
7330
7331
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007332static void PDeleter(Local<String> name,
7333 const v8::PropertyCallbackInfo<v8::Boolean>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007334 if (!name->Equals(v8_str("foo"))) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007335 return; // not intercepted
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007336 }
7337
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007338 info.GetReturnValue().Set(false); // intercepted, don't delete the property
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007339}
7340
7341
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007342static void IDeleter(uint32_t index,
7343 const v8::PropertyCallbackInfo<v8::Boolean>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007344 if (index != 2) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007345 return; // not intercepted
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007346 }
7347
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007348 info.GetReturnValue().Set(false); // intercepted, don't delete the property
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007349}
7350
7351
7352THREADED_TEST(Deleter) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00007353 v8::Isolate* isolate = CcTest::isolate();
7354 v8::HandleScope scope(isolate);
7355 v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007356 obj->SetNamedPropertyHandler(NoBlockGetterX, NULL, NULL, PDeleter, NULL);
7357 obj->SetIndexedPropertyHandler(NoBlockGetterI, NULL, NULL, IDeleter, NULL);
7358 LocalContext context;
7359 context->Global()->Set(v8_str("k"), obj->NewInstance());
7360 CompileRun(
7361 "k.foo = 'foo';"
7362 "k.bar = 'bar';"
7363 "k[2] = 2;"
7364 "k[4] = 4;");
7365 CHECK(v8_compile("delete k.foo")->Run()->IsFalse());
7366 CHECK(v8_compile("delete k.bar")->Run()->IsTrue());
7367
7368 CHECK_EQ(v8_compile("k.foo")->Run(), v8_str("foo"));
7369 CHECK(v8_compile("k.bar")->Run()->IsUndefined());
7370
7371 CHECK(v8_compile("delete k[2]")->Run()->IsFalse());
7372 CHECK(v8_compile("delete k[4]")->Run()->IsTrue());
7373
7374 CHECK_EQ(v8_compile("k[2]")->Run(), v8_num(2));
7375 CHECK(v8_compile("k[4]")->Run()->IsUndefined());
7376}
7377
7378
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007379static void GetK(Local<String> name,
7380 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007381 ApiTestFuzzer::Fuzz();
ager@chromium.org65dad4b2009-04-23 08:48:43 +00007382 if (name->Equals(v8_str("foo")) ||
7383 name->Equals(v8_str("bar")) ||
7384 name->Equals(v8_str("baz"))) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007385 info.GetReturnValue().SetUndefined();
ager@chromium.org65dad4b2009-04-23 08:48:43 +00007386 }
ager@chromium.org65dad4b2009-04-23 08:48:43 +00007387}
7388
7389
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007390static void IndexedGetK(uint32_t index,
7391 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.org65dad4b2009-04-23 08:48:43 +00007392 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007393 if (index == 0 || index == 1) info.GetReturnValue().SetUndefined();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007394}
7395
7396
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007397static void NamedEnum(const v8::PropertyCallbackInfo<v8::Array>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007398 ApiTestFuzzer::Fuzz();
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00007399 v8::Handle<v8::Array> result = v8::Array::New(info.GetIsolate(), 3);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007400 result->Set(v8::Integer::New(info.GetIsolate(), 0), v8_str("foo"));
7401 result->Set(v8::Integer::New(info.GetIsolate(), 1), v8_str("bar"));
7402 result->Set(v8::Integer::New(info.GetIsolate(), 2), v8_str("baz"));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007403 info.GetReturnValue().Set(result);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007404}
7405
7406
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007407static void IndexedEnum(const v8::PropertyCallbackInfo<v8::Array>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007408 ApiTestFuzzer::Fuzz();
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00007409 v8::Handle<v8::Array> result = v8::Array::New(info.GetIsolate(), 2);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007410 result->Set(v8::Integer::New(info.GetIsolate(), 0), v8_str("0"));
7411 result->Set(v8::Integer::New(info.GetIsolate(), 1), v8_str("1"));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007412 info.GetReturnValue().Set(result);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007413}
7414
7415
7416THREADED_TEST(Enumerators) {
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007417 v8::Isolate* isolate = CcTest::isolate();
7418 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00007419 v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007420 obj->SetNamedPropertyHandler(GetK, NULL, NULL, NULL, NamedEnum);
ager@chromium.org65dad4b2009-04-23 08:48:43 +00007421 obj->SetIndexedPropertyHandler(IndexedGetK, NULL, NULL, NULL, IndexedEnum);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007422 LocalContext context;
7423 context->Global()->Set(v8_str("k"), obj->NewInstance());
7424 v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
ager@chromium.org65dad4b2009-04-23 08:48:43 +00007425 "k[10] = 0;"
7426 "k.a = 0;"
7427 "k[5] = 0;"
7428 "k.b = 0;"
7429 "k[4294967295] = 0;"
7430 "k.c = 0;"
7431 "k[4294967296] = 0;"
7432 "k.d = 0;"
7433 "k[140000] = 0;"
7434 "k.e = 0;"
7435 "k[30000000000] = 0;"
7436 "k.f = 0;"
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007437 "var result = [];"
7438 "for (var prop in k) {"
7439 " result.push(prop);"
7440 "}"
7441 "result"));
ager@chromium.org65dad4b2009-04-23 08:48:43 +00007442 // Check that we get all the property names returned including the
7443 // ones from the enumerators in the right order: indexed properties
7444 // in numerical order, indexed interceptor properties, named
7445 // properties in insertion order, named interceptor properties.
7446 // This order is not mandated by the spec, so this test is just
7447 // documenting our behavior.
7448 CHECK_EQ(17, result->Length());
7449 // Indexed properties in numerical order.
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007450 CHECK_EQ(v8_str("5"), result->Get(v8::Integer::New(isolate, 0)));
7451 CHECK_EQ(v8_str("10"), result->Get(v8::Integer::New(isolate, 1)));
7452 CHECK_EQ(v8_str("140000"), result->Get(v8::Integer::New(isolate, 2)));
7453 CHECK_EQ(v8_str("4294967295"), result->Get(v8::Integer::New(isolate, 3)));
ager@chromium.org65dad4b2009-04-23 08:48:43 +00007454 // Indexed interceptor properties in the order they are returned
7455 // from the enumerator interceptor.
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007456 CHECK_EQ(v8_str("0"), result->Get(v8::Integer::New(isolate, 4)));
7457 CHECK_EQ(v8_str("1"), result->Get(v8::Integer::New(isolate, 5)));
ager@chromium.org65dad4b2009-04-23 08:48:43 +00007458 // Named properties in insertion order.
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007459 CHECK_EQ(v8_str("a"), result->Get(v8::Integer::New(isolate, 6)));
7460 CHECK_EQ(v8_str("b"), result->Get(v8::Integer::New(isolate, 7)));
7461 CHECK_EQ(v8_str("c"), result->Get(v8::Integer::New(isolate, 8)));
7462 CHECK_EQ(v8_str("4294967296"), result->Get(v8::Integer::New(isolate, 9)));
7463 CHECK_EQ(v8_str("d"), result->Get(v8::Integer::New(isolate, 10)));
7464 CHECK_EQ(v8_str("e"), result->Get(v8::Integer::New(isolate, 11)));
7465 CHECK_EQ(v8_str("30000000000"), result->Get(v8::Integer::New(isolate, 12)));
7466 CHECK_EQ(v8_str("f"), result->Get(v8::Integer::New(isolate, 13)));
ager@chromium.org65dad4b2009-04-23 08:48:43 +00007467 // Named interceptor properties.
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007468 CHECK_EQ(v8_str("foo"), result->Get(v8::Integer::New(isolate, 14)));
7469 CHECK_EQ(v8_str("bar"), result->Get(v8::Integer::New(isolate, 15)));
7470 CHECK_EQ(v8_str("baz"), result->Get(v8::Integer::New(isolate, 16)));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007471}
7472
7473
7474int p_getter_count;
7475int p_getter_count2;
7476
7477
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007478static void PGetter(Local<String> name,
7479 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007480 ApiTestFuzzer::Fuzz();
7481 p_getter_count++;
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007482 v8::Handle<v8::Object> global =
7483 info.GetIsolate()->GetCurrentContext()->Global();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007484 CHECK_EQ(info.Holder(), global->Get(v8_str("o1")));
7485 if (name->Equals(v8_str("p1"))) {
7486 CHECK_EQ(info.This(), global->Get(v8_str("o1")));
7487 } else if (name->Equals(v8_str("p2"))) {
7488 CHECK_EQ(info.This(), global->Get(v8_str("o2")));
7489 } else if (name->Equals(v8_str("p3"))) {
7490 CHECK_EQ(info.This(), global->Get(v8_str("o3")));
7491 } else if (name->Equals(v8_str("p4"))) {
7492 CHECK_EQ(info.This(), global->Get(v8_str("o4")));
7493 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007494}
7495
7496
7497static void RunHolderTest(v8::Handle<v8::ObjectTemplate> obj) {
7498 ApiTestFuzzer::Fuzz();
7499 LocalContext context;
7500 context->Global()->Set(v8_str("o1"), obj->NewInstance());
7501 CompileRun(
7502 "o1.__proto__ = { };"
7503 "var o2 = { __proto__: o1 };"
7504 "var o3 = { __proto__: o2 };"
7505 "var o4 = { __proto__: o3 };"
7506 "for (var i = 0; i < 10; i++) o4.p4;"
7507 "for (var i = 0; i < 10; i++) o3.p3;"
7508 "for (var i = 0; i < 10; i++) o2.p2;"
7509 "for (var i = 0; i < 10; i++) o1.p1;");
7510}
7511
7512
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007513static void PGetter2(Local<String> name,
7514 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007515 ApiTestFuzzer::Fuzz();
7516 p_getter_count2++;
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007517 v8::Handle<v8::Object> global =
7518 info.GetIsolate()->GetCurrentContext()->Global();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007519 CHECK_EQ(info.Holder(), global->Get(v8_str("o1")));
7520 if (name->Equals(v8_str("p1"))) {
7521 CHECK_EQ(info.This(), global->Get(v8_str("o1")));
7522 } else if (name->Equals(v8_str("p2"))) {
7523 CHECK_EQ(info.This(), global->Get(v8_str("o2")));
7524 } else if (name->Equals(v8_str("p3"))) {
7525 CHECK_EQ(info.This(), global->Get(v8_str("o3")));
7526 } else if (name->Equals(v8_str("p4"))) {
7527 CHECK_EQ(info.This(), global->Get(v8_str("o4")));
7528 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007529}
7530
7531
7532THREADED_TEST(GetterHolders) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00007533 v8::Isolate* isolate = CcTest::isolate();
7534 v8::HandleScope scope(isolate);
7535 v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007536 obj->SetAccessor(v8_str("p1"), PGetter);
7537 obj->SetAccessor(v8_str("p2"), PGetter);
7538 obj->SetAccessor(v8_str("p3"), PGetter);
7539 obj->SetAccessor(v8_str("p4"), PGetter);
7540 p_getter_count = 0;
7541 RunHolderTest(obj);
7542 CHECK_EQ(40, p_getter_count);
7543}
7544
7545
7546THREADED_TEST(PreInterceptorHolders) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00007547 v8::Isolate* isolate = CcTest::isolate();
7548 v8::HandleScope scope(isolate);
7549 v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007550 obj->SetNamedPropertyHandler(PGetter2);
7551 p_getter_count2 = 0;
7552 RunHolderTest(obj);
7553 CHECK_EQ(40, p_getter_count2);
7554}
7555
7556
7557THREADED_TEST(ObjectInstantiation) {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00007558 v8::Isolate* isolate = CcTest::isolate();
7559 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00007560 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007561 templ->SetAccessor(v8_str("t"), PGetter2);
7562 LocalContext context;
7563 context->Global()->Set(v8_str("o"), templ->NewInstance());
7564 for (int i = 0; i < 100; i++) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007565 v8::HandleScope inner_scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007566 v8::Handle<v8::Object> obj = templ->NewInstance();
7567 CHECK_NE(obj, context->Global()->Get(v8_str("o")));
7568 context->Global()->Set(v8_str("o2"), obj);
7569 v8::Handle<Value> value =
7570 Script::Compile(v8_str("o.__proto__ === o2.__proto__"))->Run();
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00007571 CHECK_EQ(v8::True(isolate), value);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007572 context->Global()->Set(v8_str("o"), obj);
7573 }
7574}
7575
7576
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007577static int StrCmp16(uint16_t* a, uint16_t* b) {
7578 while (true) {
7579 if (*a == 0 && *b == 0) return 0;
7580 if (*a != *b) return 0 + *a - *b;
7581 a++;
7582 b++;
7583 }
7584}
7585
7586
7587static int StrNCmp16(uint16_t* a, uint16_t* b, int n) {
7588 while (true) {
7589 if (n-- == 0) return 0;
7590 if (*a == 0 && *b == 0) return 0;
7591 if (*a != *b) return 0 + *a - *b;
7592 a++;
7593 b++;
7594 }
7595}
7596
7597
yangguo@chromium.org154ff992012-03-13 08:09:54 +00007598int GetUtf8Length(Handle<String> str) {
7599 int len = str->Utf8Length();
7600 if (len < 0) {
7601 i::Handle<i::String> istr(v8::Utils::OpenHandle(*str));
7602 i::FlattenString(istr);
7603 len = str->Utf8Length();
7604 }
7605 return len;
7606}
7607
7608
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007609THREADED_TEST(StringWrite) {
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007610 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00007611 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007612 v8::Handle<String> str = v8_str("abcde");
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007613 // abc<Icelandic eth><Unicode snowman>.
7614 v8::Handle<String> str2 = v8_str("abc\303\260\342\230\203");
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00007615 v8::Handle<String> str3 = v8::String::NewFromUtf8(
7616 context->GetIsolate(), "abc\0def", v8::String::kNormalString, 7);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007617 const int kStride = 4; // Must match stride in for loops in JS below.
7618 CompileRun(
7619 "var left = '';"
7620 "for (var i = 0; i < 0xd800; i += 4) {"
7621 " left = left + String.fromCharCode(i);"
7622 "}");
7623 CompileRun(
7624 "var right = '';"
7625 "for (var i = 0; i < 0xd800; i += 4) {"
7626 " right = String.fromCharCode(i) + right;"
7627 "}");
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007628 v8::Handle<v8::Object> global = context->Global();
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007629 Handle<String> left_tree = global->Get(v8_str("left")).As<String>();
7630 Handle<String> right_tree = global->Get(v8_str("right")).As<String>();
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007631
7632 CHECK_EQ(5, str2->Length());
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007633 CHECK_EQ(0xd800 / kStride, left_tree->Length());
7634 CHECK_EQ(0xd800 / kStride, right_tree->Length());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007635
7636 char buf[100];
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007637 char utf8buf[0xd800 * 3];
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007638 uint16_t wbuf[100];
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007639 int len;
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007640 int charlen;
7641
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007642 memset(utf8buf, 0x1, 1000);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007643 len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007644 CHECK_EQ(9, len);
7645 CHECK_EQ(5, charlen);
7646 CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007647
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007648 memset(utf8buf, 0x1, 1000);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007649 len = str2->WriteUtf8(utf8buf, 8, &charlen);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007650 CHECK_EQ(8, len);
7651 CHECK_EQ(5, charlen);
7652 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203\1", 9));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007653
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007654 memset(utf8buf, 0x1, 1000);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007655 len = str2->WriteUtf8(utf8buf, 7, &charlen);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007656 CHECK_EQ(5, len);
7657 CHECK_EQ(4, charlen);
7658 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007659
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007660 memset(utf8buf, 0x1, 1000);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007661 len = str2->WriteUtf8(utf8buf, 6, &charlen);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007662 CHECK_EQ(5, len);
7663 CHECK_EQ(4, charlen);
7664 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007665
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007666 memset(utf8buf, 0x1, 1000);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007667 len = str2->WriteUtf8(utf8buf, 5, &charlen);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007668 CHECK_EQ(5, len);
7669 CHECK_EQ(4, charlen);
7670 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007671
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007672 memset(utf8buf, 0x1, 1000);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007673 len = str2->WriteUtf8(utf8buf, 4, &charlen);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007674 CHECK_EQ(3, len);
7675 CHECK_EQ(3, charlen);
7676 CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007677
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007678 memset(utf8buf, 0x1, 1000);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007679 len = str2->WriteUtf8(utf8buf, 3, &charlen);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007680 CHECK_EQ(3, len);
7681 CHECK_EQ(3, charlen);
7682 CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007683
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007684 memset(utf8buf, 0x1, 1000);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007685 len = str2->WriteUtf8(utf8buf, 2, &charlen);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007686 CHECK_EQ(2, len);
7687 CHECK_EQ(2, charlen);
7688 CHECK_EQ(0, strncmp(utf8buf, "ab\1", 3));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007689
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007690 memset(utf8buf, 0x1, sizeof(utf8buf));
yangguo@chromium.org154ff992012-03-13 08:09:54 +00007691 len = GetUtf8Length(left_tree);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007692 int utf8_expected =
7693 (0x80 + (0x800 - 0x80) * 2 + (0xd800 - 0x800) * 3) / kStride;
7694 CHECK_EQ(utf8_expected, len);
7695 len = left_tree->WriteUtf8(utf8buf, utf8_expected, &charlen);
7696 CHECK_EQ(utf8_expected, len);
7697 CHECK_EQ(0xd800 / kStride, charlen);
7698 CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[utf8_expected - 3]));
7699 CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[utf8_expected - 2]));
7700 CHECK_EQ(0xc0 - kStride,
7701 static_cast<unsigned char>(utf8buf[utf8_expected - 1]));
7702 CHECK_EQ(1, utf8buf[utf8_expected]);
7703
7704 memset(utf8buf, 0x1, sizeof(utf8buf));
yangguo@chromium.org154ff992012-03-13 08:09:54 +00007705 len = GetUtf8Length(right_tree);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007706 CHECK_EQ(utf8_expected, len);
7707 len = right_tree->WriteUtf8(utf8buf, utf8_expected, &charlen);
7708 CHECK_EQ(utf8_expected, len);
7709 CHECK_EQ(0xd800 / kStride, charlen);
7710 CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[0]));
7711 CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[1]));
7712 CHECK_EQ(0xc0 - kStride, static_cast<unsigned char>(utf8buf[2]));
7713 CHECK_EQ(1, utf8buf[utf8_expected]);
7714
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007715 memset(buf, 0x1, sizeof(buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007716 memset(wbuf, 0x1, sizeof(wbuf));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007717 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007718 CHECK_EQ(5, len);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007719 len = str->Write(wbuf);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007720 CHECK_EQ(5, len);
7721 CHECK_EQ(0, strcmp("abcde", buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007722 uint16_t answer1[] = {'a', 'b', 'c', 'd', 'e', '\0'};
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007723 CHECK_EQ(0, StrCmp16(answer1, wbuf));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007724
7725 memset(buf, 0x1, sizeof(buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007726 memset(wbuf, 0x1, sizeof(wbuf));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007727 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 4);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007728 CHECK_EQ(4, len);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007729 len = str->Write(wbuf, 0, 4);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007730 CHECK_EQ(4, len);
7731 CHECK_EQ(0, strncmp("abcd\1", buf, 5));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007732 uint16_t answer2[] = {'a', 'b', 'c', 'd', 0x101};
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007733 CHECK_EQ(0, StrNCmp16(answer2, wbuf, 5));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007734
7735 memset(buf, 0x1, sizeof(buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007736 memset(wbuf, 0x1, sizeof(wbuf));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007737 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 5);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007738 CHECK_EQ(5, len);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007739 len = str->Write(wbuf, 0, 5);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007740 CHECK_EQ(5, len);
7741 CHECK_EQ(0, strncmp("abcde\1", buf, 6));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007742 uint16_t answer3[] = {'a', 'b', 'c', 'd', 'e', 0x101};
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007743 CHECK_EQ(0, StrNCmp16(answer3, wbuf, 6));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007744
7745 memset(buf, 0x1, sizeof(buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007746 memset(wbuf, 0x1, sizeof(wbuf));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007747 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 6);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007748 CHECK_EQ(5, len);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007749 len = str->Write(wbuf, 0, 6);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007750 CHECK_EQ(5, len);
7751 CHECK_EQ(0, strcmp("abcde", buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007752 uint16_t answer4[] = {'a', 'b', 'c', 'd', 'e', '\0'};
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007753 CHECK_EQ(0, StrCmp16(answer4, wbuf));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007754
7755 memset(buf, 0x1, sizeof(buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007756 memset(wbuf, 0x1, sizeof(wbuf));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007757 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, -1);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007758 CHECK_EQ(1, len);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007759 len = str->Write(wbuf, 4, -1);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007760 CHECK_EQ(1, len);
7761 CHECK_EQ(0, strcmp("e", buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007762 uint16_t answer5[] = {'e', '\0'};
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007763 CHECK_EQ(0, StrCmp16(answer5, wbuf));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007764
7765 memset(buf, 0x1, sizeof(buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007766 memset(wbuf, 0x1, sizeof(wbuf));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007767 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, 6);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007768 CHECK_EQ(1, len);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007769 len = str->Write(wbuf, 4, 6);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007770 CHECK_EQ(1, len);
7771 CHECK_EQ(0, strcmp("e", buf));
7772 CHECK_EQ(0, StrCmp16(answer5, wbuf));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007773
7774 memset(buf, 0x1, sizeof(buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007775 memset(wbuf, 0x1, sizeof(wbuf));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007776 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, 1);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007777 CHECK_EQ(1, len);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007778 len = str->Write(wbuf, 4, 1);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007779 CHECK_EQ(1, len);
7780 CHECK_EQ(0, strncmp("e\1", buf, 2));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007781 uint16_t answer6[] = {'e', 0x101};
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007782 CHECK_EQ(0, StrNCmp16(answer6, wbuf, 2));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007783
7784 memset(buf, 0x1, sizeof(buf));
7785 memset(wbuf, 0x1, sizeof(wbuf));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007786 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 3, 1);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007787 CHECK_EQ(1, len);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007788 len = str->Write(wbuf, 3, 1);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007789 CHECK_EQ(1, len);
7790 CHECK_EQ(0, strncmp("d\1", buf, 2));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007791 uint16_t answer7[] = {'d', 0x101};
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007792 CHECK_EQ(0, StrNCmp16(answer7, wbuf, 2));
ricow@chromium.orgddd545c2011-08-24 12:02:41 +00007793
7794 memset(wbuf, 0x1, sizeof(wbuf));
7795 wbuf[5] = 'X';
7796 len = str->Write(wbuf, 0, 6, String::NO_NULL_TERMINATION);
7797 CHECK_EQ(5, len);
7798 CHECK_EQ('X', wbuf[5]);
7799 uint16_t answer8a[] = {'a', 'b', 'c', 'd', 'e'};
7800 uint16_t answer8b[] = {'a', 'b', 'c', 'd', 'e', '\0'};
7801 CHECK_EQ(0, StrNCmp16(answer8a, wbuf, 5));
7802 CHECK_NE(0, StrCmp16(answer8b, wbuf));
7803 wbuf[5] = '\0';
7804 CHECK_EQ(0, StrCmp16(answer8b, wbuf));
7805
7806 memset(buf, 0x1, sizeof(buf));
7807 buf[5] = 'X';
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007808 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf),
7809 0,
7810 6,
7811 String::NO_NULL_TERMINATION);
ricow@chromium.orgddd545c2011-08-24 12:02:41 +00007812 CHECK_EQ(5, len);
7813 CHECK_EQ('X', buf[5]);
7814 CHECK_EQ(0, strncmp("abcde", buf, 5));
7815 CHECK_NE(0, strcmp("abcde", buf));
7816 buf[5] = '\0';
7817 CHECK_EQ(0, strcmp("abcde", buf));
7818
7819 memset(utf8buf, 0x1, sizeof(utf8buf));
7820 utf8buf[8] = 'X';
7821 len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen,
7822 String::NO_NULL_TERMINATION);
7823 CHECK_EQ(8, len);
7824 CHECK_EQ('X', utf8buf[8]);
7825 CHECK_EQ(5, charlen);
7826 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203", 8));
7827 CHECK_NE(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
7828 utf8buf[8] = '\0';
7829 CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
yangguo@chromium.org304cc332012-07-24 07:59:48 +00007830
7831 memset(utf8buf, 0x1, sizeof(utf8buf));
7832 utf8buf[5] = 'X';
7833 len = str->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen,
7834 String::NO_NULL_TERMINATION);
7835 CHECK_EQ(5, len);
7836 CHECK_EQ('X', utf8buf[5]); // Test that the sixth character is untouched.
7837 CHECK_EQ(5, charlen);
7838 utf8buf[5] = '\0';
7839 CHECK_EQ(0, strcmp(utf8buf, "abcde"));
7840
7841 memset(buf, 0x1, sizeof(buf));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007842 len = str3->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
yangguo@chromium.org304cc332012-07-24 07:59:48 +00007843 CHECK_EQ(7, len);
7844 CHECK_EQ(0, strcmp("abc", buf));
7845 CHECK_EQ(0, buf[3]);
7846 CHECK_EQ(0, strcmp("def", buf + 4));
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00007847
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007848 CHECK_EQ(0, str->WriteOneByte(NULL, 0, 0, String::NO_NULL_TERMINATION));
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00007849 CHECK_EQ(0, str->WriteUtf8(NULL, 0, 0, String::NO_NULL_TERMINATION));
7850 CHECK_EQ(0, str->Write(NULL, 0, 0, String::NO_NULL_TERMINATION));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007851}
7852
7853
yangguo@chromium.org154ff992012-03-13 08:09:54 +00007854static void Utf16Helper(
7855 LocalContext& context,
7856 const char* name,
7857 const char* lengths_name,
7858 int len) {
7859 Local<v8::Array> a =
7860 Local<v8::Array>::Cast(context->Global()->Get(v8_str(name)));
7861 Local<v8::Array> alens =
7862 Local<v8::Array>::Cast(context->Global()->Get(v8_str(lengths_name)));
7863 for (int i = 0; i < len; i++) {
7864 Local<v8::String> string =
7865 Local<v8::String>::Cast(a->Get(i));
7866 Local<v8::Number> expected_len =
7867 Local<v8::Number>::Cast(alens->Get(i));
7868 int length = GetUtf8Length(string);
7869 CHECK_EQ(static_cast<int>(expected_len->Value()), length);
7870 }
7871}
7872
7873
7874static uint16_t StringGet(Handle<String> str, int index) {
7875 i::Handle<i::String> istring =
7876 v8::Utils::OpenHandle(String::Cast(*str));
7877 return istring->Get(index);
7878}
7879
7880
7881static void WriteUtf8Helper(
7882 LocalContext& context,
7883 const char* name,
7884 const char* lengths_name,
7885 int len) {
7886 Local<v8::Array> b =
7887 Local<v8::Array>::Cast(context->Global()->Get(v8_str(name)));
7888 Local<v8::Array> alens =
7889 Local<v8::Array>::Cast(context->Global()->Get(v8_str(lengths_name)));
7890 char buffer[1000];
7891 char buffer2[1000];
7892 for (int i = 0; i < len; i++) {
7893 Local<v8::String> string =
7894 Local<v8::String>::Cast(b->Get(i));
7895 Local<v8::Number> expected_len =
7896 Local<v8::Number>::Cast(alens->Get(i));
7897 int utf8_length = static_cast<int>(expected_len->Value());
7898 for (int j = utf8_length + 1; j >= 0; j--) {
7899 memset(reinterpret_cast<void*>(&buffer), 42, sizeof(buffer));
7900 memset(reinterpret_cast<void*>(&buffer2), 42, sizeof(buffer2));
7901 int nchars;
7902 int utf8_written =
7903 string->WriteUtf8(buffer, j, &nchars, String::NO_OPTIONS);
7904 int utf8_written2 =
7905 string->WriteUtf8(buffer2, j, &nchars, String::NO_NULL_TERMINATION);
7906 CHECK_GE(utf8_length + 1, utf8_written);
7907 CHECK_GE(utf8_length, utf8_written2);
7908 for (int k = 0; k < utf8_written2; k++) {
7909 CHECK_EQ(buffer[k], buffer2[k]);
7910 }
7911 CHECK(nchars * 3 >= utf8_written - 1);
7912 CHECK(nchars <= utf8_written);
7913 if (j == utf8_length + 1) {
7914 CHECK_EQ(utf8_written2, utf8_length);
7915 CHECK_EQ(utf8_written2 + 1, utf8_written);
7916 }
7917 CHECK_EQ(buffer[utf8_written], 42);
7918 if (j > utf8_length) {
7919 if (utf8_written != 0) CHECK_EQ(buffer[utf8_written - 1], 0);
7920 if (utf8_written > 1) CHECK_NE(buffer[utf8_written - 2], 42);
7921 Handle<String> roundtrip = v8_str(buffer);
7922 CHECK(roundtrip->Equals(string));
7923 } else {
7924 if (utf8_written != 0) CHECK_NE(buffer[utf8_written - 1], 42);
7925 }
7926 if (utf8_written2 != 0) CHECK_NE(buffer[utf8_written - 1], 42);
7927 if (nchars >= 2) {
7928 uint16_t trail = StringGet(string, nchars - 1);
7929 uint16_t lead = StringGet(string, nchars - 2);
7930 if (((lead & 0xfc00) == 0xd800) &&
7931 ((trail & 0xfc00) == 0xdc00)) {
7932 unsigned char u1 = buffer2[utf8_written2 - 4];
7933 unsigned char u2 = buffer2[utf8_written2 - 3];
7934 unsigned char u3 = buffer2[utf8_written2 - 2];
7935 unsigned char u4 = buffer2[utf8_written2 - 1];
7936 CHECK_EQ((u1 & 0xf8), 0xf0);
7937 CHECK_EQ((u2 & 0xc0), 0x80);
7938 CHECK_EQ((u3 & 0xc0), 0x80);
7939 CHECK_EQ((u4 & 0xc0), 0x80);
7940 uint32_t c = 0x10000 + ((lead & 0x3ff) << 10) + (trail & 0x3ff);
7941 CHECK_EQ((u4 & 0x3f), (c & 0x3f));
7942 CHECK_EQ((u3 & 0x3f), ((c >> 6) & 0x3f));
7943 CHECK_EQ((u2 & 0x3f), ((c >> 12) & 0x3f));
7944 CHECK_EQ((u1 & 0x3), c >> 18);
7945 }
7946 }
7947 }
7948 }
7949}
7950
7951
7952THREADED_TEST(Utf16) {
7953 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00007954 v8::HandleScope scope(context->GetIsolate());
yangguo@chromium.org154ff992012-03-13 08:09:54 +00007955 CompileRun(
7956 "var pad = '01234567890123456789';"
7957 "var p = [];"
7958 "var plens = [20, 3, 3];"
7959 "p.push('01234567890123456789');"
7960 "var lead = 0xd800;"
7961 "var trail = 0xdc00;"
7962 "p.push(String.fromCharCode(0xd800));"
7963 "p.push(String.fromCharCode(0xdc00));"
7964 "var a = [];"
7965 "var b = [];"
danno@chromium.org88aa0582012-03-23 15:11:57 +00007966 "var c = [];"
yangguo@chromium.org154ff992012-03-13 08:09:54 +00007967 "var alens = [];"
7968 "for (var i = 0; i < 3; i++) {"
7969 " p[1] = String.fromCharCode(lead++);"
7970 " for (var j = 0; j < 3; j++) {"
7971 " p[2] = String.fromCharCode(trail++);"
7972 " a.push(p[i] + p[j]);"
7973 " b.push(p[i] + p[j]);"
danno@chromium.org88aa0582012-03-23 15:11:57 +00007974 " c.push(p[i] + p[j]);"
yangguo@chromium.org154ff992012-03-13 08:09:54 +00007975 " alens.push(plens[i] + plens[j]);"
7976 " }"
7977 "}"
7978 "alens[5] -= 2;" // Here the surrogate pairs match up.
7979 "var a2 = [];"
7980 "var b2 = [];"
danno@chromium.org88aa0582012-03-23 15:11:57 +00007981 "var c2 = [];"
yangguo@chromium.org154ff992012-03-13 08:09:54 +00007982 "var a2lens = [];"
7983 "for (var m = 0; m < 9; m++) {"
7984 " for (var n = 0; n < 9; n++) {"
7985 " a2.push(a[m] + a[n]);"
7986 " b2.push(b[m] + b[n]);"
danno@chromium.org88aa0582012-03-23 15:11:57 +00007987 " var newc = 'x' + c[m] + c[n] + 'y';"
7988 " c2.push(newc.substring(1, newc.length - 1));"
yangguo@chromium.org154ff992012-03-13 08:09:54 +00007989 " var utf = alens[m] + alens[n];" // And here.
7990 // The 'n's that start with 0xdc.. are 6-8
7991 // The 'm's that end with 0xd8.. are 1, 4 and 7
7992 " if ((m % 3) == 1 && n >= 6) utf -= 2;"
7993 " a2lens.push(utf);"
7994 " }"
7995 "}");
7996 Utf16Helper(context, "a", "alens", 9);
7997 Utf16Helper(context, "a2", "a2lens", 81);
7998 WriteUtf8Helper(context, "b", "alens", 9);
7999 WriteUtf8Helper(context, "b2", "a2lens", 81);
danno@chromium.org88aa0582012-03-23 15:11:57 +00008000 WriteUtf8Helper(context, "c2", "a2lens", 81);
yangguo@chromium.org154ff992012-03-13 08:09:54 +00008001}
8002
8003
8004static bool SameSymbol(Handle<String> s1, Handle<String> s2) {
8005 i::Handle<i::String> is1(v8::Utils::OpenHandle(*s1));
8006 i::Handle<i::String> is2(v8::Utils::OpenHandle(*s2));
8007 return *is1 == *is2;
8008}
8009
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00008010static void SameSymbolHelper(v8::Isolate* isolate, const char* a,
8011 const char* b) {
8012 Handle<String> symbol1 =
8013 v8::String::NewFromUtf8(isolate, a, v8::String::kInternalizedString);
8014 Handle<String> symbol2 =
8015 v8::String::NewFromUtf8(isolate, b, v8::String::kInternalizedString);
yangguo@chromium.org154ff992012-03-13 08:09:54 +00008016 CHECK(SameSymbol(symbol1, symbol2));
8017}
8018
8019
8020THREADED_TEST(Utf16Symbol) {
8021 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008022 v8::HandleScope scope(context->GetIsolate());
yangguo@chromium.org154ff992012-03-13 08:09:54 +00008023
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00008024 Handle<String> symbol1 = v8::String::NewFromUtf8(
8025 context->GetIsolate(), "abc", v8::String::kInternalizedString);
8026 Handle<String> symbol2 = v8::String::NewFromUtf8(
8027 context->GetIsolate(), "abc", v8::String::kInternalizedString);
yangguo@chromium.org154ff992012-03-13 08:09:54 +00008028 CHECK(SameSymbol(symbol1, symbol2));
8029
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00008030 SameSymbolHelper(context->GetIsolate(),
8031 "\360\220\220\205", // 4 byte encoding.
yangguo@chromium.org154ff992012-03-13 08:09:54 +00008032 "\355\240\201\355\260\205"); // 2 3-byte surrogates.
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00008033 SameSymbolHelper(context->GetIsolate(),
8034 "\355\240\201\355\260\206", // 2 3-byte surrogates.
yangguo@chromium.org154ff992012-03-13 08:09:54 +00008035 "\360\220\220\206"); // 4 byte encoding.
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00008036 SameSymbolHelper(context->GetIsolate(),
8037 "x\360\220\220\205", // 4 byte encoding.
yangguo@chromium.org154ff992012-03-13 08:09:54 +00008038 "x\355\240\201\355\260\205"); // 2 3-byte surrogates.
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00008039 SameSymbolHelper(context->GetIsolate(),
8040 "x\355\240\201\355\260\206", // 2 3-byte surrogates.
yangguo@chromium.org154ff992012-03-13 08:09:54 +00008041 "x\360\220\220\206"); // 4 byte encoding.
8042 CompileRun(
8043 "var sym0 = 'benedictus';"
8044 "var sym0b = 'S\303\270ren';"
8045 "var sym1 = '\355\240\201\355\260\207';"
8046 "var sym2 = '\360\220\220\210';"
8047 "var sym3 = 'x\355\240\201\355\260\207';"
8048 "var sym4 = 'x\360\220\220\210';"
8049 "if (sym1.length != 2) throw sym1;"
8050 "if (sym1.charCodeAt(1) != 0xdc07) throw sym1.charCodeAt(1);"
8051 "if (sym2.length != 2) throw sym2;"
8052 "if (sym2.charCodeAt(1) != 0xdc08) throw sym2.charCodeAt(2);"
8053 "if (sym3.length != 3) throw sym3;"
8054 "if (sym3.charCodeAt(2) != 0xdc07) throw sym1.charCodeAt(2);"
8055 "if (sym4.length != 3) throw sym4;"
8056 "if (sym4.charCodeAt(2) != 0xdc08) throw sym2.charCodeAt(2);");
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00008057 Handle<String> sym0 = v8::String::NewFromUtf8(
8058 context->GetIsolate(), "benedictus", v8::String::kInternalizedString);
8059 Handle<String> sym0b = v8::String::NewFromUtf8(
8060 context->GetIsolate(), "S\303\270ren", v8::String::kInternalizedString);
8061 Handle<String> sym1 =
8062 v8::String::NewFromUtf8(context->GetIsolate(), "\355\240\201\355\260\207",
8063 v8::String::kInternalizedString);
8064 Handle<String> sym2 =
8065 v8::String::NewFromUtf8(context->GetIsolate(), "\360\220\220\210",
8066 v8::String::kInternalizedString);
8067 Handle<String> sym3 = v8::String::NewFromUtf8(
8068 context->GetIsolate(), "x\355\240\201\355\260\207",
8069 v8::String::kInternalizedString);
8070 Handle<String> sym4 =
8071 v8::String::NewFromUtf8(context->GetIsolate(), "x\360\220\220\210",
8072 v8::String::kInternalizedString);
yangguo@chromium.org154ff992012-03-13 08:09:54 +00008073 v8::Local<v8::Object> global = context->Global();
8074 Local<Value> s0 = global->Get(v8_str("sym0"));
8075 Local<Value> s0b = global->Get(v8_str("sym0b"));
8076 Local<Value> s1 = global->Get(v8_str("sym1"));
8077 Local<Value> s2 = global->Get(v8_str("sym2"));
8078 Local<Value> s3 = global->Get(v8_str("sym3"));
8079 Local<Value> s4 = global->Get(v8_str("sym4"));
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00008080 CHECK(SameSymbol(sym0, Handle<String>::Cast(s0)));
8081 CHECK(SameSymbol(sym0b, Handle<String>::Cast(s0b)));
8082 CHECK(SameSymbol(sym1, Handle<String>::Cast(s1)));
8083 CHECK(SameSymbol(sym2, Handle<String>::Cast(s2)));
8084 CHECK(SameSymbol(sym3, Handle<String>::Cast(s3)));
8085 CHECK(SameSymbol(sym4, Handle<String>::Cast(s4)));
yangguo@chromium.org154ff992012-03-13 08:09:54 +00008086}
8087
8088
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008089THREADED_TEST(ToArrayIndex) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008090 LocalContext context;
ulan@chromium.org0f13e742014-01-03 15:51:11 +00008091 v8::Isolate* isolate = context->GetIsolate();
8092 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008093
8094 v8::Handle<String> str = v8_str("42");
8095 v8::Handle<v8::Uint32> index = str->ToArrayIndex();
8096 CHECK(!index.IsEmpty());
8097 CHECK_EQ(42.0, index->Uint32Value());
8098 str = v8_str("42asdf");
8099 index = str->ToArrayIndex();
8100 CHECK(index.IsEmpty());
8101 str = v8_str("-42");
8102 index = str->ToArrayIndex();
8103 CHECK(index.IsEmpty());
8104 str = v8_str("4294967295");
8105 index = str->ToArrayIndex();
8106 CHECK(!index.IsEmpty());
8107 CHECK_EQ(4294967295.0, index->Uint32Value());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00008108 v8::Handle<v8::Number> num = v8::Number::New(isolate, 1);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008109 index = num->ToArrayIndex();
8110 CHECK(!index.IsEmpty());
8111 CHECK_EQ(1.0, index->Uint32Value());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00008112 num = v8::Number::New(isolate, -1);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008113 index = num->ToArrayIndex();
8114 CHECK(index.IsEmpty());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00008115 v8::Handle<v8::Object> obj = v8::Object::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008116 index = obj->ToArrayIndex();
8117 CHECK(index.IsEmpty());
8118}
8119
8120
8121THREADED_TEST(ErrorConstruction) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008122 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008123 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008124
8125 v8::Handle<String> foo = v8_str("foo");
8126 v8::Handle<String> message = v8_str("message");
8127 v8::Handle<Value> range_error = v8::Exception::RangeError(foo);
8128 CHECK(range_error->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00008129 CHECK(range_error.As<v8::Object>()->Get(message)->Equals(foo));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008130 v8::Handle<Value> reference_error = v8::Exception::ReferenceError(foo);
8131 CHECK(reference_error->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00008132 CHECK(reference_error.As<v8::Object>()->Get(message)->Equals(foo));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008133 v8::Handle<Value> syntax_error = v8::Exception::SyntaxError(foo);
8134 CHECK(syntax_error->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00008135 CHECK(syntax_error.As<v8::Object>()->Get(message)->Equals(foo));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008136 v8::Handle<Value> type_error = v8::Exception::TypeError(foo);
8137 CHECK(type_error->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00008138 CHECK(type_error.As<v8::Object>()->Get(message)->Equals(foo));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008139 v8::Handle<Value> error = v8::Exception::Error(foo);
8140 CHECK(error->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00008141 CHECK(error.As<v8::Object>()->Get(message)->Equals(foo));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008142}
8143
8144
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00008145static void YGetter(Local<String> name,
8146 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008147 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00008148 info.GetReturnValue().Set(v8_num(10));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008149}
8150
8151
8152static void YSetter(Local<String> name,
8153 Local<Value> value,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00008154 const v8::PropertyCallbackInfo<void>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008155 if (info.This()->Has(name)) {
8156 info.This()->Delete(name);
8157 }
8158 info.This()->Set(name, value);
8159}
8160
8161
8162THREADED_TEST(DeleteAccessor) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00008163 v8::Isolate* isolate = CcTest::isolate();
8164 v8::HandleScope scope(isolate);
8165 v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008166 obj->SetAccessor(v8_str("y"), YGetter, YSetter);
8167 LocalContext context;
8168 v8::Handle<v8::Object> holder = obj->NewInstance();
8169 context->Global()->Set(v8_str("holder"), holder);
8170 v8::Handle<Value> result = CompileRun(
8171 "holder.y = 11; holder.y = 12; holder.y");
8172 CHECK_EQ(12, result->Uint32Value());
8173}
8174
8175
8176THREADED_TEST(TypeSwitch) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00008177 v8::Isolate* isolate = CcTest::isolate();
8178 v8::HandleScope scope(isolate);
8179 v8::Handle<v8::FunctionTemplate> templ1 = v8::FunctionTemplate::New(isolate);
8180 v8::Handle<v8::FunctionTemplate> templ2 = v8::FunctionTemplate::New(isolate);
8181 v8::Handle<v8::FunctionTemplate> templ3 = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008182 v8::Handle<v8::FunctionTemplate> templs[3] = { templ1, templ2, templ3 };
8183 v8::Handle<v8::TypeSwitch> type_switch = v8::TypeSwitch::New(3, templs);
8184 LocalContext context;
ulan@chromium.org0f13e742014-01-03 15:51:11 +00008185 v8::Handle<v8::Object> obj0 = v8::Object::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008186 v8::Handle<v8::Object> obj1 = templ1->GetFunction()->NewInstance();
8187 v8::Handle<v8::Object> obj2 = templ2->GetFunction()->NewInstance();
8188 v8::Handle<v8::Object> obj3 = templ3->GetFunction()->NewInstance();
8189 for (int i = 0; i < 10; i++) {
8190 CHECK_EQ(0, type_switch->match(obj0));
8191 CHECK_EQ(1, type_switch->match(obj1));
8192 CHECK_EQ(2, type_switch->match(obj2));
8193 CHECK_EQ(3, type_switch->match(obj3));
8194 CHECK_EQ(3, type_switch->match(obj3));
8195 CHECK_EQ(2, type_switch->match(obj2));
8196 CHECK_EQ(1, type_switch->match(obj1));
8197 CHECK_EQ(0, type_switch->match(obj0));
8198 }
8199}
8200
8201
8202// For use within the TestSecurityHandler() test.
8203static bool g_security_callback_result = false;
8204static bool NamedSecurityTestCallback(Local<v8::Object> global,
8205 Local<Value> name,
8206 v8::AccessType type,
8207 Local<Value> data) {
8208 // Always allow read access.
8209 if (type == v8::ACCESS_GET)
8210 return true;
8211
8212 // Sometimes allow other access.
8213 return g_security_callback_result;
8214}
8215
8216
8217static bool IndexedSecurityTestCallback(Local<v8::Object> global,
8218 uint32_t key,
8219 v8::AccessType type,
8220 Local<Value> data) {
8221 // Always allow read access.
8222 if (type == v8::ACCESS_GET)
8223 return true;
8224
8225 // Sometimes allow other access.
8226 return g_security_callback_result;
8227}
8228
8229
8230static int trouble_nesting = 0;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00008231static void TroubleCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008232 ApiTestFuzzer::Fuzz();
8233 trouble_nesting++;
8234
8235 // Call a JS function that throws an uncaught exception.
machenbach@chromium.org528ce022013-09-23 14:09:36 +00008236 Local<v8::Object> arg_this =
8237 args.GetIsolate()->GetCurrentContext()->Global();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008238 Local<Value> trouble_callee = (trouble_nesting == 3) ?
8239 arg_this->Get(v8_str("trouble_callee")) :
8240 arg_this->Get(v8_str("trouble_caller"));
8241 CHECK(trouble_callee->IsFunction());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00008242 args.GetReturnValue().Set(
8243 Function::Cast(*trouble_callee)->Call(arg_this, 0, NULL));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008244}
8245
8246
8247static int report_count = 0;
8248static void ApiUncaughtExceptionTestListener(v8::Handle<v8::Message>,
8249 v8::Handle<Value>) {
8250 report_count++;
8251}
8252
8253
8254// Counts uncaught exceptions, but other tests running in parallel
8255// also have uncaught exceptions.
8256TEST(ApiUncaughtException) {
ager@chromium.org8bb60582008-12-11 12:02:20 +00008257 report_count = 0;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008258 LocalContext env;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00008259 v8::Isolate* isolate = env->GetIsolate();
8260 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008261 v8::V8::AddMessageListener(ApiUncaughtExceptionTestListener);
8262
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00008263 Local<v8::FunctionTemplate> fun =
8264 v8::FunctionTemplate::New(isolate, TroubleCallback);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008265 v8::Local<v8::Object> global = env->Global();
8266 global->Set(v8_str("trouble"), fun->GetFunction());
8267
8268 Script::Compile(v8_str("function trouble_callee() {"
8269 " var x = null;"
8270 " return x.foo;"
8271 "};"
8272 "function trouble_caller() {"
8273 " trouble();"
8274 "};"))->Run();
8275 Local<Value> trouble = global->Get(v8_str("trouble"));
8276 CHECK(trouble->IsFunction());
8277 Local<Value> trouble_callee = global->Get(v8_str("trouble_callee"));
8278 CHECK(trouble_callee->IsFunction());
8279 Local<Value> trouble_caller = global->Get(v8_str("trouble_caller"));
8280 CHECK(trouble_caller->IsFunction());
8281 Function::Cast(*trouble_caller)->Call(global, 0, NULL);
8282 CHECK_EQ(1, report_count);
ager@chromium.org8bb60582008-12-11 12:02:20 +00008283 v8::V8::RemoveMessageListeners(ApiUncaughtExceptionTestListener);
8284}
8285
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00008286static const char* script_resource_name = "ExceptionInNativeScript.js";
8287static void ExceptionInNativeScriptTestListener(v8::Handle<v8::Message> message,
8288 v8::Handle<Value>) {
8289 v8::Handle<v8::Value> name_val = message->GetScriptResourceName();
8290 CHECK(!name_val.IsEmpty() && name_val->IsString());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00008291 v8::String::Utf8Value name(message->GetScriptResourceName());
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00008292 CHECK_EQ(script_resource_name, *name);
8293 CHECK_EQ(3, message->GetLineNumber());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00008294 v8::String::Utf8Value source_line(message->GetSourceLine());
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00008295 CHECK_EQ(" new o.foo();", *source_line);
8296}
8297
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00008298
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00008299TEST(ExceptionInNativeScript) {
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00008300 LocalContext env;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00008301 v8::Isolate* isolate = env->GetIsolate();
8302 v8::HandleScope scope(isolate);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00008303 v8::V8::AddMessageListener(ExceptionInNativeScriptTestListener);
8304
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00008305 Local<v8::FunctionTemplate> fun =
8306 v8::FunctionTemplate::New(isolate, TroubleCallback);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00008307 v8::Local<v8::Object> global = env->Global();
8308 global->Set(v8_str("trouble"), fun->GetFunction());
8309
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00008310 Script::Compile(
8311 v8_str(
8312 "function trouble() {\n"
8313 " var o = {};\n"
8314 " new o.foo();\n"
8315 "};"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00008316 v8::String::NewFromUtf8(isolate, script_resource_name))->Run();
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00008317 Local<Value> trouble = global->Get(v8_str("trouble"));
8318 CHECK(trouble->IsFunction());
8319 Function::Cast(*trouble)->Call(global, 0, NULL);
8320 v8::V8::RemoveMessageListeners(ExceptionInNativeScriptTestListener);
8321}
8322
ager@chromium.org8bb60582008-12-11 12:02:20 +00008323
8324TEST(CompilationErrorUsingTryCatchHandler) {
ager@chromium.org8bb60582008-12-11 12:02:20 +00008325 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008326 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org8bb60582008-12-11 12:02:20 +00008327 v8::TryCatch try_catch;
8328 Script::Compile(v8_str("This doesn't &*&@#$&*^ compile."));
8329 CHECK_NE(NULL, *try_catch.Exception());
8330 CHECK(try_catch.HasCaught());
8331}
8332
8333
8334TEST(TryCatchFinallyUsingTryCatchHandler) {
ager@chromium.org8bb60582008-12-11 12:02:20 +00008335 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008336 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org8bb60582008-12-11 12:02:20 +00008337 v8::TryCatch try_catch;
8338 Script::Compile(v8_str("try { throw ''; } catch (e) {}"))->Run();
8339 CHECK(!try_catch.HasCaught());
8340 Script::Compile(v8_str("try { throw ''; } finally {}"))->Run();
8341 CHECK(try_catch.HasCaught());
8342 try_catch.Reset();
8343 Script::Compile(v8_str("(function() {"
8344 "try { throw ''; } finally { return; }"
8345 "})()"))->Run();
8346 CHECK(!try_catch.HasCaught());
8347 Script::Compile(v8_str("(function()"
8348 " { try { throw ''; } finally { throw 0; }"
8349 "})()"))->Run();
8350 CHECK(try_catch.HasCaught());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008351}
8352
8353
8354// SecurityHandler can't be run twice
8355TEST(SecurityHandler) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00008356 v8::Isolate* isolate = CcTest::isolate();
8357 v8::HandleScope scope0(isolate);
8358 v8::Handle<v8::ObjectTemplate> global_template =
8359 v8::ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008360 global_template->SetAccessCheckCallbacks(NamedSecurityTestCallback,
8361 IndexedSecurityTestCallback);
8362 // Create an environment
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00008363 v8::Handle<Context> context0 = Context::New(isolate, NULL, global_template);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008364 context0->Enter();
8365
8366 v8::Handle<v8::Object> global0 = context0->Global();
8367 v8::Handle<Script> script0 = v8_compile("foo = 111");
8368 script0->Run();
8369 global0->Set(v8_str("0"), v8_num(999));
8370 v8::Handle<Value> foo0 = global0->Get(v8_str("foo"));
8371 CHECK_EQ(111, foo0->Int32Value());
8372 v8::Handle<Value> z0 = global0->Get(v8_str("0"));
8373 CHECK_EQ(999, z0->Int32Value());
8374
8375 // Create another environment, should fail security checks.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00008376 v8::HandleScope scope1(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008377
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008378 v8::Handle<Context> context1 =
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00008379 Context::New(isolate, NULL, global_template);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008380 context1->Enter();
8381
8382 v8::Handle<v8::Object> global1 = context1->Global();
8383 global1->Set(v8_str("othercontext"), global0);
8384 // This set will fail the security check.
8385 v8::Handle<Script> script1 =
8386 v8_compile("othercontext.foo = 222; othercontext[0] = 888;");
8387 script1->Run();
8388 // This read will pass the security check.
8389 v8::Handle<Value> foo1 = global0->Get(v8_str("foo"));
8390 CHECK_EQ(111, foo1->Int32Value());
8391 // This read will pass the security check.
8392 v8::Handle<Value> z1 = global0->Get(v8_str("0"));
8393 CHECK_EQ(999, z1->Int32Value());
8394
8395 // Create another environment, should pass security checks.
8396 { g_security_callback_result = true; // allow security handler to pass.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00008397 v8::HandleScope scope2(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008398 LocalContext context2;
8399 v8::Handle<v8::Object> global2 = context2->Global();
8400 global2->Set(v8_str("othercontext"), global0);
8401 v8::Handle<Script> script2 =
8402 v8_compile("othercontext.foo = 333; othercontext[0] = 888;");
8403 script2->Run();
8404 v8::Handle<Value> foo2 = global0->Get(v8_str("foo"));
8405 CHECK_EQ(333, foo2->Int32Value());
8406 v8::Handle<Value> z2 = global0->Get(v8_str("0"));
8407 CHECK_EQ(888, z2->Int32Value());
8408 }
8409
8410 context1->Exit();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008411 context0->Exit();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008412}
8413
8414
8415THREADED_TEST(SecurityChecks) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008416 LocalContext env1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008417 v8::HandleScope handle_scope(env1->GetIsolate());
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008418 v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008419
8420 Local<Value> foo = v8_str("foo");
8421 Local<Value> bar = v8_str("bar");
8422
8423 // Set to the same domain.
8424 env1->SetSecurityToken(foo);
8425
8426 // Create a function in env1.
8427 Script::Compile(v8_str("spy=function(){return spy;}"))->Run();
8428 Local<Value> spy = env1->Global()->Get(v8_str("spy"));
8429 CHECK(spy->IsFunction());
8430
8431 // Create another function accessing global objects.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00008432 Script::Compile(v8_str("spy2=function(){return new this.Array();}"))->Run();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008433 Local<Value> spy2 = env1->Global()->Get(v8_str("spy2"));
8434 CHECK(spy2->IsFunction());
8435
8436 // Switch to env2 in the same domain and invoke spy on env2.
8437 {
8438 env2->SetSecurityToken(foo);
8439 // Enter env2
8440 Context::Scope scope_env2(env2);
8441 Local<Value> result = Function::Cast(*spy)->Call(env2->Global(), 0, NULL);
8442 CHECK(result->IsFunction());
8443 }
8444
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008445 {
8446 env2->SetSecurityToken(bar);
8447 Context::Scope scope_env2(env2);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008448
8449 // Call cross_domain_call, it should throw an exception
8450 v8::TryCatch try_catch;
8451 Function::Cast(*spy2)->Call(env2->Global(), 0, NULL);
8452 CHECK(try_catch.HasCaught());
8453 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008454}
8455
8456
8457// Regression test case for issue 1183439.
8458THREADED_TEST(SecurityChecksForPrototypeChain) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008459 LocalContext current;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008460 v8::HandleScope scope(current->GetIsolate());
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008461 v8::Handle<Context> other = Context::New(current->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008462
8463 // Change context to be able to get to the Object function in the
8464 // other context without hitting the security checks.
8465 v8::Local<Value> other_object;
8466 { Context::Scope scope(other);
8467 other_object = other->Global()->Get(v8_str("Object"));
8468 other->Global()->Set(v8_num(42), v8_num(87));
8469 }
8470
8471 current->Global()->Set(v8_str("other"), other->Global());
8472 CHECK(v8_compile("other")->Run()->Equals(other->Global()));
8473
8474 // Make sure the security check fails here and we get an undefined
8475 // result instead of getting the Object function. Repeat in a loop
8476 // to make sure to exercise the IC code.
8477 v8::Local<Script> access_other0 = v8_compile("other.Object");
8478 v8::Local<Script> access_other1 = v8_compile("other[42]");
8479 for (int i = 0; i < 5; i++) {
8480 CHECK(!access_other0->Run()->Equals(other_object));
8481 CHECK(access_other0->Run()->IsUndefined());
8482 CHECK(!access_other1->Run()->Equals(v8_num(87)));
8483 CHECK(access_other1->Run()->IsUndefined());
8484 }
8485
8486 // Create an object that has 'other' in its prototype chain and make
8487 // sure we cannot access the Object function indirectly through
8488 // that. Repeat in a loop to make sure to exercise the IC code.
8489 v8_compile("function F() { };"
8490 "F.prototype = other;"
8491 "var f = new F();")->Run();
8492 v8::Local<Script> access_f0 = v8_compile("f.Object");
8493 v8::Local<Script> access_f1 = v8_compile("f[42]");
8494 for (int j = 0; j < 5; j++) {
8495 CHECK(!access_f0->Run()->Equals(other_object));
8496 CHECK(access_f0->Run()->IsUndefined());
8497 CHECK(!access_f1->Run()->Equals(v8_num(87)));
8498 CHECK(access_f1->Run()->IsUndefined());
8499 }
8500
8501 // Now it gets hairy: Set the prototype for the other global object
8502 // to be the current global object. The prototype chain for 'f' now
8503 // goes through 'other' but ends up in the current global object.
8504 { Context::Scope scope(other);
8505 other->Global()->Set(v8_str("__proto__"), current->Global());
8506 }
8507 // Set a named and an index property on the current global
8508 // object. To force the lookup to go through the other global object,
8509 // the properties must not exist in the other global object.
8510 current->Global()->Set(v8_str("foo"), v8_num(100));
8511 current->Global()->Set(v8_num(99), v8_num(101));
8512 // Try to read the properties from f and make sure that the access
8513 // gets stopped by the security checks on the other global object.
8514 Local<Script> access_f2 = v8_compile("f.foo");
8515 Local<Script> access_f3 = v8_compile("f[99]");
8516 for (int k = 0; k < 5; k++) {
8517 CHECK(!access_f2->Run()->Equals(v8_num(100)));
8518 CHECK(access_f2->Run()->IsUndefined());
8519 CHECK(!access_f3->Run()->Equals(v8_num(101)));
8520 CHECK(access_f3->Run()->IsUndefined());
8521 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008522}
8523
8524
8525THREADED_TEST(CrossDomainDelete) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008526 LocalContext env1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008527 v8::HandleScope handle_scope(env1->GetIsolate());
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008528 v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008529
8530 Local<Value> foo = v8_str("foo");
8531 Local<Value> bar = v8_str("bar");
8532
8533 // Set to the same domain.
8534 env1->SetSecurityToken(foo);
8535 env2->SetSecurityToken(foo);
8536
8537 env1->Global()->Set(v8_str("prop"), v8_num(3));
8538 env2->Global()->Set(v8_str("env1"), env1->Global());
8539
8540 // Change env2 to a different domain and delete env1.prop.
8541 env2->SetSecurityToken(bar);
8542 {
8543 Context::Scope scope_env2(env2);
8544 Local<Value> result =
8545 Script::Compile(v8_str("delete env1.prop"))->Run();
8546 CHECK(result->IsFalse());
8547 }
8548
8549 // Check that env1.prop still exists.
8550 Local<Value> v = env1->Global()->Get(v8_str("prop"));
8551 CHECK(v->IsNumber());
8552 CHECK_EQ(3, v->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008553}
8554
8555
ager@chromium.org870a0b62008-11-04 11:43:05 +00008556THREADED_TEST(CrossDomainIsPropertyEnumerable) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00008557 LocalContext env1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008558 v8::HandleScope handle_scope(env1->GetIsolate());
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008559 v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
ager@chromium.org870a0b62008-11-04 11:43:05 +00008560
8561 Local<Value> foo = v8_str("foo");
8562 Local<Value> bar = v8_str("bar");
8563
8564 // Set to the same domain.
8565 env1->SetSecurityToken(foo);
8566 env2->SetSecurityToken(foo);
8567
8568 env1->Global()->Set(v8_str("prop"), v8_num(3));
8569 env2->Global()->Set(v8_str("env1"), env1->Global());
8570
8571 // env1.prop is enumerable in env2.
8572 Local<String> test = v8_str("propertyIsEnumerable.call(env1, 'prop')");
8573 {
8574 Context::Scope scope_env2(env2);
8575 Local<Value> result = Script::Compile(test)->Run();
8576 CHECK(result->IsTrue());
8577 }
8578
8579 // Change env2 to a different domain and test again.
8580 env2->SetSecurityToken(bar);
8581 {
8582 Context::Scope scope_env2(env2);
8583 Local<Value> result = Script::Compile(test)->Run();
8584 CHECK(result->IsFalse());
8585 }
ager@chromium.org870a0b62008-11-04 11:43:05 +00008586}
8587
8588
ager@chromium.org236ad962008-09-25 09:45:57 +00008589THREADED_TEST(CrossDomainForIn) {
ager@chromium.org236ad962008-09-25 09:45:57 +00008590 LocalContext env1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008591 v8::HandleScope handle_scope(env1->GetIsolate());
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008592 v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
ager@chromium.org236ad962008-09-25 09:45:57 +00008593
8594 Local<Value> foo = v8_str("foo");
8595 Local<Value> bar = v8_str("bar");
8596
8597 // Set to the same domain.
8598 env1->SetSecurityToken(foo);
8599 env2->SetSecurityToken(foo);
8600
8601 env1->Global()->Set(v8_str("prop"), v8_num(3));
8602 env2->Global()->Set(v8_str("env1"), env1->Global());
8603
8604 // Change env2 to a different domain and set env1's global object
8605 // as the __proto__ of an object in env2 and enumerate properties
8606 // in for-in. It shouldn't enumerate properties on env1's global
8607 // object.
8608 env2->SetSecurityToken(bar);
8609 {
8610 Context::Scope scope_env2(env2);
8611 Local<Value> result =
8612 CompileRun("(function(){var obj = {'__proto__':env1};"
8613 "for (var p in obj)"
8614 " if (p == 'prop') return false;"
8615 "return true;})()");
8616 CHECK(result->IsTrue());
8617 }
ager@chromium.org236ad962008-09-25 09:45:57 +00008618}
8619
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008620
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00008621TEST(ContextDetachGlobal) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00008622 LocalContext env1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008623 v8::HandleScope handle_scope(env1->GetIsolate());
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008624 v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00008625
8626 Local<v8::Object> global1 = env1->Global();
8627
8628 Local<Value> foo = v8_str("foo");
8629
8630 // Set to the same domain.
8631 env1->SetSecurityToken(foo);
8632 env2->SetSecurityToken(foo);
8633
8634 // Enter env2
8635 env2->Enter();
8636
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00008637 // Create a function in env2 and add a reference to it in env1.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00008638 Local<v8::Object> global2 = env2->Global();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00008639 global2->Set(v8_str("prop"), v8::Integer::New(env2->GetIsolate(), 1));
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00008640 CompileRun("function getProp() {return prop;}");
8641
8642 env1->Global()->Set(v8_str("getProp"),
8643 global2->Get(v8_str("getProp")));
8644
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00008645 // Detach env2's global, and reuse the global object of env2
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00008646 env2->Exit();
8647 env2->DetachGlobal();
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00008648
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008649 v8::Handle<Context> env3 = Context::New(env1->GetIsolate(),
8650 0,
8651 v8::Handle<v8::ObjectTemplate>(),
8652 global2);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00008653 env3->SetSecurityToken(v8_str("bar"));
8654 env3->Enter();
8655
8656 Local<v8::Object> global3 = env3->Global();
8657 CHECK_EQ(global2, global3);
8658 CHECK(global3->Get(v8_str("prop"))->IsUndefined());
8659 CHECK(global3->Get(v8_str("getProp"))->IsUndefined());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00008660 global3->Set(v8_str("prop"), v8::Integer::New(env3->GetIsolate(), -1));
8661 global3->Set(v8_str("prop2"), v8::Integer::New(env3->GetIsolate(), 2));
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00008662 env3->Exit();
8663
8664 // Call getProp in env1, and it should return the value 1
8665 {
8666 Local<Value> get_prop = global1->Get(v8_str("getProp"));
8667 CHECK(get_prop->IsFunction());
8668 v8::TryCatch try_catch;
8669 Local<Value> r = Function::Cast(*get_prop)->Call(global1, 0, NULL);
8670 CHECK(!try_catch.HasCaught());
8671 CHECK_EQ(1, r->Int32Value());
8672 }
8673
8674 // Check that env3 is not accessible from env1
8675 {
8676 Local<Value> r = global3->Get(v8_str("prop2"));
8677 CHECK(r->IsUndefined());
8678 }
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00008679}
8680
8681
jkummerow@chromium.org113035e2013-12-13 15:13:40 +00008682TEST(DetachGlobal) {
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00008683 LocalContext env1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008684 v8::HandleScope scope(env1->GetIsolate());
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00008685
8686 // Create second environment.
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008687 v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00008688
8689 Local<Value> foo = v8_str("foo");
8690
8691 // Set same security token for env1 and env2.
8692 env1->SetSecurityToken(foo);
8693 env2->SetSecurityToken(foo);
8694
8695 // Create a property on the global object in env2.
8696 {
8697 v8::Context::Scope scope(env2);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00008698 env2->Global()->Set(v8_str("p"), v8::Integer::New(env2->GetIsolate(), 42));
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00008699 }
8700
8701 // Create a reference to env2 global from env1 global.
8702 env1->Global()->Set(v8_str("other"), env2->Global());
8703
8704 // Check that we have access to other.p in env2 from env1.
8705 Local<Value> result = CompileRun("other.p");
8706 CHECK(result->IsInt32());
8707 CHECK_EQ(42, result->Int32Value());
8708
8709 // Hold on to global from env2 and detach global from env2.
8710 Local<v8::Object> global2 = env2->Global();
8711 env2->DetachGlobal();
8712
8713 // Check that the global has been detached. No other.p property can
8714 // be found.
8715 result = CompileRun("other.p");
8716 CHECK(result->IsUndefined());
8717
8718 // Reuse global2 for env3.
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008719 v8::Handle<Context> env3 = Context::New(env1->GetIsolate(),
8720 0,
8721 v8::Handle<v8::ObjectTemplate>(),
8722 global2);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00008723 CHECK_EQ(global2, env3->Global());
8724
8725 // Start by using the same security token for env3 as for env1 and env2.
8726 env3->SetSecurityToken(foo);
8727
8728 // Create a property on the global object in env3.
8729 {
8730 v8::Context::Scope scope(env3);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00008731 env3->Global()->Set(v8_str("p"), v8::Integer::New(env3->GetIsolate(), 24));
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00008732 }
8733
8734 // Check that other.p is now the property in env3 and that we have access.
8735 result = CompileRun("other.p");
8736 CHECK(result->IsInt32());
8737 CHECK_EQ(24, result->Int32Value());
8738
8739 // Change security token for env3 to something different from env1 and env2.
8740 env3->SetSecurityToken(v8_str("bar"));
8741
8742 // Check that we do not have access to other.p in env1. |other| is now
8743 // the global object for env3 which has a different security token,
8744 // so access should be blocked.
8745 result = CompileRun("other.p");
8746 CHECK(result->IsUndefined());
jkummerow@chromium.org113035e2013-12-13 15:13:40 +00008747}
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00008748
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00008749
rossberg@chromium.org9ed27462014-01-07 14:16:41 +00008750void GetThisX(const v8::FunctionCallbackInfo<v8::Value>& info) {
8751 info.GetReturnValue().Set(
8752 info.GetIsolate()->GetCurrentContext()->Global()->Get(v8_str("x")));
8753}
8754
8755
jkummerow@chromium.org113035e2013-12-13 15:13:40 +00008756TEST(DetachedAccesses) {
8757 LocalContext env1;
8758 v8::HandleScope scope(env1->GetIsolate());
8759
8760 // Create second environment.
rossberg@chromium.org9ed27462014-01-07 14:16:41 +00008761 Local<ObjectTemplate> inner_global_template =
8762 FunctionTemplate::New(env1->GetIsolate())->InstanceTemplate();
8763 inner_global_template ->SetAccessorProperty(
8764 v8_str("this_x"), FunctionTemplate::New(env1->GetIsolate(), GetThisX));
8765 v8::Local<Context> env2 =
8766 Context::New(env1->GetIsolate(), NULL, inner_global_template);
jkummerow@chromium.org113035e2013-12-13 15:13:40 +00008767
8768 Local<Value> foo = v8_str("foo");
8769
8770 // Set same security token for env1 and env2.
8771 env1->SetSecurityToken(foo);
8772 env2->SetSecurityToken(foo);
8773
rossberg@chromium.org9ed27462014-01-07 14:16:41 +00008774 env1->Global()->Set(v8_str("x"), v8_str("env1_x"));
8775
jkummerow@chromium.org113035e2013-12-13 15:13:40 +00008776 {
8777 v8::Context::Scope scope(env2);
rossberg@chromium.org9ed27462014-01-07 14:16:41 +00008778 env2->Global()->Set(v8_str("x"), v8_str("env2_x"));
jkummerow@chromium.org113035e2013-12-13 15:13:40 +00008779 CompileRun(
rossberg@chromium.org9ed27462014-01-07 14:16:41 +00008780 "function bound_x() { return x; }"
8781 "function get_x() { return this.x; }"
8782 "function get_x_w() { return (function() {return this.x;})(); }");
8783 env1->Global()->Set(v8_str("bound_x"), CompileRun("bound_x"));
jkummerow@chromium.org113035e2013-12-13 15:13:40 +00008784 env1->Global()->Set(v8_str("get_x"), CompileRun("get_x"));
8785 env1->Global()->Set(v8_str("get_x_w"), CompileRun("get_x_w"));
rossberg@chromium.org9ed27462014-01-07 14:16:41 +00008786 env1->Global()->Set(
8787 v8_str("this_x"),
8788 CompileRun("Object.getOwnPropertyDescriptor(this, 'this_x').get"));
jkummerow@chromium.org113035e2013-12-13 15:13:40 +00008789 }
8790
8791 Local<Object> env2_global = env2->Global();
8792 env2_global->TurnOnAccessCheck();
8793 env2->DetachGlobal();
8794
8795 Local<Value> result;
rossberg@chromium.org9ed27462014-01-07 14:16:41 +00008796 result = CompileRun("bound_x()");
8797 CHECK_EQ(v8_str("env2_x"), result);
jkummerow@chromium.org113035e2013-12-13 15:13:40 +00008798 result = CompileRun("get_x()");
8799 CHECK(result->IsUndefined());
8800 result = CompileRun("get_x_w()");
8801 CHECK(result->IsUndefined());
rossberg@chromium.org9ed27462014-01-07 14:16:41 +00008802 result = CompileRun("this_x()");
8803 CHECK_EQ(v8_str("env2_x"), result);
jkummerow@chromium.org113035e2013-12-13 15:13:40 +00008804
8805 // Reattach env2's proxy
8806 env2 = Context::New(env1->GetIsolate(),
8807 0,
8808 v8::Handle<v8::ObjectTemplate>(),
8809 env2_global);
8810 env2->SetSecurityToken(foo);
8811 {
8812 v8::Context::Scope scope(env2);
rossberg@chromium.org9ed27462014-01-07 14:16:41 +00008813 env2->Global()->Set(v8_str("x"), v8_str("env3_x"));
8814 env2->Global()->Set(v8_str("env1"), env1->Global());
8815 result = CompileRun(
8816 "results = [];"
8817 "for (var i = 0; i < 4; i++ ) {"
8818 " results.push(env1.bound_x());"
8819 " results.push(env1.get_x());"
8820 " results.push(env1.get_x_w());"
8821 " results.push(env1.this_x());"
8822 "}"
8823 "results");
8824 Local<v8::Array> results = Local<v8::Array>::Cast(result);
8825 CHECK_EQ(16, results->Length());
8826 for (int i = 0; i < 16; i += 4) {
8827 CHECK_EQ(v8_str("env2_x"), results->Get(i + 0));
8828 CHECK_EQ(v8_str("env1_x"), results->Get(i + 1));
8829 CHECK_EQ(v8_str("env3_x"), results->Get(i + 2));
8830 CHECK_EQ(v8_str("env2_x"), results->Get(i + 3));
8831 }
jkummerow@chromium.org113035e2013-12-13 15:13:40 +00008832 }
8833
rossberg@chromium.org9ed27462014-01-07 14:16:41 +00008834 result = CompileRun(
8835 "results = [];"
8836 "for (var i = 0; i < 4; i++ ) {"
8837 " results.push(bound_x());"
8838 " results.push(get_x());"
8839 " results.push(get_x_w());"
8840 " results.push(this_x());"
8841 "}"
8842 "results");
8843 Local<v8::Array> results = Local<v8::Array>::Cast(result);
8844 CHECK_EQ(16, results->Length());
8845 for (int i = 0; i < 16; i += 4) {
8846 CHECK_EQ(v8_str("env2_x"), results->Get(i + 0));
8847 CHECK_EQ(v8_str("env3_x"), results->Get(i + 1));
8848 CHECK_EQ(v8_str("env3_x"), results->Get(i + 2));
8849 CHECK_EQ(v8_str("env2_x"), results->Get(i + 3));
8850 }
8851
8852 result = CompileRun(
8853 "results = [];"
8854 "for (var i = 0; i < 4; i++ ) {"
8855 " results.push(this.bound_x());"
8856 " results.push(this.get_x());"
8857 " results.push(this.get_x_w());"
8858 " results.push(this.this_x());"
8859 "}"
8860 "results");
8861 results = Local<v8::Array>::Cast(result);
8862 CHECK_EQ(16, results->Length());
8863 for (int i = 0; i < 16; i += 4) {
8864 CHECK_EQ(v8_str("env2_x"), results->Get(i + 0));
8865 CHECK_EQ(v8_str("env1_x"), results->Get(i + 1));
8866 CHECK_EQ(v8_str("env3_x"), results->Get(i + 2));
8867 CHECK_EQ(v8_str("env2_x"), results->Get(i + 3));
8868 }
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00008869}
8870
8871
ricow@chromium.org83aa5492011-02-07 12:42:56 +00008872static bool allowed_access_type[v8::ACCESS_KEYS + 1] = { false };
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008873static bool NamedAccessBlocker(Local<v8::Object> global,
8874 Local<Value> name,
8875 v8::AccessType type,
8876 Local<Value> data) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00008877 return CcTest::isolate()->GetCurrentContext()->Global()->Equals(global) ||
ricow@chromium.org83aa5492011-02-07 12:42:56 +00008878 allowed_access_type[type];
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008879}
8880
8881
8882static bool IndexedAccessBlocker(Local<v8::Object> global,
8883 uint32_t key,
8884 v8::AccessType type,
8885 Local<Value> data) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00008886 return CcTest::isolate()->GetCurrentContext()->Global()->Equals(global) ||
ricow@chromium.org83aa5492011-02-07 12:42:56 +00008887 allowed_access_type[type];
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008888}
8889
8890
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00008891static int g_echo_value_1 = -1;
8892static int g_echo_value_2 = -1;
8893
8894
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00008895static void EchoGetter(
8896 Local<String> name,
8897 const v8::PropertyCallbackInfo<v8::Value>& info) {
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00008898 info.GetReturnValue().Set(v8_num(g_echo_value_1));
8899}
8900
8901
8902static void EchoGetter(const v8::FunctionCallbackInfo<v8::Value>& info) {
8903 info.GetReturnValue().Set(v8_num(g_echo_value_2));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008904}
8905
8906
8907static void EchoSetter(Local<String> name,
8908 Local<Value> value,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00008909 const v8::PropertyCallbackInfo<void>&) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008910 if (value->IsNumber())
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00008911 g_echo_value_1 = value->Int32Value();
8912}
8913
8914
8915static void EchoSetter(const v8::FunctionCallbackInfo<v8::Value>& info) {
8916 v8::Handle<v8::Value> value = info[0];
8917 if (value->IsNumber())
8918 g_echo_value_2 = value->Int32Value();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008919}
8920
8921
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00008922static void UnreachableGetter(
8923 Local<String> name,
8924 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008925 CHECK(false); // This function should not be called..
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008926}
8927
8928
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00008929static void UnreachableSetter(Local<String>,
8930 Local<Value>,
8931 const v8::PropertyCallbackInfo<void>&) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008932 CHECK(false); // This function should nto be called.
8933}
8934
8935
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00008936static void UnreachableFunction(
8937 const v8::FunctionCallbackInfo<v8::Value>& info) {
8938 CHECK(false); // This function should not be called..
8939}
8940
8941
ricow@chromium.org83aa5492011-02-07 12:42:56 +00008942TEST(AccessControl) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00008943 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008944 v8::HandleScope handle_scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00008945 v8::Handle<v8::ObjectTemplate> global_template =
8946 v8::ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008947
8948 global_template->SetAccessCheckCallbacks(NamedAccessBlocker,
8949 IndexedAccessBlocker);
8950
8951 // Add an accessor accessible by cross-domain JS code.
8952 global_template->SetAccessor(
8953 v8_str("accessible_prop"),
8954 EchoGetter, EchoSetter,
8955 v8::Handle<Value>(),
8956 v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
8957
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00008958
8959 global_template->SetAccessorProperty(
8960 v8_str("accessible_js_prop"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00008961 v8::FunctionTemplate::New(isolate, EchoGetter),
8962 v8::FunctionTemplate::New(isolate, EchoSetter),
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00008963 v8::None,
8964 v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
8965
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008966 // Add an accessor that is not accessible by cross-domain JS code.
ager@chromium.org870a0b62008-11-04 11:43:05 +00008967 global_template->SetAccessor(v8_str("blocked_prop"),
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008968 UnreachableGetter, UnreachableSetter,
8969 v8::Handle<Value>(),
8970 v8::DEFAULT);
8971
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00008972 global_template->SetAccessorProperty(
8973 v8_str("blocked_js_prop"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00008974 v8::FunctionTemplate::New(isolate, UnreachableFunction),
8975 v8::FunctionTemplate::New(isolate, UnreachableFunction),
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00008976 v8::None,
8977 v8::DEFAULT);
8978
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008979 // Create an environment
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008980 v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008981 context0->Enter();
8982
8983 v8::Handle<v8::Object> global0 = context0->Global();
8984
ricow@chromium.org83aa5492011-02-07 12:42:56 +00008985 // Define a property with JS getter and setter.
8986 CompileRun(
8987 "function getter() { return 'getter'; };\n"
8988 "function setter() { return 'setter'; }\n"
8989 "Object.defineProperty(this, 'js_accessor_p', {get:getter, set:setter})");
8990
8991 Local<Value> getter = global0->Get(v8_str("getter"));
8992 Local<Value> setter = global0->Get(v8_str("setter"));
8993
8994 // And define normal element.
8995 global0->Set(239, v8_str("239"));
8996
8997 // Define an element with JS getter and setter.
8998 CompileRun(
8999 "function el_getter() { return 'el_getter'; };\n"
9000 "function el_setter() { return 'el_setter'; };\n"
9001 "Object.defineProperty(this, '42', {get: el_getter, set: el_setter});");
9002
9003 Local<Value> el_getter = global0->Get(v8_str("el_getter"));
9004 Local<Value> el_setter = global0->Get(v8_str("el_setter"));
9005
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009006 v8::HandleScope scope1(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009007
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009008 v8::Local<Context> context1 = Context::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009009 context1->Enter();
9010
9011 v8::Handle<v8::Object> global1 = context1->Global();
9012 global1->Set(v8_str("other"), global0);
9013
ricow@chromium.org83aa5492011-02-07 12:42:56 +00009014 // Access blocked property.
9015 CompileRun("other.blocked_prop = 1");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009016
ricow@chromium.org83aa5492011-02-07 12:42:56 +00009017 ExpectUndefined("other.blocked_prop");
9018 ExpectUndefined(
9019 "Object.getOwnPropertyDescriptor(other, 'blocked_prop')");
9020 ExpectFalse("propertyIsEnumerable.call(other, 'blocked_prop')");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009021
ricow@chromium.org83aa5492011-02-07 12:42:56 +00009022 // Enable ACCESS_HAS
9023 allowed_access_type[v8::ACCESS_HAS] = true;
9024 ExpectUndefined("other.blocked_prop");
9025 // ... and now we can get the descriptor...
9026 ExpectUndefined(
antonm@chromium.orgdca01352011-01-31 17:15:05 +00009027 "Object.getOwnPropertyDescriptor(other, 'blocked_prop').value");
ricow@chromium.org83aa5492011-02-07 12:42:56 +00009028 // ... and enumerate the property.
9029 ExpectTrue("propertyIsEnumerable.call(other, 'blocked_prop')");
9030 allowed_access_type[v8::ACCESS_HAS] = false;
antonm@chromium.orgdca01352011-01-31 17:15:05 +00009031
ricow@chromium.org83aa5492011-02-07 12:42:56 +00009032 // Access blocked element.
9033 CompileRun("other[239] = 1");
9034
9035 ExpectUndefined("other[239]");
9036 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '239')");
9037 ExpectFalse("propertyIsEnumerable.call(other, '239')");
9038
9039 // Enable ACCESS_HAS
9040 allowed_access_type[v8::ACCESS_HAS] = true;
9041 ExpectUndefined("other[239]");
9042 // ... and now we can get the descriptor...
9043 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '239').value");
9044 // ... and enumerate the property.
9045 ExpectTrue("propertyIsEnumerable.call(other, '239')");
9046 allowed_access_type[v8::ACCESS_HAS] = false;
9047
9048 // Access a property with JS accessor.
9049 CompileRun("other.js_accessor_p = 2");
9050
9051 ExpectUndefined("other.js_accessor_p");
9052 ExpectUndefined(
9053 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p')");
9054
9055 // Enable ACCESS_HAS.
9056 allowed_access_type[v8::ACCESS_HAS] = true;
9057 ExpectUndefined("other.js_accessor_p");
9058 ExpectUndefined(
9059 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get");
9060 ExpectUndefined(
9061 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set");
9062 ExpectUndefined(
9063 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
9064 allowed_access_type[v8::ACCESS_HAS] = false;
9065
9066 // Enable both ACCESS_HAS and ACCESS_GET.
9067 allowed_access_type[v8::ACCESS_HAS] = true;
9068 allowed_access_type[v8::ACCESS_GET] = true;
9069
9070 ExpectString("other.js_accessor_p", "getter");
9071 ExpectObject(
9072 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get", getter);
9073 ExpectUndefined(
9074 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set");
9075 ExpectUndefined(
9076 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
9077
9078 allowed_access_type[v8::ACCESS_GET] = false;
9079 allowed_access_type[v8::ACCESS_HAS] = false;
9080
9081 // Enable both ACCESS_HAS and ACCESS_SET.
9082 allowed_access_type[v8::ACCESS_HAS] = true;
9083 allowed_access_type[v8::ACCESS_SET] = true;
9084
9085 ExpectUndefined("other.js_accessor_p");
9086 ExpectUndefined(
9087 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get");
9088 ExpectObject(
9089 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set", setter);
9090 ExpectUndefined(
9091 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
9092
9093 allowed_access_type[v8::ACCESS_SET] = false;
9094 allowed_access_type[v8::ACCESS_HAS] = false;
9095
9096 // Enable both ACCESS_HAS, ACCESS_GET and ACCESS_SET.
9097 allowed_access_type[v8::ACCESS_HAS] = true;
9098 allowed_access_type[v8::ACCESS_GET] = true;
9099 allowed_access_type[v8::ACCESS_SET] = true;
9100
9101 ExpectString("other.js_accessor_p", "getter");
9102 ExpectObject(
9103 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get", getter);
9104 ExpectObject(
9105 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set", setter);
9106 ExpectUndefined(
9107 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
9108
9109 allowed_access_type[v8::ACCESS_SET] = false;
9110 allowed_access_type[v8::ACCESS_GET] = false;
9111 allowed_access_type[v8::ACCESS_HAS] = false;
9112
9113 // Access an element with JS accessor.
9114 CompileRun("other[42] = 2");
9115
9116 ExpectUndefined("other[42]");
9117 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42')");
9118
9119 // Enable ACCESS_HAS.
9120 allowed_access_type[v8::ACCESS_HAS] = true;
9121 ExpectUndefined("other[42]");
9122 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').get");
9123 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').set");
9124 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
9125 allowed_access_type[v8::ACCESS_HAS] = false;
9126
9127 // Enable both ACCESS_HAS and ACCESS_GET.
9128 allowed_access_type[v8::ACCESS_HAS] = true;
9129 allowed_access_type[v8::ACCESS_GET] = true;
9130
9131 ExpectString("other[42]", "el_getter");
9132 ExpectObject("Object.getOwnPropertyDescriptor(other, '42').get", el_getter);
9133 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').set");
9134 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
9135
9136 allowed_access_type[v8::ACCESS_GET] = false;
9137 allowed_access_type[v8::ACCESS_HAS] = false;
9138
9139 // Enable both ACCESS_HAS and ACCESS_SET.
9140 allowed_access_type[v8::ACCESS_HAS] = true;
9141 allowed_access_type[v8::ACCESS_SET] = true;
9142
9143 ExpectUndefined("other[42]");
9144 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').get");
9145 ExpectObject("Object.getOwnPropertyDescriptor(other, '42').set", el_setter);
9146 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
9147
9148 allowed_access_type[v8::ACCESS_SET] = false;
9149 allowed_access_type[v8::ACCESS_HAS] = false;
9150
9151 // Enable both ACCESS_HAS, ACCESS_GET and ACCESS_SET.
9152 allowed_access_type[v8::ACCESS_HAS] = true;
9153 allowed_access_type[v8::ACCESS_GET] = true;
9154 allowed_access_type[v8::ACCESS_SET] = true;
9155
9156 ExpectString("other[42]", "el_getter");
9157 ExpectObject("Object.getOwnPropertyDescriptor(other, '42').get", el_getter);
9158 ExpectObject("Object.getOwnPropertyDescriptor(other, '42').set", el_setter);
9159 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
9160
9161 allowed_access_type[v8::ACCESS_SET] = false;
9162 allowed_access_type[v8::ACCESS_GET] = false;
9163 allowed_access_type[v8::ACCESS_HAS] = false;
9164
9165 v8::Handle<Value> value;
ager@chromium.org870a0b62008-11-04 11:43:05 +00009166
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009167 // Access accessible property
antonm@chromium.orgdca01352011-01-31 17:15:05 +00009168 value = CompileRun("other.accessible_prop = 3");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009169 CHECK(value->IsNumber());
9170 CHECK_EQ(3, value->Int32Value());
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00009171 CHECK_EQ(3, g_echo_value_1);
9172
9173 // Access accessible js property
9174 value = CompileRun("other.accessible_js_prop = 3");
9175 CHECK(value->IsNumber());
9176 CHECK_EQ(3, value->Int32Value());
9177 CHECK_EQ(3, g_echo_value_2);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009178
antonm@chromium.orgdca01352011-01-31 17:15:05 +00009179 value = CompileRun("other.accessible_prop");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009180 CHECK(value->IsNumber());
9181 CHECK_EQ(3, value->Int32Value());
9182
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00009183 value = CompileRun("other.accessible_js_prop");
9184 CHECK(value->IsNumber());
9185 CHECK_EQ(3, value->Int32Value());
9186
antonm@chromium.orgdca01352011-01-31 17:15:05 +00009187 value = CompileRun(
9188 "Object.getOwnPropertyDescriptor(other, 'accessible_prop').value");
9189 CHECK(value->IsNumber());
9190 CHECK_EQ(3, value->Int32Value());
9191
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00009192 value = CompileRun(
9193 "Object.getOwnPropertyDescriptor(other, 'accessible_js_prop').get()");
9194 CHECK(value->IsNumber());
9195 CHECK_EQ(3, value->Int32Value());
9196
antonm@chromium.orgdca01352011-01-31 17:15:05 +00009197 value = CompileRun("propertyIsEnumerable.call(other, 'accessible_prop')");
ager@chromium.org870a0b62008-11-04 11:43:05 +00009198 CHECK(value->IsTrue());
9199
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00009200 value = CompileRun("propertyIsEnumerable.call(other, 'accessible_js_prop')");
9201 CHECK(value->IsTrue());
9202
ager@chromium.org870a0b62008-11-04 11:43:05 +00009203 // Enumeration doesn't enumerate accessors from inaccessible objects in
9204 // the prototype chain even if the accessors are in themselves accessible.
antonm@chromium.orgdca01352011-01-31 17:15:05 +00009205 value =
ager@chromium.org870a0b62008-11-04 11:43:05 +00009206 CompileRun("(function(){var obj = {'__proto__':other};"
9207 "for (var p in obj)"
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00009208 " if (p == 'accessible_prop' ||"
9209 " p == 'accessible_js_prop' ||"
9210 " p == 'blocked_js_prop' ||"
9211 " p == 'blocked_js_prop') {"
ager@chromium.org870a0b62008-11-04 11:43:05 +00009212 " return false;"
9213 " }"
9214 "return true;})()");
antonm@chromium.orgdca01352011-01-31 17:15:05 +00009215 CHECK(value->IsTrue());
ager@chromium.org870a0b62008-11-04 11:43:05 +00009216
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009217 context1->Exit();
9218 context0->Exit();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009219}
9220
9221
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00009222TEST(AccessControlES5) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00009223 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009224 v8::HandleScope handle_scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00009225 v8::Handle<v8::ObjectTemplate> global_template =
9226 v8::ObjectTemplate::New(isolate);
ricow@chromium.org65001782011-02-15 13:36:41 +00009227
9228 global_template->SetAccessCheckCallbacks(NamedAccessBlocker,
9229 IndexedAccessBlocker);
9230
ricow@chromium.orgf5a18a22011-03-15 10:00:20 +00009231 // Add accessible accessor.
9232 global_template->SetAccessor(
9233 v8_str("accessible_prop"),
9234 EchoGetter, EchoSetter,
9235 v8::Handle<Value>(),
9236 v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
9237
9238
ricow@chromium.org65001782011-02-15 13:36:41 +00009239 // Add an accessor that is not accessible by cross-domain JS code.
9240 global_template->SetAccessor(v8_str("blocked_prop"),
9241 UnreachableGetter, UnreachableSetter,
9242 v8::Handle<Value>(),
9243 v8::DEFAULT);
9244
9245 // Create an environment
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009246 v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
ricow@chromium.org65001782011-02-15 13:36:41 +00009247 context0->Enter();
9248
9249 v8::Handle<v8::Object> global0 = context0->Global();
9250
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009251 v8::Local<Context> context1 = Context::New(isolate);
ricow@chromium.org65001782011-02-15 13:36:41 +00009252 context1->Enter();
9253 v8::Handle<v8::Object> global1 = context1->Global();
9254 global1->Set(v8_str("other"), global0);
9255
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00009256 // Regression test for issue 1154.
ricow@chromium.org65001782011-02-15 13:36:41 +00009257 ExpectTrue("Object.keys(other).indexOf('blocked_prop') == -1");
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00009258
9259 ExpectUndefined("other.blocked_prop");
9260
9261 // Regression test for issue 1027.
9262 CompileRun("Object.defineProperty(\n"
9263 " other, 'blocked_prop', {configurable: false})");
9264 ExpectUndefined("other.blocked_prop");
9265 ExpectUndefined(
9266 "Object.getOwnPropertyDescriptor(other, 'blocked_prop')");
9267
9268 // Regression test for issue 1171.
9269 ExpectTrue("Object.isExtensible(other)");
9270 CompileRun("Object.preventExtensions(other)");
9271 ExpectTrue("Object.isExtensible(other)");
9272
9273 // Object.seal and Object.freeze.
9274 CompileRun("Object.freeze(other)");
9275 ExpectTrue("Object.isExtensible(other)");
9276
9277 CompileRun("Object.seal(other)");
9278 ExpectTrue("Object.isExtensible(other)");
ricow@chromium.orgf5a18a22011-03-15 10:00:20 +00009279
9280 // Regression test for issue 1250.
9281 // Make sure that we can set the accessible accessors value using normal
9282 // assignment.
9283 CompileRun("other.accessible_prop = 42");
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00009284 CHECK_EQ(42, g_echo_value_1);
ricow@chromium.orgf5a18a22011-03-15 10:00:20 +00009285
9286 v8::Handle<Value> value;
9287 // We follow Safari in ignoring assignments to host object accessors.
9288 CompileRun("Object.defineProperty(other, 'accessible_prop', {value: -1})");
9289 value = CompileRun("other.accessible_prop == 42");
9290 CHECK(value->IsTrue());
ricow@chromium.org65001782011-02-15 13:36:41 +00009291}
9292
9293
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00009294static bool GetOwnPropertyNamesNamedBlocker(Local<v8::Object> global,
9295 Local<Value> name,
9296 v8::AccessType type,
9297 Local<Value> data) {
9298 return false;
9299}
9300
9301
9302static bool GetOwnPropertyNamesIndexedBlocker(Local<v8::Object> global,
9303 uint32_t key,
9304 v8::AccessType type,
9305 Local<Value> data) {
9306 return false;
9307}
9308
9309
9310THREADED_TEST(AccessControlGetOwnPropertyNames) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00009311 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009312 v8::HandleScope handle_scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00009313 v8::Handle<v8::ObjectTemplate> obj_template =
9314 v8::ObjectTemplate::New(isolate);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00009315
ulan@chromium.org0f13e742014-01-03 15:51:11 +00009316 obj_template->Set(v8_str("x"), v8::Integer::New(isolate, 42));
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00009317 obj_template->SetAccessCheckCallbacks(GetOwnPropertyNamesNamedBlocker,
9318 GetOwnPropertyNamesIndexedBlocker);
9319
9320 // Create an environment
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009321 v8::Local<Context> context0 = Context::New(isolate, NULL, obj_template);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00009322 context0->Enter();
9323
9324 v8::Handle<v8::Object> global0 = context0->Global();
9325
machenbach@chromium.org528ce022013-09-23 14:09:36 +00009326 v8::HandleScope scope1(CcTest::isolate());
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00009327
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009328 v8::Local<Context> context1 = Context::New(isolate);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00009329 context1->Enter();
9330
9331 v8::Handle<v8::Object> global1 = context1->Global();
9332 global1->Set(v8_str("other"), global0);
9333 global1->Set(v8_str("object"), obj_template->NewInstance());
9334
9335 v8::Handle<Value> value;
9336
9337 // Attempt to get the property names of the other global object and
9338 // of an object that requires access checks. Accessing the other
9339 // global object should be blocked by access checks on the global
9340 // proxy object. Accessing the object that requires access checks
9341 // is blocked by the access checks on the object itself.
9342 value = CompileRun("Object.getOwnPropertyNames(other).length == 0");
9343 CHECK(value->IsTrue());
9344
9345 value = CompileRun("Object.getOwnPropertyNames(object).length == 0");
9346 CHECK(value->IsTrue());
9347
9348 context1->Exit();
9349 context0->Exit();
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00009350}
9351
9352
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009353static void IndexedPropertyEnumerator(
9354 const v8::PropertyCallbackInfo<v8::Array>& info) {
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00009355 v8::Handle<v8::Array> result = v8::Array::New(info.GetIsolate(), 2);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00009356 result->Set(0, v8::Integer::New(info.GetIsolate(), 7));
9357 result->Set(1, v8::Object::New(info.GetIsolate()));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009358 info.GetReturnValue().Set(result);
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00009359}
9360
9361
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009362static void NamedPropertyEnumerator(
9363 const v8::PropertyCallbackInfo<v8::Array>& info) {
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00009364 v8::Handle<v8::Array> result = v8::Array::New(info.GetIsolate(), 2);
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00009365 result->Set(0, v8_str("x"));
ulan@chromium.org0f13e742014-01-03 15:51:11 +00009366 result->Set(1, v8::Object::New(info.GetIsolate()));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009367 info.GetReturnValue().Set(result);
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00009368}
9369
9370
9371THREADED_TEST(GetOwnPropertyNamesWithInterceptor) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00009372 v8::Isolate* isolate = CcTest::isolate();
9373 v8::HandleScope handle_scope(isolate);
9374 v8::Handle<v8::ObjectTemplate> obj_template =
9375 v8::ObjectTemplate::New(isolate);
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00009376
ulan@chromium.org0f13e742014-01-03 15:51:11 +00009377 obj_template->Set(v8_str("7"), v8::Integer::New(CcTest::isolate(), 7));
9378 obj_template->Set(v8_str("x"), v8::Integer::New(CcTest::isolate(), 42));
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00009379 obj_template->SetIndexedPropertyHandler(NULL, NULL, NULL, NULL,
9380 IndexedPropertyEnumerator);
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00009381 obj_template->SetNamedPropertyHandler(NULL, NULL, NULL, NULL,
9382 NamedPropertyEnumerator);
9383
9384 LocalContext context;
9385 v8::Handle<v8::Object> global = context->Global();
9386 global->Set(v8_str("object"), obj_template->NewInstance());
9387
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00009388 v8::Handle<v8::Value> result =
9389 CompileRun("Object.getOwnPropertyNames(object)");
9390 CHECK(result->IsArray());
9391 v8::Handle<v8::Array> result_array = v8::Handle<v8::Array>::Cast(result);
9392 CHECK_EQ(3, result_array->Length());
9393 CHECK(result_array->Get(0)->IsString());
9394 CHECK(result_array->Get(1)->IsString());
9395 CHECK(result_array->Get(2)->IsString());
9396 CHECK_EQ(v8_str("7"), result_array->Get(0));
9397 CHECK_EQ(v8_str("[object Object]"), result_array->Get(1));
9398 CHECK_EQ(v8_str("x"), result_array->Get(2));
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00009399}
9400
9401
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009402static void ConstTenGetter(Local<String> name,
9403 const v8::PropertyCallbackInfo<v8::Value>& info) {
9404 info.GetReturnValue().Set(v8_num(10));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009405}
9406
9407
9408THREADED_TEST(CrossDomainAccessors) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00009409 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009410 v8::HandleScope handle_scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009411
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00009412 v8::Handle<v8::FunctionTemplate> func_template =
9413 v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009414
9415 v8::Handle<v8::ObjectTemplate> global_template =
9416 func_template->InstanceTemplate();
9417
9418 v8::Handle<v8::ObjectTemplate> proto_template =
9419 func_template->PrototypeTemplate();
9420
9421 // Add an accessor to proto that's accessible by cross-domain JS code.
9422 proto_template->SetAccessor(v8_str("accessible"),
9423 ConstTenGetter, 0,
9424 v8::Handle<Value>(),
9425 v8::ALL_CAN_READ);
9426
9427 // Add an accessor that is not accessible by cross-domain JS code.
9428 global_template->SetAccessor(v8_str("unreachable"),
9429 UnreachableGetter, 0,
9430 v8::Handle<Value>(),
9431 v8::DEFAULT);
9432
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009433 v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009434 context0->Enter();
9435
9436 Local<v8::Object> global = context0->Global();
9437 // Add a normal property that shadows 'accessible'
9438 global->Set(v8_str("accessible"), v8_num(11));
9439
9440 // Enter a new context.
machenbach@chromium.org528ce022013-09-23 14:09:36 +00009441 v8::HandleScope scope1(CcTest::isolate());
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009442 v8::Local<Context> context1 = Context::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009443 context1->Enter();
9444
9445 v8::Handle<v8::Object> global1 = context1->Global();
9446 global1->Set(v8_str("other"), global);
9447
9448 // Should return 10, instead of 11
9449 v8::Handle<Value> value = v8_compile("other.accessible")->Run();
9450 CHECK(value->IsNumber());
9451 CHECK_EQ(10, value->Int32Value());
9452
9453 value = v8_compile("other.unreachable")->Run();
9454 CHECK(value->IsUndefined());
9455
9456 context1->Exit();
9457 context0->Exit();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009458}
9459
9460
9461static int named_access_count = 0;
9462static int indexed_access_count = 0;
9463
9464static bool NamedAccessCounter(Local<v8::Object> global,
9465 Local<Value> name,
9466 v8::AccessType type,
9467 Local<Value> data) {
9468 named_access_count++;
9469 return true;
9470}
9471
9472
9473static bool IndexedAccessCounter(Local<v8::Object> global,
9474 uint32_t key,
9475 v8::AccessType type,
9476 Local<Value> data) {
9477 indexed_access_count++;
9478 return true;
9479}
9480
9481
9482// This one is too easily disturbed by other tests.
9483TEST(AccessControlIC) {
9484 named_access_count = 0;
9485 indexed_access_count = 0;
9486
machenbach@chromium.org528ce022013-09-23 14:09:36 +00009487 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009488 v8::HandleScope handle_scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009489
9490 // Create an environment.
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009491 v8::Local<Context> context0 = Context::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009492 context0->Enter();
9493
9494 // Create an object that requires access-check functions to be
9495 // called for cross-domain access.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00009496 v8::Handle<v8::ObjectTemplate> object_template =
9497 v8::ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009498 object_template->SetAccessCheckCallbacks(NamedAccessCounter,
9499 IndexedAccessCounter);
9500 Local<v8::Object> object = object_template->NewInstance();
9501
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009502 v8::HandleScope scope1(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009503
9504 // Create another environment.
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009505 v8::Local<Context> context1 = Context::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009506 context1->Enter();
9507
9508 // Make easy access to the object from the other environment.
9509 v8::Handle<v8::Object> global1 = context1->Global();
9510 global1->Set(v8_str("obj"), object);
9511
9512 v8::Handle<Value> value;
9513
9514 // Check that the named access-control function is called every time.
ager@chromium.org8bb60582008-12-11 12:02:20 +00009515 CompileRun("function testProp(obj) {"
9516 " for (var i = 0; i < 10; i++) obj.prop = 1;"
9517 " for (var j = 0; j < 10; j++) obj.prop;"
9518 " return obj.prop"
9519 "}");
9520 value = CompileRun("testProp(obj)");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009521 CHECK(value->IsNumber());
9522 CHECK_EQ(1, value->Int32Value());
9523 CHECK_EQ(21, named_access_count);
9524
9525 // Check that the named access-control function is called every time.
ager@chromium.org8bb60582008-12-11 12:02:20 +00009526 CompileRun("var p = 'prop';"
9527 "function testKeyed(obj) {"
9528 " for (var i = 0; i < 10; i++) obj[p] = 1;"
9529 " for (var j = 0; j < 10; j++) obj[p];"
9530 " return obj[p];"
9531 "}");
9532 // Use obj which requires access checks. No inline caching is used
9533 // in that case.
9534 value = CompileRun("testKeyed(obj)");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009535 CHECK(value->IsNumber());
9536 CHECK_EQ(1, value->Int32Value());
9537 CHECK_EQ(42, named_access_count);
ager@chromium.org8bb60582008-12-11 12:02:20 +00009538 // Force the inline caches into generic state and try again.
9539 CompileRun("testKeyed({ a: 0 })");
9540 CompileRun("testKeyed({ b: 0 })");
9541 value = CompileRun("testKeyed(obj)");
9542 CHECK(value->IsNumber());
9543 CHECK_EQ(1, value->Int32Value());
9544 CHECK_EQ(63, named_access_count);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009545
9546 // Check that the indexed access-control function is called every time.
ager@chromium.org8bb60582008-12-11 12:02:20 +00009547 CompileRun("function testIndexed(obj) {"
9548 " for (var i = 0; i < 10; i++) obj[0] = 1;"
9549 " for (var j = 0; j < 10; j++) obj[0];"
9550 " return obj[0]"
9551 "}");
9552 value = CompileRun("testIndexed(obj)");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009553 CHECK(value->IsNumber());
9554 CHECK_EQ(1, value->Int32Value());
9555 CHECK_EQ(21, indexed_access_count);
ager@chromium.org8bb60582008-12-11 12:02:20 +00009556 // Force the inline caches into generic state.
9557 CompileRun("testIndexed(new Array(1))");
9558 // Test that the indexed access check is called.
9559 value = CompileRun("testIndexed(obj)");
9560 CHECK(value->IsNumber());
9561 CHECK_EQ(1, value->Int32Value());
9562 CHECK_EQ(42, indexed_access_count);
9563
9564 // Check that the named access check is called when invoking
9565 // functions on an object that requires access checks.
9566 CompileRun("obj.f = function() {}");
9567 CompileRun("function testCallNormal(obj) {"
9568 " for (var i = 0; i < 10; i++) obj.f();"
9569 "}");
9570 CompileRun("testCallNormal(obj)");
9571 CHECK_EQ(74, named_access_count);
9572
9573 // Force obj into slow case.
9574 value = CompileRun("delete obj.prop");
9575 CHECK(value->BooleanValue());
9576 // Force inline caches into dictionary probing mode.
9577 CompileRun("var o = { x: 0 }; delete o.x; testProp(o);");
9578 // Test that the named access check is called.
9579 value = CompileRun("testProp(obj);");
9580 CHECK(value->IsNumber());
9581 CHECK_EQ(1, value->Int32Value());
9582 CHECK_EQ(96, named_access_count);
9583
9584 // Force the call inline cache into dictionary probing mode.
9585 CompileRun("o.f = function() {}; testCallNormal(o)");
9586 // Test that the named access check is still called for each
9587 // invocation of the function.
9588 value = CompileRun("testCallNormal(obj)");
9589 CHECK_EQ(106, named_access_count);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009590
9591 context1->Exit();
9592 context0->Exit();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009593}
9594
9595
9596static bool NamedAccessFlatten(Local<v8::Object> global,
9597 Local<Value> name,
9598 v8::AccessType type,
9599 Local<Value> data) {
9600 char buf[100];
9601 int len;
9602
9603 CHECK(name->IsString());
9604
9605 memset(buf, 0x1, sizeof(buf));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009606 len = name.As<String>()->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009607 CHECK_EQ(4, len);
9608
9609 uint16_t buf2[100];
9610
9611 memset(buf, 0x1, sizeof(buf));
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00009612 len = name.As<String>()->Write(buf2);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009613 CHECK_EQ(4, len);
9614
9615 return true;
9616}
9617
9618
9619static bool IndexedAccessFlatten(Local<v8::Object> global,
9620 uint32_t key,
9621 v8::AccessType type,
9622 Local<Value> data) {
9623 return true;
9624}
9625
9626
9627// Regression test. In access checks, operations that may cause
9628// garbage collection are not allowed. It used to be the case that
9629// using the Write operation on a string could cause a garbage
9630// collection due to flattening of the string. This is no longer the
9631// case.
9632THREADED_TEST(AccessControlFlatten) {
9633 named_access_count = 0;
9634 indexed_access_count = 0;
9635
machenbach@chromium.org528ce022013-09-23 14:09:36 +00009636 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009637 v8::HandleScope handle_scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009638
9639 // Create an environment.
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009640 v8::Local<Context> context0 = Context::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009641 context0->Enter();
9642
9643 // Create an object that requires access-check functions to be
9644 // called for cross-domain access.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00009645 v8::Handle<v8::ObjectTemplate> object_template =
9646 v8::ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009647 object_template->SetAccessCheckCallbacks(NamedAccessFlatten,
9648 IndexedAccessFlatten);
9649 Local<v8::Object> object = object_template->NewInstance();
9650
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009651 v8::HandleScope scope1(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009652
9653 // Create another environment.
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009654 v8::Local<Context> context1 = Context::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009655 context1->Enter();
9656
9657 // Make easy access to the object from the other environment.
9658 v8::Handle<v8::Object> global1 = context1->Global();
9659 global1->Set(v8_str("obj"), object);
9660
9661 v8::Handle<Value> value;
9662
9663 value = v8_compile("var p = 'as' + 'df';")->Run();
9664 value = v8_compile("obj[p];")->Run();
9665
9666 context1->Exit();
9667 context0->Exit();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009668}
9669
9670
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009671static void AccessControlNamedGetter(
9672 Local<String>,
9673 const v8::PropertyCallbackInfo<v8::Value>& info) {
9674 info.GetReturnValue().Set(42);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009675}
9676
9677
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009678static void AccessControlNamedSetter(
9679 Local<String>,
9680 Local<Value> value,
9681 const v8::PropertyCallbackInfo<v8::Value>& info) {
9682 info.GetReturnValue().Set(value);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009683}
9684
9685
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009686static void AccessControlIndexedGetter(
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009687 uint32_t index,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009688 const v8::PropertyCallbackInfo<v8::Value>& info) {
9689 info.GetReturnValue().Set(v8_num(42));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009690}
9691
9692
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009693static void AccessControlIndexedSetter(
9694 uint32_t,
9695 Local<Value> value,
9696 const v8::PropertyCallbackInfo<v8::Value>& info) {
9697 info.GetReturnValue().Set(value);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009698}
9699
9700
9701THREADED_TEST(AccessControlInterceptorIC) {
9702 named_access_count = 0;
9703 indexed_access_count = 0;
9704
machenbach@chromium.org528ce022013-09-23 14:09:36 +00009705 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009706 v8::HandleScope handle_scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009707
9708 // Create an environment.
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009709 v8::Local<Context> context0 = Context::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009710 context0->Enter();
9711
9712 // Create an object that requires access-check functions to be
9713 // called for cross-domain access. The object also has interceptors
9714 // interceptor.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00009715 v8::Handle<v8::ObjectTemplate> object_template =
9716 v8::ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009717 object_template->SetAccessCheckCallbacks(NamedAccessCounter,
9718 IndexedAccessCounter);
9719 object_template->SetNamedPropertyHandler(AccessControlNamedGetter,
9720 AccessControlNamedSetter);
9721 object_template->SetIndexedPropertyHandler(AccessControlIndexedGetter,
9722 AccessControlIndexedSetter);
9723 Local<v8::Object> object = object_template->NewInstance();
9724
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009725 v8::HandleScope scope1(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009726
9727 // Create another environment.
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009728 v8::Local<Context> context1 = Context::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009729 context1->Enter();
9730
9731 // Make easy access to the object from the other environment.
9732 v8::Handle<v8::Object> global1 = context1->Global();
9733 global1->Set(v8_str("obj"), object);
9734
9735 v8::Handle<Value> value;
9736
9737 // Check that the named access-control function is called every time
9738 // eventhough there is an interceptor on the object.
9739 value = v8_compile("for (var i = 0; i < 10; i++) obj.x = 1;")->Run();
9740 value = v8_compile("for (var i = 0; i < 10; i++) obj.x;"
9741 "obj.x")->Run();
9742 CHECK(value->IsNumber());
9743 CHECK_EQ(42, value->Int32Value());
9744 CHECK_EQ(21, named_access_count);
9745
9746 value = v8_compile("var p = 'x';")->Run();
9747 value = v8_compile("for (var i = 0; i < 10; i++) obj[p] = 1;")->Run();
9748 value = v8_compile("for (var i = 0; i < 10; i++) obj[p];"
9749 "obj[p]")->Run();
9750 CHECK(value->IsNumber());
9751 CHECK_EQ(42, value->Int32Value());
9752 CHECK_EQ(42, named_access_count);
9753
9754 // Check that the indexed access-control function is called every
9755 // time eventhough there is an interceptor on the object.
9756 value = v8_compile("for (var i = 0; i < 10; i++) obj[0] = 1;")->Run();
9757 value = v8_compile("for (var i = 0; i < 10; i++) obj[0];"
9758 "obj[0]")->Run();
9759 CHECK(value->IsNumber());
9760 CHECK_EQ(42, value->Int32Value());
9761 CHECK_EQ(21, indexed_access_count);
9762
9763 context1->Exit();
9764 context0->Exit();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009765}
9766
9767
9768THREADED_TEST(Version) {
9769 v8::V8::GetVersion();
9770}
9771
9772
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009773static void InstanceFunctionCallback(
9774 const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009775 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009776 args.GetReturnValue().Set(v8_num(12));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009777}
9778
9779
9780THREADED_TEST(InstanceProperties) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009781 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00009782 v8::Isolate* isolate = context->GetIsolate();
9783 v8::HandleScope handle_scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009784
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00009785 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009786 Local<ObjectTemplate> instance = t->InstanceTemplate();
9787
9788 instance->Set(v8_str("x"), v8_num(42));
9789 instance->Set(v8_str("f"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00009790 v8::FunctionTemplate::New(isolate, InstanceFunctionCallback));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009791
9792 Local<Value> o = t->GetFunction()->NewInstance();
9793
9794 context->Global()->Set(v8_str("i"), o);
9795 Local<Value> value = Script::Compile(v8_str("i.x"))->Run();
9796 CHECK_EQ(42, value->Int32Value());
9797
9798 value = Script::Compile(v8_str("i.f()"))->Run();
9799 CHECK_EQ(12, value->Int32Value());
9800}
9801
9802
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009803static void GlobalObjectInstancePropertiesGet(
9804 Local<String> key,
9805 const v8::PropertyCallbackInfo<v8::Value>&) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009806 ApiTestFuzzer::Fuzz();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009807}
9808
9809
9810THREADED_TEST(GlobalObjectInstanceProperties) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00009811 v8::Isolate* isolate = CcTest::isolate();
9812 v8::HandleScope handle_scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009813
9814 Local<Value> global_object;
9815
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00009816 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009817 t->InstanceTemplate()->SetNamedPropertyHandler(
9818 GlobalObjectInstancePropertiesGet);
9819 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
9820 instance_template->Set(v8_str("x"), v8_num(42));
9821 instance_template->Set(v8_str("f"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00009822 v8::FunctionTemplate::New(isolate,
9823 InstanceFunctionCallback));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009824
kasperl@chromium.orga5551262010-12-07 12:49:48 +00009825 // The script to check how Crankshaft compiles missing global function
9826 // invocations. function g is not defined and should throw on call.
9827 const char* script =
9828 "function wrapper(call) {"
9829 " var x = 0, y = 1;"
9830 " for (var i = 0; i < 1000; i++) {"
9831 " x += i * 100;"
9832 " y += i * 100;"
9833 " }"
9834 " if (call) g();"
9835 "}"
9836 "for (var i = 0; i < 17; i++) wrapper(false);"
9837 "var thrown = 0;"
9838 "try { wrapper(true); } catch (e) { thrown = 1; };"
9839 "thrown";
9840
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009841 {
9842 LocalContext env(NULL, instance_template);
9843 // Hold on to the global object so it can be used again in another
9844 // environment initialization.
9845 global_object = env->Global();
9846
9847 Local<Value> value = Script::Compile(v8_str("x"))->Run();
9848 CHECK_EQ(42, value->Int32Value());
9849 value = Script::Compile(v8_str("f()"))->Run();
9850 CHECK_EQ(12, value->Int32Value());
kasperl@chromium.orga5551262010-12-07 12:49:48 +00009851 value = Script::Compile(v8_str(script))->Run();
9852 CHECK_EQ(1, value->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009853 }
9854
9855 {
9856 // Create new environment reusing the global object.
9857 LocalContext env(NULL, instance_template, global_object);
9858 Local<Value> value = Script::Compile(v8_str("x"))->Run();
9859 CHECK_EQ(42, value->Int32Value());
9860 value = Script::Compile(v8_str("f()"))->Run();
9861 CHECK_EQ(12, value->Int32Value());
kasperl@chromium.orga5551262010-12-07 12:49:48 +00009862 value = Script::Compile(v8_str(script))->Run();
9863 CHECK_EQ(1, value->Int32Value());
9864 }
9865}
9866
9867
9868THREADED_TEST(CallKnownGlobalReceiver) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00009869 v8::Isolate* isolate = CcTest::isolate();
9870 v8::HandleScope handle_scope(isolate);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00009871
9872 Local<Value> global_object;
9873
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00009874 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00009875 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
9876
9877 // The script to check that we leave global object not
9878 // global object proxy on stack when we deoptimize from inside
9879 // arguments evaluation.
9880 // To provoke error we need to both force deoptimization
9881 // from arguments evaluation and to force CallIC to take
9882 // CallIC_Miss code path that can't cope with global proxy.
9883 const char* script =
9884 "function bar(x, y) { try { } finally { } }"
9885 "function baz(x) { try { } finally { } }"
9886 "function bom(x) { try { } finally { } }"
9887 "function foo(x) { bar([x], bom(2)); }"
9888 "for (var i = 0; i < 10000; i++) foo(1);"
9889 "foo";
9890
9891 Local<Value> foo;
9892 {
9893 LocalContext env(NULL, instance_template);
9894 // Hold on to the global object so it can be used again in another
9895 // environment initialization.
9896 global_object = env->Global();
9897 foo = Script::Compile(v8_str(script))->Run();
9898 }
9899
9900 {
9901 // Create new environment reusing the global object.
9902 LocalContext env(NULL, instance_template, global_object);
9903 env->Global()->Set(v8_str("foo"), foo);
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00009904 Script::Compile(v8_str("foo()"))->Run();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009905 }
9906}
9907
9908
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009909static void ShadowFunctionCallback(
9910 const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009911 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009912 args.GetReturnValue().Set(v8_num(42));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009913}
9914
9915
9916static int shadow_y;
9917static int shadow_y_setter_call_count;
9918static int shadow_y_getter_call_count;
9919
9920
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009921static void ShadowYSetter(Local<String>,
9922 Local<Value>,
9923 const v8::PropertyCallbackInfo<void>&) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009924 shadow_y_setter_call_count++;
9925 shadow_y = 42;
9926}
9927
9928
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009929static void ShadowYGetter(Local<String> name,
9930 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009931 ApiTestFuzzer::Fuzz();
9932 shadow_y_getter_call_count++;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009933 info.GetReturnValue().Set(v8_num(shadow_y));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009934}
9935
9936
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009937static void ShadowIndexedGet(uint32_t index,
9938 const v8::PropertyCallbackInfo<v8::Value>&) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009939}
9940
9941
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009942static void ShadowNamedGet(Local<String> key,
9943 const v8::PropertyCallbackInfo<v8::Value>&) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009944}
9945
9946
9947THREADED_TEST(ShadowObject) {
9948 shadow_y = shadow_y_setter_call_count = shadow_y_getter_call_count = 0;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00009949 v8::Isolate* isolate = CcTest::isolate();
9950 v8::HandleScope handle_scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009951
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00009952 Local<ObjectTemplate> global_template = v8::ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009953 LocalContext context(NULL, global_template);
9954
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00009955 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009956 t->InstanceTemplate()->SetNamedPropertyHandler(ShadowNamedGet);
9957 t->InstanceTemplate()->SetIndexedPropertyHandler(ShadowIndexedGet);
9958 Local<ObjectTemplate> proto = t->PrototypeTemplate();
9959 Local<ObjectTemplate> instance = t->InstanceTemplate();
9960
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009961 proto->Set(v8_str("f"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00009962 v8::FunctionTemplate::New(isolate,
9963 ShadowFunctionCallback,
9964 Local<Value>()));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009965 proto->Set(v8_str("x"), v8_num(12));
9966
9967 instance->SetAccessor(v8_str("y"), ShadowYGetter, ShadowYSetter);
9968
9969 Local<Value> o = t->GetFunction()->NewInstance();
9970 context->Global()->Set(v8_str("__proto__"), o);
9971
9972 Local<Value> value =
ricow@chromium.orgd2be9012011-06-01 06:00:58 +00009973 Script::Compile(v8_str("this.propertyIsEnumerable(0)"))->Run();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009974 CHECK(value->IsBoolean());
9975 CHECK(!value->BooleanValue());
9976
9977 value = Script::Compile(v8_str("x"))->Run();
9978 CHECK_EQ(12, value->Int32Value());
9979
9980 value = Script::Compile(v8_str("f()"))->Run();
9981 CHECK_EQ(42, value->Int32Value());
9982
mmassi@chromium.org7028c052012-06-13 11:51:58 +00009983 Script::Compile(v8_str("y = 43"))->Run();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009984 CHECK_EQ(1, shadow_y_setter_call_count);
9985 value = Script::Compile(v8_str("y"))->Run();
9986 CHECK_EQ(1, shadow_y_getter_call_count);
9987 CHECK_EQ(42, value->Int32Value());
9988}
9989
9990
9991THREADED_TEST(HiddenPrototype) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009992 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00009993 v8::Isolate* isolate = context->GetIsolate();
9994 v8::HandleScope handle_scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009995
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00009996 Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009997 t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00009998 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009999 t1->SetHiddenPrototype(true);
10000 t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010001 Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010002 t2->SetHiddenPrototype(true);
10003 t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010004 Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010005 t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
10006
10007 Local<v8::Object> o0 = t0->GetFunction()->NewInstance();
10008 Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
10009 Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
10010 Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
10011
10012 // Setting the prototype on an object skips hidden prototypes.
10013 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
10014 o0->Set(v8_str("__proto__"), o1);
10015 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
10016 CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
10017 o0->Set(v8_str("__proto__"), o2);
10018 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
10019 CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
10020 CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
10021 o0->Set(v8_str("__proto__"), o3);
10022 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
10023 CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
10024 CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
10025 CHECK_EQ(3, o0->Get(v8_str("u"))->Int32Value());
10026
10027 // Getting the prototype of o0 should get the first visible one
10028 // which is o3. Therefore, z should not be defined on the prototype
10029 // object.
10030 Local<Value> proto = o0->Get(v8_str("__proto__"));
10031 CHECK(proto->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000010032 CHECK(proto.As<v8::Object>()->Get(v8_str("z"))->IsUndefined());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010033}
10034
10035
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000010036THREADED_TEST(HiddenPrototypeSet) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000010037 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010038 v8::Isolate* isolate = context->GetIsolate();
10039 v8::HandleScope handle_scope(isolate);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000010040
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010041 Local<v8::FunctionTemplate> ot = v8::FunctionTemplate::New(isolate);
10042 Local<v8::FunctionTemplate> ht = v8::FunctionTemplate::New(isolate);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000010043 ht->SetHiddenPrototype(true);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010044 Local<v8::FunctionTemplate> pt = v8::FunctionTemplate::New(isolate);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000010045 ht->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
10046
10047 Local<v8::Object> o = ot->GetFunction()->NewInstance();
10048 Local<v8::Object> h = ht->GetFunction()->NewInstance();
10049 Local<v8::Object> p = pt->GetFunction()->NewInstance();
10050 o->Set(v8_str("__proto__"), h);
10051 h->Set(v8_str("__proto__"), p);
10052
10053 // Setting a property that exists on the hidden prototype goes there.
10054 o->Set(v8_str("x"), v8_num(7));
10055 CHECK_EQ(7, o->Get(v8_str("x"))->Int32Value());
10056 CHECK_EQ(7, h->Get(v8_str("x"))->Int32Value());
10057 CHECK(p->Get(v8_str("x"))->IsUndefined());
10058
10059 // Setting a new property should not be forwarded to the hidden prototype.
10060 o->Set(v8_str("y"), v8_num(6));
10061 CHECK_EQ(6, o->Get(v8_str("y"))->Int32Value());
10062 CHECK(h->Get(v8_str("y"))->IsUndefined());
10063 CHECK(p->Get(v8_str("y"))->IsUndefined());
10064
10065 // Setting a property that only exists on a prototype of the hidden prototype
10066 // is treated normally again.
10067 p->Set(v8_str("z"), v8_num(8));
10068 CHECK_EQ(8, o->Get(v8_str("z"))->Int32Value());
10069 CHECK_EQ(8, h->Get(v8_str("z"))->Int32Value());
10070 CHECK_EQ(8, p->Get(v8_str("z"))->Int32Value());
10071 o->Set(v8_str("z"), v8_num(9));
10072 CHECK_EQ(9, o->Get(v8_str("z"))->Int32Value());
10073 CHECK_EQ(8, h->Get(v8_str("z"))->Int32Value());
10074 CHECK_EQ(8, p->Get(v8_str("z"))->Int32Value());
10075}
10076
10077
10078// Regression test for issue 2457.
10079THREADED_TEST(HiddenPrototypeIdentityHash) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000010080 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000010081 v8::HandleScope handle_scope(context->GetIsolate());
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000010082
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010083 Handle<FunctionTemplate> t = FunctionTemplate::New(context->GetIsolate());
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000010084 t->SetHiddenPrototype(true);
10085 t->InstanceTemplate()->Set(v8_str("foo"), v8_num(75));
10086 Handle<Object> p = t->GetFunction()->NewInstance();
ulan@chromium.org0f13e742014-01-03 15:51:11 +000010087 Handle<Object> o = Object::New(context->GetIsolate());
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000010088 o->SetPrototype(p);
10089
10090 int hash = o->GetIdentityHash();
10091 USE(hash);
10092 o->Set(v8_str("foo"), v8_num(42));
10093 ASSERT_EQ(hash, o->GetIdentityHash());
10094}
10095
10096
ager@chromium.org5c838252010-02-19 08:53:10 +000010097THREADED_TEST(SetPrototype) {
ager@chromium.org5c838252010-02-19 08:53:10 +000010098 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010099 v8::Isolate* isolate = context->GetIsolate();
10100 v8::HandleScope handle_scope(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +000010101
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010102 Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +000010103 t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010104 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +000010105 t1->SetHiddenPrototype(true);
10106 t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010107 Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +000010108 t2->SetHiddenPrototype(true);
10109 t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010110 Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +000010111 t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
10112
10113 Local<v8::Object> o0 = t0->GetFunction()->NewInstance();
10114 Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
10115 Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
10116 Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
10117
10118 // Setting the prototype on an object does not skip hidden prototypes.
10119 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
10120 CHECK(o0->SetPrototype(o1));
10121 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
10122 CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
10123 CHECK(o1->SetPrototype(o2));
10124 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
10125 CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
10126 CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
10127 CHECK(o2->SetPrototype(o3));
10128 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
10129 CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
10130 CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
10131 CHECK_EQ(3, o0->Get(v8_str("u"))->Int32Value());
10132
10133 // Getting the prototype of o0 should get the first visible one
10134 // which is o3. Therefore, z should not be defined on the prototype
10135 // object.
10136 Local<Value> proto = o0->Get(v8_str("__proto__"));
10137 CHECK(proto->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000010138 CHECK_EQ(proto.As<v8::Object>(), o3);
ager@chromium.org5c838252010-02-19 08:53:10 +000010139
10140 // However, Object::GetPrototype ignores hidden prototype.
10141 Local<Value> proto0 = o0->GetPrototype();
10142 CHECK(proto0->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000010143 CHECK_EQ(proto0.As<v8::Object>(), o1);
ager@chromium.org5c838252010-02-19 08:53:10 +000010144
10145 Local<Value> proto1 = o1->GetPrototype();
10146 CHECK(proto1->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000010147 CHECK_EQ(proto1.As<v8::Object>(), o2);
ager@chromium.org5c838252010-02-19 08:53:10 +000010148
10149 Local<Value> proto2 = o2->GetPrototype();
10150 CHECK(proto2->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000010151 CHECK_EQ(proto2.As<v8::Object>(), o3);
ager@chromium.org5c838252010-02-19 08:53:10 +000010152}
10153
10154
ricow@chromium.org27bf2882011-11-17 08:34:43 +000010155// Getting property names of an object with a prototype chain that
10156// triggers dictionary elements in GetLocalPropertyNames() shouldn't
10157// crash the runtime.
10158THREADED_TEST(Regress91517) {
10159 i::FLAG_allow_natives_syntax = true;
ricow@chromium.org27bf2882011-11-17 08:34:43 +000010160 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010161 v8::Isolate* isolate = context->GetIsolate();
10162 v8::HandleScope handle_scope(isolate);
ricow@chromium.org27bf2882011-11-17 08:34:43 +000010163
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010164 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
ricow@chromium.org27bf2882011-11-17 08:34:43 +000010165 t1->SetHiddenPrototype(true);
10166 t1->InstanceTemplate()->Set(v8_str("foo"), v8_num(1));
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010167 Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
ricow@chromium.org27bf2882011-11-17 08:34:43 +000010168 t2->SetHiddenPrototype(true);
10169 t2->InstanceTemplate()->Set(v8_str("fuz1"), v8_num(2));
ulan@chromium.org0f13e742014-01-03 15:51:11 +000010170 t2->InstanceTemplate()->Set(v8_str("objects"), v8::Object::New(isolate));
ricow@chromium.org27bf2882011-11-17 08:34:43 +000010171 t2->InstanceTemplate()->Set(v8_str("fuz2"), v8_num(2));
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010172 Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
ricow@chromium.org27bf2882011-11-17 08:34:43 +000010173 t3->SetHiddenPrototype(true);
10174 t3->InstanceTemplate()->Set(v8_str("boo"), v8_num(3));
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010175 Local<v8::FunctionTemplate> t4 = v8::FunctionTemplate::New(isolate);
ricow@chromium.org27bf2882011-11-17 08:34:43 +000010176 t4->InstanceTemplate()->Set(v8_str("baz"), v8_num(4));
10177
10178 // Force dictionary-based properties.
10179 i::ScopedVector<char> name_buf(1024);
10180 for (int i = 1; i <= 1000; i++) {
10181 i::OS::SNPrintF(name_buf, "sdf%d", i);
10182 t2->InstanceTemplate()->Set(v8_str(name_buf.start()), v8_num(2));
10183 }
10184
10185 Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
10186 Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
10187 Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
10188 Local<v8::Object> o4 = t4->GetFunction()->NewInstance();
10189
10190 // Create prototype chain of hidden prototypes.
10191 CHECK(o4->SetPrototype(o3));
10192 CHECK(o3->SetPrototype(o2));
10193 CHECK(o2->SetPrototype(o1));
10194
10195 // Call the runtime version of GetLocalPropertyNames() on the natively
10196 // created object through JavaScript.
10197 context->Global()->Set(v8_str("obj"), o4);
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +000010198 CompileRun("var names = %GetLocalPropertyNames(obj, true);");
ricow@chromium.org27bf2882011-11-17 08:34:43 +000010199
10200 ExpectInt32("names.length", 1006);
10201 ExpectTrue("names.indexOf(\"baz\") >= 0");
10202 ExpectTrue("names.indexOf(\"boo\") >= 0");
10203 ExpectTrue("names.indexOf(\"foo\") >= 0");
10204 ExpectTrue("names.indexOf(\"fuz1\") >= 0");
10205 ExpectTrue("names.indexOf(\"fuz2\") >= 0");
10206 ExpectFalse("names[1005] == undefined");
10207}
10208
10209
ulan@chromium.org0f13e742014-01-03 15:51:11 +000010210// Getting property names of an object with a hidden and inherited
10211// prototype should not duplicate the accessor properties inherited.
10212THREADED_TEST(Regress269562) {
10213 i::FLAG_allow_natives_syntax = true;
10214 LocalContext context;
10215 v8::HandleScope handle_scope(context->GetIsolate());
10216
10217 Local<v8::FunctionTemplate> t1 =
10218 v8::FunctionTemplate::New(context->GetIsolate());
10219 t1->SetHiddenPrototype(true);
10220
10221 Local<v8::ObjectTemplate> i1 = t1->InstanceTemplate();
10222 i1->SetAccessor(v8_str("foo"),
10223 SimpleAccessorGetter, SimpleAccessorSetter);
10224 i1->SetAccessor(v8_str("bar"),
10225 SimpleAccessorGetter, SimpleAccessorSetter);
10226 i1->SetAccessor(v8_str("baz"),
10227 SimpleAccessorGetter, SimpleAccessorSetter);
10228 i1->Set(v8_str("n1"), v8_num(1));
10229 i1->Set(v8_str("n2"), v8_num(2));
10230
10231 Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
10232 Local<v8::FunctionTemplate> t2 =
10233 v8::FunctionTemplate::New(context->GetIsolate());
10234 t2->SetHiddenPrototype(true);
10235
10236 // Inherit from t1 and mark prototype as hidden.
10237 t2->Inherit(t1);
10238 t2->InstanceTemplate()->Set(v8_str("mine"), v8_num(4));
10239
10240 Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
10241 CHECK(o2->SetPrototype(o1));
10242
10243 v8::Local<v8::Symbol> sym = v8::Symbol::New(context->GetIsolate(), "s1");
10244 o1->Set(sym, v8_num(3));
10245 o1->SetHiddenValue(v8_str("h1"),
10246 v8::Integer::New(context->GetIsolate(), 2013));
10247
10248 // Call the runtime version of GetLocalPropertyNames() on
10249 // the natively created object through JavaScript.
10250 context->Global()->Set(v8_str("obj"), o2);
10251 context->Global()->Set(v8_str("sym"), sym);
10252 CompileRun("var names = %GetLocalPropertyNames(obj, true);");
10253
10254 ExpectInt32("names.length", 7);
10255 ExpectTrue("names.indexOf(\"foo\") >= 0");
10256 ExpectTrue("names.indexOf(\"bar\") >= 0");
10257 ExpectTrue("names.indexOf(\"baz\") >= 0");
10258 ExpectTrue("names.indexOf(\"n1\") >= 0");
10259 ExpectTrue("names.indexOf(\"n2\") >= 0");
10260 ExpectTrue("names.indexOf(sym) >= 0");
10261 ExpectTrue("names.indexOf(\"mine\") >= 0");
10262}
10263
10264
ricow@chromium.org2c99e282011-07-28 09:15:17 +000010265THREADED_TEST(FunctionReadOnlyPrototype) {
ager@chromium.org04921a82011-06-27 13:21:41 +000010266 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010267 v8::Isolate* isolate = context->GetIsolate();
10268 v8::HandleScope handle_scope(isolate);
ager@chromium.org04921a82011-06-27 13:21:41 +000010269
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010270 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000010271 t1->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(isolate, 42));
ricow@chromium.org2c99e282011-07-28 09:15:17 +000010272 t1->ReadOnlyPrototype();
ager@chromium.org04921a82011-06-27 13:21:41 +000010273 context->Global()->Set(v8_str("func1"), t1->GetFunction());
ricow@chromium.org2c99e282011-07-28 09:15:17 +000010274 // Configured value of ReadOnly flag.
ager@chromium.org04921a82011-06-27 13:21:41 +000010275 CHECK(CompileRun(
10276 "(function() {"
10277 " descriptor = Object.getOwnPropertyDescriptor(func1, 'prototype');"
ricow@chromium.org2c99e282011-07-28 09:15:17 +000010278 " return (descriptor['writable'] == false);"
ager@chromium.org04921a82011-06-27 13:21:41 +000010279 "})()")->BooleanValue());
ricow@chromium.org2c99e282011-07-28 09:15:17 +000010280 CHECK_EQ(42, CompileRun("func1.prototype.x")->Int32Value());
10281 CHECK_EQ(42,
10282 CompileRun("func1.prototype = {}; func1.prototype.x")->Int32Value());
ager@chromium.org04921a82011-06-27 13:21:41 +000010283
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010284 Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000010285 t2->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(isolate, 42));
ager@chromium.org04921a82011-06-27 13:21:41 +000010286 context->Global()->Set(v8_str("func2"), t2->GetFunction());
ricow@chromium.org2c99e282011-07-28 09:15:17 +000010287 // Default value of ReadOnly flag.
ager@chromium.org04921a82011-06-27 13:21:41 +000010288 CHECK(CompileRun(
10289 "(function() {"
10290 " descriptor = Object.getOwnPropertyDescriptor(func2, 'prototype');"
ricow@chromium.org2c99e282011-07-28 09:15:17 +000010291 " return (descriptor['writable'] == true);"
ager@chromium.org04921a82011-06-27 13:21:41 +000010292 "})()")->BooleanValue());
ricow@chromium.org2c99e282011-07-28 09:15:17 +000010293 CHECK_EQ(42, CompileRun("func2.prototype.x")->Int32Value());
ager@chromium.org04921a82011-06-27 13:21:41 +000010294}
10295
10296
ager@chromium.org5c838252010-02-19 08:53:10 +000010297THREADED_TEST(SetPrototypeThrows) {
ager@chromium.org5c838252010-02-19 08:53:10 +000010298 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010299 v8::Isolate* isolate = context->GetIsolate();
10300 v8::HandleScope handle_scope(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +000010301
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010302 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +000010303
10304 Local<v8::Object> o0 = t->GetFunction()->NewInstance();
10305 Local<v8::Object> o1 = t->GetFunction()->NewInstance();
10306
10307 CHECK(o0->SetPrototype(o1));
10308 // If setting the prototype leads to the cycle, SetPrototype should
10309 // return false and keep VM in sane state.
10310 v8::TryCatch try_catch;
10311 CHECK(!o1->SetPrototype(o0));
10312 CHECK(!try_catch.HasCaught());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000010313 ASSERT(!CcTest::i_isolate()->has_pending_exception());
ager@chromium.org5c838252010-02-19 08:53:10 +000010314
10315 CHECK_EQ(42, CompileRun("function f() { return 42; }; f()")->Int32Value());
10316}
10317
10318
verwaest@chromium.org662436e2013-08-28 08:41:27 +000010319THREADED_TEST(FunctionRemovePrototype) {
10320 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010321 v8::Isolate* isolate = context->GetIsolate();
10322 v8::HandleScope handle_scope(isolate);
verwaest@chromium.org662436e2013-08-28 08:41:27 +000010323
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010324 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
verwaest@chromium.org662436e2013-08-28 08:41:27 +000010325 t1->RemovePrototype();
10326 Local<v8::Function> fun = t1->GetFunction();
10327 context->Global()->Set(v8_str("fun"), fun);
10328 CHECK(!CompileRun("'prototype' in fun")->BooleanValue());
10329
10330 v8::TryCatch try_catch;
10331 CompileRun("new fun()");
10332 CHECK(try_catch.HasCaught());
10333
10334 try_catch.Reset();
10335 fun->NewInstance();
10336 CHECK(try_catch.HasCaught());
10337}
10338
10339
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010340THREADED_TEST(GetterSetterExceptions) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010341 LocalContext context;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000010342 v8::Isolate* isolate = context->GetIsolate();
10343 v8::HandleScope handle_scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010344 CompileRun(
10345 "function Foo() { };"
10346 "function Throw() { throw 5; };"
10347 "var x = { };"
10348 "x.__defineSetter__('set', Throw);"
10349 "x.__defineGetter__('get', Throw);");
10350 Local<v8::Object> x =
10351 Local<v8::Object>::Cast(context->Global()->Get(v8_str("x")));
10352 v8::TryCatch try_catch;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000010353 x->Set(v8_str("set"), v8::Integer::New(isolate, 8));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010354 x->Get(v8_str("get"));
ulan@chromium.org0f13e742014-01-03 15:51:11 +000010355 x->Set(v8_str("set"), v8::Integer::New(isolate, 8));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010356 x->Get(v8_str("get"));
ulan@chromium.org0f13e742014-01-03 15:51:11 +000010357 x->Set(v8_str("set"), v8::Integer::New(isolate, 8));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010358 x->Get(v8_str("get"));
ulan@chromium.org0f13e742014-01-03 15:51:11 +000010359 x->Set(v8_str("set"), v8::Integer::New(isolate, 8));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010360 x->Get(v8_str("get"));
10361}
10362
10363
10364THREADED_TEST(Constructor) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010365 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010366 v8::Isolate* isolate = context->GetIsolate();
10367 v8::HandleScope handle_scope(isolate);
10368 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010369 templ->SetClassName(v8_str("Fun"));
10370 Local<Function> cons = templ->GetFunction();
10371 context->Global()->Set(v8_str("Fun"), cons);
10372 Local<v8::Object> inst = cons->NewInstance();
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000010373 i::Handle<i::JSObject> obj(v8::Utils::OpenHandle(*inst));
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000010374 CHECK(obj->IsJSObject());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010375 Local<Value> value = CompileRun("(new Fun()).constructor === Fun");
10376 CHECK(value->BooleanValue());
10377}
10378
lrn@chromium.org1c092762011-05-09 09:42:16 +000010379
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010380static void ConstructorCallback(
10381 const v8::FunctionCallbackInfo<v8::Value>& args) {
lrn@chromium.org1c092762011-05-09 09:42:16 +000010382 ApiTestFuzzer::Fuzz();
10383 Local<Object> This;
10384
10385 if (args.IsConstructCall()) {
10386 Local<Object> Holder = args.Holder();
ulan@chromium.org0f13e742014-01-03 15:51:11 +000010387 This = Object::New(args.GetIsolate());
lrn@chromium.org1c092762011-05-09 09:42:16 +000010388 Local<Value> proto = Holder->GetPrototype();
10389 if (proto->IsObject()) {
10390 This->SetPrototype(proto);
10391 }
10392 } else {
10393 This = args.This();
10394 }
10395
10396 This->Set(v8_str("a"), args[0]);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010397 args.GetReturnValue().Set(This);
lrn@chromium.org1c092762011-05-09 09:42:16 +000010398}
10399
10400
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010401static void FakeConstructorCallback(
10402 const v8::FunctionCallbackInfo<v8::Value>& args) {
lrn@chromium.org1c092762011-05-09 09:42:16 +000010403 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010404 args.GetReturnValue().Set(args[0]);
lrn@chromium.org1c092762011-05-09 09:42:16 +000010405}
10406
10407
10408THREADED_TEST(ConstructorForObject) {
lrn@chromium.org1c092762011-05-09 09:42:16 +000010409 LocalContext context;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000010410 v8::Isolate* isolate = context->GetIsolate();
10411 v8::HandleScope handle_scope(isolate);
lrn@chromium.org1c092762011-05-09 09:42:16 +000010412
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000010413 { Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
lrn@chromium.org1c092762011-05-09 09:42:16 +000010414 instance_template->SetCallAsFunctionHandler(ConstructorCallback);
10415 Local<Object> instance = instance_template->NewInstance();
10416 context->Global()->Set(v8_str("obj"), instance);
10417 v8::TryCatch try_catch;
10418 Local<Value> value;
10419 CHECK(!try_catch.HasCaught());
10420
10421 // Call the Object's constructor with a 32-bit signed integer.
10422 value = CompileRun("(function() { var o = new obj(28); return o.a; })()");
10423 CHECK(!try_catch.HasCaught());
10424 CHECK(value->IsInt32());
10425 CHECK_EQ(28, value->Int32Value());
10426
10427 Local<Value> args1[] = { v8_num(28) };
10428 Local<Value> value_obj1 = instance->CallAsConstructor(1, args1);
10429 CHECK(value_obj1->IsObject());
10430 Local<Object> object1 = Local<Object>::Cast(value_obj1);
10431 value = object1->Get(v8_str("a"));
10432 CHECK(value->IsInt32());
10433 CHECK(!try_catch.HasCaught());
10434 CHECK_EQ(28, value->Int32Value());
10435
10436 // Call the Object's constructor with a String.
10437 value = CompileRun(
10438 "(function() { var o = new obj('tipli'); return o.a; })()");
10439 CHECK(!try_catch.HasCaught());
10440 CHECK(value->IsString());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000010441 String::Utf8Value string_value1(value->ToString());
lrn@chromium.org1c092762011-05-09 09:42:16 +000010442 CHECK_EQ("tipli", *string_value1);
10443
10444 Local<Value> args2[] = { v8_str("tipli") };
10445 Local<Value> value_obj2 = instance->CallAsConstructor(1, args2);
10446 CHECK(value_obj2->IsObject());
10447 Local<Object> object2 = Local<Object>::Cast(value_obj2);
10448 value = object2->Get(v8_str("a"));
10449 CHECK(!try_catch.HasCaught());
10450 CHECK(value->IsString());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000010451 String::Utf8Value string_value2(value->ToString());
lrn@chromium.org1c092762011-05-09 09:42:16 +000010452 CHECK_EQ("tipli", *string_value2);
10453
10454 // Call the Object's constructor with a Boolean.
10455 value = CompileRun("(function() { var o = new obj(true); return o.a; })()");
10456 CHECK(!try_catch.HasCaught());
10457 CHECK(value->IsBoolean());
10458 CHECK_EQ(true, value->BooleanValue());
10459
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000010460 Handle<Value> args3[] = { v8::True(isolate) };
lrn@chromium.org1c092762011-05-09 09:42:16 +000010461 Local<Value> value_obj3 = instance->CallAsConstructor(1, args3);
10462 CHECK(value_obj3->IsObject());
10463 Local<Object> object3 = Local<Object>::Cast(value_obj3);
10464 value = object3->Get(v8_str("a"));
10465 CHECK(!try_catch.HasCaught());
10466 CHECK(value->IsBoolean());
10467 CHECK_EQ(true, value->BooleanValue());
10468
10469 // Call the Object's constructor with undefined.
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000010470 Handle<Value> args4[] = { v8::Undefined(isolate) };
lrn@chromium.org1c092762011-05-09 09:42:16 +000010471 Local<Value> value_obj4 = instance->CallAsConstructor(1, args4);
10472 CHECK(value_obj4->IsObject());
10473 Local<Object> object4 = Local<Object>::Cast(value_obj4);
10474 value = object4->Get(v8_str("a"));
10475 CHECK(!try_catch.HasCaught());
10476 CHECK(value->IsUndefined());
10477
10478 // Call the Object's constructor with null.
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000010479 Handle<Value> args5[] = { v8::Null(isolate) };
lrn@chromium.org1c092762011-05-09 09:42:16 +000010480 Local<Value> value_obj5 = instance->CallAsConstructor(1, args5);
10481 CHECK(value_obj5->IsObject());
10482 Local<Object> object5 = Local<Object>::Cast(value_obj5);
10483 value = object5->Get(v8_str("a"));
10484 CHECK(!try_catch.HasCaught());
10485 CHECK(value->IsNull());
10486 }
10487
10488 // Check exception handling when there is no constructor set for the Object.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000010489 { Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
lrn@chromium.org1c092762011-05-09 09:42:16 +000010490 Local<Object> instance = instance_template->NewInstance();
10491 context->Global()->Set(v8_str("obj2"), instance);
10492 v8::TryCatch try_catch;
10493 Local<Value> value;
10494 CHECK(!try_catch.HasCaught());
10495
10496 value = CompileRun("new obj2(28)");
10497 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000010498 String::Utf8Value exception_value1(try_catch.Exception());
lrn@chromium.org1c092762011-05-09 09:42:16 +000010499 CHECK_EQ("TypeError: object is not a function", *exception_value1);
10500 try_catch.Reset();
10501
10502 Local<Value> args[] = { v8_num(29) };
10503 value = instance->CallAsConstructor(1, args);
10504 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000010505 String::Utf8Value exception_value2(try_catch.Exception());
lrn@chromium.org1c092762011-05-09 09:42:16 +000010506 CHECK_EQ("TypeError: #<Object> is not a function", *exception_value2);
10507 try_catch.Reset();
10508 }
10509
10510 // Check the case when constructor throws exception.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000010511 { Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
lrn@chromium.org1c092762011-05-09 09:42:16 +000010512 instance_template->SetCallAsFunctionHandler(ThrowValue);
10513 Local<Object> instance = instance_template->NewInstance();
10514 context->Global()->Set(v8_str("obj3"), instance);
10515 v8::TryCatch try_catch;
10516 Local<Value> value;
10517 CHECK(!try_catch.HasCaught());
10518
10519 value = CompileRun("new obj3(22)");
10520 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000010521 String::Utf8Value exception_value1(try_catch.Exception());
lrn@chromium.org1c092762011-05-09 09:42:16 +000010522 CHECK_EQ("22", *exception_value1);
10523 try_catch.Reset();
10524
10525 Local<Value> args[] = { v8_num(23) };
10526 value = instance->CallAsConstructor(1, args);
10527 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000010528 String::Utf8Value exception_value2(try_catch.Exception());
lrn@chromium.org1c092762011-05-09 09:42:16 +000010529 CHECK_EQ("23", *exception_value2);
10530 try_catch.Reset();
10531 }
10532
10533 // Check whether constructor returns with an object or non-object.
10534 { Local<FunctionTemplate> function_template =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010535 FunctionTemplate::New(isolate, FakeConstructorCallback);
lrn@chromium.org1c092762011-05-09 09:42:16 +000010536 Local<Function> function = function_template->GetFunction();
10537 Local<Object> instance1 = function;
10538 context->Global()->Set(v8_str("obj4"), instance1);
10539 v8::TryCatch try_catch;
10540 Local<Value> value;
10541 CHECK(!try_catch.HasCaught());
10542
10543 CHECK(instance1->IsObject());
10544 CHECK(instance1->IsFunction());
10545
10546 value = CompileRun("new obj4(28)");
10547 CHECK(!try_catch.HasCaught());
10548 CHECK(value->IsObject());
10549
10550 Local<Value> args1[] = { v8_num(28) };
10551 value = instance1->CallAsConstructor(1, args1);
10552 CHECK(!try_catch.HasCaught());
10553 CHECK(value->IsObject());
10554
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000010555 Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
lrn@chromium.org1c092762011-05-09 09:42:16 +000010556 instance_template->SetCallAsFunctionHandler(FakeConstructorCallback);
10557 Local<Object> instance2 = instance_template->NewInstance();
10558 context->Global()->Set(v8_str("obj5"), instance2);
10559 CHECK(!try_catch.HasCaught());
10560
10561 CHECK(instance2->IsObject());
10562 CHECK(!instance2->IsFunction());
10563
10564 value = CompileRun("new obj5(28)");
10565 CHECK(!try_catch.HasCaught());
10566 CHECK(!value->IsObject());
10567
10568 Local<Value> args2[] = { v8_num(28) };
10569 value = instance2->CallAsConstructor(1, args2);
10570 CHECK(!try_catch.HasCaught());
10571 CHECK(!value->IsObject());
10572 }
10573}
10574
10575
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010576THREADED_TEST(FunctionDescriptorException) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010577 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010578 v8::Isolate* isolate = context->GetIsolate();
10579 v8::HandleScope handle_scope(isolate);
10580 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010581 templ->SetClassName(v8_str("Fun"));
10582 Local<Function> cons = templ->GetFunction();
10583 context->Global()->Set(v8_str("Fun"), cons);
10584 Local<Value> value = CompileRun(
10585 "function test() {"
10586 " try {"
10587 " (new Fun()).blah()"
10588 " } catch (e) {"
10589 " var str = String(e);"
10590 " if (str.indexOf('TypeError') == -1) return 1;"
10591 " if (str.indexOf('[object Fun]') != -1) return 2;"
whesse@chromium.org7a392b32011-01-31 11:30:36 +000010592 " if (str.indexOf('#<Fun>') == -1) return 3;"
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010593 " return 0;"
10594 " }"
10595 " return 4;"
10596 "}"
10597 "test();");
10598 CHECK_EQ(0, value->Int32Value());
10599}
10600
10601
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010602THREADED_TEST(EvalAliasedDynamic) {
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010603 LocalContext current;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000010604 v8::HandleScope scope(current->GetIsolate());
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010605
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010606 // Tests where aliased eval can only be resolved dynamically.
10607 Local<Script> script =
10608 Script::Compile(v8_str("function f(x) { "
10609 " var foo = 2;"
10610 " with (x) { return eval('foo'); }"
10611 "}"
10612 "foo = 0;"
10613 "result1 = f(new Object());"
ager@chromium.orge2902be2009-06-08 12:21:35 +000010614 "result2 = f(this);"
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010615 "var x = new Object();"
10616 "x.eval = function(x) { return 1; };"
10617 "result3 = f(x);"));
10618 script->Run();
10619 CHECK_EQ(2, current->Global()->Get(v8_str("result1"))->Int32Value());
10620 CHECK_EQ(0, current->Global()->Get(v8_str("result2"))->Int32Value());
10621 CHECK_EQ(1, current->Global()->Get(v8_str("result3"))->Int32Value());
10622
10623 v8::TryCatch try_catch;
10624 script =
10625 Script::Compile(v8_str("function f(x) { "
10626 " var bar = 2;"
10627 " with (x) { return eval('bar'); }"
10628 "}"
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000010629 "result4 = f(this)"));
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010630 script->Run();
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000010631 CHECK(!try_catch.HasCaught());
10632 CHECK_EQ(2, current->Global()->Get(v8_str("result4"))->Int32Value());
10633
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010634 try_catch.Reset();
10635}
10636
10637
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010638THREADED_TEST(CrossEval) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000010639 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010640 LocalContext other;
10641 LocalContext current;
10642
10643 Local<String> token = v8_str("<security token>");
10644 other->SetSecurityToken(token);
10645 current->SetSecurityToken(token);
10646
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000010647 // Set up reference from current to other.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010648 current->Global()->Set(v8_str("other"), other->Global());
10649
10650 // Check that new variables are introduced in other context.
10651 Local<Script> script =
10652 Script::Compile(v8_str("other.eval('var foo = 1234')"));
10653 script->Run();
10654 Local<Value> foo = other->Global()->Get(v8_str("foo"));
10655 CHECK_EQ(1234, foo->Int32Value());
10656 CHECK(!current->Global()->Has(v8_str("foo")));
10657
10658 // Check that writing to non-existing properties introduces them in
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010659 // the other context.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010660 script =
10661 Script::Compile(v8_str("other.eval('na = 1234')"));
10662 script->Run();
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010663 CHECK_EQ(1234, other->Global()->Get(v8_str("na"))->Int32Value());
10664 CHECK(!current->Global()->Has(v8_str("na")));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010665
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010666 // Check that global variables in current context are not visible in other
10667 // context.
10668 v8::TryCatch try_catch;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010669 script =
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010670 Script::Compile(v8_str("var bar = 42; other.eval('bar');"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010671 Local<Value> result = script->Run();
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010672 CHECK(try_catch.HasCaught());
10673 try_catch.Reset();
10674
10675 // Check that local variables in current context are not visible in other
10676 // context.
10677 script =
10678 Script::Compile(v8_str("(function() { "
10679 " var baz = 87;"
10680 " return other.eval('baz');"
10681 "})();"));
10682 result = script->Run();
10683 CHECK(try_catch.HasCaught());
10684 try_catch.Reset();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010685
10686 // Check that global variables in the other environment are visible
10687 // when evaluting code.
10688 other->Global()->Set(v8_str("bis"), v8_num(1234));
10689 script = Script::Compile(v8_str("other.eval('bis')"));
10690 CHECK_EQ(1234, script->Run()->Int32Value());
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010691 CHECK(!try_catch.HasCaught());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010692
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010693 // Check that the 'this' pointer points to the global object evaluating
10694 // code.
10695 other->Global()->Set(v8_str("t"), other->Global());
10696 script = Script::Compile(v8_str("other.eval('this == t')"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010697 result = script->Run();
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010698 CHECK(result->IsTrue());
10699 CHECK(!try_catch.HasCaught());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010700
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010701 // Check that variables introduced in with-statement are not visible in
10702 // other context.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010703 script =
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010704 Script::Compile(v8_str("with({x:2}){other.eval('x')}"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010705 result = script->Run();
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010706 CHECK(try_catch.HasCaught());
10707 try_catch.Reset();
ager@chromium.org3bf7b912008-11-17 09:09:45 +000010708
10709 // Check that you cannot use 'eval.call' with another object than the
10710 // current global object.
ager@chromium.org3bf7b912008-11-17 09:09:45 +000010711 script =
10712 Script::Compile(v8_str("other.y = 1; eval.call(other, 'y')"));
10713 result = script->Run();
10714 CHECK(try_catch.HasCaught());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010715}
10716
10717
ager@chromium.orge2902be2009-06-08 12:21:35 +000010718// Test that calling eval in a context which has been detached from
10719// its global throws an exception. This behavior is consistent with
10720// other JavaScript implementations.
10721THREADED_TEST(EvalInDetachedGlobal) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000010722 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000010723 v8::HandleScope scope(isolate);
ager@chromium.orge2902be2009-06-08 12:21:35 +000010724
ulan@chromium.org57ff8812013-05-10 08:16:55 +000010725 v8::Local<Context> context0 = Context::New(isolate);
10726 v8::Local<Context> context1 = Context::New(isolate);
ager@chromium.orge2902be2009-06-08 12:21:35 +000010727
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000010728 // Set up function in context0 that uses eval from context0.
ager@chromium.orge2902be2009-06-08 12:21:35 +000010729 context0->Enter();
10730 v8::Handle<v8::Value> fun =
10731 CompileRun("var x = 42;"
10732 "(function() {"
10733 " var e = eval;"
10734 " return function(s) { return e(s); }"
10735 "})()");
10736 context0->Exit();
10737
10738 // Put the function into context1 and call it before and after
10739 // detaching the global. Before detaching, the call succeeds and
10740 // after detaching and exception is thrown.
10741 context1->Enter();
10742 context1->Global()->Set(v8_str("fun"), fun);
10743 v8::Handle<v8::Value> x_value = CompileRun("fun('x')");
10744 CHECK_EQ(42, x_value->Int32Value());
10745 context0->DetachGlobal();
10746 v8::TryCatch catcher;
10747 x_value = CompileRun("fun('x')");
10748 CHECK(x_value.IsEmpty());
10749 CHECK(catcher.HasCaught());
10750 context1->Exit();
ager@chromium.orge2902be2009-06-08 12:21:35 +000010751}
10752
10753
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010754THREADED_TEST(CrossLazyLoad) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000010755 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010756 LocalContext other;
10757 LocalContext current;
10758
10759 Local<String> token = v8_str("<security token>");
10760 other->SetSecurityToken(token);
10761 current->SetSecurityToken(token);
10762
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000010763 // Set up reference from current to other.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010764 current->Global()->Set(v8_str("other"), other->Global());
10765
10766 // Trigger lazy loading in other context.
10767 Local<Script> script =
10768 Script::Compile(v8_str("other.eval('new Date(42)')"));
10769 Local<Value> value = script->Run();
10770 CHECK_EQ(42.0, value->NumberValue());
10771}
10772
10773
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010774static void call_as_function(const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010775 ApiTestFuzzer::Fuzz();
sgjesse@chromium.org05521fc2009-05-21 07:37:44 +000010776 if (args.IsConstructCall()) {
10777 if (args[0]->IsInt32()) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010778 args.GetReturnValue().Set(v8_num(-args[0]->Int32Value()));
10779 return;
sgjesse@chromium.org05521fc2009-05-21 07:37:44 +000010780 }
10781 }
10782
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010783 args.GetReturnValue().Set(args[0]);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010784}
10785
10786
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +000010787static void ReturnThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
10788 args.GetReturnValue().Set(args.This());
10789}
10790
10791
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010792// Test that a call handler can be set for objects which will allow
10793// non-function objects created through the API to be called as
10794// functions.
10795THREADED_TEST(CallAsFunction) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010796 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010797 v8::Isolate* isolate = context->GetIsolate();
10798 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010799
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010800 { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
lrn@chromium.org1c092762011-05-09 09:42:16 +000010801 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
10802 instance_template->SetCallAsFunctionHandler(call_as_function);
10803 Local<v8::Object> instance = t->GetFunction()->NewInstance();
10804 context->Global()->Set(v8_str("obj"), instance);
10805 v8::TryCatch try_catch;
10806 Local<Value> value;
10807 CHECK(!try_catch.HasCaught());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010808
lrn@chromium.org1c092762011-05-09 09:42:16 +000010809 value = CompileRun("obj(42)");
10810 CHECK(!try_catch.HasCaught());
10811 CHECK_EQ(42, value->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010812
lrn@chromium.org1c092762011-05-09 09:42:16 +000010813 value = CompileRun("(function(o){return o(49)})(obj)");
10814 CHECK(!try_catch.HasCaught());
10815 CHECK_EQ(49, value->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010816
lrn@chromium.org1c092762011-05-09 09:42:16 +000010817 // test special case of call as function
10818 value = CompileRun("[obj]['0'](45)");
10819 CHECK(!try_catch.HasCaught());
10820 CHECK_EQ(45, value->Int32Value());
ager@chromium.org9258b6b2008-09-11 09:11:10 +000010821
lrn@chromium.org1c092762011-05-09 09:42:16 +000010822 value = CompileRun("obj.call = Function.prototype.call;"
10823 "obj.call(null, 87)");
10824 CHECK(!try_catch.HasCaught());
10825 CHECK_EQ(87, value->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010826
lrn@chromium.org1c092762011-05-09 09:42:16 +000010827 // Regression tests for bug #1116356: Calling call through call/apply
10828 // must work for non-function receivers.
10829 const char* apply_99 = "Function.prototype.call.apply(obj, [this, 99])";
10830 value = CompileRun(apply_99);
10831 CHECK(!try_catch.HasCaught());
10832 CHECK_EQ(99, value->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010833
lrn@chromium.org1c092762011-05-09 09:42:16 +000010834 const char* call_17 = "Function.prototype.call.call(obj, this, 17)";
10835 value = CompileRun(call_17);
10836 CHECK(!try_catch.HasCaught());
10837 CHECK_EQ(17, value->Int32Value());
ager@chromium.org9085a012009-05-11 19:22:57 +000010838
lrn@chromium.org1c092762011-05-09 09:42:16 +000010839 // Check that the call-as-function handler can be called through
10840 // new.
10841 value = CompileRun("new obj(43)");
10842 CHECK(!try_catch.HasCaught());
10843 CHECK_EQ(-43, value->Int32Value());
10844
10845 // Check that the call-as-function handler can be called through
10846 // the API.
10847 v8::Handle<Value> args[] = { v8_num(28) };
10848 value = instance->CallAsFunction(instance, 1, args);
10849 CHECK(!try_catch.HasCaught());
10850 CHECK_EQ(28, value->Int32Value());
10851 }
10852
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010853 { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000010854 Local<ObjectTemplate> instance_template(t->InstanceTemplate());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000010855 USE(instance_template);
lrn@chromium.org1c092762011-05-09 09:42:16 +000010856 Local<v8::Object> instance = t->GetFunction()->NewInstance();
10857 context->Global()->Set(v8_str("obj2"), instance);
10858 v8::TryCatch try_catch;
10859 Local<Value> value;
10860 CHECK(!try_catch.HasCaught());
10861
10862 // Call an object without call-as-function handler through the JS
10863 value = CompileRun("obj2(28)");
10864 CHECK(value.IsEmpty());
10865 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000010866 String::Utf8Value exception_value1(try_catch.Exception());
lrn@chromium.org1c092762011-05-09 09:42:16 +000010867 CHECK_EQ("TypeError: Property 'obj2' of object #<Object> is not a function",
10868 *exception_value1);
10869 try_catch.Reset();
10870
10871 // Call an object without call-as-function handler through the API
10872 value = CompileRun("obj2(28)");
10873 v8::Handle<Value> args[] = { v8_num(28) };
10874 value = instance->CallAsFunction(instance, 1, args);
10875 CHECK(value.IsEmpty());
10876 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000010877 String::Utf8Value exception_value2(try_catch.Exception());
lrn@chromium.org1c092762011-05-09 09:42:16 +000010878 CHECK_EQ("TypeError: [object Object] is not a function", *exception_value2);
10879 try_catch.Reset();
10880 }
10881
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010882 { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
lrn@chromium.org1c092762011-05-09 09:42:16 +000010883 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
10884 instance_template->SetCallAsFunctionHandler(ThrowValue);
10885 Local<v8::Object> instance = t->GetFunction()->NewInstance();
10886 context->Global()->Set(v8_str("obj3"), instance);
10887 v8::TryCatch try_catch;
10888 Local<Value> value;
10889 CHECK(!try_catch.HasCaught());
10890
10891 // Catch the exception which is thrown by call-as-function handler
10892 value = CompileRun("obj3(22)");
10893 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000010894 String::Utf8Value exception_value1(try_catch.Exception());
lrn@chromium.org1c092762011-05-09 09:42:16 +000010895 CHECK_EQ("22", *exception_value1);
10896 try_catch.Reset();
10897
10898 v8::Handle<Value> args[] = { v8_num(23) };
10899 value = instance->CallAsFunction(instance, 1, args);
10900 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000010901 String::Utf8Value exception_value2(try_catch.Exception());
lrn@chromium.org1c092762011-05-09 09:42:16 +000010902 CHECK_EQ("23", *exception_value2);
10903 try_catch.Reset();
10904 }
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +000010905
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010906 { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +000010907 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
10908 instance_template->SetCallAsFunctionHandler(ReturnThis);
10909 Local<v8::Object> instance = t->GetFunction()->NewInstance();
10910
10911 Local<v8::Value> a1 =
10912 instance->CallAsFunction(v8::Undefined(isolate), 0, NULL);
10913 CHECK(a1->StrictEquals(instance));
10914 Local<v8::Value> a2 =
10915 instance->CallAsFunction(v8::Null(isolate), 0, NULL);
10916 CHECK(a2->StrictEquals(instance));
10917 Local<v8::Value> a3 =
10918 instance->CallAsFunction(v8_num(42), 0, NULL);
10919 CHECK(a3->StrictEquals(instance));
10920 Local<v8::Value> a4 =
10921 instance->CallAsFunction(v8_str("hello"), 0, NULL);
10922 CHECK(a4->StrictEquals(instance));
10923 Local<v8::Value> a5 =
10924 instance->CallAsFunction(v8::True(isolate), 0, NULL);
10925 CHECK(a5->StrictEquals(instance));
10926 }
10927
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010928 { CompileRun(
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +000010929 "function ReturnThisSloppy() {"
10930 " return this;"
10931 "}"
10932 "function ReturnThisStrict() {"
10933 " 'use strict';"
10934 " return this;"
10935 "}");
10936 Local<Function> ReturnThisSloppy =
10937 Local<Function>::Cast(
10938 context->Global()->Get(v8_str("ReturnThisSloppy")));
10939 Local<Function> ReturnThisStrict =
10940 Local<Function>::Cast(
10941 context->Global()->Get(v8_str("ReturnThisStrict")));
10942
10943 Local<v8::Value> a1 =
10944 ReturnThisSloppy->CallAsFunction(v8::Undefined(isolate), 0, NULL);
10945 CHECK(a1->StrictEquals(context->Global()));
10946 Local<v8::Value> a2 =
10947 ReturnThisSloppy->CallAsFunction(v8::Null(isolate), 0, NULL);
10948 CHECK(a2->StrictEquals(context->Global()));
10949 Local<v8::Value> a3 =
10950 ReturnThisSloppy->CallAsFunction(v8_num(42), 0, NULL);
10951 CHECK(a3->IsNumberObject());
10952 CHECK_EQ(42.0, a3.As<v8::NumberObject>()->ValueOf());
10953 Local<v8::Value> a4 =
10954 ReturnThisSloppy->CallAsFunction(v8_str("hello"), 0, NULL);
10955 CHECK(a4->IsStringObject());
10956 CHECK(a4.As<v8::StringObject>()->ValueOf()->StrictEquals(v8_str("hello")));
10957 Local<v8::Value> a5 =
10958 ReturnThisSloppy->CallAsFunction(v8::True(isolate), 0, NULL);
10959 CHECK(a5->IsBooleanObject());
10960 CHECK(a5.As<v8::BooleanObject>()->ValueOf());
10961
10962 Local<v8::Value> a6 =
10963 ReturnThisStrict->CallAsFunction(v8::Undefined(isolate), 0, NULL);
10964 CHECK(a6->IsUndefined());
10965 Local<v8::Value> a7 =
10966 ReturnThisStrict->CallAsFunction(v8::Null(isolate), 0, NULL);
10967 CHECK(a7->IsNull());
10968 Local<v8::Value> a8 =
10969 ReturnThisStrict->CallAsFunction(v8_num(42), 0, NULL);
10970 CHECK(a8->StrictEquals(v8_num(42)));
10971 Local<v8::Value> a9 =
10972 ReturnThisStrict->CallAsFunction(v8_str("hello"), 0, NULL);
10973 CHECK(a9->StrictEquals(v8_str("hello")));
10974 Local<v8::Value> a10 =
10975 ReturnThisStrict->CallAsFunction(v8::True(isolate), 0, NULL);
10976 CHECK(a10->StrictEquals(v8::True(isolate)));
10977 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010978}
10979
10980
karlklose@chromium.org83a47282011-05-11 11:54:09 +000010981// Check whether a non-function object is callable.
10982THREADED_TEST(CallableObject) {
karlklose@chromium.org83a47282011-05-11 11:54:09 +000010983 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010984 v8::Isolate* isolate = context->GetIsolate();
10985 v8::HandleScope scope(isolate);
karlklose@chromium.org83a47282011-05-11 11:54:09 +000010986
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000010987 { Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
karlklose@chromium.org83a47282011-05-11 11:54:09 +000010988 instance_template->SetCallAsFunctionHandler(call_as_function);
10989 Local<Object> instance = instance_template->NewInstance();
10990 v8::TryCatch try_catch;
10991
10992 CHECK(instance->IsCallable());
10993 CHECK(!try_catch.HasCaught());
10994 }
10995
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000010996 { Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
karlklose@chromium.org83a47282011-05-11 11:54:09 +000010997 Local<Object> instance = instance_template->NewInstance();
10998 v8::TryCatch try_catch;
10999
11000 CHECK(!instance->IsCallable());
11001 CHECK(!try_catch.HasCaught());
11002 }
11003
11004 { Local<FunctionTemplate> function_template =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000011005 FunctionTemplate::New(isolate, call_as_function);
karlklose@chromium.org83a47282011-05-11 11:54:09 +000011006 Local<Function> function = function_template->GetFunction();
11007 Local<Object> instance = function;
11008 v8::TryCatch try_catch;
11009
11010 CHECK(instance->IsCallable());
11011 CHECK(!try_catch.HasCaught());
11012 }
11013
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000011014 { Local<FunctionTemplate> function_template = FunctionTemplate::New(isolate);
karlklose@chromium.org83a47282011-05-11 11:54:09 +000011015 Local<Function> function = function_template->GetFunction();
11016 Local<Object> instance = function;
11017 v8::TryCatch try_catch;
11018
11019 CHECK(instance->IsCallable());
11020 CHECK(!try_catch.HasCaught());
11021 }
11022}
11023
11024
machenbach@chromium.org4610c282014-01-09 10:39:51 +000011025static int Recurse(v8::Isolate* isolate, int depth, int iterations) {
11026 v8::HandleScope scope(isolate);
11027 if (depth == 0) return v8::HandleScope::NumberOfHandles(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011028 for (int i = 0; i < iterations; i++) {
machenbach@chromium.org4610c282014-01-09 10:39:51 +000011029 Local<v8::Number> n(v8::Integer::New(isolate, 42));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011030 }
machenbach@chromium.org4610c282014-01-09 10:39:51 +000011031 return Recurse(isolate, depth - 1, iterations);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011032}
11033
11034
11035THREADED_TEST(HandleIteration) {
11036 static const int kIterations = 500;
11037 static const int kNesting = 200;
machenbach@chromium.org4610c282014-01-09 10:39:51 +000011038 LocalContext context;
11039 v8::Isolate* isolate = context->GetIsolate();
11040 v8::HandleScope scope0(isolate);
11041 CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011042 {
machenbach@chromium.org4610c282014-01-09 10:39:51 +000011043 v8::HandleScope scope1(isolate);
11044 CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011045 for (int i = 0; i < kIterations; i++) {
ulan@chromium.org0f13e742014-01-03 15:51:11 +000011046 Local<v8::Number> n(v8::Integer::New(CcTest::isolate(), 42));
machenbach@chromium.org4610c282014-01-09 10:39:51 +000011047 CHECK_EQ(i + 1, v8::HandleScope::NumberOfHandles(isolate));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011048 }
11049
machenbach@chromium.org4610c282014-01-09 10:39:51 +000011050 CHECK_EQ(kIterations, v8::HandleScope::NumberOfHandles(isolate));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011051 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011052 v8::HandleScope scope2(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011053 for (int j = 0; j < kIterations; j++) {
ulan@chromium.org0f13e742014-01-03 15:51:11 +000011054 Local<v8::Number> n(v8::Integer::New(CcTest::isolate(), 42));
machenbach@chromium.org4610c282014-01-09 10:39:51 +000011055 CHECK_EQ(j + 1 + kIterations,
11056 v8::HandleScope::NumberOfHandles(isolate));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011057 }
11058 }
machenbach@chromium.org4610c282014-01-09 10:39:51 +000011059 CHECK_EQ(kIterations, v8::HandleScope::NumberOfHandles(isolate));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011060 }
machenbach@chromium.org4610c282014-01-09 10:39:51 +000011061 CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
11062 CHECK_EQ(kNesting * kIterations, Recurse(isolate, kNesting, kIterations));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011063}
11064
11065
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011066static void InterceptorHasOwnPropertyGetter(
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011067 Local<String> name,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011068 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011069 ApiTestFuzzer::Fuzz();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011070}
11071
11072
11073THREADED_TEST(InterceptorHasOwnProperty) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011074 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000011075 v8::Isolate* isolate = context->GetIsolate();
11076 v8::HandleScope scope(isolate);
11077 Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011078 Local<v8::ObjectTemplate> instance_templ = fun_templ->InstanceTemplate();
11079 instance_templ->SetNamedPropertyHandler(InterceptorHasOwnPropertyGetter);
11080 Local<Function> function = fun_templ->GetFunction();
11081 context->Global()->Set(v8_str("constructor"), function);
11082 v8::Handle<Value> value = CompileRun(
11083 "var o = new constructor();"
11084 "o.hasOwnProperty('ostehaps');");
11085 CHECK_EQ(false, value->BooleanValue());
11086 value = CompileRun(
11087 "o.ostehaps = 42;"
11088 "o.hasOwnProperty('ostehaps');");
11089 CHECK_EQ(true, value->BooleanValue());
11090 value = CompileRun(
11091 "var p = new constructor();"
11092 "p.hasOwnProperty('ostehaps');");
11093 CHECK_EQ(false, value->BooleanValue());
11094}
11095
11096
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011097static void InterceptorHasOwnPropertyGetterGC(
ager@chromium.org9085a012009-05-11 19:22:57 +000011098 Local<String> name,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011099 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.org9085a012009-05-11 19:22:57 +000011100 ApiTestFuzzer::Fuzz();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011101 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org9085a012009-05-11 19:22:57 +000011102}
11103
11104
11105THREADED_TEST(InterceptorHasOwnPropertyCausingGC) {
ager@chromium.org9085a012009-05-11 19:22:57 +000011106 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000011107 v8::Isolate* isolate = context->GetIsolate();
11108 v8::HandleScope scope(isolate);
11109 Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(isolate);
ager@chromium.org9085a012009-05-11 19:22:57 +000011110 Local<v8::ObjectTemplate> instance_templ = fun_templ->InstanceTemplate();
11111 instance_templ->SetNamedPropertyHandler(InterceptorHasOwnPropertyGetterGC);
11112 Local<Function> function = fun_templ->GetFunction();
11113 context->Global()->Set(v8_str("constructor"), function);
11114 // Let's first make some stuff so we can be sure to get a good GC.
11115 CompileRun(
11116 "function makestr(size) {"
11117 " switch (size) {"
11118 " case 1: return 'f';"
11119 " case 2: return 'fo';"
11120 " case 3: return 'foo';"
11121 " }"
11122 " return makestr(size >> 1) + makestr((size + 1) >> 1);"
11123 "}"
11124 "var x = makestr(12345);"
11125 "x = makestr(31415);"
11126 "x = makestr(23456);");
11127 v8::Handle<Value> value = CompileRun(
11128 "var o = new constructor();"
11129 "o.__proto__ = new String(x);"
11130 "o.hasOwnProperty('ostehaps');");
11131 CHECK_EQ(false, value->BooleanValue());
11132}
11133
11134
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011135typedef void (*NamedPropertyGetter)(
11136 Local<String> property,
11137 const v8::PropertyCallbackInfo<v8::Value>& info);
ager@chromium.orge2902be2009-06-08 12:21:35 +000011138
11139
11140static void CheckInterceptorLoadIC(NamedPropertyGetter getter,
11141 const char* source,
11142 int expected) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011143 v8::Isolate* isolate = CcTest::isolate();
11144 v8::HandleScope scope(isolate);
11145 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
vegorov@chromium.org21b5e952010-11-23 10:24:40 +000011146 templ->SetNamedPropertyHandler(getter, 0, 0, 0, 0, v8_str("data"));
ager@chromium.orge2902be2009-06-08 12:21:35 +000011147 LocalContext context;
11148 context->Global()->Set(v8_str("o"), templ->NewInstance());
11149 v8::Handle<Value> value = CompileRun(source);
11150 CHECK_EQ(expected, value->Int32Value());
11151}
11152
11153
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011154static void InterceptorLoadICGetter(
11155 Local<String> name,
11156 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011157 ApiTestFuzzer::Fuzz();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011158 v8::Isolate* isolate = CcTest::isolate();
jkummerow@chromium.org28faa982012-04-13 09:58:30 +000011159 CHECK_EQ(isolate, info.GetIsolate());
vegorov@chromium.org21b5e952010-11-23 10:24:40 +000011160 CHECK_EQ(v8_str("data"), info.Data());
11161 CHECK_EQ(v8_str("x"), name);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000011162 info.GetReturnValue().Set(v8::Integer::New(isolate, 42));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011163}
11164
11165
11166// This test should hit the load IC for the interceptor case.
11167THREADED_TEST(InterceptorLoadIC) {
ager@chromium.orge2902be2009-06-08 12:21:35 +000011168 CheckInterceptorLoadIC(InterceptorLoadICGetter,
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011169 "var result = 0;"
11170 "for (var i = 0; i < 1000; i++) {"
11171 " result = o.x;"
ager@chromium.orge2902be2009-06-08 12:21:35 +000011172 "}",
11173 42);
11174}
11175
11176
11177// Below go several tests which verify that JITing for various
11178// configurations of interceptor and explicit fields works fine
11179// (those cases are special cased to get better performance).
11180
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011181static void InterceptorLoadXICGetter(
11182 Local<String> name,
11183 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.orge2902be2009-06-08 12:21:35 +000011184 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011185 info.GetReturnValue().Set(
11186 v8_str("x")->Equals(name) ?
ulan@chromium.org0f13e742014-01-03 15:51:11 +000011187 v8::Handle<v8::Value>(v8::Integer::New(info.GetIsolate(), 42)) :
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011188 v8::Handle<v8::Value>());
ager@chromium.orge2902be2009-06-08 12:21:35 +000011189}
11190
11191
11192THREADED_TEST(InterceptorLoadICWithFieldOnHolder) {
11193 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
11194 "var result = 0;"
11195 "o.y = 239;"
11196 "for (var i = 0; i < 1000; i++) {"
11197 " result = o.y;"
11198 "}",
11199 239);
11200}
11201
11202
11203THREADED_TEST(InterceptorLoadICWithSubstitutedProto) {
11204 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
11205 "var result = 0;"
11206 "o.__proto__ = { 'y': 239 };"
11207 "for (var i = 0; i < 1000; i++) {"
11208 " result = o.y + o.x;"
11209 "}",
11210 239 + 42);
11211}
11212
11213
11214THREADED_TEST(InterceptorLoadICWithPropertyOnProto) {
11215 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
11216 "var result = 0;"
11217 "o.__proto__.y = 239;"
11218 "for (var i = 0; i < 1000; i++) {"
11219 " result = o.y + o.x;"
11220 "}",
11221 239 + 42);
11222}
11223
11224
11225THREADED_TEST(InterceptorLoadICUndefined) {
11226 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
11227 "var result = 0;"
11228 "for (var i = 0; i < 1000; i++) {"
11229 " result = (o.y == undefined) ? 239 : 42;"
11230 "}",
11231 239);
11232}
11233
11234
11235THREADED_TEST(InterceptorLoadICWithOverride) {
11236 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
11237 "fst = new Object(); fst.__proto__ = o;"
11238 "snd = new Object(); snd.__proto__ = fst;"
11239 "var result1 = 0;"
11240 "for (var i = 0; i < 1000; i++) {"
11241 " result1 = snd.x;"
11242 "}"
11243 "fst.x = 239;"
11244 "var result = 0;"
11245 "for (var i = 0; i < 1000; i++) {"
11246 " result = snd.x;"
11247 "}"
11248 "result + result1",
11249 239 + 42);
11250}
11251
11252
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011253// Test the case when we stored field into
11254// a stub, but interceptor produced value on its own.
11255THREADED_TEST(InterceptorLoadICFieldNotNeeded) {
11256 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
11257 "proto = new Object();"
11258 "o.__proto__ = proto;"
11259 "proto.x = 239;"
11260 "for (var i = 0; i < 1000; i++) {"
11261 " o.x;"
11262 // Now it should be ICed and keep a reference to x defined on proto
11263 "}"
11264 "var result = 0;"
11265 "for (var i = 0; i < 1000; i++) {"
11266 " result += o.x;"
11267 "}"
11268 "result;",
11269 42 * 1000);
11270}
11271
11272
11273// Test the case when we stored field into
11274// a stub, but it got invalidated later on.
11275THREADED_TEST(InterceptorLoadICInvalidatedField) {
11276 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
11277 "proto1 = new Object();"
11278 "proto2 = new Object();"
11279 "o.__proto__ = proto1;"
11280 "proto1.__proto__ = proto2;"
11281 "proto2.y = 239;"
11282 "for (var i = 0; i < 1000; i++) {"
11283 " o.y;"
11284 // Now it should be ICed and keep a reference to y defined on proto2
11285 "}"
11286 "proto1.y = 42;"
11287 "var result = 0;"
11288 "for (var i = 0; i < 1000; i++) {"
11289 " result += o.y;"
11290 "}"
11291 "result;",
11292 42 * 1000);
11293}
11294
11295
ager@chromium.orgb26c50a2010-03-26 09:27:16 +000011296static int interceptor_load_not_handled_calls = 0;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011297static void InterceptorLoadNotHandled(
11298 Local<String> name,
11299 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.orgb26c50a2010-03-26 09:27:16 +000011300 ++interceptor_load_not_handled_calls;
ager@chromium.orgb26c50a2010-03-26 09:27:16 +000011301}
11302
11303
11304// Test how post-interceptor lookups are done in the non-cacheable
11305// case: the interceptor should not be invoked during this lookup.
11306THREADED_TEST(InterceptorLoadICPostInterceptor) {
11307 interceptor_load_not_handled_calls = 0;
11308 CheckInterceptorLoadIC(InterceptorLoadNotHandled,
11309 "receiver = new Object();"
11310 "receiver.__proto__ = o;"
11311 "proto = new Object();"
11312 "/* Make proto a slow-case object. */"
11313 "for (var i = 0; i < 1000; i++) {"
11314 " proto[\"xxxxxxxx\" + i] = [];"
11315 "}"
11316 "proto.x = 17;"
11317 "o.__proto__ = proto;"
11318 "var result = 0;"
11319 "for (var i = 0; i < 1000; i++) {"
11320 " result += receiver.x;"
11321 "}"
11322 "result;",
11323 17 * 1000);
11324 CHECK_EQ(1000, interceptor_load_not_handled_calls);
11325}
11326
11327
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011328// Test the case when we stored field into
11329// a stub, but it got invalidated later on due to override on
11330// global object which is between interceptor and fields' holders.
11331THREADED_TEST(InterceptorLoadICInvalidatedFieldViaGlobal) {
11332 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
11333 "o.__proto__ = this;" // set a global to be a proto of o.
11334 "this.__proto__.y = 239;"
11335 "for (var i = 0; i < 10; i++) {"
11336 " if (o.y != 239) throw 'oops: ' + o.y;"
11337 // Now it should be ICed and keep a reference to y defined on field_holder.
11338 "}"
11339 "this.y = 42;" // Assign on a global.
11340 "var result = 0;"
11341 "for (var i = 0; i < 10; i++) {"
11342 " result += o.y;"
11343 "}"
11344 "result;",
11345 42 * 10);
11346}
11347
11348
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011349static void SetOnThis(Local<String> name,
11350 Local<Value> value,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011351 const v8::PropertyCallbackInfo<void>& info) {
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011352 info.This()->ForceSet(name, value);
11353}
11354
11355
11356THREADED_TEST(InterceptorLoadICWithCallbackOnHolder) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011357 v8::Isolate* isolate = CcTest::isolate();
11358 v8::HandleScope scope(isolate);
11359 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011360 templ->SetNamedPropertyHandler(InterceptorLoadXICGetter);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011361 templ->SetAccessor(v8_str("y"), Return239Callback);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011362 LocalContext context;
11363 context->Global()->Set(v8_str("o"), templ->NewInstance());
ricow@chromium.org30ce4112010-05-31 10:38:25 +000011364
11365 // Check the case when receiver and interceptor's holder
11366 // are the same objects.
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011367 v8::Handle<Value> value = CompileRun(
11368 "var result = 0;"
11369 "for (var i = 0; i < 7; i++) {"
11370 " result = o.y;"
11371 "}");
11372 CHECK_EQ(239, value->Int32Value());
ricow@chromium.org30ce4112010-05-31 10:38:25 +000011373
11374 // Check the case when interceptor's holder is in proto chain
11375 // of receiver.
11376 value = CompileRun(
11377 "r = { __proto__: o };"
11378 "var result = 0;"
11379 "for (var i = 0; i < 7; i++) {"
11380 " result = r.y;"
11381 "}");
11382 CHECK_EQ(239, value->Int32Value());
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011383}
11384
11385
11386THREADED_TEST(InterceptorLoadICWithCallbackOnProto) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011387 v8::Isolate* isolate = CcTest::isolate();
11388 v8::HandleScope scope(isolate);
11389 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011390 templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011391 v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New(isolate);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011392 templ_p->SetAccessor(v8_str("y"), Return239Callback);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011393
11394 LocalContext context;
11395 context->Global()->Set(v8_str("o"), templ_o->NewInstance());
11396 context->Global()->Set(v8_str("p"), templ_p->NewInstance());
11397
ricow@chromium.org30ce4112010-05-31 10:38:25 +000011398 // Check the case when receiver and interceptor's holder
11399 // are the same objects.
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011400 v8::Handle<Value> value = CompileRun(
11401 "o.__proto__ = p;"
11402 "var result = 0;"
11403 "for (var i = 0; i < 7; i++) {"
11404 " result = o.x + o.y;"
11405 "}");
11406 CHECK_EQ(239 + 42, value->Int32Value());
ricow@chromium.org30ce4112010-05-31 10:38:25 +000011407
11408 // Check the case when interceptor's holder is in proto chain
11409 // of receiver.
11410 value = CompileRun(
11411 "r = { __proto__: o };"
11412 "var result = 0;"
11413 "for (var i = 0; i < 7; i++) {"
11414 " result = r.x + r.y;"
11415 "}");
11416 CHECK_EQ(239 + 42, value->Int32Value());
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011417}
11418
11419
11420THREADED_TEST(InterceptorLoadICForCallbackWithOverride) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011421 v8::Isolate* isolate = CcTest::isolate();
11422 v8::HandleScope scope(isolate);
11423 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011424 templ->SetNamedPropertyHandler(InterceptorLoadXICGetter);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011425 templ->SetAccessor(v8_str("y"), Return239Callback);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011426
11427 LocalContext context;
11428 context->Global()->Set(v8_str("o"), templ->NewInstance());
11429
11430 v8::Handle<Value> value = CompileRun(
11431 "fst = new Object(); fst.__proto__ = o;"
11432 "snd = new Object(); snd.__proto__ = fst;"
11433 "var result1 = 0;"
11434 "for (var i = 0; i < 7; i++) {"
11435 " result1 = snd.x;"
11436 "}"
11437 "fst.x = 239;"
11438 "var result = 0;"
11439 "for (var i = 0; i < 7; i++) {"
11440 " result = snd.x;"
11441 "}"
11442 "result + result1");
11443 CHECK_EQ(239 + 42, value->Int32Value());
11444}
11445
11446
11447// Test the case when we stored callback into
11448// a stub, but interceptor produced value on its own.
11449THREADED_TEST(InterceptorLoadICCallbackNotNeeded) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011450 v8::Isolate* isolate = CcTest::isolate();
11451 v8::HandleScope scope(isolate);
11452 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011453 templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011454 v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New(isolate);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011455 templ_p->SetAccessor(v8_str("y"), Return239Callback);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011456
11457 LocalContext context;
11458 context->Global()->Set(v8_str("o"), templ_o->NewInstance());
11459 context->Global()->Set(v8_str("p"), templ_p->NewInstance());
11460
11461 v8::Handle<Value> value = CompileRun(
11462 "o.__proto__ = p;"
11463 "for (var i = 0; i < 7; i++) {"
11464 " o.x;"
11465 // Now it should be ICed and keep a reference to x defined on p
11466 "}"
11467 "var result = 0;"
11468 "for (var i = 0; i < 7; i++) {"
11469 " result += o.x;"
11470 "}"
11471 "result");
11472 CHECK_EQ(42 * 7, value->Int32Value());
11473}
11474
11475
11476// Test the case when we stored callback into
11477// a stub, but it got invalidated later on.
11478THREADED_TEST(InterceptorLoadICInvalidatedCallback) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011479 v8::Isolate* isolate = CcTest::isolate();
11480 v8::HandleScope scope(isolate);
11481 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011482 templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011483 v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New(isolate);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011484 templ_p->SetAccessor(v8_str("y"), Return239Callback, SetOnThis);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011485
11486 LocalContext context;
11487 context->Global()->Set(v8_str("o"), templ_o->NewInstance());
11488 context->Global()->Set(v8_str("p"), templ_p->NewInstance());
11489
11490 v8::Handle<Value> value = CompileRun(
11491 "inbetween = new Object();"
11492 "o.__proto__ = inbetween;"
11493 "inbetween.__proto__ = p;"
11494 "for (var i = 0; i < 10; i++) {"
11495 " o.y;"
11496 // Now it should be ICed and keep a reference to y defined on p
11497 "}"
11498 "inbetween.y = 42;"
11499 "var result = 0;"
11500 "for (var i = 0; i < 10; i++) {"
11501 " result += o.y;"
11502 "}"
11503 "result");
11504 CHECK_EQ(42 * 10, value->Int32Value());
11505}
11506
11507
11508// Test the case when we stored callback into
11509// a stub, but it got invalidated later on due to override on
11510// global object which is between interceptor and callbacks' holders.
11511THREADED_TEST(InterceptorLoadICInvalidatedCallbackViaGlobal) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011512 v8::Isolate* isolate = CcTest::isolate();
11513 v8::HandleScope scope(isolate);
11514 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011515 templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011516 v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New(isolate);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011517 templ_p->SetAccessor(v8_str("y"), Return239Callback, SetOnThis);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011518
11519 LocalContext context;
11520 context->Global()->Set(v8_str("o"), templ_o->NewInstance());
11521 context->Global()->Set(v8_str("p"), templ_p->NewInstance());
11522
11523 v8::Handle<Value> value = CompileRun(
11524 "o.__proto__ = this;"
11525 "this.__proto__ = p;"
11526 "for (var i = 0; i < 10; i++) {"
11527 " if (o.y != 239) throw 'oops: ' + o.y;"
11528 // Now it should be ICed and keep a reference to y defined on p
11529 "}"
11530 "this.y = 42;"
11531 "var result = 0;"
11532 "for (var i = 0; i < 10; i++) {"
11533 " result += o.y;"
11534 "}"
11535 "result");
11536 CHECK_EQ(42 * 10, value->Int32Value());
11537}
11538
11539
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011540static void InterceptorLoadICGetter0(
11541 Local<String> name,
11542 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.orge2902be2009-06-08 12:21:35 +000011543 ApiTestFuzzer::Fuzz();
11544 CHECK(v8_str("x")->Equals(name));
ulan@chromium.org0f13e742014-01-03 15:51:11 +000011545 info.GetReturnValue().Set(v8::Integer::New(info.GetIsolate(), 0));
ager@chromium.orge2902be2009-06-08 12:21:35 +000011546}
11547
11548
11549THREADED_TEST(InterceptorReturningZero) {
11550 CheckInterceptorLoadIC(InterceptorLoadICGetter0,
11551 "o.x == undefined ? 1 : 0",
11552 0);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011553}
11554
11555
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011556static void InterceptorStoreICSetter(
11557 Local<String> key,
11558 Local<Value> value,
11559 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011560 CHECK(v8_str("x")->Equals(key));
11561 CHECK_EQ(42, value->Int32Value());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011562 info.GetReturnValue().Set(value);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011563}
11564
11565
11566// This test should hit the store IC for the interceptor case.
11567THREADED_TEST(InterceptorStoreIC) {
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 = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011571 templ->SetNamedPropertyHandler(InterceptorLoadICGetter,
vegorov@chromium.org21b5e952010-11-23 10:24:40 +000011572 InterceptorStoreICSetter,
11573 0, 0, 0, v8_str("data"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011574 LocalContext context;
11575 context->Global()->Set(v8_str("o"), templ->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000011576 CompileRun(
11577 "for (var i = 0; i < 1000; i++) {"
11578 " o.x = 42;"
11579 "}");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011580}
11581
11582
ager@chromium.orgeadaf222009-06-16 09:43:10 +000011583THREADED_TEST(InterceptorStoreICWithNoSetter) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011584 v8::Isolate* isolate = CcTest::isolate();
11585 v8::HandleScope scope(isolate);
11586 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.orgeadaf222009-06-16 09:43:10 +000011587 templ->SetNamedPropertyHandler(InterceptorLoadXICGetter);
11588 LocalContext context;
11589 context->Global()->Set(v8_str("o"), templ->NewInstance());
11590 v8::Handle<Value> value = CompileRun(
11591 "for (var i = 0; i < 1000; i++) {"
11592 " o.y = 239;"
11593 "}"
11594 "42 + o.y");
11595 CHECK_EQ(239 + 42, value->Int32Value());
11596}
11597
11598
11599
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011600
11601v8::Handle<Value> call_ic_function;
11602v8::Handle<Value> call_ic_function2;
11603v8::Handle<Value> call_ic_function3;
11604
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011605static void InterceptorCallICGetter(
11606 Local<String> name,
11607 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011608 ApiTestFuzzer::Fuzz();
11609 CHECK(v8_str("x")->Equals(name));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011610 info.GetReturnValue().Set(call_ic_function);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011611}
11612
11613
11614// This test should hit the call IC for the interceptor case.
11615THREADED_TEST(InterceptorCallIC) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011616 v8::Isolate* isolate = CcTest::isolate();
11617 v8::HandleScope scope(isolate);
11618 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011619 templ->SetNamedPropertyHandler(InterceptorCallICGetter);
11620 LocalContext context;
11621 context->Global()->Set(v8_str("o"), templ->NewInstance());
11622 call_ic_function =
11623 v8_compile("function f(x) { return x + 1; }; f")->Run();
11624 v8::Handle<Value> value = CompileRun(
11625 "var result = 0;"
11626 "for (var i = 0; i < 1000; i++) {"
11627 " result = o.x(41);"
11628 "}");
11629 CHECK_EQ(42, value->Int32Value());
11630}
11631
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011632
11633// This test checks that if interceptor doesn't provide
11634// a value, we can fetch regular value.
11635THREADED_TEST(InterceptorCallICSeesOthers) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011636 v8::Isolate* isolate = CcTest::isolate();
11637 v8::HandleScope scope(isolate);
11638 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011639 templ->SetNamedPropertyHandler(NoBlockGetterX);
11640 LocalContext context;
11641 context->Global()->Set(v8_str("o"), templ->NewInstance());
11642 v8::Handle<Value> value = CompileRun(
11643 "o.x = function f(x) { return x + 1; };"
11644 "var result = 0;"
11645 "for (var i = 0; i < 7; i++) {"
11646 " result = o.x(41);"
11647 "}");
11648 CHECK_EQ(42, value->Int32Value());
11649}
11650
11651
11652static v8::Handle<Value> call_ic_function4;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011653static void InterceptorCallICGetter4(
11654 Local<String> name,
11655 const v8::PropertyCallbackInfo<v8::Value>& info) {
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011656 ApiTestFuzzer::Fuzz();
11657 CHECK(v8_str("x")->Equals(name));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011658 info.GetReturnValue().Set(call_ic_function4);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011659}
11660
11661
11662// This test checks that if interceptor provides a function,
11663// even if we cached shadowed variant, interceptor's function
11664// is invoked
11665THREADED_TEST(InterceptorCallICCacheableNotNeeded) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011666 v8::Isolate* isolate = CcTest::isolate();
11667 v8::HandleScope scope(isolate);
11668 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011669 templ->SetNamedPropertyHandler(InterceptorCallICGetter4);
11670 LocalContext context;
11671 context->Global()->Set(v8_str("o"), templ->NewInstance());
11672 call_ic_function4 =
11673 v8_compile("function f(x) { return x - 1; }; f")->Run();
11674 v8::Handle<Value> value = CompileRun(
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +000011675 "Object.getPrototypeOf(o).x = function(x) { return x + 1; };"
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011676 "var result = 0;"
11677 "for (var i = 0; i < 1000; i++) {"
11678 " result = o.x(42);"
11679 "}");
11680 CHECK_EQ(41, value->Int32Value());
11681}
11682
11683
11684// Test the case when we stored cacheable lookup into
11685// a stub, but it got invalidated later on
11686THREADED_TEST(InterceptorCallICInvalidatedCacheable) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011687 v8::Isolate* isolate = CcTest::isolate();
11688 v8::HandleScope scope(isolate);
11689 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011690 templ->SetNamedPropertyHandler(NoBlockGetterX);
11691 LocalContext context;
11692 context->Global()->Set(v8_str("o"), templ->NewInstance());
11693 v8::Handle<Value> value = CompileRun(
11694 "proto1 = new Object();"
11695 "proto2 = new Object();"
11696 "o.__proto__ = proto1;"
11697 "proto1.__proto__ = proto2;"
11698 "proto2.y = function(x) { return x + 1; };"
11699 // Invoke it many times to compile a stub
11700 "for (var i = 0; i < 7; i++) {"
11701 " o.y(42);"
11702 "}"
11703 "proto1.y = function(x) { return x - 1; };"
11704 "var result = 0;"
11705 "for (var i = 0; i < 7; i++) {"
11706 " result += o.y(42);"
11707 "}");
11708 CHECK_EQ(41 * 7, value->Int32Value());
11709}
11710
11711
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011712// This test checks that if interceptor doesn't provide a function,
11713// cached constant function is used
11714THREADED_TEST(InterceptorCallICConstantFunctionUsed) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011715 v8::Isolate* isolate = CcTest::isolate();
11716 v8::HandleScope scope(isolate);
11717 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011718 templ->SetNamedPropertyHandler(NoBlockGetterX);
11719 LocalContext context;
11720 context->Global()->Set(v8_str("o"), templ->NewInstance());
11721 v8::Handle<Value> value = CompileRun(
11722 "function inc(x) { return x + 1; };"
11723 "inc(1);"
11724 "o.x = inc;"
11725 "var result = 0;"
11726 "for (var i = 0; i < 1000; i++) {"
11727 " result = o.x(42);"
11728 "}");
11729 CHECK_EQ(43, value->Int32Value());
11730}
11731
11732
ulan@chromium.org2efb9002012-01-19 15:36:35 +000011733static v8::Handle<Value> call_ic_function5;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011734static void InterceptorCallICGetter5(
11735 Local<String> name,
11736 const v8::PropertyCallbackInfo<v8::Value>& info) {
ulan@chromium.org2efb9002012-01-19 15:36:35 +000011737 ApiTestFuzzer::Fuzz();
11738 if (v8_str("x")->Equals(name))
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011739 info.GetReturnValue().Set(call_ic_function5);
ulan@chromium.org2efb9002012-01-19 15:36:35 +000011740}
11741
11742
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011743// This test checks that if interceptor provides a function,
11744// even if we cached constant function, interceptor's function
11745// is invoked
11746THREADED_TEST(InterceptorCallICConstantFunctionNotNeeded) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011747 v8::Isolate* isolate = CcTest::isolate();
11748 v8::HandleScope scope(isolate);
11749 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011750 templ->SetNamedPropertyHandler(InterceptorCallICGetter5);
11751 LocalContext context;
11752 context->Global()->Set(v8_str("o"), templ->NewInstance());
11753 call_ic_function5 =
11754 v8_compile("function f(x) { return x - 1; }; f")->Run();
11755 v8::Handle<Value> value = CompileRun(
11756 "function inc(x) { return x + 1; };"
11757 "inc(1);"
11758 "o.x = inc;"
11759 "var result = 0;"
11760 "for (var i = 0; i < 1000; i++) {"
11761 " result = o.x(42);"
11762 "}");
11763 CHECK_EQ(41, value->Int32Value());
11764}
11765
11766
ulan@chromium.org2efb9002012-01-19 15:36:35 +000011767static v8::Handle<Value> call_ic_function6;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011768static void InterceptorCallICGetter6(
11769 Local<String> name,
11770 const v8::PropertyCallbackInfo<v8::Value>& info) {
ulan@chromium.org2efb9002012-01-19 15:36:35 +000011771 ApiTestFuzzer::Fuzz();
11772 if (v8_str("x")->Equals(name))
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011773 info.GetReturnValue().Set(call_ic_function6);
ulan@chromium.org2efb9002012-01-19 15:36:35 +000011774}
11775
11776
11777// Same test as above, except the code is wrapped in a function
11778// to test the optimized compiler.
11779THREADED_TEST(InterceptorCallICConstantFunctionNotNeededWrapped) {
11780 i::FLAG_allow_natives_syntax = true;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011781 v8::Isolate* isolate = CcTest::isolate();
11782 v8::HandleScope scope(isolate);
11783 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
ulan@chromium.org2efb9002012-01-19 15:36:35 +000011784 templ->SetNamedPropertyHandler(InterceptorCallICGetter6);
11785 LocalContext context;
11786 context->Global()->Set(v8_str("o"), templ->NewInstance());
11787 call_ic_function6 =
11788 v8_compile("function f(x) { return x - 1; }; f")->Run();
11789 v8::Handle<Value> value = CompileRun(
11790 "function inc(x) { return x + 1; };"
11791 "inc(1);"
11792 "o.x = inc;"
11793 "function test() {"
11794 " var result = 0;"
11795 " for (var i = 0; i < 1000; i++) {"
11796 " result = o.x(42);"
11797 " }"
11798 " return result;"
11799 "};"
11800 "test();"
11801 "test();"
11802 "test();"
11803 "%OptimizeFunctionOnNextCall(test);"
11804 "test()");
11805 CHECK_EQ(41, value->Int32Value());
11806}
11807
11808
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011809// Test the case when we stored constant function into
11810// a stub, but it got invalidated later on
11811THREADED_TEST(InterceptorCallICInvalidatedConstantFunction) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011812 v8::Isolate* isolate = CcTest::isolate();
11813 v8::HandleScope scope(isolate);
11814 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011815 templ->SetNamedPropertyHandler(NoBlockGetterX);
11816 LocalContext context;
11817 context->Global()->Set(v8_str("o"), templ->NewInstance());
11818 v8::Handle<Value> value = CompileRun(
11819 "function inc(x) { return x + 1; };"
11820 "inc(1);"
11821 "proto1 = new Object();"
11822 "proto2 = new Object();"
11823 "o.__proto__ = proto1;"
11824 "proto1.__proto__ = proto2;"
11825 "proto2.y = inc;"
11826 // Invoke it many times to compile a stub
11827 "for (var i = 0; i < 7; i++) {"
11828 " o.y(42);"
11829 "}"
11830 "proto1.y = function(x) { return x - 1; };"
11831 "var result = 0;"
11832 "for (var i = 0; i < 7; i++) {"
11833 " result += o.y(42);"
11834 "}");
11835 CHECK_EQ(41 * 7, value->Int32Value());
11836}
11837
11838
11839// Test the case when we stored constant function into
11840// a stub, but it got invalidated later on due to override on
11841// global object which is between interceptor and constant function' holders.
11842THREADED_TEST(InterceptorCallICInvalidatedConstantFunctionViaGlobal) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011843 v8::Isolate* isolate = CcTest::isolate();
11844 v8::HandleScope scope(isolate);
11845 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011846 templ->SetNamedPropertyHandler(NoBlockGetterX);
11847 LocalContext context;
11848 context->Global()->Set(v8_str("o"), templ->NewInstance());
11849 v8::Handle<Value> value = CompileRun(
11850 "function inc(x) { return x + 1; };"
11851 "inc(1);"
11852 "o.__proto__ = this;"
11853 "this.__proto__.y = inc;"
11854 // Invoke it many times to compile a stub
11855 "for (var i = 0; i < 7; i++) {"
11856 " if (o.y(42) != 43) throw 'oops: ' + o.y(42);"
11857 "}"
11858 "this.y = function(x) { return x - 1; };"
11859 "var result = 0;"
11860 "for (var i = 0; i < 7; i++) {"
11861 " result += o.y(42);"
11862 "}");
11863 CHECK_EQ(41 * 7, value->Int32Value());
11864}
11865
11866
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000011867// Test the case when actual function to call sits on global object.
11868THREADED_TEST(InterceptorCallICCachedFromGlobal) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011869 v8::Isolate* isolate = CcTest::isolate();
11870 v8::HandleScope scope(isolate);
11871 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000011872 templ_o->SetNamedPropertyHandler(NoBlockGetterX);
11873
11874 LocalContext context;
11875 context->Global()->Set(v8_str("o"), templ_o->NewInstance());
11876
11877 v8::Handle<Value> value = CompileRun(
11878 "try {"
11879 " o.__proto__ = this;"
11880 " for (var i = 0; i < 10; i++) {"
11881 " var v = o.parseFloat('239');"
11882 " if (v != 239) throw v;"
11883 // Now it should be ICed and keep a reference to parseFloat.
11884 " }"
11885 " var result = 0;"
11886 " for (var i = 0; i < 10; i++) {"
11887 " result += o.parseFloat('239');"
11888 " }"
11889 " result"
11890 "} catch(e) {"
11891 " e"
11892 "};");
11893 CHECK_EQ(239 * 10, value->Int32Value());
11894}
11895
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011896static void InterceptorCallICFastApi(
11897 Local<String> name,
11898 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.org5c838252010-02-19 08:53:10 +000011899 ApiTestFuzzer::Fuzz();
dslomov@chromium.orgb752d402013-06-18 11:54:54 +000011900 CheckReturnValue(info, FUNCTION_ADDR(InterceptorCallICFastApi));
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000011901 int* call_count =
11902 reinterpret_cast<int*>(v8::External::Cast(*info.Data())->Value());
ager@chromium.org5c838252010-02-19 08:53:10 +000011903 ++(*call_count);
11904 if ((*call_count) % 20 == 0) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011905 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org5c838252010-02-19 08:53:10 +000011906 }
ager@chromium.org5c838252010-02-19 08:53:10 +000011907}
11908
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011909static void FastApiCallback_TrivialSignature(
11910 const v8::FunctionCallbackInfo<v8::Value>& args) {
ager@chromium.org5c838252010-02-19 08:53:10 +000011911 ApiTestFuzzer::Fuzz();
dslomov@chromium.orgb752d402013-06-18 11:54:54 +000011912 CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_TrivialSignature));
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011913 v8::Isolate* isolate = CcTest::isolate();
jkummerow@chromium.org28faa982012-04-13 09:58:30 +000011914 CHECK_EQ(isolate, args.GetIsolate());
ager@chromium.org5c838252010-02-19 08:53:10 +000011915 CHECK_EQ(args.This(), args.Holder());
11916 CHECK(args.Data()->Equals(v8_str("method_data")));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011917 args.GetReturnValue().Set(args[0]->Int32Value() + 1);
ager@chromium.org5c838252010-02-19 08:53:10 +000011918}
11919
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011920static void FastApiCallback_SimpleSignature(
11921 const v8::FunctionCallbackInfo<v8::Value>& args) {
ager@chromium.org5c838252010-02-19 08:53:10 +000011922 ApiTestFuzzer::Fuzz();
dslomov@chromium.orgb752d402013-06-18 11:54:54 +000011923 CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_SimpleSignature));
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011924 v8::Isolate* isolate = CcTest::isolate();
jkummerow@chromium.org28faa982012-04-13 09:58:30 +000011925 CHECK_EQ(isolate, args.GetIsolate());
ager@chromium.org5c838252010-02-19 08:53:10 +000011926 CHECK_EQ(args.This()->GetPrototype(), args.Holder());
11927 CHECK(args.Data()->Equals(v8_str("method_data")));
11928 // Note, we're using HasRealNamedProperty instead of Has to avoid
11929 // invoking the interceptor again.
11930 CHECK(args.Holder()->HasRealNamedProperty(v8_str("foo")));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011931 args.GetReturnValue().Set(args[0]->Int32Value() + 1);
ager@chromium.org5c838252010-02-19 08:53:10 +000011932}
11933
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000011934
ager@chromium.org5c838252010-02-19 08:53:10 +000011935// Helper to maximize the odds of object moving.
11936static void GenerateSomeGarbage() {
11937 CompileRun(
11938 "var garbage;"
11939 "for (var i = 0; i < 1000; i++) {"
11940 " garbage = [1/i, \"garbage\" + i, garbage, {foo: garbage}];"
11941 "}"
11942 "garbage = undefined;");
11943}
11944
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000011945
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011946void DirectApiCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +000011947 static int count = 0;
11948 if (count++ % 3 == 0) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011949 CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
yangguo@chromium.orgd2899aa2012-06-21 11:16:20 +000011950 // This should move the stub
ricow@chromium.org83aa5492011-02-07 12:42:56 +000011951 GenerateSomeGarbage(); // This should ensure the old stub memory is flushed
11952 }
ricow@chromium.org83aa5492011-02-07 12:42:56 +000011953}
11954
11955
11956THREADED_TEST(CallICFastApi_DirectCall_GCMoveStub) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +000011957 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000011958 v8::Isolate* isolate = context->GetIsolate();
11959 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011960 v8::Handle<v8::ObjectTemplate> nativeobject_templ =
11961 v8::ObjectTemplate::New(isolate);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000011962 nativeobject_templ->Set(isolate, "callback",
11963 v8::FunctionTemplate::New(isolate,
11964 DirectApiCallback));
ricow@chromium.org83aa5492011-02-07 12:42:56 +000011965 v8::Local<v8::Object> nativeobject_obj = nativeobject_templ->NewInstance();
11966 context->Global()->Set(v8_str("nativeobject"), nativeobject_obj);
11967 // call the api function multiple times to ensure direct call stub creation.
11968 CompileRun(
11969 "function f() {"
11970 " for (var i = 1; i <= 30; i++) {"
11971 " nativeobject.callback();"
11972 " }"
11973 "}"
11974 "f();");
11975}
11976
11977
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011978void ThrowingDirectApiCallback(
11979 const v8::FunctionCallbackInfo<v8::Value>& args) {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000011980 args.GetIsolate()->ThrowException(v8_str("g"));
ricow@chromium.org83aa5492011-02-07 12:42:56 +000011981}
11982
11983
11984THREADED_TEST(CallICFastApi_DirectCall_Throw) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +000011985 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000011986 v8::Isolate* isolate = context->GetIsolate();
11987 v8::HandleScope scope(isolate);
11988 v8::Handle<v8::ObjectTemplate> nativeobject_templ =
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011989 v8::ObjectTemplate::New(isolate);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000011990 nativeobject_templ->Set(isolate, "callback",
11991 v8::FunctionTemplate::New(isolate,
11992 ThrowingDirectApiCallback));
ricow@chromium.org83aa5492011-02-07 12:42:56 +000011993 v8::Local<v8::Object> nativeobject_obj = nativeobject_templ->NewInstance();
11994 context->Global()->Set(v8_str("nativeobject"), nativeobject_obj);
11995 // call the api function multiple times to ensure direct call stub creation.
11996 v8::Handle<Value> result = CompileRun(
11997 "var result = '';"
11998 "function f() {"
11999 " for (var i = 1; i <= 5; i++) {"
12000 " try { nativeobject.callback(); } catch (e) { result += e; }"
12001 " }"
12002 "}"
12003 "f(); result;");
12004 CHECK_EQ(v8_str("ggggg"), result);
12005}
12006
12007
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000012008static Handle<Value> DoDirectGetter() {
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000012009 if (++p_getter_count % 3 == 0) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000012010 CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000012011 GenerateSomeGarbage();
12012 }
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000012013 return v8_str("Direct Getter Result");
12014}
12015
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000012016static void DirectGetterCallback(
12017 Local<String> name,
12018 const v8::PropertyCallbackInfo<v8::Value>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +000012019 CheckReturnValue(info, FUNCTION_ADDR(DirectGetterCallback));
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000012020 info.GetReturnValue().Set(DoDirectGetter());
12021}
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000012022
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000012023
12024template<typename Accessor>
12025static void LoadICFastApi_DirectCall_GCMoveStub(Accessor accessor) {
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000012026 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012027 v8::Isolate* isolate = context->GetIsolate();
12028 v8::HandleScope scope(isolate);
12029 v8::Handle<v8::ObjectTemplate> obj = v8::ObjectTemplate::New(isolate);
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000012030 obj->SetAccessor(v8_str("p1"), accessor);
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000012031 context->Global()->Set(v8_str("o1"), obj->NewInstance());
12032 p_getter_count = 0;
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000012033 v8::Handle<v8::Value> result = CompileRun(
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000012034 "function f() {"
12035 " for (var i = 0; i < 30; i++) o1.p1;"
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000012036 " return o1.p1"
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000012037 "}"
12038 "f();");
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000012039 CHECK_EQ(v8_str("Direct Getter Result"), result);
12040 CHECK_EQ(31, p_getter_count);
12041}
12042
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012043
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012044THREADED_PROFILED_TEST(LoadICFastApi_DirectCall_GCMoveStub) {
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000012045 LoadICFastApi_DirectCall_GCMoveStub(DirectGetterCallback);
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000012046}
12047
12048
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012049void ThrowingDirectGetterCallback(
12050 Local<String> name,
12051 const v8::PropertyCallbackInfo<v8::Value>& info) {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000012052 info.GetIsolate()->ThrowException(v8_str("g"));
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000012053}
12054
12055
12056THREADED_TEST(LoadICFastApi_DirectCall_Throw) {
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000012057 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012058 v8::Isolate* isolate = context->GetIsolate();
12059 v8::HandleScope scope(isolate);
12060 v8::Handle<v8::ObjectTemplate> obj = v8::ObjectTemplate::New(isolate);
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000012061 obj->SetAccessor(v8_str("p1"), ThrowingDirectGetterCallback);
12062 context->Global()->Set(v8_str("o1"), obj->NewInstance());
12063 v8::Handle<Value> result = CompileRun(
12064 "var result = '';"
12065 "for (var i = 0; i < 5; i++) {"
12066 " try { o1.p1; } catch (e) { result += e; }"
12067 "}"
12068 "result;");
12069 CHECK_EQ(v8_str("ggggg"), result);
12070}
12071
12072
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012073THREADED_PROFILED_TEST(InterceptorCallICFastApi_TrivialSignature) {
ager@chromium.org5c838252010-02-19 08:53:10 +000012074 int interceptor_call_count = 0;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012075 v8::Isolate* isolate = CcTest::isolate();
12076 v8::HandleScope scope(isolate);
12077 v8::Handle<v8::FunctionTemplate> fun_templ =
12078 v8::FunctionTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +000012079 v8::Handle<v8::FunctionTemplate> method_templ =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012080 v8::FunctionTemplate::New(isolate,
12081 FastApiCallback_TrivialSignature,
ager@chromium.org5c838252010-02-19 08:53:10 +000012082 v8_str("method_data"),
12083 v8::Handle<v8::Signature>());
12084 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12085 proto_templ->Set(v8_str("method"), method_templ);
12086 v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
machenbach@chromium.org0cc09502013-11-13 12:20:55 +000012087 templ->SetNamedPropertyHandler(
12088 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012089 v8::External::New(isolate, &interceptor_call_count));
ager@chromium.org5c838252010-02-19 08:53:10 +000012090 LocalContext context;
12091 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12092 GenerateSomeGarbage();
12093 context->Global()->Set(v8_str("o"), fun->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012094 CompileRun(
ager@chromium.org5c838252010-02-19 08:53:10 +000012095 "var result = 0;"
12096 "for (var i = 0; i < 100; i++) {"
12097 " result = o.method(41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012098 "}");
ager@chromium.org5c838252010-02-19 08:53:10 +000012099 CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
12100 CHECK_EQ(100, interceptor_call_count);
12101}
12102
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012103
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012104THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature) {
ager@chromium.org5c838252010-02-19 08:53:10 +000012105 int interceptor_call_count = 0;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012106 v8::Isolate* isolate = CcTest::isolate();
12107 v8::HandleScope scope(isolate);
12108 v8::Handle<v8::FunctionTemplate> fun_templ =
12109 v8::FunctionTemplate::New(isolate);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000012110 v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012111 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12112 v8::Signature::New(isolate, fun_templ));
ager@chromium.org5c838252010-02-19 08:53:10 +000012113 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12114 proto_templ->Set(v8_str("method"), method_templ);
mmassi@chromium.org49a44672012-12-04 13:52:03 +000012115 fun_templ->SetHiddenPrototype(true);
ager@chromium.org5c838252010-02-19 08:53:10 +000012116 v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
machenbach@chromium.org0cc09502013-11-13 12:20:55 +000012117 templ->SetNamedPropertyHandler(
12118 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012119 v8::External::New(isolate, &interceptor_call_count));
ager@chromium.org5c838252010-02-19 08:53:10 +000012120 LocalContext context;
12121 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12122 GenerateSomeGarbage();
12123 context->Global()->Set(v8_str("o"), fun->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012124 CompileRun(
ager@chromium.org5c838252010-02-19 08:53:10 +000012125 "o.foo = 17;"
12126 "var receiver = {};"
12127 "receiver.__proto__ = o;"
12128 "var result = 0;"
12129 "for (var i = 0; i < 100; i++) {"
12130 " result = receiver.method(41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012131 "}");
ager@chromium.org5c838252010-02-19 08:53:10 +000012132 CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
12133 CHECK_EQ(100, interceptor_call_count);
12134}
12135
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012136
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012137THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss1) {
ager@chromium.org5c838252010-02-19 08:53:10 +000012138 int interceptor_call_count = 0;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012139 v8::Isolate* isolate = CcTest::isolate();
12140 v8::HandleScope scope(isolate);
12141 v8::Handle<v8::FunctionTemplate> fun_templ =
12142 v8::FunctionTemplate::New(isolate);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000012143 v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012144 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12145 v8::Signature::New(isolate, fun_templ));
ager@chromium.org5c838252010-02-19 08:53:10 +000012146 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12147 proto_templ->Set(v8_str("method"), method_templ);
mmassi@chromium.org49a44672012-12-04 13:52:03 +000012148 fun_templ->SetHiddenPrototype(true);
ager@chromium.org5c838252010-02-19 08:53:10 +000012149 v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
machenbach@chromium.org0cc09502013-11-13 12:20:55 +000012150 templ->SetNamedPropertyHandler(
12151 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012152 v8::External::New(isolate, &interceptor_call_count));
ager@chromium.org5c838252010-02-19 08:53:10 +000012153 LocalContext context;
12154 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12155 GenerateSomeGarbage();
12156 context->Global()->Set(v8_str("o"), fun->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012157 CompileRun(
ager@chromium.org5c838252010-02-19 08:53:10 +000012158 "o.foo = 17;"
12159 "var receiver = {};"
12160 "receiver.__proto__ = o;"
12161 "var result = 0;"
12162 "var saved_result = 0;"
12163 "for (var i = 0; i < 100; i++) {"
12164 " result = receiver.method(41);"
12165 " if (i == 50) {"
12166 " saved_result = result;"
12167 " receiver = {method: function(x) { return x - 1 }};"
12168 " }"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012169 "}");
ager@chromium.org5c838252010-02-19 08:53:10 +000012170 CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
12171 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
12172 CHECK_GE(interceptor_call_count, 50);
12173}
12174
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012175
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012176THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss2) {
ager@chromium.org5c838252010-02-19 08:53:10 +000012177 int interceptor_call_count = 0;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012178 v8::Isolate* isolate = CcTest::isolate();
12179 v8::HandleScope scope(isolate);
12180 v8::Handle<v8::FunctionTemplate> fun_templ =
12181 v8::FunctionTemplate::New(isolate);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000012182 v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012183 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12184 v8::Signature::New(isolate, fun_templ));
ager@chromium.org5c838252010-02-19 08:53:10 +000012185 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12186 proto_templ->Set(v8_str("method"), method_templ);
mmassi@chromium.org49a44672012-12-04 13:52:03 +000012187 fun_templ->SetHiddenPrototype(true);
ager@chromium.org5c838252010-02-19 08:53:10 +000012188 v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
machenbach@chromium.org0cc09502013-11-13 12:20:55 +000012189 templ->SetNamedPropertyHandler(
12190 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012191 v8::External::New(isolate, &interceptor_call_count));
ager@chromium.org5c838252010-02-19 08:53:10 +000012192 LocalContext context;
12193 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12194 GenerateSomeGarbage();
12195 context->Global()->Set(v8_str("o"), fun->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012196 CompileRun(
ager@chromium.org5c838252010-02-19 08:53:10 +000012197 "o.foo = 17;"
12198 "var receiver = {};"
12199 "receiver.__proto__ = o;"
12200 "var result = 0;"
12201 "var saved_result = 0;"
12202 "for (var i = 0; i < 100; i++) {"
12203 " result = receiver.method(41);"
12204 " if (i == 50) {"
12205 " saved_result = result;"
12206 " o.method = function(x) { return x - 1 };"
12207 " }"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012208 "}");
ager@chromium.org5c838252010-02-19 08:53:10 +000012209 CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
12210 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
12211 CHECK_GE(interceptor_call_count, 50);
12212}
12213
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012214
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012215THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss3) {
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000012216 int interceptor_call_count = 0;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012217 v8::Isolate* isolate = CcTest::isolate();
12218 v8::HandleScope scope(isolate);
12219 v8::Handle<v8::FunctionTemplate> fun_templ =
12220 v8::FunctionTemplate::New(isolate);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000012221 v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012222 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12223 v8::Signature::New(isolate, fun_templ));
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000012224 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12225 proto_templ->Set(v8_str("method"), method_templ);
mmassi@chromium.org49a44672012-12-04 13:52:03 +000012226 fun_templ->SetHiddenPrototype(true);
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000012227 v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
machenbach@chromium.org0cc09502013-11-13 12:20:55 +000012228 templ->SetNamedPropertyHandler(
12229 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012230 v8::External::New(isolate, &interceptor_call_count));
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000012231 LocalContext context;
12232 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12233 GenerateSomeGarbage();
12234 context->Global()->Set(v8_str("o"), fun->NewInstance());
12235 v8::TryCatch try_catch;
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012236 CompileRun(
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000012237 "o.foo = 17;"
12238 "var receiver = {};"
12239 "receiver.__proto__ = o;"
12240 "var result = 0;"
12241 "var saved_result = 0;"
12242 "for (var i = 0; i < 100; i++) {"
12243 " result = receiver.method(41);"
12244 " if (i == 50) {"
12245 " saved_result = result;"
12246 " receiver = 333;"
12247 " }"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012248 "}");
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000012249 CHECK(try_catch.HasCaught());
12250 CHECK_EQ(v8_str("TypeError: Object 333 has no method 'method'"),
12251 try_catch.Exception()->ToString());
12252 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
12253 CHECK_GE(interceptor_call_count, 50);
12254}
12255
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012256
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012257THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_TypeError) {
ager@chromium.org5c838252010-02-19 08:53:10 +000012258 int interceptor_call_count = 0;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012259 v8::Isolate* isolate = CcTest::isolate();
12260 v8::HandleScope scope(isolate);
12261 v8::Handle<v8::FunctionTemplate> fun_templ =
12262 v8::FunctionTemplate::New(isolate);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000012263 v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012264 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12265 v8::Signature::New(isolate, fun_templ));
ager@chromium.org5c838252010-02-19 08:53:10 +000012266 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12267 proto_templ->Set(v8_str("method"), method_templ);
mmassi@chromium.org49a44672012-12-04 13:52:03 +000012268 fun_templ->SetHiddenPrototype(true);
ager@chromium.org5c838252010-02-19 08:53:10 +000012269 v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
machenbach@chromium.org0cc09502013-11-13 12:20:55 +000012270 templ->SetNamedPropertyHandler(
12271 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012272 v8::External::New(isolate, &interceptor_call_count));
ager@chromium.org5c838252010-02-19 08:53:10 +000012273 LocalContext context;
12274 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12275 GenerateSomeGarbage();
12276 context->Global()->Set(v8_str("o"), fun->NewInstance());
12277 v8::TryCatch try_catch;
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012278 CompileRun(
ager@chromium.org5c838252010-02-19 08:53:10 +000012279 "o.foo = 17;"
12280 "var receiver = {};"
12281 "receiver.__proto__ = o;"
12282 "var result = 0;"
12283 "var saved_result = 0;"
12284 "for (var i = 0; i < 100; i++) {"
12285 " result = receiver.method(41);"
12286 " if (i == 50) {"
12287 " saved_result = result;"
12288 " receiver = {method: receiver.method};"
12289 " }"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012290 "}");
ager@chromium.org5c838252010-02-19 08:53:10 +000012291 CHECK(try_catch.HasCaught());
12292 CHECK_EQ(v8_str("TypeError: Illegal invocation"),
12293 try_catch.Exception()->ToString());
12294 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
12295 CHECK_GE(interceptor_call_count, 50);
12296}
12297
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012298
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012299THREADED_PROFILED_TEST(CallICFastApi_TrivialSignature) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012300 v8::Isolate* isolate = CcTest::isolate();
12301 v8::HandleScope scope(isolate);
12302 v8::Handle<v8::FunctionTemplate> fun_templ =
12303 v8::FunctionTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +000012304 v8::Handle<v8::FunctionTemplate> method_templ =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012305 v8::FunctionTemplate::New(isolate,
12306 FastApiCallback_TrivialSignature,
ager@chromium.org5c838252010-02-19 08:53:10 +000012307 v8_str("method_data"),
12308 v8::Handle<v8::Signature>());
12309 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12310 proto_templ->Set(v8_str("method"), method_templ);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000012311 v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012312 USE(templ);
ager@chromium.org5c838252010-02-19 08:53:10 +000012313 LocalContext context;
12314 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12315 GenerateSomeGarbage();
12316 context->Global()->Set(v8_str("o"), fun->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012317 CompileRun(
ager@chromium.org5c838252010-02-19 08:53:10 +000012318 "var result = 0;"
12319 "for (var i = 0; i < 100; i++) {"
12320 " result = o.method(41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012321 "}");
ager@chromium.org5c838252010-02-19 08:53:10 +000012322
12323 CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
12324}
12325
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012326
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012327THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012328 v8::Isolate* isolate = CcTest::isolate();
12329 v8::HandleScope scope(isolate);
12330 v8::Handle<v8::FunctionTemplate> fun_templ =
12331 v8::FunctionTemplate::New(isolate);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000012332 v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012333 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12334 v8::Signature::New(isolate, fun_templ));
ager@chromium.org5c838252010-02-19 08:53:10 +000012335 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12336 proto_templ->Set(v8_str("method"), method_templ);
mmassi@chromium.org49a44672012-12-04 13:52:03 +000012337 fun_templ->SetHiddenPrototype(true);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000012338 v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012339 CHECK(!templ.IsEmpty());
ager@chromium.org5c838252010-02-19 08:53:10 +000012340 LocalContext context;
12341 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12342 GenerateSomeGarbage();
12343 context->Global()->Set(v8_str("o"), fun->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012344 CompileRun(
ager@chromium.org5c838252010-02-19 08:53:10 +000012345 "o.foo = 17;"
12346 "var receiver = {};"
12347 "receiver.__proto__ = o;"
12348 "var result = 0;"
12349 "for (var i = 0; i < 100; i++) {"
12350 " result = receiver.method(41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012351 "}");
ager@chromium.org5c838252010-02-19 08:53:10 +000012352
12353 CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
12354}
12355
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012356
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012357THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss1) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012358 v8::Isolate* isolate = CcTest::isolate();
12359 v8::HandleScope scope(isolate);
12360 v8::Handle<v8::FunctionTemplate> fun_templ =
12361 v8::FunctionTemplate::New(isolate);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000012362 v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012363 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12364 v8::Signature::New(isolate, fun_templ));
ager@chromium.org5c838252010-02-19 08:53:10 +000012365 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12366 proto_templ->Set(v8_str("method"), method_templ);
mmassi@chromium.org49a44672012-12-04 13:52:03 +000012367 fun_templ->SetHiddenPrototype(true);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000012368 v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012369 CHECK(!templ.IsEmpty());
ager@chromium.org5c838252010-02-19 08:53:10 +000012370 LocalContext context;
12371 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12372 GenerateSomeGarbage();
12373 context->Global()->Set(v8_str("o"), fun->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012374 CompileRun(
ager@chromium.org5c838252010-02-19 08:53:10 +000012375 "o.foo = 17;"
12376 "var receiver = {};"
12377 "receiver.__proto__ = o;"
12378 "var result = 0;"
12379 "var saved_result = 0;"
12380 "for (var i = 0; i < 100; i++) {"
12381 " result = receiver.method(41);"
12382 " if (i == 50) {"
12383 " saved_result = result;"
12384 " receiver = {method: function(x) { return x - 1 }};"
12385 " }"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012386 "}");
ager@chromium.org5c838252010-02-19 08:53:10 +000012387 CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
12388 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
12389}
12390
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012391
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012392THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss2) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012393 v8::Isolate* isolate = CcTest::isolate();
12394 v8::HandleScope scope(isolate);
12395 v8::Handle<v8::FunctionTemplate> fun_templ =
12396 v8::FunctionTemplate::New(isolate);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000012397 v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012398 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12399 v8::Signature::New(isolate, fun_templ));
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000012400 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12401 proto_templ->Set(v8_str("method"), method_templ);
mmassi@chromium.org49a44672012-12-04 13:52:03 +000012402 fun_templ->SetHiddenPrototype(true);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000012403 v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012404 CHECK(!templ.IsEmpty());
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000012405 LocalContext context;
12406 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12407 GenerateSomeGarbage();
12408 context->Global()->Set(v8_str("o"), fun->NewInstance());
12409 v8::TryCatch try_catch;
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012410 CompileRun(
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000012411 "o.foo = 17;"
12412 "var receiver = {};"
12413 "receiver.__proto__ = o;"
12414 "var result = 0;"
12415 "var saved_result = 0;"
12416 "for (var i = 0; i < 100; i++) {"
12417 " result = receiver.method(41);"
12418 " if (i == 50) {"
12419 " saved_result = result;"
12420 " receiver = 333;"
12421 " }"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012422 "}");
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000012423 CHECK(try_catch.HasCaught());
12424 CHECK_EQ(v8_str("TypeError: Object 333 has no method 'method'"),
12425 try_catch.Exception()->ToString());
12426 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
12427}
12428
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012429
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012430THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_TypeError) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012431 v8::Isolate* isolate = CcTest::isolate();
12432 v8::HandleScope scope(isolate);
12433 v8::Handle<v8::FunctionTemplate> fun_templ =
12434 v8::FunctionTemplate::New(isolate);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000012435 v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012436 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12437 v8::Signature::New(isolate, fun_templ));
mmassi@chromium.org49a44672012-12-04 13:52:03 +000012438 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12439 proto_templ->Set(v8_str("method"), method_templ);
12440 fun_templ->SetHiddenPrototype(true);
12441 v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
12442 CHECK(!templ.IsEmpty());
12443 LocalContext context;
12444 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12445 GenerateSomeGarbage();
12446 context->Global()->Set(v8_str("o"), fun->NewInstance());
12447 v8::TryCatch try_catch;
12448 CompileRun(
12449 "o.foo = 17;"
12450 "var receiver = {};"
12451 "receiver.__proto__ = o;"
12452 "var result = 0;"
12453 "var saved_result = 0;"
12454 "for (var i = 0; i < 100; i++) {"
12455 " result = receiver.method(41);"
12456 " if (i == 50) {"
12457 " saved_result = result;"
12458 " receiver = Object.create(receiver);"
12459 " }"
12460 "}");
12461 CHECK(try_catch.HasCaught());
12462 CHECK_EQ(v8_str("TypeError: Illegal invocation"),
12463 try_catch.Exception()->ToString());
12464 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
12465}
12466
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000012467
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012468v8::Handle<Value> keyed_call_ic_function;
12469
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012470static void InterceptorKeyedCallICGetter(
12471 Local<String> name,
12472 const v8::PropertyCallbackInfo<v8::Value>& info) {
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012473 ApiTestFuzzer::Fuzz();
12474 if (v8_str("x")->Equals(name)) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012475 info.GetReturnValue().Set(keyed_call_ic_function);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012476 }
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012477}
12478
12479
12480// Test the case when we stored cacheable lookup into
12481// a stub, but the function name changed (to another cacheable function).
12482THREADED_TEST(InterceptorKeyedCallICKeyChange1) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012483 v8::Isolate* isolate = CcTest::isolate();
12484 v8::HandleScope scope(isolate);
12485 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012486 templ->SetNamedPropertyHandler(NoBlockGetterX);
12487 LocalContext context;
12488 context->Global()->Set(v8_str("o"), templ->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012489 CompileRun(
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012490 "proto = new Object();"
12491 "proto.y = function(x) { return x + 1; };"
12492 "proto.z = function(x) { return x - 1; };"
12493 "o.__proto__ = proto;"
12494 "var result = 0;"
12495 "var method = 'y';"
12496 "for (var i = 0; i < 10; i++) {"
12497 " if (i == 5) { method = 'z'; };"
12498 " result += o[method](41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012499 "}");
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012500 CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
12501}
12502
12503
12504// Test the case when we stored cacheable lookup into
12505// a stub, but the function name changed (and the new function is present
12506// both before and after the interceptor in the prototype chain).
12507THREADED_TEST(InterceptorKeyedCallICKeyChange2) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012508 v8::Isolate* isolate = CcTest::isolate();
12509 v8::HandleScope scope(isolate);
12510 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012511 templ->SetNamedPropertyHandler(InterceptorKeyedCallICGetter);
12512 LocalContext context;
12513 context->Global()->Set(v8_str("proto1"), templ->NewInstance());
12514 keyed_call_ic_function =
12515 v8_compile("function f(x) { return x - 1; }; f")->Run();
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012516 CompileRun(
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012517 "o = new Object();"
12518 "proto2 = new Object();"
12519 "o.y = function(x) { return x + 1; };"
12520 "proto2.y = function(x) { return x + 2; };"
12521 "o.__proto__ = proto1;"
12522 "proto1.__proto__ = proto2;"
12523 "var result = 0;"
12524 "var method = 'x';"
12525 "for (var i = 0; i < 10; i++) {"
12526 " if (i == 5) { method = 'y'; };"
12527 " result += o[method](41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012528 "}");
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012529 CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
12530}
12531
12532
12533// Same as InterceptorKeyedCallICKeyChange1 only the cacheable function sit
12534// on the global object.
12535THREADED_TEST(InterceptorKeyedCallICKeyChangeOnGlobal) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012536 v8::Isolate* isolate = CcTest::isolate();
12537 v8::HandleScope scope(isolate);
12538 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012539 templ->SetNamedPropertyHandler(NoBlockGetterX);
12540 LocalContext context;
12541 context->Global()->Set(v8_str("o"), templ->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012542 CompileRun(
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012543 "function inc(x) { return x + 1; };"
12544 "inc(1);"
12545 "function dec(x) { return x - 1; };"
12546 "dec(1);"
12547 "o.__proto__ = this;"
12548 "this.__proto__.x = inc;"
12549 "this.__proto__.y = dec;"
12550 "var result = 0;"
12551 "var method = 'x';"
12552 "for (var i = 0; i < 10; i++) {"
12553 " if (i == 5) { method = 'y'; };"
12554 " result += o[method](41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012555 "}");
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012556 CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
12557}
12558
12559
12560// Test the case when actual function to call sits on global object.
12561THREADED_TEST(InterceptorKeyedCallICFromGlobal) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012562 v8::Isolate* isolate = CcTest::isolate();
12563 v8::HandleScope scope(isolate);
12564 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012565 templ_o->SetNamedPropertyHandler(NoBlockGetterX);
12566 LocalContext context;
12567 context->Global()->Set(v8_str("o"), templ_o->NewInstance());
12568
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012569 CompileRun(
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012570 "function len(x) { return x.length; };"
12571 "o.__proto__ = this;"
12572 "var m = 'parseFloat';"
12573 "var result = 0;"
12574 "for (var i = 0; i < 10; i++) {"
12575 " if (i == 5) {"
12576 " m = 'len';"
12577 " saved_result = result;"
12578 " };"
12579 " result = o[m]('239');"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012580 "}");
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012581 CHECK_EQ(3, context->Global()->Get(v8_str("result"))->Int32Value());
12582 CHECK_EQ(239, context->Global()->Get(v8_str("saved_result"))->Int32Value());
12583}
12584
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012585
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012586// Test the map transition before the interceptor.
12587THREADED_TEST(InterceptorKeyedCallICMapChangeBefore) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012588 v8::Isolate* isolate = CcTest::isolate();
12589 v8::HandleScope scope(isolate);
12590 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012591 templ_o->SetNamedPropertyHandler(NoBlockGetterX);
12592 LocalContext context;
12593 context->Global()->Set(v8_str("proto"), templ_o->NewInstance());
12594
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012595 CompileRun(
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012596 "var o = new Object();"
12597 "o.__proto__ = proto;"
12598 "o.method = function(x) { return x + 1; };"
12599 "var m = 'method';"
12600 "var result = 0;"
12601 "for (var i = 0; i < 10; i++) {"
12602 " if (i == 5) { o.method = function(x) { return x - 1; }; };"
12603 " result += o[m](41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012604 "}");
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012605 CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
12606}
12607
12608
12609// Test the map transition after the interceptor.
12610THREADED_TEST(InterceptorKeyedCallICMapChangeAfter) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012611 v8::Isolate* isolate = CcTest::isolate();
12612 v8::HandleScope scope(isolate);
12613 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012614 templ_o->SetNamedPropertyHandler(NoBlockGetterX);
12615 LocalContext context;
12616 context->Global()->Set(v8_str("o"), templ_o->NewInstance());
12617
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012618 CompileRun(
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012619 "var proto = new Object();"
12620 "o.__proto__ = proto;"
12621 "proto.method = function(x) { return x + 1; };"
12622 "var m = 'method';"
12623 "var result = 0;"
12624 "for (var i = 0; i < 10; i++) {"
12625 " if (i == 5) { proto.method = function(x) { return x - 1; }; };"
12626 " result += o[m](41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012627 "}");
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012628 CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
12629}
12630
12631
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012632static int interceptor_call_count = 0;
12633
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012634static void InterceptorICRefErrorGetter(
12635 Local<String> name,
12636 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012637 ApiTestFuzzer::Fuzz();
12638 if (v8_str("x")->Equals(name) && interceptor_call_count++ < 20) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012639 info.GetReturnValue().Set(call_ic_function2);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012640 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012641}
12642
12643
12644// This test should hit load and call ICs for the interceptor case.
12645// Once in a while, the interceptor will reply that a property was not
12646// found in which case we should get a reference error.
12647THREADED_TEST(InterceptorICReferenceErrors) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012648 v8::Isolate* isolate = CcTest::isolate();
12649 v8::HandleScope scope(isolate);
12650 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012651 templ->SetNamedPropertyHandler(InterceptorICRefErrorGetter);
12652 LocalContext context(0, templ, v8::Handle<Value>());
12653 call_ic_function2 = v8_compile("function h(x) { return x; }; h")->Run();
12654 v8::Handle<Value> value = CompileRun(
12655 "function f() {"
12656 " for (var i = 0; i < 1000; i++) {"
12657 " try { x; } catch(e) { return true; }"
12658 " }"
12659 " return false;"
12660 "};"
12661 "f();");
12662 CHECK_EQ(true, value->BooleanValue());
12663 interceptor_call_count = 0;
12664 value = CompileRun(
12665 "function g() {"
12666 " for (var i = 0; i < 1000; i++) {"
12667 " try { x(42); } catch(e) { return true; }"
12668 " }"
12669 " return false;"
12670 "};"
12671 "g();");
12672 CHECK_EQ(true, value->BooleanValue());
12673}
12674
12675
12676static int interceptor_ic_exception_get_count = 0;
12677
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012678static void InterceptorICExceptionGetter(
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012679 Local<String> name,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012680 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012681 ApiTestFuzzer::Fuzz();
12682 if (v8_str("x")->Equals(name) && ++interceptor_ic_exception_get_count < 20) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012683 info.GetReturnValue().Set(call_ic_function3);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012684 }
12685 if (interceptor_ic_exception_get_count == 20) {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000012686 info.GetIsolate()->ThrowException(v8_num(42));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012687 return;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012688 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012689}
12690
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012691
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012692// Test interceptor load/call IC where the interceptor throws an
12693// exception once in a while.
12694THREADED_TEST(InterceptorICGetterExceptions) {
12695 interceptor_ic_exception_get_count = 0;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012696 v8::Isolate* isolate = CcTest::isolate();
12697 v8::HandleScope scope(isolate);
12698 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012699 templ->SetNamedPropertyHandler(InterceptorICExceptionGetter);
12700 LocalContext context(0, templ, v8::Handle<Value>());
12701 call_ic_function3 = v8_compile("function h(x) { return x; }; h")->Run();
12702 v8::Handle<Value> value = CompileRun(
12703 "function f() {"
12704 " for (var i = 0; i < 100; i++) {"
12705 " try { x; } catch(e) { return true; }"
12706 " }"
12707 " return false;"
12708 "};"
12709 "f();");
12710 CHECK_EQ(true, value->BooleanValue());
12711 interceptor_ic_exception_get_count = 0;
12712 value = CompileRun(
12713 "function f() {"
12714 " for (var i = 0; i < 100; i++) {"
12715 " try { x(42); } catch(e) { return true; }"
12716 " }"
12717 " return false;"
12718 "};"
12719 "f();");
12720 CHECK_EQ(true, value->BooleanValue());
12721}
12722
12723
12724static int interceptor_ic_exception_set_count = 0;
12725
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012726static void InterceptorICExceptionSetter(
12727 Local<String> key,
12728 Local<Value> value,
12729 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012730 ApiTestFuzzer::Fuzz();
12731 if (++interceptor_ic_exception_set_count > 20) {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000012732 info.GetIsolate()->ThrowException(v8_num(42));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012733 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012734}
12735
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012736
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012737// Test interceptor store IC where the interceptor throws an exception
12738// once in a while.
12739THREADED_TEST(InterceptorICSetterExceptions) {
12740 interceptor_ic_exception_set_count = 0;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012741 v8::Isolate* isolate = CcTest::isolate();
12742 v8::HandleScope scope(isolate);
12743 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012744 templ->SetNamedPropertyHandler(0, InterceptorICExceptionSetter);
12745 LocalContext context(0, templ, v8::Handle<Value>());
12746 v8::Handle<Value> value = CompileRun(
12747 "function f() {"
12748 " for (var i = 0; i < 100; i++) {"
12749 " try { x = 42; } catch(e) { return true; }"
12750 " }"
12751 " return false;"
12752 "};"
12753 "f();");
12754 CHECK_EQ(true, value->BooleanValue());
12755}
12756
12757
12758// Test that we ignore null interceptors.
12759THREADED_TEST(NullNamedInterceptor) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012760 v8::Isolate* isolate = CcTest::isolate();
12761 v8::HandleScope scope(isolate);
12762 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012763 templ->SetNamedPropertyHandler(
12764 static_cast<v8::NamedPropertyGetterCallback>(0));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012765 LocalContext context;
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000012766 templ->Set(CcTest::isolate(), "x", v8_num(42));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012767 v8::Handle<v8::Object> obj = templ->NewInstance();
12768 context->Global()->Set(v8_str("obj"), obj);
12769 v8::Handle<Value> value = CompileRun("obj.x");
12770 CHECK(value->IsInt32());
12771 CHECK_EQ(42, value->Int32Value());
12772}
12773
12774
12775// Test that we ignore null interceptors.
12776THREADED_TEST(NullIndexedInterceptor) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012777 v8::Isolate* isolate = CcTest::isolate();
12778 v8::HandleScope scope(isolate);
12779 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012780 templ->SetIndexedPropertyHandler(
12781 static_cast<v8::IndexedPropertyGetterCallback>(0));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012782 LocalContext context;
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000012783 templ->Set(CcTest::isolate(), "42", v8_num(42));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012784 v8::Handle<v8::Object> obj = templ->NewInstance();
12785 context->Global()->Set(v8_str("obj"), obj);
12786 v8::Handle<Value> value = CompileRun("obj[42]");
12787 CHECK(value->IsInt32());
12788 CHECK_EQ(42, value->Int32Value());
12789}
12790
12791
ricow@chromium.org30ce4112010-05-31 10:38:25 +000012792THREADED_TEST(NamedPropertyHandlerGetterAttributes) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012793 v8::Isolate* isolate = CcTest::isolate();
12794 v8::HandleScope scope(isolate);
12795 v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
ricow@chromium.org30ce4112010-05-31 10:38:25 +000012796 templ->InstanceTemplate()->SetNamedPropertyHandler(InterceptorLoadXICGetter);
12797 LocalContext env;
12798 env->Global()->Set(v8_str("obj"),
12799 templ->GetFunction()->NewInstance());
12800 ExpectTrue("obj.x === 42");
12801 ExpectTrue("!obj.propertyIsEnumerable('x')");
12802}
12803
12804
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012805static void ThrowingGetter(Local<String> name,
12806 const v8::PropertyCallbackInfo<v8::Value>& info) {
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012807 ApiTestFuzzer::Fuzz();
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000012808 info.GetIsolate()->ThrowException(Handle<Value>());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012809 info.GetReturnValue().SetUndefined();
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012810}
12811
12812
12813THREADED_TEST(VariousGetPropertiesAndThrowingCallbacks) {
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012814 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000012815 HandleScope scope(context->GetIsolate());
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012816
ulan@chromium.org0f13e742014-01-03 15:51:11 +000012817 Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012818 Local<ObjectTemplate> instance_templ = templ->InstanceTemplate();
12819 instance_templ->SetAccessor(v8_str("f"), ThrowingGetter);
12820
12821 Local<Object> instance = templ->GetFunction()->NewInstance();
12822
ulan@chromium.org0f13e742014-01-03 15:51:11 +000012823 Local<Object> another = Object::New(context->GetIsolate());
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012824 another->SetPrototype(instance);
12825
12826 Local<Object> with_js_getter = CompileRun(
12827 "o = {};\n"
12828 "o.__defineGetter__('f', function() { throw undefined; });\n"
12829 "o\n").As<Object>();
12830 CHECK(!with_js_getter.IsEmpty());
12831
12832 TryCatch try_catch;
12833
12834 Local<Value> result = instance->GetRealNamedProperty(v8_str("f"));
12835 CHECK(try_catch.HasCaught());
12836 try_catch.Reset();
12837 CHECK(result.IsEmpty());
12838
12839 result = another->GetRealNamedProperty(v8_str("f"));
12840 CHECK(try_catch.HasCaught());
12841 try_catch.Reset();
12842 CHECK(result.IsEmpty());
12843
12844 result = another->GetRealNamedPropertyInPrototypeChain(v8_str("f"));
12845 CHECK(try_catch.HasCaught());
12846 try_catch.Reset();
12847 CHECK(result.IsEmpty());
12848
12849 result = another->Get(v8_str("f"));
12850 CHECK(try_catch.HasCaught());
12851 try_catch.Reset();
12852 CHECK(result.IsEmpty());
12853
12854 result = with_js_getter->GetRealNamedProperty(v8_str("f"));
12855 CHECK(try_catch.HasCaught());
12856 try_catch.Reset();
12857 CHECK(result.IsEmpty());
12858
12859 result = with_js_getter->Get(v8_str("f"));
12860 CHECK(try_catch.HasCaught());
12861 try_catch.Reset();
12862 CHECK(result.IsEmpty());
12863}
12864
12865
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012866static void ThrowingCallbackWithTryCatch(
12867 const v8::FunctionCallbackInfo<v8::Value>& args) {
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012868 TryCatch try_catch;
12869 // Verboseness is important: it triggers message delivery which can call into
12870 // external code.
12871 try_catch.SetVerbose(true);
12872 CompileRun("throw 'from JS';");
12873 CHECK(try_catch.HasCaught());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000012874 CHECK(!CcTest::i_isolate()->has_pending_exception());
12875 CHECK(!CcTest::i_isolate()->has_scheduled_exception());
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012876}
12877
12878
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +000012879static int call_depth;
12880
12881
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012882static void WithTryCatch(Handle<Message> message, Handle<Value> data) {
12883 TryCatch try_catch;
12884}
12885
12886
12887static void ThrowFromJS(Handle<Message> message, Handle<Value> data) {
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +000012888 if (--call_depth) CompileRun("throw 'ThrowInJS';");
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012889}
12890
12891
12892static void ThrowViaApi(Handle<Message> message, Handle<Value> data) {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000012893 if (--call_depth) CcTest::isolate()->ThrowException(v8_str("ThrowViaApi"));
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012894}
12895
12896
12897static void WebKitLike(Handle<Message> message, Handle<Value> data) {
12898 Handle<String> errorMessageString = message->Get();
12899 CHECK(!errorMessageString.IsEmpty());
12900 message->GetStackTrace();
12901 message->GetScriptResourceName();
12902}
12903
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012904
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012905THREADED_TEST(ExceptionsDoNotPropagatePastTryCatch) {
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012906 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012907 v8::Isolate* isolate = context->GetIsolate();
12908 HandleScope scope(isolate);
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012909
12910 Local<Function> func =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012911 FunctionTemplate::New(isolate,
12912 ThrowingCallbackWithTryCatch)->GetFunction();
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012913 context->Global()->Set(v8_str("func"), func);
12914
12915 MessageCallback callbacks[] =
12916 { NULL, WebKitLike, ThrowViaApi, ThrowFromJS, WithTryCatch };
12917 for (unsigned i = 0; i < sizeof(callbacks)/sizeof(callbacks[0]); i++) {
12918 MessageCallback callback = callbacks[i];
12919 if (callback != NULL) {
12920 V8::AddMessageListener(callback);
12921 }
ricow@chromium.orgdcebac02011-04-20 09:44:50 +000012922 // Some small number to control number of times message handler should
12923 // throw an exception.
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +000012924 call_depth = 5;
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012925 ExpectFalse(
12926 "var thrown = false;\n"
12927 "try { func(); } catch(e) { thrown = true; }\n"
12928 "thrown\n");
12929 if (callback != NULL) {
12930 V8::RemoveMessageListeners(callback);
12931 }
12932 }
12933}
12934
12935
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012936static void ParentGetter(Local<String> name,
12937 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012938 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012939 info.GetReturnValue().Set(v8_num(1));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012940}
12941
12942
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012943static void ChildGetter(Local<String> name,
12944 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012945 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012946 info.GetReturnValue().Set(v8_num(42));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012947}
12948
12949
12950THREADED_TEST(Overriding) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +000012951 i::FLAG_es5_readonly = true;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012952 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012953 v8::Isolate* isolate = context->GetIsolate();
12954 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012955
12956 // Parent template.
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012957 Local<v8::FunctionTemplate> parent_templ = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012958 Local<ObjectTemplate> parent_instance_templ =
12959 parent_templ->InstanceTemplate();
12960 parent_instance_templ->SetAccessor(v8_str("f"), ParentGetter);
12961
12962 // Template that inherits from the parent template.
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012963 Local<v8::FunctionTemplate> child_templ = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012964 Local<ObjectTemplate> child_instance_templ =
12965 child_templ->InstanceTemplate();
12966 child_templ->Inherit(parent_templ);
12967 // Override 'f'. The child version of 'f' should get called for child
12968 // instances.
12969 child_instance_templ->SetAccessor(v8_str("f"), ChildGetter);
12970 // Add 'g' twice. The 'g' added last should get called for instances.
12971 child_instance_templ->SetAccessor(v8_str("g"), ParentGetter);
12972 child_instance_templ->SetAccessor(v8_str("g"), ChildGetter);
12973
12974 // Add 'h' as an accessor to the proto template with ReadOnly attributes
12975 // so 'h' can be shadowed on the instance object.
12976 Local<ObjectTemplate> child_proto_templ = child_templ->PrototypeTemplate();
12977 child_proto_templ->SetAccessor(v8_str("h"), ParentGetter, 0,
12978 v8::Handle<Value>(), v8::DEFAULT, v8::ReadOnly);
12979
12980 // Add 'i' as an accessor to the instance template with ReadOnly attributes
12981 // but the attribute does not have effect because it is duplicated with
12982 // NULL setter.
12983 child_instance_templ->SetAccessor(v8_str("i"), ChildGetter, 0,
12984 v8::Handle<Value>(), v8::DEFAULT, v8::ReadOnly);
12985
12986
12987
12988 // Instantiate the child template.
12989 Local<v8::Object> instance = child_templ->GetFunction()->NewInstance();
12990
12991 // Check that the child function overrides the parent one.
12992 context->Global()->Set(v8_str("o"), instance);
12993 Local<Value> value = v8_compile("o.f")->Run();
12994 // Check that the 'g' that was added last is hit.
12995 CHECK_EQ(42, value->Int32Value());
12996 value = v8_compile("o.g")->Run();
12997 CHECK_EQ(42, value->Int32Value());
12998
mmassi@chromium.org7028c052012-06-13 11:51:58 +000012999 // Check that 'h' cannot be shadowed.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013000 value = v8_compile("o.h = 3; o.h")->Run();
mmassi@chromium.org7028c052012-06-13 11:51:58 +000013001 CHECK_EQ(1, value->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013002
mmassi@chromium.org7028c052012-06-13 11:51:58 +000013003 // Check that 'i' cannot be shadowed or changed.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013004 value = v8_compile("o.i = 3; o.i")->Run();
13005 CHECK_EQ(42, value->Int32Value());
13006}
13007
13008
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013009static void IsConstructHandler(
13010 const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013011 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013012 args.GetReturnValue().Set(args.IsConstructCall());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013013}
13014
13015
13016THREADED_TEST(IsConstructCall) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000013017 v8::Isolate* isolate = CcTest::isolate();
13018 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013019
13020 // Function template with call handler.
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000013021 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013022 templ->SetCallHandler(IsConstructHandler);
13023
13024 LocalContext context;
13025
13026 context->Global()->Set(v8_str("f"), templ->GetFunction());
13027 Local<Value> value = v8_compile("f()")->Run();
13028 CHECK(!value->BooleanValue());
13029 value = v8_compile("new f()")->Run();
13030 CHECK(value->BooleanValue());
13031}
13032
13033
13034THREADED_TEST(ObjectProtoToString) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000013035 v8::Isolate* isolate = CcTest::isolate();
13036 v8::HandleScope scope(isolate);
13037 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013038 templ->SetClassName(v8_str("MyClass"));
13039
13040 LocalContext context;
13041
13042 Local<String> customized_tostring = v8_str("customized toString");
13043
13044 // Replace Object.prototype.toString
13045 v8_compile("Object.prototype.toString = function() {"
13046 " return 'customized toString';"
13047 "}")->Run();
13048
13049 // Normal ToString call should call replaced Object.prototype.toString
13050 Local<v8::Object> instance = templ->GetFunction()->NewInstance();
13051 Local<String> value = instance->ToString();
13052 CHECK(value->IsString() && value->Equals(customized_tostring));
13053
13054 // ObjectProtoToString should not call replace toString function.
13055 value = instance->ObjectProtoToString();
13056 CHECK(value->IsString() && value->Equals(v8_str("[object MyClass]")));
13057
13058 // Check global
13059 value = context->Global()->ObjectProtoToString();
13060 CHECK(value->IsString() && value->Equals(v8_str("[object global]")));
13061
13062 // Check ordinary object
13063 Local<Value> object = v8_compile("new Object()")->Run();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000013064 value = object.As<v8::Object>()->ObjectProtoToString();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013065 CHECK(value->IsString() && value->Equals(v8_str("[object Object]")));
13066}
13067
13068
ager@chromium.orgbeb25712010-11-29 08:02:25 +000013069THREADED_TEST(ObjectGetConstructorName) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +000013070 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013071 v8::HandleScope scope(context->GetIsolate());
ager@chromium.orgbeb25712010-11-29 08:02:25 +000013072 v8_compile("function Parent() {};"
13073 "function Child() {};"
13074 "Child.prototype = new Parent();"
13075 "var outer = { inner: function() { } };"
13076 "var p = new Parent();"
13077 "var c = new Child();"
13078 "var x = new outer.inner();")->Run();
13079
13080 Local<v8::Value> p = context->Global()->Get(v8_str("p"));
13081 CHECK(p->IsObject() && p->ToObject()->GetConstructorName()->Equals(
13082 v8_str("Parent")));
13083
13084 Local<v8::Value> c = context->Global()->Get(v8_str("c"));
13085 CHECK(c->IsObject() && c->ToObject()->GetConstructorName()->Equals(
13086 v8_str("Child")));
13087
13088 Local<v8::Value> x = context->Global()->Get(v8_str("x"));
13089 CHECK(x->IsObject() && x->ToObject()->GetConstructorName()->Equals(
13090 v8_str("outer.inner")));
13091}
13092
13093
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013094bool ApiTestFuzzer::fuzzing_ = false;
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000013095i::Semaphore ApiTestFuzzer::all_tests_done_(0);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013096int ApiTestFuzzer::active_tests_;
13097int ApiTestFuzzer::tests_being_run_;
13098int ApiTestFuzzer::current_;
13099
13100
13101// We are in a callback and want to switch to another thread (if we
13102// are currently running the thread fuzzing test).
13103void ApiTestFuzzer::Fuzz() {
13104 if (!fuzzing_) return;
13105 ApiTestFuzzer* test = RegisterThreadedTest::nth(current_)->fuzzer_;
13106 test->ContextSwitch();
13107}
13108
13109
13110// Let the next thread go. Since it is also waiting on the V8 lock it may
13111// not start immediately.
13112bool ApiTestFuzzer::NextThread() {
13113 int test_position = GetNextTestNumber();
ager@chromium.orgc4c92722009-11-18 14:12:51 +000013114 const char* test_name = RegisterThreadedTest::nth(current_)->name();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013115 if (test_position == current_) {
ager@chromium.orgc4c92722009-11-18 14:12:51 +000013116 if (kLogThreading)
13117 printf("Stay with %s\n", test_name);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013118 return false;
13119 }
ager@chromium.orgc4c92722009-11-18 14:12:51 +000013120 if (kLogThreading) {
13121 printf("Switch from %s to %s\n",
13122 test_name,
13123 RegisterThreadedTest::nth(test_position)->name());
13124 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013125 current_ = test_position;
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000013126 RegisterThreadedTest::nth(current_)->fuzzer_->gate_.Signal();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013127 return true;
13128}
13129
13130
13131void ApiTestFuzzer::Run() {
13132 // When it is our turn...
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000013133 gate_.Wait();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013134 {
13135 // ... get the V8 lock and start running the test.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013136 v8::Locker locker(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013137 CallTest();
13138 }
13139 // This test finished.
13140 active_ = false;
13141 active_tests_--;
13142 // If it was the last then signal that fact.
13143 if (active_tests_ == 0) {
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000013144 all_tests_done_.Signal();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013145 } else {
13146 // Otherwise select a new test and start that.
13147 NextThread();
13148 }
13149}
13150
13151
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013152static unsigned linear_congruential_generator;
13153
13154
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000013155void ApiTestFuzzer::SetUp(PartOfTest part) {
kasperl@chromium.orgb9123622008-09-17 14:05:56 +000013156 linear_congruential_generator = i::FLAG_testing_prng_seed;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013157 fuzzing_ = true;
lrn@chromium.org1c092762011-05-09 09:42:16 +000013158 int count = RegisterThreadedTest::count();
13159 int start = count * part / (LAST_PART + 1);
13160 int end = (count * (part + 1) / (LAST_PART + 1)) - 1;
13161 active_tests_ = tests_being_run_ = end - start + 1;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013162 for (int i = 0; i < tests_being_run_; i++) {
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000013163 RegisterThreadedTest::nth(i)->fuzzer_ = new ApiTestFuzzer(i + start);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013164 }
13165 for (int i = 0; i < active_tests_; i++) {
13166 RegisterThreadedTest::nth(i)->fuzzer_->Start();
13167 }
13168}
13169
13170
13171static void CallTestNumber(int test_number) {
13172 (RegisterThreadedTest::nth(test_number)->callback())();
13173}
13174
13175
13176void ApiTestFuzzer::RunAllTests() {
13177 // Set off the first test.
13178 current_ = -1;
13179 NextThread();
13180 // Wait till they are all done.
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000013181 all_tests_done_.Wait();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013182}
13183
13184
13185int ApiTestFuzzer::GetNextTestNumber() {
13186 int next_test;
13187 do {
13188 next_test = (linear_congruential_generator >> 16) % tests_being_run_;
13189 linear_congruential_generator *= 1664525u;
13190 linear_congruential_generator += 1013904223u;
13191 } while (!RegisterThreadedTest::nth(next_test)->fuzzer_->active_);
13192 return next_test;
13193}
13194
13195
13196void ApiTestFuzzer::ContextSwitch() {
13197 // If the new thread is the same as the current thread there is nothing to do.
13198 if (NextThread()) {
13199 // Now it can start.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013200 v8::Unlocker unlocker(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013201 // Wait till someone starts us again.
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000013202 gate_.Wait();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013203 // And we're off.
13204 }
13205}
13206
13207
13208void ApiTestFuzzer::TearDown() {
13209 fuzzing_ = false;
ager@chromium.org41826e72009-03-30 13:30:57 +000013210 for (int i = 0; i < RegisterThreadedTest::count(); i++) {
13211 ApiTestFuzzer *fuzzer = RegisterThreadedTest::nth(i)->fuzzer_;
13212 if (fuzzer != NULL) fuzzer->Join();
13213 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013214}
13215
13216
13217// Lets not be needlessly self-referential.
mmassi@chromium.org2f0efde2013-02-06 14:12:58 +000013218TEST(Threading1) {
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000013219 ApiTestFuzzer::SetUp(ApiTestFuzzer::FIRST_PART);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013220 ApiTestFuzzer::RunAllTests();
13221 ApiTestFuzzer::TearDown();
13222}
13223
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000013224
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013225TEST(Threading2) {
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000013226 ApiTestFuzzer::SetUp(ApiTestFuzzer::SECOND_PART);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013227 ApiTestFuzzer::RunAllTests();
13228 ApiTestFuzzer::TearDown();
13229}
13230
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000013231
lrn@chromium.org1c092762011-05-09 09:42:16 +000013232TEST(Threading3) {
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000013233 ApiTestFuzzer::SetUp(ApiTestFuzzer::THIRD_PART);
lrn@chromium.org1c092762011-05-09 09:42:16 +000013234 ApiTestFuzzer::RunAllTests();
13235 ApiTestFuzzer::TearDown();
13236}
13237
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000013238
lrn@chromium.org1c092762011-05-09 09:42:16 +000013239TEST(Threading4) {
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000013240 ApiTestFuzzer::SetUp(ApiTestFuzzer::FOURTH_PART);
lrn@chromium.org1c092762011-05-09 09:42:16 +000013241 ApiTestFuzzer::RunAllTests();
13242 ApiTestFuzzer::TearDown();
13243}
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013244
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000013245
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013246void ApiTestFuzzer::CallTest() {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013247 v8::Isolate::Scope scope(CcTest::isolate());
ager@chromium.orgc4c92722009-11-18 14:12:51 +000013248 if (kLogThreading)
13249 printf("Start test %d\n", test_number_);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013250 CallTestNumber(test_number_);
ager@chromium.orgc4c92722009-11-18 14:12:51 +000013251 if (kLogThreading)
13252 printf("End test %d\n", test_number_);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013253}
13254
13255
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013256static void ThrowInJS(const v8::FunctionCallbackInfo<v8::Value>& args) {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000013257 v8::Isolate* isolate = args.GetIsolate();
13258 CHECK(v8::Locker::IsLocked(isolate));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013259 ApiTestFuzzer::Fuzz();
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000013260 v8::Unlocker unlocker(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013261 const char* code = "throw 7;";
13262 {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000013263 v8::Locker nested_locker(isolate);
13264 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013265 v8::Handle<Value> exception;
13266 { v8::TryCatch try_catch;
13267 v8::Handle<Value> value = CompileRun(code);
13268 CHECK(value.IsEmpty());
13269 CHECK(try_catch.HasCaught());
13270 // Make sure to wrap the exception in a new handle because
13271 // the handle returned from the TryCatch is destroyed
13272 // when the TryCatch is destroyed.
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000013273 exception = Local<Value>::New(isolate, try_catch.Exception());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013274 }
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000013275 args.GetIsolate()->ThrowException(exception);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013276 }
13277}
13278
13279
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013280static void ThrowInJSNoCatch(const v8::FunctionCallbackInfo<v8::Value>& args) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013281 CHECK(v8::Locker::IsLocked(CcTest::isolate()));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013282 ApiTestFuzzer::Fuzz();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013283 v8::Unlocker unlocker(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013284 const char* code = "throw 7;";
13285 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013286 v8::Locker nested_locker(CcTest::isolate());
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013287 v8::HandleScope scope(args.GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013288 v8::Handle<Value> value = CompileRun(code);
13289 CHECK(value.IsEmpty());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013290 args.GetReturnValue().Set(v8_str("foo"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013291 }
13292}
13293
13294
13295// These are locking tests that don't need to be run again
13296// as part of the locking aggregation tests.
13297TEST(NestedLockers) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000013298 v8::Isolate* isolate = CcTest::isolate();
13299 v8::Locker locker(isolate);
13300 CHECK(v8::Locker::IsLocked(isolate));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013301 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013302 v8::HandleScope scope(env->GetIsolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000013303 Local<v8::FunctionTemplate> fun_templ =
13304 v8::FunctionTemplate::New(isolate, ThrowInJS);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013305 Local<Function> fun = fun_templ->GetFunction();
13306 env->Global()->Set(v8_str("throw_in_js"), fun);
13307 Local<Script> script = v8_compile("(function () {"
13308 " try {"
13309 " throw_in_js();"
13310 " return 42;"
13311 " } catch (e) {"
13312 " return e * 13;"
13313 " }"
13314 "})();");
13315 CHECK_EQ(91, script->Run()->Int32Value());
13316}
13317
13318
13319// These are locking tests that don't need to be run again
13320// as part of the locking aggregation tests.
13321TEST(NestedLockersNoTryCatch) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013322 v8::Locker locker(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013323 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013324 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013325 Local<v8::FunctionTemplate> fun_templ =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000013326 v8::FunctionTemplate::New(env->GetIsolate(), ThrowInJSNoCatch);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013327 Local<Function> fun = fun_templ->GetFunction();
13328 env->Global()->Set(v8_str("throw_in_js"), fun);
13329 Local<Script> script = v8_compile("(function () {"
13330 " try {"
13331 " throw_in_js();"
13332 " return 42;"
13333 " } catch (e) {"
13334 " return e * 13;"
13335 " }"
13336 "})();");
13337 CHECK_EQ(91, script->Run()->Int32Value());
13338}
13339
13340
13341THREADED_TEST(RecursiveLocking) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013342 v8::Locker locker(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013343 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013344 v8::Locker locker2(CcTest::isolate());
13345 CHECK(v8::Locker::IsLocked(CcTest::isolate()));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013346 }
13347}
13348
13349
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013350static void UnlockForAMoment(const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013351 ApiTestFuzzer::Fuzz();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013352 v8::Unlocker unlocker(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013353}
13354
13355
13356THREADED_TEST(LockUnlockLock) {
13357 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013358 v8::Locker locker(CcTest::isolate());
13359 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013360 LocalContext env;
13361 Local<v8::FunctionTemplate> fun_templ =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000013362 v8::FunctionTemplate::New(CcTest::isolate(), UnlockForAMoment);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013363 Local<Function> fun = fun_templ->GetFunction();
13364 env->Global()->Set(v8_str("unlock_for_a_moment"), fun);
13365 Local<Script> script = v8_compile("(function () {"
13366 " unlock_for_a_moment();"
13367 " return 42;"
13368 "})();");
13369 CHECK_EQ(42, script->Run()->Int32Value());
13370 }
13371 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013372 v8::Locker locker(CcTest::isolate());
13373 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013374 LocalContext env;
13375 Local<v8::FunctionTemplate> fun_templ =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000013376 v8::FunctionTemplate::New(CcTest::isolate(), UnlockForAMoment);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013377 Local<Function> fun = fun_templ->GetFunction();
13378 env->Global()->Set(v8_str("unlock_for_a_moment"), fun);
13379 Local<Script> script = v8_compile("(function () {"
13380 " unlock_for_a_moment();"
13381 " return 42;"
13382 "})();");
13383 CHECK_EQ(42, script->Run()->Int32Value());
13384 }
13385}
13386
13387
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000013388static int GetGlobalObjectsCount() {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013389 CcTest::heap()->EnsureHeapIsIterable();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013390 int count = 0;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013391 i::HeapIterator it(CcTest::heap());
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000013392 for (i::HeapObject* object = it.next(); object != NULL; object = it.next())
13393 if (object->IsJSGlobalObject()) count++;
13394 return count;
13395}
13396
13397
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000013398static void CheckSurvivingGlobalObjectsCount(int expected) {
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +000013399 // We need to collect all garbage twice to be sure that everything
13400 // has been collected. This is because inline caches are cleared in
13401 // the first garbage collection but some of the maps have already
13402 // been marked at that point. Therefore some of the maps are not
13403 // collected until the second garbage collection.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013404 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
13405 CcTest::heap()->CollectAllGarbage(i::Heap::kMakeHeapIterableMask);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000013406 int count = GetGlobalObjectsCount();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013407#ifdef DEBUG
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013408 if (count != expected) CcTest::heap()->TracePathToGlobal();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013409#endif
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000013410 CHECK_EQ(expected, count);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013411}
13412
13413
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013414TEST(DontLeakGlobalObjects) {
13415 // Regression test for issues 1139850 and 1174891.
13416
kasperl@chromium.orgb9123622008-09-17 14:05:56 +000013417 v8::V8::Initialize();
ager@chromium.org9258b6b2008-09-11 09:11:10 +000013418
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013419 for (int i = 0; i < 5; i++) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013420 { v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013421 LocalContext context;
13422 }
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +000013423 v8::V8::ContextDisposedNotification();
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000013424 CheckSurvivingGlobalObjectsCount(0);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013425
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013426 { v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013427 LocalContext context;
13428 v8_compile("Date")->Run();
13429 }
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +000013430 v8::V8::ContextDisposedNotification();
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000013431 CheckSurvivingGlobalObjectsCount(0);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013432
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013433 { v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013434 LocalContext context;
13435 v8_compile("/aaa/")->Run();
13436 }
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +000013437 v8::V8::ContextDisposedNotification();
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000013438 CheckSurvivingGlobalObjectsCount(0);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013439
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013440 { v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013441 const char* extension_list[] = { "v8/gc" };
13442 v8::ExtensionConfiguration extensions(1, extension_list);
13443 LocalContext context(&extensions);
13444 v8_compile("gc();")->Run();
13445 }
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +000013446 v8::V8::ContextDisposedNotification();
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000013447 CheckSurvivingGlobalObjectsCount(0);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013448 }
13449}
13450
dslomov@chromium.org639bac02013-09-09 11:58:54 +000013451
13452TEST(CopyablePersistent) {
13453 LocalContext context;
13454 v8::Isolate* isolate = context->GetIsolate();
13455 i::GlobalHandles* globals =
13456 reinterpret_cast<i::Isolate*>(isolate)->global_handles();
13457 int initial_handles = globals->global_handles_count();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013458 typedef v8::Persistent<v8::Object, v8::CopyablePersistentTraits<v8::Object> >
13459 CopyableObject;
dslomov@chromium.org639bac02013-09-09 11:58:54 +000013460 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013461 CopyableObject handle1;
dslomov@chromium.org639bac02013-09-09 11:58:54 +000013462 {
13463 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000013464 handle1.Reset(isolate, v8::Object::New(isolate));
dslomov@chromium.org639bac02013-09-09 11:58:54 +000013465 }
13466 CHECK_EQ(initial_handles + 1, globals->global_handles_count());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013467 CopyableObject handle2;
dslomov@chromium.org639bac02013-09-09 11:58:54 +000013468 handle2 = handle1;
13469 CHECK(handle1 == handle2);
13470 CHECK_EQ(initial_handles + 2, globals->global_handles_count());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013471 CopyableObject handle3(handle2);
dslomov@chromium.org639bac02013-09-09 11:58:54 +000013472 CHECK(handle1 == handle3);
13473 CHECK_EQ(initial_handles + 3, globals->global_handles_count());
13474 }
13475 // Verify autodispose
hpayer@chromium.orgc5d49712013-09-11 08:25:48 +000013476 CHECK_EQ(initial_handles, globals->global_handles_count());
dslomov@chromium.org639bac02013-09-09 11:58:54 +000013477}
13478
13479
13480static void WeakApiCallback(
13481 const v8::WeakCallbackData<v8::Object, Persistent<v8::Object> >& data) {
13482 Local<Value> value = data.GetValue()->Get(v8_str("key"));
13483 CHECK_EQ(231, static_cast<int32_t>(Local<v8::Integer>::Cast(value)->Value()));
13484 data.GetParameter()->Reset();
13485 delete data.GetParameter();
13486}
13487
13488
13489TEST(WeakCallbackApi) {
13490 LocalContext context;
13491 v8::Isolate* isolate = context->GetIsolate();
13492 i::GlobalHandles* globals =
13493 reinterpret_cast<i::Isolate*>(isolate)->global_handles();
13494 int initial_handles = globals->global_handles_count();
13495 {
13496 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000013497 v8::Local<v8::Object> obj = v8::Object::New(isolate);
13498 obj->Set(v8_str("key"), v8::Integer::New(isolate, 231));
dslomov@chromium.org639bac02013-09-09 11:58:54 +000013499 v8::Persistent<v8::Object>* handle =
13500 new v8::Persistent<v8::Object>(isolate, obj);
13501 handle->SetWeak<v8::Object, v8::Persistent<v8::Object> >(handle,
13502 WeakApiCallback);
13503 }
13504 reinterpret_cast<i::Isolate*>(isolate)->heap()->
13505 CollectAllGarbage(i::Heap::kNoGCFlags);
13506 // Verify disposed.
13507 CHECK_EQ(initial_handles, globals->global_handles_count());
13508}
13509
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013510
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000013511v8::Persistent<v8::Object> some_object;
13512v8::Persistent<v8::Object> bad_handle;
13513
machenbach@chromium.orgddf38112013-12-04 09:42:52 +000013514void NewPersistentHandleCallback(
13515 const v8::WeakCallbackData<v8::Object, v8::Persistent<v8::Object> >& data) {
13516 v8::HandleScope scope(data.GetIsolate());
13517 bad_handle.Reset(data.GetIsolate(), some_object);
13518 data.GetParameter()->Reset();
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000013519}
13520
13521
13522THREADED_TEST(NewPersistentHandleFromWeakCallback) {
13523 LocalContext context;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000013524 v8::Isolate* isolate = context->GetIsolate();
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000013525
13526 v8::Persistent<v8::Object> handle1, handle2;
13527 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013528 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000013529 some_object.Reset(isolate, v8::Object::New(isolate));
13530 handle1.Reset(isolate, v8::Object::New(isolate));
13531 handle2.Reset(isolate, v8::Object::New(isolate));
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000013532 }
13533 // Note: order is implementation dependent alas: currently
13534 // global handle nodes are processed by PostGarbageCollectionProcessing
13535 // in reverse allocation order, so if second allocated handle is deleted,
13536 // weak callback of the first handle would be able to 'reallocate' it.
machenbach@chromium.orgddf38112013-12-04 09:42:52 +000013537 handle1.SetWeak(&handle1, NewPersistentHandleCallback);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000013538 handle2.Reset();
machenbach@chromium.orgddf38112013-12-04 09:42:52 +000013539 CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000013540}
13541
13542
13543v8::Persistent<v8::Object> to_be_disposed;
13544
machenbach@chromium.orgddf38112013-12-04 09:42:52 +000013545void DisposeAndForceGcCallback(
13546 const v8::WeakCallbackData<v8::Object, v8::Persistent<v8::Object> >& data) {
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000013547 to_be_disposed.Reset();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013548 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
machenbach@chromium.orgddf38112013-12-04 09:42:52 +000013549 data.GetParameter()->Reset();
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000013550}
13551
13552
13553THREADED_TEST(DoNotUseDeletedNodesInSecondLevelGc) {
13554 LocalContext context;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000013555 v8::Isolate* isolate = context->GetIsolate();
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000013556
13557 v8::Persistent<v8::Object> handle1, handle2;
13558 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013559 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000013560 handle1.Reset(isolate, v8::Object::New(isolate));
13561 handle2.Reset(isolate, v8::Object::New(isolate));
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000013562 }
machenbach@chromium.orgddf38112013-12-04 09:42:52 +000013563 handle1.SetWeak(&handle1, DisposeAndForceGcCallback);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000013564 to_be_disposed.Reset(isolate, handle2);
machenbach@chromium.orgddf38112013-12-04 09:42:52 +000013565 CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000013566}
13567
machenbach@chromium.orgddf38112013-12-04 09:42:52 +000013568void DisposingCallback(
13569 const v8::WeakCallbackData<v8::Object, v8::Persistent<v8::Object> >& data) {
13570 data.GetParameter()->Reset();
ager@chromium.orgc4c92722009-11-18 14:12:51 +000013571}
13572
machenbach@chromium.orgddf38112013-12-04 09:42:52 +000013573void HandleCreatingCallback(
13574 const v8::WeakCallbackData<v8::Object, v8::Persistent<v8::Object> >& data) {
13575 v8::HandleScope scope(data.GetIsolate());
ulan@chromium.org0f13e742014-01-03 15:51:11 +000013576 v8::Persistent<v8::Object>(data.GetIsolate(),
13577 v8::Object::New(data.GetIsolate()));
machenbach@chromium.orgddf38112013-12-04 09:42:52 +000013578 data.GetParameter()->Reset();
ager@chromium.orgc4c92722009-11-18 14:12:51 +000013579}
13580
13581
13582THREADED_TEST(NoGlobalHandlesOrphaningDueToWeakCallback) {
13583 LocalContext context;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000013584 v8::Isolate* isolate = context->GetIsolate();
ager@chromium.orgc4c92722009-11-18 14:12:51 +000013585
13586 v8::Persistent<v8::Object> handle1, handle2, handle3;
13587 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013588 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000013589 handle3.Reset(isolate, v8::Object::New(isolate));
13590 handle2.Reset(isolate, v8::Object::New(isolate));
13591 handle1.Reset(isolate, v8::Object::New(isolate));
ager@chromium.orgc4c92722009-11-18 14:12:51 +000013592 }
machenbach@chromium.orgddf38112013-12-04 09:42:52 +000013593 handle2.SetWeak(&handle2, DisposingCallback);
13594 handle3.SetWeak(&handle3, HandleCreatingCallback);
13595 CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
ager@chromium.orgc4c92722009-11-18 14:12:51 +000013596}
13597
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000013598
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013599THREADED_TEST(CheckForCrossContextObjectLiterals) {
kasperl@chromium.orgb9123622008-09-17 14:05:56 +000013600 v8::V8::Initialize();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013601
13602 const int nof = 2;
13603 const char* sources[nof] = {
13604 "try { [ 2, 3, 4 ].forEach(5); } catch(e) { e.toString(); }",
13605 "Object()"
13606 };
13607
13608 for (int i = 0; i < nof; i++) {
13609 const char* source = sources[i];
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013610 { v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013611 LocalContext context;
13612 CompileRun(source);
13613 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013614 { v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013615 LocalContext context;
13616 CompileRun(source);
13617 }
13618 }
13619}
13620
13621
ulan@chromium.org57ff8812013-05-10 08:16:55 +000013622static v8::Handle<Value> NestedScope(v8::Local<Context> env) {
machenbach@chromium.orgafbdadc2013-12-09 16:12:18 +000013623 v8::EscapableHandleScope inner(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013624 env->Enter();
machenbach@chromium.orgafbdadc2013-12-09 16:12:18 +000013625 v8::Local<Value> three = v8_num(3);
13626 v8::Local<Value> value = inner.Escape(three);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013627 env->Exit();
13628 return value;
13629}
13630
13631
13632THREADED_TEST(NestedHandleScopeAndContexts) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013633 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000013634 v8::HandleScope outer(isolate);
13635 v8::Local<Context> env = Context::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013636 env->Enter();
13637 v8::Handle<Value> value = NestedScope(env);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000013638 v8::Handle<String> str(value->ToString());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000013639 CHECK(!str.IsEmpty());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013640 env->Exit();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013641}
13642
13643
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013644static bool MatchPointers(void* key1, void* key2) {
13645 return key1 == key2;
13646}
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013647
13648
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013649struct SymbolInfo {
13650 size_t id;
13651 size_t size;
13652 std::string name;
13653};
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013654
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013655
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013656class SetFunctionEntryHookTest {
13657 public:
13658 SetFunctionEntryHookTest() {
13659 CHECK(instance_ == NULL);
13660 instance_ = this;
13661 }
13662 ~SetFunctionEntryHookTest() {
13663 CHECK(instance_ == this);
13664 instance_ = NULL;
13665 }
13666 void Reset() {
13667 symbols_.clear();
13668 symbol_locations_.clear();
13669 invocations_.clear();
13670 }
13671 void RunTest();
13672 void OnJitEvent(const v8::JitCodeEvent* event);
13673 static void JitEvent(const v8::JitCodeEvent* event) {
13674 CHECK(instance_ != NULL);
13675 instance_->OnJitEvent(event);
13676 }
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013677
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013678 void OnEntryHook(uintptr_t function,
13679 uintptr_t return_addr_location);
13680 static void EntryHook(uintptr_t function,
13681 uintptr_t return_addr_location) {
13682 CHECK(instance_ != NULL);
13683 instance_->OnEntryHook(function, return_addr_location);
13684 }
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000013685
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013686 static void RuntimeCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
13687 CHECK(instance_ != NULL);
13688 args.GetReturnValue().Set(v8_num(42));
13689 }
13690 void RunLoopInNewEnv(v8::Isolate* isolate);
13691
13692 // Records addr as location of symbol.
13693 void InsertSymbolAt(i::Address addr, SymbolInfo* symbol);
13694
13695 // Finds the symbol containing addr
13696 SymbolInfo* FindSymbolForAddr(i::Address addr);
13697 // Returns the number of invocations where the caller name contains
13698 // \p caller_name and the function name contains \p function_name.
13699 int CountInvocations(const char* caller_name,
13700 const char* function_name);
13701
13702 i::Handle<i::JSFunction> foo_func_;
13703 i::Handle<i::JSFunction> bar_func_;
13704
13705 typedef std::map<size_t, SymbolInfo> SymbolMap;
13706 typedef std::map<i::Address, SymbolInfo*> SymbolLocationMap;
13707 typedef std::map<std::pair<SymbolInfo*, SymbolInfo*>, int> InvocationMap;
13708 SymbolMap symbols_;
13709 SymbolLocationMap symbol_locations_;
13710 InvocationMap invocations_;
13711
13712 static SetFunctionEntryHookTest* instance_;
13713};
13714SetFunctionEntryHookTest* SetFunctionEntryHookTest::instance_ = NULL;
13715
13716
13717// Returns true if addr is in the range [start, start+len).
13718static bool Overlaps(i::Address start, size_t len, i::Address addr) {
13719 if (start <= addr && start + len > addr)
13720 return true;
13721
13722 return false;
13723}
13724
13725void SetFunctionEntryHookTest::InsertSymbolAt(i::Address addr,
13726 SymbolInfo* symbol) {
13727 // Insert the symbol at the new location.
13728 SymbolLocationMap::iterator it =
13729 symbol_locations_.insert(std::make_pair(addr, symbol)).first;
13730 // Now erase symbols to the left and right that overlap this one.
13731 while (it != symbol_locations_.begin()) {
13732 SymbolLocationMap::iterator left = it;
13733 --left;
13734 if (!Overlaps(left->first, left->second->size, addr))
13735 break;
13736 symbol_locations_.erase(left);
13737 }
13738
13739 // Now erase symbols to the left and right that overlap this one.
13740 while (true) {
13741 SymbolLocationMap::iterator right = it;
13742 ++right;
13743 if (right == symbol_locations_.end())
13744 break;
13745 if (!Overlaps(addr, symbol->size, right->first))
13746 break;
13747 symbol_locations_.erase(right);
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000013748 }
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013749}
13750
13751
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013752void SetFunctionEntryHookTest::OnJitEvent(const v8::JitCodeEvent* event) {
13753 switch (event->type) {
13754 case v8::JitCodeEvent::CODE_ADDED: {
13755 CHECK(event->code_start != NULL);
13756 CHECK_NE(0, static_cast<int>(event->code_len));
13757 CHECK(event->name.str != NULL);
13758 size_t symbol_id = symbols_.size();
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013759
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013760 // Record the new symbol.
13761 SymbolInfo& info = symbols_[symbol_id];
13762 info.id = symbol_id;
13763 info.size = event->code_len;
13764 info.name.assign(event->name.str, event->name.str + event->name.len);
13765
13766 // And record it's location.
13767 InsertSymbolAt(reinterpret_cast<i::Address>(event->code_start), &info);
13768 }
13769 break;
13770
13771 case v8::JitCodeEvent::CODE_MOVED: {
13772 // We would like to never see code move that we haven't seen before,
13773 // but the code creation event does not happen until the line endings
13774 // have been calculated (this is so that we can report the line in the
13775 // script at which the function source is found, see
13776 // Compiler::RecordFunctionCompilation) and the line endings
13777 // calculations can cause a GC, which can move the newly created code
13778 // before its existence can be logged.
13779 SymbolLocationMap::iterator it(
13780 symbol_locations_.find(
13781 reinterpret_cast<i::Address>(event->code_start)));
13782 if (it != symbol_locations_.end()) {
13783 // Found a symbol at this location, move it.
13784 SymbolInfo* info = it->second;
13785 symbol_locations_.erase(it);
13786 InsertSymbolAt(reinterpret_cast<i::Address>(event->new_code_start),
13787 info);
13788 }
13789 }
13790 default:
13791 break;
13792 }
13793}
13794
13795void SetFunctionEntryHookTest::OnEntryHook(
13796 uintptr_t function, uintptr_t return_addr_location) {
13797 // Get the function's code object.
13798 i::Code* function_code = i::Code::GetCodeFromTargetAddress(
13799 reinterpret_cast<i::Address>(function));
13800 CHECK(function_code != NULL);
13801
13802 // Then try and look up the caller's code object.
13803 i::Address caller = *reinterpret_cast<i::Address*>(return_addr_location);
13804
13805 // Count the invocation.
13806 SymbolInfo* caller_symbol = FindSymbolForAddr(caller);
13807 SymbolInfo* function_symbol =
13808 FindSymbolForAddr(reinterpret_cast<i::Address>(function));
13809 ++invocations_[std::make_pair(caller_symbol, function_symbol)];
13810
13811 if (!bar_func_.is_null() && function_code == bar_func_->code()) {
13812 // Check that we have a symbol for the "bar" function at the right location.
13813 SymbolLocationMap::iterator it(
13814 symbol_locations_.find(function_code->instruction_start()));
13815 CHECK(it != symbol_locations_.end());
13816 }
13817
13818 if (!foo_func_.is_null() && function_code == foo_func_->code()) {
13819 // Check that we have a symbol for "foo" at the right location.
13820 SymbolLocationMap::iterator it(
13821 symbol_locations_.find(function_code->instruction_start()));
13822 CHECK(it != symbol_locations_.end());
13823 }
13824}
13825
13826
13827SymbolInfo* SetFunctionEntryHookTest::FindSymbolForAddr(i::Address addr) {
13828 SymbolLocationMap::iterator it(symbol_locations_.lower_bound(addr));
13829 // Do we have a direct hit on a symbol?
13830 if (it != symbol_locations_.end()) {
13831 if (it->first == addr)
13832 return it->second;
13833 }
13834
13835 // If not a direct hit, it'll have to be the previous symbol.
13836 if (it == symbol_locations_.begin())
13837 return NULL;
13838
13839 --it;
13840 size_t offs = addr - it->first;
13841 if (offs < it->second->size)
13842 return it->second;
13843
13844 return NULL;
13845}
13846
13847
13848int SetFunctionEntryHookTest::CountInvocations(
13849 const char* caller_name, const char* function_name) {
13850 InvocationMap::iterator it(invocations_.begin());
13851 int invocations = 0;
13852 for (; it != invocations_.end(); ++it) {
13853 SymbolInfo* caller = it->first.first;
13854 SymbolInfo* function = it->first.second;
13855
13856 // Filter out non-matching functions.
13857 if (function_name != NULL) {
13858 if (function->name.find(function_name) == std::string::npos)
13859 continue;
13860 }
13861
13862 // Filter out non-matching callers.
13863 if (caller_name != NULL) {
13864 if (caller == NULL)
13865 continue;
13866 if (caller->name.find(caller_name) == std::string::npos)
13867 continue;
13868 }
13869
13870 // It matches add the invocation count to the tally.
13871 invocations += it->second;
13872 }
13873
13874 return invocations;
13875}
13876
13877
13878void SetFunctionEntryHookTest::RunLoopInNewEnv(v8::Isolate* isolate) {
ulan@chromium.org57ff8812013-05-10 08:16:55 +000013879 v8::HandleScope outer(isolate);
13880 v8::Local<Context> env = Context::New(isolate);
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013881 env->Enter();
13882
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000013883 Local<ObjectTemplate> t = ObjectTemplate::New(isolate);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000013884 t->Set(v8_str("asdf"), v8::FunctionTemplate::New(isolate, RuntimeCallback));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013885 env->Global()->Set(v8_str("obj"), t->NewInstance());
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013886
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013887 const char* script =
13888 "function bar() {\n"
13889 " var sum = 0;\n"
13890 " for (i = 0; i < 100; ++i)\n"
13891 " sum = foo(i);\n"
13892 " return sum;\n"
13893 "}\n"
13894 "function foo(i) { return i * i; }\n"
13895 "// Invoke on the runtime function.\n"
13896 "obj.asdf()";
13897 CompileRun(script);
13898 bar_func_ = i::Handle<i::JSFunction>::cast(
13899 v8::Utils::OpenHandle(*env->Global()->Get(v8_str("bar"))));
13900 ASSERT(!bar_func_.is_null());
13901
13902 foo_func_ =
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013903 i::Handle<i::JSFunction>::cast(
13904 v8::Utils::OpenHandle(*env->Global()->Get(v8_str("foo"))));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013905 ASSERT(!foo_func_.is_null());
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013906
13907 v8::Handle<v8::Value> value = CompileRun("bar();");
13908 CHECK(value->IsNumber());
13909 CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value());
13910
13911 // Test the optimized codegen path.
13912 value = CompileRun("%OptimizeFunctionOnNextCall(foo);"
13913 "bar();");
13914 CHECK(value->IsNumber());
13915 CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value());
13916
13917 env->Exit();
13918}
13919
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000013920
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013921void SetFunctionEntryHookTest::RunTest() {
13922 // Work in a new isolate throughout.
13923 v8::Isolate* isolate = v8::Isolate::New();
13924
13925 // Test setting the entry hook on the new isolate.
13926 CHECK(v8::V8::SetFunctionEntryHook(isolate, EntryHook));
13927
13928 // Replacing the hook, once set should fail.
13929 CHECK_EQ(false, v8::V8::SetFunctionEntryHook(isolate, EntryHook));
13930
13931 {
13932 v8::Isolate::Scope scope(isolate);
13933
13934 v8::V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, JitEvent);
13935
13936 RunLoopInNewEnv(isolate);
13937
13938 // Check the exepected invocation counts.
13939 CHECK_EQ(2, CountInvocations(NULL, "bar"));
13940 CHECK_EQ(200, CountInvocations("bar", "foo"));
13941 CHECK_EQ(200, CountInvocations(NULL, "foo"));
13942
13943 // Verify that we have an entry hook on some specific stubs.
13944 CHECK_NE(0, CountInvocations(NULL, "CEntryStub"));
13945 CHECK_NE(0, CountInvocations(NULL, "JSEntryStub"));
13946 CHECK_NE(0, CountInvocations(NULL, "JSEntryTrampoline"));
13947 }
13948 isolate->Dispose();
13949
13950 Reset();
13951
13952 // Make sure a second isolate is unaffected by the previous entry hook.
13953 isolate = v8::Isolate::New();
13954 {
13955 v8::Isolate::Scope scope(isolate);
13956
13957 // Reset the entry count to zero and set the entry hook.
13958 RunLoopInNewEnv(isolate);
13959
13960 // We should record no invocations in this isolate.
13961 CHECK_EQ(0, static_cast<int>(invocations_.size()));
13962 }
13963 // Since the isolate has been used, we shouldn't be able to set an entry
13964 // hook anymore.
13965 CHECK_EQ(false, v8::V8::SetFunctionEntryHook(isolate, EntryHook));
13966
13967 isolate->Dispose();
13968}
13969
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013970
13971TEST(SetFunctionEntryHook) {
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000013972 // FunctionEntryHook does not work well with experimental natives.
13973 // Experimental natives are compiled during snapshot deserialization.
13974 // This test breaks because InstallGetter (function from snapshot that
13975 // only gets called from experimental natives) is compiled with entry hooks.
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013976 i::FLAG_allow_natives_syntax = true;
yangguo@chromium.orgfb377212012-11-16 14:43:43 +000013977 i::FLAG_use_inlining = false;
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013978
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013979 SetFunctionEntryHookTest test;
13980 test.RunTest();
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013981}
13982
13983
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000013984static i::HashMap* code_map = NULL;
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +000013985static i::HashMap* jitcode_line_info = NULL;
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000013986static int saw_bar = 0;
13987static int move_events = 0;
13988
13989
13990static bool FunctionNameIs(const char* expected,
13991 const v8::JitCodeEvent* event) {
13992 // Log lines for functions are of the general form:
13993 // "LazyCompile:<type><function_name>", where the type is one of
13994 // "*", "~" or "".
13995 static const char kPreamble[] = "LazyCompile:";
13996 static size_t kPreambleLen = sizeof(kPreamble) - 1;
13997
13998 if (event->name.len < sizeof(kPreamble) - 1 ||
13999 strncmp(kPreamble, event->name.str, kPreambleLen) != 0) {
14000 return false;
14001 }
14002
14003 const char* tail = event->name.str + kPreambleLen;
14004 size_t tail_len = event->name.len - kPreambleLen;
14005 size_t expected_len = strlen(expected);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000014006 if (tail_len > 1 && (*tail == '*' || *tail == '~')) {
14007 --tail_len;
14008 ++tail;
14009 }
14010
14011 // Check for tails like 'bar :1'.
14012 if (tail_len > expected_len + 2 &&
14013 tail[expected_len] == ' ' &&
14014 tail[expected_len + 1] == ':' &&
14015 tail[expected_len + 2] &&
14016 !strncmp(tail, expected, expected_len)) {
14017 return true;
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014018 }
14019
14020 if (tail_len != expected_len)
14021 return false;
14022
14023 return strncmp(tail, expected, expected_len) == 0;
14024}
14025
14026
14027static void event_handler(const v8::JitCodeEvent* event) {
14028 CHECK(event != NULL);
14029 CHECK(code_map != NULL);
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +000014030 CHECK(jitcode_line_info != NULL);
14031
14032 class DummyJitCodeLineInfo {
14033 };
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014034
14035 switch (event->type) {
14036 case v8::JitCodeEvent::CODE_ADDED: {
14037 CHECK(event->code_start != NULL);
14038 CHECK_NE(0, static_cast<int>(event->code_len));
14039 CHECK(event->name.str != NULL);
14040 i::HashMap::Entry* entry =
14041 code_map->Lookup(event->code_start,
14042 i::ComputePointerHash(event->code_start),
14043 true);
14044 entry->value = reinterpret_cast<void*>(event->code_len);
14045
14046 if (FunctionNameIs("bar", event)) {
14047 ++saw_bar;
14048 }
14049 }
14050 break;
14051
14052 case v8::JitCodeEvent::CODE_MOVED: {
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014053 uint32_t hash = i::ComputePointerHash(event->code_start);
jkummerow@chromium.org78502a92012-09-06 13:50:42 +000014054 // We would like to never see code move that we haven't seen before,
14055 // but the code creation event does not happen until the line endings
14056 // have been calculated (this is so that we can report the line in the
14057 // script at which the function source is found, see
14058 // Compiler::RecordFunctionCompilation) and the line endings
14059 // calculations can cause a GC, which can move the newly created code
14060 // before its existence can be logged.
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014061 i::HashMap::Entry* entry =
14062 code_map->Lookup(event->code_start, hash, false);
jkummerow@chromium.org78502a92012-09-06 13:50:42 +000014063 if (entry != NULL) {
14064 ++move_events;
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014065
jkummerow@chromium.org78502a92012-09-06 13:50:42 +000014066 CHECK_EQ(reinterpret_cast<void*>(event->code_len), entry->value);
14067 code_map->Remove(event->code_start, hash);
14068
14069 entry = code_map->Lookup(event->new_code_start,
14070 i::ComputePointerHash(event->new_code_start),
14071 true);
14072 CHECK(entry != NULL);
14073 entry->value = reinterpret_cast<void*>(event->code_len);
14074 }
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014075 }
14076 break;
14077
14078 case v8::JitCodeEvent::CODE_REMOVED:
14079 // Object/code removal events are currently not dispatched from the GC.
14080 CHECK(false);
14081 break;
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +000014082
14083 // For CODE_START_LINE_INFO_RECORDING event, we will create one
14084 // DummyJitCodeLineInfo data structure pointed by event->user_dat. We
14085 // record it in jitcode_line_info.
14086 case v8::JitCodeEvent::CODE_START_LINE_INFO_RECORDING: {
14087 DummyJitCodeLineInfo* line_info = new DummyJitCodeLineInfo();
14088 v8::JitCodeEvent* temp_event = const_cast<v8::JitCodeEvent*>(event);
14089 temp_event->user_data = line_info;
14090 i::HashMap::Entry* entry =
14091 jitcode_line_info->Lookup(line_info,
14092 i::ComputePointerHash(line_info),
14093 true);
14094 entry->value = reinterpret_cast<void*>(line_info);
14095 }
14096 break;
14097 // For these two events, we will check whether the event->user_data
14098 // data structure is created before during CODE_START_LINE_INFO_RECORDING
14099 // event. And delete it in CODE_END_LINE_INFO_RECORDING event handling.
14100 case v8::JitCodeEvent::CODE_END_LINE_INFO_RECORDING: {
14101 CHECK(event->user_data != NULL);
14102 uint32_t hash = i::ComputePointerHash(event->user_data);
14103 i::HashMap::Entry* entry =
14104 jitcode_line_info->Lookup(event->user_data, hash, false);
14105 CHECK(entry != NULL);
14106 delete reinterpret_cast<DummyJitCodeLineInfo*>(event->user_data);
14107 }
14108 break;
14109
14110 case v8::JitCodeEvent::CODE_ADD_LINE_POS_INFO: {
14111 CHECK(event->user_data != NULL);
14112 uint32_t hash = i::ComputePointerHash(event->user_data);
14113 i::HashMap::Entry* entry =
14114 jitcode_line_info->Lookup(event->user_data, hash, false);
14115 CHECK(entry != NULL);
14116 }
14117 break;
14118
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014119 default:
14120 // Impossible event.
14121 CHECK(false);
14122 break;
14123 }
14124}
14125
14126
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014127UNINITIALIZED_TEST(SetJitCodeEventHandler) {
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +000014128 i::FLAG_stress_compaction = true;
danno@chromium.orgf005df62013-04-30 16:36:45 +000014129 i::FLAG_incremental_marking = false;
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014130 const char* script =
14131 "function bar() {"
14132 " var sum = 0;"
14133 " for (i = 0; i < 100; ++i)"
14134 " sum = foo(i);"
14135 " return sum;"
14136 "}"
14137 "function foo(i) { return i * i; };"
14138 "bar();";
14139
14140 // Run this test in a new isolate to make sure we don't
14141 // have remnants of state from other code.
14142 v8::Isolate* isolate = v8::Isolate::New();
14143 isolate->Enter();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014144 i::Heap* heap = reinterpret_cast<i::Isolate*>(isolate)->heap();
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014145
14146 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014147 v8::HandleScope scope(isolate);
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014148 i::HashMap code(MatchPointers);
14149 code_map = &code;
14150
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +000014151 i::HashMap lineinfo(MatchPointers);
14152 jitcode_line_info = &lineinfo;
14153
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014154 saw_bar = 0;
14155 move_events = 0;
14156
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014157 V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, event_handler);
14158
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014159 // Generate new code objects sparsely distributed across several
14160 // different fragmented code-space pages.
14161 const int kIterations = 10;
14162 for (int i = 0; i < kIterations; ++i) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014163 LocalContext env(isolate);
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +000014164 i::AlwaysAllocateScope always_allocate;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014165 SimulateFullSpace(heap->code_space());
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +000014166 CompileRun(script);
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014167
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +000014168 // Keep a strong reference to the code object in the handle scope.
14169 i::Handle<i::Code> bar_code(i::Handle<i::JSFunction>::cast(
14170 v8::Utils::OpenHandle(*env->Global()->Get(v8_str("bar"))))->code());
14171 i::Handle<i::Code> foo_code(i::Handle<i::JSFunction>::cast(
14172 v8::Utils::OpenHandle(*env->Global()->Get(v8_str("foo"))))->code());
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014173
14174 // Clear the compilation cache to get more wastage.
hpayer@chromium.orgc5d49712013-09-11 08:25:48 +000014175 reinterpret_cast<i::Isolate*>(isolate)->compilation_cache()->Clear();
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014176 }
14177
14178 // Force code movement.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014179 heap->CollectAllAvailableGarbage("TestSetJitCodeEventHandler");
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014180
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +000014181 V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
14182
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014183 CHECK_LE(kIterations, saw_bar);
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +000014184 CHECK_LT(0, move_events);
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014185
14186 code_map = NULL;
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +000014187 jitcode_line_info = NULL;
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014188 }
14189
14190 isolate->Exit();
14191 isolate->Dispose();
14192
14193 // Do this in a new isolate.
14194 isolate = v8::Isolate::New();
14195 isolate->Enter();
14196
14197 // Verify that we get callbacks for existing code objects when we
14198 // request enumeration of existing code.
14199 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014200 v8::HandleScope scope(isolate);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014201 LocalContext env(isolate);
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014202 CompileRun(script);
14203
14204 // Now get code through initial iteration.
14205 i::HashMap code(MatchPointers);
14206 code_map = &code;
14207
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +000014208 i::HashMap lineinfo(MatchPointers);
14209 jitcode_line_info = &lineinfo;
14210
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014211 V8::SetJitCodeEventHandler(v8::kJitCodeEventEnumExisting, event_handler);
14212 V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
14213
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +000014214 jitcode_line_info = NULL;
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014215 // We expect that we got some events. Note that if we could get code removal
14216 // notifications, we could compare two collections, one created by listening
14217 // from the time of creation of an isolate, and the other by subscribing
14218 // with EnumExisting.
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +000014219 CHECK_LT(0, code.occupancy());
14220
14221 code_map = NULL;
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014222 }
14223
14224 isolate->Exit();
14225 isolate->Dispose();
14226}
14227
14228
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000014229THREADED_TEST(ExternalAllocatedMemory) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014230 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000014231 v8::HandleScope outer(isolate);
14232 v8::Local<Context> env(Context::New(isolate));
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000014233 CHECK(!env.IsEmpty());
machenbach@chromium.org7ff76072013-11-21 09:47:43 +000014234 const int64_t kSize = 1024*1024;
14235 int64_t baseline = isolate->AdjustAmountOfExternalAllocatedMemory(0);
14236 CHECK_EQ(baseline + kSize,
14237 isolate->AdjustAmountOfExternalAllocatedMemory(kSize));
danno@chromium.orgf005df62013-04-30 16:36:45 +000014238 CHECK_EQ(baseline,
machenbach@chromium.org7ff76072013-11-21 09:47:43 +000014239 isolate->AdjustAmountOfExternalAllocatedMemory(-kSize));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000014240}
14241
14242
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014243// Regression test for issue 54, object templates with internal fields
14244// but no accessors or interceptors did not get their internal field
14245// count set on instances.
14246THREADED_TEST(Regress54) {
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014247 LocalContext context;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000014248 v8::Isolate* isolate = context->GetIsolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014249 v8::HandleScope outer(isolate);
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014250 static v8::Persistent<v8::ObjectTemplate> templ;
14251 if (templ.IsEmpty()) {
machenbach@chromium.orgafbdadc2013-12-09 16:12:18 +000014252 v8::EscapableHandleScope inner(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000014253 v8::Local<v8::ObjectTemplate> local = v8::ObjectTemplate::New(isolate);
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014254 local->SetInternalFieldCount(1);
machenbach@chromium.orgafbdadc2013-12-09 16:12:18 +000014255 templ.Reset(isolate, inner.Escape(local));
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014256 }
rossberg@chromium.org79e79022013-06-03 15:43:46 +000014257 v8::Handle<v8::Object> result =
14258 v8::Local<v8::ObjectTemplate>::New(isolate, templ)->NewInstance();
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014259 CHECK_EQ(1, result->InternalFieldCount());
14260}
14261
14262
14263// If part of the threaded tests, this test makes ThreadingTest fail
14264// on mac.
14265TEST(CatchStackOverflow) {
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014266 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014267 v8::HandleScope scope(context->GetIsolate());
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014268 v8::TryCatch try_catch;
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000014269 v8::Handle<v8::Script> script = v8::Script::Compile(v8::String::NewFromUtf8(
14270 context->GetIsolate(),
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014271 "function f() {"
14272 " return f();"
14273 "}"
14274 ""
14275 "f();"));
14276 v8::Handle<v8::Value> result = script->Run();
14277 CHECK(result.IsEmpty());
14278}
14279
14280
kasperl@chromium.org7be3c992009-03-12 07:19:55 +000014281static void CheckTryCatchSourceInfo(v8::Handle<v8::Script> script,
14282 const char* resource_name,
14283 int line_offset) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014284 v8::HandleScope scope(CcTest::isolate());
kasperl@chromium.org7be3c992009-03-12 07:19:55 +000014285 v8::TryCatch try_catch;
14286 v8::Handle<v8::Value> result = script->Run();
14287 CHECK(result.IsEmpty());
14288 CHECK(try_catch.HasCaught());
14289 v8::Handle<v8::Message> message = try_catch.Message();
14290 CHECK(!message.IsEmpty());
14291 CHECK_EQ(10 + line_offset, message->GetLineNumber());
14292 CHECK_EQ(91, message->GetStartPosition());
14293 CHECK_EQ(92, message->GetEndPosition());
14294 CHECK_EQ(2, message->GetStartColumn());
14295 CHECK_EQ(3, message->GetEndColumn());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000014296 v8::String::Utf8Value line(message->GetSourceLine());
kasperl@chromium.org7be3c992009-03-12 07:19:55 +000014297 CHECK_EQ(" throw 'nirk';", *line);
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000014298 v8::String::Utf8Value name(message->GetScriptResourceName());
kasperl@chromium.org7be3c992009-03-12 07:19:55 +000014299 CHECK_EQ(resource_name, *name);
14300}
14301
14302
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014303THREADED_TEST(TryCatchSourceInfo) {
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014304 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014305 v8::HandleScope scope(context->GetIsolate());
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000014306 v8::Handle<v8::String> source = v8::String::NewFromUtf8(
14307 context->GetIsolate(),
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014308 "function Foo() {\n"
14309 " return Bar();\n"
14310 "}\n"
14311 "\n"
14312 "function Bar() {\n"
14313 " return Baz();\n"
14314 "}\n"
14315 "\n"
14316 "function Baz() {\n"
14317 " throw 'nirk';\n"
14318 "}\n"
14319 "\n"
14320 "Foo();\n");
kasperl@chromium.org7be3c992009-03-12 07:19:55 +000014321
14322 const char* resource_name;
14323 v8::Handle<v8::Script> script;
14324 resource_name = "test.js";
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000014325 script = v8::Script::Compile(
14326 source, v8::String::NewFromUtf8(context->GetIsolate(), resource_name));
kasperl@chromium.org7be3c992009-03-12 07:19:55 +000014327 CheckTryCatchSourceInfo(script, resource_name, 0);
14328
14329 resource_name = "test1.js";
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000014330 v8::ScriptOrigin origin1(
14331 v8::String::NewFromUtf8(context->GetIsolate(), resource_name));
kasperl@chromium.org7be3c992009-03-12 07:19:55 +000014332 script = v8::Script::Compile(source, &origin1);
14333 CheckTryCatchSourceInfo(script, resource_name, 0);
14334
14335 resource_name = "test2.js";
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000014336 v8::ScriptOrigin origin2(
14337 v8::String::NewFromUtf8(context->GetIsolate(), resource_name),
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014338 v8::Integer::New(context->GetIsolate(), 7));
kasperl@chromium.org7be3c992009-03-12 07:19:55 +000014339 script = v8::Script::Compile(source, &origin2);
14340 CheckTryCatchSourceInfo(script, resource_name, 7);
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014341}
kasperl@chromium.orgb9123622008-09-17 14:05:56 +000014342
14343
14344THREADED_TEST(CompilationCache) {
kasperl@chromium.orgb9123622008-09-17 14:05:56 +000014345 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014346 v8::HandleScope scope(context->GetIsolate());
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000014347 v8::Handle<v8::String> source0 =
14348 v8::String::NewFromUtf8(context->GetIsolate(), "1234");
14349 v8::Handle<v8::String> source1 =
14350 v8::String::NewFromUtf8(context->GetIsolate(), "1234");
14351 v8::Handle<v8::Script> script0 = v8::Script::Compile(
14352 source0, v8::String::NewFromUtf8(context->GetIsolate(), "test.js"));
14353 v8::Handle<v8::Script> script1 = v8::Script::Compile(
14354 source1, v8::String::NewFromUtf8(context->GetIsolate(), "test.js"));
kasperl@chromium.orgb9123622008-09-17 14:05:56 +000014355 v8::Handle<v8::Script> script2 =
14356 v8::Script::Compile(source0); // different origin
14357 CHECK_EQ(1234, script0->Run()->Int32Value());
14358 CHECK_EQ(1234, script1->Run()->Int32Value());
14359 CHECK_EQ(1234, script2->Run()->Int32Value());
14360}
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000014361
14362
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000014363static void FunctionNameCallback(
14364 const v8::FunctionCallbackInfo<v8::Value>& args) {
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000014365 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000014366 args.GetReturnValue().Set(v8_num(42));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000014367}
14368
14369
14370THREADED_TEST(CallbackFunctionName) {
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000014371 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000014372 v8::Isolate* isolate = context->GetIsolate();
14373 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000014374 Local<ObjectTemplate> t = ObjectTemplate::New(isolate);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000014375 t->Set(v8_str("asdf"),
14376 v8::FunctionTemplate::New(isolate, FunctionNameCallback));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000014377 context->Global()->Set(v8_str("obj"), t->NewInstance());
14378 v8::Handle<v8::Value> value = CompileRun("obj.asdf.name");
14379 CHECK(value->IsString());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000014380 v8::String::Utf8Value name(value);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000014381 CHECK_EQ("asdf", *name);
14382}
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014383
14384
14385THREADED_TEST(DateAccess) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014386 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014387 v8::HandleScope scope(context->GetIsolate());
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000014388 v8::Handle<v8::Value> date =
14389 v8::Date::New(context->GetIsolate(), 1224744689038.0);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014390 CHECK(date->IsDate());
danno@chromium.orgd3c42102013-08-01 16:58:23 +000014391 CHECK_EQ(1224744689038.0, date.As<v8::Date>()->ValueOf());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014392}
14393
14394
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014395void CheckProperties(v8::Isolate* isolate,
14396 v8::Handle<v8::Value> val,
14397 int elmc,
14398 const char* elmv[]) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000014399 v8::Handle<v8::Object> obj = val.As<v8::Object>();
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014400 v8::Handle<v8::Array> props = obj->GetPropertyNames();
14401 CHECK_EQ(elmc, props->Length());
14402 for (int i = 0; i < elmc; i++) {
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014403 v8::String::Utf8Value elm(props->Get(v8::Integer::New(isolate, i)));
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014404 CHECK_EQ(elmv[i], *elm);
14405 }
14406}
14407
14408
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014409void CheckOwnProperties(v8::Isolate* isolate,
14410 v8::Handle<v8::Value> val,
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000014411 int elmc,
14412 const char* elmv[]) {
14413 v8::Handle<v8::Object> obj = val.As<v8::Object>();
14414 v8::Handle<v8::Array> props = obj->GetOwnPropertyNames();
14415 CHECK_EQ(elmc, props->Length());
14416 for (int i = 0; i < elmc; i++) {
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014417 v8::String::Utf8Value elm(props->Get(v8::Integer::New(isolate, i)));
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000014418 CHECK_EQ(elmv[i], *elm);
14419 }
14420}
14421
14422
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014423THREADED_TEST(PropertyEnumeration) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014424 LocalContext context;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014425 v8::Isolate* isolate = context->GetIsolate();
14426 v8::HandleScope scope(isolate);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000014427 v8::Handle<v8::Value> obj = v8::Script::Compile(v8::String::NewFromUtf8(
14428 context->GetIsolate(),
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014429 "var result = [];"
14430 "result[0] = {};"
14431 "result[1] = {a: 1, b: 2};"
14432 "result[2] = [1, 2, 3];"
14433 "var proto = {x: 1, y: 2, z: 3};"
14434 "var x = { __proto__: proto, w: 0, z: 1 };"
14435 "result[3] = x;"
14436 "result;"))->Run();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000014437 v8::Handle<v8::Array> elms = obj.As<v8::Array>();
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014438 CHECK_EQ(4, elms->Length());
14439 int elmc0 = 0;
14440 const char** elmv0 = NULL;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014441 CheckProperties(
14442 isolate, elms->Get(v8::Integer::New(isolate, 0)), elmc0, elmv0);
14443 CheckOwnProperties(
14444 isolate, elms->Get(v8::Integer::New(isolate, 0)), elmc0, elmv0);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014445 int elmc1 = 2;
14446 const char* elmv1[] = {"a", "b"};
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014447 CheckProperties(
14448 isolate, elms->Get(v8::Integer::New(isolate, 1)), elmc1, elmv1);
14449 CheckOwnProperties(
14450 isolate, elms->Get(v8::Integer::New(isolate, 1)), elmc1, elmv1);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014451 int elmc2 = 3;
14452 const char* elmv2[] = {"0", "1", "2"};
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014453 CheckProperties(
14454 isolate, elms->Get(v8::Integer::New(isolate, 2)), elmc2, elmv2);
14455 CheckOwnProperties(
14456 isolate, elms->Get(v8::Integer::New(isolate, 2)), elmc2, elmv2);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014457 int elmc3 = 4;
14458 const char* elmv3[] = {"w", "z", "x", "y"};
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014459 CheckProperties(
14460 isolate, elms->Get(v8::Integer::New(isolate, 3)), elmc3, elmv3);
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000014461 int elmc4 = 2;
14462 const char* elmv4[] = {"w", "z"};
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014463 CheckOwnProperties(
14464 isolate, elms->Get(v8::Integer::New(isolate, 3)), elmc4, elmv4);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014465}
ager@chromium.org870a0b62008-11-04 11:43:05 +000014466
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000014467
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000014468THREADED_TEST(PropertyEnumeration2) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000014469 LocalContext context;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014470 v8::Isolate* isolate = context->GetIsolate();
14471 v8::HandleScope scope(isolate);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000014472 v8::Handle<v8::Value> obj = v8::Script::Compile(v8::String::NewFromUtf8(
14473 context->GetIsolate(),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000014474 "var result = [];"
14475 "result[0] = {};"
14476 "result[1] = {a: 1, b: 2};"
14477 "result[2] = [1, 2, 3];"
14478 "var proto = {x: 1, y: 2, z: 3};"
14479 "var x = { __proto__: proto, w: 0, z: 1 };"
14480 "result[3] = x;"
14481 "result;"))->Run();
14482 v8::Handle<v8::Array> elms = obj.As<v8::Array>();
14483 CHECK_EQ(4, elms->Length());
14484 int elmc0 = 0;
14485 const char** elmv0 = NULL;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014486 CheckProperties(isolate,
14487 elms->Get(v8::Integer::New(isolate, 0)), elmc0, elmv0);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000014488
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014489 v8::Handle<v8::Value> val = elms->Get(v8::Integer::New(isolate, 0));
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000014490 v8::Handle<v8::Array> props = val.As<v8::Object>()->GetPropertyNames();
14491 CHECK_EQ(0, props->Length());
14492 for (uint32_t i = 0; i < props->Length(); i++) {
14493 printf("p[%d]\n", i);
14494 }
14495}
ager@chromium.org870a0b62008-11-04 11:43:05 +000014496
ager@chromium.org870a0b62008-11-04 11:43:05 +000014497static bool NamedSetAccessBlocker(Local<v8::Object> obj,
14498 Local<Value> name,
14499 v8::AccessType type,
14500 Local<Value> data) {
14501 return type != v8::ACCESS_SET;
14502}
14503
14504
14505static bool IndexedSetAccessBlocker(Local<v8::Object> obj,
14506 uint32_t key,
14507 v8::AccessType type,
14508 Local<Value> data) {
14509 return type != v8::ACCESS_SET;
14510}
14511
14512
14513THREADED_TEST(DisableAccessChecksWhileConfiguring) {
ager@chromium.org870a0b62008-11-04 11:43:05 +000014514 LocalContext context;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000014515 v8::Isolate* isolate = context->GetIsolate();
14516 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000014517 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org870a0b62008-11-04 11:43:05 +000014518 templ->SetAccessCheckCallbacks(NamedSetAccessBlocker,
14519 IndexedSetAccessBlocker);
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000014520 templ->Set(v8_str("x"), v8::True(isolate));
ager@chromium.org870a0b62008-11-04 11:43:05 +000014521 Local<v8::Object> instance = templ->NewInstance();
14522 context->Global()->Set(v8_str("obj"), instance);
14523 Local<Value> value = CompileRun("obj.x");
14524 CHECK(value->BooleanValue());
14525}
ager@chromium.orga74f0da2008-12-03 16:05:52 +000014526
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000014527
ager@chromium.org32912102009-01-16 10:38:43 +000014528static bool NamedGetAccessBlocker(Local<v8::Object> obj,
14529 Local<Value> name,
14530 v8::AccessType type,
14531 Local<Value> data) {
14532 return false;
14533}
14534
14535
14536static bool IndexedGetAccessBlocker(Local<v8::Object> obj,
14537 uint32_t key,
14538 v8::AccessType type,
14539 Local<Value> data) {
14540 return false;
14541}
14542
14543
14544
14545THREADED_TEST(AccessChecksReenabledCorrectly) {
ager@chromium.org32912102009-01-16 10:38:43 +000014546 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000014547 v8::Isolate* isolate = context->GetIsolate();
14548 v8::HandleScope scope(isolate);
14549 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org32912102009-01-16 10:38:43 +000014550 templ->SetAccessCheckCallbacks(NamedGetAccessBlocker,
14551 IndexedGetAccessBlocker);
14552 templ->Set(v8_str("a"), v8_str("a"));
14553 // Add more than 8 (see kMaxFastProperties) properties
14554 // so that the constructor will force copying map.
14555 // Cannot sprintf, gcc complains unsafety.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000014556 char buf[4];
ager@chromium.org32912102009-01-16 10:38:43 +000014557 for (char i = '0'; i <= '9' ; i++) {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000014558 buf[0] = i;
ager@chromium.org32912102009-01-16 10:38:43 +000014559 for (char j = '0'; j <= '9'; j++) {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000014560 buf[1] = j;
ager@chromium.org32912102009-01-16 10:38:43 +000014561 for (char k = '0'; k <= '9'; k++) {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000014562 buf[2] = k;
14563 buf[3] = 0;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000014564 templ->Set(v8_str(buf), v8::Number::New(isolate, k));
ager@chromium.org32912102009-01-16 10:38:43 +000014565 }
14566 }
14567 }
14568
14569 Local<v8::Object> instance_1 = templ->NewInstance();
14570 context->Global()->Set(v8_str("obj_1"), instance_1);
14571
14572 Local<Value> value_1 = CompileRun("obj_1.a");
14573 CHECK(value_1->IsUndefined());
14574
14575 Local<v8::Object> instance_2 = templ->NewInstance();
14576 context->Global()->Set(v8_str("obj_2"), instance_2);
14577
14578 Local<Value> value_2 = CompileRun("obj_2.a");
14579 CHECK(value_2->IsUndefined());
14580}
ager@chromium.orga74f0da2008-12-03 16:05:52 +000014581
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000014582
ager@chromium.org8bb60582008-12-11 12:02:20 +000014583// This tests that access check information remains on the global
14584// object template when creating contexts.
14585THREADED_TEST(AccessControlRepeatedContextCreation) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014586 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000014587 v8::HandleScope handle_scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000014588 v8::Handle<v8::ObjectTemplate> global_template =
14589 v8::ObjectTemplate::New(isolate);
ager@chromium.org8bb60582008-12-11 12:02:20 +000014590 global_template->SetAccessCheckCallbacks(NamedSetAccessBlocker,
14591 IndexedSetAccessBlocker);
14592 i::Handle<i::ObjectTemplateInfo> internal_template =
14593 v8::Utils::OpenHandle(*global_template);
14594 CHECK(!internal_template->constructor()->IsUndefined());
14595 i::Handle<i::FunctionTemplateInfo> constructor(
14596 i::FunctionTemplateInfo::cast(internal_template->constructor()));
14597 CHECK(!constructor->access_check_info()->IsUndefined());
ulan@chromium.org57ff8812013-05-10 08:16:55 +000014598 v8::Local<Context> context0(Context::New(isolate, NULL, global_template));
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000014599 CHECK(!context0.IsEmpty());
ager@chromium.org8bb60582008-12-11 12:02:20 +000014600 CHECK(!constructor->access_check_info()->IsUndefined());
14601}
14602
14603
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000014604THREADED_TEST(TurnOnAccessCheck) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014605 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000014606 v8::HandleScope handle_scope(isolate);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000014607
14608 // Create an environment with access check to the global object disabled by
14609 // default.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000014610 v8::Handle<v8::ObjectTemplate> global_template =
14611 v8::ObjectTemplate::New(isolate);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000014612 global_template->SetAccessCheckCallbacks(NamedGetAccessBlocker,
14613 IndexedGetAccessBlocker,
14614 v8::Handle<v8::Value>(),
14615 false);
ulan@chromium.org57ff8812013-05-10 08:16:55 +000014616 v8::Local<Context> context = Context::New(isolate, NULL, global_template);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000014617 Context::Scope context_scope(context);
14618
14619 // Set up a property and a number of functions.
14620 context->Global()->Set(v8_str("a"), v8_num(1));
14621 CompileRun("function f1() {return a;}"
14622 "function f2() {return a;}"
14623 "function g1() {return h();}"
14624 "function g2() {return h();}"
14625 "function h() {return 1;}");
14626 Local<Function> f1 =
14627 Local<Function>::Cast(context->Global()->Get(v8_str("f1")));
14628 Local<Function> f2 =
14629 Local<Function>::Cast(context->Global()->Get(v8_str("f2")));
14630 Local<Function> g1 =
14631 Local<Function>::Cast(context->Global()->Get(v8_str("g1")));
14632 Local<Function> g2 =
14633 Local<Function>::Cast(context->Global()->Get(v8_str("g2")));
14634 Local<Function> h =
14635 Local<Function>::Cast(context->Global()->Get(v8_str("h")));
14636
14637 // Get the global object.
14638 v8::Handle<v8::Object> global = context->Global();
14639
14640 // Call f1 one time and f2 a number of times. This will ensure that f1 still
14641 // uses the runtime system to retreive property a whereas f2 uses global load
14642 // inline cache.
14643 CHECK(f1->Call(global, 0, NULL)->Equals(v8_num(1)));
14644 for (int i = 0; i < 4; i++) {
14645 CHECK(f2->Call(global, 0, NULL)->Equals(v8_num(1)));
14646 }
14647
14648 // Same for g1 and g2.
14649 CHECK(g1->Call(global, 0, NULL)->Equals(v8_num(1)));
14650 for (int i = 0; i < 4; i++) {
14651 CHECK(g2->Call(global, 0, NULL)->Equals(v8_num(1)));
14652 }
14653
14654 // Detach the global and turn on access check.
jkummerow@chromium.org113035e2013-12-13 15:13:40 +000014655 Local<Object> hidden_global = Local<Object>::Cast(
14656 context->Global()->GetPrototype());
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000014657 context->DetachGlobal();
jkummerow@chromium.org113035e2013-12-13 15:13:40 +000014658 hidden_global->TurnOnAccessCheck();
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000014659
14660 // Failing access check to property get results in undefined.
14661 CHECK(f1->Call(global, 0, NULL)->IsUndefined());
14662 CHECK(f2->Call(global, 0, NULL)->IsUndefined());
14663
14664 // Failing access check to function call results in exception.
14665 CHECK(g1->Call(global, 0, NULL).IsEmpty());
14666 CHECK(g2->Call(global, 0, NULL).IsEmpty());
14667
14668 // No failing access check when just returning a constant.
14669 CHECK(h->Call(global, 0, NULL)->Equals(v8_num(1)));
14670}
14671
14672
jkummerow@chromium.orgf7a58842012-02-21 10:08:21 +000014673static const char* kPropertyA = "a";
14674static const char* kPropertyH = "h";
kasperl@chromium.orga5551262010-12-07 12:49:48 +000014675
14676static bool NamedGetAccessBlockAandH(Local<v8::Object> obj,
14677 Local<Value> name,
14678 v8::AccessType type,
14679 Local<Value> data) {
jkummerow@chromium.orgf7a58842012-02-21 10:08:21 +000014680 if (!name->IsString()) return false;
14681 i::Handle<i::String> name_handle =
14682 v8::Utils::OpenHandle(String::Cast(*name));
jkummerow@chromium.org59297c72013-01-09 16:32:23 +000014683 return !name_handle->IsUtf8EqualTo(i::CStrVector(kPropertyA))
14684 && !name_handle->IsUtf8EqualTo(i::CStrVector(kPropertyH));
kasperl@chromium.orga5551262010-12-07 12:49:48 +000014685}
14686
14687
jkummerow@chromium.orgf7a58842012-02-21 10:08:21 +000014688THREADED_TEST(TurnOnAccessCheckAndRecompile) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014689 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000014690 v8::HandleScope handle_scope(isolate);
kasperl@chromium.orga5551262010-12-07 12:49:48 +000014691
14692 // Create an environment with access check to the global object disabled by
14693 // default. When the registered access checker will block access to properties
jkummerow@chromium.orgf7a58842012-02-21 10:08:21 +000014694 // a and h.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000014695 v8::Handle<v8::ObjectTemplate> global_template =
14696 v8::ObjectTemplate::New(isolate);
kasperl@chromium.orga5551262010-12-07 12:49:48 +000014697 global_template->SetAccessCheckCallbacks(NamedGetAccessBlockAandH,
14698 IndexedGetAccessBlocker,
14699 v8::Handle<v8::Value>(),
14700 false);
ulan@chromium.org57ff8812013-05-10 08:16:55 +000014701 v8::Local<Context> context = Context::New(isolate, NULL, global_template);
kasperl@chromium.orga5551262010-12-07 12:49:48 +000014702 Context::Scope context_scope(context);
14703
14704 // Set up a property and a number of functions.
14705 context->Global()->Set(v8_str("a"), v8_num(1));
14706 static const char* source = "function f1() {return a;}"
14707 "function f2() {return a;}"
14708 "function g1() {return h();}"
14709 "function g2() {return h();}"
14710 "function h() {return 1;}";
14711
14712 CompileRun(source);
14713 Local<Function> f1;
14714 Local<Function> f2;
14715 Local<Function> g1;
14716 Local<Function> g2;
14717 Local<Function> h;
14718 f1 = Local<Function>::Cast(context->Global()->Get(v8_str("f1")));
14719 f2 = Local<Function>::Cast(context->Global()->Get(v8_str("f2")));
14720 g1 = Local<Function>::Cast(context->Global()->Get(v8_str("g1")));
14721 g2 = Local<Function>::Cast(context->Global()->Get(v8_str("g2")));
14722 h = Local<Function>::Cast(context->Global()->Get(v8_str("h")));
14723
14724 // Get the global object.
14725 v8::Handle<v8::Object> global = context->Global();
14726
14727 // Call f1 one time and f2 a number of times. This will ensure that f1 still
14728 // uses the runtime system to retreive property a whereas f2 uses global load
14729 // inline cache.
14730 CHECK(f1->Call(global, 0, NULL)->Equals(v8_num(1)));
14731 for (int i = 0; i < 4; i++) {
14732 CHECK(f2->Call(global, 0, NULL)->Equals(v8_num(1)));
14733 }
14734
14735 // Same for g1 and g2.
14736 CHECK(g1->Call(global, 0, NULL)->Equals(v8_num(1)));
14737 for (int i = 0; i < 4; i++) {
14738 CHECK(g2->Call(global, 0, NULL)->Equals(v8_num(1)));
14739 }
14740
14741 // Detach the global and turn on access check now blocking access to property
14742 // a and function h.
jkummerow@chromium.org113035e2013-12-13 15:13:40 +000014743 Local<Object> hidden_global = Local<Object>::Cast(
14744 context->Global()->GetPrototype());
kasperl@chromium.orga5551262010-12-07 12:49:48 +000014745 context->DetachGlobal();
jkummerow@chromium.org113035e2013-12-13 15:13:40 +000014746 hidden_global->TurnOnAccessCheck();
kasperl@chromium.orga5551262010-12-07 12:49:48 +000014747
14748 // Failing access check to property get results in undefined.
14749 CHECK(f1->Call(global, 0, NULL)->IsUndefined());
14750 CHECK(f2->Call(global, 0, NULL)->IsUndefined());
14751
14752 // Failing access check to function call results in exception.
14753 CHECK(g1->Call(global, 0, NULL).IsEmpty());
14754 CHECK(g2->Call(global, 0, NULL).IsEmpty());
14755
14756 // No failing access check when just returning a constant.
14757 CHECK(h->Call(global, 0, NULL)->Equals(v8_num(1)));
14758
14759 // Now compile the source again. And get the newly compiled functions, except
14760 // for h for which access is blocked.
14761 CompileRun(source);
jkummerow@chromium.org113035e2013-12-13 15:13:40 +000014762 f1 = Local<Function>::Cast(hidden_global->Get(v8_str("f1")));
14763 f2 = Local<Function>::Cast(hidden_global->Get(v8_str("f2")));
14764 g1 = Local<Function>::Cast(hidden_global->Get(v8_str("g1")));
14765 g2 = Local<Function>::Cast(hidden_global->Get(v8_str("g2")));
14766 CHECK(hidden_global->Get(v8_str("h"))->IsUndefined());
kasperl@chromium.orga5551262010-12-07 12:49:48 +000014767
14768 // Failing access check to property get results in undefined.
14769 CHECK(f1->Call(global, 0, NULL)->IsUndefined());
14770 CHECK(f2->Call(global, 0, NULL)->IsUndefined());
14771
14772 // Failing access check to function call results in exception.
14773 CHECK(g1->Call(global, 0, NULL).IsEmpty());
14774 CHECK(g2->Call(global, 0, NULL).IsEmpty());
14775}
14776
14777
ager@chromium.orga74f0da2008-12-03 16:05:52 +000014778// This test verifies that pre-compilation (aka preparsing) can be called
14779// without initializing the whole VM. Thus we cannot run this test in a
14780// multi-threaded setup.
14781TEST(PreCompile) {
14782 // TODO(155): This test would break without the initialization of V8. This is
14783 // a workaround for now to make this test not fail.
14784 v8::V8::Initialize();
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +000014785 v8::Isolate* isolate = CcTest::isolate();
kmillikin@chromium.org9155e252010-05-26 13:27:57 +000014786 const char* script = "function foo(a) { return a+1; }";
14787 v8::ScriptData* sd =
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +000014788 v8::ScriptData::PreCompile(isolate, script, i::StrLength(script));
ager@chromium.orga74f0da2008-12-03 16:05:52 +000014789 CHECK_NE(sd->Length(), 0);
14790 CHECK_NE(sd->Data(), NULL);
fschneider@chromium.org0c20e672010-01-14 15:28:53 +000014791 CHECK(!sd->HasError());
14792 delete sd;
14793}
14794
14795
14796TEST(PreCompileWithError) {
14797 v8::V8::Initialize();
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +000014798 v8::Isolate* isolate = CcTest::isolate();
kmillikin@chromium.org9155e252010-05-26 13:27:57 +000014799 const char* script = "function foo(a) { return 1 * * 2; }";
14800 v8::ScriptData* sd =
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +000014801 v8::ScriptData::PreCompile(isolate, script, i::StrLength(script));
fschneider@chromium.org0c20e672010-01-14 15:28:53 +000014802 CHECK(sd->HasError());
14803 delete sd;
14804}
14805
14806
14807TEST(Regress31661) {
14808 v8::V8::Initialize();
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +000014809 v8::Isolate* isolate = CcTest::isolate();
kmillikin@chromium.org9155e252010-05-26 13:27:57 +000014810 const char* script = " The Definintive Guide";
14811 v8::ScriptData* sd =
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +000014812 v8::ScriptData::PreCompile(isolate, script, i::StrLength(script));
fschneider@chromium.org0c20e672010-01-14 15:28:53 +000014813 CHECK(sd->HasError());
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000014814 delete sd;
ager@chromium.orga74f0da2008-12-03 16:05:52 +000014815}
14816
14817
kmillikin@chromium.org9155e252010-05-26 13:27:57 +000014818// Tests that ScriptData can be serialized and deserialized.
14819TEST(PreCompileSerialization) {
14820 v8::V8::Initialize();
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +000014821 v8::Isolate* isolate = CcTest::isolate();
kmillikin@chromium.org9155e252010-05-26 13:27:57 +000014822 const char* script = "function foo(a) { return a+1; }";
14823 v8::ScriptData* sd =
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +000014824 v8::ScriptData::PreCompile(isolate, script, i::StrLength(script));
kmillikin@chromium.org9155e252010-05-26 13:27:57 +000014825
14826 // Serialize.
14827 int serialized_data_length = sd->Length();
14828 char* serialized_data = i::NewArray<char>(serialized_data_length);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +000014829 i::OS::MemCopy(serialized_data, sd->Data(), serialized_data_length);
kmillikin@chromium.org9155e252010-05-26 13:27:57 +000014830
14831 // Deserialize.
14832 v8::ScriptData* deserialized_sd =
14833 v8::ScriptData::New(serialized_data, serialized_data_length);
14834
14835 // Verify that the original is the same as the deserialized.
14836 CHECK_EQ(sd->Length(), deserialized_sd->Length());
14837 CHECK_EQ(0, memcmp(sd->Data(), deserialized_sd->Data(), sd->Length()));
14838 CHECK_EQ(sd->HasError(), deserialized_sd->HasError());
14839
14840 delete sd;
14841 delete deserialized_sd;
14842}
14843
14844
14845// Attempts to deserialize bad data.
14846TEST(PreCompileDeserializationError) {
14847 v8::V8::Initialize();
14848 const char* data = "DONT CARE";
14849 int invalid_size = 3;
14850 v8::ScriptData* sd = v8::ScriptData::New(data, invalid_size);
14851
14852 CHECK_EQ(0, sd->Length());
14853
14854 delete sd;
14855}
14856
14857
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014858// Attempts to deserialize bad data.
14859TEST(PreCompileInvalidPreparseDataError) {
14860 v8::V8::Initialize();
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +000014861 v8::Isolate* isolate = CcTest::isolate();
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014862 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014863 v8::HandleScope scope(context->GetIsolate());
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014864
14865 const char* script = "function foo(){ return 5;}\n"
14866 "function bar(){ return 6 + 7;} foo();";
14867 v8::ScriptData* sd =
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +000014868 v8::ScriptData::PreCompile(isolate, script, i::StrLength(script));
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014869 CHECK(!sd->HasError());
14870 // ScriptDataImpl private implementation details
ager@chromium.orgbeb25712010-11-29 08:02:25 +000014871 const int kHeaderSize = i::PreparseDataConstants::kHeaderSize;
ager@chromium.org5b2fbee2010-09-08 06:38:15 +000014872 const int kFunctionEntrySize = i::FunctionEntry::kSize;
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014873 const int kFunctionEntryStartOffset = 0;
14874 const int kFunctionEntryEndOffset = 1;
14875 unsigned* sd_data =
14876 reinterpret_cast<unsigned*>(const_cast<char*>(sd->Data()));
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014877
14878 // Overwrite function bar's end position with 0.
14879 sd_data[kHeaderSize + 1 * kFunctionEntrySize + kFunctionEntryEndOffset] = 0;
14880 v8::TryCatch try_catch;
14881
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000014882 Local<String> source = String::NewFromUtf8(isolate, script);
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014883 Local<Script> compiled_script = Script::New(source, NULL, sd);
14884 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000014885 String::Utf8Value exception_value(try_catch.Message()->Get());
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014886 CHECK_EQ("Uncaught SyntaxError: Invalid preparser data for function bar",
14887 *exception_value);
14888
14889 try_catch.Reset();
lrn@chromium.orgd4e9e222011-08-03 12:01:58 +000014890
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014891 // Overwrite function bar's start position with 200. The function entry
lrn@chromium.orgd4e9e222011-08-03 12:01:58 +000014892 // will not be found when searching for it by position and we should fall
14893 // back on eager compilation.
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +000014894 sd = v8::ScriptData::PreCompile(isolate, script, i::StrLength(script));
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +000014895 sd_data = reinterpret_cast<unsigned*>(const_cast<char*>(sd->Data()));
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014896 sd_data[kHeaderSize + 1 * kFunctionEntrySize + kFunctionEntryStartOffset] =
14897 200;
14898 compiled_script = Script::New(source, NULL, sd);
lrn@chromium.orgd4e9e222011-08-03 12:01:58 +000014899 CHECK(!try_catch.HasCaught());
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014900
14901 delete sd;
14902}
14903
14904
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +000014905// Verifies that the Handle<String> and const char* versions of the API produce
14906// the same results (at least for one trivial case).
14907TEST(PreCompileAPIVariationsAreSame) {
14908 v8::V8::Initialize();
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +000014909 v8::Isolate* isolate = CcTest::isolate();
14910 v8::HandleScope scope(isolate);
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +000014911
14912 const char* cstring = "function foo(a) { return a+1; }";
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000014913
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +000014914 v8::ScriptData* sd_from_cstring =
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +000014915 v8::ScriptData::PreCompile(isolate, cstring, i::StrLength(cstring));
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +000014916
14917 TestAsciiResource* resource = new TestAsciiResource(cstring);
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000014918 v8::ScriptData* sd_from_external_string = v8::ScriptData::PreCompile(
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000014919 v8::String::NewExternal(isolate, resource));
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +000014920
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000014921 v8::ScriptData* sd_from_string = v8::ScriptData::PreCompile(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000014922 v8::String::NewFromUtf8(isolate, cstring));
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000014923
14924 CHECK_EQ(sd_from_cstring->Length(), sd_from_external_string->Length());
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +000014925 CHECK_EQ(0, memcmp(sd_from_cstring->Data(),
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000014926 sd_from_external_string->Data(),
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +000014927 sd_from_cstring->Length()));
14928
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000014929 CHECK_EQ(sd_from_cstring->Length(), sd_from_string->Length());
14930 CHECK_EQ(0, memcmp(sd_from_cstring->Data(),
14931 sd_from_string->Data(),
14932 sd_from_cstring->Length()));
14933
14934
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +000014935 delete sd_from_cstring;
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000014936 delete sd_from_external_string;
14937 delete sd_from_string;
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +000014938}
14939
14940
ager@chromium.orga74f0da2008-12-03 16:05:52 +000014941// This tests that we do not allow dictionary load/call inline caches
14942// to use functions that have not yet been compiled. The potential
14943// problem of loading a function that has not yet been compiled can
14944// arise because we share code between contexts via the compilation
14945// cache.
14946THREADED_TEST(DictionaryICLoadedFunction) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014947 v8::HandleScope scope(CcTest::isolate());
ager@chromium.orga74f0da2008-12-03 16:05:52 +000014948 // Test LoadIC.
14949 for (int i = 0; i < 2; i++) {
14950 LocalContext context;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000014951 context->Global()->Set(v8_str("tmp"), v8::True(CcTest::isolate()));
ager@chromium.orga74f0da2008-12-03 16:05:52 +000014952 context->Global()->Delete(v8_str("tmp"));
14953 CompileRun("for (var j = 0; j < 10; j++) new RegExp('');");
14954 }
14955 // Test CallIC.
14956 for (int i = 0; i < 2; i++) {
14957 LocalContext context;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000014958 context->Global()->Set(v8_str("tmp"), v8::True(CcTest::isolate()));
ager@chromium.orga74f0da2008-12-03 16:05:52 +000014959 context->Global()->Delete(v8_str("tmp"));
14960 CompileRun("for (var j = 0; j < 10; j++) RegExp('')");
14961 }
14962}
ager@chromium.orgddb913d2009-01-27 10:01:48 +000014963
14964
14965// Test that cross-context new calls use the context of the callee to
14966// create the new JavaScript object.
14967THREADED_TEST(CrossContextNew) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014968 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000014969 v8::HandleScope scope(isolate);
14970 v8::Local<Context> context0 = Context::New(isolate);
14971 v8::Local<Context> context1 = Context::New(isolate);
ager@chromium.orgddb913d2009-01-27 10:01:48 +000014972
14973 // Allow cross-domain access.
14974 Local<String> token = v8_str("<security token>");
14975 context0->SetSecurityToken(token);
14976 context1->SetSecurityToken(token);
14977
14978 // Set an 'x' property on the Object prototype and define a
14979 // constructor function in context0.
14980 context0->Enter();
14981 CompileRun("Object.prototype.x = 42; function C() {};");
14982 context0->Exit();
14983
14984 // Call the constructor function from context0 and check that the
14985 // result has the 'x' property.
14986 context1->Enter();
14987 context1->Global()->Set(v8_str("other"), context0->Global());
14988 Local<Value> value = CompileRun("var instance = new other.C(); instance.x");
14989 CHECK(value->IsInt32());
14990 CHECK_EQ(42, value->Int32Value());
14991 context1->Exit();
ager@chromium.orgddb913d2009-01-27 10:01:48 +000014992}
ager@chromium.org381abbb2009-02-25 13:23:22 +000014993
14994
ager@chromium.org3b45ab52009-03-19 22:21:34 +000014995// Verify that we can clone an object
14996TEST(ObjectClone) {
ager@chromium.org3b45ab52009-03-19 22:21:34 +000014997 LocalContext env;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014998 v8::Isolate* isolate = env->GetIsolate();
14999 v8::HandleScope scope(isolate);
ager@chromium.org3b45ab52009-03-19 22:21:34 +000015000
15001 const char* sample =
15002 "var rv = {};" \
15003 "rv.alpha = 'hello';" \
15004 "rv.beta = 123;" \
15005 "rv;";
15006
15007 // Create an object, verify basics.
15008 Local<Value> val = CompileRun(sample);
15009 CHECK(val->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000015010 Local<v8::Object> obj = val.As<v8::Object>();
ager@chromium.org3b45ab52009-03-19 22:21:34 +000015011 obj->Set(v8_str("gamma"), v8_str("cloneme"));
15012
15013 CHECK_EQ(v8_str("hello"), obj->Get(v8_str("alpha")));
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015014 CHECK_EQ(v8::Integer::New(isolate, 123), obj->Get(v8_str("beta")));
ager@chromium.org3b45ab52009-03-19 22:21:34 +000015015 CHECK_EQ(v8_str("cloneme"), obj->Get(v8_str("gamma")));
15016
15017 // Clone it.
15018 Local<v8::Object> clone = obj->Clone();
15019 CHECK_EQ(v8_str("hello"), clone->Get(v8_str("alpha")));
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015020 CHECK_EQ(v8::Integer::New(isolate, 123), clone->Get(v8_str("beta")));
ager@chromium.org3b45ab52009-03-19 22:21:34 +000015021 CHECK_EQ(v8_str("cloneme"), clone->Get(v8_str("gamma")));
15022
15023 // Set a property on the clone, verify each object.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015024 clone->Set(v8_str("beta"), v8::Integer::New(isolate, 456));
15025 CHECK_EQ(v8::Integer::New(isolate, 123), obj->Get(v8_str("beta")));
15026 CHECK_EQ(v8::Integer::New(isolate, 456), clone->Get(v8_str("beta")));
ager@chromium.org3b45ab52009-03-19 22:21:34 +000015027}
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015028
15029
ager@chromium.org5ec48922009-05-05 07:25:34 +000015030class AsciiVectorResource : public v8::String::ExternalAsciiStringResource {
15031 public:
15032 explicit AsciiVectorResource(i::Vector<const char> vector)
15033 : data_(vector) {}
15034 virtual ~AsciiVectorResource() {}
15035 virtual size_t length() const { return data_.length(); }
15036 virtual const char* data() const { return data_.start(); }
15037 private:
15038 i::Vector<const char> data_;
15039};
15040
15041
15042class UC16VectorResource : public v8::String::ExternalStringResource {
15043 public:
15044 explicit UC16VectorResource(i::Vector<const i::uc16> vector)
15045 : data_(vector) {}
15046 virtual ~UC16VectorResource() {}
15047 virtual size_t length() const { return data_.length(); }
15048 virtual const i::uc16* data() const { return data_.start(); }
15049 private:
15050 i::Vector<const i::uc16> data_;
15051};
15052
15053
15054static void MorphAString(i::String* string,
15055 AsciiVectorResource* ascii_resource,
15056 UC16VectorResource* uc16_resource) {
15057 CHECK(i::StringShape(string).IsExternal());
ulan@chromium.org8e8d8822012-11-23 14:36:46 +000015058 if (string->IsOneByteRepresentation()) {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +000015059 // Check old map is not internalized or long.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015060 CHECK(string->map() == CcTest::heap()->external_ascii_string_map());
ager@chromium.org5ec48922009-05-05 07:25:34 +000015061 // Morph external string to be TwoByte string.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015062 string->set_map(CcTest::heap()->external_string_map());
ager@chromium.org5ec48922009-05-05 07:25:34 +000015063 i::ExternalTwoByteString* morphed =
15064 i::ExternalTwoByteString::cast(string);
15065 morphed->set_resource(uc16_resource);
15066 } else {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +000015067 // Check old map is not internalized or long.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015068 CHECK(string->map() == CcTest::heap()->external_string_map());
ager@chromium.org5ec48922009-05-05 07:25:34 +000015069 // Morph external string to be ASCII string.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015070 string->set_map(CcTest::heap()->external_ascii_string_map());
ager@chromium.org5ec48922009-05-05 07:25:34 +000015071 i::ExternalAsciiString* morphed =
15072 i::ExternalAsciiString::cast(string);
15073 morphed->set_resource(ascii_resource);
15074 }
15075}
15076
15077
15078// Test that we can still flatten a string if the components it is built up
15079// from have been turned into 16 bit strings in the mean time.
15080THREADED_TEST(MorphCompositeStringTest) {
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +000015081 char utf_buffer[129];
ager@chromium.org5ec48922009-05-05 07:25:34 +000015082 const char* c_string = "Now is the time for all good men"
15083 " to come to the aid of the party";
15084 uint16_t* two_byte_string = AsciiToTwoByteString(c_string);
15085 {
ager@chromium.org5ec48922009-05-05 07:25:34 +000015086 LocalContext env;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015087 i::Factory* factory = CcTest::i_isolate()->factory();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015088 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org5ec48922009-05-05 07:25:34 +000015089 AsciiVectorResource ascii_resource(
ager@chromium.orgc4c92722009-11-18 14:12:51 +000015090 i::Vector<const char>(c_string, i::StrLength(c_string)));
ager@chromium.org5ec48922009-05-05 07:25:34 +000015091 UC16VectorResource uc16_resource(
ager@chromium.orgc4c92722009-11-18 14:12:51 +000015092 i::Vector<const uint16_t>(two_byte_string,
15093 i::StrLength(c_string)));
ager@chromium.org5ec48922009-05-05 07:25:34 +000015094
15095 Local<String> lhs(v8::Utils::ToLocal(
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000015096 factory->NewExternalStringFromAscii(&ascii_resource)));
ager@chromium.org5ec48922009-05-05 07:25:34 +000015097 Local<String> rhs(v8::Utils::ToLocal(
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000015098 factory->NewExternalStringFromAscii(&ascii_resource)));
ager@chromium.org5ec48922009-05-05 07:25:34 +000015099
15100 env->Global()->Set(v8_str("lhs"), lhs);
15101 env->Global()->Set(v8_str("rhs"), rhs);
15102
15103 CompileRun(
15104 "var cons = lhs + rhs;"
15105 "var slice = lhs.substring(1, lhs.length - 1);"
15106 "var slice_on_cons = (lhs + rhs).substring(1, lhs.length *2 - 1);");
15107
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015108 CHECK(lhs->IsOneByte());
15109 CHECK(rhs->IsOneByte());
rossberg@chromium.org2c067b12012-03-19 11:01:52 +000015110
ager@chromium.org5ec48922009-05-05 07:25:34 +000015111 MorphAString(*v8::Utils::OpenHandle(*lhs), &ascii_resource, &uc16_resource);
15112 MorphAString(*v8::Utils::OpenHandle(*rhs), &ascii_resource, &uc16_resource);
15113
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +000015114 // This should UTF-8 without flattening, since everything is ASCII.
15115 Handle<String> cons = v8_compile("cons")->Run().As<String>();
15116 CHECK_EQ(128, cons->Utf8Length());
15117 int nchars = -1;
15118 CHECK_EQ(129, cons->WriteUtf8(utf_buffer, -1, &nchars));
15119 CHECK_EQ(128, nchars);
15120 CHECK_EQ(0, strcmp(
15121 utf_buffer,
15122 "Now is the time for all good men to come to the aid of the party"
15123 "Now is the time for all good men to come to the aid of the party"));
15124
ager@chromium.org5ec48922009-05-05 07:25:34 +000015125 // Now do some stuff to make sure the strings are flattened, etc.
15126 CompileRun(
15127 "/[^a-z]/.test(cons);"
15128 "/[^a-z]/.test(slice);"
15129 "/[^a-z]/.test(slice_on_cons);");
15130 const char* expected_cons =
15131 "Now is the time for all good men to come to the aid of the party"
15132 "Now is the time for all good men to come to the aid of the party";
15133 const char* expected_slice =
15134 "ow is the time for all good men to come to the aid of the part";
15135 const char* expected_slice_on_cons =
15136 "ow is the time for all good men to come to the aid of the party"
15137 "Now is the time for all good men to come to the aid of the part";
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015138 CHECK_EQ(String::NewFromUtf8(env->GetIsolate(), expected_cons),
ager@chromium.org5ec48922009-05-05 07:25:34 +000015139 env->Global()->Get(v8_str("cons")));
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015140 CHECK_EQ(String::NewFromUtf8(env->GetIsolate(), expected_slice),
ager@chromium.org5ec48922009-05-05 07:25:34 +000015141 env->Global()->Get(v8_str("slice")));
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015142 CHECK_EQ(String::NewFromUtf8(env->GetIsolate(), expected_slice_on_cons),
ager@chromium.org5ec48922009-05-05 07:25:34 +000015143 env->Global()->Get(v8_str("slice_on_cons")));
15144 }
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000015145 i::DeleteArray(two_byte_string);
ager@chromium.org5ec48922009-05-05 07:25:34 +000015146}
15147
15148
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000015149TEST(CompileExternalTwoByteSource) {
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000015150 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015151 v8::HandleScope scope(context->GetIsolate());
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000015152
15153 // This is a very short list of sources, which currently is to check for a
15154 // regression caused by r2703.
15155 const char* ascii_sources[] = {
15156 "0.5",
15157 "-0.5", // This mainly testes PushBack in the Scanner.
15158 "--0.5", // This mainly testes PushBack in the Scanner.
15159 NULL
15160 };
15161
15162 // Compile the sources as external two byte strings.
15163 for (int i = 0; ascii_sources[i] != NULL; i++) {
15164 uint16_t* two_byte_string = AsciiToTwoByteString(ascii_sources[i]);
15165 UC16VectorResource uc16_resource(
ager@chromium.orgc4c92722009-11-18 14:12:51 +000015166 i::Vector<const uint16_t>(two_byte_string,
15167 i::StrLength(ascii_sources[i])));
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000015168 v8::Local<v8::String> source =
15169 v8::String::NewExternal(context->GetIsolate(), &uc16_resource);
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000015170 v8::Script::Compile(source);
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000015171 i::DeleteArray(two_byte_string);
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000015172 }
15173}
15174
15175
mstarzinger@chromium.orgb4968be2013-10-16 09:00:56 +000015176#ifndef V8_INTERPRETED_REGEXP
15177
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +000015178struct RegExpInterruptionData {
15179 int loop_count;
15180 UC16VectorResource* string_resource;
15181 v8::Persistent<v8::String> string;
15182} regexp_interruption_data;
15183
15184
15185class RegExpInterruptionThread : public i::Thread {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015186 public:
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +000015187 explicit RegExpInterruptionThread(v8::Isolate* isolate)
15188 : Thread("TimeoutThread"), isolate_(isolate) {}
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000015189
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +000015190 virtual void Run() {
15191 for (regexp_interruption_data.loop_count = 0;
15192 regexp_interruption_data.loop_count < 7;
15193 regexp_interruption_data.loop_count++) {
15194 i::OS::Sleep(50); // Wait a bit before requesting GC.
15195 reinterpret_cast<i::Isolate*>(isolate_)->stack_guard()->RequestGC();
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015196 }
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +000015197 i::OS::Sleep(50); // Wait a bit before terminating.
15198 v8::V8::TerminateExecution(isolate_);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015199 }
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015200
jkummerow@chromium.orge297f592011-06-08 10:05:15 +000015201 private:
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +000015202 v8::Isolate* isolate_;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015203};
15204
15205
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +000015206void RunBeforeGC(v8::GCType type, v8::GCCallbackFlags flags) {
15207 if (regexp_interruption_data.loop_count != 2) return;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015208 v8::HandleScope scope(CcTest::isolate());
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +000015209 v8::Local<v8::String> string = v8::Local<v8::String>::New(
15210 CcTest::isolate(), regexp_interruption_data.string);
15211 string->MakeExternal(regexp_interruption_data.string_resource);
15212}
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015213
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015214
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +000015215// Test that RegExp execution can be interrupted. Specifically, we test
15216// * interrupting with GC
15217// * turn the subject string from one-byte internal to two-byte external string
15218// * force termination
15219TEST(RegExpInterruption) {
15220 v8::HandleScope scope(CcTest::isolate());
15221 LocalContext env;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015222
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +000015223 RegExpInterruptionThread timeout_thread(CcTest::isolate());
15224
15225 v8::V8::AddGCPrologueCallback(RunBeforeGC);
15226 static const char* ascii_content = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
15227 i::uc16* uc16_content = AsciiToTwoByteString(ascii_content);
15228 v8::Local<v8::String> string = v8_str(ascii_content);
15229
15230 CcTest::global()->Set(v8_str("a"), string);
15231 regexp_interruption_data.string.Reset(CcTest::isolate(), string);
15232 regexp_interruption_data.string_resource = new UC16VectorResource(
15233 i::Vector<const i::uc16>(uc16_content, i::StrLength(ascii_content)));
15234
15235 v8::TryCatch try_catch;
15236 timeout_thread.Start();
15237
15238 CompileRun("/((a*)*)*b/.exec(a)");
15239 CHECK(try_catch.HasTerminated());
15240
15241 timeout_thread.Join();
15242
15243 delete regexp_interruption_data.string_resource;
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015244 regexp_interruption_data.string.Reset();
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015245}
15246
mstarzinger@chromium.orgb4968be2013-10-16 09:00:56 +000015247#endif // V8_INTERPRETED_REGEXP
15248
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015249
mmassi@chromium.org7028c052012-06-13 11:51:58 +000015250// Test that we cannot set a property on the global object if there
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015251// is a read-only property in the prototype chain.
15252TEST(ReadOnlyPropertyInGlobalProto) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +000015253 i::FLAG_es5_readonly = true;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015254 v8::Isolate* isolate = CcTest::isolate();
15255 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000015256 v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015257 LocalContext context(0, templ);
15258 v8::Handle<v8::Object> global = context->Global();
15259 v8::Handle<v8::Object> global_proto =
15260 v8::Handle<v8::Object>::Cast(global->Get(v8_str("__proto__")));
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015261 global_proto->Set(v8_str("x"), v8::Integer::New(isolate, 0), v8::ReadOnly);
15262 global_proto->Set(v8_str("y"), v8::Integer::New(isolate, 0), v8::ReadOnly);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015263 // Check without 'eval' or 'with'.
15264 v8::Handle<v8::Value> res =
15265 CompileRun("function f() { x = 42; return x; }; f()");
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015266 CHECK_EQ(v8::Integer::New(isolate, 0), res);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015267 // Check with 'eval'.
mmassi@chromium.org7028c052012-06-13 11:51:58 +000015268 res = CompileRun("function f() { eval('1'); y = 43; return y; }; f()");
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015269 CHECK_EQ(v8::Integer::New(isolate, 0), res);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015270 // Check with 'with'.
mmassi@chromium.org7028c052012-06-13 11:51:58 +000015271 res = CompileRun("function f() { with (this) { y = 44 }; return y; }; f()");
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015272 CHECK_EQ(v8::Integer::New(isolate, 0), res);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015273}
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015274
15275static int force_set_set_count = 0;
15276static int force_set_get_count = 0;
15277bool pass_on_get = false;
15278
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015279static void ForceSetGetter(v8::Local<v8::String> name,
15280 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015281 force_set_get_count++;
15282 if (pass_on_get) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015283 return;
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015284 }
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015285 info.GetReturnValue().Set(3);
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015286}
15287
15288static void ForceSetSetter(v8::Local<v8::String> name,
15289 v8::Local<v8::Value> value,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015290 const v8::PropertyCallbackInfo<void>& info) {
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015291 force_set_set_count++;
15292}
15293
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015294static void ForceSetInterceptSetter(
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015295 v8::Local<v8::String> name,
15296 v8::Local<v8::Value> value,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015297 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015298 force_set_set_count++;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015299 info.GetReturnValue().SetUndefined();
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015300}
15301
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000015302
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015303TEST(ForceSet) {
15304 force_set_get_count = 0;
15305 force_set_set_count = 0;
15306 pass_on_get = false;
15307
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015308 v8::Isolate* isolate = CcTest::isolate();
15309 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000015310 v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015311 v8::Handle<v8::String> access_property =
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015312 v8::String::NewFromUtf8(isolate, "a");
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015313 templ->SetAccessor(access_property, ForceSetGetter, ForceSetSetter);
15314 LocalContext context(NULL, templ);
15315 v8::Handle<v8::Object> global = context->Global();
15316
15317 // Ordinary properties
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015318 v8::Handle<v8::String> simple_property =
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015319 v8::String::NewFromUtf8(isolate, "p");
15320 global->Set(simple_property, v8::Int32::New(isolate, 4), v8::ReadOnly);
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015321 CHECK_EQ(4, global->Get(simple_property)->Int32Value());
15322 // This should fail because the property is read-only
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015323 global->Set(simple_property, v8::Int32::New(isolate, 5));
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015324 CHECK_EQ(4, global->Get(simple_property)->Int32Value());
15325 // This should succeed even though the property is read-only
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015326 global->ForceSet(simple_property, v8::Int32::New(isolate, 6));
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015327 CHECK_EQ(6, global->Get(simple_property)->Int32Value());
15328
15329 // Accessors
15330 CHECK_EQ(0, force_set_set_count);
15331 CHECK_EQ(0, force_set_get_count);
15332 CHECK_EQ(3, global->Get(access_property)->Int32Value());
15333 // CHECK_EQ the property shouldn't override it, just call the setter
15334 // which in this case does nothing.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015335 global->Set(access_property, v8::Int32::New(isolate, 7));
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015336 CHECK_EQ(3, global->Get(access_property)->Int32Value());
15337 CHECK_EQ(1, force_set_set_count);
15338 CHECK_EQ(2, force_set_get_count);
15339 // Forcing the property to be set should override the accessor without
15340 // calling it
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015341 global->ForceSet(access_property, v8::Int32::New(isolate, 8));
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015342 CHECK_EQ(8, global->Get(access_property)->Int32Value());
15343 CHECK_EQ(1, force_set_set_count);
15344 CHECK_EQ(2, force_set_get_count);
15345}
15346
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000015347
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015348TEST(ForceSetWithInterceptor) {
15349 force_set_get_count = 0;
15350 force_set_set_count = 0;
15351 pass_on_get = false;
15352
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015353 v8::Isolate* isolate = CcTest::isolate();
15354 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000015355 v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015356 templ->SetNamedPropertyHandler(ForceSetGetter, ForceSetInterceptSetter);
15357 LocalContext context(NULL, templ);
15358 v8::Handle<v8::Object> global = context->Global();
15359
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015360 v8::Handle<v8::String> some_property =
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015361 v8::String::NewFromUtf8(isolate, "a");
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015362 CHECK_EQ(0, force_set_set_count);
15363 CHECK_EQ(0, force_set_get_count);
15364 CHECK_EQ(3, global->Get(some_property)->Int32Value());
15365 // Setting the property shouldn't override it, just call the setter
15366 // which in this case does nothing.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015367 global->Set(some_property, v8::Int32::New(isolate, 7));
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015368 CHECK_EQ(3, global->Get(some_property)->Int32Value());
15369 CHECK_EQ(1, force_set_set_count);
15370 CHECK_EQ(2, force_set_get_count);
15371 // Getting the property when the interceptor returns an empty handle
15372 // should yield undefined, since the property isn't present on the
15373 // object itself yet.
15374 pass_on_get = true;
15375 CHECK(global->Get(some_property)->IsUndefined());
15376 CHECK_EQ(1, force_set_set_count);
15377 CHECK_EQ(3, force_set_get_count);
15378 // Forcing the property to be set should cause the value to be
15379 // set locally without calling the interceptor.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015380 global->ForceSet(some_property, v8::Int32::New(isolate, 8));
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015381 CHECK_EQ(8, global->Get(some_property)->Int32Value());
15382 CHECK_EQ(1, force_set_set_count);
15383 CHECK_EQ(4, force_set_get_count);
15384 // Reenabling the interceptor should cause it to take precedence over
15385 // the property
15386 pass_on_get = false;
15387 CHECK_EQ(3, global->Get(some_property)->Int32Value());
15388 CHECK_EQ(1, force_set_set_count);
15389 CHECK_EQ(5, force_set_get_count);
15390 // The interceptor should also work for other properties
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015391 CHECK_EQ(3, global->Get(v8::String::NewFromUtf8(isolate, "b"))
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015392 ->Int32Value());
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015393 CHECK_EQ(1, force_set_set_count);
15394 CHECK_EQ(6, force_set_get_count);
15395}
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000015396
15397
ager@chromium.orge2902be2009-06-08 12:21:35 +000015398THREADED_TEST(ForceDelete) {
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015399 v8::Isolate* isolate = CcTest::isolate();
15400 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000015401 v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
ager@chromium.orge2902be2009-06-08 12:21:35 +000015402 LocalContext context(NULL, templ);
15403 v8::Handle<v8::Object> global = context->Global();
15404
15405 // Ordinary properties
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015406 v8::Handle<v8::String> simple_property =
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015407 v8::String::NewFromUtf8(isolate, "p");
15408 global->Set(simple_property, v8::Int32::New(isolate, 4), v8::DontDelete);
ager@chromium.orge2902be2009-06-08 12:21:35 +000015409 CHECK_EQ(4, global->Get(simple_property)->Int32Value());
15410 // This should fail because the property is dont-delete.
15411 CHECK(!global->Delete(simple_property));
15412 CHECK_EQ(4, global->Get(simple_property)->Int32Value());
15413 // This should succeed even though the property is dont-delete.
15414 CHECK(global->ForceDelete(simple_property));
15415 CHECK(global->Get(simple_property)->IsUndefined());
15416}
15417
15418
15419static int force_delete_interceptor_count = 0;
15420static bool pass_on_delete = false;
15421
15422
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015423static void ForceDeleteDeleter(
ager@chromium.orge2902be2009-06-08 12:21:35 +000015424 v8::Local<v8::String> name,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015425 const v8::PropertyCallbackInfo<v8::Boolean>& info) {
ager@chromium.orge2902be2009-06-08 12:21:35 +000015426 force_delete_interceptor_count++;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015427 if (pass_on_delete) return;
15428 info.GetReturnValue().Set(true);
ager@chromium.orge2902be2009-06-08 12:21:35 +000015429}
15430
15431
15432THREADED_TEST(ForceDeleteWithInterceptor) {
15433 force_delete_interceptor_count = 0;
15434 pass_on_delete = false;
15435
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015436 v8::Isolate* isolate = CcTest::isolate();
15437 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000015438 v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
ager@chromium.orge2902be2009-06-08 12:21:35 +000015439 templ->SetNamedPropertyHandler(0, 0, 0, ForceDeleteDeleter);
15440 LocalContext context(NULL, templ);
15441 v8::Handle<v8::Object> global = context->Global();
15442
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015443 v8::Handle<v8::String> some_property =
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015444 v8::String::NewFromUtf8(isolate, "a");
15445 global->Set(some_property, v8::Integer::New(isolate, 42), v8::DontDelete);
ager@chromium.orge2902be2009-06-08 12:21:35 +000015446
15447 // Deleting a property should get intercepted and nothing should
15448 // happen.
15449 CHECK_EQ(0, force_delete_interceptor_count);
15450 CHECK(global->Delete(some_property));
15451 CHECK_EQ(1, force_delete_interceptor_count);
15452 CHECK_EQ(42, global->Get(some_property)->Int32Value());
15453 // Deleting the property when the interceptor returns an empty
15454 // handle should not delete the property since it is DontDelete.
15455 pass_on_delete = true;
15456 CHECK(!global->Delete(some_property));
15457 CHECK_EQ(2, force_delete_interceptor_count);
15458 CHECK_EQ(42, global->Get(some_property)->Int32Value());
15459 // Forcing the property to be deleted should delete the value
15460 // without calling the interceptor.
15461 CHECK(global->ForceDelete(some_property));
15462 CHECK(global->Get(some_property)->IsUndefined());
15463 CHECK_EQ(2, force_delete_interceptor_count);
15464}
15465
15466
kasperl@chromium.org68ac0092009-07-09 06:00:35 +000015467// Make sure that forcing a delete invalidates any IC stubs, so we
15468// don't read the hole value.
15469THREADED_TEST(ForceDeleteIC) {
kasperl@chromium.org68ac0092009-07-09 06:00:35 +000015470 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015471 v8::HandleScope scope(context->GetIsolate());
kasperl@chromium.org68ac0092009-07-09 06:00:35 +000015472 // Create a DontDelete variable on the global object.
15473 CompileRun("this.__proto__ = { foo: 'horse' };"
15474 "var foo = 'fish';"
15475 "function f() { return foo.length; }");
15476 // Initialize the IC for foo in f.
15477 CompileRun("for (var i = 0; i < 4; i++) f();");
15478 // Make sure the value of foo is correct before the deletion.
15479 CHECK_EQ(4, CompileRun("f()")->Int32Value());
15480 // Force the deletion of foo.
15481 CHECK(context->Global()->ForceDelete(v8_str("foo")));
15482 // Make sure the value for foo is read from the prototype, and that
15483 // we don't get in trouble with reading the deleted cell value
15484 // sentinel.
15485 CHECK_EQ(5, CompileRun("f()")->Int32Value());
15486}
15487
15488
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +000015489TEST(InlinedFunctionAcrossContexts) {
15490 i::FLAG_allow_natives_syntax = true;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015491 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000015492 v8::HandleScope outer_scope(isolate);
15493 v8::Local<v8::Context> ctx1 = v8::Context::New(isolate);
15494 v8::Local<v8::Context> ctx2 = v8::Context::New(isolate);
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +000015495 ctx1->Enter();
15496
15497 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015498 v8::HandleScope inner_scope(CcTest::isolate());
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +000015499 CompileRun("var G = 42; function foo() { return G; }");
15500 v8::Local<v8::Value> foo = ctx1->Global()->Get(v8_str("foo"));
15501 ctx2->Enter();
15502 ctx2->Global()->Set(v8_str("o"), foo);
15503 v8::Local<v8::Value> res = CompileRun(
15504 "function f() { return o(); }"
15505 "for (var i = 0; i < 10; ++i) f();"
15506 "%OptimizeFunctionOnNextCall(f);"
15507 "f();");
15508 CHECK_EQ(42, res->Int32Value());
15509 ctx2->Exit();
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015510 v8::Handle<v8::String> G_property =
15511 v8::String::NewFromUtf8(CcTest::isolate(), "G");
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +000015512 CHECK(ctx1->Global()->ForceDelete(G_property));
15513 ctx2->Enter();
15514 ExpectString(
15515 "(function() {"
15516 " try {"
15517 " return f();"
15518 " } catch(e) {"
15519 " return e.toString();"
15520 " }"
15521 " })()",
15522 "ReferenceError: G is not defined");
15523 ctx2->Exit();
15524 ctx1->Exit();
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +000015525 }
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +000015526}
15527
15528
ulan@chromium.org57ff8812013-05-10 08:16:55 +000015529static v8::Local<Context> calling_context0;
15530static v8::Local<Context> calling_context1;
15531static v8::Local<Context> calling_context2;
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000015532
15533
15534// Check that the call to the callback is initiated in
15535// calling_context2, the directly calling context is calling_context1
15536// and the callback itself is in calling_context0.
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015537static void GetCallingContextCallback(
15538 const v8::FunctionCallbackInfo<v8::Value>& args) {
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000015539 ApiTestFuzzer::Fuzz();
mvstanton@chromium.org40ce96b2013-04-09 09:52:22 +000015540 CHECK(args.GetIsolate()->GetCurrentContext() == calling_context0);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015541 CHECK(args.GetIsolate()->GetCallingContext() == calling_context1);
15542 CHECK(args.GetIsolate()->GetEnteredContext() == calling_context2);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015543 args.GetReturnValue().Set(42);
15544}
15545
15546
15547THREADED_TEST(GetCurrentContextWhenNotInContext) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015548 i::Isolate* isolate = CcTest::i_isolate();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015549 CHECK(isolate != NULL);
15550 CHECK(isolate->context() == NULL);
15551 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
15552 v8::HandleScope scope(v8_isolate);
15553 // The following should not crash, but return an empty handle.
15554 v8::Local<v8::Context> current = v8_isolate->GetCurrentContext();
15555 CHECK(current.IsEmpty());
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000015556}
15557
15558
15559THREADED_TEST(GetCallingContext) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015560 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000015561 v8::HandleScope scope(isolate);
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000015562
ulan@chromium.org57ff8812013-05-10 08:16:55 +000015563 Local<Context> calling_context0(Context::New(isolate));
15564 Local<Context> calling_context1(Context::New(isolate));
15565 Local<Context> calling_context2(Context::New(isolate));
15566 ::calling_context0 = calling_context0;
15567 ::calling_context1 = calling_context1;
15568 ::calling_context2 = calling_context2;
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000015569
15570 // Allow cross-domain access.
15571 Local<String> token = v8_str("<security token>");
15572 calling_context0->SetSecurityToken(token);
15573 calling_context1->SetSecurityToken(token);
15574 calling_context2->SetSecurityToken(token);
15575
15576 // Create an object with a C++ callback in context0.
15577 calling_context0->Enter();
15578 Local<v8::FunctionTemplate> callback_templ =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000015579 v8::FunctionTemplate::New(isolate, GetCallingContextCallback);
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000015580 calling_context0->Global()->Set(v8_str("callback"),
15581 callback_templ->GetFunction());
15582 calling_context0->Exit();
15583
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000015584 // Expose context0 in context1 and set up a function that calls the
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000015585 // callback function.
15586 calling_context1->Enter();
15587 calling_context1->Global()->Set(v8_str("context0"),
15588 calling_context0->Global());
15589 CompileRun("function f() { context0.callback() }");
15590 calling_context1->Exit();
15591
15592 // Expose context1 in context2 and call the callback function in
15593 // context0 indirectly through f in context1.
15594 calling_context2->Enter();
15595 calling_context2->Global()->Set(v8_str("context1"),
15596 calling_context1->Global());
15597 CompileRun("context1.f()");
15598 calling_context2->Exit();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000015599 ::calling_context0.Clear();
15600 ::calling_context1.Clear();
15601 ::calling_context2.Clear();
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000015602}
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000015603
15604
15605// Check that a variable declaration with no explicit initialization
erik.corry@gmail.comed49e962012-04-17 11:57:53 +000015606// value does shadow an existing property in the prototype chain.
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000015607THREADED_TEST(InitGlobalVarInProtoChain) {
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +000015608 i::FLAG_es52_globals = true;
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000015609 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015610 v8::HandleScope scope(context->GetIsolate());
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000015611 // Introduce a variable in the prototype chain.
15612 CompileRun("__proto__.x = 42");
erik.corry@gmail.comed49e962012-04-17 11:57:53 +000015613 v8::Handle<v8::Value> result = CompileRun("var x = 43; x");
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000015614 CHECK(!result->IsUndefined());
erik.corry@gmail.comed49e962012-04-17 11:57:53 +000015615 CHECK_EQ(43, result->Int32Value());
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000015616}
kasperl@chromium.org68ac0092009-07-09 06:00:35 +000015617
15618
15619// Regression test for issue 398.
15620// If a function is added to an object, creating a constant function
15621// field, and the result is cloned, replacing the constant function on the
15622// original should not affect the clone.
15623// See http://code.google.com/p/v8/issues/detail?id=398
15624THREADED_TEST(ReplaceConstantFunction) {
kasperl@chromium.org68ac0092009-07-09 06:00:35 +000015625 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000015626 v8::Isolate* isolate = context->GetIsolate();
15627 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015628 v8::Handle<v8::Object> obj = v8::Object::New(isolate);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000015629 v8::Handle<v8::FunctionTemplate> func_templ =
15630 v8::FunctionTemplate::New(isolate);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015631 v8::Handle<v8::String> foo_string =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000015632 v8::String::NewFromUtf8(isolate, "foo");
kasperl@chromium.org68ac0092009-07-09 06:00:35 +000015633 obj->Set(foo_string, func_templ->GetFunction());
15634 v8::Handle<v8::Object> obj_clone = obj->Clone();
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015635 obj_clone->Set(foo_string,
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000015636 v8::String::NewFromUtf8(isolate, "Hello"));
kasperl@chromium.org68ac0092009-07-09 06:00:35 +000015637 CHECK(!obj->Get(foo_string)->IsUndefined());
15638}
kasperl@chromium.orge959c182009-07-27 08:59:04 +000015639
15640
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015641static void CheckElementValue(i::Isolate* isolate,
15642 int expected,
15643 i::Handle<i::Object> obj,
15644 int offset) {
15645 i::Object* element = obj->GetElement(isolate, offset)->ToObjectChecked();
15646 CHECK_EQ(expected, i::Smi::cast(element)->value());
15647}
15648
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015649
15650THREADED_TEST(PixelArray) {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015651 LocalContext context;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015652 i::Isolate* isolate = CcTest::i_isolate();
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015653 i::Factory* factory = isolate->factory();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015654 v8::HandleScope scope(context->GetIsolate());
ager@chromium.orgc4c92722009-11-18 14:12:51 +000015655 const int kElementCount = 260;
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015656 uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(kElementCount));
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000015657 i::Handle<i::ExternalPixelArray> pixels =
15658 i::Handle<i::ExternalPixelArray>::cast(
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000015659 factory->NewExternalArray(kElementCount,
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000015660 v8::kExternalPixelArray,
15661 pixel_data));
15662 // Force GC to trigger verification.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015663 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015664 for (int i = 0; i < kElementCount; i++) {
ager@chromium.orgc4c92722009-11-18 14:12:51 +000015665 pixels->set(i, i % 256);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015666 }
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000015667 // Force GC to trigger verification.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015668 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015669 for (int i = 0; i < kElementCount; i++) {
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +000015670 CHECK_EQ(i % 256, pixels->get_scalar(i));
ager@chromium.orgc4c92722009-11-18 14:12:51 +000015671 CHECK_EQ(i % 256, pixel_data[i]);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015672 }
15673
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015674 v8::Handle<v8::Object> obj = v8::Object::New(context->GetIsolate());
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015675 i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
15676 // Set the elements to be the pixels.
15677 // jsobj->set_elements(*pixels);
15678 obj->SetIndexedPropertiesToPixelData(pixel_data, kElementCount);
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015679 CheckElementValue(isolate, 1, jsobj, 1);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015680 obj->Set(v8_str("field"), v8::Int32::New(CcTest::isolate(), 1503));
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015681 context->Global()->Set(v8_str("pixels"), obj);
15682 v8::Handle<v8::Value> result = CompileRun("pixels.field");
15683 CHECK_EQ(1503, result->Int32Value());
15684 result = CompileRun("pixels[1]");
15685 CHECK_EQ(1, result->Int32Value());
sgjesse@chromium.org9eceac12009-09-30 07:18:41 +000015686
15687 result = CompileRun("var sum = 0;"
15688 "for (var i = 0; i < 8; i++) {"
15689 " sum += pixels[i] = pixels[i] = -i;"
15690 "}"
15691 "sum;");
15692 CHECK_EQ(-28, result->Int32Value());
15693
15694 result = CompileRun("var sum = 0;"
15695 "for (var i = 0; i < 8; i++) {"
15696 " sum += pixels[i] = pixels[i] = 0;"
15697 "}"
15698 "sum;");
15699 CHECK_EQ(0, result->Int32Value());
15700
15701 result = CompileRun("var sum = 0;"
15702 "for (var i = 0; i < 8; i++) {"
15703 " sum += pixels[i] = pixels[i] = 255;"
15704 "}"
15705 "sum;");
15706 CHECK_EQ(8 * 255, result->Int32Value());
15707
15708 result = CompileRun("var sum = 0;"
15709 "for (var i = 0; i < 8; i++) {"
15710 " sum += pixels[i] = pixels[i] = 256 + i;"
15711 "}"
15712 "sum;");
15713 CHECK_EQ(2076, result->Int32Value());
15714
15715 result = CompileRun("var sum = 0;"
15716 "for (var i = 0; i < 8; i++) {"
15717 " sum += pixels[i] = pixels[i] = i;"
15718 "}"
15719 "sum;");
15720 CHECK_EQ(28, result->Int32Value());
15721
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015722 result = CompileRun("var sum = 0;"
15723 "for (var i = 0; i < 8; i++) {"
15724 " sum += pixels[i];"
15725 "}"
15726 "sum;");
15727 CHECK_EQ(28, result->Int32Value());
15728
ulan@chromium.org09d7ab52013-02-25 15:50:35 +000015729 i::Handle<i::Smi> value(i::Smi::FromInt(2),
15730 reinterpret_cast<i::Isolate*>(context->GetIsolate()));
jkummerow@chromium.org486075a2011-09-07 12:44:28 +000015731 i::Handle<i::Object> no_failure;
yangguo@chromium.orgab30bb82012-02-24 14:41:46 +000015732 no_failure =
15733 i::JSObject::SetElement(jsobj, 1, value, NONE, i::kNonStrictMode);
jkummerow@chromium.org486075a2011-09-07 12:44:28 +000015734 ASSERT(!no_failure.is_null());
15735 i::USE(no_failure);
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015736 CheckElementValue(isolate, 2, jsobj, 1);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015737 *value.location() = i::Smi::FromInt(256);
yangguo@chromium.orgab30bb82012-02-24 14:41:46 +000015738 no_failure =
15739 i::JSObject::SetElement(jsobj, 1, value, NONE, i::kNonStrictMode);
jkummerow@chromium.org486075a2011-09-07 12:44:28 +000015740 ASSERT(!no_failure.is_null());
15741 i::USE(no_failure);
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015742 CheckElementValue(isolate, 255, jsobj, 1);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015743 *value.location() = i::Smi::FromInt(-1);
yangguo@chromium.orgab30bb82012-02-24 14:41:46 +000015744 no_failure =
15745 i::JSObject::SetElement(jsobj, 1, value, NONE, i::kNonStrictMode);
jkummerow@chromium.org486075a2011-09-07 12:44:28 +000015746 ASSERT(!no_failure.is_null());
15747 i::USE(no_failure);
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015748 CheckElementValue(isolate, 0, jsobj, 1);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015749
15750 result = CompileRun("for (var i = 0; i < 8; i++) {"
15751 " pixels[i] = (i * 65) - 109;"
15752 "}"
15753 "pixels[1] + pixels[6];");
15754 CHECK_EQ(255, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015755 CheckElementValue(isolate, 0, jsobj, 0);
15756 CheckElementValue(isolate, 0, jsobj, 1);
15757 CheckElementValue(isolate, 21, jsobj, 2);
15758 CheckElementValue(isolate, 86, jsobj, 3);
15759 CheckElementValue(isolate, 151, jsobj, 4);
15760 CheckElementValue(isolate, 216, jsobj, 5);
15761 CheckElementValue(isolate, 255, jsobj, 6);
15762 CheckElementValue(isolate, 255, jsobj, 7);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015763 result = CompileRun("var sum = 0;"
15764 "for (var i = 0; i < 8; i++) {"
15765 " sum += pixels[i];"
15766 "}"
15767 "sum;");
15768 CHECK_EQ(984, result->Int32Value());
15769
15770 result = CompileRun("for (var i = 0; i < 8; i++) {"
15771 " pixels[i] = (i * 1.1);"
15772 "}"
15773 "pixels[1] + pixels[6];");
15774 CHECK_EQ(8, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015775 CheckElementValue(isolate, 0, jsobj, 0);
15776 CheckElementValue(isolate, 1, jsobj, 1);
15777 CheckElementValue(isolate, 2, jsobj, 2);
15778 CheckElementValue(isolate, 3, jsobj, 3);
15779 CheckElementValue(isolate, 4, jsobj, 4);
15780 CheckElementValue(isolate, 6, jsobj, 5);
15781 CheckElementValue(isolate, 7, jsobj, 6);
15782 CheckElementValue(isolate, 8, jsobj, 7);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015783
15784 result = CompileRun("for (var i = 0; i < 8; i++) {"
15785 " pixels[7] = undefined;"
15786 "}"
15787 "pixels[7];");
15788 CHECK_EQ(0, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015789 CheckElementValue(isolate, 0, jsobj, 7);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015790
15791 result = CompileRun("for (var i = 0; i < 8; i++) {"
15792 " pixels[6] = '2.3';"
15793 "}"
15794 "pixels[6];");
15795 CHECK_EQ(2, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015796 CheckElementValue(isolate, 2, jsobj, 6);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015797
15798 result = CompileRun("for (var i = 0; i < 8; i++) {"
15799 " pixels[5] = NaN;"
15800 "}"
15801 "pixels[5];");
15802 CHECK_EQ(0, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015803 CheckElementValue(isolate, 0, jsobj, 5);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015804
15805 result = CompileRun("for (var i = 0; i < 8; i++) {"
15806 " pixels[8] = Infinity;"
15807 "}"
15808 "pixels[8];");
15809 CHECK_EQ(255, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015810 CheckElementValue(isolate, 255, jsobj, 8);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015811
15812 result = CompileRun("for (var i = 0; i < 8; i++) {"
15813 " pixels[9] = -Infinity;"
15814 "}"
15815 "pixels[9];");
15816 CHECK_EQ(0, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015817 CheckElementValue(isolate, 0, jsobj, 9);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015818
15819 result = CompileRun("pixels[3] = 33;"
15820 "delete pixels[3];"
15821 "pixels[3];");
15822 CHECK_EQ(33, result->Int32Value());
15823
15824 result = CompileRun("pixels[0] = 10; pixels[1] = 11;"
15825 "pixels[2] = 12; pixels[3] = 13;"
15826 "pixels.__defineGetter__('2',"
15827 "function() { return 120; });"
15828 "pixels[2];");
15829 CHECK_EQ(12, result->Int32Value());
15830
15831 result = CompileRun("var js_array = new Array(40);"
15832 "js_array[0] = 77;"
15833 "js_array;");
15834 CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
15835
15836 result = CompileRun("pixels[1] = 23;"
15837 "pixels.__proto__ = [];"
15838 "js_array.__proto__ = pixels;"
15839 "js_array.concat(pixels);");
15840 CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
15841 CHECK_EQ(23, v8::Object::Cast(*result)->Get(v8_str("1"))->Int32Value());
15842
sgjesse@chromium.org9eceac12009-09-30 07:18:41 +000015843 result = CompileRun("pixels[1] = 23;");
15844 CHECK_EQ(23, result->Int32Value());
15845
ager@chromium.orgc4c92722009-11-18 14:12:51 +000015846 // Test for index greater than 255. Regression test for:
15847 // http://code.google.com/p/chromium/issues/detail?id=26337.
15848 result = CompileRun("pixels[256] = 255;");
15849 CHECK_EQ(255, result->Int32Value());
15850 result = CompileRun("var i = 0;"
15851 "for (var j = 0; j < 8; j++) { i = pixels[256]; }"
15852 "i");
15853 CHECK_EQ(255, result->Int32Value());
15854
ricow@chromium.org83aa5492011-02-07 12:42:56 +000015855 // Make sure that pixel array ICs recognize when a non-pixel array
15856 // is passed to it.
15857 result = CompileRun("function pa_load(p) {"
15858 " var sum = 0;"
15859 " for (var j = 0; j < 256; j++) { sum += p[j]; }"
15860 " return sum;"
15861 "}"
15862 "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
15863 "for (var i = 0; i < 10; ++i) { pa_load(pixels); }"
15864 "just_ints = new Object();"
15865 "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
15866 "for (var i = 0; i < 10; ++i) {"
15867 " result = pa_load(just_ints);"
15868 "}"
15869 "result");
15870 CHECK_EQ(32640, result->Int32Value());
15871
15872 // Make sure that pixel array ICs recognize out-of-bound accesses.
15873 result = CompileRun("function pa_load(p, start) {"
15874 " var sum = 0;"
15875 " for (var j = start; j < 256; j++) { sum += p[j]; }"
15876 " return sum;"
15877 "}"
15878 "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
15879 "for (var i = 0; i < 10; ++i) { pa_load(pixels,0); }"
15880 "for (var i = 0; i < 10; ++i) {"
15881 " result = pa_load(pixels,-10);"
15882 "}"
15883 "result");
15884 CHECK_EQ(0, result->Int32Value());
15885
15886 // Make sure that generic ICs properly handles a pixel array.
15887 result = CompileRun("function pa_load(p) {"
15888 " var sum = 0;"
15889 " for (var j = 0; j < 256; j++) { sum += p[j]; }"
15890 " return sum;"
15891 "}"
15892 "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
15893 "just_ints = new Object();"
15894 "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
15895 "for (var i = 0; i < 10; ++i) { pa_load(just_ints); }"
15896 "for (var i = 0; i < 10; ++i) {"
15897 " result = pa_load(pixels);"
15898 "}"
15899 "result");
15900 CHECK_EQ(32640, result->Int32Value());
15901
15902 // Make sure that generic load ICs recognize out-of-bound accesses in
15903 // pixel arrays.
15904 result = CompileRun("function pa_load(p, start) {"
15905 " var sum = 0;"
15906 " for (var j = start; j < 256; j++) { sum += p[j]; }"
15907 " return sum;"
15908 "}"
15909 "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
15910 "just_ints = new Object();"
15911 "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
15912 "for (var i = 0; i < 10; ++i) { pa_load(just_ints,0); }"
15913 "for (var i = 0; i < 10; ++i) { pa_load(pixels,0); }"
15914 "for (var i = 0; i < 10; ++i) {"
15915 " result = pa_load(pixels,-10);"
15916 "}"
15917 "result");
15918 CHECK_EQ(0, result->Int32Value());
15919
15920 // Make sure that generic ICs properly handles other types than pixel
15921 // arrays (that the inlined fast pixel array test leaves the right information
15922 // in the right registers).
15923 result = CompileRun("function pa_load(p) {"
15924 " var sum = 0;"
15925 " for (var j = 0; j < 256; j++) { sum += p[j]; }"
15926 " return sum;"
15927 "}"
15928 "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
15929 "just_ints = new Object();"
15930 "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
15931 "for (var i = 0; i < 10; ++i) { pa_load(just_ints); }"
15932 "for (var i = 0; i < 10; ++i) { pa_load(pixels); }"
15933 "sparse_array = new Object();"
15934 "for (var i = 0; i < 256; ++i) { sparse_array[i] = i; }"
15935 "sparse_array[1000000] = 3;"
15936 "for (var i = 0; i < 10; ++i) {"
15937 " result = pa_load(sparse_array);"
15938 "}"
15939 "result");
15940 CHECK_EQ(32640, result->Int32Value());
15941
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +000015942 // Make sure that pixel array store ICs clamp values correctly.
15943 result = CompileRun("function pa_store(p) {"
15944 " for (var j = 0; j < 256; j++) { p[j] = j * 2; }"
15945 "}"
15946 "pa_store(pixels);"
15947 "var sum = 0;"
15948 "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
15949 "sum");
15950 CHECK_EQ(48896, result->Int32Value());
15951
15952 // Make sure that pixel array stores correctly handle accesses outside
15953 // of the pixel array..
15954 result = CompileRun("function pa_store(p,start) {"
15955 " for (var j = 0; j < 256; j++) {"
15956 " p[j+start] = j * 2;"
15957 " }"
15958 "}"
15959 "pa_store(pixels,0);"
15960 "pa_store(pixels,-128);"
15961 "var sum = 0;"
15962 "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
15963 "sum");
15964 CHECK_EQ(65280, result->Int32Value());
15965
15966 // Make sure that the generic store stub correctly handle accesses outside
15967 // of the pixel array..
15968 result = CompileRun("function pa_store(p,start) {"
15969 " for (var j = 0; j < 256; j++) {"
15970 " p[j+start] = j * 2;"
15971 " }"
15972 "}"
15973 "pa_store(pixels,0);"
15974 "just_ints = new Object();"
15975 "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
15976 "pa_store(just_ints, 0);"
15977 "pa_store(pixels,-128);"
15978 "var sum = 0;"
15979 "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
15980 "sum");
15981 CHECK_EQ(65280, result->Int32Value());
15982
15983 // Make sure that the generic keyed store stub clamps pixel array values
15984 // correctly.
15985 result = CompileRun("function pa_store(p) {"
15986 " for (var j = 0; j < 256; j++) { p[j] = j * 2; }"
15987 "}"
15988 "pa_store(pixels);"
15989 "just_ints = new Object();"
15990 "pa_store(just_ints);"
15991 "pa_store(pixels);"
15992 "var sum = 0;"
15993 "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
15994 "sum");
15995 CHECK_EQ(48896, result->Int32Value());
15996
15997 // Make sure that pixel array loads are optimized by crankshaft.
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000015998 result = CompileRun("function pa_load(p) {"
15999 " var sum = 0;"
16000 " for (var i=0; i<256; ++i) {"
16001 " sum += p[i];"
16002 " }"
16003 " return sum; "
16004 "}"
16005 "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000016006 "for (var i = 0; i < 5000; ++i) {"
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000016007 " result = pa_load(pixels);"
16008 "}"
16009 "result");
16010 CHECK_EQ(32640, result->Int32Value());
16011
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000016012 // Make sure that pixel array stores are optimized by crankshaft.
16013 result = CompileRun("function pa_init(p) {"
16014 "for (var i = 0; i < 256; ++i) { p[i] = i; }"
16015 "}"
16016 "function pa_load(p) {"
16017 " var sum = 0;"
16018 " for (var i=0; i<256; ++i) {"
16019 " sum += p[i];"
16020 " }"
16021 " return sum; "
16022 "}"
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000016023 "for (var i = 0; i < 5000; ++i) {"
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000016024 " pa_init(pixels);"
16025 "}"
16026 "result = pa_load(pixels);"
16027 "result");
16028 CHECK_EQ(32640, result->Int32Value());
16029
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000016030 free(pixel_data);
16031}
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000016032
ager@chromium.org96c75b52009-08-26 09:13:16 +000016033
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016034THREADED_TEST(PixelArrayInfo) {
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016035 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016036 v8::HandleScope scope(context->GetIsolate());
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016037 for (int size = 0; size < 100; size += 10) {
16038 uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(size));
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016039 v8::Handle<v8::Object> obj = v8::Object::New(context->GetIsolate());
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016040 obj->SetIndexedPropertiesToPixelData(pixel_data, size);
16041 CHECK(obj->HasIndexedPropertiesInPixelData());
16042 CHECK_EQ(pixel_data, obj->GetIndexedPropertiesPixelData());
16043 CHECK_EQ(size, obj->GetIndexedPropertiesPixelDataLength());
16044 free(pixel_data);
16045 }
16046}
16047
16048
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000016049static void NotHandledIndexedPropertyGetter(
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000016050 uint32_t index,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000016051 const v8::PropertyCallbackInfo<v8::Value>& info) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000016052 ApiTestFuzzer::Fuzz();
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000016053}
16054
16055
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000016056static void NotHandledIndexedPropertySetter(
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000016057 uint32_t index,
16058 Local<Value> value,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000016059 const v8::PropertyCallbackInfo<v8::Value>& info) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000016060 ApiTestFuzzer::Fuzz();
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000016061}
16062
16063
16064THREADED_TEST(PixelArrayWithInterceptor) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000016065 LocalContext context;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000016066 i::Factory* factory = CcTest::i_isolate()->factory();
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000016067 v8::Isolate* isolate = context->GetIsolate();
16068 v8::HandleScope scope(isolate);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000016069 const int kElementCount = 260;
16070 uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(kElementCount));
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000016071 i::Handle<i::ExternalPixelArray> pixels =
16072 i::Handle<i::ExternalPixelArray>::cast(
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000016073 factory->NewExternalArray(kElementCount,
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000016074 v8::kExternalPixelArray,
16075 pixel_data));
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000016076 for (int i = 0; i < kElementCount; i++) {
16077 pixels->set(i, i % 256);
16078 }
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000016079 v8::Handle<v8::ObjectTemplate> templ =
16080 v8::ObjectTemplate::New(context->GetIsolate());
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000016081 templ->SetIndexedPropertyHandler(NotHandledIndexedPropertyGetter,
16082 NotHandledIndexedPropertySetter);
16083 v8::Handle<v8::Object> obj = templ->NewInstance();
16084 obj->SetIndexedPropertiesToPixelData(pixel_data, kElementCount);
16085 context->Global()->Set(v8_str("pixels"), obj);
16086 v8::Handle<v8::Value> result = CompileRun("pixels[1]");
16087 CHECK_EQ(1, result->Int32Value());
16088 result = CompileRun("var sum = 0;"
16089 "for (var i = 0; i < 8; i++) {"
16090 " sum += pixels[i] = pixels[i] = -i;"
16091 "}"
16092 "sum;");
16093 CHECK_EQ(-28, result->Int32Value());
16094 result = CompileRun("pixels.hasOwnProperty('1')");
16095 CHECK(result->BooleanValue());
16096 free(pixel_data);
16097}
16098
16099
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016100static int ExternalArrayElementSize(v8::ExternalArrayType array_type) {
16101 switch (array_type) {
16102 case v8::kExternalByteArray:
16103 case v8::kExternalUnsignedByteArray:
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000016104 case v8::kExternalPixelArray:
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016105 return 1;
16106 break;
16107 case v8::kExternalShortArray:
16108 case v8::kExternalUnsignedShortArray:
16109 return 2;
16110 break;
16111 case v8::kExternalIntArray:
16112 case v8::kExternalUnsignedIntArray:
16113 case v8::kExternalFloatArray:
16114 return 4;
16115 break;
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +000016116 case v8::kExternalDoubleArray:
16117 return 8;
16118 break;
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016119 default:
16120 UNREACHABLE();
16121 return -1;
16122 }
16123 UNREACHABLE();
16124 return -1;
16125}
16126
16127
ager@chromium.org3811b432009-10-28 14:53:37 +000016128template <class ExternalArrayClass, class ElementType>
danno@chromium.orgf005df62013-04-30 16:36:45 +000016129static void ObjectWithExternalArrayTestHelper(
16130 Handle<Context> context,
16131 v8::Handle<Object> obj,
16132 int element_count,
16133 v8::ExternalArrayType array_type,
16134 int64_t low, int64_t high) {
ager@chromium.org3811b432009-10-28 14:53:37 +000016135 i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000016136 i::Isolate* isolate = jsobj->GetIsolate();
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016137 obj->Set(v8_str("field"),
16138 v8::Int32::New(reinterpret_cast<v8::Isolate*>(isolate), 1503));
ager@chromium.org3811b432009-10-28 14:53:37 +000016139 context->Global()->Set(v8_str("ext_array"), obj);
16140 v8::Handle<v8::Value> result = CompileRun("ext_array.field");
16141 CHECK_EQ(1503, result->Int32Value());
16142 result = CompileRun("ext_array[1]");
16143 CHECK_EQ(1, result->Int32Value());
16144
16145 // Check pass through of assigned smis
16146 result = CompileRun("var sum = 0;"
16147 "for (var i = 0; i < 8; i++) {"
16148 " sum += ext_array[i] = ext_array[i] = -i;"
16149 "}"
16150 "sum;");
16151 CHECK_EQ(-28, result->Int32Value());
16152
16153 // Check assigned smis
16154 result = CompileRun("for (var i = 0; i < 8; i++) {"
16155 " ext_array[i] = i;"
16156 "}"
16157 "var sum = 0;"
16158 "for (var i = 0; i < 8; i++) {"
16159 " sum += ext_array[i];"
16160 "}"
16161 "sum;");
16162 CHECK_EQ(28, result->Int32Value());
16163
16164 // Check assigned smis in reverse order
16165 result = CompileRun("for (var i = 8; --i >= 0; ) {"
16166 " ext_array[i] = i;"
16167 "}"
16168 "var sum = 0;"
16169 "for (var i = 0; i < 8; i++) {"
16170 " sum += ext_array[i];"
16171 "}"
16172 "sum;");
16173 CHECK_EQ(28, result->Int32Value());
16174
16175 // Check pass through of assigned HeapNumbers
16176 result = CompileRun("var sum = 0;"
16177 "for (var i = 0; i < 16; i+=2) {"
16178 " sum += ext_array[i] = ext_array[i] = (-i * 0.5);"
16179 "}"
16180 "sum;");
16181 CHECK_EQ(-28, result->Int32Value());
16182
16183 // Check assigned HeapNumbers
16184 result = CompileRun("for (var i = 0; i < 16; i+=2) {"
16185 " ext_array[i] = (i * 0.5);"
16186 "}"
16187 "var sum = 0;"
16188 "for (var i = 0; i < 16; i+=2) {"
16189 " sum += ext_array[i];"
16190 "}"
16191 "sum;");
16192 CHECK_EQ(28, result->Int32Value());
16193
16194 // Check assigned HeapNumbers in reverse order
16195 result = CompileRun("for (var i = 14; i >= 0; i-=2) {"
16196 " ext_array[i] = (i * 0.5);"
16197 "}"
16198 "var sum = 0;"
16199 "for (var i = 0; i < 16; i+=2) {"
16200 " sum += ext_array[i];"
16201 "}"
16202 "sum;");
16203 CHECK_EQ(28, result->Int32Value());
16204
16205 i::ScopedVector<char> test_buf(1024);
16206
16207 // Check legal boundary conditions.
16208 // The repeated loads and stores ensure the ICs are exercised.
16209 const char* boundary_program =
16210 "var res = 0;"
16211 "for (var i = 0; i < 16; i++) {"
16212 " ext_array[i] = %lld;"
16213 " if (i > 8) {"
16214 " res = ext_array[i];"
16215 " }"
16216 "}"
16217 "res;";
16218 i::OS::SNPrintF(test_buf,
16219 boundary_program,
16220 low);
16221 result = CompileRun(test_buf.start());
16222 CHECK_EQ(low, result->IntegerValue());
16223
16224 i::OS::SNPrintF(test_buf,
16225 boundary_program,
16226 high);
16227 result = CompileRun(test_buf.start());
16228 CHECK_EQ(high, result->IntegerValue());
16229
16230 // Check misprediction of type in IC.
16231 result = CompileRun("var tmp_array = ext_array;"
16232 "var sum = 0;"
16233 "for (var i = 0; i < 8; i++) {"
16234 " tmp_array[i] = i;"
16235 " sum += tmp_array[i];"
16236 " if (i == 4) {"
16237 " tmp_array = {};"
16238 " }"
16239 "}"
16240 "sum;");
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000016241 // Force GC to trigger verification.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000016242 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org3811b432009-10-28 14:53:37 +000016243 CHECK_EQ(28, result->Int32Value());
16244
16245 // Make sure out-of-range loads do not throw.
16246 i::OS::SNPrintF(test_buf,
16247 "var caught_exception = false;"
16248 "try {"
16249 " ext_array[%d];"
16250 "} catch (e) {"
16251 " caught_exception = true;"
16252 "}"
16253 "caught_exception;",
danno@chromium.orgf005df62013-04-30 16:36:45 +000016254 element_count);
ager@chromium.org3811b432009-10-28 14:53:37 +000016255 result = CompileRun(test_buf.start());
16256 CHECK_EQ(false, result->BooleanValue());
16257
16258 // Make sure out-of-range stores do not throw.
16259 i::OS::SNPrintF(test_buf,
16260 "var caught_exception = false;"
16261 "try {"
16262 " ext_array[%d] = 1;"
16263 "} catch (e) {"
16264 " caught_exception = true;"
16265 "}"
16266 "caught_exception;",
danno@chromium.orgf005df62013-04-30 16:36:45 +000016267 element_count);
ager@chromium.org3811b432009-10-28 14:53:37 +000016268 result = CompileRun(test_buf.start());
16269 CHECK_EQ(false, result->BooleanValue());
16270
16271 // Check other boundary conditions, values and operations.
16272 result = CompileRun("for (var i = 0; i < 8; i++) {"
16273 " ext_array[7] = undefined;"
16274 "}"
16275 "ext_array[7];");
16276 CHECK_EQ(0, result->Int32Value());
yangguo@chromium.org56454712012-02-16 15:33:53 +000016277 if (array_type == v8::kExternalDoubleArray ||
16278 array_type == v8::kExternalFloatArray) {
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000016279 CHECK_EQ(static_cast<int>(i::OS::nan_value()),
16280 static_cast<int>(
16281 jsobj->GetElement(isolate, 7)->ToObjectChecked()->Number()));
yangguo@chromium.org56454712012-02-16 15:33:53 +000016282 } else {
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000016283 CheckElementValue(isolate, 0, jsobj, 7);
yangguo@chromium.org56454712012-02-16 15:33:53 +000016284 }
ager@chromium.org3811b432009-10-28 14:53:37 +000016285
16286 result = CompileRun("for (var i = 0; i < 8; i++) {"
16287 " ext_array[6] = '2.3';"
16288 "}"
16289 "ext_array[6];");
16290 CHECK_EQ(2, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000016291 CHECK_EQ(2,
16292 static_cast<int>(
16293 jsobj->GetElement(isolate, 6)->ToObjectChecked()->Number()));
ager@chromium.org3811b432009-10-28 14:53:37 +000016294
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +000016295 if (array_type != v8::kExternalFloatArray &&
16296 array_type != v8::kExternalDoubleArray) {
ager@chromium.org3811b432009-10-28 14:53:37 +000016297 // Though the specification doesn't state it, be explicit about
16298 // converting NaNs and +/-Infinity to zero.
16299 result = CompileRun("for (var i = 0; i < 8; i++) {"
16300 " ext_array[i] = 5;"
16301 "}"
16302 "for (var i = 0; i < 8; i++) {"
16303 " ext_array[i] = NaN;"
16304 "}"
16305 "ext_array[5];");
16306 CHECK_EQ(0, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000016307 CheckElementValue(isolate, 0, jsobj, 5);
ager@chromium.org3811b432009-10-28 14:53:37 +000016308
16309 result = CompileRun("for (var i = 0; i < 8; i++) {"
16310 " ext_array[i] = 5;"
16311 "}"
16312 "for (var i = 0; i < 8; i++) {"
16313 " ext_array[i] = Infinity;"
16314 "}"
16315 "ext_array[5];");
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000016316 int expected_value =
16317 (array_type == v8::kExternalPixelArray) ? 255 : 0;
16318 CHECK_EQ(expected_value, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000016319 CheckElementValue(isolate, expected_value, jsobj, 5);
ager@chromium.org3811b432009-10-28 14:53:37 +000016320
16321 result = CompileRun("for (var i = 0; i < 8; i++) {"
16322 " ext_array[i] = 5;"
16323 "}"
16324 "for (var i = 0; i < 8; i++) {"
16325 " ext_array[i] = -Infinity;"
16326 "}"
16327 "ext_array[5];");
16328 CHECK_EQ(0, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000016329 CheckElementValue(isolate, 0, jsobj, 5);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +000016330
16331 // Check truncation behavior of integral arrays.
16332 const char* unsigned_data =
16333 "var source_data = [0.6, 10.6];"
16334 "var expected_results = [0, 10];";
16335 const char* signed_data =
16336 "var source_data = [0.6, 10.6, -0.6, -10.6];"
16337 "var expected_results = [0, 10, 0, -10];";
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000016338 const char* pixel_data =
16339 "var source_data = [0.6, 10.6];"
16340 "var expected_results = [1, 11];";
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +000016341 bool is_unsigned =
16342 (array_type == v8::kExternalUnsignedByteArray ||
16343 array_type == v8::kExternalUnsignedShortArray ||
16344 array_type == v8::kExternalUnsignedIntArray);
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000016345 bool is_pixel_data = array_type == v8::kExternalPixelArray;
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +000016346
16347 i::OS::SNPrintF(test_buf,
16348 "%s"
16349 "var all_passed = true;"
16350 "for (var i = 0; i < source_data.length; i++) {"
16351 " for (var j = 0; j < 8; j++) {"
16352 " ext_array[j] = source_data[i];"
16353 " }"
16354 " all_passed = all_passed &&"
16355 " (ext_array[5] == expected_results[i]);"
16356 "}"
16357 "all_passed;",
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000016358 (is_unsigned ?
16359 unsigned_data :
16360 (is_pixel_data ? pixel_data : signed_data)));
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +000016361 result = CompileRun(test_buf.start());
16362 CHECK_EQ(true, result->BooleanValue());
ager@chromium.org3811b432009-10-28 14:53:37 +000016363 }
16364
danno@chromium.orgf005df62013-04-30 16:36:45 +000016365 i::Handle<ExternalArrayClass> array(
16366 ExternalArrayClass::cast(jsobj->elements()));
16367 for (int i = 0; i < element_count; i++) {
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000016368 array->set(i, static_cast<ElementType>(i));
16369 }
danno@chromium.orgf005df62013-04-30 16:36:45 +000016370
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000016371 // Test complex assignments
16372 result = CompileRun("function ee_op_test_complex_func(sum) {"
16373 " for (var i = 0; i < 40; ++i) {"
16374 " sum += (ext_array[i] += 1);"
16375 " sum += (ext_array[i] -= 1);"
16376 " } "
16377 " return sum;"
16378 "}"
16379 "sum=0;"
16380 "for (var i=0;i<10000;++i) {"
16381 " sum=ee_op_test_complex_func(sum);"
16382 "}"
16383 "sum;");
16384 CHECK_EQ(16000000, result->Int32Value());
16385
16386 // Test count operations
16387 result = CompileRun("function ee_op_test_count_func(sum) {"
16388 " for (var i = 0; i < 40; ++i) {"
16389 " sum += (++ext_array[i]);"
16390 " sum += (--ext_array[i]);"
16391 " } "
16392 " return sum;"
16393 "}"
16394 "sum=0;"
16395 "for (var i=0;i<10000;++i) {"
16396 " sum=ee_op_test_count_func(sum);"
16397 "}"
16398 "sum;");
16399 CHECK_EQ(16000000, result->Int32Value());
16400
ager@chromium.org3811b432009-10-28 14:53:37 +000016401 result = CompileRun("ext_array[3] = 33;"
16402 "delete ext_array[3];"
16403 "ext_array[3];");
16404 CHECK_EQ(33, result->Int32Value());
16405
16406 result = CompileRun("ext_array[0] = 10; ext_array[1] = 11;"
16407 "ext_array[2] = 12; ext_array[3] = 13;"
16408 "ext_array.__defineGetter__('2',"
16409 "function() { return 120; });"
16410 "ext_array[2];");
16411 CHECK_EQ(12, result->Int32Value());
16412
16413 result = CompileRun("var js_array = new Array(40);"
16414 "js_array[0] = 77;"
16415 "js_array;");
16416 CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
16417
16418 result = CompileRun("ext_array[1] = 23;"
16419 "ext_array.__proto__ = [];"
16420 "js_array.__proto__ = ext_array;"
16421 "js_array.concat(ext_array);");
16422 CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
16423 CHECK_EQ(23, v8::Object::Cast(*result)->Get(v8_str("1"))->Int32Value());
16424
16425 result = CompileRun("ext_array[1] = 23;");
16426 CHECK_EQ(23, result->Int32Value());
danno@chromium.orgf005df62013-04-30 16:36:45 +000016427}
16428
16429
16430template <class ExternalArrayClass, class ElementType>
16431static void ExternalArrayTestHelper(v8::ExternalArrayType array_type,
16432 int64_t low,
16433 int64_t high) {
16434 LocalContext context;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000016435 i::Isolate* isolate = CcTest::i_isolate();
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000016436 i::Factory* factory = isolate->factory();
danno@chromium.orgf005df62013-04-30 16:36:45 +000016437 v8::HandleScope scope(context->GetIsolate());
16438 const int kElementCount = 40;
16439 int element_size = ExternalArrayElementSize(array_type);
16440 ElementType* array_data =
16441 static_cast<ElementType*>(malloc(kElementCount * element_size));
16442 i::Handle<ExternalArrayClass> array =
16443 i::Handle<ExternalArrayClass>::cast(
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000016444 factory->NewExternalArray(kElementCount, array_type, array_data));
danno@chromium.orgf005df62013-04-30 16:36:45 +000016445 // Force GC to trigger verification.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000016446 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
danno@chromium.orgf005df62013-04-30 16:36:45 +000016447 for (int i = 0; i < kElementCount; i++) {
16448 array->set(i, static_cast<ElementType>(i));
16449 }
16450 // Force GC to trigger verification.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000016451 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
danno@chromium.orgf005df62013-04-30 16:36:45 +000016452 for (int i = 0; i < kElementCount; i++) {
16453 CHECK_EQ(static_cast<int64_t>(i),
16454 static_cast<int64_t>(array->get_scalar(i)));
16455 CHECK_EQ(static_cast<int64_t>(i), static_cast<int64_t>(array_data[i]));
16456 }
16457
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016458 v8::Handle<v8::Object> obj = v8::Object::New(context->GetIsolate());
danno@chromium.orgf005df62013-04-30 16:36:45 +000016459 i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
16460 // Set the elements to be the external array.
16461 obj->SetIndexedPropertiesToExternalArrayData(array_data,
16462 array_type,
16463 kElementCount);
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000016464 CHECK_EQ(1,
16465 static_cast<int>(
16466 jsobj->GetElement(isolate, 1)->ToObjectChecked()->Number()));
danno@chromium.orgf005df62013-04-30 16:36:45 +000016467
16468 ObjectWithExternalArrayTestHelper<ExternalArrayClass, ElementType>(
16469 context.local(), obj, kElementCount, array_type, low, high);
16470
16471 v8::Handle<v8::Value> result;
ager@chromium.org3811b432009-10-28 14:53:37 +000016472
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +000016473 // Test more complex manipulations which cause eax to contain values
16474 // that won't be completely overwritten by loads from the arrays.
16475 // This catches bugs in the instructions used for the KeyedLoadIC
16476 // for byte and word types.
16477 {
16478 const int kXSize = 300;
16479 const int kYSize = 300;
16480 const int kLargeElementCount = kXSize * kYSize * 4;
16481 ElementType* large_array_data =
16482 static_cast<ElementType*>(malloc(kLargeElementCount * element_size));
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016483 v8::Handle<v8::Object> large_obj = v8::Object::New(context->GetIsolate());
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +000016484 // Set the elements to be the external array.
16485 large_obj->SetIndexedPropertiesToExternalArrayData(large_array_data,
16486 array_type,
16487 kLargeElementCount);
16488 context->Global()->Set(v8_str("large_array"), large_obj);
16489 // Initialize contents of a few rows.
16490 for (int x = 0; x < 300; x++) {
16491 int row = 0;
16492 int offset = row * 300 * 4;
16493 large_array_data[offset + 4 * x + 0] = (ElementType) 127;
16494 large_array_data[offset + 4 * x + 1] = (ElementType) 0;
16495 large_array_data[offset + 4 * x + 2] = (ElementType) 0;
16496 large_array_data[offset + 4 * x + 3] = (ElementType) 127;
16497 row = 150;
16498 offset = row * 300 * 4;
16499 large_array_data[offset + 4 * x + 0] = (ElementType) 127;
16500 large_array_data[offset + 4 * x + 1] = (ElementType) 0;
16501 large_array_data[offset + 4 * x + 2] = (ElementType) 0;
16502 large_array_data[offset + 4 * x + 3] = (ElementType) 127;
16503 row = 298;
16504 offset = row * 300 * 4;
16505 large_array_data[offset + 4 * x + 0] = (ElementType) 127;
16506 large_array_data[offset + 4 * x + 1] = (ElementType) 0;
16507 large_array_data[offset + 4 * x + 2] = (ElementType) 0;
16508 large_array_data[offset + 4 * x + 3] = (ElementType) 127;
16509 }
16510 // The goal of the code below is to make "offset" large enough
16511 // that the computation of the index (which goes into eax) has
16512 // high bits set which will not be overwritten by a byte or short
16513 // load.
16514 result = CompileRun("var failed = false;"
16515 "var offset = 0;"
16516 "for (var i = 0; i < 300; i++) {"
16517 " if (large_array[4 * i] != 127 ||"
16518 " large_array[4 * i + 1] != 0 ||"
16519 " large_array[4 * i + 2] != 0 ||"
16520 " large_array[4 * i + 3] != 127) {"
16521 " failed = true;"
16522 " }"
16523 "}"
16524 "offset = 150 * 300 * 4;"
16525 "for (var i = 0; i < 300; i++) {"
16526 " if (large_array[offset + 4 * i] != 127 ||"
16527 " large_array[offset + 4 * i + 1] != 0 ||"
16528 " large_array[offset + 4 * i + 2] != 0 ||"
16529 " large_array[offset + 4 * i + 3] != 127) {"
16530 " failed = true;"
16531 " }"
16532 "}"
16533 "offset = 298 * 300 * 4;"
16534 "for (var i = 0; i < 300; i++) {"
16535 " if (large_array[offset + 4 * i] != 127 ||"
16536 " large_array[offset + 4 * i + 1] != 0 ||"
16537 " large_array[offset + 4 * i + 2] != 0 ||"
16538 " large_array[offset + 4 * i + 3] != 127) {"
16539 " failed = true;"
16540 " }"
16541 "}"
16542 "!failed;");
16543 CHECK_EQ(true, result->BooleanValue());
16544 free(large_array_data);
16545 }
16546
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016547 // The "" property descriptor is overloaded to store information about
16548 // the external array. Ensure that setting and accessing the "" property
16549 // works (it should overwrite the information cached about the external
16550 // array in the DescriptorArray) in various situations.
16551 result = CompileRun("ext_array[''] = 23; ext_array['']");
16552 CHECK_EQ(23, result->Int32Value());
16553
16554 // Property "" set after the external array is associated with the object.
16555 {
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016556 v8::Handle<v8::Object> obj2 = v8::Object::New(context->GetIsolate());
16557 obj2->Set(v8_str("ee_test_field"),
16558 v8::Int32::New(context->GetIsolate(), 256));
16559 obj2->Set(v8_str(""), v8::Int32::New(context->GetIsolate(), 1503));
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016560 // Set the elements to be the external array.
16561 obj2->SetIndexedPropertiesToExternalArrayData(array_data,
16562 array_type,
16563 kElementCount);
16564 context->Global()->Set(v8_str("ext_array"), obj2);
16565 result = CompileRun("ext_array['']");
16566 CHECK_EQ(1503, result->Int32Value());
16567 }
16568
16569 // Property "" set after the external array is associated with the object.
16570 {
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016571 v8::Handle<v8::Object> obj2 = v8::Object::New(context->GetIsolate());
16572 obj2->Set(v8_str("ee_test_field_2"),
16573 v8::Int32::New(context->GetIsolate(), 256));
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016574 // Set the elements to be the external array.
16575 obj2->SetIndexedPropertiesToExternalArrayData(array_data,
16576 array_type,
16577 kElementCount);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016578 obj2->Set(v8_str(""), v8::Int32::New(context->GetIsolate(), 1503));
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016579 context->Global()->Set(v8_str("ext_array"), obj2);
16580 result = CompileRun("ext_array['']");
16581 CHECK_EQ(1503, result->Int32Value());
16582 }
16583
16584 // Should reuse the map from previous test.
16585 {
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016586 v8::Handle<v8::Object> obj2 = v8::Object::New(context->GetIsolate());
16587 obj2->Set(v8_str("ee_test_field_2"),
16588 v8::Int32::New(context->GetIsolate(), 256));
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016589 // Set the elements to be the external array. Should re-use the map
16590 // from previous test.
16591 obj2->SetIndexedPropertiesToExternalArrayData(array_data,
16592 array_type,
16593 kElementCount);
16594 context->Global()->Set(v8_str("ext_array"), obj2);
16595 result = CompileRun("ext_array['']");
16596 }
16597
16598 // Property "" is a constant function that shouldn't not be interfered with
16599 // when an external array is set.
16600 {
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016601 v8::Handle<v8::Object> obj2 = v8::Object::New(context->GetIsolate());
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016602 // Start
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016603 obj2->Set(v8_str("ee_test_field3"),
16604 v8::Int32::New(context->GetIsolate(), 256));
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016605
16606 // Add a constant function to an object.
16607 context->Global()->Set(v8_str("ext_array"), obj2);
16608 result = CompileRun("ext_array[''] = function() {return 1503;};"
16609 "ext_array['']();");
16610
16611 // Add an external array transition to the same map that
16612 // has the constant transition.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016613 v8::Handle<v8::Object> obj3 = v8::Object::New(context->GetIsolate());
16614 obj3->Set(v8_str("ee_test_field3"),
16615 v8::Int32::New(context->GetIsolate(), 256));
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016616 obj3->SetIndexedPropertiesToExternalArrayData(array_data,
16617 array_type,
16618 kElementCount);
16619 context->Global()->Set(v8_str("ext_array"), obj3);
16620 }
16621
16622 // If a external array transition is in the map, it should get clobbered
16623 // by a constant function.
16624 {
16625 // Add an external array transition.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016626 v8::Handle<v8::Object> obj3 = v8::Object::New(context->GetIsolate());
16627 obj3->Set(v8_str("ee_test_field4"),
16628 v8::Int32::New(context->GetIsolate(), 256));
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016629 obj3->SetIndexedPropertiesToExternalArrayData(array_data,
16630 array_type,
16631 kElementCount);
16632
16633 // Add a constant function to the same map that just got an external array
16634 // transition.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016635 v8::Handle<v8::Object> obj2 = v8::Object::New(context->GetIsolate());
16636 obj2->Set(v8_str("ee_test_field4"),
16637 v8::Int32::New(context->GetIsolate(), 256));
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016638 context->Global()->Set(v8_str("ext_array"), obj2);
16639 result = CompileRun("ext_array[''] = function() {return 1503;};"
16640 "ext_array['']();");
16641 }
16642
ager@chromium.org3811b432009-10-28 14:53:37 +000016643 free(array_data);
16644}
16645
16646
16647THREADED_TEST(ExternalByteArray) {
lrn@chromium.org32d961d2010-06-30 09:09:34 +000016648 ExternalArrayTestHelper<i::ExternalByteArray, int8_t>(
ager@chromium.org3811b432009-10-28 14:53:37 +000016649 v8::kExternalByteArray,
16650 -128,
16651 127);
16652}
16653
16654
16655THREADED_TEST(ExternalUnsignedByteArray) {
lrn@chromium.org32d961d2010-06-30 09:09:34 +000016656 ExternalArrayTestHelper<i::ExternalUnsignedByteArray, uint8_t>(
ager@chromium.org3811b432009-10-28 14:53:37 +000016657 v8::kExternalUnsignedByteArray,
16658 0,
16659 255);
16660}
16661
16662
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000016663THREADED_TEST(ExternalPixelArray) {
16664 ExternalArrayTestHelper<i::ExternalPixelArray, uint8_t>(
16665 v8::kExternalPixelArray,
16666 0,
16667 255);
16668}
16669
16670
ager@chromium.org3811b432009-10-28 14:53:37 +000016671THREADED_TEST(ExternalShortArray) {
lrn@chromium.org32d961d2010-06-30 09:09:34 +000016672 ExternalArrayTestHelper<i::ExternalShortArray, int16_t>(
ager@chromium.org3811b432009-10-28 14:53:37 +000016673 v8::kExternalShortArray,
16674 -32768,
16675 32767);
16676}
16677
16678
16679THREADED_TEST(ExternalUnsignedShortArray) {
lrn@chromium.org32d961d2010-06-30 09:09:34 +000016680 ExternalArrayTestHelper<i::ExternalUnsignedShortArray, uint16_t>(
ager@chromium.org3811b432009-10-28 14:53:37 +000016681 v8::kExternalUnsignedShortArray,
16682 0,
16683 65535);
16684}
16685
16686
16687THREADED_TEST(ExternalIntArray) {
lrn@chromium.org32d961d2010-06-30 09:09:34 +000016688 ExternalArrayTestHelper<i::ExternalIntArray, int32_t>(
ager@chromium.org3811b432009-10-28 14:53:37 +000016689 v8::kExternalIntArray,
16690 INT_MIN, // -2147483648
16691 INT_MAX); // 2147483647
16692}
16693
16694
16695THREADED_TEST(ExternalUnsignedIntArray) {
lrn@chromium.org32d961d2010-06-30 09:09:34 +000016696 ExternalArrayTestHelper<i::ExternalUnsignedIntArray, uint32_t>(
ager@chromium.org3811b432009-10-28 14:53:37 +000016697 v8::kExternalUnsignedIntArray,
16698 0,
16699 UINT_MAX); // 4294967295
16700}
16701
16702
16703THREADED_TEST(ExternalFloatArray) {
lrn@chromium.org32d961d2010-06-30 09:09:34 +000016704 ExternalArrayTestHelper<i::ExternalFloatArray, float>(
ager@chromium.org3811b432009-10-28 14:53:37 +000016705 v8::kExternalFloatArray,
16706 -500,
16707 500);
16708}
16709
16710
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +000016711THREADED_TEST(ExternalDoubleArray) {
16712 ExternalArrayTestHelper<i::ExternalDoubleArray, double>(
16713 v8::kExternalDoubleArray,
16714 -500,
16715 500);
16716}
16717
16718
ager@chromium.org3811b432009-10-28 14:53:37 +000016719THREADED_TEST(ExternalArrays) {
16720 TestExternalByteArray();
16721 TestExternalUnsignedByteArray();
16722 TestExternalShortArray();
16723 TestExternalUnsignedShortArray();
16724 TestExternalIntArray();
16725 TestExternalUnsignedIntArray();
16726 TestExternalFloatArray();
16727}
16728
16729
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016730void ExternalArrayInfoTestHelper(v8::ExternalArrayType array_type) {
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016731 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016732 v8::HandleScope scope(context->GetIsolate());
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016733 for (int size = 0; size < 100; size += 10) {
16734 int element_size = ExternalArrayElementSize(array_type);
16735 void* external_data = malloc(size * element_size);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016736 v8::Handle<v8::Object> obj = v8::Object::New(context->GetIsolate());
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016737 obj->SetIndexedPropertiesToExternalArrayData(
16738 external_data, array_type, size);
16739 CHECK(obj->HasIndexedPropertiesInExternalArrayData());
16740 CHECK_EQ(external_data, obj->GetIndexedPropertiesExternalArrayData());
16741 CHECK_EQ(array_type, obj->GetIndexedPropertiesExternalArrayDataType());
16742 CHECK_EQ(size, obj->GetIndexedPropertiesExternalArrayDataLength());
16743 free(external_data);
16744 }
16745}
16746
16747
16748THREADED_TEST(ExternalArrayInfo) {
16749 ExternalArrayInfoTestHelper(v8::kExternalByteArray);
16750 ExternalArrayInfoTestHelper(v8::kExternalUnsignedByteArray);
16751 ExternalArrayInfoTestHelper(v8::kExternalShortArray);
16752 ExternalArrayInfoTestHelper(v8::kExternalUnsignedShortArray);
16753 ExternalArrayInfoTestHelper(v8::kExternalIntArray);
16754 ExternalArrayInfoTestHelper(v8::kExternalUnsignedIntArray);
16755 ExternalArrayInfoTestHelper(v8::kExternalFloatArray);
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +000016756 ExternalArrayInfoTestHelper(v8::kExternalDoubleArray);
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000016757 ExternalArrayInfoTestHelper(v8::kExternalPixelArray);
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016758}
16759
16760
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016761void ExtArrayLimitsHelper(v8::Isolate* isolate,
16762 v8::ExternalArrayType array_type,
16763 int size) {
16764 v8::Handle<v8::Object> obj = v8::Object::New(isolate);
danno@chromium.org412fa512012-09-14 13:28:26 +000016765 v8::V8::SetFatalErrorHandler(StoringErrorCallback);
16766 last_location = last_message = NULL;
16767 obj->SetIndexedPropertiesToExternalArrayData(NULL, array_type, size);
16768 CHECK(!obj->HasIndexedPropertiesInExternalArrayData());
16769 CHECK_NE(NULL, last_location);
16770 CHECK_NE(NULL, last_message);
16771}
16772
16773
16774TEST(ExternalArrayLimits) {
danno@chromium.org412fa512012-09-14 13:28:26 +000016775 LocalContext context;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016776 v8::Isolate* isolate = context->GetIsolate();
16777 v8::HandleScope scope(isolate);
16778 ExtArrayLimitsHelper(isolate, v8::kExternalByteArray, 0x40000000);
16779 ExtArrayLimitsHelper(isolate, v8::kExternalByteArray, 0xffffffff);
16780 ExtArrayLimitsHelper(isolate, v8::kExternalUnsignedByteArray, 0x40000000);
16781 ExtArrayLimitsHelper(isolate, v8::kExternalUnsignedByteArray, 0xffffffff);
16782 ExtArrayLimitsHelper(isolate, v8::kExternalShortArray, 0x40000000);
16783 ExtArrayLimitsHelper(isolate, v8::kExternalShortArray, 0xffffffff);
16784 ExtArrayLimitsHelper(isolate, v8::kExternalUnsignedShortArray, 0x40000000);
16785 ExtArrayLimitsHelper(isolate, v8::kExternalUnsignedShortArray, 0xffffffff);
16786 ExtArrayLimitsHelper(isolate, v8::kExternalIntArray, 0x40000000);
16787 ExtArrayLimitsHelper(isolate, v8::kExternalIntArray, 0xffffffff);
16788 ExtArrayLimitsHelper(isolate, v8::kExternalUnsignedIntArray, 0x40000000);
16789 ExtArrayLimitsHelper(isolate, v8::kExternalUnsignedIntArray, 0xffffffff);
16790 ExtArrayLimitsHelper(isolate, v8::kExternalFloatArray, 0x40000000);
16791 ExtArrayLimitsHelper(isolate, v8::kExternalFloatArray, 0xffffffff);
16792 ExtArrayLimitsHelper(isolate, v8::kExternalDoubleArray, 0x40000000);
16793 ExtArrayLimitsHelper(isolate, v8::kExternalDoubleArray, 0xffffffff);
16794 ExtArrayLimitsHelper(isolate, v8::kExternalPixelArray, 0x40000000);
16795 ExtArrayLimitsHelper(isolate, v8::kExternalPixelArray, 0xffffffff);
danno@chromium.org412fa512012-09-14 13:28:26 +000016796}
16797
16798
danno@chromium.orgf005df62013-04-30 16:36:45 +000016799template <typename ElementType, typename TypedArray,
16800 class ExternalArrayClass>
16801void TypedArrayTestHelper(v8::ExternalArrayType array_type,
16802 int64_t low, int64_t high) {
16803 const int kElementCount = 50;
danno@chromium.orgf005df62013-04-30 16:36:45 +000016804
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +000016805 i::ScopedVector<ElementType> backing_store(kElementCount+2);
16806
danno@chromium.orgf005df62013-04-30 16:36:45 +000016807 LocalContext env;
16808 v8::Isolate* isolate = env->GetIsolate();
16809 v8::HandleScope handle_scope(isolate);
16810
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000016811 Local<v8::ArrayBuffer> ab =
16812 v8::ArrayBuffer::New(isolate, backing_store.start(),
16813 (kElementCount + 2) * sizeof(ElementType));
danno@chromium.orgf005df62013-04-30 16:36:45 +000016814 Local<TypedArray> ta =
16815 TypedArray::New(ab, 2*sizeof(ElementType), kElementCount);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000016816 CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
danno@chromium.orgf005df62013-04-30 16:36:45 +000016817 CHECK_EQ(kElementCount, static_cast<int>(ta->Length()));
16818 CHECK_EQ(2*sizeof(ElementType), static_cast<int>(ta->ByteOffset()));
16819 CHECK_EQ(kElementCount*sizeof(ElementType),
16820 static_cast<int>(ta->ByteLength()));
16821 CHECK_EQ(ab, ta->Buffer());
16822
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +000016823 ElementType* data = backing_store.start() + 2;
danno@chromium.orgf005df62013-04-30 16:36:45 +000016824 for (int i = 0; i < kElementCount; i++) {
16825 data[i] = static_cast<ElementType>(i);
16826 }
16827
16828 ObjectWithExternalArrayTestHelper<ExternalArrayClass, ElementType>(
16829 env.local(), ta, kElementCount, array_type, low, high);
16830}
16831
16832
16833THREADED_TEST(Uint8Array) {
16834 TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::ExternalUnsignedByteArray>(
16835 v8::kExternalUnsignedByteArray, 0, 0xFF);
16836}
16837
16838
16839THREADED_TEST(Int8Array) {
16840 TypedArrayTestHelper<int8_t, v8::Int8Array, i::ExternalByteArray>(
16841 v8::kExternalByteArray, -0x80, 0x7F);
16842}
16843
16844
16845THREADED_TEST(Uint16Array) {
16846 TypedArrayTestHelper<uint16_t,
16847 v8::Uint16Array,
16848 i::ExternalUnsignedShortArray>(
16849 v8::kExternalUnsignedShortArray, 0, 0xFFFF);
16850}
16851
16852
16853THREADED_TEST(Int16Array) {
16854 TypedArrayTestHelper<int16_t, v8::Int16Array, i::ExternalShortArray>(
16855 v8::kExternalShortArray, -0x8000, 0x7FFF);
16856}
16857
16858
16859THREADED_TEST(Uint32Array) {
16860 TypedArrayTestHelper<uint32_t, v8::Uint32Array, i::ExternalUnsignedIntArray>(
16861 v8::kExternalUnsignedIntArray, 0, UINT_MAX);
16862}
16863
16864
16865THREADED_TEST(Int32Array) {
16866 TypedArrayTestHelper<int32_t, v8::Int32Array, i::ExternalIntArray>(
16867 v8::kExternalIntArray, INT_MIN, INT_MAX);
16868}
16869
16870
16871THREADED_TEST(Float32Array) {
16872 TypedArrayTestHelper<float, v8::Float32Array, i::ExternalFloatArray>(
16873 v8::kExternalFloatArray, -500, 500);
16874}
16875
16876
16877THREADED_TEST(Float64Array) {
16878 TypedArrayTestHelper<double, v8::Float64Array, i::ExternalDoubleArray>(
16879 v8::kExternalDoubleArray, -500, 500);
16880}
16881
16882
ulan@chromium.org57ff8812013-05-10 08:16:55 +000016883THREADED_TEST(Uint8ClampedArray) {
16884 TypedArrayTestHelper<uint8_t, v8::Uint8ClampedArray, i::ExternalPixelArray>(
16885 v8::kExternalPixelArray, 0, 0xFF);
16886}
16887
16888
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000016889THREADED_TEST(DataView) {
16890 const int kSize = 50;
16891
16892 i::ScopedVector<uint8_t> backing_store(kSize+2);
16893
16894 LocalContext env;
16895 v8::Isolate* isolate = env->GetIsolate();
16896 v8::HandleScope handle_scope(isolate);
16897
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000016898 Local<v8::ArrayBuffer> ab =
16899 v8::ArrayBuffer::New(isolate, backing_store.start(), 2 + kSize);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000016900 Local<v8::DataView> dv =
16901 v8::DataView::New(ab, 2, kSize);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000016902 CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000016903 CHECK_EQ(2, static_cast<int>(dv->ByteOffset()));
16904 CHECK_EQ(kSize, static_cast<int>(dv->ByteLength()));
16905 CHECK_EQ(ab, dv->Buffer());
16906}
16907
16908
16909#define IS_ARRAY_BUFFER_VIEW_TEST(View) \
16910 THREADED_TEST(Is##View) { \
ulan@chromium.org57ff8812013-05-10 08:16:55 +000016911 LocalContext env; \
16912 v8::Isolate* isolate = env->GetIsolate(); \
16913 v8::HandleScope handle_scope(isolate); \
16914 \
16915 Handle<Value> result = CompileRun( \
16916 "var ab = new ArrayBuffer(128);" \
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000016917 "new " #View "(ab)"); \
16918 CHECK(result->IsArrayBufferView()); \
16919 CHECK(result->Is##View()); \
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000016920 CheckInternalFieldsAreZero<v8::ArrayBufferView>(result.As<v8::View>()); \
ulan@chromium.org57ff8812013-05-10 08:16:55 +000016921 }
16922
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000016923IS_ARRAY_BUFFER_VIEW_TEST(Uint8Array)
16924IS_ARRAY_BUFFER_VIEW_TEST(Int8Array)
16925IS_ARRAY_BUFFER_VIEW_TEST(Uint16Array)
16926IS_ARRAY_BUFFER_VIEW_TEST(Int16Array)
16927IS_ARRAY_BUFFER_VIEW_TEST(Uint32Array)
16928IS_ARRAY_BUFFER_VIEW_TEST(Int32Array)
16929IS_ARRAY_BUFFER_VIEW_TEST(Float32Array)
16930IS_ARRAY_BUFFER_VIEW_TEST(Float64Array)
16931IS_ARRAY_BUFFER_VIEW_TEST(Uint8ClampedArray)
16932IS_ARRAY_BUFFER_VIEW_TEST(DataView)
ulan@chromium.org57ff8812013-05-10 08:16:55 +000016933
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000016934#undef IS_ARRAY_BUFFER_VIEW_TEST
ulan@chromium.org57ff8812013-05-10 08:16:55 +000016935
16936
16937
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000016938THREADED_TEST(ScriptContextDependence) {
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000016939 LocalContext c1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016940 v8::HandleScope scope(c1->GetIsolate());
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000016941 const char *source = "foo";
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000016942 v8::Handle<v8::Script> dep =
16943 v8::Script::Compile(v8::String::NewFromUtf8(c1->GetIsolate(), source));
16944 v8::Handle<v8::Script> indep =
16945 v8::Script::New(v8::String::NewFromUtf8(c1->GetIsolate(), source));
16946 c1->Global()->Set(v8::String::NewFromUtf8(c1->GetIsolate(), "foo"),
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016947 v8::Integer::New(c1->GetIsolate(), 100));
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000016948 CHECK_EQ(dep->Run()->Int32Value(), 100);
16949 CHECK_EQ(indep->Run()->Int32Value(), 100);
16950 LocalContext c2;
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000016951 c2->Global()->Set(v8::String::NewFromUtf8(c2->GetIsolate(), "foo"),
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016952 v8::Integer::New(c2->GetIsolate(), 101));
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000016953 CHECK_EQ(dep->Run()->Int32Value(), 100);
16954 CHECK_EQ(indep->Run()->Int32Value(), 101);
16955}
16956
ager@chromium.org96c75b52009-08-26 09:13:16 +000016957
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000016958THREADED_TEST(StackTrace) {
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000016959 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016960 v8::HandleScope scope(context->GetIsolate());
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000016961 v8::TryCatch try_catch;
16962 const char *source = "function foo() { FAIL.FAIL; }; foo();";
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000016963 v8::Handle<v8::String> src =
16964 v8::String::NewFromUtf8(context->GetIsolate(), source);
16965 v8::Handle<v8::String> origin =
16966 v8::String::NewFromUtf8(context->GetIsolate(), "stack-trace-test");
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000016967 v8::Script::New(src, origin)->Run();
16968 CHECK(try_catch.HasCaught());
16969 v8::String::Utf8Value stack(try_catch.StackTrace());
16970 CHECK(strstr(*stack, "at foo (stack-trace-test") != NULL);
16971}
ager@chromium.org96c75b52009-08-26 09:13:16 +000016972
16973
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000016974// Checks that a StackFrame has certain expected values.
16975void checkStackFrame(const char* expected_script_name,
16976 const char* expected_func_name, int expected_line_number,
16977 int expected_column, bool is_eval, bool is_constructor,
16978 v8::Handle<v8::StackFrame> frame) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000016979 v8::HandleScope scope(CcTest::isolate());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000016980 v8::String::Utf8Value func_name(frame->GetFunctionName());
16981 v8::String::Utf8Value script_name(frame->GetScriptName());
16982 if (*script_name == NULL) {
16983 // The situation where there is no associated script, like for evals.
16984 CHECK(expected_script_name == NULL);
16985 } else {
16986 CHECK(strstr(*script_name, expected_script_name) != NULL);
16987 }
16988 CHECK(strstr(*func_name, expected_func_name) != NULL);
16989 CHECK_EQ(expected_line_number, frame->GetLineNumber());
16990 CHECK_EQ(expected_column, frame->GetColumn());
16991 CHECK_EQ(is_eval, frame->IsEval());
16992 CHECK_EQ(is_constructor, frame->IsConstructor());
16993}
16994
16995
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000016996void AnalyzeStackInNativeCode(const v8::FunctionCallbackInfo<v8::Value>& args) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016997 v8::HandleScope scope(args.GetIsolate());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000016998 const char* origin = "capture-stack-trace-test";
16999 const int kOverviewTest = 1;
17000 const int kDetailedTest = 2;
17001
17002 ASSERT(args.Length() == 1);
17003
17004 int testGroup = args[0]->Int32Value();
17005 if (testGroup == kOverviewTest) {
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017006 v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
17007 args.GetIsolate(), 10, v8::StackTrace::kOverview);
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017008 CHECK_EQ(4, stackTrace->GetFrameCount());
17009 checkStackFrame(origin, "bar", 2, 10, false, false,
17010 stackTrace->GetFrame(0));
17011 checkStackFrame(origin, "foo", 6, 3, false, false,
17012 stackTrace->GetFrame(1));
whesse@chromium.org030d38e2011-07-13 13:23:34 +000017013 // This is the source string inside the eval which has the call to foo.
17014 checkStackFrame(NULL, "", 1, 5, false, false,
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017015 stackTrace->GetFrame(2));
whesse@chromium.org030d38e2011-07-13 13:23:34 +000017016 // The last frame is an anonymous function which has the initial eval call.
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017017 checkStackFrame(origin, "", 8, 7, false, false,
17018 stackTrace->GetFrame(3));
17019
17020 CHECK(stackTrace->AsArray()->IsArray());
17021 } else if (testGroup == kDetailedTest) {
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017022 v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
17023 args.GetIsolate(), 10, v8::StackTrace::kDetailed);
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017024 CHECK_EQ(4, stackTrace->GetFrameCount());
17025 checkStackFrame(origin, "bat", 4, 22, false, false,
17026 stackTrace->GetFrame(0));
17027 checkStackFrame(origin, "baz", 8, 3, false, true,
17028 stackTrace->GetFrame(1));
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +000017029#ifdef ENABLE_DEBUGGER_SUPPORT
17030 bool is_eval = true;
17031#else // ENABLE_DEBUGGER_SUPPORT
17032 bool is_eval = false;
17033#endif // ENABLE_DEBUGGER_SUPPORT
17034
whesse@chromium.org030d38e2011-07-13 13:23:34 +000017035 // This is the source string inside the eval which has the call to baz.
17036 checkStackFrame(NULL, "", 1, 5, is_eval, false,
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017037 stackTrace->GetFrame(2));
whesse@chromium.org030d38e2011-07-13 13:23:34 +000017038 // The last frame is an anonymous function which has the initial eval call.
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017039 checkStackFrame(origin, "", 10, 1, false, false,
17040 stackTrace->GetFrame(3));
17041
17042 CHECK(stackTrace->AsArray()->IsArray());
17043 }
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017044}
17045
17046
17047// Tests the C++ StackTrace API.
kasperl@chromium.orga5551262010-12-07 12:49:48 +000017048// TODO(3074796): Reenable this as a THREADED_TEST once it passes.
17049// THREADED_TEST(CaptureStackTrace) {
17050TEST(CaptureStackTrace) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017051 v8::Isolate* isolate = CcTest::isolate();
17052 v8::HandleScope scope(isolate);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017053 v8::Handle<v8::String> origin =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017054 v8::String::NewFromUtf8(isolate, "capture-stack-trace-test");
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000017055 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017056 templ->Set(v8_str("AnalyzeStackInNativeCode"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017057 v8::FunctionTemplate::New(isolate, AnalyzeStackInNativeCode));
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017058 LocalContext context(0, templ);
17059
17060 // Test getting OVERVIEW information. Should ignore information that is not
17061 // script name, function name, line number, and column offset.
17062 const char *overview_source =
17063 "function bar() {\n"
17064 " var y; AnalyzeStackInNativeCode(1);\n"
17065 "}\n"
17066 "function foo() {\n"
17067 "\n"
17068 " bar();\n"
17069 "}\n"
17070 "var x;eval('new foo();');";
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017071 v8::Handle<v8::String> overview_src =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017072 v8::String::NewFromUtf8(isolate, overview_source);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000017073 v8::Handle<Value> overview_result(
17074 v8::Script::New(overview_src, origin)->Run());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000017075 CHECK(!overview_result.IsEmpty());
17076 CHECK(overview_result->IsObject());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017077
17078 // Test getting DETAILED information.
17079 const char *detailed_source =
17080 "function bat() {AnalyzeStackInNativeCode(2);\n"
17081 "}\n"
17082 "\n"
17083 "function baz() {\n"
17084 " bat();\n"
17085 "}\n"
17086 "eval('new baz();');";
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017087 v8::Handle<v8::String> detailed_src =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017088 v8::String::NewFromUtf8(isolate, detailed_source);
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017089 // Make the script using a non-zero line and column offset.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000017090 v8::Handle<v8::Integer> line_offset = v8::Integer::New(isolate, 3);
17091 v8::Handle<v8::Integer> column_offset = v8::Integer::New(isolate, 5);
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017092 v8::ScriptOrigin detailed_origin(origin, line_offset, column_offset);
17093 v8::Handle<v8::Script> detailed_script(
17094 v8::Script::New(detailed_src, &detailed_origin));
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000017095 v8::Handle<Value> detailed_result(detailed_script->Run());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000017096 CHECK(!detailed_result.IsEmpty());
17097 CHECK(detailed_result->IsObject());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017098}
17099
17100
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000017101static void StackTraceForUncaughtExceptionListener(
17102 v8::Handle<v8::Message> message,
17103 v8::Handle<Value>) {
17104 v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
17105 CHECK_EQ(2, stack_trace->GetFrameCount());
17106 checkStackFrame("origin", "foo", 2, 3, false, false,
17107 stack_trace->GetFrame(0));
17108 checkStackFrame("origin", "bar", 5, 3, false, false,
17109 stack_trace->GetFrame(1));
17110}
17111
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000017112
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000017113TEST(CaptureStackTraceForUncaughtException) {
17114 report_count = 0;
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000017115 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017116 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000017117 v8::V8::AddMessageListener(StackTraceForUncaughtExceptionListener);
17118 v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
17119
17120 Script::Compile(v8_str("function foo() {\n"
17121 " throw 1;\n"
17122 "};\n"
17123 "function bar() {\n"
17124 " foo();\n"
17125 "};"),
17126 v8_str("origin"))->Run();
17127 v8::Local<v8::Object> global = env->Global();
17128 Local<Value> trouble = global->Get(v8_str("bar"));
17129 CHECK(trouble->IsFunction());
17130 Function::Cast(*trouble)->Call(global, 0, NULL);
17131 v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
17132 v8::V8::RemoveMessageListeners(StackTraceForUncaughtExceptionListener);
17133}
17134
17135
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000017136TEST(CaptureStackTraceForUncaughtExceptionAndSetters) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000017137 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017138 v8::HandleScope scope(env->GetIsolate());
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000017139 v8::V8::SetCaptureStackTraceForUncaughtExceptions(true,
17140 1024,
17141 v8::StackTrace::kDetailed);
17142
17143 CompileRun(
17144 "var setters = ['column', 'lineNumber', 'scriptName',\n"
17145 " 'scriptNameOrSourceURL', 'functionName', 'isEval',\n"
17146 " 'isConstructor'];\n"
17147 "for (var i = 0; i < setters.length; i++) {\n"
17148 " var prop = setters[i];\n"
17149 " Object.prototype.__defineSetter__(prop, function() { throw prop; });\n"
17150 "}\n");
17151 CompileRun("throw 'exception';");
17152 v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
17153}
17154
17155
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000017156static void RethrowStackTraceHandler(v8::Handle<v8::Message> message,
17157 v8::Handle<v8::Value> data) {
17158 // Use the frame where JavaScript is called from.
17159 v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
17160 CHECK(!stack_trace.IsEmpty());
17161 int frame_count = stack_trace->GetFrameCount();
17162 CHECK_EQ(3, frame_count);
17163 int line_number[] = {1, 2, 5};
17164 for (int i = 0; i < frame_count; i++) {
17165 CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
17166 }
17167}
17168
17169
17170// Test that we only return the stack trace at the site where the exception
17171// is first thrown (not where it is rethrown).
17172TEST(RethrowStackTrace) {
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000017173 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017174 v8::HandleScope scope(env->GetIsolate());
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000017175 // We make sure that
17176 // - the stack trace of the ReferenceError in g() is reported.
17177 // - the stack trace is not overwritten when e1 is rethrown by t().
17178 // - the stack trace of e2 does not overwrite that of e1.
17179 const char* source =
17180 "function g() { error; } \n"
17181 "function f() { g(); } \n"
17182 "function t(e) { throw e; } \n"
17183 "try { \n"
17184 " f(); \n"
17185 "} catch (e1) { \n"
17186 " try { \n"
17187 " error; \n"
17188 " } catch (e2) { \n"
17189 " t(e1); \n"
17190 " } \n"
17191 "} \n";
17192 v8::V8::AddMessageListener(RethrowStackTraceHandler);
17193 v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
17194 CompileRun(source);
17195 v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
17196 v8::V8::RemoveMessageListeners(RethrowStackTraceHandler);
17197}
17198
17199
17200static void RethrowPrimitiveStackTraceHandler(v8::Handle<v8::Message> message,
17201 v8::Handle<v8::Value> data) {
17202 v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
17203 CHECK(!stack_trace.IsEmpty());
17204 int frame_count = stack_trace->GetFrameCount();
17205 CHECK_EQ(2, frame_count);
17206 int line_number[] = {3, 7};
17207 for (int i = 0; i < frame_count; i++) {
17208 CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
17209 }
17210}
17211
17212
17213// Test that we do not recognize identity for primitive exceptions.
17214TEST(RethrowPrimitiveStackTrace) {
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000017215 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017216 v8::HandleScope scope(env->GetIsolate());
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000017217 // We do not capture stack trace for non Error objects on creation time.
17218 // Instead, we capture the stack trace on last throw.
17219 const char* source =
17220 "function g() { throw 404; } \n"
17221 "function f() { g(); } \n"
17222 "function t(e) { throw e; } \n"
17223 "try { \n"
17224 " f(); \n"
17225 "} catch (e1) { \n"
17226 " t(e1) \n"
17227 "} \n";
17228 v8::V8::AddMessageListener(RethrowPrimitiveStackTraceHandler);
17229 v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
17230 CompileRun(source);
17231 v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
17232 v8::V8::RemoveMessageListeners(RethrowPrimitiveStackTraceHandler);
17233}
17234
17235
17236static void RethrowExistingStackTraceHandler(v8::Handle<v8::Message> message,
17237 v8::Handle<v8::Value> data) {
17238 // Use the frame where JavaScript is called from.
17239 v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
17240 CHECK(!stack_trace.IsEmpty());
17241 CHECK_EQ(1, stack_trace->GetFrameCount());
17242 CHECK_EQ(1, stack_trace->GetFrame(0)->GetLineNumber());
17243}
17244
17245
17246// Test that the stack trace is captured when the error object is created and
17247// not where it is thrown.
17248TEST(RethrowExistingStackTrace) {
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000017249 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017250 v8::HandleScope scope(env->GetIsolate());
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000017251 const char* source =
17252 "var e = new Error(); \n"
17253 "throw e; \n";
17254 v8::V8::AddMessageListener(RethrowExistingStackTraceHandler);
17255 v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
17256 CompileRun(source);
17257 v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
17258 v8::V8::RemoveMessageListeners(RethrowExistingStackTraceHandler);
17259}
17260
17261
17262static void RethrowBogusErrorStackTraceHandler(v8::Handle<v8::Message> message,
17263 v8::Handle<v8::Value> data) {
17264 // Use the frame where JavaScript is called from.
17265 v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
17266 CHECK(!stack_trace.IsEmpty());
17267 CHECK_EQ(1, stack_trace->GetFrameCount());
17268 CHECK_EQ(2, stack_trace->GetFrame(0)->GetLineNumber());
17269}
17270
17271
17272// Test that the stack trace is captured where the bogus Error object is thrown.
17273TEST(RethrowBogusErrorStackTrace) {
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000017274 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017275 v8::HandleScope scope(env->GetIsolate());
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000017276 const char* source =
17277 "var e = {__proto__: new Error()} \n"
17278 "throw e; \n";
17279 v8::V8::AddMessageListener(RethrowBogusErrorStackTraceHandler);
17280 v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
17281 CompileRun(source);
17282 v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
17283 v8::V8::RemoveMessageListeners(RethrowBogusErrorStackTraceHandler);
17284}
17285
17286
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017287void AnalyzeStackOfEvalWithSourceURL(
17288 const v8::FunctionCallbackInfo<v8::Value>& args) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017289 v8::HandleScope scope(args.GetIsolate());
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017290 v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
17291 args.GetIsolate(), 10, v8::StackTrace::kDetailed);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000017292 CHECK_EQ(5, stackTrace->GetFrameCount());
17293 v8::Handle<v8::String> url = v8_str("eval_url");
17294 for (int i = 0; i < 3; i++) {
17295 v8::Handle<v8::String> name =
17296 stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
17297 CHECK(!name.IsEmpty());
17298 CHECK_EQ(url, name);
17299 }
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000017300}
17301
17302
17303TEST(SourceURLInStackTrace) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017304 v8::Isolate* isolate = CcTest::isolate();
17305 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000017306 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000017307 templ->Set(v8_str("AnalyzeStackOfEvalWithSourceURL"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017308 v8::FunctionTemplate::New(isolate,
17309 AnalyzeStackOfEvalWithSourceURL));
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000017310 LocalContext context(0, templ);
17311
17312 const char *source =
17313 "function outer() {\n"
17314 "function bar() {\n"
17315 " AnalyzeStackOfEvalWithSourceURL();\n"
17316 "}\n"
17317 "function foo() {\n"
17318 "\n"
17319 " bar();\n"
17320 "}\n"
17321 "foo();\n"
17322 "}\n"
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000017323 "eval('(' + outer +')()%s');";
17324
17325 i::ScopedVector<char> code(1024);
17326 i::OS::SNPrintF(code, source, "//# sourceURL=eval_url");
17327 CHECK(CompileRun(code.start())->IsUndefined());
17328 i::OS::SNPrintF(code, source, "//@ sourceURL=eval_url");
17329 CHECK(CompileRun(code.start())->IsUndefined());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000017330}
17331
17332
jkummerow@chromium.org8fa5bd92013-09-02 11:45:09 +000017333static int scriptIdInStack[2];
17334
17335void AnalyzeScriptIdInStack(
17336 const v8::FunctionCallbackInfo<v8::Value>& args) {
17337 v8::HandleScope scope(args.GetIsolate());
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017338 v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
17339 args.GetIsolate(), 10, v8::StackTrace::kScriptId);
jkummerow@chromium.org8fa5bd92013-09-02 11:45:09 +000017340 CHECK_EQ(2, stackTrace->GetFrameCount());
17341 for (int i = 0; i < 2; i++) {
17342 scriptIdInStack[i] = stackTrace->GetFrame(i)->GetScriptId();
17343 }
17344}
17345
17346
17347TEST(ScriptIdInStackTrace) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017348 v8::Isolate* isolate = CcTest::isolate();
17349 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000017350 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
jkummerow@chromium.org8fa5bd92013-09-02 11:45:09 +000017351 templ->Set(v8_str("AnalyzeScriptIdInStack"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017352 v8::FunctionTemplate::New(isolate, AnalyzeScriptIdInStack));
jkummerow@chromium.org8fa5bd92013-09-02 11:45:09 +000017353 LocalContext context(0, templ);
17354
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017355 v8::Handle<v8::String> scriptSource = v8::String::NewFromUtf8(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017356 isolate,
jkummerow@chromium.org8fa5bd92013-09-02 11:45:09 +000017357 "function foo() {\n"
17358 " AnalyzeScriptIdInStack();"
17359 "}\n"
17360 "foo();\n");
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017361 v8::ScriptOrigin origin =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017362 v8::ScriptOrigin(v8::String::NewFromUtf8(isolate, "test"));
jkummerow@chromium.org8fa5bd92013-09-02 11:45:09 +000017363 v8::Local<v8::Script> script(v8::Script::Compile(scriptSource, &origin));
17364 script->Run();
17365 for (int i = 0; i < 2; i++) {
17366 CHECK(scriptIdInStack[i] != v8::Message::kNoScriptIdInfo);
17367 CHECK_EQ(scriptIdInStack[i], script->GetId());
17368 }
17369}
17370
17371
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017372void AnalyzeStackOfInlineScriptWithSourceURL(
17373 const v8::FunctionCallbackInfo<v8::Value>& args) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017374 v8::HandleScope scope(args.GetIsolate());
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017375 v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
17376 args.GetIsolate(), 10, v8::StackTrace::kDetailed);
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017377 CHECK_EQ(4, stackTrace->GetFrameCount());
17378 v8::Handle<v8::String> url = v8_str("url");
17379 for (int i = 0; i < 3; i++) {
17380 v8::Handle<v8::String> name =
17381 stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
17382 CHECK(!name.IsEmpty());
17383 CHECK_EQ(url, name);
17384 }
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017385}
17386
17387
17388TEST(InlineScriptWithSourceURLInStackTrace) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000017389 v8::Isolate* isolate = CcTest::isolate();
17390 v8::HandleScope scope(isolate);
17391 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017392 templ->Set(v8_str("AnalyzeStackOfInlineScriptWithSourceURL"),
17393 v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017394 CcTest::isolate(), AnalyzeStackOfInlineScriptWithSourceURL));
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017395 LocalContext context(0, templ);
17396
17397 const char *source =
17398 "function outer() {\n"
17399 "function bar() {\n"
17400 " AnalyzeStackOfInlineScriptWithSourceURL();\n"
17401 "}\n"
17402 "function foo() {\n"
17403 "\n"
17404 " bar();\n"
17405 "}\n"
17406 "foo();\n"
17407 "}\n"
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000017408 "outer()\n%s";
17409
17410 i::ScopedVector<char> code(1024);
17411 i::OS::SNPrintF(code, source, "//# sourceURL=source_url");
17412 CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
17413 i::OS::SNPrintF(code, source, "//@ sourceURL=source_url");
17414 CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017415}
17416
17417
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017418void AnalyzeStackOfDynamicScriptWithSourceURL(
17419 const v8::FunctionCallbackInfo<v8::Value>& args) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017420 v8::HandleScope scope(args.GetIsolate());
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017421 v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
17422 args.GetIsolate(), 10, v8::StackTrace::kDetailed);
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017423 CHECK_EQ(4, stackTrace->GetFrameCount());
17424 v8::Handle<v8::String> url = v8_str("source_url");
17425 for (int i = 0; i < 3; i++) {
17426 v8::Handle<v8::String> name =
17427 stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
17428 CHECK(!name.IsEmpty());
17429 CHECK_EQ(url, name);
17430 }
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017431}
17432
17433
17434TEST(DynamicWithSourceURLInStackTrace) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000017435 v8::Isolate* isolate = CcTest::isolate();
17436 v8::HandleScope scope(isolate);
17437 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017438 templ->Set(v8_str("AnalyzeStackOfDynamicScriptWithSourceURL"),
17439 v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017440 CcTest::isolate(), AnalyzeStackOfDynamicScriptWithSourceURL));
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017441 LocalContext context(0, templ);
17442
17443 const char *source =
17444 "function outer() {\n"
17445 "function bar() {\n"
17446 " AnalyzeStackOfDynamicScriptWithSourceURL();\n"
17447 "}\n"
17448 "function foo() {\n"
17449 "\n"
17450 " bar();\n"
17451 "}\n"
17452 "foo();\n"
17453 "}\n"
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000017454 "outer()\n%s";
17455
17456 i::ScopedVector<char> code(1024);
17457 i::OS::SNPrintF(code, source, "//# sourceURL=source_url");
17458 CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
17459 i::OS::SNPrintF(code, source, "//@ sourceURL=source_url");
17460 CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017461}
17462
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000017463
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017464static void CreateGarbageInOldSpace() {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017465 i::Factory* factory = CcTest::i_isolate()->factory();
17466 v8::HandleScope scope(CcTest::isolate());
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017467 i::AlwaysAllocateScope always_allocate;
17468 for (int i = 0; i < 1000; i++) {
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000017469 factory->NewFixedArray(1000, i::TENURED);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017470 }
svenpanne@chromium.orgecb9dd62011-12-01 08:22:35 +000017471}
17472
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000017473
svenpanne@chromium.orgecb9dd62011-12-01 08:22:35 +000017474// Test that idle notification can be handled and eventually returns true.
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017475TEST(IdleNotification) {
17476 const intptr_t MB = 1024 * 1024;
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017477 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017478 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017479 intptr_t initial_size = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017480 CreateGarbageInOldSpace();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017481 intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017482 CHECK_GT(size_with_garbage, initial_size + MB);
17483 bool finished = false;
17484 for (int i = 0; i < 200 && !finished; i++) {
17485 finished = v8::V8::IdleNotification();
17486 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017487 intptr_t final_size = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017488 CHECK(finished);
17489 CHECK_LT(final_size, initial_size + 1);
17490}
17491
17492
17493// Test that idle notification can be handled and eventually collects garbage.
yangguo@chromium.org56454712012-02-16 15:33:53 +000017494TEST(IdleNotificationWithSmallHint) {
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017495 const intptr_t MB = 1024 * 1024;
17496 const int IdlePauseInMs = 900;
svenpanne@chromium.orgecb9dd62011-12-01 08:22:35 +000017497 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017498 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017499 intptr_t initial_size = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017500 CreateGarbageInOldSpace();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017501 intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017502 CHECK_GT(size_with_garbage, initial_size + MB);
17503 bool finished = false;
17504 for (int i = 0; i < 200 && !finished; i++) {
17505 finished = v8::V8::IdleNotification(IdlePauseInMs);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017506 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017507 intptr_t final_size = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017508 CHECK(finished);
17509 CHECK_LT(final_size, initial_size + 1);
yangguo@chromium.org56454712012-02-16 15:33:53 +000017510}
17511
17512
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017513// Test that idle notification can be handled and eventually collects garbage.
yangguo@chromium.org56454712012-02-16 15:33:53 +000017514TEST(IdleNotificationWithLargeHint) {
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017515 const intptr_t MB = 1024 * 1024;
17516 const int IdlePauseInMs = 900;
yangguo@chromium.org56454712012-02-16 15:33:53 +000017517 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017518 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017519 intptr_t initial_size = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017520 CreateGarbageInOldSpace();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017521 intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017522 CHECK_GT(size_with_garbage, initial_size + MB);
17523 bool finished = false;
17524 for (int i = 0; i < 200 && !finished; i++) {
17525 finished = v8::V8::IdleNotification(IdlePauseInMs);
yangguo@chromium.org56454712012-02-16 15:33:53 +000017526 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017527 intptr_t final_size = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017528 CHECK(finished);
17529 CHECK_LT(final_size, initial_size + 1);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017530}
17531
17532
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017533TEST(Regress2107) {
17534 const intptr_t MB = 1024 * 1024;
17535 const int kShortIdlePauseInMs = 100;
17536 const int kLongIdlePauseInMs = 1000;
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017537 LocalContext env;
ulan@chromium.org57ff8812013-05-10 08:16:55 +000017538 v8::Isolate* isolate = env->GetIsolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017539 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017540 intptr_t initial_size = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017541 // Send idle notification to start a round of incremental GCs.
17542 v8::V8::IdleNotification(kShortIdlePauseInMs);
17543 // Emulate 7 page reloads.
17544 for (int i = 0; i < 7; i++) {
ulan@chromium.org57ff8812013-05-10 08:16:55 +000017545 {
17546 v8::HandleScope inner_scope(env->GetIsolate());
17547 v8::Local<v8::Context> ctx = v8::Context::New(isolate);
17548 ctx->Enter();
17549 CreateGarbageInOldSpace();
17550 ctx->Exit();
17551 }
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017552 v8::V8::ContextDisposedNotification();
17553 v8::V8::IdleNotification(kLongIdlePauseInMs);
17554 }
17555 // Create garbage and check that idle notification still collects it.
17556 CreateGarbageInOldSpace();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017557 intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017558 CHECK_GT(size_with_garbage, initial_size + MB);
17559 bool finished = false;
17560 for (int i = 0; i < 200 && !finished; i++) {
17561 finished = v8::V8::IdleNotification(kShortIdlePauseInMs);
17562 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017563 intptr_t final_size = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017564 CHECK_LT(final_size, initial_size + 1);
17565}
17566
machenbach@chromium.orgb5be0a92013-11-15 10:32:41 +000017567
17568TEST(Regress2333) {
17569 LocalContext env;
17570 for (int i = 0; i < 3; i++) {
17571 CcTest::heap()->PerformScavenge();
17572 }
17573}
17574
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017575static uint32_t* stack_limit;
17576
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017577static void GetStackLimitCallback(
17578 const v8::FunctionCallbackInfo<v8::Value>& args) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000017579 stack_limit = reinterpret_cast<uint32_t*>(
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017580 CcTest::i_isolate()->stack_guard()->real_climit());
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017581}
17582
17583
17584// Uses the address of a local variable to determine the stack top now.
17585// Given a size, returns an address that is that far from the current
17586// top of stack.
17587static uint32_t* ComputeStackLimit(uint32_t size) {
17588 uint32_t* answer = &size - (size / sizeof(size));
17589 // If the size is very large and the stack is very near the bottom of
17590 // memory then the calculation above may wrap around and give an address
17591 // that is above the (downwards-growing) stack. In that case we return
17592 // a very low address.
17593 if (answer > &size) return reinterpret_cast<uint32_t*>(sizeof(size));
17594 return answer;
17595}
17596
17597
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +000017598// We need at least 165kB for an x64 debug build with clang and ASAN.
17599static const int stack_breathing_room = 256 * i::KB;
17600
17601
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017602TEST(SetResourceConstraints) {
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +000017603 uint32_t* set_limit = ComputeStackLimit(stack_breathing_room);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017604
17605 // Set stack limit.
17606 v8::ResourceConstraints constraints;
17607 constraints.set_stack_limit(set_limit);
machenbach@chromium.org7ff76072013-11-21 09:47:43 +000017608 CHECK(v8::SetResourceConstraints(CcTest::isolate(), &constraints));
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017609
17610 // Execute a script.
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017611 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017612 v8::HandleScope scope(env->GetIsolate());
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017613 Local<v8::FunctionTemplate> fun_templ =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017614 v8::FunctionTemplate::New(env->GetIsolate(), GetStackLimitCallback);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017615 Local<Function> fun = fun_templ->GetFunction();
17616 env->Global()->Set(v8_str("get_stack_limit"), fun);
17617 CompileRun("get_stack_limit();");
17618
17619 CHECK(stack_limit == set_limit);
17620}
17621
17622
17623TEST(SetResourceConstraintsInThread) {
17624 uint32_t* set_limit;
17625 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017626 v8::Locker locker(CcTest::isolate());
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +000017627 set_limit = ComputeStackLimit(stack_breathing_room);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017628
17629 // Set stack limit.
17630 v8::ResourceConstraints constraints;
17631 constraints.set_stack_limit(set_limit);
machenbach@chromium.org7ff76072013-11-21 09:47:43 +000017632 CHECK(v8::SetResourceConstraints(CcTest::isolate(), &constraints));
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017633
17634 // Execute a script.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017635 v8::HandleScope scope(CcTest::isolate());
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017636 LocalContext env;
17637 Local<v8::FunctionTemplate> fun_templ =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017638 v8::FunctionTemplate::New(CcTest::isolate(), GetStackLimitCallback);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017639 Local<Function> fun = fun_templ->GetFunction();
17640 env->Global()->Set(v8_str("get_stack_limit"), fun);
17641 CompileRun("get_stack_limit();");
17642
17643 CHECK(stack_limit == set_limit);
17644 }
17645 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017646 v8::Locker locker(CcTest::isolate());
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017647 CHECK(stack_limit == set_limit);
17648 }
ager@chromium.org96c75b52009-08-26 09:13:16 +000017649}
ager@chromium.org3811b432009-10-28 14:53:37 +000017650
17651
17652THREADED_TEST(GetHeapStatistics) {
ager@chromium.org3811b432009-10-28 14:53:37 +000017653 LocalContext c1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017654 v8::HandleScope scope(c1->GetIsolate());
ager@chromium.org3811b432009-10-28 14:53:37 +000017655 v8::HeapStatistics heap_statistics;
ager@chromium.orgc4c92722009-11-18 14:12:51 +000017656 CHECK_EQ(static_cast<int>(heap_statistics.total_heap_size()), 0);
17657 CHECK_EQ(static_cast<int>(heap_statistics.used_heap_size()), 0);
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +000017658 c1->GetIsolate()->GetHeapStatistics(&heap_statistics);
ager@chromium.orgc4c92722009-11-18 14:12:51 +000017659 CHECK_NE(static_cast<int>(heap_statistics.total_heap_size()), 0);
17660 CHECK_NE(static_cast<int>(heap_statistics.used_heap_size()), 0);
ager@chromium.org3811b432009-10-28 14:53:37 +000017661}
17662
17663
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017664class VisitorImpl : public v8::ExternalResourceVisitor {
17665 public:
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017666 explicit VisitorImpl(TestResource** resource) {
17667 for (int i = 0; i < 4; i++) {
17668 resource_[i] = resource[i];
17669 found_resource_[i] = false;
17670 }
17671 }
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017672 virtual ~VisitorImpl() {}
17673 virtual void VisitExternalString(v8::Handle<v8::String> string) {
17674 if (!string->IsExternal()) {
17675 CHECK(string->IsExternalAscii());
17676 return;
17677 }
17678 v8::String::ExternalStringResource* resource =
17679 string->GetExternalStringResource();
17680 CHECK(resource);
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017681 for (int i = 0; i < 4; i++) {
17682 if (resource_[i] == resource) {
17683 CHECK(!found_resource_[i]);
17684 found_resource_[i] = true;
17685 }
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017686 }
17687 }
17688 void CheckVisitedResources() {
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017689 for (int i = 0; i < 4; i++) {
17690 CHECK(found_resource_[i]);
17691 }
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017692 }
17693
17694 private:
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017695 v8::String::ExternalStringResource* resource_[4];
17696 bool found_resource_[4];
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017697};
17698
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000017699
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017700TEST(VisitExternalStrings) {
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017701 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017702 v8::HandleScope scope(env->GetIsolate());
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017703 const char* string = "Some string";
17704 uint16_t* two_byte_string = AsciiToTwoByteString(string);
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017705 TestResource* resource[4];
17706 resource[0] = new TestResource(two_byte_string);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017707 v8::Local<v8::String> string0 =
17708 v8::String::NewExternal(env->GetIsolate(), resource[0]);
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017709 resource[1] = new TestResource(two_byte_string);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017710 v8::Local<v8::String> string1 =
17711 v8::String::NewExternal(env->GetIsolate(), resource[1]);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017712
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017713 // Externalized symbol.
17714 resource[2] = new TestResource(two_byte_string);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017715 v8::Local<v8::String> string2 = v8::String::NewFromUtf8(
17716 env->GetIsolate(), string, v8::String::kInternalizedString);
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017717 CHECK(string2->MakeExternal(resource[2]));
17718
17719 // Symbolized External.
17720 resource[3] = new TestResource(AsciiToTwoByteString("Some other string"));
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017721 v8::Local<v8::String> string3 =
17722 v8::String::NewExternal(env->GetIsolate(), resource[3]);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017723 CcTest::heap()->CollectAllAvailableGarbage(); // Tenure string.
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017724 // Turn into a symbol.
17725 i::Handle<i::String> string3_i = v8::Utils::OpenHandle(*string3);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017726 CHECK(!CcTest::heap()->InternalizeString(*string3_i)->IsFailure());
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +000017727 CHECK(string3_i->IsInternalizedString());
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017728
17729 // We need to add usages for string* to avoid warnings in GCC 4.7
17730 CHECK(string0->IsExternal());
ulan@chromium.org2efb9002012-01-19 15:36:35 +000017731 CHECK(string1->IsExternal());
17732 CHECK(string2->IsExternal());
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017733 CHECK(string3->IsExternal());
ulan@chromium.org2efb9002012-01-19 15:36:35 +000017734
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017735 VisitorImpl visitor(resource);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017736 v8::V8::VisitExternalResources(&visitor);
17737 visitor.CheckVisitedResources();
17738}
17739
17740
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017741TEST(ExternalStringCollectedAtTearDown) {
17742 int destroyed = 0;
17743 v8::Isolate* isolate = v8::Isolate::New();
17744 { v8::Isolate::Scope isolate_scope(isolate);
17745 v8::HandleScope handle_scope(isolate);
17746 const char* s = "One string to test them all, one string to find them.";
17747 TestAsciiResource* inscription =
17748 new TestAsciiResource(i::StrDup(s), &destroyed);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017749 v8::Local<v8::String> ring = v8::String::NewExternal(isolate, inscription);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017750 // Ring is still alive. Orcs are roaming freely across our lands.
17751 CHECK_EQ(0, destroyed);
17752 USE(ring);
17753 }
17754
17755 isolate->Dispose();
17756 // Ring has been destroyed. Free Peoples of Middle-earth Rejoice.
17757 CHECK_EQ(1, destroyed);
17758}
17759
17760
jkummerow@chromium.org113035e2013-12-13 15:13:40 +000017761TEST(ExternalInternalizedStringCollectedAtTearDown) {
17762 int destroyed = 0;
17763 v8::Isolate* isolate = v8::Isolate::New();
17764 { v8::Isolate::Scope isolate_scope(isolate);
17765 LocalContext env(isolate);
17766 v8::HandleScope handle_scope(isolate);
17767 CompileRun("var ring = 'One string to test them all';");
17768 const char* s = "One string to test them all";
17769 TestAsciiResource* inscription =
17770 new TestAsciiResource(i::StrDup(s), &destroyed);
17771 v8::Local<v8::String> ring = CompileRun("ring")->ToString();
17772 CHECK(v8::Utils::OpenHandle(*ring)->IsInternalizedString());
17773 ring->MakeExternal(inscription);
17774 // Ring is still alive. Orcs are roaming freely across our lands.
17775 CHECK_EQ(0, destroyed);
17776 USE(ring);
17777 }
17778
17779 isolate->Dispose();
17780 // Ring has been destroyed. Free Peoples of Middle-earth Rejoice.
17781 CHECK_EQ(1, destroyed);
17782}
17783
17784
17785TEST(ExternalInternalizedStringCollectedAtGC) {
17786 int destroyed = 0;
17787 { LocalContext env;
17788 v8::HandleScope handle_scope(env->GetIsolate());
17789 CompileRun("var ring = 'One string to test them all';");
17790 const char* s = "One string to test them all";
17791 TestAsciiResource* inscription =
17792 new TestAsciiResource(i::StrDup(s), &destroyed);
17793 v8::Local<v8::String> ring = CompileRun("ring")->ToString();
17794 CHECK(v8::Utils::OpenHandle(*ring)->IsInternalizedString());
17795 ring->MakeExternal(inscription);
17796 // Ring is still alive. Orcs are roaming freely across our lands.
17797 CHECK_EQ(0, destroyed);
17798 USE(ring);
17799 }
17800
17801 // Garbage collector deals swift blows to evil.
17802 CcTest::i_isolate()->compilation_cache()->Clear();
17803 CcTest::heap()->CollectAllAvailableGarbage();
17804
17805 // Ring has been destroyed. Free Peoples of Middle-earth Rejoice.
17806 CHECK_EQ(1, destroyed);
17807}
17808
17809
ager@chromium.org3811b432009-10-28 14:53:37 +000017810static double DoubleFromBits(uint64_t value) {
17811 double target;
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +000017812 i::OS::MemCopy(&target, &value, sizeof(target));
ager@chromium.org3811b432009-10-28 14:53:37 +000017813 return target;
17814}
17815
17816
17817static uint64_t DoubleToBits(double value) {
17818 uint64_t target;
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +000017819 i::OS::MemCopy(&target, &value, sizeof(target));
ager@chromium.org3811b432009-10-28 14:53:37 +000017820 return target;
17821}
17822
17823
17824static double DoubleToDateTime(double input) {
17825 double date_limit = 864e13;
ulan@chromium.org77ca49a2013-04-22 09:43:56 +000017826 if (std::isnan(input) || input < -date_limit || input > date_limit) {
ager@chromium.org3811b432009-10-28 14:53:37 +000017827 return i::OS::nan_value();
17828 }
17829 return (input < 0) ? -(floor(-input)) : floor(input);
17830}
17831
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000017832
ager@chromium.org3811b432009-10-28 14:53:37 +000017833// We don't have a consistent way to write 64-bit constants syntactically, so we
17834// split them into two 32-bit constants and combine them programmatically.
17835static double DoubleFromBits(uint32_t high_bits, uint32_t low_bits) {
17836 return DoubleFromBits((static_cast<uint64_t>(high_bits) << 32) | low_bits);
17837}
17838
17839
17840THREADED_TEST(QuietSignalingNaNs) {
ager@chromium.org3811b432009-10-28 14:53:37 +000017841 LocalContext context;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000017842 v8::Isolate* isolate = context->GetIsolate();
17843 v8::HandleScope scope(isolate);
ager@chromium.org3811b432009-10-28 14:53:37 +000017844 v8::TryCatch try_catch;
17845
17846 // Special double values.
17847 double snan = DoubleFromBits(0x7ff00000, 0x00000001);
17848 double qnan = DoubleFromBits(0x7ff80000, 0x00000000);
17849 double infinity = DoubleFromBits(0x7ff00000, 0x00000000);
17850 double max_normal = DoubleFromBits(0x7fefffff, 0xffffffffu);
17851 double min_normal = DoubleFromBits(0x00100000, 0x00000000);
17852 double max_denormal = DoubleFromBits(0x000fffff, 0xffffffffu);
17853 double min_denormal = DoubleFromBits(0x00000000, 0x00000001);
17854
17855 // Date values are capped at +/-100000000 days (times 864e5 ms per day)
17856 // on either side of the epoch.
17857 double date_limit = 864e13;
17858
17859 double test_values[] = {
17860 snan,
17861 qnan,
17862 infinity,
17863 max_normal,
17864 date_limit + 1,
17865 date_limit,
17866 min_normal,
17867 max_denormal,
17868 min_denormal,
17869 0,
17870 -0,
17871 -min_denormal,
17872 -max_denormal,
17873 -min_normal,
17874 -date_limit,
17875 -date_limit - 1,
17876 -max_normal,
17877 -infinity,
17878 -qnan,
17879 -snan
17880 };
17881 int num_test_values = 20;
17882
17883 for (int i = 0; i < num_test_values; i++) {
17884 double test_value = test_values[i];
17885
17886 // Check that Number::New preserves non-NaNs and quiets SNaNs.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000017887 v8::Handle<v8::Value> number = v8::Number::New(isolate, test_value);
ager@chromium.org3811b432009-10-28 14:53:37 +000017888 double stored_number = number->NumberValue();
ulan@chromium.org77ca49a2013-04-22 09:43:56 +000017889 if (!std::isnan(test_value)) {
ager@chromium.org3811b432009-10-28 14:53:37 +000017890 CHECK_EQ(test_value, stored_number);
17891 } else {
17892 uint64_t stored_bits = DoubleToBits(stored_number);
17893 // Check if quiet nan (bits 51..62 all set).
danno@chromium.orgc612e022011-11-10 11:38:15 +000017894#if defined(V8_TARGET_ARCH_MIPS) && !defined(USE_SIMULATOR)
17895 // Most significant fraction bit for quiet nan is set to 0
17896 // on MIPS architecture. Allowed by IEEE-754.
17897 CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
17898#else
ager@chromium.org3811b432009-10-28 14:53:37 +000017899 CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
danno@chromium.orgc612e022011-11-10 11:38:15 +000017900#endif
ager@chromium.org3811b432009-10-28 14:53:37 +000017901 }
17902
17903 // Check that Date::New preserves non-NaNs in the date range and
17904 // quiets SNaNs.
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017905 v8::Handle<v8::Value> date =
ulan@chromium.org0f13e742014-01-03 15:51:11 +000017906 v8::Date::New(isolate, test_value);
ager@chromium.org3811b432009-10-28 14:53:37 +000017907 double expected_stored_date = DoubleToDateTime(test_value);
17908 double stored_date = date->NumberValue();
ulan@chromium.org77ca49a2013-04-22 09:43:56 +000017909 if (!std::isnan(expected_stored_date)) {
ager@chromium.org3811b432009-10-28 14:53:37 +000017910 CHECK_EQ(expected_stored_date, stored_date);
17911 } else {
17912 uint64_t stored_bits = DoubleToBits(stored_date);
17913 // Check if quiet nan (bits 51..62 all set).
danno@chromium.orgc612e022011-11-10 11:38:15 +000017914#if defined(V8_TARGET_ARCH_MIPS) && !defined(USE_SIMULATOR)
17915 // Most significant fraction bit for quiet nan is set to 0
17916 // on MIPS architecture. Allowed by IEEE-754.
17917 CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
17918#else
ager@chromium.org3811b432009-10-28 14:53:37 +000017919 CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
danno@chromium.orgc612e022011-11-10 11:38:15 +000017920#endif
ager@chromium.org3811b432009-10-28 14:53:37 +000017921 }
17922 }
17923}
christian.plesner.hansen@gmail.comb9ce6372009-11-03 11:38:18 +000017924
17925
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017926static void SpaghettiIncident(
17927 const v8::FunctionCallbackInfo<v8::Value>& args) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017928 v8::HandleScope scope(args.GetIsolate());
christian.plesner.hansen@gmail.comb9ce6372009-11-03 11:38:18 +000017929 v8::TryCatch tc;
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000017930 v8::Handle<v8::String> str(args[0]->ToString());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000017931 USE(str);
christian.plesner.hansen@gmail.comb9ce6372009-11-03 11:38:18 +000017932 if (tc.HasCaught())
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017933 tc.ReThrow();
christian.plesner.hansen@gmail.comb9ce6372009-11-03 11:38:18 +000017934}
17935
17936
17937// Test that an exception can be propagated down through a spaghetti
17938// stack using ReThrow.
17939THREADED_TEST(SpaghettiStackReThrow) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017940 v8::Isolate* isolate = CcTest::isolate();
17941 v8::HandleScope scope(isolate);
christian.plesner.hansen@gmail.comb9ce6372009-11-03 11:38:18 +000017942 LocalContext context;
17943 context->Global()->Set(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017944 v8::String::NewFromUtf8(isolate, "s"),
17945 v8::FunctionTemplate::New(isolate, SpaghettiIncident)->GetFunction());
christian.plesner.hansen@gmail.comb9ce6372009-11-03 11:38:18 +000017946 v8::TryCatch try_catch;
17947 CompileRun(
17948 "var i = 0;"
17949 "var o = {"
17950 " toString: function () {"
17951 " if (i == 10) {"
17952 " throw 'Hey!';"
17953 " } else {"
17954 " i++;"
17955 " return s(o);"
17956 " }"
17957 " }"
17958 "};"
17959 "s(o);");
17960 CHECK(try_catch.HasCaught());
17961 v8::String::Utf8Value value(try_catch.Exception());
17962 CHECK_EQ(0, strcmp(*value, "Hey!"));
17963}
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000017964
17965
sgjesse@chromium.org98180592009-12-02 08:17:28 +000017966TEST(Regress528) {
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000017967 v8::V8::Initialize();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017968 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000017969 v8::HandleScope scope(isolate);
17970 v8::Local<Context> other_context;
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000017971 int gc_count;
17972
ager@chromium.org60121232009-12-03 11:25:37 +000017973 // Create a context used to keep the code from aging in the compilation
17974 // cache.
ulan@chromium.org57ff8812013-05-10 08:16:55 +000017975 other_context = Context::New(isolate);
ager@chromium.org60121232009-12-03 11:25:37 +000017976
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000017977 // Context-dependent context data creates reference from the compilation
17978 // cache to the global object.
ager@chromium.org60121232009-12-03 11:25:37 +000017979 const char* source_simple = "1";
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000017980 {
ulan@chromium.org57ff8812013-05-10 08:16:55 +000017981 v8::HandleScope scope(isolate);
17982 v8::Local<Context> context = Context::New(isolate);
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000017983
17984 context->Enter();
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017985 Local<v8::String> obj = v8::String::NewFromUtf8(isolate, "");
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000017986 context->SetEmbedderData(0, obj);
ager@chromium.org60121232009-12-03 11:25:37 +000017987 CompileRun(source_simple);
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000017988 context->Exit();
17989 }
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000017990 v8::V8::ContextDisposedNotification();
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000017991 for (gc_count = 1; gc_count < 10; gc_count++) {
ager@chromium.org60121232009-12-03 11:25:37 +000017992 other_context->Enter();
17993 CompileRun(source_simple);
17994 other_context->Exit();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017995 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org60121232009-12-03 11:25:37 +000017996 if (GetGlobalObjectsCount() == 1) break;
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000017997 }
ager@chromium.org60121232009-12-03 11:25:37 +000017998 CHECK_GE(2, gc_count);
17999 CHECK_EQ(1, GetGlobalObjectsCount());
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018000
18001 // Eval in a function creates reference from the compilation cache to the
18002 // global object.
ager@chromium.org60121232009-12-03 11:25:37 +000018003 const char* source_eval = "function f(){eval('1')}; f()";
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018004 {
ulan@chromium.org57ff8812013-05-10 08:16:55 +000018005 v8::HandleScope scope(isolate);
18006 v8::Local<Context> context = Context::New(isolate);
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018007
18008 context->Enter();
ager@chromium.org60121232009-12-03 11:25:37 +000018009 CompileRun(source_eval);
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018010 context->Exit();
18011 }
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000018012 v8::V8::ContextDisposedNotification();
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018013 for (gc_count = 1; gc_count < 10; gc_count++) {
ager@chromium.org60121232009-12-03 11:25:37 +000018014 other_context->Enter();
18015 CompileRun(source_eval);
18016 other_context->Exit();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018017 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org60121232009-12-03 11:25:37 +000018018 if (GetGlobalObjectsCount() == 1) break;
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018019 }
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +000018020 CHECK_GE(2, gc_count);
sgjesse@chromium.org98180592009-12-02 08:17:28 +000018021 CHECK_EQ(1, GetGlobalObjectsCount());
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018022
18023 // Looking up the line number for an exception creates reference from the
18024 // compilation cache to the global object.
ager@chromium.org60121232009-12-03 11:25:37 +000018025 const char* source_exception = "function f(){throw 1;} f()";
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018026 {
ulan@chromium.org57ff8812013-05-10 08:16:55 +000018027 v8::HandleScope scope(isolate);
18028 v8::Local<Context> context = Context::New(isolate);
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018029
18030 context->Enter();
18031 v8::TryCatch try_catch;
ager@chromium.org60121232009-12-03 11:25:37 +000018032 CompileRun(source_exception);
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018033 CHECK(try_catch.HasCaught());
18034 v8::Handle<v8::Message> message = try_catch.Message();
18035 CHECK(!message.IsEmpty());
18036 CHECK_EQ(1, message->GetLineNumber());
18037 context->Exit();
18038 }
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +000018039 v8::V8::ContextDisposedNotification();
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018040 for (gc_count = 1; gc_count < 10; gc_count++) {
ager@chromium.org60121232009-12-03 11:25:37 +000018041 other_context->Enter();
18042 CompileRun(source_exception);
18043 other_context->Exit();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018044 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org60121232009-12-03 11:25:37 +000018045 if (GetGlobalObjectsCount() == 1) break;
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018046 }
ager@chromium.org60121232009-12-03 11:25:37 +000018047 CHECK_GE(2, gc_count);
18048 CHECK_EQ(1, GetGlobalObjectsCount());
18049
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000018050 v8::V8::ContextDisposedNotification();
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018051}
ager@chromium.org5c838252010-02-19 08:53:10 +000018052
18053
18054THREADED_TEST(ScriptOrigin) {
ager@chromium.org5c838252010-02-19 08:53:10 +000018055 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018056 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018057 v8::ScriptOrigin origin =
18058 v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
18059 v8::Handle<v8::String> script = v8::String::NewFromUtf8(
18060 env->GetIsolate(), "function f() {}\n\nfunction g() {}");
ager@chromium.org5c838252010-02-19 08:53:10 +000018061 v8::Script::Compile(script, &origin)->Run();
18062 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018063 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
ager@chromium.org5c838252010-02-19 08:53:10 +000018064 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018065 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
ager@chromium.org5c838252010-02-19 08:53:10 +000018066
18067 v8::ScriptOrigin script_origin_f = f->GetScriptOrigin();
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000018068 CHECK_EQ("test", *v8::String::Utf8Value(script_origin_f.ResourceName()));
ager@chromium.org5c838252010-02-19 08:53:10 +000018069 CHECK_EQ(0, script_origin_f.ResourceLineOffset()->Int32Value());
18070
18071 v8::ScriptOrigin script_origin_g = g->GetScriptOrigin();
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000018072 CHECK_EQ("test", *v8::String::Utf8Value(script_origin_g.ResourceName()));
ager@chromium.org5c838252010-02-19 08:53:10 +000018073 CHECK_EQ(0, script_origin_g.ResourceLineOffset()->Int32Value());
18074}
18075
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000018076
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000018077THREADED_TEST(FunctionGetInferredName) {
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000018078 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018079 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018080 v8::ScriptOrigin origin =
18081 v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
18082 v8::Handle<v8::String> script = v8::String::NewFromUtf8(
18083 env->GetIsolate(),
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000018084 "var foo = { bar : { baz : function() {}}}; var f = foo.bar.baz;");
18085 v8::Script::Compile(script, &origin)->Run();
18086 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018087 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000018088 CHECK_EQ("foo.bar.baz", *v8::String::Utf8Value(f->GetInferredName()));
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000018089}
ager@chromium.org5c838252010-02-19 08:53:10 +000018090
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000018091
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +000018092THREADED_TEST(FunctionGetDisplayName) {
18093 LocalContext env;
18094 v8::HandleScope scope(env->GetIsolate());
18095 const char* code = "var error = false;"
18096 "function a() { this.x = 1; };"
18097 "a.displayName = 'display_a';"
18098 "var b = (function() {"
18099 " var f = function() { this.x = 2; };"
18100 " f.displayName = 'display_b';"
18101 " return f;"
18102 "})();"
18103 "var c = function() {};"
18104 "c.__defineGetter__('displayName', function() {"
18105 " error = true;"
18106 " throw new Error();"
18107 "});"
18108 "function d() {};"
18109 "d.__defineGetter__('displayName', function() {"
18110 " error = true;"
18111 " return 'wrong_display_name';"
18112 "});"
18113 "function e() {};"
18114 "e.displayName = 'wrong_display_name';"
18115 "e.__defineSetter__('displayName', function() {"
18116 " error = true;"
18117 " throw new Error();"
18118 "});"
18119 "function f() {};"
18120 "f.displayName = { 'foo': 6, toString: function() {"
18121 " error = true;"
18122 " return 'wrong_display_name';"
18123 "}};"
18124 "var g = function() {"
18125 " arguments.callee.displayName = 'set_in_runtime';"
18126 "}; g();"
18127 ;
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018128 v8::ScriptOrigin origin =
18129 v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
18130 v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), code), &origin)
18131 ->Run();
18132 v8::Local<v8::Value> error =
18133 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "error"));
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +000018134 v8::Local<v8::Function> a = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018135 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "a")));
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +000018136 v8::Local<v8::Function> b = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018137 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "b")));
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +000018138 v8::Local<v8::Function> c = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018139 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "c")));
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +000018140 v8::Local<v8::Function> d = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018141 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "d")));
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +000018142 v8::Local<v8::Function> e = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018143 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "e")));
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +000018144 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018145 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +000018146 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018147 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +000018148 CHECK_EQ(false, error->BooleanValue());
18149 CHECK_EQ("display_a", *v8::String::Utf8Value(a->GetDisplayName()));
18150 CHECK_EQ("display_b", *v8::String::Utf8Value(b->GetDisplayName()));
18151 CHECK(c->GetDisplayName()->IsUndefined());
18152 CHECK(d->GetDisplayName()->IsUndefined());
18153 CHECK(e->GetDisplayName()->IsUndefined());
18154 CHECK(f->GetDisplayName()->IsUndefined());
18155 CHECK_EQ("set_in_runtime", *v8::String::Utf8Value(g->GetDisplayName()));
18156}
18157
18158
ager@chromium.org5c838252010-02-19 08:53:10 +000018159THREADED_TEST(ScriptLineNumber) {
ager@chromium.org5c838252010-02-19 08:53:10 +000018160 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018161 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018162 v8::ScriptOrigin origin =
18163 v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
18164 v8::Handle<v8::String> script = v8::String::NewFromUtf8(
18165 env->GetIsolate(), "function f() {}\n\nfunction g() {}");
ager@chromium.org5c838252010-02-19 08:53:10 +000018166 v8::Script::Compile(script, &origin)->Run();
18167 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018168 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
ager@chromium.org5c838252010-02-19 08:53:10 +000018169 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018170 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
ager@chromium.org5c838252010-02-19 08:53:10 +000018171 CHECK_EQ(0, f->GetScriptLineNumber());
18172 CHECK_EQ(2, g->GetScriptLineNumber());
18173}
18174
18175
danno@chromium.orgc612e022011-11-10 11:38:15 +000018176THREADED_TEST(ScriptColumnNumber) {
danno@chromium.orgc612e022011-11-10 11:38:15 +000018177 LocalContext env;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018178 v8::Isolate* isolate = env->GetIsolate();
18179 v8::HandleScope scope(isolate);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018180 v8::ScriptOrigin origin =
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018181 v8::ScriptOrigin(v8::String::NewFromUtf8(isolate, "test"),
18182 v8::Integer::New(isolate, 3),
18183 v8::Integer::New(isolate, 2));
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018184 v8::Handle<v8::String> script = v8::String::NewFromUtf8(
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018185 isolate, "function foo() {}\n\n function bar() {}");
danno@chromium.orgc612e022011-11-10 11:38:15 +000018186 v8::Script::Compile(script, &origin)->Run();
18187 v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018188 env->Global()->Get(v8::String::NewFromUtf8(isolate, "foo")));
danno@chromium.orgc612e022011-11-10 11:38:15 +000018189 v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018190 env->Global()->Get(v8::String::NewFromUtf8(isolate, "bar")));
danno@chromium.orgc612e022011-11-10 11:38:15 +000018191 CHECK_EQ(14, foo->GetScriptColumnNumber());
18192 CHECK_EQ(17, bar->GetScriptColumnNumber());
18193}
18194
18195
bmeurer@chromium.orgdb783292013-10-23 06:51:00 +000018196THREADED_TEST(FunctionIsBuiltin) {
18197 LocalContext env;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018198 v8::Isolate* isolate = env->GetIsolate();
18199 v8::HandleScope scope(isolate);
bmeurer@chromium.orgdb783292013-10-23 06:51:00 +000018200 v8::Local<v8::Function> f;
18201 f = v8::Local<v8::Function>::Cast(CompileRun("Math.floor"));
18202 CHECK(f->IsBuiltin());
18203 f = v8::Local<v8::Function>::Cast(CompileRun("Object"));
18204 CHECK(f->IsBuiltin());
18205 f = v8::Local<v8::Function>::Cast(CompileRun("Object.__defineSetter__"));
18206 CHECK(f->IsBuiltin());
18207 f = v8::Local<v8::Function>::Cast(CompileRun("Array.prototype.toString"));
18208 CHECK(f->IsBuiltin());
18209 f = v8::Local<v8::Function>::Cast(CompileRun("function a() {}; a;"));
18210 CHECK(!f->IsBuiltin());
18211}
18212
18213
danno@chromium.orgc612e022011-11-10 11:38:15 +000018214THREADED_TEST(FunctionGetScriptId) {
danno@chromium.orgc612e022011-11-10 11:38:15 +000018215 LocalContext env;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018216 v8::Isolate* isolate = env->GetIsolate();
18217 v8::HandleScope scope(isolate);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018218 v8::ScriptOrigin origin =
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018219 v8::ScriptOrigin(v8::String::NewFromUtf8(isolate, "test"),
18220 v8::Integer::New(isolate, 3),
18221 v8::Integer::New(isolate, 2));
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018222 v8::Handle<v8::String> scriptSource = v8::String::NewFromUtf8(
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018223 isolate, "function foo() {}\n\n function bar() {}");
danno@chromium.orgc612e022011-11-10 11:38:15 +000018224 v8::Local<v8::Script> script(v8::Script::Compile(scriptSource, &origin));
18225 script->Run();
18226 v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018227 env->Global()->Get(v8::String::NewFromUtf8(isolate, "foo")));
danno@chromium.orgc612e022011-11-10 11:38:15 +000018228 v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018229 env->Global()->Get(v8::String::NewFromUtf8(isolate, "bar")));
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018230 CHECK_EQ(script->GetId(), foo->ScriptId());
18231 CHECK_EQ(script->GetId(), bar->ScriptId());
danno@chromium.orgc612e022011-11-10 11:38:15 +000018232}
18233
18234
yangguo@chromium.org49546742013-12-23 16:17:49 +000018235THREADED_TEST(FunctionGetBoundFunction) {
18236 LocalContext env;
18237 v8::HandleScope scope(env->GetIsolate());
18238 v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::NewFromUtf8(
18239 env->GetIsolate(), "test"));
18240 v8::Handle<v8::String> script = v8::String::NewFromUtf8(
18241 env->GetIsolate(),
18242 "var a = new Object();\n"
18243 "a.x = 1;\n"
18244 "function f () { return this.x };\n"
18245 "var g = f.bind(a);\n"
18246 "var b = g();");
18247 v8::Script::Compile(script, &origin)->Run();
18248 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
18249 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
18250 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
18251 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
18252 CHECK(g->GetBoundFunction()->IsFunction());
18253 Local<v8::Function> original_function = Local<v8::Function>::Cast(
18254 g->GetBoundFunction());
18255 CHECK_EQ(f->GetName(), original_function->GetName());
18256 CHECK_EQ(f->GetScriptLineNumber(), original_function->GetScriptLineNumber());
18257 CHECK_EQ(f->GetScriptColumnNumber(),
18258 original_function->GetScriptColumnNumber());
18259}
18260
18261
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018262static void GetterWhichReturns42(
18263 Local<String> name,
18264 const v8::PropertyCallbackInfo<v8::Value>& info) {
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000018265 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
18266 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018267 info.GetReturnValue().Set(v8_num(42));
ager@chromium.org5c838252010-02-19 08:53:10 +000018268}
18269
18270
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018271static void SetterWhichSetsYOnThisTo23(
18272 Local<String> name,
18273 Local<Value> value,
18274 const v8::PropertyCallbackInfo<void>& info) {
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000018275 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
18276 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
ager@chromium.org5c838252010-02-19 08:53:10 +000018277 info.This()->Set(v8_str("y"), v8_num(23));
18278}
18279
18280
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018281void FooGetInterceptor(Local<String> name,
18282 const v8::PropertyCallbackInfo<v8::Value>& info) {
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000018283 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
18284 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018285 if (!name->Equals(v8_str("foo"))) return;
18286 info.GetReturnValue().Set(v8_num(42));
erik.corry@gmail.com88767242012-08-08 14:43:45 +000018287}
18288
18289
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018290void FooSetInterceptor(Local<String> name,
18291 Local<Value> value,
18292 const v8::PropertyCallbackInfo<v8::Value>& info) {
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000018293 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
18294 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018295 if (!name->Equals(v8_str("foo"))) return;
erik.corry@gmail.com88767242012-08-08 14:43:45 +000018296 info.This()->Set(v8_str("y"), v8_num(23));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018297 info.GetReturnValue().Set(v8_num(23));
erik.corry@gmail.com88767242012-08-08 14:43:45 +000018298}
18299
18300
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000018301TEST(SetterOnConstructorPrototype) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000018302 v8::Isolate* isolate = CcTest::isolate();
18303 v8::HandleScope scope(isolate);
18304 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +000018305 templ->SetAccessor(v8_str("x"),
18306 GetterWhichReturns42,
18307 SetterWhichSetsYOnThisTo23);
18308 LocalContext context;
18309 context->Global()->Set(v8_str("P"), templ->NewInstance());
18310 CompileRun("function C1() {"
18311 " this.x = 23;"
18312 "};"
18313 "C1.prototype = P;"
18314 "function C2() {"
18315 " this.x = 23"
18316 "};"
18317 "C2.prototype = { };"
18318 "C2.prototype.__proto__ = P;");
18319
18320 v8::Local<v8::Script> script;
18321 script = v8::Script::Compile(v8_str("new C1();"));
18322 for (int i = 0; i < 10; i++) {
18323 v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
18324 CHECK_EQ(42, c1->Get(v8_str("x"))->Int32Value());
18325 CHECK_EQ(23, c1->Get(v8_str("y"))->Int32Value());
18326 }
18327
18328 script = v8::Script::Compile(v8_str("new C2();"));
18329 for (int i = 0; i < 10; i++) {
18330 v8::Handle<v8::Object> c2 = v8::Handle<v8::Object>::Cast(script->Run());
18331 CHECK_EQ(42, c2->Get(v8_str("x"))->Int32Value());
18332 CHECK_EQ(23, c2->Get(v8_str("y"))->Int32Value());
18333 }
18334}
18335
18336
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018337static void NamedPropertyGetterWhichReturns42(
18338 Local<String> name,
18339 const v8::PropertyCallbackInfo<v8::Value>& info) {
18340 info.GetReturnValue().Set(v8_num(42));
ager@chromium.org5c838252010-02-19 08:53:10 +000018341}
18342
18343
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018344static void NamedPropertySetterWhichSetsYOnThisTo23(
18345 Local<String> name,
18346 Local<Value> value,
18347 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.org5c838252010-02-19 08:53:10 +000018348 if (name->Equals(v8_str("x"))) {
18349 info.This()->Set(v8_str("y"), v8_num(23));
18350 }
ager@chromium.org5c838252010-02-19 08:53:10 +000018351}
18352
18353
18354THREADED_TEST(InterceptorOnConstructorPrototype) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000018355 v8::Isolate* isolate = CcTest::isolate();
18356 v8::HandleScope scope(isolate);
18357 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +000018358 templ->SetNamedPropertyHandler(NamedPropertyGetterWhichReturns42,
18359 NamedPropertySetterWhichSetsYOnThisTo23);
18360 LocalContext context;
18361 context->Global()->Set(v8_str("P"), templ->NewInstance());
18362 CompileRun("function C1() {"
18363 " this.x = 23;"
18364 "};"
18365 "C1.prototype = P;"
18366 "function C2() {"
18367 " this.x = 23"
18368 "};"
18369 "C2.prototype = { };"
18370 "C2.prototype.__proto__ = P;");
18371
18372 v8::Local<v8::Script> script;
18373 script = v8::Script::Compile(v8_str("new C1();"));
18374 for (int i = 0; i < 10; i++) {
18375 v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
18376 CHECK_EQ(23, c1->Get(v8_str("x"))->Int32Value());
18377 CHECK_EQ(42, c1->Get(v8_str("y"))->Int32Value());
18378 }
18379
18380 script = v8::Script::Compile(v8_str("new C2();"));
18381 for (int i = 0; i < 10; i++) {
18382 v8::Handle<v8::Object> c2 = v8::Handle<v8::Object>::Cast(script->Run());
18383 CHECK_EQ(23, c2->Get(v8_str("x"))->Int32Value());
18384 CHECK_EQ(42, c2->Get(v8_str("y"))->Int32Value());
18385 }
18386}
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000018387
18388
danno@chromium.orgf005df62013-04-30 16:36:45 +000018389TEST(Regress618) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000018390 const char* source = "function C1() {"
18391 " this.x = 23;"
18392 "};"
18393 "C1.prototype = P;";
18394
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000018395 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000018396 v8::Isolate* isolate = context->GetIsolate();
18397 v8::HandleScope scope(isolate);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000018398 v8::Local<v8::Script> script;
18399
18400 // Use a simple object as prototype.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000018401 v8::Local<v8::Object> prototype = v8::Object::New(isolate);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000018402 prototype->Set(v8_str("y"), v8_num(42));
18403 context->Global()->Set(v8_str("P"), prototype);
18404
18405 // This compile will add the code to the compilation cache.
18406 CompileRun(source);
18407
18408 script = v8::Script::Compile(v8_str("new C1();"));
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +000018409 // Allow enough iterations for the inobject slack tracking logic
18410 // to finalize instance size and install the fast construct stub.
18411 for (int i = 0; i < 256; i++) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000018412 v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
18413 CHECK_EQ(23, c1->Get(v8_str("x"))->Int32Value());
18414 CHECK_EQ(42, c1->Get(v8_str("y"))->Int32Value());
18415 }
18416
18417 // Use an API object with accessors as prototype.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000018418 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000018419 templ->SetAccessor(v8_str("x"),
18420 GetterWhichReturns42,
18421 SetterWhichSetsYOnThisTo23);
18422 context->Global()->Set(v8_str("P"), templ->NewInstance());
18423
18424 // This compile will get the code from the compilation cache.
18425 CompileRun(source);
18426
18427 script = v8::Script::Compile(v8_str("new C1();"));
18428 for (int i = 0; i < 10; i++) {
18429 v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
18430 CHECK_EQ(42, c1->Get(v8_str("x"))->Int32Value());
18431 CHECK_EQ(23, c1->Get(v8_str("y"))->Int32Value());
18432 }
18433}
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018434
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018435v8::Isolate* gc_callbacks_isolate = NULL;
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018436int prologue_call_count = 0;
18437int epilogue_call_count = 0;
18438int prologue_call_count_second = 0;
18439int epilogue_call_count_second = 0;
18440
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018441void PrologueCallback(v8::GCType, v8::GCCallbackFlags flags) {
18442 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018443 ++prologue_call_count;
18444}
18445
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000018446
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018447void PrologueCallback(v8::Isolate* isolate,
18448 v8::GCType,
18449 v8::GCCallbackFlags flags) {
18450 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
18451 CHECK_EQ(gc_callbacks_isolate, isolate);
18452 ++prologue_call_count;
18453}
18454
18455
18456void EpilogueCallback(v8::GCType, v8::GCCallbackFlags flags) {
18457 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018458 ++epilogue_call_count;
18459}
18460
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000018461
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018462void EpilogueCallback(v8::Isolate* isolate,
18463 v8::GCType,
18464 v8::GCCallbackFlags flags) {
18465 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
18466 CHECK_EQ(gc_callbacks_isolate, isolate);
18467 ++epilogue_call_count;
18468}
18469
18470
18471void PrologueCallbackSecond(v8::GCType, v8::GCCallbackFlags flags) {
18472 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018473 ++prologue_call_count_second;
18474}
18475
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000018476
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018477void PrologueCallbackSecond(v8::Isolate* isolate,
18478 v8::GCType,
18479 v8::GCCallbackFlags flags) {
18480 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
18481 CHECK_EQ(gc_callbacks_isolate, isolate);
18482 ++prologue_call_count_second;
18483}
18484
18485
18486void EpilogueCallbackSecond(v8::GCType, v8::GCCallbackFlags flags) {
18487 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018488 ++epilogue_call_count_second;
18489}
18490
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000018491
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018492void EpilogueCallbackSecond(v8::Isolate* isolate,
18493 v8::GCType,
18494 v8::GCCallbackFlags flags) {
18495 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
18496 CHECK_EQ(gc_callbacks_isolate, isolate);
18497 ++epilogue_call_count_second;
18498}
18499
18500
18501TEST(GCCallbacksOld) {
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018502 LocalContext context;
18503
18504 v8::V8::AddGCPrologueCallback(PrologueCallback);
18505 v8::V8::AddGCEpilogueCallback(EpilogueCallback);
18506 CHECK_EQ(0, prologue_call_count);
18507 CHECK_EQ(0, epilogue_call_count);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018508 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018509 CHECK_EQ(1, prologue_call_count);
18510 CHECK_EQ(1, epilogue_call_count);
18511 v8::V8::AddGCPrologueCallback(PrologueCallbackSecond);
18512 v8::V8::AddGCEpilogueCallback(EpilogueCallbackSecond);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018513 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018514 CHECK_EQ(2, prologue_call_count);
18515 CHECK_EQ(2, epilogue_call_count);
18516 CHECK_EQ(1, prologue_call_count_second);
18517 CHECK_EQ(1, epilogue_call_count_second);
18518 v8::V8::RemoveGCPrologueCallback(PrologueCallback);
18519 v8::V8::RemoveGCEpilogueCallback(EpilogueCallback);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018520 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018521 CHECK_EQ(2, prologue_call_count);
18522 CHECK_EQ(2, epilogue_call_count);
18523 CHECK_EQ(2, prologue_call_count_second);
18524 CHECK_EQ(2, epilogue_call_count_second);
18525 v8::V8::RemoveGCPrologueCallback(PrologueCallbackSecond);
18526 v8::V8::RemoveGCEpilogueCallback(EpilogueCallbackSecond);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018527 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
18528 CHECK_EQ(2, prologue_call_count);
18529 CHECK_EQ(2, epilogue_call_count);
18530 CHECK_EQ(2, prologue_call_count_second);
18531 CHECK_EQ(2, epilogue_call_count_second);
18532}
18533
18534
18535TEST(GCCallbacks) {
18536 LocalContext context;
18537 v8::Isolate* isolate = context->GetIsolate();
18538 gc_callbacks_isolate = isolate;
18539 isolate->AddGCPrologueCallback(PrologueCallback);
18540 isolate->AddGCEpilogueCallback(EpilogueCallback);
18541 CHECK_EQ(0, prologue_call_count);
18542 CHECK_EQ(0, epilogue_call_count);
18543 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
18544 CHECK_EQ(1, prologue_call_count);
18545 CHECK_EQ(1, epilogue_call_count);
18546 isolate->AddGCPrologueCallback(PrologueCallbackSecond);
18547 isolate->AddGCEpilogueCallback(EpilogueCallbackSecond);
18548 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
18549 CHECK_EQ(2, prologue_call_count);
18550 CHECK_EQ(2, epilogue_call_count);
18551 CHECK_EQ(1, prologue_call_count_second);
18552 CHECK_EQ(1, epilogue_call_count_second);
18553 isolate->RemoveGCPrologueCallback(PrologueCallback);
18554 isolate->RemoveGCEpilogueCallback(EpilogueCallback);
18555 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
18556 CHECK_EQ(2, prologue_call_count);
18557 CHECK_EQ(2, epilogue_call_count);
18558 CHECK_EQ(2, prologue_call_count_second);
18559 CHECK_EQ(2, epilogue_call_count_second);
18560 isolate->RemoveGCPrologueCallback(PrologueCallbackSecond);
18561 isolate->RemoveGCEpilogueCallback(EpilogueCallbackSecond);
18562 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018563 CHECK_EQ(2, prologue_call_count);
18564 CHECK_EQ(2, epilogue_call_count);
18565 CHECK_EQ(2, prologue_call_count_second);
18566 CHECK_EQ(2, epilogue_call_count_second);
18567}
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018568
18569
18570THREADED_TEST(AddToJSFunctionResultCache) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018571 i::FLAG_stress_compaction = false;
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018572 i::FLAG_allow_natives_syntax = true;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018573 v8::HandleScope scope(CcTest::isolate());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018574
18575 LocalContext context;
18576
18577 const char* code =
18578 "(function() {"
18579 " var key0 = 'a';"
18580 " var key1 = 'b';"
18581 " var r0 = %_GetFromCache(0, key0);"
18582 " var r1 = %_GetFromCache(0, key1);"
18583 " var r0_ = %_GetFromCache(0, key0);"
18584 " if (r0 !== r0_)"
18585 " return 'Different results for ' + key0 + ': ' + r0 + ' vs. ' + r0_;"
18586 " var r1_ = %_GetFromCache(0, key1);"
18587 " if (r1 !== r1_)"
18588 " return 'Different results for ' + key1 + ': ' + r1 + ' vs. ' + r1_;"
18589 " return 'PASSED';"
18590 "})()";
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018591 CcTest::heap()->ClearJSFunctionResultCaches();
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018592 ExpectString(code, "PASSED");
18593}
18594
18595
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018596THREADED_TEST(FillJSFunctionResultCache) {
18597 i::FLAG_allow_natives_syntax = true;
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018598 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018599 v8::HandleScope scope(context->GetIsolate());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018600
18601 const char* code =
18602 "(function() {"
18603 " var k = 'a';"
18604 " var r = %_GetFromCache(0, k);"
18605 " for (var i = 0; i < 16; i++) {"
18606 " %_GetFromCache(0, 'a' + i);"
18607 " };"
18608 " if (r === %_GetFromCache(0, k))"
18609 " return 'FAILED: k0CacheSize is too small';"
18610 " return 'PASSED';"
18611 "})()";
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018612 CcTest::heap()->ClearJSFunctionResultCaches();
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018613 ExpectString(code, "PASSED");
18614}
18615
18616
18617THREADED_TEST(RoundRobinGetFromCache) {
18618 i::FLAG_allow_natives_syntax = true;
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018619 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018620 v8::HandleScope scope(context->GetIsolate());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018621
18622 const char* code =
18623 "(function() {"
18624 " var keys = [];"
18625 " for (var i = 0; i < 16; i++) keys.push(i);"
18626 " var values = [];"
18627 " for (var i = 0; i < 16; i++) values[i] = %_GetFromCache(0, keys[i]);"
18628 " for (var i = 0; i < 16; i++) {"
18629 " var v = %_GetFromCache(0, keys[i]);"
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000018630 " if (v.toString() !== values[i].toString())"
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018631 " return 'Wrong value for ' + "
18632 " keys[i] + ': ' + v + ' vs. ' + values[i];"
18633 " };"
18634 " return 'PASSED';"
18635 "})()";
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018636 CcTest::heap()->ClearJSFunctionResultCaches();
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018637 ExpectString(code, "PASSED");
18638}
18639
18640
18641THREADED_TEST(ReverseGetFromCache) {
18642 i::FLAG_allow_natives_syntax = true;
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018643 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018644 v8::HandleScope scope(context->GetIsolate());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018645
18646 const char* code =
18647 "(function() {"
18648 " var keys = [];"
18649 " for (var i = 0; i < 16; i++) keys.push(i);"
18650 " var values = [];"
18651 " for (var i = 0; i < 16; i++) values[i] = %_GetFromCache(0, keys[i]);"
18652 " for (var i = 15; i >= 16; i--) {"
18653 " var v = %_GetFromCache(0, keys[i]);"
18654 " if (v !== values[i])"
18655 " return 'Wrong value for ' + "
18656 " keys[i] + ': ' + v + ' vs. ' + values[i];"
18657 " };"
18658 " return 'PASSED';"
18659 "})()";
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018660 CcTest::heap()->ClearJSFunctionResultCaches();
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018661 ExpectString(code, "PASSED");
18662}
18663
18664
18665THREADED_TEST(TestEviction) {
18666 i::FLAG_allow_natives_syntax = true;
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018667 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018668 v8::HandleScope scope(context->GetIsolate());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018669
18670 const char* code =
18671 "(function() {"
18672 " for (var i = 0; i < 2*16; i++) {"
18673 " %_GetFromCache(0, 'a' + i);"
18674 " };"
18675 " return 'PASSED';"
18676 "})()";
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018677 CcTest::heap()->ClearJSFunctionResultCaches();
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018678 ExpectString(code, "PASSED");
18679}
lrn@chromium.org32d961d2010-06-30 09:09:34 +000018680
18681
18682THREADED_TEST(TwoByteStringInAsciiCons) {
18683 // See Chromium issue 47824.
lrn@chromium.org32d961d2010-06-30 09:09:34 +000018684 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018685 v8::HandleScope scope(context->GetIsolate());
18686
lrn@chromium.org32d961d2010-06-30 09:09:34 +000018687 const char* init_code =
18688 "var str1 = 'abelspendabel';"
18689 "var str2 = str1 + str1 + str1;"
18690 "str2;";
18691 Local<Value> result = CompileRun(init_code);
18692
ricow@chromium.orgddd545c2011-08-24 12:02:41 +000018693 Local<Value> indexof = CompileRun("str2.indexOf('els')");
18694 Local<Value> lastindexof = CompileRun("str2.lastIndexOf('dab')");
18695
lrn@chromium.org32d961d2010-06-30 09:09:34 +000018696 CHECK(result->IsString());
18697 i::Handle<i::String> string = v8::Utils::OpenHandle(String::Cast(*result));
18698 int length = string->length();
ulan@chromium.org8e8d8822012-11-23 14:36:46 +000018699 CHECK(string->IsOneByteRepresentation());
lrn@chromium.org32d961d2010-06-30 09:09:34 +000018700
18701 FlattenString(string);
18702 i::Handle<i::String> flat_string = FlattenGetString(string);
18703
ulan@chromium.org8e8d8822012-11-23 14:36:46 +000018704 CHECK(string->IsOneByteRepresentation());
18705 CHECK(flat_string->IsOneByteRepresentation());
lrn@chromium.org32d961d2010-06-30 09:09:34 +000018706
18707 // Create external resource.
18708 uint16_t* uc16_buffer = new uint16_t[length + 1];
18709
18710 i::String::WriteToFlat(*flat_string, uc16_buffer, 0, length);
18711 uc16_buffer[length] = 0;
18712
18713 TestResource resource(uc16_buffer);
18714
18715 flat_string->MakeExternal(&resource);
18716
18717 CHECK(flat_string->IsTwoByteRepresentation());
18718
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +000018719 // If the cons string has been short-circuited, skip the following checks.
18720 if (!string.is_identical_to(flat_string)) {
18721 // At this point, we should have a Cons string which is flat and ASCII,
18722 // with a first half that is a two-byte string (although it only contains
18723 // ASCII characters). This is a valid sequence of steps, and it can happen
18724 // in real pages.
18725 CHECK(string->IsOneByteRepresentation());
18726 i::ConsString* cons = i::ConsString::cast(*string);
18727 CHECK_EQ(0, cons->second()->length());
18728 CHECK(cons->first()->IsTwoByteRepresentation());
18729 }
lrn@chromium.org32d961d2010-06-30 09:09:34 +000018730
18731 // Check that some string operations work.
18732
18733 // Atom RegExp.
18734 Local<Value> reresult = CompileRun("str2.match(/abel/g).length;");
18735 CHECK_EQ(6, reresult->Int32Value());
18736
18737 // Nonatom RegExp.
18738 reresult = CompileRun("str2.match(/abe./g).length;");
18739 CHECK_EQ(6, reresult->Int32Value());
18740
18741 reresult = CompileRun("str2.search(/bel/g);");
18742 CHECK_EQ(1, reresult->Int32Value());
18743
18744 reresult = CompileRun("str2.search(/be./g);");
18745 CHECK_EQ(1, reresult->Int32Value());
18746
18747 ExpectTrue("/bel/g.test(str2);");
18748
18749 ExpectTrue("/be./g.test(str2);");
18750
18751 reresult = CompileRun("/bel/g.exec(str2);");
18752 CHECK(!reresult->IsNull());
18753
18754 reresult = CompileRun("/be./g.exec(str2);");
18755 CHECK(!reresult->IsNull());
18756
18757 ExpectString("str2.substring(2, 10);", "elspenda");
18758
18759 ExpectString("str2.substring(2, 20);", "elspendabelabelspe");
18760
18761 ExpectString("str2.charAt(2);", "e");
18762
ricow@chromium.orgddd545c2011-08-24 12:02:41 +000018763 ExpectObject("str2.indexOf('els');", indexof);
18764
18765 ExpectObject("str2.lastIndexOf('dab');", lastindexof);
18766
lrn@chromium.org32d961d2010-06-30 09:09:34 +000018767 reresult = CompileRun("str2.charCodeAt(2);");
18768 CHECK_EQ(static_cast<int32_t>('e'), reresult->Int32Value());
18769}
ager@chromium.orgea4f62e2010-08-16 16:28:43 +000018770
18771
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000018772TEST(ContainsOnlyOneByte) {
18773 v8::V8::Initialize();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018774 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000018775 v8::HandleScope scope(isolate);
18776 // Make a buffer long enough that it won't automatically be converted.
verwaest@chromium.org8a00e822013-06-10 15:11:22 +000018777 const int length = 512;
18778 // Ensure word aligned assignment.
18779 const int aligned_length = length*sizeof(uintptr_t)/sizeof(uint16_t);
18780 i::SmartArrayPointer<uintptr_t>
18781 aligned_contents(new uintptr_t[aligned_length]);
machenbach@chromium.orgafbdadc2013-12-09 16:12:18 +000018782 uint16_t* string_contents =
18783 reinterpret_cast<uint16_t*>(aligned_contents.get());
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000018784 // Set to contain only one byte.
18785 for (int i = 0; i < length-1; i++) {
18786 string_contents[i] = 0x41;
18787 }
18788 string_contents[length-1] = 0;
18789 // Simple case.
18790 Handle<String> string;
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000018791 string = String::NewExternal(isolate, new TestResource(string_contents));
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000018792 CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
18793 // Counter example.
verwaest@chromium.org8a00e822013-06-10 15:11:22 +000018794 string = String::NewFromTwoByte(isolate, string_contents);
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000018795 CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
18796 // Test left right and balanced cons strings.
18797 Handle<String> base = String::NewFromUtf8(isolate, "a");
18798 Handle<String> left = base;
18799 Handle<String> right = base;
18800 for (int i = 0; i < 1000; i++) {
18801 left = String::Concat(base, left);
18802 right = String::Concat(right, base);
18803 }
18804 Handle<String> balanced = String::Concat(left, base);
18805 balanced = String::Concat(balanced, right);
18806 Handle<String> cons_strings[] = {left, balanced, right};
18807 Handle<String> two_byte =
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000018808 String::NewExternal(isolate, new TestResource(string_contents));
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000018809 for (size_t i = 0; i < ARRAY_SIZE(cons_strings); i++) {
18810 // Base assumptions.
18811 string = cons_strings[i];
18812 CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
18813 // Test left and right concatentation.
18814 string = String::Concat(two_byte, cons_strings[i]);
18815 CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
18816 string = String::Concat(cons_strings[i], two_byte);
18817 CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
18818 }
verwaest@chromium.org8a00e822013-06-10 15:11:22 +000018819 // Set bits in different positions
18820 // for strings of different lengths and alignments.
18821 for (int alignment = 0; alignment < 7; alignment++) {
18822 for (int size = 2; alignment + size < length; size *= 2) {
18823 int zero_offset = size + alignment;
18824 string_contents[zero_offset] = 0;
18825 for (int i = 0; i < size; i++) {
18826 int shift = 8 + (i % 7);
18827 string_contents[alignment + i] = 1 << shift;
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000018828 string = String::NewExternal(
18829 isolate, new TestResource(string_contents + alignment));
verwaest@chromium.org8a00e822013-06-10 15:11:22 +000018830 CHECK_EQ(size, string->Length());
18831 CHECK(!string->ContainsOnlyOneByte());
18832 string_contents[alignment + i] = 0x41;
18833 }
18834 string_contents[zero_offset] = 0x41;
18835 }
18836 }
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000018837}
18838
18839
ager@chromium.orgea4f62e2010-08-16 16:28:43 +000018840// Failed access check callback that performs a GC on each invocation.
18841void FailedAccessCheckCallbackGC(Local<v8::Object> target,
18842 v8::AccessType type,
18843 Local<v8::Value> data) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018844 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.orgea4f62e2010-08-16 16:28:43 +000018845}
18846
18847
18848TEST(GCInFailedAccessCheckCallback) {
18849 // Install a failed access check callback that performs a GC on each
18850 // invocation. Then force the callback to be called from va
18851
18852 v8::V8::Initialize();
18853 v8::V8::SetFailedAccessCheckCallbackFunction(&FailedAccessCheckCallbackGC);
18854
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000018855 v8::Isolate* isolate = CcTest::isolate();
18856 v8::HandleScope scope(isolate);
ager@chromium.orgea4f62e2010-08-16 16:28:43 +000018857
18858 // Create an ObjectTemplate for global objects and install access
18859 // check callbacks that will block access.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000018860 v8::Handle<v8::ObjectTemplate> global_template =
18861 v8::ObjectTemplate::New(isolate);
ager@chromium.orgea4f62e2010-08-16 16:28:43 +000018862 global_template->SetAccessCheckCallbacks(NamedGetAccessBlocker,
18863 IndexedGetAccessBlocker,
18864 v8::Handle<v8::Value>(),
18865 false);
18866
18867 // Create a context and set an x property on it's global object.
18868 LocalContext context0(NULL, global_template);
18869 context0->Global()->Set(v8_str("x"), v8_num(42));
18870 v8::Handle<v8::Object> global0 = context0->Global();
18871
18872 // Create a context with a different security token so that the
18873 // failed access check callback will be called on each access.
18874 LocalContext context1(NULL, global_template);
18875 context1->Global()->Set(v8_str("other"), global0);
18876
18877 // Get property with failed access check.
18878 ExpectUndefined("other.x");
18879
18880 // Get element with failed access check.
18881 ExpectUndefined("other[0]");
18882
18883 // Set property with failed access check.
18884 v8::Handle<v8::Value> result = CompileRun("other.x = new Object()");
18885 CHECK(result->IsObject());
18886
18887 // Set element with failed access check.
18888 result = CompileRun("other[0] = new Object()");
18889 CHECK(result->IsObject());
18890
18891 // Get property attribute with failed access check.
18892 ExpectFalse("\'x\' in other");
18893
18894 // Get property attribute for element with failed access check.
18895 ExpectFalse("0 in other");
18896
18897 // Delete property.
18898 ExpectFalse("delete other.x");
18899
18900 // Delete element.
18901 CHECK_EQ(false, global0->Delete(0));
18902
18903 // DefineAccessor.
18904 CHECK_EQ(false,
18905 global0->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("x")));
18906
18907 // Define JavaScript accessor.
18908 ExpectUndefined("Object.prototype.__defineGetter__.call("
18909 " other, \'x\', function() { return 42; })");
18910
18911 // LookupAccessor.
18912 ExpectUndefined("Object.prototype.__lookupGetter__.call("
18913 " other, \'x\')");
18914
18915 // HasLocalElement.
18916 ExpectFalse("Object.prototype.hasOwnProperty.call(other, \'0\')");
18917
18918 CHECK_EQ(false, global0->HasRealIndexedProperty(0));
18919 CHECK_EQ(false, global0->HasRealNamedProperty(v8_str("x")));
18920 CHECK_EQ(false, global0->HasRealNamedCallbackProperty(v8_str("x")));
18921
18922 // Reset the failed access check callback so it does not influence
18923 // the other tests.
18924 v8::V8::SetFailedAccessCheckCallbackFunction(NULL);
18925}
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000018926
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000018927
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000018928TEST(IsolateNewDispose) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018929 v8::Isolate* current_isolate = CcTest::isolate();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000018930 v8::Isolate* isolate = v8::Isolate::New();
18931 CHECK(isolate != NULL);
18932 CHECK(!reinterpret_cast<i::Isolate*>(isolate)->IsDefaultIsolate());
18933 CHECK(current_isolate != isolate);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018934 CHECK(current_isolate == CcTest::isolate());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000018935
18936 v8::V8::SetFatalErrorHandler(StoringErrorCallback);
18937 last_location = last_message = NULL;
18938 isolate->Dispose();
18939 CHECK_EQ(last_location, NULL);
18940 CHECK_EQ(last_message, NULL);
18941}
18942
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000018943
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018944UNINITIALIZED_TEST(DisposeIsolateWhenInUse) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000018945 v8::Isolate* isolate = v8::Isolate::New();
18946 CHECK(isolate);
18947 isolate->Enter();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018948 v8::HandleScope scope(isolate);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018949 LocalContext context(isolate);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000018950 // Run something in this isolate.
18951 ExpectTrue("true");
18952 v8::V8::SetFatalErrorHandler(StoringErrorCallback);
18953 last_location = last_message = NULL;
18954 // Still entered, should fail.
18955 isolate->Dispose();
18956 CHECK_NE(last_location, NULL);
18957 CHECK_NE(last_message, NULL);
18958}
18959
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000018960
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000018961TEST(RunTwoIsolatesOnSingleThread) {
18962 // Run isolate 1.
18963 v8::Isolate* isolate1 = v8::Isolate::New();
18964 isolate1->Enter();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000018965 v8::Persistent<v8::Context> context1;
18966 {
18967 v8::HandleScope scope(isolate1);
18968 context1.Reset(isolate1, Context::New(isolate1));
18969 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000018970
18971 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018972 v8::HandleScope scope(isolate1);
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000018973 v8::Local<v8::Context> context =
18974 v8::Local<v8::Context>::New(isolate1, context1);
18975 v8::Context::Scope context_scope(context);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000018976 // Run something in new isolate.
18977 CompileRun("var foo = 'isolate 1';");
18978 ExpectString("function f() { return foo; }; f()", "isolate 1");
18979 }
18980
18981 // Run isolate 2.
18982 v8::Isolate* isolate2 = v8::Isolate::New();
18983 v8::Persistent<v8::Context> context2;
18984
18985 {
18986 v8::Isolate::Scope iscope(isolate2);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018987 v8::HandleScope scope(isolate2);
ulan@chromium.org57ff8812013-05-10 08:16:55 +000018988 context2.Reset(isolate2, Context::New(isolate2));
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000018989 v8::Local<v8::Context> context =
18990 v8::Local<v8::Context>::New(isolate2, context2);
18991 v8::Context::Scope context_scope(context);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000018992
18993 // Run something in new isolate.
18994 CompileRun("var foo = 'isolate 2';");
18995 ExpectString("function f() { return foo; }; f()", "isolate 2");
18996 }
18997
18998 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018999 v8::HandleScope scope(isolate1);
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000019000 v8::Local<v8::Context> context =
19001 v8::Local<v8::Context>::New(isolate1, context1);
19002 v8::Context::Scope context_scope(context);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019003 // Now again in isolate 1
19004 ExpectString("function f() { return foo; }; f()", "isolate 1");
19005 }
19006
19007 isolate1->Exit();
19008
19009 // Run some stuff in default isolate.
ulan@chromium.org57ff8812013-05-10 08:16:55 +000019010 v8::Persistent<v8::Context> context_default;
19011 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019012 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000019013 v8::Isolate::Scope iscope(isolate);
19014 v8::HandleScope scope(isolate);
19015 context_default.Reset(isolate, Context::New(isolate));
19016 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019017
19018 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019019 v8::HandleScope scope(CcTest::isolate());
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000019020 v8::Local<v8::Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019021 v8::Local<v8::Context>::New(CcTest::isolate(), context_default);
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000019022 v8::Context::Scope context_scope(context);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019023 // Variables in other isolates should be not available, verify there
19024 // is an exception.
19025 ExpectTrue("function f() {"
19026 " try {"
19027 " foo;"
19028 " return false;"
19029 " } catch(e) {"
19030 " return true;"
19031 " }"
19032 "};"
19033 "var isDefaultIsolate = true;"
19034 "f()");
19035 }
19036
19037 isolate1->Enter();
19038
19039 {
19040 v8::Isolate::Scope iscope(isolate2);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019041 v8::HandleScope scope(isolate2);
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000019042 v8::Local<v8::Context> context =
19043 v8::Local<v8::Context>::New(isolate2, context2);
19044 v8::Context::Scope context_scope(context);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019045 ExpectString("function f() { return foo; }; f()", "isolate 2");
19046 }
19047
19048 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019049 v8::HandleScope scope(v8::Isolate::GetCurrent());
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000019050 v8::Local<v8::Context> context =
19051 v8::Local<v8::Context>::New(v8::Isolate::GetCurrent(), context1);
19052 v8::Context::Scope context_scope(context);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019053 ExpectString("function f() { return foo; }; f()", "isolate 1");
19054 }
19055
19056 {
19057 v8::Isolate::Scope iscope(isolate2);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000019058 context2.Reset();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019059 }
19060
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000019061 context1.Reset();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019062 isolate1->Exit();
19063
19064 v8::V8::SetFatalErrorHandler(StoringErrorCallback);
19065 last_location = last_message = NULL;
19066
19067 isolate1->Dispose();
19068 CHECK_EQ(last_location, NULL);
19069 CHECK_EQ(last_message, NULL);
19070
19071 isolate2->Dispose();
19072 CHECK_EQ(last_location, NULL);
19073 CHECK_EQ(last_message, NULL);
19074
19075 // Check that default isolate still runs.
19076 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019077 v8::HandleScope scope(CcTest::isolate());
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000019078 v8::Local<v8::Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019079 v8::Local<v8::Context>::New(CcTest::isolate(), context_default);
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000019080 v8::Context::Scope context_scope(context);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019081 ExpectTrue("function f() { return isDefaultIsolate; }; f()");
19082 }
19083}
19084
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019085
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019086static int CalcFibonacci(v8::Isolate* isolate, int limit) {
19087 v8::Isolate::Scope isolate_scope(isolate);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019088 v8::HandleScope scope(isolate);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019089 LocalContext context(isolate);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019090 i::ScopedVector<char> code(1024);
19091 i::OS::SNPrintF(code, "function fib(n) {"
19092 " if (n <= 2) return 1;"
19093 " return fib(n-1) + fib(n-2);"
19094 "}"
19095 "fib(%d)", limit);
19096 Local<Value> value = CompileRun(code.start());
19097 CHECK(value->IsNumber());
19098 return static_cast<int>(value->NumberValue());
19099}
19100
19101class IsolateThread : public v8::internal::Thread {
19102 public:
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000019103 IsolateThread(v8::Isolate* isolate, int fib_limit)
19104 : Thread("IsolateThread"),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019105 isolate_(isolate),
19106 fib_limit_(fib_limit),
19107 result_(0) { }
19108
19109 void Run() {
19110 result_ = CalcFibonacci(isolate_, fib_limit_);
19111 }
19112
19113 int result() { return result_; }
19114
19115 private:
19116 v8::Isolate* isolate_;
19117 int fib_limit_;
19118 int result_;
19119};
19120
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019121
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019122TEST(MultipleIsolatesOnIndividualThreads) {
19123 v8::Isolate* isolate1 = v8::Isolate::New();
19124 v8::Isolate* isolate2 = v8::Isolate::New();
19125
19126 IsolateThread thread1(isolate1, 21);
19127 IsolateThread thread2(isolate2, 12);
19128
19129 // Compute some fibonacci numbers on 3 threads in 3 isolates.
19130 thread1.Start();
19131 thread2.Start();
19132
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019133 int result1 = CalcFibonacci(CcTest::isolate(), 21);
19134 int result2 = CalcFibonacci(CcTest::isolate(), 12);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019135
19136 thread1.Join();
19137 thread2.Join();
19138
19139 // Compare results. The actual fibonacci numbers for 12 and 21 are taken
19140 // (I'm lazy!) from http://en.wikipedia.org/wiki/Fibonacci_number
19141 CHECK_EQ(result1, 10946);
19142 CHECK_EQ(result2, 144);
19143 CHECK_EQ(result1, thread1.result());
19144 CHECK_EQ(result2, thread2.result());
19145
19146 isolate1->Dispose();
19147 isolate2->Dispose();
19148}
19149
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019150
lrn@chromium.org1c092762011-05-09 09:42:16 +000019151TEST(IsolateDifferentContexts) {
19152 v8::Isolate* isolate = v8::Isolate::New();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000019153 Local<v8::Context> context;
lrn@chromium.org1c092762011-05-09 09:42:16 +000019154 {
19155 v8::Isolate::Scope isolate_scope(isolate);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019156 v8::HandleScope handle_scope(isolate);
ulan@chromium.org57ff8812013-05-10 08:16:55 +000019157 context = v8::Context::New(isolate);
lrn@chromium.org1c092762011-05-09 09:42:16 +000019158 v8::Context::Scope context_scope(context);
19159 Local<Value> v = CompileRun("2");
19160 CHECK(v->IsNumber());
19161 CHECK_EQ(2, static_cast<int>(v->NumberValue()));
19162 }
19163 {
19164 v8::Isolate::Scope isolate_scope(isolate);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019165 v8::HandleScope handle_scope(isolate);
ulan@chromium.org57ff8812013-05-10 08:16:55 +000019166 context = v8::Context::New(isolate);
lrn@chromium.org1c092762011-05-09 09:42:16 +000019167 v8::Context::Scope context_scope(context);
19168 Local<Value> v = CompileRun("22");
19169 CHECK(v->IsNumber());
19170 CHECK_EQ(22, static_cast<int>(v->NumberValue()));
19171 }
19172}
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019173
19174class InitDefaultIsolateThread : public v8::internal::Thread {
19175 public:
sgjesse@chromium.orge0599052011-03-25 07:34:35 +000019176 enum TestCase {
19177 IgnoreOOM,
19178 SetResourceConstraints,
19179 SetFatalHandler,
19180 SetCounterFunction,
19181 SetCreateHistogramFunction,
19182 SetAddHistogramSampleFunction
19183 };
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019184
19185 explicit InitDefaultIsolateThread(TestCase testCase)
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000019186 : Thread("InitDefaultIsolateThread"),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019187 testCase_(testCase),
19188 result_(false) { }
19189
19190 void Run() {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019191 v8::Isolate* isolate = v8::Isolate::New();
19192 isolate->Enter();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019193 switch (testCase_) {
19194 case IgnoreOOM:
19195 v8::V8::IgnoreOutOfMemoryException();
19196 break;
19197
19198 case SetResourceConstraints: {
19199 static const int K = 1024;
19200 v8::ResourceConstraints constraints;
19201 constraints.set_max_young_space_size(256 * K);
19202 constraints.set_max_old_space_size(4 * K * K);
machenbach@chromium.org7ff76072013-11-21 09:47:43 +000019203 v8::SetResourceConstraints(CcTest::isolate(), &constraints);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019204 break;
19205 }
19206
19207 case SetFatalHandler:
19208 v8::V8::SetFatalErrorHandler(NULL);
19209 break;
sgjesse@chromium.orge0599052011-03-25 07:34:35 +000019210
19211 case SetCounterFunction:
19212 v8::V8::SetCounterFunction(NULL);
19213 break;
19214
19215 case SetCreateHistogramFunction:
19216 v8::V8::SetCreateHistogramFunction(NULL);
19217 break;
19218
19219 case SetAddHistogramSampleFunction:
19220 v8::V8::SetAddHistogramSampleFunction(NULL);
19221 break;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019222 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019223 isolate->Exit();
19224 isolate->Dispose();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019225 result_ = true;
19226 }
19227
19228 bool result() { return result_; }
19229
19230 private:
19231 TestCase testCase_;
19232 bool result_;
19233};
19234
19235
19236static void InitializeTestHelper(InitDefaultIsolateThread::TestCase testCase) {
19237 InitDefaultIsolateThread thread(testCase);
19238 thread.Start();
19239 thread.Join();
19240 CHECK_EQ(thread.result(), true);
19241}
19242
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019243
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019244TEST(InitializeDefaultIsolateOnSecondaryThread1) {
19245 InitializeTestHelper(InitDefaultIsolateThread::IgnoreOOM);
19246}
19247
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019248
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019249TEST(InitializeDefaultIsolateOnSecondaryThread2) {
19250 InitializeTestHelper(InitDefaultIsolateThread::SetResourceConstraints);
19251}
19252
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019253
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019254TEST(InitializeDefaultIsolateOnSecondaryThread3) {
19255 InitializeTestHelper(InitDefaultIsolateThread::SetFatalHandler);
19256}
19257
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019258
sgjesse@chromium.orge0599052011-03-25 07:34:35 +000019259TEST(InitializeDefaultIsolateOnSecondaryThread4) {
19260 InitializeTestHelper(InitDefaultIsolateThread::SetCounterFunction);
19261}
19262
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019263
sgjesse@chromium.orge0599052011-03-25 07:34:35 +000019264TEST(InitializeDefaultIsolateOnSecondaryThread5) {
19265 InitializeTestHelper(InitDefaultIsolateThread::SetCreateHistogramFunction);
19266}
19267
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019268
sgjesse@chromium.orge0599052011-03-25 07:34:35 +000019269TEST(InitializeDefaultIsolateOnSecondaryThread6) {
19270 InitializeTestHelper(InitDefaultIsolateThread::SetAddHistogramSampleFunction);
19271}
19272
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019273
19274TEST(StringCheckMultipleContexts) {
19275 const char* code =
19276 "(function() { return \"a\".charAt(0); })()";
19277
19278 {
19279 // Run the code twice in the first context to initialize the call IC.
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019280 LocalContext context1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019281 v8::HandleScope scope(context1->GetIsolate());
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019282 ExpectString(code, "a");
19283 ExpectString(code, "a");
19284 }
19285
19286 {
19287 // Change the String.prototype in the second context and check
19288 // that the right function gets called.
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019289 LocalContext context2;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019290 v8::HandleScope scope(context2->GetIsolate());
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019291 CompileRun("String.prototype.charAt = function() { return \"not a\"; }");
19292 ExpectString(code, "not a");
19293 }
19294}
19295
19296
19297TEST(NumberCheckMultipleContexts) {
19298 const char* code =
19299 "(function() { return (42).toString(); })()";
19300
19301 {
19302 // Run the code twice in the first context to initialize the call IC.
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019303 LocalContext context1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019304 v8::HandleScope scope(context1->GetIsolate());
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019305 ExpectString(code, "42");
19306 ExpectString(code, "42");
19307 }
19308
19309 {
19310 // Change the Number.prototype in the second context and check
19311 // that the right function gets called.
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019312 LocalContext context2;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019313 v8::HandleScope scope(context2->GetIsolate());
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019314 CompileRun("Number.prototype.toString = function() { return \"not 42\"; }");
19315 ExpectString(code, "not 42");
19316 }
19317}
19318
19319
19320TEST(BooleanCheckMultipleContexts) {
19321 const char* code =
19322 "(function() { return true.toString(); })()";
19323
19324 {
19325 // Run the code twice in the first context to initialize the call IC.
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019326 LocalContext context1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019327 v8::HandleScope scope(context1->GetIsolate());
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019328 ExpectString(code, "true");
19329 ExpectString(code, "true");
19330 }
19331
19332 {
19333 // Change the Boolean.prototype in the second context and check
19334 // that the right function gets called.
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019335 LocalContext context2;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019336 v8::HandleScope scope(context2->GetIsolate());
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019337 CompileRun("Boolean.prototype.toString = function() { return \"\"; }");
19338 ExpectString(code, "");
19339 }
19340}
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019341
19342
19343TEST(DontDeleteCellLoadIC) {
19344 const char* function_code =
19345 "function readCell() { while (true) { return cell; } }";
19346
19347 {
19348 // Run the code twice in the first context to initialize the load
19349 // IC for a don't delete cell.
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019350 LocalContext context1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019351 v8::HandleScope scope(context1->GetIsolate());
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019352 CompileRun("var cell = \"first\";");
19353 ExpectBoolean("delete cell", false);
19354 CompileRun(function_code);
19355 ExpectString("readCell()", "first");
19356 ExpectString("readCell()", "first");
19357 }
19358
19359 {
19360 // Use a deletable cell in the second context.
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019361 LocalContext context2;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019362 v8::HandleScope scope(context2->GetIsolate());
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019363 CompileRun("cell = \"second\";");
19364 CompileRun(function_code);
19365 ExpectString("readCell()", "second");
19366 ExpectBoolean("delete cell", true);
19367 ExpectString("(function() {"
19368 " try {"
19369 " return readCell();"
19370 " } catch(e) {"
19371 " return e.toString();"
19372 " }"
19373 "})()",
19374 "ReferenceError: cell is not defined");
19375 CompileRun("cell = \"new_second\";");
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019376 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019377 ExpectString("readCell()", "new_second");
19378 ExpectString("readCell()", "new_second");
19379 }
19380}
19381
19382
19383TEST(DontDeleteCellLoadICForceDelete) {
19384 const char* function_code =
19385 "function readCell() { while (true) { return cell; } }";
19386
19387 // Run the code twice to initialize the load IC for a don't delete
19388 // cell.
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019389 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019390 v8::HandleScope scope(context->GetIsolate());
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019391 CompileRun("var cell = \"value\";");
19392 ExpectBoolean("delete cell", false);
19393 CompileRun(function_code);
19394 ExpectString("readCell()", "value");
19395 ExpectString("readCell()", "value");
19396
19397 // Delete the cell using the API and check the inlined code works
19398 // correctly.
19399 CHECK(context->Global()->ForceDelete(v8_str("cell")));
19400 ExpectString("(function() {"
19401 " try {"
19402 " return readCell();"
19403 " } catch(e) {"
19404 " return e.toString();"
19405 " }"
19406 "})()",
19407 "ReferenceError: cell is not defined");
19408}
19409
19410
19411TEST(DontDeleteCellLoadICAPI) {
19412 const char* function_code =
19413 "function readCell() { while (true) { return cell; } }";
19414
19415 // Run the code twice to initialize the load IC for a don't delete
19416 // cell created using the API.
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019417 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019418 v8::HandleScope scope(context->GetIsolate());
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019419 context->Global()->Set(v8_str("cell"), v8_str("value"), v8::DontDelete);
19420 ExpectBoolean("delete cell", false);
19421 CompileRun(function_code);
19422 ExpectString("readCell()", "value");
19423 ExpectString("readCell()", "value");
19424
19425 // Delete the cell using the API and check the inlined code works
19426 // correctly.
19427 CHECK(context->Global()->ForceDelete(v8_str("cell")));
19428 ExpectString("(function() {"
19429 " try {"
19430 " return readCell();"
19431 " } catch(e) {"
19432 " return e.toString();"
19433 " }"
19434 "})()",
19435 "ReferenceError: cell is not defined");
19436}
19437
19438
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000019439class Visitor42 : public v8::PersistentHandleVisitor {
19440 public:
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000019441 explicit Visitor42(v8::Persistent<v8::Object>* object)
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000019442 : counter_(0), object_(object) { }
19443
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000019444 virtual void VisitPersistentHandle(Persistent<Value>* value,
19445 uint16_t class_id) {
19446 if (class_id != 42) return;
19447 CHECK_EQ(42, value->WrapperClassId());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019448 v8::Isolate* isolate = CcTest::isolate();
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000019449 v8::HandleScope handle_scope(isolate);
19450 v8::Handle<v8::Value> handle = v8::Local<v8::Value>::New(isolate, *value);
19451 v8::Handle<v8::Value> object =
19452 v8::Local<v8::Object>::New(isolate, *object_);
19453 CHECK(handle->IsObject());
19454 CHECK_EQ(Handle<Object>::Cast(handle), object);
19455 ++counter_;
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000019456 }
19457
19458 int counter_;
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000019459 v8::Persistent<v8::Object>* object_;
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000019460};
19461
19462
19463TEST(PersistentHandleVisitor) {
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000019464 LocalContext context;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000019465 v8::Isolate* isolate = context->GetIsolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019466 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000019467 v8::Persistent<v8::Object> object(isolate, v8::Object::New(isolate));
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000019468 CHECK_EQ(0, object.WrapperClassId());
19469 object.SetWrapperClassId(42);
19470 CHECK_EQ(42, object.WrapperClassId());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000019471
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000019472 Visitor42 visitor(&object);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000019473 v8::V8::VisitHandlesWithClassIds(&visitor);
19474 CHECK_EQ(1, visitor.counter_);
19475
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000019476 object.Reset();
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000019477}
19478
19479
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000019480TEST(WrapperClassId) {
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000019481 LocalContext context;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000019482 v8::Isolate* isolate = context->GetIsolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019483 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000019484 v8::Persistent<v8::Object> object(isolate, v8::Object::New(isolate));
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000019485 CHECK_EQ(0, object.WrapperClassId());
19486 object.SetWrapperClassId(65535);
19487 CHECK_EQ(65535, object.WrapperClassId());
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000019488 object.Reset();
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000019489}
19490
19491
yangguo@chromium.org003650e2013-01-24 16:31:08 +000019492TEST(PersistentHandleInNewSpaceVisitor) {
yangguo@chromium.org003650e2013-01-24 16:31:08 +000019493 LocalContext context;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000019494 v8::Isolate* isolate = context->GetIsolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019495 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000019496 v8::Persistent<v8::Object> object1(isolate, v8::Object::New(isolate));
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000019497 CHECK_EQ(0, object1.WrapperClassId());
19498 object1.SetWrapperClassId(42);
19499 CHECK_EQ(42, object1.WrapperClassId());
yangguo@chromium.org003650e2013-01-24 16:31:08 +000019500
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019501 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
yangguo@chromium.org003650e2013-01-24 16:31:08 +000019502
ulan@chromium.org0f13e742014-01-03 15:51:11 +000019503 v8::Persistent<v8::Object> object2(isolate, v8::Object::New(isolate));
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000019504 CHECK_EQ(0, object2.WrapperClassId());
19505 object2.SetWrapperClassId(42);
19506 CHECK_EQ(42, object2.WrapperClassId());
yangguo@chromium.org003650e2013-01-24 16:31:08 +000019507
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000019508 Visitor42 visitor(&object2);
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000019509 v8::V8::VisitHandlesForPartialDependence(isolate, &visitor);
yangguo@chromium.org003650e2013-01-24 16:31:08 +000019510 CHECK_EQ(1, visitor.counter_);
19511
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000019512 object1.Reset();
19513 object2.Reset();
yangguo@chromium.org003650e2013-01-24 16:31:08 +000019514}
19515
19516
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019517TEST(RegExp) {
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019518 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019519 v8::HandleScope scope(context->GetIsolate());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019520
19521 v8::Handle<v8::RegExp> re = v8::RegExp::New(v8_str("foo"), v8::RegExp::kNone);
19522 CHECK(re->IsRegExp());
19523 CHECK(re->GetSource()->Equals(v8_str("foo")));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000019524 CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019525
19526 re = v8::RegExp::New(v8_str("bar"),
19527 static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
19528 v8::RegExp::kGlobal));
19529 CHECK(re->IsRegExp());
19530 CHECK(re->GetSource()->Equals(v8_str("bar")));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000019531 CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kGlobal,
19532 static_cast<int>(re->GetFlags()));
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019533
19534 re = v8::RegExp::New(v8_str("baz"),
19535 static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
19536 v8::RegExp::kMultiline));
19537 CHECK(re->IsRegExp());
19538 CHECK(re->GetSource()->Equals(v8_str("baz")));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000019539 CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
19540 static_cast<int>(re->GetFlags()));
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019541
19542 re = CompileRun("/quux/").As<v8::RegExp>();
19543 CHECK(re->IsRegExp());
19544 CHECK(re->GetSource()->Equals(v8_str("quux")));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000019545 CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019546
19547 re = CompileRun("/quux/gm").As<v8::RegExp>();
19548 CHECK(re->IsRegExp());
19549 CHECK(re->GetSource()->Equals(v8_str("quux")));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000019550 CHECK_EQ(v8::RegExp::kGlobal | v8::RegExp::kMultiline,
19551 static_cast<int>(re->GetFlags()));
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019552
19553 // Override the RegExp constructor and check the API constructor
19554 // still works.
19555 CompileRun("RegExp = function() {}");
19556
19557 re = v8::RegExp::New(v8_str("foobar"), v8::RegExp::kNone);
19558 CHECK(re->IsRegExp());
19559 CHECK(re->GetSource()->Equals(v8_str("foobar")));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000019560 CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019561
19562 re = v8::RegExp::New(v8_str("foobarbaz"),
19563 static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
19564 v8::RegExp::kMultiline));
19565 CHECK(re->IsRegExp());
19566 CHECK(re->GetSource()->Equals(v8_str("foobarbaz")));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000019567 CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
19568 static_cast<int>(re->GetFlags()));
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019569
19570 context->Global()->Set(v8_str("re"), re);
19571 ExpectTrue("re.test('FoobarbaZ')");
19572
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000019573 // RegExps are objects on which you can set properties.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000019574 re->Set(v8_str("property"), v8::Integer::New(context->GetIsolate(), 32));
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000019575 v8::Handle<v8::Value> value(CompileRun("re.property"));
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000019576 CHECK_EQ(32, value->Int32Value());
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000019577
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019578 v8::TryCatch try_catch;
19579 re = v8::RegExp::New(v8_str("foo["), v8::RegExp::kNone);
19580 CHECK(re.IsEmpty());
19581 CHECK(try_catch.HasCaught());
19582 context->Global()->Set(v8_str("ex"), try_catch.Exception());
19583 ExpectTrue("ex instanceof SyntaxError");
19584}
19585
19586
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000019587THREADED_TEST(Equals) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000019588 LocalContext localContext;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019589 v8::HandleScope handleScope(localContext->GetIsolate());
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000019590
19591 v8::Handle<v8::Object> globalProxy = localContext->Global();
19592 v8::Handle<Value> global = globalProxy->GetPrototype();
19593
19594 CHECK(global->StrictEquals(global));
19595 CHECK(!global->StrictEquals(globalProxy));
19596 CHECK(!globalProxy->StrictEquals(global));
19597 CHECK(globalProxy->StrictEquals(globalProxy));
19598
19599 CHECK(global->Equals(global));
19600 CHECK(!global->Equals(globalProxy));
19601 CHECK(!globalProxy->Equals(global));
19602 CHECK(globalProxy->Equals(globalProxy));
19603}
19604
19605
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019606static void Getter(v8::Local<v8::String> property,
19607 const v8::PropertyCallbackInfo<v8::Value>& info ) {
19608 info.GetReturnValue().Set(v8_str("42!"));
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019609}
19610
19611
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019612static void Enumerator(const v8::PropertyCallbackInfo<v8::Array>& info) {
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000019613 v8::Handle<v8::Array> result = v8::Array::New(info.GetIsolate());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019614 result->Set(0, v8_str("universalAnswer"));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019615 info.GetReturnValue().Set(result);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019616}
19617
19618
19619TEST(NamedEnumeratorAndForIn) {
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019620 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000019621 v8::Isolate* isolate = context->GetIsolate();
19622 v8::HandleScope handle_scope(isolate);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019623 v8::Context::Scope context_scope(context.local());
19624
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000019625 v8::Handle<v8::ObjectTemplate> tmpl = v8::ObjectTemplate::New(isolate);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019626 tmpl->SetNamedPropertyHandler(Getter, NULL, NULL, NULL, Enumerator);
19627 context->Global()->Set(v8_str("o"), tmpl->NewInstance());
19628 v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
19629 "var result = []; for (var k in o) result.push(k); result"));
19630 CHECK_EQ(1, result->Length());
19631 CHECK_EQ(v8_str("universalAnswer"), result->Get(0));
19632}
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +000019633
19634
19635TEST(DefinePropertyPostDetach) {
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +000019636 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019637 v8::HandleScope scope(context->GetIsolate());
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +000019638 v8::Handle<v8::Object> proxy = context->Global();
19639 v8::Handle<v8::Function> define_property =
19640 CompileRun("(function() {"
19641 " Object.defineProperty("
19642 " this,"
19643 " 1,"
19644 " { configurable: true, enumerable: true, value: 3 });"
19645 "})").As<Function>();
19646 context->DetachGlobal();
19647 define_property->Call(proxy, 0, NULL);
19648}
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000019649
19650
19651static void InstallContextId(v8::Handle<Context> context, int id) {
19652 Context::Scope scope(context);
19653 CompileRun("Object.prototype").As<Object>()->
ulan@chromium.org0f13e742014-01-03 15:51:11 +000019654 Set(v8_str("context_id"), v8::Integer::New(context->GetIsolate(), id));
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000019655}
19656
19657
19658static void CheckContextId(v8::Handle<Object> object, int expected) {
19659 CHECK_EQ(expected, object->Get(v8_str("context_id"))->Int32Value());
19660}
19661
19662
19663THREADED_TEST(CreationContext) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000019664 v8::Isolate* isolate = CcTest::isolate();
19665 HandleScope handle_scope(isolate);
19666 Handle<Context> context1 = Context::New(isolate);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000019667 InstallContextId(context1, 1);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000019668 Handle<Context> context2 = Context::New(isolate);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000019669 InstallContextId(context2, 2);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000019670 Handle<Context> context3 = Context::New(isolate);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000019671 InstallContextId(context3, 3);
19672
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000019673 Local<v8::FunctionTemplate> tmpl = v8::FunctionTemplate::New(isolate);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000019674
19675 Local<Object> object1;
19676 Local<Function> func1;
19677 {
19678 Context::Scope scope(context1);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000019679 object1 = Object::New(isolate);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000019680 func1 = tmpl->GetFunction();
19681 }
19682
19683 Local<Object> object2;
19684 Local<Function> func2;
19685 {
19686 Context::Scope scope(context2);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000019687 object2 = Object::New(isolate);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000019688 func2 = tmpl->GetFunction();
19689 }
19690
19691 Local<Object> instance1;
19692 Local<Object> instance2;
19693
19694 {
19695 Context::Scope scope(context3);
19696 instance1 = func1->NewInstance();
19697 instance2 = func2->NewInstance();
19698 }
19699
19700 CHECK(object1->CreationContext() == context1);
19701 CheckContextId(object1, 1);
19702 CHECK(func1->CreationContext() == context1);
19703 CheckContextId(func1, 1);
19704 CHECK(instance1->CreationContext() == context1);
19705 CheckContextId(instance1, 1);
19706 CHECK(object2->CreationContext() == context2);
19707 CheckContextId(object2, 2);
19708 CHECK(func2->CreationContext() == context2);
19709 CheckContextId(func2, 2);
19710 CHECK(instance2->CreationContext() == context2);
19711 CheckContextId(instance2, 2);
19712
19713 {
19714 Context::Scope scope(context1);
19715 CHECK(object1->CreationContext() == context1);
19716 CheckContextId(object1, 1);
19717 CHECK(func1->CreationContext() == context1);
19718 CheckContextId(func1, 1);
19719 CHECK(instance1->CreationContext() == context1);
19720 CheckContextId(instance1, 1);
19721 CHECK(object2->CreationContext() == context2);
19722 CheckContextId(object2, 2);
19723 CHECK(func2->CreationContext() == context2);
19724 CheckContextId(func2, 2);
19725 CHECK(instance2->CreationContext() == context2);
19726 CheckContextId(instance2, 2);
19727 }
19728
19729 {
19730 Context::Scope scope(context2);
19731 CHECK(object1->CreationContext() == context1);
19732 CheckContextId(object1, 1);
19733 CHECK(func1->CreationContext() == context1);
19734 CheckContextId(func1, 1);
19735 CHECK(instance1->CreationContext() == context1);
19736 CheckContextId(instance1, 1);
19737 CHECK(object2->CreationContext() == context2);
19738 CheckContextId(object2, 2);
19739 CHECK(func2->CreationContext() == context2);
19740 CheckContextId(func2, 2);
19741 CHECK(instance2->CreationContext() == context2);
19742 CheckContextId(instance2, 2);
19743 }
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000019744}
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019745
19746
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +000019747THREADED_TEST(CreationContextOfJsFunction) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019748 HandleScope handle_scope(CcTest::isolate());
19749 Handle<Context> context = Context::New(CcTest::isolate());
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +000019750 InstallContextId(context, 1);
19751
19752 Local<Object> function;
19753 {
19754 Context::Scope scope(context);
19755 function = CompileRun("function foo() {}; foo").As<Object>();
19756 }
19757
19758 CHECK(function->CreationContext() == context);
19759 CheckContextId(function, 1);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +000019760}
19761
19762
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019763void HasOwnPropertyIndexedPropertyGetter(
19764 uint32_t index,
19765 const v8::PropertyCallbackInfo<v8::Value>& info) {
19766 if (index == 42) info.GetReturnValue().Set(v8_str("yes"));
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019767}
19768
19769
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019770void HasOwnPropertyNamedPropertyGetter(
19771 Local<String> property,
19772 const v8::PropertyCallbackInfo<v8::Value>& info) {
19773 if (property->Equals(v8_str("foo"))) info.GetReturnValue().Set(v8_str("yes"));
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019774}
19775
19776
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019777void HasOwnPropertyIndexedPropertyQuery(
19778 uint32_t index, const v8::PropertyCallbackInfo<v8::Integer>& info) {
19779 if (index == 42) info.GetReturnValue().Set(1);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019780}
19781
19782
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019783void HasOwnPropertyNamedPropertyQuery(
19784 Local<String> property,
19785 const v8::PropertyCallbackInfo<v8::Integer>& info) {
19786 if (property->Equals(v8_str("foo"))) info.GetReturnValue().Set(1);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019787}
19788
19789
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019790void HasOwnPropertyNamedPropertyQuery2(
19791 Local<String> property,
19792 const v8::PropertyCallbackInfo<v8::Integer>& info) {
19793 if (property->Equals(v8_str("bar"))) info.GetReturnValue().Set(1);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019794}
19795
19796
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019797void HasOwnPropertyAccessorGetter(
19798 Local<String> property,
19799 const v8::PropertyCallbackInfo<v8::Value>& info) {
19800 info.GetReturnValue().Set(v8_str("yes"));
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019801}
19802
19803
19804TEST(HasOwnProperty) {
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019805 LocalContext env;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000019806 v8::Isolate* isolate = env->GetIsolate();
19807 v8::HandleScope scope(isolate);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019808 { // Check normal properties and defined getters.
19809 Handle<Value> value = CompileRun(
19810 "function Foo() {"
19811 " this.foo = 11;"
19812 " this.__defineGetter__('baz', function() { return 1; });"
19813 "};"
19814 "function Bar() { "
19815 " this.bar = 13;"
19816 " this.__defineGetter__('bla', function() { return 2; });"
19817 "};"
19818 "Bar.prototype = new Foo();"
19819 "new Bar();");
19820 CHECK(value->IsObject());
19821 Handle<Object> object = value->ToObject();
19822 CHECK(object->Has(v8_str("foo")));
19823 CHECK(!object->HasOwnProperty(v8_str("foo")));
19824 CHECK(object->HasOwnProperty(v8_str("bar")));
19825 CHECK(object->Has(v8_str("baz")));
19826 CHECK(!object->HasOwnProperty(v8_str("baz")));
19827 CHECK(object->HasOwnProperty(v8_str("bla")));
19828 }
19829 { // Check named getter interceptors.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000019830 Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019831 templ->SetNamedPropertyHandler(HasOwnPropertyNamedPropertyGetter);
19832 Handle<Object> instance = templ->NewInstance();
19833 CHECK(!instance->HasOwnProperty(v8_str("42")));
19834 CHECK(instance->HasOwnProperty(v8_str("foo")));
19835 CHECK(!instance->HasOwnProperty(v8_str("bar")));
19836 }
19837 { // Check indexed getter interceptors.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000019838 Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019839 templ->SetIndexedPropertyHandler(HasOwnPropertyIndexedPropertyGetter);
19840 Handle<Object> instance = templ->NewInstance();
19841 CHECK(instance->HasOwnProperty(v8_str("42")));
19842 CHECK(!instance->HasOwnProperty(v8_str("43")));
19843 CHECK(!instance->HasOwnProperty(v8_str("foo")));
19844 }
19845 { // Check named query interceptors.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000019846 Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019847 templ->SetNamedPropertyHandler(0, 0, HasOwnPropertyNamedPropertyQuery);
19848 Handle<Object> instance = templ->NewInstance();
19849 CHECK(instance->HasOwnProperty(v8_str("foo")));
19850 CHECK(!instance->HasOwnProperty(v8_str("bar")));
19851 }
19852 { // Check indexed query interceptors.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000019853 Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019854 templ->SetIndexedPropertyHandler(0, 0, HasOwnPropertyIndexedPropertyQuery);
19855 Handle<Object> instance = templ->NewInstance();
19856 CHECK(instance->HasOwnProperty(v8_str("42")));
19857 CHECK(!instance->HasOwnProperty(v8_str("41")));
19858 }
19859 { // Check callbacks.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000019860 Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019861 templ->SetAccessor(v8_str("foo"), HasOwnPropertyAccessorGetter);
19862 Handle<Object> instance = templ->NewInstance();
19863 CHECK(instance->HasOwnProperty(v8_str("foo")));
19864 CHECK(!instance->HasOwnProperty(v8_str("bar")));
19865 }
19866 { // Check that query wins on disagreement.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000019867 Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019868 templ->SetNamedPropertyHandler(HasOwnPropertyNamedPropertyGetter,
19869 0,
19870 HasOwnPropertyNamedPropertyQuery2);
19871 Handle<Object> instance = templ->NewInstance();
19872 CHECK(!instance->HasOwnProperty(v8_str("foo")));
19873 CHECK(instance->HasOwnProperty(v8_str("bar")));
19874 }
19875}
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000019876
19877
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +000019878TEST(IndexedInterceptorWithStringProto) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000019879 v8::Isolate* isolate = CcTest::isolate();
19880 v8::HandleScope scope(isolate);
19881 Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +000019882 templ->SetIndexedPropertyHandler(NULL,
19883 NULL,
19884 HasOwnPropertyIndexedPropertyQuery);
19885 LocalContext context;
19886 context->Global()->Set(v8_str("obj"), templ->NewInstance());
19887 CompileRun("var s = new String('foobar'); obj.__proto__ = s;");
19888 // These should be intercepted.
19889 CHECK(CompileRun("42 in obj")->BooleanValue());
19890 CHECK(CompileRun("'42' in obj")->BooleanValue());
19891 // These should fall through to the String prototype.
19892 CHECK(CompileRun("0 in obj")->BooleanValue());
19893 CHECK(CompileRun("'0' in obj")->BooleanValue());
19894 // And these should both fail.
19895 CHECK(!CompileRun("32 in obj")->BooleanValue());
19896 CHECK(!CompileRun("'32' in obj")->BooleanValue());
19897}
19898
19899
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000019900void CheckCodeGenerationAllowed() {
19901 Handle<Value> result = CompileRun("eval('42')");
19902 CHECK_EQ(42, result->Int32Value());
19903 result = CompileRun("(function(e) { return e('42'); })(eval)");
19904 CHECK_EQ(42, result->Int32Value());
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000019905 result = CompileRun("var f = new Function('return 42'); f()");
19906 CHECK_EQ(42, result->Int32Value());
19907}
19908
19909
19910void CheckCodeGenerationDisallowed() {
19911 TryCatch try_catch;
19912
19913 Handle<Value> result = CompileRun("eval('42')");
19914 CHECK(result.IsEmpty());
19915 CHECK(try_catch.HasCaught());
19916 try_catch.Reset();
19917
19918 result = CompileRun("(function(e) { return e('42'); })(eval)");
19919 CHECK(result.IsEmpty());
19920 CHECK(try_catch.HasCaught());
19921 try_catch.Reset();
19922
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000019923 result = CompileRun("var f = new Function('return 42'); f()");
19924 CHECK(result.IsEmpty());
19925 CHECK(try_catch.HasCaught());
19926}
19927
19928
19929bool CodeGenerationAllowed(Local<Context> context) {
19930 ApiTestFuzzer::Fuzz();
19931 return true;
19932}
19933
19934
19935bool CodeGenerationDisallowed(Local<Context> context) {
19936 ApiTestFuzzer::Fuzz();
19937 return false;
19938}
19939
19940
19941THREADED_TEST(AllowCodeGenFromStrings) {
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000019942 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019943 v8::HandleScope scope(context->GetIsolate());
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000019944
ager@chromium.orgea91cc52011-05-23 06:06:11 +000019945 // eval and the Function constructor allowed by default.
jkummerow@chromium.org1145ef82012-02-02 16:21:15 +000019946 CHECK(context->IsCodeGenerationFromStringsAllowed());
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000019947 CheckCodeGenerationAllowed();
19948
ager@chromium.orgea91cc52011-05-23 06:06:11 +000019949 // Disallow eval and the Function constructor.
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000019950 context->AllowCodeGenerationFromStrings(false);
jkummerow@chromium.org1145ef82012-02-02 16:21:15 +000019951 CHECK(!context->IsCodeGenerationFromStringsAllowed());
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000019952 CheckCodeGenerationDisallowed();
19953
19954 // Allow again.
19955 context->AllowCodeGenerationFromStrings(true);
19956 CheckCodeGenerationAllowed();
19957
19958 // Disallow but setting a global callback that will allow the calls.
19959 context->AllowCodeGenerationFromStrings(false);
19960 V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationAllowed);
jkummerow@chromium.org1145ef82012-02-02 16:21:15 +000019961 CHECK(!context->IsCodeGenerationFromStringsAllowed());
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000019962 CheckCodeGenerationAllowed();
19963
19964 // Set a callback that disallows the code generation.
19965 V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationDisallowed);
jkummerow@chromium.org1145ef82012-02-02 16:21:15 +000019966 CHECK(!context->IsCodeGenerationFromStringsAllowed());
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000019967 CheckCodeGenerationDisallowed();
19968}
lrn@chromium.org1c092762011-05-09 09:42:16 +000019969
19970
ulan@chromium.org56c14af2012-09-20 12:51:09 +000019971TEST(SetErrorMessageForCodeGenFromStrings) {
ulan@chromium.org56c14af2012-09-20 12:51:09 +000019972 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019973 v8::HandleScope scope(context->GetIsolate());
ulan@chromium.org56c14af2012-09-20 12:51:09 +000019974 TryCatch try_catch;
19975
19976 Handle<String> message = v8_str("Message") ;
19977 Handle<String> expected_message = v8_str("Uncaught EvalError: Message");
19978 V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationDisallowed);
19979 context->AllowCodeGenerationFromStrings(false);
19980 context->SetErrorMessageForCodeGenerationFromStrings(message);
19981 Handle<Value> result = CompileRun("eval('42')");
19982 CHECK(result.IsEmpty());
19983 CHECK(try_catch.HasCaught());
19984 Handle<String> actual_message = try_catch.Message()->Get();
19985 CHECK(expected_message->Equals(actual_message));
19986}
19987
19988
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019989static void NonObjectThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
lrn@chromium.org1c092762011-05-09 09:42:16 +000019990}
19991
19992
19993THREADED_TEST(CallAPIFunctionOnNonObject) {
lrn@chromium.org1c092762011-05-09 09:42:16 +000019994 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000019995 v8::Isolate* isolate = context->GetIsolate();
19996 v8::HandleScope scope(isolate);
19997 Handle<FunctionTemplate> templ =
19998 v8::FunctionTemplate::New(isolate, NonObjectThis);
lrn@chromium.org1c092762011-05-09 09:42:16 +000019999 Handle<Function> function = templ->GetFunction();
20000 context->Global()->Set(v8_str("f"), function);
20001 TryCatch try_catch;
20002 CompileRun("f.call(2)");
lrn@chromium.org1c092762011-05-09 09:42:16 +000020003}
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000020004
20005
20006// Regression test for issue 1470.
20007THREADED_TEST(ReadOnlyIndexedProperties) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000020008 v8::Isolate* isolate = CcTest::isolate();
20009 v8::HandleScope scope(isolate);
20010 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000020011
20012 LocalContext context;
20013 Local<v8::Object> obj = templ->NewInstance();
20014 context->Global()->Set(v8_str("obj"), obj);
20015 obj->Set(v8_str("1"), v8_str("DONT_CHANGE"), v8::ReadOnly);
20016 obj->Set(v8_str("1"), v8_str("foobar"));
20017 CHECK_EQ(v8_str("DONT_CHANGE"), obj->Get(v8_str("1")));
20018 obj->Set(v8_num(2), v8_str("DONT_CHANGE"), v8::ReadOnly);
20019 obj->Set(v8_num(2), v8_str("foobar"));
20020 CHECK_EQ(v8_str("DONT_CHANGE"), obj->Get(v8_num(2)));
20021
20022 // Test non-smi case.
20023 obj->Set(v8_str("2000000000"), v8_str("DONT_CHANGE"), v8::ReadOnly);
20024 obj->Set(v8_str("2000000000"), v8_str("foobar"));
20025 CHECK_EQ(v8_str("DONT_CHANGE"), obj->Get(v8_str("2000000000")));
20026}
ricow@chromium.org4f693d62011-07-04 14:01:31 +000020027
20028
20029THREADED_TEST(Regress1516) {
ricow@chromium.org4f693d62011-07-04 14:01:31 +000020030 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020031 v8::HandleScope scope(context->GetIsolate());
20032
20033 { v8::HandleScope temp_scope(context->GetIsolate());
ricow@chromium.org4f693d62011-07-04 14:01:31 +000020034 CompileRun("({'a': 0})");
20035 }
20036
20037 int elements;
20038 { i::MapCache* map_cache =
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020039 i::MapCache::cast(CcTest::i_isolate()->context()->map_cache());
ricow@chromium.org4f693d62011-07-04 14:01:31 +000020040 elements = map_cache->NumberOfElements();
20041 CHECK_LE(1, elements);
20042 }
20043
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020044 CcTest::heap()->CollectAllGarbage(
yangguo@chromium.orgd2899aa2012-06-21 11:16:20 +000020045 i::Heap::kAbortIncrementalMarkingMask);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020046 { i::Object* raw_map_cache = CcTest::i_isolate()->context()->map_cache();
20047 if (raw_map_cache != CcTest::heap()->undefined_value()) {
ricow@chromium.org4f693d62011-07-04 14:01:31 +000020048 i::MapCache* map_cache = i::MapCache::cast(raw_map_cache);
20049 CHECK_GT(elements, map_cache->NumberOfElements());
20050 }
20051 }
20052}
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020053
20054
20055static bool BlockProtoNamedSecurityTestCallback(Local<v8::Object> global,
20056 Local<Value> name,
20057 v8::AccessType type,
20058 Local<Value> data) {
20059 // Only block read access to __proto__.
20060 if (type == v8::ACCESS_GET &&
20061 name->IsString() &&
20062 name->ToString()->Length() == 9 &&
20063 name->ToString()->Utf8Length() == 9) {
20064 char buffer[10];
20065 CHECK_EQ(10, name->ToString()->WriteUtf8(buffer));
20066 return strncmp(buffer, "__proto__", 9) != 0;
20067 }
20068
20069 return true;
20070}
20071
20072
20073THREADED_TEST(Regress93759) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020074 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000020075 HandleScope scope(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020076
20077 // Template for object with security check.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000020078 Local<ObjectTemplate> no_proto_template = v8::ObjectTemplate::New(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020079 // We don't do indexing, so any callback can be used for that.
20080 no_proto_template->SetAccessCheckCallbacks(
20081 BlockProtoNamedSecurityTestCallback,
20082 IndexedSecurityTestCallback);
20083
20084 // Templates for objects with hidden prototypes and possibly security check.
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000020085 Local<FunctionTemplate> hidden_proto_template =
20086 v8::FunctionTemplate::New(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020087 hidden_proto_template->SetHiddenPrototype(true);
20088
20089 Local<FunctionTemplate> protected_hidden_proto_template =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000020090 v8::FunctionTemplate::New(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020091 protected_hidden_proto_template->InstanceTemplate()->SetAccessCheckCallbacks(
20092 BlockProtoNamedSecurityTestCallback,
20093 IndexedSecurityTestCallback);
20094 protected_hidden_proto_template->SetHiddenPrototype(true);
20095
20096 // Context for "foreign" objects used in test.
ulan@chromium.org57ff8812013-05-10 08:16:55 +000020097 Local<Context> context = v8::Context::New(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020098 context->Enter();
20099
20100 // Plain object, no security check.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000020101 Local<Object> simple_object = Object::New(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020102
20103 // Object with explicit security check.
20104 Local<Object> protected_object =
20105 no_proto_template->NewInstance();
20106
20107 // JSGlobalProxy object, always have security check.
20108 Local<Object> proxy_object =
20109 context->Global();
20110
20111 // Global object, the prototype of proxy_object. No security checks.
20112 Local<Object> global_object =
20113 proxy_object->GetPrototype()->ToObject();
20114
20115 // Hidden prototype without security check.
20116 Local<Object> hidden_prototype =
20117 hidden_proto_template->GetFunction()->NewInstance();
20118 Local<Object> object_with_hidden =
ulan@chromium.org0f13e742014-01-03 15:51:11 +000020119 Object::New(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020120 object_with_hidden->SetPrototype(hidden_prototype);
20121
20122 // Hidden prototype with security check on the hidden prototype.
20123 Local<Object> protected_hidden_prototype =
20124 protected_hidden_proto_template->GetFunction()->NewInstance();
20125 Local<Object> object_with_protected_hidden =
ulan@chromium.org0f13e742014-01-03 15:51:11 +000020126 Object::New(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020127 object_with_protected_hidden->SetPrototype(protected_hidden_prototype);
20128
20129 context->Exit();
20130
20131 // Template for object for second context. Values to test are put on it as
20132 // properties.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000020133 Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020134 global_template->Set(v8_str("simple"), simple_object);
20135 global_template->Set(v8_str("protected"), protected_object);
20136 global_template->Set(v8_str("global"), global_object);
20137 global_template->Set(v8_str("proxy"), proxy_object);
20138 global_template->Set(v8_str("hidden"), object_with_hidden);
20139 global_template->Set(v8_str("phidden"), object_with_protected_hidden);
20140
20141 LocalContext context2(NULL, global_template);
20142
20143 Local<Value> result1 = CompileRun("Object.getPrototypeOf(simple)");
20144 CHECK(result1->Equals(simple_object->GetPrototype()));
20145
20146 Local<Value> result2 = CompileRun("Object.getPrototypeOf(protected)");
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000020147 CHECK(result2->Equals(Undefined(isolate)));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020148
20149 Local<Value> result3 = CompileRun("Object.getPrototypeOf(global)");
20150 CHECK(result3->Equals(global_object->GetPrototype()));
20151
20152 Local<Value> result4 = CompileRun("Object.getPrototypeOf(proxy)");
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000020153 CHECK(result4->Equals(Undefined(isolate)));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020154
20155 Local<Value> result5 = CompileRun("Object.getPrototypeOf(hidden)");
20156 CHECK(result5->Equals(
20157 object_with_hidden->GetPrototype()->ToObject()->GetPrototype()));
20158
20159 Local<Value> result6 = CompileRun("Object.getPrototypeOf(phidden)");
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000020160 CHECK(result6->Equals(Undefined(isolate)));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020161}
20162
20163
jkummerow@chromium.org212d9642012-05-11 15:02:09 +000020164THREADED_TEST(Regress125988) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020165 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000020166 Handle<FunctionTemplate> intercept = FunctionTemplate::New(CcTest::isolate());
jkummerow@chromium.org212d9642012-05-11 15:02:09 +000020167 AddInterceptor(intercept, EmptyInterceptorGetter, EmptyInterceptorSetter);
20168 LocalContext env;
20169 env->Global()->Set(v8_str("Intercept"), intercept->GetFunction());
20170 CompileRun("var a = new Object();"
20171 "var b = new Intercept();"
20172 "var c = new Object();"
20173 "c.__proto__ = b;"
20174 "b.__proto__ = a;"
20175 "a.x = 23;"
20176 "for (var i = 0; i < 3; i++) c.x;");
20177 ExpectBoolean("c.hasOwnProperty('x')", false);
20178 ExpectInt32("c.x", 23);
20179 CompileRun("a.y = 42;"
20180 "for (var i = 0; i < 3; i++) c.x;");
20181 ExpectBoolean("c.hasOwnProperty('x')", false);
20182 ExpectInt32("c.x", 23);
20183 ExpectBoolean("c.hasOwnProperty('y')", false);
20184 ExpectInt32("c.y", 42);
20185}
20186
20187
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020188static void TestReceiver(Local<Value> expected_result,
20189 Local<Value> expected_receiver,
20190 const char* code) {
20191 Local<Value> result = CompileRun(code);
20192 CHECK(result->IsObject());
20193 CHECK(expected_receiver->Equals(result->ToObject()->Get(1)));
20194 CHECK(expected_result->Equals(result->ToObject()->Get(0)));
20195}
20196
20197
20198THREADED_TEST(ForeignFunctionReceiver) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020199 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000020200 HandleScope scope(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020201
20202 // Create two contexts with different "id" properties ('i' and 'o').
20203 // Call a function both from its own context and from a the foreign
20204 // context, and see what "this" is bound to (returning both "this"
20205 // and "this.id" for comparison).
20206
ulan@chromium.org57ff8812013-05-10 08:16:55 +000020207 Local<Context> foreign_context = v8::Context::New(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020208 foreign_context->Enter();
20209 Local<Value> foreign_function =
20210 CompileRun("function func() { return { 0: this.id, "
20211 " 1: this, "
20212 " toString: function() { "
20213 " return this[0];"
20214 " }"
20215 " };"
20216 "}"
20217 "var id = 'i';"
20218 "func;");
20219 CHECK(foreign_function->IsFunction());
20220 foreign_context->Exit();
20221
20222 LocalContext context;
20223
20224 Local<String> password = v8_str("Password");
20225 // Don't get hit by security checks when accessing foreign_context's
20226 // global receiver (aka. global proxy).
20227 context->SetSecurityToken(password);
20228 foreign_context->SetSecurityToken(password);
20229
20230 Local<String> i = v8_str("i");
20231 Local<String> o = v8_str("o");
20232 Local<String> id = v8_str("id");
20233
20234 CompileRun("function ownfunc() { return { 0: this.id, "
20235 " 1: this, "
20236 " toString: function() { "
20237 " return this[0];"
20238 " }"
20239 " };"
20240 "}"
20241 "var id = 'o';"
20242 "ownfunc");
20243 context->Global()->Set(v8_str("func"), foreign_function);
20244
20245 // Sanity check the contexts.
20246 CHECK(i->Equals(foreign_context->Global()->Get(id)));
20247 CHECK(o->Equals(context->Global()->Get(id)));
20248
20249 // Checking local function's receiver.
20250 // Calling function using its call/apply methods.
20251 TestReceiver(o, context->Global(), "ownfunc.call()");
20252 TestReceiver(o, context->Global(), "ownfunc.apply()");
20253 // Making calls through built-in functions.
20254 TestReceiver(o, context->Global(), "[1].map(ownfunc)[0]");
20255 CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/,ownfunc)[1]")));
20256 CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/g,ownfunc)[1]")));
20257 CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/g,ownfunc)[3]")));
20258 // Calling with environment record as base.
20259 TestReceiver(o, context->Global(), "ownfunc()");
20260 // Calling with no base.
20261 TestReceiver(o, context->Global(), "(1,ownfunc)()");
20262
20263 // Checking foreign function return value.
20264 // Calling function using its call/apply methods.
20265 TestReceiver(i, foreign_context->Global(), "func.call()");
20266 TestReceiver(i, foreign_context->Global(), "func.apply()");
20267 // Calling function using another context's call/apply methods.
20268 TestReceiver(i, foreign_context->Global(),
20269 "Function.prototype.call.call(func)");
20270 TestReceiver(i, foreign_context->Global(),
20271 "Function.prototype.call.apply(func)");
20272 TestReceiver(i, foreign_context->Global(),
20273 "Function.prototype.apply.call(func)");
20274 TestReceiver(i, foreign_context->Global(),
20275 "Function.prototype.apply.apply(func)");
20276 // Making calls through built-in functions.
20277 TestReceiver(i, foreign_context->Global(), "[1].map(func)[0]");
20278 // ToString(func()) is func()[0], i.e., the returned this.id.
20279 CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/,func)[1]")));
20280 CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/g,func)[1]")));
20281 CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/g,func)[3]")));
20282
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020283 // Calling with environment record as base.
rossberg@chromium.org9ed27462014-01-07 14:16:41 +000020284 TestReceiver(i, foreign_context->Global(), "func()");
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020285 // Calling with no base.
rossberg@chromium.org9ed27462014-01-07 14:16:41 +000020286 TestReceiver(i, foreign_context->Global(), "(1,func)()");
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020287}
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020288
20289
20290uint8_t callback_fired = 0;
20291
20292
20293void CallCompletedCallback1() {
20294 i::OS::Print("Firing callback 1.\n");
20295 callback_fired ^= 1; // Toggle first bit.
20296}
20297
20298
20299void CallCompletedCallback2() {
20300 i::OS::Print("Firing callback 2.\n");
20301 callback_fired ^= 2; // Toggle second bit.
20302}
20303
20304
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000020305void RecursiveCall(const v8::FunctionCallbackInfo<v8::Value>& args) {
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020306 int32_t level = args[0]->Int32Value();
20307 if (level < 3) {
20308 level++;
20309 i::OS::Print("Entering recursion level %d.\n", level);
20310 char script[64];
20311 i::Vector<char> script_vector(script, sizeof(script));
20312 i::OS::SNPrintF(script_vector, "recursion(%d)", level);
20313 CompileRun(script_vector.start());
20314 i::OS::Print("Leaving recursion level %d.\n", level);
20315 CHECK_EQ(0, callback_fired);
20316 } else {
20317 i::OS::Print("Recursion ends.\n");
20318 CHECK_EQ(0, callback_fired);
20319 }
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020320}
20321
20322
20323TEST(CallCompletedCallback) {
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020324 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020325 v8::HandleScope scope(env->GetIsolate());
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020326 v8::Handle<v8::FunctionTemplate> recursive_runtime =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000020327 v8::FunctionTemplate::New(env->GetIsolate(), RecursiveCall);
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020328 env->Global()->Set(v8_str("recursion"),
20329 recursive_runtime->GetFunction());
20330 // Adding the same callback a second time has no effect.
20331 v8::V8::AddCallCompletedCallback(CallCompletedCallback1);
20332 v8::V8::AddCallCompletedCallback(CallCompletedCallback1);
20333 v8::V8::AddCallCompletedCallback(CallCompletedCallback2);
20334 i::OS::Print("--- Script (1) ---\n");
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000020335 Local<Script> script = v8::Script::Compile(
20336 v8::String::NewFromUtf8(env->GetIsolate(), "recursion(0)"));
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020337 script->Run();
20338 CHECK_EQ(3, callback_fired);
20339
20340 i::OS::Print("\n--- Script (2) ---\n");
20341 callback_fired = 0;
20342 v8::V8::RemoveCallCompletedCallback(CallCompletedCallback1);
20343 script->Run();
20344 CHECK_EQ(2, callback_fired);
20345
20346 i::OS::Print("\n--- Function ---\n");
20347 callback_fired = 0;
20348 Local<Function> recursive_function =
20349 Local<Function>::Cast(env->Global()->Get(v8_str("recursion")));
20350 v8::Handle<Value> args[] = { v8_num(0) };
20351 recursive_function->Call(env->Global(), 1, args);
20352 CHECK_EQ(2, callback_fired);
20353}
20354
20355
20356void CallCompletedCallbackNoException() {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020357 v8::HandleScope scope(CcTest::isolate());
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020358 CompileRun("1+1;");
20359}
20360
20361
20362void CallCompletedCallbackException() {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020363 v8::HandleScope scope(CcTest::isolate());
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020364 CompileRun("throw 'second exception';");
20365}
20366
20367
20368TEST(CallCompletedCallbackOneException) {
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020369 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020370 v8::HandleScope scope(env->GetIsolate());
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020371 v8::V8::AddCallCompletedCallback(CallCompletedCallbackNoException);
20372 CompileRun("throw 'exception';");
20373}
20374
20375
20376TEST(CallCompletedCallbackTwoExceptions) {
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020377 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020378 v8::HandleScope scope(env->GetIsolate());
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020379 v8::V8::AddCallCompletedCallback(CallCompletedCallbackException);
20380 CompileRun("throw 'first exception';");
20381}
ulan@chromium.org812308e2012-02-29 15:58:45 +000020382
20383
20384static int probes_counter = 0;
20385static int misses_counter = 0;
20386static int updates_counter = 0;
20387
20388
20389static int* LookupCounter(const char* name) {
20390 if (strcmp(name, "c:V8.MegamorphicStubCacheProbes") == 0) {
20391 return &probes_counter;
20392 } else if (strcmp(name, "c:V8.MegamorphicStubCacheMisses") == 0) {
20393 return &misses_counter;
20394 } else if (strcmp(name, "c:V8.MegamorphicStubCacheUpdates") == 0) {
20395 return &updates_counter;
20396 }
20397 return NULL;
20398}
20399
20400
20401static const char* kMegamorphicTestProgram =
20402 "function ClassA() { };"
20403 "function ClassB() { };"
20404 "ClassA.prototype.foo = function() { };"
20405 "ClassB.prototype.foo = function() { };"
20406 "function fooify(obj) { obj.foo(); };"
20407 "var a = new ClassA();"
20408 "var b = new ClassB();"
20409 "for (var i = 0; i < 10000; i++) {"
20410 " fooify(a);"
20411 " fooify(b);"
20412 "}";
20413
20414
20415static void StubCacheHelper(bool primary) {
20416 V8::SetCounterFunction(LookupCounter);
20417 USE(kMegamorphicTestProgram);
20418#ifdef DEBUG
20419 i::FLAG_native_code_counters = true;
20420 if (primary) {
20421 i::FLAG_test_primary_stub_cache = true;
20422 } else {
20423 i::FLAG_test_secondary_stub_cache = true;
20424 }
20425 i::FLAG_crankshaft = false;
ulan@chromium.org812308e2012-02-29 15:58:45 +000020426 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020427 v8::HandleScope scope(env->GetIsolate());
ulan@chromium.org812308e2012-02-29 15:58:45 +000020428 int initial_probes = probes_counter;
20429 int initial_misses = misses_counter;
20430 int initial_updates = updates_counter;
20431 CompileRun(kMegamorphicTestProgram);
20432 int probes = probes_counter - initial_probes;
20433 int misses = misses_counter - initial_misses;
20434 int updates = updates_counter - initial_updates;
20435 CHECK_LT(updates, 10);
20436 CHECK_LT(misses, 10);
20437 CHECK_GE(probes, 10000);
20438#endif
20439}
20440
20441
20442TEST(SecondaryStubCache) {
20443 StubCacheHelper(true);
20444}
20445
20446
20447TEST(PrimaryStubCache) {
20448 StubCacheHelper(false);
20449}
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020450
20451
verwaest@chromium.org057bd502013-11-06 12:03:29 +000020452static int cow_arrays_created_runtime = 0;
20453
20454
20455static int* LookupCounterCOWArrays(const char* name) {
20456 if (strcmp(name, "c:V8.COWArraysCreatedRuntime") == 0) {
20457 return &cow_arrays_created_runtime;
20458 }
20459 return NULL;
20460}
20461
20462
20463TEST(CheckCOWArraysCreatedRuntimeCounter) {
20464 V8::SetCounterFunction(LookupCounterCOWArrays);
20465#ifdef DEBUG
20466 i::FLAG_native_code_counters = true;
20467 LocalContext env;
20468 v8::HandleScope scope(env->GetIsolate());
20469 int initial_cow_arrays = cow_arrays_created_runtime;
20470 CompileRun("var o = [1, 2, 3];");
20471 CHECK_EQ(1, cow_arrays_created_runtime - initial_cow_arrays);
20472 CompileRun("var o = {foo: [4, 5, 6], bar: [3, 0]};");
20473 CHECK_EQ(3, cow_arrays_created_runtime - initial_cow_arrays);
20474 CompileRun("var o = {foo: [1, 2, 3, [4, 5, 6]], bar: 'hi'};");
20475 CHECK_EQ(4, cow_arrays_created_runtime - initial_cow_arrays);
20476#endif
20477}
20478
20479
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020480TEST(StaticGetters) {
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020481 LocalContext context;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020482 i::Factory* factory = CcTest::i_isolate()->factory();
20483 v8::Isolate* isolate = CcTest::isolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020484 v8::HandleScope scope(isolate);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000020485 i::Handle<i::Object> undefined_value = factory->undefined_value();
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020486 CHECK(*v8::Utils::OpenHandle(*v8::Undefined(isolate)) == *undefined_value);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000020487 i::Handle<i::Object> null_value = factory->null_value();
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020488 CHECK(*v8::Utils::OpenHandle(*v8::Null(isolate)) == *null_value);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000020489 i::Handle<i::Object> true_value = factory->true_value();
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020490 CHECK(*v8::Utils::OpenHandle(*v8::True(isolate)) == *true_value);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000020491 i::Handle<i::Object> false_value = factory->false_value();
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020492 CHECK(*v8::Utils::OpenHandle(*v8::False(isolate)) == *false_value);
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020493}
20494
20495
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020496UNINITIALIZED_TEST(IsolateEmbedderData) {
20497 CcTest::DisableAutomaticDispose();
20498 v8::Isolate* isolate = v8::Isolate::New();
20499 isolate->Enter();
hpayer@chromium.orgc5d49712013-09-11 08:25:48 +000020500 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
machenbach@chromium.org7ff76072013-11-21 09:47:43 +000020501 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
20502 CHECK_EQ(NULL, isolate->GetData(slot));
20503 CHECK_EQ(NULL, i_isolate->GetData(slot));
20504 }
20505 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
20506 void* data = reinterpret_cast<void*>(0xacce55ed + slot);
20507 isolate->SetData(slot, data);
20508 }
20509 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
20510 void* data = reinterpret_cast<void*>(0xacce55ed + slot);
20511 CHECK_EQ(data, isolate->GetData(slot));
20512 CHECK_EQ(data, i_isolate->GetData(slot));
20513 }
20514 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
20515 void* data = reinterpret_cast<void*>(0xdecea5ed + slot);
20516 isolate->SetData(slot, data);
20517 }
20518 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
20519 void* data = reinterpret_cast<void*>(0xdecea5ed + slot);
20520 CHECK_EQ(data, isolate->GetData(slot));
20521 CHECK_EQ(data, i_isolate->GetData(slot));
20522 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020523 isolate->Exit();
20524 isolate->Dispose();
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020525}
20526
20527
20528TEST(StringEmpty) {
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020529 LocalContext context;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020530 i::Factory* factory = CcTest::i_isolate()->factory();
20531 v8::Isolate* isolate = CcTest::isolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020532 v8::HandleScope scope(isolate);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000020533 i::Handle<i::Object> empty_string = factory->empty_string();
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020534 CHECK(*v8::Utils::OpenHandle(*v8::String::Empty(isolate)) == *empty_string);
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020535}
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020536
20537
20538static int instance_checked_getter_count = 0;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000020539static void InstanceCheckedGetter(
20540 Local<String> name,
20541 const v8::PropertyCallbackInfo<v8::Value>& info) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020542 CHECK_EQ(name, v8_str("foo"));
20543 instance_checked_getter_count++;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000020544 info.GetReturnValue().Set(v8_num(11));
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020545}
20546
20547
20548static int instance_checked_setter_count = 0;
20549static void InstanceCheckedSetter(Local<String> name,
20550 Local<Value> value,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000020551 const v8::PropertyCallbackInfo<void>& info) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020552 CHECK_EQ(name, v8_str("foo"));
20553 CHECK_EQ(value, v8_num(23));
20554 instance_checked_setter_count++;
20555}
20556
20557
20558static void CheckInstanceCheckedResult(int getters,
20559 int setters,
20560 bool expects_callbacks,
20561 TryCatch* try_catch) {
20562 if (expects_callbacks) {
20563 CHECK(!try_catch->HasCaught());
20564 CHECK_EQ(getters, instance_checked_getter_count);
20565 CHECK_EQ(setters, instance_checked_setter_count);
20566 } else {
20567 CHECK(try_catch->HasCaught());
20568 CHECK_EQ(0, instance_checked_getter_count);
20569 CHECK_EQ(0, instance_checked_setter_count);
20570 }
20571 try_catch->Reset();
20572}
20573
20574
20575static void CheckInstanceCheckedAccessors(bool expects_callbacks) {
20576 instance_checked_getter_count = 0;
20577 instance_checked_setter_count = 0;
20578 TryCatch try_catch;
20579
20580 // Test path through generic runtime code.
20581 CompileRun("obj.foo");
20582 CheckInstanceCheckedResult(1, 0, expects_callbacks, &try_catch);
20583 CompileRun("obj.foo = 23");
20584 CheckInstanceCheckedResult(1, 1, expects_callbacks, &try_catch);
20585
20586 // Test path through generated LoadIC and StoredIC.
20587 CompileRun("function test_get(o) { o.foo; }"
20588 "test_get(obj);");
20589 CheckInstanceCheckedResult(2, 1, expects_callbacks, &try_catch);
20590 CompileRun("test_get(obj);");
20591 CheckInstanceCheckedResult(3, 1, expects_callbacks, &try_catch);
20592 CompileRun("test_get(obj);");
20593 CheckInstanceCheckedResult(4, 1, expects_callbacks, &try_catch);
20594 CompileRun("function test_set(o) { o.foo = 23; }"
20595 "test_set(obj);");
20596 CheckInstanceCheckedResult(4, 2, expects_callbacks, &try_catch);
20597 CompileRun("test_set(obj);");
20598 CheckInstanceCheckedResult(4, 3, expects_callbacks, &try_catch);
20599 CompileRun("test_set(obj);");
20600 CheckInstanceCheckedResult(4, 4, expects_callbacks, &try_catch);
20601
20602 // Test path through optimized code.
20603 CompileRun("%OptimizeFunctionOnNextCall(test_get);"
20604 "test_get(obj);");
20605 CheckInstanceCheckedResult(5, 4, expects_callbacks, &try_catch);
20606 CompileRun("%OptimizeFunctionOnNextCall(test_set);"
20607 "test_set(obj);");
20608 CheckInstanceCheckedResult(5, 5, expects_callbacks, &try_catch);
20609
20610 // Cleanup so that closures start out fresh in next check.
20611 CompileRun("%DeoptimizeFunction(test_get);"
20612 "%ClearFunctionTypeFeedback(test_get);"
20613 "%DeoptimizeFunction(test_set);"
20614 "%ClearFunctionTypeFeedback(test_set);");
20615}
20616
20617
20618THREADED_TEST(InstanceCheckOnInstanceAccessor) {
20619 v8::internal::FLAG_allow_natives_syntax = true;
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020620 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020621 v8::HandleScope scope(context->GetIsolate());
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020622
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000020623 Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020624 Local<ObjectTemplate> inst = templ->InstanceTemplate();
20625 inst->SetAccessor(v8_str("foo"),
20626 InstanceCheckedGetter, InstanceCheckedSetter,
20627 Handle<Value>(),
20628 v8::DEFAULT,
20629 v8::None,
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000020630 v8::AccessorSignature::New(context->GetIsolate(), templ));
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020631 context->Global()->Set(v8_str("f"), templ->GetFunction());
20632
20633 printf("Testing positive ...\n");
20634 CompileRun("var obj = new f();");
20635 CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
20636 CheckInstanceCheckedAccessors(true);
20637
20638 printf("Testing negative ...\n");
20639 CompileRun("var obj = {};"
20640 "obj.__proto__ = new f();");
20641 CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
20642 CheckInstanceCheckedAccessors(false);
20643}
20644
20645
20646THREADED_TEST(InstanceCheckOnInstanceAccessorWithInterceptor) {
20647 v8::internal::FLAG_allow_natives_syntax = true;
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020648 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020649 v8::HandleScope scope(context->GetIsolate());
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020650
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000020651 Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020652 Local<ObjectTemplate> inst = templ->InstanceTemplate();
20653 AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter);
20654 inst->SetAccessor(v8_str("foo"),
20655 InstanceCheckedGetter, InstanceCheckedSetter,
20656 Handle<Value>(),
20657 v8::DEFAULT,
20658 v8::None,
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000020659 v8::AccessorSignature::New(context->GetIsolate(), templ));
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020660 context->Global()->Set(v8_str("f"), templ->GetFunction());
20661
20662 printf("Testing positive ...\n");
20663 CompileRun("var obj = new f();");
20664 CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
20665 CheckInstanceCheckedAccessors(true);
20666
20667 printf("Testing negative ...\n");
20668 CompileRun("var obj = {};"
20669 "obj.__proto__ = new f();");
20670 CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
20671 CheckInstanceCheckedAccessors(false);
20672}
20673
20674
20675THREADED_TEST(InstanceCheckOnPrototypeAccessor) {
20676 v8::internal::FLAG_allow_natives_syntax = true;
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020677 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020678 v8::HandleScope scope(context->GetIsolate());
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020679
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000020680 Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020681 Local<ObjectTemplate> proto = templ->PrototypeTemplate();
20682 proto->SetAccessor(v8_str("foo"),
20683 InstanceCheckedGetter, InstanceCheckedSetter,
20684 Handle<Value>(),
20685 v8::DEFAULT,
20686 v8::None,
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000020687 v8::AccessorSignature::New(context->GetIsolate(), templ));
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020688 context->Global()->Set(v8_str("f"), templ->GetFunction());
20689
20690 printf("Testing positive ...\n");
20691 CompileRun("var obj = new f();");
20692 CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
20693 CheckInstanceCheckedAccessors(true);
20694
20695 printf("Testing negative ...\n");
20696 CompileRun("var obj = {};"
20697 "obj.__proto__ = new f();");
20698 CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
20699 CheckInstanceCheckedAccessors(false);
20700
20701 printf("Testing positive with modified prototype chain ...\n");
20702 CompileRun("var obj = new f();"
20703 "var pro = {};"
20704 "pro.__proto__ = obj.__proto__;"
20705 "obj.__proto__ = pro;");
20706 CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
20707 CheckInstanceCheckedAccessors(true);
20708}
20709
20710
20711TEST(TryFinallyMessage) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020712 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020713 v8::HandleScope scope(context->GetIsolate());
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020714 {
20715 // Test that the original error message is not lost if there is a
20716 // recursive call into Javascript is done in the finally block, e.g. to
20717 // initialize an IC. (crbug.com/129171)
20718 TryCatch try_catch;
20719 const char* trigger_ic =
20720 "try { \n"
20721 " throw new Error('test'); \n"
20722 "} finally { \n"
20723 " var x = 0; \n"
20724 " x++; \n" // Trigger an IC initialization here.
20725 "} \n";
20726 CompileRun(trigger_ic);
20727 CHECK(try_catch.HasCaught());
20728 Local<Message> message = try_catch.Message();
20729 CHECK(!message.IsEmpty());
20730 CHECK_EQ(2, message->GetLineNumber());
20731 }
20732
20733 {
20734 // Test that the original exception message is indeed overwritten if
20735 // a new error is thrown in the finally block.
20736 TryCatch try_catch;
20737 const char* throw_again =
20738 "try { \n"
20739 " throw new Error('test'); \n"
20740 "} finally { \n"
20741 " var x = 0; \n"
20742 " x++; \n"
20743 " throw new Error('again'); \n" // This is the new uncaught error.
20744 "} \n";
20745 CompileRun(throw_again);
20746 CHECK(try_catch.HasCaught());
20747 Local<Message> message = try_catch.Message();
20748 CHECK(!message.IsEmpty());
20749 CHECK_EQ(6, message->GetLineNumber());
20750 }
20751}
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000020752
20753
erik.corry@gmail.com88767242012-08-08 14:43:45 +000020754static void Helper137002(bool do_store,
20755 bool polymorphic,
20756 bool remove_accessor,
20757 bool interceptor) {
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000020758 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000020759 Local<ObjectTemplate> templ = ObjectTemplate::New(context->GetIsolate());
erik.corry@gmail.com88767242012-08-08 14:43:45 +000020760 if (interceptor) {
20761 templ->SetNamedPropertyHandler(FooGetInterceptor, FooSetInterceptor);
20762 } else {
20763 templ->SetAccessor(v8_str("foo"),
20764 GetterWhichReturns42,
20765 SetterWhichSetsYOnThisTo23);
20766 }
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000020767 context->Global()->Set(v8_str("obj"), templ->NewInstance());
20768
20769 // Turn monomorphic on slow object with native accessor, then turn
20770 // polymorphic, finally optimize to create negative lookup and fail.
erik.corry@gmail.com88767242012-08-08 14:43:45 +000020771 CompileRun(do_store ?
20772 "function f(x) { x.foo = void 0; }" :
20773 "function f(x) { return x.foo; }");
20774 CompileRun("obj.y = void 0;");
20775 if (!interceptor) {
20776 CompileRun("%OptimizeObjectForAddingMultipleProperties(obj, 1);");
20777 }
20778 CompileRun("obj.__proto__ = null;"
20779 "f(obj); f(obj); f(obj);");
20780 if (polymorphic) {
20781 CompileRun("f({});");
20782 }
20783 CompileRun("obj.y = void 0;"
20784 "%OptimizeFunctionOnNextCall(f);");
20785 if (remove_accessor) {
20786 CompileRun("delete obj.foo;");
20787 }
20788 CompileRun("var result = f(obj);");
20789 if (do_store) {
20790 CompileRun("result = obj.y;");
20791 }
20792 if (remove_accessor && !interceptor) {
20793 CHECK(context->Global()->Get(v8_str("result"))->IsUndefined());
20794 } else {
20795 CHECK_EQ(do_store ? 23 : 42,
20796 context->Global()->Get(v8_str("result"))->Int32Value());
20797 }
20798}
20799
20800
20801THREADED_TEST(Regress137002a) {
20802 i::FLAG_allow_natives_syntax = true;
20803 i::FLAG_compilation_cache = false;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020804 v8::HandleScope scope(CcTest::isolate());
erik.corry@gmail.com88767242012-08-08 14:43:45 +000020805 for (int i = 0; i < 16; i++) {
20806 Helper137002(i & 8, i & 4, i & 2, i & 1);
20807 }
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000020808}
20809
20810
20811THREADED_TEST(Regress137002b) {
20812 i::FLAG_allow_natives_syntax = true;
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000020813 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000020814 v8::Isolate* isolate = context->GetIsolate();
20815 v8::HandleScope scope(isolate);
20816 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000020817 templ->SetAccessor(v8_str("foo"),
20818 GetterWhichReturns42,
20819 SetterWhichSetsYOnThisTo23);
20820 context->Global()->Set(v8_str("obj"), templ->NewInstance());
20821
20822 // Turn monomorphic on slow object with native accessor, then just
20823 // delete the property and fail.
erik.corry@gmail.com88767242012-08-08 14:43:45 +000020824 CompileRun("function load(x) { return x.foo; }"
20825 "function store(x) { x.foo = void 0; }"
20826 "function keyed_load(x, key) { return x[key]; }"
20827 // Second version of function has a different source (add void 0)
20828 // so that it does not share code with the first version. This
20829 // ensures that the ICs are monomorphic.
20830 "function load2(x) { void 0; return x.foo; }"
20831 "function store2(x) { void 0; x.foo = void 0; }"
20832 "function keyed_load2(x, key) { void 0; return x[key]; }"
20833
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000020834 "obj.y = void 0;"
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000020835 "obj.__proto__ = null;"
erik.corry@gmail.com88767242012-08-08 14:43:45 +000020836 "var subobj = {};"
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000020837 "subobj.y = void 0;"
erik.corry@gmail.com88767242012-08-08 14:43:45 +000020838 "subobj.__proto__ = obj;"
20839 "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
20840
20841 // Make the ICs monomorphic.
20842 "load(obj); load(obj);"
20843 "load2(subobj); load2(subobj);"
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000020844 "store(obj); store(obj);"
20845 "store2(subobj); store2(subobj);"
erik.corry@gmail.com88767242012-08-08 14:43:45 +000020846 "keyed_load(obj, 'foo'); keyed_load(obj, 'foo');"
20847 "keyed_load2(subobj, 'foo'); keyed_load2(subobj, 'foo');"
20848
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000020849 // Actually test the shiny new ICs and better not crash. This
20850 // serves as a regression test for issue 142088 as well.
20851 "load(obj);"
20852 "load2(subobj);"
20853 "store(obj);"
20854 "store2(subobj);"
20855 "keyed_load(obj, 'foo');"
20856 "keyed_load2(subobj, 'foo');"
20857
erik.corry@gmail.com88767242012-08-08 14:43:45 +000020858 // Delete the accessor. It better not be called any more now.
20859 "delete obj.foo;"
20860 "obj.y = void 0;"
20861 "subobj.y = void 0;"
20862
20863 "var load_result = load(obj);"
20864 "var load_result2 = load2(subobj);"
20865 "var keyed_load_result = keyed_load(obj, 'foo');"
20866 "var keyed_load_result2 = keyed_load2(subobj, 'foo');"
20867 "store(obj);"
20868 "store2(subobj);"
20869 "var y_from_obj = obj.y;"
20870 "var y_from_subobj = subobj.y;");
20871 CHECK(context->Global()->Get(v8_str("load_result"))->IsUndefined());
20872 CHECK(context->Global()->Get(v8_str("load_result2"))->IsUndefined());
20873 CHECK(context->Global()->Get(v8_str("keyed_load_result"))->IsUndefined());
20874 CHECK(context->Global()->Get(v8_str("keyed_load_result2"))->IsUndefined());
20875 CHECK(context->Global()->Get(v8_str("y_from_obj"))->IsUndefined());
20876 CHECK(context->Global()->Get(v8_str("y_from_subobj"))->IsUndefined());
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000020877}
verwaest@chromium.org753aee42012-07-17 16:15:42 +000020878
20879
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000020880THREADED_TEST(Regress142088) {
20881 i::FLAG_allow_natives_syntax = true;
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000020882 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000020883 v8::Isolate* isolate = context->GetIsolate();
20884 v8::HandleScope scope(isolate);
20885 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000020886 templ->SetAccessor(v8_str("foo"),
20887 GetterWhichReturns42,
20888 SetterWhichSetsYOnThisTo23);
20889 context->Global()->Set(v8_str("obj"), templ->NewInstance());
20890
20891 CompileRun("function load(x) { return x.foo; }"
20892 "var o = Object.create(obj);"
20893 "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
20894 "load(o); load(o); load(o); load(o);");
20895}
20896
20897
verwaest@chromium.org753aee42012-07-17 16:15:42 +000020898THREADED_TEST(Regress137496) {
20899 i::FLAG_expose_gc = true;
verwaest@chromium.org753aee42012-07-17 16:15:42 +000020900 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020901 v8::HandleScope scope(context->GetIsolate());
verwaest@chromium.org753aee42012-07-17 16:15:42 +000020902
20903 // Compile a try-finally clause where the finally block causes a GC
20904 // while there still is a message pending for external reporting.
20905 TryCatch try_catch;
20906 try_catch.SetVerbose(true);
20907 CompileRun("try { throw new Error(); } finally { gc(); }");
20908 CHECK(try_catch.HasCaught());
20909}
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000020910
20911
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000020912THREADED_TEST(Regress149912) {
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000020913 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020914 v8::HandleScope scope(context->GetIsolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000020915 Handle<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000020916 AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter);
20917 context->Global()->Set(v8_str("Bug"), templ->GetFunction());
20918 CompileRun("Number.prototype.__proto__ = new Bug; var x = 0; x.foo();");
20919}
20920
20921
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000020922THREADED_TEST(Regress157124) {
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000020923 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000020924 v8::Isolate* isolate = context->GetIsolate();
20925 v8::HandleScope scope(isolate);
20926 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000020927 Local<Object> obj = templ->NewInstance();
20928 obj->GetIdentityHash();
20929 obj->DeleteHiddenValue(v8_str("Bug"));
20930}
20931
20932
ulan@chromium.org6e196bf2013-03-13 09:38:22 +000020933THREADED_TEST(Regress2535) {
20934 i::FLAG_harmony_collections = true;
ulan@chromium.org6e196bf2013-03-13 09:38:22 +000020935 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020936 v8::HandleScope scope(context->GetIsolate());
ulan@chromium.org6e196bf2013-03-13 09:38:22 +000020937 Local<Value> set_value = CompileRun("new Set();");
danno@chromium.orgf95d4b92013-06-13 14:40:17 +000020938 Local<Object> set_object(Local<Object>::Cast(set_value));
ulan@chromium.org6e196bf2013-03-13 09:38:22 +000020939 CHECK_EQ(0, set_object->InternalFieldCount());
20940 Local<Value> map_value = CompileRun("new Map();");
danno@chromium.orgf95d4b92013-06-13 14:40:17 +000020941 Local<Object> map_object(Local<Object>::Cast(map_value));
ulan@chromium.org6e196bf2013-03-13 09:38:22 +000020942 CHECK_EQ(0, map_object->InternalFieldCount());
20943}
20944
20945
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000020946THREADED_TEST(Regress2746) {
20947 LocalContext context;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000020948 v8::Isolate* isolate = context->GetIsolate();
20949 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000020950 Local<Object> obj = Object::New(isolate);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000020951 Local<String> key = String::NewFromUtf8(context->GetIsolate(), "key");
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000020952 obj->SetHiddenValue(key, v8::Undefined(isolate));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000020953 Local<Value> value = obj->GetHiddenValue(key);
20954 CHECK(!value.IsEmpty());
20955 CHECK(value->IsUndefined());
20956}
20957
20958
jkummerow@chromium.org10480472013-07-17 08:22:15 +000020959THREADED_TEST(Regress260106) {
20960 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000020961 v8::Isolate* isolate = context->GetIsolate();
20962 v8::HandleScope scope(isolate);
20963 Local<FunctionTemplate> templ = FunctionTemplate::New(isolate,
20964 DummyCallHandler);
jkummerow@chromium.org10480472013-07-17 08:22:15 +000020965 CompileRun("for (var i = 0; i < 128; i++) Object.prototype[i] = 0;");
20966 Local<Function> function = templ->GetFunction();
20967 CHECK(!function.IsEmpty());
20968 CHECK(function->IsFunction());
20969}
20970
20971
danno@chromium.org59400602013-08-13 17:09:37 +000020972THREADED_TEST(JSONParseObject) {
20973 LocalContext context;
20974 HandleScope scope(context->GetIsolate());
20975 Local<Value> obj = v8::JSON::Parse(v8_str("{\"x\":42}"));
20976 Handle<Object> global = context->Global();
20977 global->Set(v8_str("obj"), obj);
20978 ExpectString("JSON.stringify(obj)", "{\"x\":42}");
20979}
20980
20981
20982THREADED_TEST(JSONParseNumber) {
20983 LocalContext context;
20984 HandleScope scope(context->GetIsolate());
20985 Local<Value> obj = v8::JSON::Parse(v8_str("42"));
20986 Handle<Object> global = context->Global();
20987 global->Set(v8_str("obj"), obj);
20988 ExpectString("JSON.stringify(obj)", "42");
20989}
20990
20991
verwaest@chromium.org662436e2013-08-28 08:41:27 +000020992#if V8_OS_POSIX
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000020993class ThreadInterruptTest {
20994 public:
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000020995 ThreadInterruptTest() : sem_(0), sem_value_(0) { }
20996 ~ThreadInterruptTest() {}
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000020997
20998 void RunTest() {
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000020999 InterruptThread i_thread(this);
21000 i_thread.Start();
21001
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000021002 sem_.Wait();
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000021003 CHECK_EQ(kExpectedValue, sem_value_);
21004 }
21005
21006 private:
21007 static const int kExpectedValue = 1;
21008
21009 class InterruptThread : public i::Thread {
21010 public:
21011 explicit InterruptThread(ThreadInterruptTest* test)
21012 : Thread("InterruptThread"), test_(test) {}
21013
21014 virtual void Run() {
21015 struct sigaction action;
21016
21017 // Ensure that we'll enter waiting condition
21018 i::OS::Sleep(100);
21019
21020 // Setup signal handler
21021 memset(&action, 0, sizeof(action));
21022 action.sa_handler = SignalHandler;
21023 sigaction(SIGCHLD, &action, NULL);
21024
21025 // Send signal
21026 kill(getpid(), SIGCHLD);
21027
21028 // Ensure that if wait has returned because of error
21029 i::OS::Sleep(100);
21030
21031 // Set value and signal semaphore
21032 test_->sem_value_ = 1;
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000021033 test_->sem_.Signal();
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000021034 }
21035
21036 static void SignalHandler(int signal) {
21037 }
21038
21039 private:
21040 ThreadInterruptTest* test_;
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000021041 };
21042
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000021043 i::Semaphore sem_;
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000021044 volatile int sem_value_;
21045};
21046
21047
21048THREADED_TEST(SemaphoreInterruption) {
21049 ThreadInterruptTest().RunTest();
21050}
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000021051
danno@chromium.org169691d2013-07-15 08:01:13 +000021052
hpayer@chromium.orgea9b8ba2013-12-20 19:22:39 +000021053#endif // V8_OS_POSIX
21054
21055
danno@chromium.org169691d2013-07-15 08:01:13 +000021056static bool NamedAccessAlwaysBlocked(Local<v8::Object> global,
21057 Local<Value> name,
21058 v8::AccessType type,
21059 Local<Value> data) {
21060 i::PrintF("Named access blocked.\n");
21061 return false;
21062}
21063
21064
21065static bool IndexAccessAlwaysBlocked(Local<v8::Object> global,
21066 uint32_t key,
21067 v8::AccessType type,
21068 Local<Value> data) {
21069 i::PrintF("Indexed access blocked.\n");
21070 return false;
21071}
21072
21073
21074void UnreachableCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
21075 CHECK(false);
21076}
21077
21078
21079TEST(JSONStringifyAccessCheck) {
21080 v8::V8::Initialize();
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000021081 v8::Isolate* isolate = CcTest::isolate();
21082 v8::HandleScope scope(isolate);
danno@chromium.org169691d2013-07-15 08:01:13 +000021083
21084 // Create an ObjectTemplate for global objects and install access
21085 // check callbacks that will block access.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000021086 v8::Handle<v8::ObjectTemplate> global_template =
21087 v8::ObjectTemplate::New(isolate);
danno@chromium.org169691d2013-07-15 08:01:13 +000021088 global_template->SetAccessCheckCallbacks(NamedAccessAlwaysBlocked,
21089 IndexAccessAlwaysBlocked);
21090
21091 // Create a context and set an x property on it's global object.
21092 LocalContext context0(NULL, global_template);
21093 v8::Handle<v8::Object> global0 = context0->Global();
21094 global0->Set(v8_str("x"), v8_num(42));
21095 ExpectString("JSON.stringify(this)", "{\"x\":42}");
21096
21097 for (int i = 0; i < 2; i++) {
21098 if (i == 1) {
21099 // Install a toJSON function on the second run.
21100 v8::Handle<v8::FunctionTemplate> toJSON =
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000021101 v8::FunctionTemplate::New(isolate, UnreachableCallback);
danno@chromium.org169691d2013-07-15 08:01:13 +000021102
21103 global0->Set(v8_str("toJSON"), toJSON->GetFunction());
21104 }
21105 // Create a context with a different security token so that the
21106 // failed access check callback will be called on each access.
21107 LocalContext context1(NULL, global_template);
21108 context1->Global()->Set(v8_str("other"), global0);
21109
21110 ExpectString("JSON.stringify(other)", "{}");
21111 ExpectString("JSON.stringify({ 'a' : other, 'b' : ['c'] })",
21112 "{\"a\":{},\"b\":[\"c\"]}");
21113 ExpectString("JSON.stringify([other, 'b', 'c'])",
21114 "[{},\"b\",\"c\"]");
21115
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000021116 v8::Handle<v8::Array> array = v8::Array::New(isolate, 2);
danno@chromium.org169691d2013-07-15 08:01:13 +000021117 array->Set(0, v8_str("a"));
21118 array->Set(1, v8_str("b"));
21119 context1->Global()->Set(v8_str("array"), array);
21120 ExpectString("JSON.stringify(array)", "[\"a\",\"b\"]");
21121 array->TurnOnAccessCheck();
21122 ExpectString("JSON.stringify(array)", "[]");
21123 ExpectString("JSON.stringify([array])", "[[]]");
21124 ExpectString("JSON.stringify({'a' : array})", "{\"a\":[]}");
21125 }
21126}
21127
21128
21129bool access_check_fail_thrown = false;
21130bool catch_callback_called = false;
21131
21132
21133// Failed access check callback that performs a GC on each invocation.
21134void FailedAccessCheckThrows(Local<v8::Object> target,
21135 v8::AccessType type,
21136 Local<v8::Value> data) {
21137 access_check_fail_thrown = true;
21138 i::PrintF("Access check failed. Error thrown.\n");
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000021139 CcTest::isolate()->ThrowException(
21140 v8::Exception::Error(v8_str("cross context")));
danno@chromium.org169691d2013-07-15 08:01:13 +000021141}
21142
21143
21144void CatcherCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
21145 for (int i = 0; i < args.Length(); i++) {
21146 i::PrintF("%s\n", *String::Utf8Value(args[i]));
21147 }
21148 catch_callback_called = true;
21149}
21150
21151
21152void HasOwnPropertyCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
21153 args[0]->ToObject()->HasOwnProperty(args[1]->ToString());
21154}
21155
21156
21157void CheckCorrectThrow(const char* script) {
21158 // Test that the script, when wrapped into a try-catch, triggers the catch
21159 // clause due to failed access check throwing an exception.
21160 // The subsequent try-catch should run without any exception.
21161 access_check_fail_thrown = false;
21162 catch_callback_called = false;
21163 i::ScopedVector<char> source(1024);
21164 i::OS::SNPrintF(source, "try { %s; } catch (e) { catcher(e); }", script);
21165 CompileRun(source.start());
21166 CHECK(access_check_fail_thrown);
21167 CHECK(catch_callback_called);
21168
21169 access_check_fail_thrown = false;
21170 catch_callback_called = false;
21171 CompileRun("try { [1, 2, 3].sort(); } catch (e) { catcher(e) };");
21172 CHECK(!access_check_fail_thrown);
21173 CHECK(!catch_callback_called);
21174}
21175
21176
21177TEST(AccessCheckThrows) {
21178 i::FLAG_allow_natives_syntax = true;
21179 v8::V8::Initialize();
21180 v8::V8::SetFailedAccessCheckCallbackFunction(&FailedAccessCheckThrows);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000021181 v8::Isolate* isolate = CcTest::isolate();
21182 v8::HandleScope scope(isolate);
danno@chromium.org169691d2013-07-15 08:01:13 +000021183
21184 // Create an ObjectTemplate for global objects and install access
21185 // check callbacks that will block access.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000021186 v8::Handle<v8::ObjectTemplate> global_template =
21187 v8::ObjectTemplate::New(isolate);
danno@chromium.org169691d2013-07-15 08:01:13 +000021188 global_template->SetAccessCheckCallbacks(NamedAccessAlwaysBlocked,
21189 IndexAccessAlwaysBlocked);
21190
21191 // Create a context and set an x property on it's global object.
21192 LocalContext context0(NULL, global_template);
21193 context0->Global()->Set(v8_str("x"), v8_num(42));
21194 v8::Handle<v8::Object> global0 = context0->Global();
21195
21196 // Create a context with a different security token so that the
21197 // failed access check callback will be called on each access.
21198 LocalContext context1(NULL, global_template);
21199 context1->Global()->Set(v8_str("other"), global0);
21200
21201 v8::Handle<v8::FunctionTemplate> catcher_fun =
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000021202 v8::FunctionTemplate::New(isolate, CatcherCallback);
danno@chromium.org169691d2013-07-15 08:01:13 +000021203 context1->Global()->Set(v8_str("catcher"), catcher_fun->GetFunction());
21204
21205 v8::Handle<v8::FunctionTemplate> has_own_property_fun =
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000021206 v8::FunctionTemplate::New(isolate, HasOwnPropertyCallback);
danno@chromium.org169691d2013-07-15 08:01:13 +000021207 context1->Global()->Set(v8_str("has_own_property"),
21208 has_own_property_fun->GetFunction());
21209
21210 { v8::TryCatch try_catch;
21211 access_check_fail_thrown = false;
21212 CompileRun("other.x;");
21213 CHECK(access_check_fail_thrown);
21214 CHECK(try_catch.HasCaught());
21215 }
21216
21217 CheckCorrectThrow("other.x");
21218 CheckCorrectThrow("other[1]");
21219 CheckCorrectThrow("JSON.stringify(other)");
21220 CheckCorrectThrow("has_own_property(other, 'x')");
21221 CheckCorrectThrow("%GetProperty(other, 'x')");
21222 CheckCorrectThrow("%SetProperty(other, 'x', 'foo', 1, 0)");
21223 CheckCorrectThrow("%IgnoreAttributesAndSetProperty(other, 'x', 'foo')");
21224 CheckCorrectThrow("%DeleteProperty(other, 'x', 0)");
21225 CheckCorrectThrow("%DeleteProperty(other, '1', 0)");
21226 CheckCorrectThrow("%HasLocalProperty(other, 'x')");
21227 CheckCorrectThrow("%HasProperty(other, 'x')");
21228 CheckCorrectThrow("%HasElement(other, 1)");
21229 CheckCorrectThrow("%IsPropertyEnumerable(other, 'x')");
21230 CheckCorrectThrow("%GetPropertyNames(other)");
21231 CheckCorrectThrow("%GetLocalPropertyNames(other, true)");
21232 CheckCorrectThrow("%DefineOrRedefineAccessorProperty("
21233 "other, 'x', null, null, 1)");
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +000021234
21235 // Reset the failed access check callback so it does not influence
21236 // the other tests.
21237 v8::V8::SetFailedAccessCheckCallbackFunction(NULL);
danno@chromium.org169691d2013-07-15 08:01:13 +000021238}
21239
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000021240
21241THREADED_TEST(Regress256330) {
21242 i::FLAG_allow_natives_syntax = true;
21243 LocalContext context;
21244 v8::HandleScope scope(context->GetIsolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000021245 Handle<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000021246 AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter);
21247 context->Global()->Set(v8_str("Bug"), templ->GetFunction());
21248 CompileRun("\"use strict\"; var o = new Bug;"
21249 "function f(o) { o.x = 10; };"
21250 "f(o); f(o); f(o);"
21251 "%OptimizeFunctionOnNextCall(f);"
21252 "f(o);");
21253 ExpectBoolean("%GetOptimizationStatus(f) != 2", true);
21254}
21255
21256
21257THREADED_TEST(CrankshaftInterceptorSetter) {
21258 i::FLAG_allow_natives_syntax = true;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000021259 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000021260 Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000021261 AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
21262 LocalContext env;
21263 env->Global()->Set(v8_str("Obj"), templ->GetFunction());
21264 CompileRun("var obj = new Obj;"
21265 // Initialize fields to avoid transitions later.
21266 "obj.age = 0;"
21267 "obj.accessor_age = 42;"
21268 "function setter(i) { this.accessor_age = i; };"
21269 "function getter() { return this.accessor_age; };"
21270 "function setAge(i) { obj.age = i; };"
21271 "Object.defineProperty(obj, 'age', { get:getter, set:setter });"
21272 "setAge(1);"
21273 "setAge(2);"
21274 "setAge(3);"
21275 "%OptimizeFunctionOnNextCall(setAge);"
21276 "setAge(4);");
21277 // All stores went through the interceptor.
21278 ExpectInt32("obj.interceptor_age", 4);
21279 ExpectInt32("obj.accessor_age", 42);
21280}
21281
21282
21283THREADED_TEST(CrankshaftInterceptorGetter) {
21284 i::FLAG_allow_natives_syntax = true;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000021285 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000021286 Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000021287 AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
21288 LocalContext env;
21289 env->Global()->Set(v8_str("Obj"), templ->GetFunction());
21290 CompileRun("var obj = new Obj;"
21291 // Initialize fields to avoid transitions later.
21292 "obj.age = 1;"
21293 "obj.accessor_age = 42;"
21294 "function getter() { return this.accessor_age; };"
21295 "function getAge() { return obj.interceptor_age; };"
21296 "Object.defineProperty(obj, 'interceptor_age', { get:getter });"
21297 "getAge();"
21298 "getAge();"
21299 "getAge();"
21300 "%OptimizeFunctionOnNextCall(getAge);");
21301 // Access through interceptor.
21302 ExpectInt32("getAge()", 1);
21303}
21304
21305
21306THREADED_TEST(CrankshaftInterceptorFieldRead) {
21307 i::FLAG_allow_natives_syntax = true;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000021308 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000021309 Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000021310 AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
21311 LocalContext env;
21312 env->Global()->Set(v8_str("Obj"), templ->GetFunction());
21313 CompileRun("var obj = new Obj;"
21314 "obj.__proto__.interceptor_age = 42;"
21315 "obj.age = 100;"
21316 "function getAge() { return obj.interceptor_age; };");
21317 ExpectInt32("getAge();", 100);
21318 ExpectInt32("getAge();", 100);
21319 ExpectInt32("getAge();", 100);
21320 CompileRun("%OptimizeFunctionOnNextCall(getAge);");
21321 // Access through interceptor.
21322 ExpectInt32("getAge();", 100);
21323}
21324
21325
21326THREADED_TEST(CrankshaftInterceptorFieldWrite) {
21327 i::FLAG_allow_natives_syntax = true;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000021328 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000021329 Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000021330 AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
21331 LocalContext env;
21332 env->Global()->Set(v8_str("Obj"), templ->GetFunction());
21333 CompileRun("var obj = new Obj;"
21334 "obj.age = 100000;"
21335 "function setAge(i) { obj.age = i };"
21336 "setAge(100);"
21337 "setAge(101);"
21338 "setAge(102);"
21339 "%OptimizeFunctionOnNextCall(setAge);"
21340 "setAge(103);");
21341 ExpectInt32("obj.age", 100000);
21342 ExpectInt32("obj.interceptor_age", 103);
21343}
21344
dslomov@chromium.org639bac02013-09-09 11:58:54 +000021345
hpayer@chromium.orgea9b8ba2013-12-20 19:22:39 +000021346class RequestInterruptTestBase {
21347 public:
21348 RequestInterruptTestBase()
21349 : env_(),
21350 isolate_(env_->GetIsolate()),
21351 sem_(0),
21352 warmup_(20000),
21353 should_continue_(true) {
21354 }
21355
21356 virtual ~RequestInterruptTestBase() { }
21357
21358 virtual void TestBody() = 0;
21359
21360 void RunTest() {
21361 InterruptThread i_thread(this);
21362 i_thread.Start();
21363
21364 v8::HandleScope handle_scope(isolate_);
21365
21366 TestBody();
21367
21368 isolate_->ClearInterrupt();
21369
21370 // Verify we arrived here because interruptor was called
21371 // not due to a bug causing us to exit the loop too early.
21372 CHECK(!should_continue());
21373 }
21374
21375 void WakeUpInterruptor() {
21376 sem_.Signal();
21377 }
21378
21379 bool should_continue() const { return should_continue_; }
21380
21381 bool ShouldContinue() {
21382 if (warmup_ > 0) {
21383 if (--warmup_ == 0) {
21384 WakeUpInterruptor();
21385 }
21386 }
21387
21388 return should_continue_;
21389 }
21390
21391 protected:
21392 static void ShouldContinueCallback(
21393 const v8::FunctionCallbackInfo<Value>& info) {
21394 RequestInterruptTestBase* test =
21395 reinterpret_cast<RequestInterruptTestBase*>(
21396 info.Data().As<v8::External>()->Value());
21397 info.GetReturnValue().Set(test->ShouldContinue());
21398 }
21399
21400 class InterruptThread : public i::Thread {
21401 public:
21402 explicit InterruptThread(RequestInterruptTestBase* test)
21403 : Thread("RequestInterruptTest"), test_(test) {}
21404
21405 virtual void Run() {
21406 test_->sem_.Wait();
21407 test_->isolate_->RequestInterrupt(&OnInterrupt, test_);
21408 }
21409
21410 static void OnInterrupt(v8::Isolate* isolate, void* data) {
21411 reinterpret_cast<RequestInterruptTestBase*>(data)->
21412 should_continue_ = false;
21413 }
21414
21415 private:
21416 RequestInterruptTestBase* test_;
21417 };
21418
21419 LocalContext env_;
21420 v8::Isolate* isolate_;
21421 i::Semaphore sem_;
21422 int warmup_;
21423 bool should_continue_;
21424};
21425
21426
21427class RequestInterruptTestWithFunctionCall : public RequestInterruptTestBase {
21428 public:
21429 virtual void TestBody() {
21430 Local<Function> func = Function::New(
21431 isolate_, ShouldContinueCallback, v8::External::New(isolate_, this));
21432 env_->Global()->Set(v8_str("ShouldContinue"), func);
21433
21434 CompileRun("while (ShouldContinue()) { }");
21435 }
21436};
21437
21438
21439class RequestInterruptTestWithMethodCall : public RequestInterruptTestBase {
21440 public:
21441 virtual void TestBody() {
21442 v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
21443 v8::Local<v8::Template> proto = t->PrototypeTemplate();
21444 proto->Set(v8_str("shouldContinue"), Function::New(
21445 isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
21446 env_->Global()->Set(v8_str("Klass"), t->GetFunction());
21447
21448 CompileRun("var obj = new Klass; while (obj.shouldContinue()) { }");
21449 }
21450};
21451
21452
21453class RequestInterruptTestWithAccessor : public RequestInterruptTestBase {
21454 public:
21455 virtual void TestBody() {
21456 v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
21457 v8::Local<v8::Template> proto = t->PrototypeTemplate();
21458 proto->SetAccessorProperty(v8_str("shouldContinue"), FunctionTemplate::New(
21459 isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
21460 env_->Global()->Set(v8_str("Klass"), t->GetFunction());
21461
21462 CompileRun("var obj = new Klass; while (obj.shouldContinue) { }");
21463 }
21464};
21465
21466
21467class RequestInterruptTestWithNativeAccessor : public RequestInterruptTestBase {
21468 public:
21469 virtual void TestBody() {
21470 v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
21471 t->InstanceTemplate()->SetNativeDataProperty(
21472 v8_str("shouldContinue"),
21473 &ShouldContinueNativeGetter,
21474 NULL,
21475 v8::External::New(isolate_, this));
21476 env_->Global()->Set(v8_str("Klass"), t->GetFunction());
21477
21478 CompileRun("var obj = new Klass; while (obj.shouldContinue) { }");
21479 }
21480
21481 private:
21482 static void ShouldContinueNativeGetter(
21483 Local<String> property,
21484 const v8::PropertyCallbackInfo<v8::Value>& info) {
21485 RequestInterruptTestBase* test =
21486 reinterpret_cast<RequestInterruptTestBase*>(
21487 info.Data().As<v8::External>()->Value());
21488 info.GetReturnValue().Set(test->ShouldContinue());
21489 }
21490};
21491
21492
21493class RequestInterruptTestWithMethodCallAndInterceptor
21494 : public RequestInterruptTestBase {
21495 public:
21496 virtual void TestBody() {
21497 v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
21498 v8::Local<v8::Template> proto = t->PrototypeTemplate();
21499 proto->Set(v8_str("shouldContinue"), Function::New(
21500 isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
21501 v8::Local<v8::ObjectTemplate> instance_template = t->InstanceTemplate();
21502 instance_template->SetNamedPropertyHandler(EmptyInterceptor);
21503
21504 env_->Global()->Set(v8_str("Klass"), t->GetFunction());
21505
21506 CompileRun("var obj = new Klass; while (obj.shouldContinue()) { }");
21507 }
21508
21509 private:
21510 static void EmptyInterceptor(
21511 Local<String> property,
21512 const v8::PropertyCallbackInfo<v8::Value>& info) {
21513 }
21514};
21515
21516
21517class RequestInterruptTestWithMathAbs : public RequestInterruptTestBase {
21518 public:
21519 virtual void TestBody() {
21520 env_->Global()->Set(v8_str("WakeUpInterruptor"), Function::New(
21521 isolate_,
21522 WakeUpInterruptorCallback,
21523 v8::External::New(isolate_, this)));
21524
21525 env_->Global()->Set(v8_str("ShouldContinue"), Function::New(
21526 isolate_,
21527 ShouldContinueCallback,
21528 v8::External::New(isolate_, this)));
21529
21530 i::FLAG_allow_natives_syntax = true;
21531 CompileRun("function loopish(o) {"
21532 " var pre = 10;"
21533 " while (o.abs(1) > 0) {"
21534 " if (o.abs(1) >= 0 && !ShouldContinue()) break;"
21535 " if (pre > 0) {"
21536 " if (--pre === 0) WakeUpInterruptor(o === Math);"
21537 " }"
21538 " }"
21539 "}"
21540 "var i = 50;"
21541 "var obj = {abs: function () { return i-- }, x: null};"
21542 "delete obj.x;"
21543 "loopish(obj);"
21544 "%OptimizeFunctionOnNextCall(loopish);"
21545 "loopish(Math);");
21546
21547 i::FLAG_allow_natives_syntax = false;
21548 }
21549
21550 private:
21551 static void WakeUpInterruptorCallback(
21552 const v8::FunctionCallbackInfo<Value>& info) {
21553 if (!info[0]->BooleanValue()) return;
21554
21555 RequestInterruptTestBase* test =
21556 reinterpret_cast<RequestInterruptTestBase*>(
21557 info.Data().As<v8::External>()->Value());
21558 test->WakeUpInterruptor();
21559 }
21560
21561 static void ShouldContinueCallback(
21562 const v8::FunctionCallbackInfo<Value>& info) {
21563 RequestInterruptTestBase* test =
21564 reinterpret_cast<RequestInterruptTestBase*>(
21565 info.Data().As<v8::External>()->Value());
21566 info.GetReturnValue().Set(test->should_continue());
21567 }
21568};
21569
21570
21571TEST(RequestInterruptTestWithFunctionCall) {
21572 RequestInterruptTestWithFunctionCall().RunTest();
21573}
21574
21575
21576TEST(RequestInterruptTestWithMethodCall) {
21577 RequestInterruptTestWithMethodCall().RunTest();
21578}
21579
21580
21581TEST(RequestInterruptTestWithAccessor) {
21582 RequestInterruptTestWithAccessor().RunTest();
21583}
21584
21585
21586TEST(RequestInterruptTestWithNativeAccessor) {
21587 RequestInterruptTestWithNativeAccessor().RunTest();
21588}
21589
21590
21591TEST(RequestInterruptTestWithMethodCallAndInterceptor) {
21592 RequestInterruptTestWithMethodCallAndInterceptor().RunTest();
21593}
21594
21595
21596TEST(RequestInterruptTestWithMathAbs) {
21597 RequestInterruptTestWithMathAbs().RunTest();
21598}
dslomov@chromium.org639bac02013-09-09 11:58:54 +000021599
21600
21601static Local<Value> function_new_expected_env;
21602static void FunctionNewCallback(const v8::FunctionCallbackInfo<Value>& info) {
21603 CHECK_EQ(function_new_expected_env, info.Data());
21604 info.GetReturnValue().Set(17);
21605}
21606
21607
21608THREADED_TEST(FunctionNew) {
21609 LocalContext env;
21610 v8::Isolate* isolate = env->GetIsolate();
21611 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000021612 Local<Object> data = v8::Object::New(isolate);
dslomov@chromium.org639bac02013-09-09 11:58:54 +000021613 function_new_expected_env = data;
21614 Local<Function> func = Function::New(isolate, FunctionNewCallback, data);
21615 env->Global()->Set(v8_str("func"), func);
21616 Local<Value> result = CompileRun("func();");
ulan@chromium.org0f13e742014-01-03 15:51:11 +000021617 CHECK_EQ(v8::Integer::New(isolate, 17), result);
dslomov@chromium.org639bac02013-09-09 11:58:54 +000021618 // Verify function not cached
21619 int serial_number =
21620 i::Smi::cast(v8::Utils::OpenHandle(*func)
21621 ->shared()->get_api_func_data()->serial_number())->value();
21622 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
21623 i::Object* elm = i_isolate->native_context()->function_cache()
21624 ->GetElementNoExceptionThrown(i_isolate, serial_number);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000021625 CHECK(elm->IsUndefined());
21626 // Verify that each Function::New creates a new function instance
ulan@chromium.org0f13e742014-01-03 15:51:11 +000021627 Local<Object> data2 = v8::Object::New(isolate);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000021628 function_new_expected_env = data2;
21629 Local<Function> func2 = Function::New(isolate, FunctionNewCallback, data2);
21630 CHECK(!func2->IsNull());
21631 CHECK_NE(func, func2);
21632 env->Global()->Set(v8_str("func2"), func2);
21633 Local<Value> result2 = CompileRun("func2();");
ulan@chromium.org0f13e742014-01-03 15:51:11 +000021634 CHECK_EQ(v8::Integer::New(isolate, 17), result2);
dslomov@chromium.org639bac02013-09-09 11:58:54 +000021635}
21636
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000021637
21638TEST(EscapeableHandleScope) {
21639 HandleScope outer_scope(CcTest::isolate());
21640 LocalContext context;
21641 const int runs = 10;
21642 Local<String> values[runs];
21643 for (int i = 0; i < runs; i++) {
21644 v8::EscapableHandleScope inner_scope(CcTest::isolate());
21645 Local<String> value;
21646 if (i != 0) value = v8_str("escape value");
21647 values[i] = inner_scope.Escape(value);
21648 }
21649 for (int i = 0; i < runs; i++) {
21650 Local<String> expected;
21651 if (i != 0) {
21652 CHECK_EQ(v8_str("escape value"), values[i]);
21653 } else {
21654 CHECK(values[i].IsEmpty());
21655 }
21656 }
21657}