blob: d8b714c050f784664c9e013f896d6b0bdf6c0839 [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);
machenbach@chromium.org03453962014-01-10 14:16:31 +000010198 // PROPERTY_ATTRIBUTES_NONE = 0
10199 CompileRun("var names = %GetLocalPropertyNames(obj, 0);");
ricow@chromium.org27bf2882011-11-17 08:34:43 +000010200
10201 ExpectInt32("names.length", 1006);
10202 ExpectTrue("names.indexOf(\"baz\") >= 0");
10203 ExpectTrue("names.indexOf(\"boo\") >= 0");
10204 ExpectTrue("names.indexOf(\"foo\") >= 0");
10205 ExpectTrue("names.indexOf(\"fuz1\") >= 0");
10206 ExpectTrue("names.indexOf(\"fuz2\") >= 0");
10207 ExpectFalse("names[1005] == undefined");
10208}
10209
10210
ulan@chromium.org0f13e742014-01-03 15:51:11 +000010211// Getting property names of an object with a hidden and inherited
10212// prototype should not duplicate the accessor properties inherited.
10213THREADED_TEST(Regress269562) {
10214 i::FLAG_allow_natives_syntax = true;
10215 LocalContext context;
10216 v8::HandleScope handle_scope(context->GetIsolate());
10217
10218 Local<v8::FunctionTemplate> t1 =
10219 v8::FunctionTemplate::New(context->GetIsolate());
10220 t1->SetHiddenPrototype(true);
10221
10222 Local<v8::ObjectTemplate> i1 = t1->InstanceTemplate();
10223 i1->SetAccessor(v8_str("foo"),
10224 SimpleAccessorGetter, SimpleAccessorSetter);
10225 i1->SetAccessor(v8_str("bar"),
10226 SimpleAccessorGetter, SimpleAccessorSetter);
10227 i1->SetAccessor(v8_str("baz"),
10228 SimpleAccessorGetter, SimpleAccessorSetter);
10229 i1->Set(v8_str("n1"), v8_num(1));
10230 i1->Set(v8_str("n2"), v8_num(2));
10231
10232 Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
10233 Local<v8::FunctionTemplate> t2 =
10234 v8::FunctionTemplate::New(context->GetIsolate());
10235 t2->SetHiddenPrototype(true);
10236
10237 // Inherit from t1 and mark prototype as hidden.
10238 t2->Inherit(t1);
10239 t2->InstanceTemplate()->Set(v8_str("mine"), v8_num(4));
10240
10241 Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
10242 CHECK(o2->SetPrototype(o1));
10243
10244 v8::Local<v8::Symbol> sym = v8::Symbol::New(context->GetIsolate(), "s1");
10245 o1->Set(sym, v8_num(3));
10246 o1->SetHiddenValue(v8_str("h1"),
10247 v8::Integer::New(context->GetIsolate(), 2013));
10248
10249 // Call the runtime version of GetLocalPropertyNames() on
10250 // the natively created object through JavaScript.
10251 context->Global()->Set(v8_str("obj"), o2);
10252 context->Global()->Set(v8_str("sym"), sym);
machenbach@chromium.org03453962014-01-10 14:16:31 +000010253 // PROPERTY_ATTRIBUTES_NONE = 0
10254 CompileRun("var names = %GetLocalPropertyNames(obj, 0);");
ulan@chromium.org0f13e742014-01-03 15:51:11 +000010255
10256 ExpectInt32("names.length", 7);
10257 ExpectTrue("names.indexOf(\"foo\") >= 0");
10258 ExpectTrue("names.indexOf(\"bar\") >= 0");
10259 ExpectTrue("names.indexOf(\"baz\") >= 0");
10260 ExpectTrue("names.indexOf(\"n1\") >= 0");
10261 ExpectTrue("names.indexOf(\"n2\") >= 0");
10262 ExpectTrue("names.indexOf(sym) >= 0");
10263 ExpectTrue("names.indexOf(\"mine\") >= 0");
10264}
10265
10266
ricow@chromium.org2c99e282011-07-28 09:15:17 +000010267THREADED_TEST(FunctionReadOnlyPrototype) {
ager@chromium.org04921a82011-06-27 13:21:41 +000010268 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010269 v8::Isolate* isolate = context->GetIsolate();
10270 v8::HandleScope handle_scope(isolate);
ager@chromium.org04921a82011-06-27 13:21:41 +000010271
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010272 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000010273 t1->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(isolate, 42));
ricow@chromium.org2c99e282011-07-28 09:15:17 +000010274 t1->ReadOnlyPrototype();
ager@chromium.org04921a82011-06-27 13:21:41 +000010275 context->Global()->Set(v8_str("func1"), t1->GetFunction());
ricow@chromium.org2c99e282011-07-28 09:15:17 +000010276 // Configured value of ReadOnly flag.
ager@chromium.org04921a82011-06-27 13:21:41 +000010277 CHECK(CompileRun(
10278 "(function() {"
10279 " descriptor = Object.getOwnPropertyDescriptor(func1, 'prototype');"
ricow@chromium.org2c99e282011-07-28 09:15:17 +000010280 " return (descriptor['writable'] == false);"
ager@chromium.org04921a82011-06-27 13:21:41 +000010281 "})()")->BooleanValue());
ricow@chromium.org2c99e282011-07-28 09:15:17 +000010282 CHECK_EQ(42, CompileRun("func1.prototype.x")->Int32Value());
10283 CHECK_EQ(42,
10284 CompileRun("func1.prototype = {}; func1.prototype.x")->Int32Value());
ager@chromium.org04921a82011-06-27 13:21:41 +000010285
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010286 Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000010287 t2->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(isolate, 42));
ager@chromium.org04921a82011-06-27 13:21:41 +000010288 context->Global()->Set(v8_str("func2"), t2->GetFunction());
ricow@chromium.org2c99e282011-07-28 09:15:17 +000010289 // Default value of ReadOnly flag.
ager@chromium.org04921a82011-06-27 13:21:41 +000010290 CHECK(CompileRun(
10291 "(function() {"
10292 " descriptor = Object.getOwnPropertyDescriptor(func2, 'prototype');"
ricow@chromium.org2c99e282011-07-28 09:15:17 +000010293 " return (descriptor['writable'] == true);"
ager@chromium.org04921a82011-06-27 13:21:41 +000010294 "})()")->BooleanValue());
ricow@chromium.org2c99e282011-07-28 09:15:17 +000010295 CHECK_EQ(42, CompileRun("func2.prototype.x")->Int32Value());
ager@chromium.org04921a82011-06-27 13:21:41 +000010296}
10297
10298
ager@chromium.org5c838252010-02-19 08:53:10 +000010299THREADED_TEST(SetPrototypeThrows) {
ager@chromium.org5c838252010-02-19 08:53:10 +000010300 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010301 v8::Isolate* isolate = context->GetIsolate();
10302 v8::HandleScope handle_scope(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +000010303
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010304 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +000010305
10306 Local<v8::Object> o0 = t->GetFunction()->NewInstance();
10307 Local<v8::Object> o1 = t->GetFunction()->NewInstance();
10308
10309 CHECK(o0->SetPrototype(o1));
10310 // If setting the prototype leads to the cycle, SetPrototype should
10311 // return false and keep VM in sane state.
10312 v8::TryCatch try_catch;
10313 CHECK(!o1->SetPrototype(o0));
10314 CHECK(!try_catch.HasCaught());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000010315 ASSERT(!CcTest::i_isolate()->has_pending_exception());
ager@chromium.org5c838252010-02-19 08:53:10 +000010316
10317 CHECK_EQ(42, CompileRun("function f() { return 42; }; f()")->Int32Value());
10318}
10319
10320
verwaest@chromium.org662436e2013-08-28 08:41:27 +000010321THREADED_TEST(FunctionRemovePrototype) {
10322 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010323 v8::Isolate* isolate = context->GetIsolate();
10324 v8::HandleScope handle_scope(isolate);
verwaest@chromium.org662436e2013-08-28 08:41:27 +000010325
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010326 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
verwaest@chromium.org662436e2013-08-28 08:41:27 +000010327 t1->RemovePrototype();
10328 Local<v8::Function> fun = t1->GetFunction();
10329 context->Global()->Set(v8_str("fun"), fun);
10330 CHECK(!CompileRun("'prototype' in fun")->BooleanValue());
10331
10332 v8::TryCatch try_catch;
10333 CompileRun("new fun()");
10334 CHECK(try_catch.HasCaught());
10335
10336 try_catch.Reset();
10337 fun->NewInstance();
10338 CHECK(try_catch.HasCaught());
10339}
10340
10341
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010342THREADED_TEST(GetterSetterExceptions) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010343 LocalContext context;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000010344 v8::Isolate* isolate = context->GetIsolate();
10345 v8::HandleScope handle_scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010346 CompileRun(
10347 "function Foo() { };"
10348 "function Throw() { throw 5; };"
10349 "var x = { };"
10350 "x.__defineSetter__('set', Throw);"
10351 "x.__defineGetter__('get', Throw);");
10352 Local<v8::Object> x =
10353 Local<v8::Object>::Cast(context->Global()->Get(v8_str("x")));
10354 v8::TryCatch try_catch;
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"));
ulan@chromium.org0f13e742014-01-03 15:51:11 +000010361 x->Set(v8_str("set"), v8::Integer::New(isolate, 8));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010362 x->Get(v8_str("get"));
10363}
10364
10365
10366THREADED_TEST(Constructor) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010367 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010368 v8::Isolate* isolate = context->GetIsolate();
10369 v8::HandleScope handle_scope(isolate);
10370 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010371 templ->SetClassName(v8_str("Fun"));
10372 Local<Function> cons = templ->GetFunction();
10373 context->Global()->Set(v8_str("Fun"), cons);
10374 Local<v8::Object> inst = cons->NewInstance();
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000010375 i::Handle<i::JSObject> obj(v8::Utils::OpenHandle(*inst));
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000010376 CHECK(obj->IsJSObject());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010377 Local<Value> value = CompileRun("(new Fun()).constructor === Fun");
10378 CHECK(value->BooleanValue());
10379}
10380
lrn@chromium.org1c092762011-05-09 09:42:16 +000010381
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010382static void ConstructorCallback(
10383 const v8::FunctionCallbackInfo<v8::Value>& args) {
lrn@chromium.org1c092762011-05-09 09:42:16 +000010384 ApiTestFuzzer::Fuzz();
10385 Local<Object> This;
10386
10387 if (args.IsConstructCall()) {
10388 Local<Object> Holder = args.Holder();
ulan@chromium.org0f13e742014-01-03 15:51:11 +000010389 This = Object::New(args.GetIsolate());
lrn@chromium.org1c092762011-05-09 09:42:16 +000010390 Local<Value> proto = Holder->GetPrototype();
10391 if (proto->IsObject()) {
10392 This->SetPrototype(proto);
10393 }
10394 } else {
10395 This = args.This();
10396 }
10397
10398 This->Set(v8_str("a"), args[0]);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010399 args.GetReturnValue().Set(This);
lrn@chromium.org1c092762011-05-09 09:42:16 +000010400}
10401
10402
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010403static void FakeConstructorCallback(
10404 const v8::FunctionCallbackInfo<v8::Value>& args) {
lrn@chromium.org1c092762011-05-09 09:42:16 +000010405 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010406 args.GetReturnValue().Set(args[0]);
lrn@chromium.org1c092762011-05-09 09:42:16 +000010407}
10408
10409
10410THREADED_TEST(ConstructorForObject) {
lrn@chromium.org1c092762011-05-09 09:42:16 +000010411 LocalContext context;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000010412 v8::Isolate* isolate = context->GetIsolate();
10413 v8::HandleScope handle_scope(isolate);
lrn@chromium.org1c092762011-05-09 09:42:16 +000010414
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000010415 { Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
lrn@chromium.org1c092762011-05-09 09:42:16 +000010416 instance_template->SetCallAsFunctionHandler(ConstructorCallback);
10417 Local<Object> instance = instance_template->NewInstance();
10418 context->Global()->Set(v8_str("obj"), instance);
10419 v8::TryCatch try_catch;
10420 Local<Value> value;
10421 CHECK(!try_catch.HasCaught());
10422
10423 // Call the Object's constructor with a 32-bit signed integer.
10424 value = CompileRun("(function() { var o = new obj(28); return o.a; })()");
10425 CHECK(!try_catch.HasCaught());
10426 CHECK(value->IsInt32());
10427 CHECK_EQ(28, value->Int32Value());
10428
10429 Local<Value> args1[] = { v8_num(28) };
10430 Local<Value> value_obj1 = instance->CallAsConstructor(1, args1);
10431 CHECK(value_obj1->IsObject());
10432 Local<Object> object1 = Local<Object>::Cast(value_obj1);
10433 value = object1->Get(v8_str("a"));
10434 CHECK(value->IsInt32());
10435 CHECK(!try_catch.HasCaught());
10436 CHECK_EQ(28, value->Int32Value());
10437
10438 // Call the Object's constructor with a String.
10439 value = CompileRun(
10440 "(function() { var o = new obj('tipli'); return o.a; })()");
10441 CHECK(!try_catch.HasCaught());
10442 CHECK(value->IsString());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000010443 String::Utf8Value string_value1(value->ToString());
lrn@chromium.org1c092762011-05-09 09:42:16 +000010444 CHECK_EQ("tipli", *string_value1);
10445
10446 Local<Value> args2[] = { v8_str("tipli") };
10447 Local<Value> value_obj2 = instance->CallAsConstructor(1, args2);
10448 CHECK(value_obj2->IsObject());
10449 Local<Object> object2 = Local<Object>::Cast(value_obj2);
10450 value = object2->Get(v8_str("a"));
10451 CHECK(!try_catch.HasCaught());
10452 CHECK(value->IsString());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000010453 String::Utf8Value string_value2(value->ToString());
lrn@chromium.org1c092762011-05-09 09:42:16 +000010454 CHECK_EQ("tipli", *string_value2);
10455
10456 // Call the Object's constructor with a Boolean.
10457 value = CompileRun("(function() { var o = new obj(true); return o.a; })()");
10458 CHECK(!try_catch.HasCaught());
10459 CHECK(value->IsBoolean());
10460 CHECK_EQ(true, value->BooleanValue());
10461
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000010462 Handle<Value> args3[] = { v8::True(isolate) };
lrn@chromium.org1c092762011-05-09 09:42:16 +000010463 Local<Value> value_obj3 = instance->CallAsConstructor(1, args3);
10464 CHECK(value_obj3->IsObject());
10465 Local<Object> object3 = Local<Object>::Cast(value_obj3);
10466 value = object3->Get(v8_str("a"));
10467 CHECK(!try_catch.HasCaught());
10468 CHECK(value->IsBoolean());
10469 CHECK_EQ(true, value->BooleanValue());
10470
10471 // Call the Object's constructor with undefined.
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000010472 Handle<Value> args4[] = { v8::Undefined(isolate) };
lrn@chromium.org1c092762011-05-09 09:42:16 +000010473 Local<Value> value_obj4 = instance->CallAsConstructor(1, args4);
10474 CHECK(value_obj4->IsObject());
10475 Local<Object> object4 = Local<Object>::Cast(value_obj4);
10476 value = object4->Get(v8_str("a"));
10477 CHECK(!try_catch.HasCaught());
10478 CHECK(value->IsUndefined());
10479
10480 // Call the Object's constructor with null.
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000010481 Handle<Value> args5[] = { v8::Null(isolate) };
lrn@chromium.org1c092762011-05-09 09:42:16 +000010482 Local<Value> value_obj5 = instance->CallAsConstructor(1, args5);
10483 CHECK(value_obj5->IsObject());
10484 Local<Object> object5 = Local<Object>::Cast(value_obj5);
10485 value = object5->Get(v8_str("a"));
10486 CHECK(!try_catch.HasCaught());
10487 CHECK(value->IsNull());
10488 }
10489
10490 // Check exception handling when there is no constructor set for the Object.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000010491 { Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
lrn@chromium.org1c092762011-05-09 09:42:16 +000010492 Local<Object> instance = instance_template->NewInstance();
10493 context->Global()->Set(v8_str("obj2"), instance);
10494 v8::TryCatch try_catch;
10495 Local<Value> value;
10496 CHECK(!try_catch.HasCaught());
10497
10498 value = CompileRun("new obj2(28)");
10499 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000010500 String::Utf8Value exception_value1(try_catch.Exception());
lrn@chromium.org1c092762011-05-09 09:42:16 +000010501 CHECK_EQ("TypeError: object is not a function", *exception_value1);
10502 try_catch.Reset();
10503
10504 Local<Value> args[] = { v8_num(29) };
10505 value = instance->CallAsConstructor(1, args);
10506 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000010507 String::Utf8Value exception_value2(try_catch.Exception());
lrn@chromium.org1c092762011-05-09 09:42:16 +000010508 CHECK_EQ("TypeError: #<Object> is not a function", *exception_value2);
10509 try_catch.Reset();
10510 }
10511
10512 // Check the case when constructor throws exception.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000010513 { Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
lrn@chromium.org1c092762011-05-09 09:42:16 +000010514 instance_template->SetCallAsFunctionHandler(ThrowValue);
10515 Local<Object> instance = instance_template->NewInstance();
10516 context->Global()->Set(v8_str("obj3"), instance);
10517 v8::TryCatch try_catch;
10518 Local<Value> value;
10519 CHECK(!try_catch.HasCaught());
10520
10521 value = CompileRun("new obj3(22)");
10522 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000010523 String::Utf8Value exception_value1(try_catch.Exception());
lrn@chromium.org1c092762011-05-09 09:42:16 +000010524 CHECK_EQ("22", *exception_value1);
10525 try_catch.Reset();
10526
10527 Local<Value> args[] = { v8_num(23) };
10528 value = instance->CallAsConstructor(1, args);
10529 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000010530 String::Utf8Value exception_value2(try_catch.Exception());
lrn@chromium.org1c092762011-05-09 09:42:16 +000010531 CHECK_EQ("23", *exception_value2);
10532 try_catch.Reset();
10533 }
10534
10535 // Check whether constructor returns with an object or non-object.
10536 { Local<FunctionTemplate> function_template =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010537 FunctionTemplate::New(isolate, FakeConstructorCallback);
lrn@chromium.org1c092762011-05-09 09:42:16 +000010538 Local<Function> function = function_template->GetFunction();
10539 Local<Object> instance1 = function;
10540 context->Global()->Set(v8_str("obj4"), instance1);
10541 v8::TryCatch try_catch;
10542 Local<Value> value;
10543 CHECK(!try_catch.HasCaught());
10544
10545 CHECK(instance1->IsObject());
10546 CHECK(instance1->IsFunction());
10547
10548 value = CompileRun("new obj4(28)");
10549 CHECK(!try_catch.HasCaught());
10550 CHECK(value->IsObject());
10551
10552 Local<Value> args1[] = { v8_num(28) };
10553 value = instance1->CallAsConstructor(1, args1);
10554 CHECK(!try_catch.HasCaught());
10555 CHECK(value->IsObject());
10556
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000010557 Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
lrn@chromium.org1c092762011-05-09 09:42:16 +000010558 instance_template->SetCallAsFunctionHandler(FakeConstructorCallback);
10559 Local<Object> instance2 = instance_template->NewInstance();
10560 context->Global()->Set(v8_str("obj5"), instance2);
10561 CHECK(!try_catch.HasCaught());
10562
10563 CHECK(instance2->IsObject());
10564 CHECK(!instance2->IsFunction());
10565
10566 value = CompileRun("new obj5(28)");
10567 CHECK(!try_catch.HasCaught());
10568 CHECK(!value->IsObject());
10569
10570 Local<Value> args2[] = { v8_num(28) };
10571 value = instance2->CallAsConstructor(1, args2);
10572 CHECK(!try_catch.HasCaught());
10573 CHECK(!value->IsObject());
10574 }
10575}
10576
10577
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010578THREADED_TEST(FunctionDescriptorException) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010579 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010580 v8::Isolate* isolate = context->GetIsolate();
10581 v8::HandleScope handle_scope(isolate);
10582 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010583 templ->SetClassName(v8_str("Fun"));
10584 Local<Function> cons = templ->GetFunction();
10585 context->Global()->Set(v8_str("Fun"), cons);
10586 Local<Value> value = CompileRun(
10587 "function test() {"
10588 " try {"
10589 " (new Fun()).blah()"
10590 " } catch (e) {"
10591 " var str = String(e);"
10592 " if (str.indexOf('TypeError') == -1) return 1;"
10593 " if (str.indexOf('[object Fun]') != -1) return 2;"
whesse@chromium.org7a392b32011-01-31 11:30:36 +000010594 " if (str.indexOf('#<Fun>') == -1) return 3;"
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010595 " return 0;"
10596 " }"
10597 " return 4;"
10598 "}"
10599 "test();");
10600 CHECK_EQ(0, value->Int32Value());
10601}
10602
10603
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010604THREADED_TEST(EvalAliasedDynamic) {
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010605 LocalContext current;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000010606 v8::HandleScope scope(current->GetIsolate());
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010607
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010608 // Tests where aliased eval can only be resolved dynamically.
10609 Local<Script> script =
10610 Script::Compile(v8_str("function f(x) { "
10611 " var foo = 2;"
10612 " with (x) { return eval('foo'); }"
10613 "}"
10614 "foo = 0;"
10615 "result1 = f(new Object());"
ager@chromium.orge2902be2009-06-08 12:21:35 +000010616 "result2 = f(this);"
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010617 "var x = new Object();"
10618 "x.eval = function(x) { return 1; };"
10619 "result3 = f(x);"));
10620 script->Run();
10621 CHECK_EQ(2, current->Global()->Get(v8_str("result1"))->Int32Value());
10622 CHECK_EQ(0, current->Global()->Get(v8_str("result2"))->Int32Value());
10623 CHECK_EQ(1, current->Global()->Get(v8_str("result3"))->Int32Value());
10624
10625 v8::TryCatch try_catch;
10626 script =
10627 Script::Compile(v8_str("function f(x) { "
10628 " var bar = 2;"
10629 " with (x) { return eval('bar'); }"
10630 "}"
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000010631 "result4 = f(this)"));
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010632 script->Run();
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000010633 CHECK(!try_catch.HasCaught());
10634 CHECK_EQ(2, current->Global()->Get(v8_str("result4"))->Int32Value());
10635
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010636 try_catch.Reset();
10637}
10638
10639
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010640THREADED_TEST(CrossEval) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000010641 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010642 LocalContext other;
10643 LocalContext current;
10644
10645 Local<String> token = v8_str("<security token>");
10646 other->SetSecurityToken(token);
10647 current->SetSecurityToken(token);
10648
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000010649 // Set up reference from current to other.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010650 current->Global()->Set(v8_str("other"), other->Global());
10651
10652 // Check that new variables are introduced in other context.
10653 Local<Script> script =
10654 Script::Compile(v8_str("other.eval('var foo = 1234')"));
10655 script->Run();
10656 Local<Value> foo = other->Global()->Get(v8_str("foo"));
10657 CHECK_EQ(1234, foo->Int32Value());
10658 CHECK(!current->Global()->Has(v8_str("foo")));
10659
10660 // Check that writing to non-existing properties introduces them in
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010661 // the other context.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010662 script =
10663 Script::Compile(v8_str("other.eval('na = 1234')"));
10664 script->Run();
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010665 CHECK_EQ(1234, other->Global()->Get(v8_str("na"))->Int32Value());
10666 CHECK(!current->Global()->Has(v8_str("na")));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010667
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010668 // Check that global variables in current context are not visible in other
10669 // context.
10670 v8::TryCatch try_catch;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010671 script =
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010672 Script::Compile(v8_str("var bar = 42; other.eval('bar');"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010673 Local<Value> result = script->Run();
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010674 CHECK(try_catch.HasCaught());
10675 try_catch.Reset();
10676
10677 // Check that local variables in current context are not visible in other
10678 // context.
10679 script =
10680 Script::Compile(v8_str("(function() { "
10681 " var baz = 87;"
10682 " return other.eval('baz');"
10683 "})();"));
10684 result = script->Run();
10685 CHECK(try_catch.HasCaught());
10686 try_catch.Reset();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010687
10688 // Check that global variables in the other environment are visible
10689 // when evaluting code.
10690 other->Global()->Set(v8_str("bis"), v8_num(1234));
10691 script = Script::Compile(v8_str("other.eval('bis')"));
10692 CHECK_EQ(1234, script->Run()->Int32Value());
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010693 CHECK(!try_catch.HasCaught());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010694
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010695 // Check that the 'this' pointer points to the global object evaluating
10696 // code.
10697 other->Global()->Set(v8_str("t"), other->Global());
10698 script = Script::Compile(v8_str("other.eval('this == t')"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010699 result = script->Run();
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010700 CHECK(result->IsTrue());
10701 CHECK(!try_catch.HasCaught());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010702
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010703 // Check that variables introduced in with-statement are not visible in
10704 // other context.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010705 script =
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010706 Script::Compile(v8_str("with({x:2}){other.eval('x')}"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010707 result = script->Run();
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010708 CHECK(try_catch.HasCaught());
10709 try_catch.Reset();
ager@chromium.org3bf7b912008-11-17 09:09:45 +000010710
10711 // Check that you cannot use 'eval.call' with another object than the
10712 // current global object.
ager@chromium.org3bf7b912008-11-17 09:09:45 +000010713 script =
10714 Script::Compile(v8_str("other.y = 1; eval.call(other, 'y')"));
10715 result = script->Run();
10716 CHECK(try_catch.HasCaught());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010717}
10718
10719
ager@chromium.orge2902be2009-06-08 12:21:35 +000010720// Test that calling eval in a context which has been detached from
10721// its global throws an exception. This behavior is consistent with
10722// other JavaScript implementations.
10723THREADED_TEST(EvalInDetachedGlobal) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000010724 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000010725 v8::HandleScope scope(isolate);
ager@chromium.orge2902be2009-06-08 12:21:35 +000010726
ulan@chromium.org57ff8812013-05-10 08:16:55 +000010727 v8::Local<Context> context0 = Context::New(isolate);
10728 v8::Local<Context> context1 = Context::New(isolate);
ager@chromium.orge2902be2009-06-08 12:21:35 +000010729
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000010730 // Set up function in context0 that uses eval from context0.
ager@chromium.orge2902be2009-06-08 12:21:35 +000010731 context0->Enter();
10732 v8::Handle<v8::Value> fun =
10733 CompileRun("var x = 42;"
10734 "(function() {"
10735 " var e = eval;"
10736 " return function(s) { return e(s); }"
10737 "})()");
10738 context0->Exit();
10739
10740 // Put the function into context1 and call it before and after
10741 // detaching the global. Before detaching, the call succeeds and
10742 // after detaching and exception is thrown.
10743 context1->Enter();
10744 context1->Global()->Set(v8_str("fun"), fun);
10745 v8::Handle<v8::Value> x_value = CompileRun("fun('x')");
10746 CHECK_EQ(42, x_value->Int32Value());
10747 context0->DetachGlobal();
10748 v8::TryCatch catcher;
10749 x_value = CompileRun("fun('x')");
10750 CHECK(x_value.IsEmpty());
10751 CHECK(catcher.HasCaught());
10752 context1->Exit();
ager@chromium.orge2902be2009-06-08 12:21:35 +000010753}
10754
10755
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010756THREADED_TEST(CrossLazyLoad) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000010757 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010758 LocalContext other;
10759 LocalContext current;
10760
10761 Local<String> token = v8_str("<security token>");
10762 other->SetSecurityToken(token);
10763 current->SetSecurityToken(token);
10764
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000010765 // Set up reference from current to other.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010766 current->Global()->Set(v8_str("other"), other->Global());
10767
10768 // Trigger lazy loading in other context.
10769 Local<Script> script =
10770 Script::Compile(v8_str("other.eval('new Date(42)')"));
10771 Local<Value> value = script->Run();
10772 CHECK_EQ(42.0, value->NumberValue());
10773}
10774
10775
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010776static void call_as_function(const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010777 ApiTestFuzzer::Fuzz();
sgjesse@chromium.org05521fc2009-05-21 07:37:44 +000010778 if (args.IsConstructCall()) {
10779 if (args[0]->IsInt32()) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010780 args.GetReturnValue().Set(v8_num(-args[0]->Int32Value()));
10781 return;
sgjesse@chromium.org05521fc2009-05-21 07:37:44 +000010782 }
10783 }
10784
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010785 args.GetReturnValue().Set(args[0]);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010786}
10787
10788
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +000010789static void ReturnThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
10790 args.GetReturnValue().Set(args.This());
10791}
10792
10793
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010794// Test that a call handler can be set for objects which will allow
10795// non-function objects created through the API to be called as
10796// functions.
10797THREADED_TEST(CallAsFunction) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010798 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010799 v8::Isolate* isolate = context->GetIsolate();
10800 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010801
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010802 { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
lrn@chromium.org1c092762011-05-09 09:42:16 +000010803 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
10804 instance_template->SetCallAsFunctionHandler(call_as_function);
10805 Local<v8::Object> instance = t->GetFunction()->NewInstance();
10806 context->Global()->Set(v8_str("obj"), instance);
10807 v8::TryCatch try_catch;
10808 Local<Value> value;
10809 CHECK(!try_catch.HasCaught());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010810
lrn@chromium.org1c092762011-05-09 09:42:16 +000010811 value = CompileRun("obj(42)");
10812 CHECK(!try_catch.HasCaught());
10813 CHECK_EQ(42, value->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010814
lrn@chromium.org1c092762011-05-09 09:42:16 +000010815 value = CompileRun("(function(o){return o(49)})(obj)");
10816 CHECK(!try_catch.HasCaught());
10817 CHECK_EQ(49, value->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010818
lrn@chromium.org1c092762011-05-09 09:42:16 +000010819 // test special case of call as function
10820 value = CompileRun("[obj]['0'](45)");
10821 CHECK(!try_catch.HasCaught());
10822 CHECK_EQ(45, value->Int32Value());
ager@chromium.org9258b6b2008-09-11 09:11:10 +000010823
lrn@chromium.org1c092762011-05-09 09:42:16 +000010824 value = CompileRun("obj.call = Function.prototype.call;"
10825 "obj.call(null, 87)");
10826 CHECK(!try_catch.HasCaught());
10827 CHECK_EQ(87, value->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010828
lrn@chromium.org1c092762011-05-09 09:42:16 +000010829 // Regression tests for bug #1116356: Calling call through call/apply
10830 // must work for non-function receivers.
10831 const char* apply_99 = "Function.prototype.call.apply(obj, [this, 99])";
10832 value = CompileRun(apply_99);
10833 CHECK(!try_catch.HasCaught());
10834 CHECK_EQ(99, value->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010835
lrn@chromium.org1c092762011-05-09 09:42:16 +000010836 const char* call_17 = "Function.prototype.call.call(obj, this, 17)";
10837 value = CompileRun(call_17);
10838 CHECK(!try_catch.HasCaught());
10839 CHECK_EQ(17, value->Int32Value());
ager@chromium.org9085a012009-05-11 19:22:57 +000010840
lrn@chromium.org1c092762011-05-09 09:42:16 +000010841 // Check that the call-as-function handler can be called through
10842 // new.
10843 value = CompileRun("new obj(43)");
10844 CHECK(!try_catch.HasCaught());
10845 CHECK_EQ(-43, value->Int32Value());
10846
10847 // Check that the call-as-function handler can be called through
10848 // the API.
10849 v8::Handle<Value> args[] = { v8_num(28) };
10850 value = instance->CallAsFunction(instance, 1, args);
10851 CHECK(!try_catch.HasCaught());
10852 CHECK_EQ(28, value->Int32Value());
10853 }
10854
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010855 { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000010856 Local<ObjectTemplate> instance_template(t->InstanceTemplate());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000010857 USE(instance_template);
lrn@chromium.org1c092762011-05-09 09:42:16 +000010858 Local<v8::Object> instance = t->GetFunction()->NewInstance();
10859 context->Global()->Set(v8_str("obj2"), instance);
10860 v8::TryCatch try_catch;
10861 Local<Value> value;
10862 CHECK(!try_catch.HasCaught());
10863
10864 // Call an object without call-as-function handler through the JS
10865 value = CompileRun("obj2(28)");
10866 CHECK(value.IsEmpty());
10867 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000010868 String::Utf8Value exception_value1(try_catch.Exception());
lrn@chromium.org1c092762011-05-09 09:42:16 +000010869 CHECK_EQ("TypeError: Property 'obj2' of object #<Object> is not a function",
10870 *exception_value1);
10871 try_catch.Reset();
10872
10873 // Call an object without call-as-function handler through the API
10874 value = CompileRun("obj2(28)");
10875 v8::Handle<Value> args[] = { v8_num(28) };
10876 value = instance->CallAsFunction(instance, 1, args);
10877 CHECK(value.IsEmpty());
10878 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000010879 String::Utf8Value exception_value2(try_catch.Exception());
lrn@chromium.org1c092762011-05-09 09:42:16 +000010880 CHECK_EQ("TypeError: [object Object] is not a function", *exception_value2);
10881 try_catch.Reset();
10882 }
10883
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010884 { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
lrn@chromium.org1c092762011-05-09 09:42:16 +000010885 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
10886 instance_template->SetCallAsFunctionHandler(ThrowValue);
10887 Local<v8::Object> instance = t->GetFunction()->NewInstance();
10888 context->Global()->Set(v8_str("obj3"), instance);
10889 v8::TryCatch try_catch;
10890 Local<Value> value;
10891 CHECK(!try_catch.HasCaught());
10892
10893 // Catch the exception which is thrown by call-as-function handler
10894 value = CompileRun("obj3(22)");
10895 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000010896 String::Utf8Value exception_value1(try_catch.Exception());
lrn@chromium.org1c092762011-05-09 09:42:16 +000010897 CHECK_EQ("22", *exception_value1);
10898 try_catch.Reset();
10899
10900 v8::Handle<Value> args[] = { v8_num(23) };
10901 value = instance->CallAsFunction(instance, 1, args);
10902 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000010903 String::Utf8Value exception_value2(try_catch.Exception());
lrn@chromium.org1c092762011-05-09 09:42:16 +000010904 CHECK_EQ("23", *exception_value2);
10905 try_catch.Reset();
10906 }
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +000010907
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010908 { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +000010909 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
10910 instance_template->SetCallAsFunctionHandler(ReturnThis);
10911 Local<v8::Object> instance = t->GetFunction()->NewInstance();
10912
10913 Local<v8::Value> a1 =
10914 instance->CallAsFunction(v8::Undefined(isolate), 0, NULL);
10915 CHECK(a1->StrictEquals(instance));
10916 Local<v8::Value> a2 =
10917 instance->CallAsFunction(v8::Null(isolate), 0, NULL);
10918 CHECK(a2->StrictEquals(instance));
10919 Local<v8::Value> a3 =
10920 instance->CallAsFunction(v8_num(42), 0, NULL);
10921 CHECK(a3->StrictEquals(instance));
10922 Local<v8::Value> a4 =
10923 instance->CallAsFunction(v8_str("hello"), 0, NULL);
10924 CHECK(a4->StrictEquals(instance));
10925 Local<v8::Value> a5 =
10926 instance->CallAsFunction(v8::True(isolate), 0, NULL);
10927 CHECK(a5->StrictEquals(instance));
10928 }
10929
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010930 { CompileRun(
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +000010931 "function ReturnThisSloppy() {"
10932 " return this;"
10933 "}"
10934 "function ReturnThisStrict() {"
10935 " 'use strict';"
10936 " return this;"
10937 "}");
10938 Local<Function> ReturnThisSloppy =
10939 Local<Function>::Cast(
10940 context->Global()->Get(v8_str("ReturnThisSloppy")));
10941 Local<Function> ReturnThisStrict =
10942 Local<Function>::Cast(
10943 context->Global()->Get(v8_str("ReturnThisStrict")));
10944
10945 Local<v8::Value> a1 =
10946 ReturnThisSloppy->CallAsFunction(v8::Undefined(isolate), 0, NULL);
10947 CHECK(a1->StrictEquals(context->Global()));
10948 Local<v8::Value> a2 =
10949 ReturnThisSloppy->CallAsFunction(v8::Null(isolate), 0, NULL);
10950 CHECK(a2->StrictEquals(context->Global()));
10951 Local<v8::Value> a3 =
10952 ReturnThisSloppy->CallAsFunction(v8_num(42), 0, NULL);
10953 CHECK(a3->IsNumberObject());
10954 CHECK_EQ(42.0, a3.As<v8::NumberObject>()->ValueOf());
10955 Local<v8::Value> a4 =
10956 ReturnThisSloppy->CallAsFunction(v8_str("hello"), 0, NULL);
10957 CHECK(a4->IsStringObject());
10958 CHECK(a4.As<v8::StringObject>()->ValueOf()->StrictEquals(v8_str("hello")));
10959 Local<v8::Value> a5 =
10960 ReturnThisSloppy->CallAsFunction(v8::True(isolate), 0, NULL);
10961 CHECK(a5->IsBooleanObject());
10962 CHECK(a5.As<v8::BooleanObject>()->ValueOf());
10963
10964 Local<v8::Value> a6 =
10965 ReturnThisStrict->CallAsFunction(v8::Undefined(isolate), 0, NULL);
10966 CHECK(a6->IsUndefined());
10967 Local<v8::Value> a7 =
10968 ReturnThisStrict->CallAsFunction(v8::Null(isolate), 0, NULL);
10969 CHECK(a7->IsNull());
10970 Local<v8::Value> a8 =
10971 ReturnThisStrict->CallAsFunction(v8_num(42), 0, NULL);
10972 CHECK(a8->StrictEquals(v8_num(42)));
10973 Local<v8::Value> a9 =
10974 ReturnThisStrict->CallAsFunction(v8_str("hello"), 0, NULL);
10975 CHECK(a9->StrictEquals(v8_str("hello")));
10976 Local<v8::Value> a10 =
10977 ReturnThisStrict->CallAsFunction(v8::True(isolate), 0, NULL);
10978 CHECK(a10->StrictEquals(v8::True(isolate)));
10979 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010980}
10981
10982
karlklose@chromium.org83a47282011-05-11 11:54:09 +000010983// Check whether a non-function object is callable.
10984THREADED_TEST(CallableObject) {
karlklose@chromium.org83a47282011-05-11 11:54:09 +000010985 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010986 v8::Isolate* isolate = context->GetIsolate();
10987 v8::HandleScope scope(isolate);
karlklose@chromium.org83a47282011-05-11 11:54:09 +000010988
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000010989 { Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
karlklose@chromium.org83a47282011-05-11 11:54:09 +000010990 instance_template->SetCallAsFunctionHandler(call_as_function);
10991 Local<Object> instance = instance_template->NewInstance();
10992 v8::TryCatch try_catch;
10993
10994 CHECK(instance->IsCallable());
10995 CHECK(!try_catch.HasCaught());
10996 }
10997
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000010998 { Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
karlklose@chromium.org83a47282011-05-11 11:54:09 +000010999 Local<Object> instance = instance_template->NewInstance();
11000 v8::TryCatch try_catch;
11001
11002 CHECK(!instance->IsCallable());
11003 CHECK(!try_catch.HasCaught());
11004 }
11005
11006 { Local<FunctionTemplate> function_template =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000011007 FunctionTemplate::New(isolate, call_as_function);
karlklose@chromium.org83a47282011-05-11 11:54:09 +000011008 Local<Function> function = function_template->GetFunction();
11009 Local<Object> instance = function;
11010 v8::TryCatch try_catch;
11011
11012 CHECK(instance->IsCallable());
11013 CHECK(!try_catch.HasCaught());
11014 }
11015
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000011016 { Local<FunctionTemplate> function_template = FunctionTemplate::New(isolate);
karlklose@chromium.org83a47282011-05-11 11:54:09 +000011017 Local<Function> function = function_template->GetFunction();
11018 Local<Object> instance = function;
11019 v8::TryCatch try_catch;
11020
11021 CHECK(instance->IsCallable());
11022 CHECK(!try_catch.HasCaught());
11023 }
11024}
11025
11026
machenbach@chromium.org4610c282014-01-09 10:39:51 +000011027static int Recurse(v8::Isolate* isolate, int depth, int iterations) {
11028 v8::HandleScope scope(isolate);
11029 if (depth == 0) return v8::HandleScope::NumberOfHandles(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011030 for (int i = 0; i < iterations; i++) {
machenbach@chromium.org4610c282014-01-09 10:39:51 +000011031 Local<v8::Number> n(v8::Integer::New(isolate, 42));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011032 }
machenbach@chromium.org4610c282014-01-09 10:39:51 +000011033 return Recurse(isolate, depth - 1, iterations);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011034}
11035
11036
11037THREADED_TEST(HandleIteration) {
11038 static const int kIterations = 500;
11039 static const int kNesting = 200;
machenbach@chromium.org4610c282014-01-09 10:39:51 +000011040 LocalContext context;
11041 v8::Isolate* isolate = context->GetIsolate();
11042 v8::HandleScope scope0(isolate);
11043 CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011044 {
machenbach@chromium.org4610c282014-01-09 10:39:51 +000011045 v8::HandleScope scope1(isolate);
11046 CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011047 for (int i = 0; i < kIterations; i++) {
ulan@chromium.org0f13e742014-01-03 15:51:11 +000011048 Local<v8::Number> n(v8::Integer::New(CcTest::isolate(), 42));
machenbach@chromium.org4610c282014-01-09 10:39:51 +000011049 CHECK_EQ(i + 1, v8::HandleScope::NumberOfHandles(isolate));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011050 }
11051
machenbach@chromium.org4610c282014-01-09 10:39:51 +000011052 CHECK_EQ(kIterations, v8::HandleScope::NumberOfHandles(isolate));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011053 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011054 v8::HandleScope scope2(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011055 for (int j = 0; j < kIterations; j++) {
ulan@chromium.org0f13e742014-01-03 15:51:11 +000011056 Local<v8::Number> n(v8::Integer::New(CcTest::isolate(), 42));
machenbach@chromium.org4610c282014-01-09 10:39:51 +000011057 CHECK_EQ(j + 1 + kIterations,
11058 v8::HandleScope::NumberOfHandles(isolate));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011059 }
11060 }
machenbach@chromium.org4610c282014-01-09 10:39:51 +000011061 CHECK_EQ(kIterations, v8::HandleScope::NumberOfHandles(isolate));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011062 }
machenbach@chromium.org4610c282014-01-09 10:39:51 +000011063 CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
11064 CHECK_EQ(kNesting * kIterations, Recurse(isolate, kNesting, kIterations));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011065}
11066
11067
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011068static void InterceptorHasOwnPropertyGetter(
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011069 Local<String> name,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011070 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011071 ApiTestFuzzer::Fuzz();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011072}
11073
11074
11075THREADED_TEST(InterceptorHasOwnProperty) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011076 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000011077 v8::Isolate* isolate = context->GetIsolate();
11078 v8::HandleScope scope(isolate);
11079 Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011080 Local<v8::ObjectTemplate> instance_templ = fun_templ->InstanceTemplate();
11081 instance_templ->SetNamedPropertyHandler(InterceptorHasOwnPropertyGetter);
11082 Local<Function> function = fun_templ->GetFunction();
11083 context->Global()->Set(v8_str("constructor"), function);
11084 v8::Handle<Value> value = CompileRun(
11085 "var o = new constructor();"
11086 "o.hasOwnProperty('ostehaps');");
11087 CHECK_EQ(false, value->BooleanValue());
11088 value = CompileRun(
11089 "o.ostehaps = 42;"
11090 "o.hasOwnProperty('ostehaps');");
11091 CHECK_EQ(true, value->BooleanValue());
11092 value = CompileRun(
11093 "var p = new constructor();"
11094 "p.hasOwnProperty('ostehaps');");
11095 CHECK_EQ(false, value->BooleanValue());
11096}
11097
11098
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011099static void InterceptorHasOwnPropertyGetterGC(
ager@chromium.org9085a012009-05-11 19:22:57 +000011100 Local<String> name,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011101 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.org9085a012009-05-11 19:22:57 +000011102 ApiTestFuzzer::Fuzz();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011103 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org9085a012009-05-11 19:22:57 +000011104}
11105
11106
11107THREADED_TEST(InterceptorHasOwnPropertyCausingGC) {
ager@chromium.org9085a012009-05-11 19:22:57 +000011108 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000011109 v8::Isolate* isolate = context->GetIsolate();
11110 v8::HandleScope scope(isolate);
11111 Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(isolate);
ager@chromium.org9085a012009-05-11 19:22:57 +000011112 Local<v8::ObjectTemplate> instance_templ = fun_templ->InstanceTemplate();
11113 instance_templ->SetNamedPropertyHandler(InterceptorHasOwnPropertyGetterGC);
11114 Local<Function> function = fun_templ->GetFunction();
11115 context->Global()->Set(v8_str("constructor"), function);
11116 // Let's first make some stuff so we can be sure to get a good GC.
11117 CompileRun(
11118 "function makestr(size) {"
11119 " switch (size) {"
11120 " case 1: return 'f';"
11121 " case 2: return 'fo';"
11122 " case 3: return 'foo';"
11123 " }"
11124 " return makestr(size >> 1) + makestr((size + 1) >> 1);"
11125 "}"
11126 "var x = makestr(12345);"
11127 "x = makestr(31415);"
11128 "x = makestr(23456);");
11129 v8::Handle<Value> value = CompileRun(
11130 "var o = new constructor();"
11131 "o.__proto__ = new String(x);"
11132 "o.hasOwnProperty('ostehaps');");
11133 CHECK_EQ(false, value->BooleanValue());
11134}
11135
11136
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011137typedef void (*NamedPropertyGetter)(
11138 Local<String> property,
11139 const v8::PropertyCallbackInfo<v8::Value>& info);
ager@chromium.orge2902be2009-06-08 12:21:35 +000011140
11141
11142static void CheckInterceptorLoadIC(NamedPropertyGetter getter,
11143 const char* source,
11144 int expected) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011145 v8::Isolate* isolate = CcTest::isolate();
11146 v8::HandleScope scope(isolate);
11147 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
vegorov@chromium.org21b5e952010-11-23 10:24:40 +000011148 templ->SetNamedPropertyHandler(getter, 0, 0, 0, 0, v8_str("data"));
ager@chromium.orge2902be2009-06-08 12:21:35 +000011149 LocalContext context;
11150 context->Global()->Set(v8_str("o"), templ->NewInstance());
11151 v8::Handle<Value> value = CompileRun(source);
11152 CHECK_EQ(expected, value->Int32Value());
11153}
11154
11155
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011156static void InterceptorLoadICGetter(
11157 Local<String> name,
11158 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011159 ApiTestFuzzer::Fuzz();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011160 v8::Isolate* isolate = CcTest::isolate();
jkummerow@chromium.org28faa982012-04-13 09:58:30 +000011161 CHECK_EQ(isolate, info.GetIsolate());
vegorov@chromium.org21b5e952010-11-23 10:24:40 +000011162 CHECK_EQ(v8_str("data"), info.Data());
11163 CHECK_EQ(v8_str("x"), name);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000011164 info.GetReturnValue().Set(v8::Integer::New(isolate, 42));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011165}
11166
11167
11168// This test should hit the load IC for the interceptor case.
11169THREADED_TEST(InterceptorLoadIC) {
ager@chromium.orge2902be2009-06-08 12:21:35 +000011170 CheckInterceptorLoadIC(InterceptorLoadICGetter,
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011171 "var result = 0;"
11172 "for (var i = 0; i < 1000; i++) {"
11173 " result = o.x;"
ager@chromium.orge2902be2009-06-08 12:21:35 +000011174 "}",
11175 42);
11176}
11177
11178
11179// Below go several tests which verify that JITing for various
11180// configurations of interceptor and explicit fields works fine
11181// (those cases are special cased to get better performance).
11182
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011183static void InterceptorLoadXICGetter(
11184 Local<String> name,
11185 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.orge2902be2009-06-08 12:21:35 +000011186 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011187 info.GetReturnValue().Set(
11188 v8_str("x")->Equals(name) ?
ulan@chromium.org0f13e742014-01-03 15:51:11 +000011189 v8::Handle<v8::Value>(v8::Integer::New(info.GetIsolate(), 42)) :
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011190 v8::Handle<v8::Value>());
ager@chromium.orge2902be2009-06-08 12:21:35 +000011191}
11192
11193
11194THREADED_TEST(InterceptorLoadICWithFieldOnHolder) {
11195 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
11196 "var result = 0;"
11197 "o.y = 239;"
11198 "for (var i = 0; i < 1000; i++) {"
11199 " result = o.y;"
11200 "}",
11201 239);
11202}
11203
11204
11205THREADED_TEST(InterceptorLoadICWithSubstitutedProto) {
11206 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
11207 "var result = 0;"
11208 "o.__proto__ = { 'y': 239 };"
11209 "for (var i = 0; i < 1000; i++) {"
11210 " result = o.y + o.x;"
11211 "}",
11212 239 + 42);
11213}
11214
11215
11216THREADED_TEST(InterceptorLoadICWithPropertyOnProto) {
11217 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
11218 "var result = 0;"
11219 "o.__proto__.y = 239;"
11220 "for (var i = 0; i < 1000; i++) {"
11221 " result = o.y + o.x;"
11222 "}",
11223 239 + 42);
11224}
11225
11226
11227THREADED_TEST(InterceptorLoadICUndefined) {
11228 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
11229 "var result = 0;"
11230 "for (var i = 0; i < 1000; i++) {"
11231 " result = (o.y == undefined) ? 239 : 42;"
11232 "}",
11233 239);
11234}
11235
11236
11237THREADED_TEST(InterceptorLoadICWithOverride) {
11238 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
11239 "fst = new Object(); fst.__proto__ = o;"
11240 "snd = new Object(); snd.__proto__ = fst;"
11241 "var result1 = 0;"
11242 "for (var i = 0; i < 1000; i++) {"
11243 " result1 = snd.x;"
11244 "}"
11245 "fst.x = 239;"
11246 "var result = 0;"
11247 "for (var i = 0; i < 1000; i++) {"
11248 " result = snd.x;"
11249 "}"
11250 "result + result1",
11251 239 + 42);
11252}
11253
11254
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011255// Test the case when we stored field into
11256// a stub, but interceptor produced value on its own.
11257THREADED_TEST(InterceptorLoadICFieldNotNeeded) {
11258 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
11259 "proto = new Object();"
11260 "o.__proto__ = proto;"
11261 "proto.x = 239;"
11262 "for (var i = 0; i < 1000; i++) {"
11263 " o.x;"
11264 // Now it should be ICed and keep a reference to x defined on proto
11265 "}"
11266 "var result = 0;"
11267 "for (var i = 0; i < 1000; i++) {"
11268 " result += o.x;"
11269 "}"
11270 "result;",
11271 42 * 1000);
11272}
11273
11274
11275// Test the case when we stored field into
11276// a stub, but it got invalidated later on.
11277THREADED_TEST(InterceptorLoadICInvalidatedField) {
11278 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
11279 "proto1 = new Object();"
11280 "proto2 = new Object();"
11281 "o.__proto__ = proto1;"
11282 "proto1.__proto__ = proto2;"
11283 "proto2.y = 239;"
11284 "for (var i = 0; i < 1000; i++) {"
11285 " o.y;"
11286 // Now it should be ICed and keep a reference to y defined on proto2
11287 "}"
11288 "proto1.y = 42;"
11289 "var result = 0;"
11290 "for (var i = 0; i < 1000; i++) {"
11291 " result += o.y;"
11292 "}"
11293 "result;",
11294 42 * 1000);
11295}
11296
11297
ager@chromium.orgb26c50a2010-03-26 09:27:16 +000011298static int interceptor_load_not_handled_calls = 0;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011299static void InterceptorLoadNotHandled(
11300 Local<String> name,
11301 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.orgb26c50a2010-03-26 09:27:16 +000011302 ++interceptor_load_not_handled_calls;
ager@chromium.orgb26c50a2010-03-26 09:27:16 +000011303}
11304
11305
11306// Test how post-interceptor lookups are done in the non-cacheable
11307// case: the interceptor should not be invoked during this lookup.
11308THREADED_TEST(InterceptorLoadICPostInterceptor) {
11309 interceptor_load_not_handled_calls = 0;
11310 CheckInterceptorLoadIC(InterceptorLoadNotHandled,
11311 "receiver = new Object();"
11312 "receiver.__proto__ = o;"
11313 "proto = new Object();"
11314 "/* Make proto a slow-case object. */"
11315 "for (var i = 0; i < 1000; i++) {"
11316 " proto[\"xxxxxxxx\" + i] = [];"
11317 "}"
11318 "proto.x = 17;"
11319 "o.__proto__ = proto;"
11320 "var result = 0;"
11321 "for (var i = 0; i < 1000; i++) {"
11322 " result += receiver.x;"
11323 "}"
11324 "result;",
11325 17 * 1000);
11326 CHECK_EQ(1000, interceptor_load_not_handled_calls);
11327}
11328
11329
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011330// Test the case when we stored field into
11331// a stub, but it got invalidated later on due to override on
11332// global object which is between interceptor and fields' holders.
11333THREADED_TEST(InterceptorLoadICInvalidatedFieldViaGlobal) {
11334 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
11335 "o.__proto__ = this;" // set a global to be a proto of o.
11336 "this.__proto__.y = 239;"
11337 "for (var i = 0; i < 10; i++) {"
11338 " if (o.y != 239) throw 'oops: ' + o.y;"
11339 // Now it should be ICed and keep a reference to y defined on field_holder.
11340 "}"
11341 "this.y = 42;" // Assign on a global.
11342 "var result = 0;"
11343 "for (var i = 0; i < 10; i++) {"
11344 " result += o.y;"
11345 "}"
11346 "result;",
11347 42 * 10);
11348}
11349
11350
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011351static void SetOnThis(Local<String> name,
11352 Local<Value> value,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011353 const v8::PropertyCallbackInfo<void>& info) {
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011354 info.This()->ForceSet(name, value);
11355}
11356
11357
11358THREADED_TEST(InterceptorLoadICWithCallbackOnHolder) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011359 v8::Isolate* isolate = CcTest::isolate();
11360 v8::HandleScope scope(isolate);
11361 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011362 templ->SetNamedPropertyHandler(InterceptorLoadXICGetter);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011363 templ->SetAccessor(v8_str("y"), Return239Callback);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011364 LocalContext context;
11365 context->Global()->Set(v8_str("o"), templ->NewInstance());
ricow@chromium.org30ce4112010-05-31 10:38:25 +000011366
11367 // Check the case when receiver and interceptor's holder
11368 // are the same objects.
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011369 v8::Handle<Value> value = CompileRun(
11370 "var result = 0;"
11371 "for (var i = 0; i < 7; i++) {"
11372 " result = o.y;"
11373 "}");
11374 CHECK_EQ(239, value->Int32Value());
ricow@chromium.org30ce4112010-05-31 10:38:25 +000011375
11376 // Check the case when interceptor's holder is in proto chain
11377 // of receiver.
11378 value = CompileRun(
11379 "r = { __proto__: o };"
11380 "var result = 0;"
11381 "for (var i = 0; i < 7; i++) {"
11382 " result = r.y;"
11383 "}");
11384 CHECK_EQ(239, value->Int32Value());
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011385}
11386
11387
11388THREADED_TEST(InterceptorLoadICWithCallbackOnProto) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011389 v8::Isolate* isolate = CcTest::isolate();
11390 v8::HandleScope scope(isolate);
11391 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011392 templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011393 v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New(isolate);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011394 templ_p->SetAccessor(v8_str("y"), Return239Callback);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011395
11396 LocalContext context;
11397 context->Global()->Set(v8_str("o"), templ_o->NewInstance());
11398 context->Global()->Set(v8_str("p"), templ_p->NewInstance());
11399
ricow@chromium.org30ce4112010-05-31 10:38:25 +000011400 // Check the case when receiver and interceptor's holder
11401 // are the same objects.
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011402 v8::Handle<Value> value = CompileRun(
11403 "o.__proto__ = p;"
11404 "var result = 0;"
11405 "for (var i = 0; i < 7; i++) {"
11406 " result = o.x + o.y;"
11407 "}");
11408 CHECK_EQ(239 + 42, value->Int32Value());
ricow@chromium.org30ce4112010-05-31 10:38:25 +000011409
11410 // Check the case when interceptor's holder is in proto chain
11411 // of receiver.
11412 value = CompileRun(
11413 "r = { __proto__: o };"
11414 "var result = 0;"
11415 "for (var i = 0; i < 7; i++) {"
11416 " result = r.x + r.y;"
11417 "}");
11418 CHECK_EQ(239 + 42, value->Int32Value());
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011419}
11420
11421
11422THREADED_TEST(InterceptorLoadICForCallbackWithOverride) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011423 v8::Isolate* isolate = CcTest::isolate();
11424 v8::HandleScope scope(isolate);
11425 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011426 templ->SetNamedPropertyHandler(InterceptorLoadXICGetter);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011427 templ->SetAccessor(v8_str("y"), Return239Callback);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011428
11429 LocalContext context;
11430 context->Global()->Set(v8_str("o"), templ->NewInstance());
11431
11432 v8::Handle<Value> value = CompileRun(
11433 "fst = new Object(); fst.__proto__ = o;"
11434 "snd = new Object(); snd.__proto__ = fst;"
11435 "var result1 = 0;"
11436 "for (var i = 0; i < 7; i++) {"
11437 " result1 = snd.x;"
11438 "}"
11439 "fst.x = 239;"
11440 "var result = 0;"
11441 "for (var i = 0; i < 7; i++) {"
11442 " result = snd.x;"
11443 "}"
11444 "result + result1");
11445 CHECK_EQ(239 + 42, value->Int32Value());
11446}
11447
11448
11449// Test the case when we stored callback into
11450// a stub, but interceptor produced value on its own.
11451THREADED_TEST(InterceptorLoadICCallbackNotNeeded) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011452 v8::Isolate* isolate = CcTest::isolate();
11453 v8::HandleScope scope(isolate);
11454 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011455 templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011456 v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New(isolate);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011457 templ_p->SetAccessor(v8_str("y"), Return239Callback);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011458
11459 LocalContext context;
11460 context->Global()->Set(v8_str("o"), templ_o->NewInstance());
11461 context->Global()->Set(v8_str("p"), templ_p->NewInstance());
11462
11463 v8::Handle<Value> value = CompileRun(
11464 "o.__proto__ = p;"
11465 "for (var i = 0; i < 7; i++) {"
11466 " o.x;"
11467 // Now it should be ICed and keep a reference to x defined on p
11468 "}"
11469 "var result = 0;"
11470 "for (var i = 0; i < 7; i++) {"
11471 " result += o.x;"
11472 "}"
11473 "result");
11474 CHECK_EQ(42 * 7, value->Int32Value());
11475}
11476
11477
11478// Test the case when we stored callback into
11479// a stub, but it got invalidated later on.
11480THREADED_TEST(InterceptorLoadICInvalidatedCallback) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011481 v8::Isolate* isolate = CcTest::isolate();
11482 v8::HandleScope scope(isolate);
11483 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011484 templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011485 v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New(isolate);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011486 templ_p->SetAccessor(v8_str("y"), Return239Callback, SetOnThis);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011487
11488 LocalContext context;
11489 context->Global()->Set(v8_str("o"), templ_o->NewInstance());
11490 context->Global()->Set(v8_str("p"), templ_p->NewInstance());
11491
11492 v8::Handle<Value> value = CompileRun(
11493 "inbetween = new Object();"
11494 "o.__proto__ = inbetween;"
11495 "inbetween.__proto__ = p;"
11496 "for (var i = 0; i < 10; i++) {"
11497 " o.y;"
11498 // Now it should be ICed and keep a reference to y defined on p
11499 "}"
11500 "inbetween.y = 42;"
11501 "var result = 0;"
11502 "for (var i = 0; i < 10; i++) {"
11503 " result += o.y;"
11504 "}"
11505 "result");
11506 CHECK_EQ(42 * 10, value->Int32Value());
11507}
11508
11509
11510// Test the case when we stored callback into
11511// a stub, but it got invalidated later on due to override on
11512// global object which is between interceptor and callbacks' holders.
11513THREADED_TEST(InterceptorLoadICInvalidatedCallbackViaGlobal) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011514 v8::Isolate* isolate = CcTest::isolate();
11515 v8::HandleScope scope(isolate);
11516 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011517 templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011518 v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New(isolate);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011519 templ_p->SetAccessor(v8_str("y"), Return239Callback, SetOnThis);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011520
11521 LocalContext context;
11522 context->Global()->Set(v8_str("o"), templ_o->NewInstance());
11523 context->Global()->Set(v8_str("p"), templ_p->NewInstance());
11524
11525 v8::Handle<Value> value = CompileRun(
11526 "o.__proto__ = this;"
11527 "this.__proto__ = p;"
11528 "for (var i = 0; i < 10; i++) {"
11529 " if (o.y != 239) throw 'oops: ' + o.y;"
11530 // Now it should be ICed and keep a reference to y defined on p
11531 "}"
11532 "this.y = 42;"
11533 "var result = 0;"
11534 "for (var i = 0; i < 10; i++) {"
11535 " result += o.y;"
11536 "}"
11537 "result");
11538 CHECK_EQ(42 * 10, value->Int32Value());
11539}
11540
11541
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011542static void InterceptorLoadICGetter0(
11543 Local<String> name,
11544 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.orge2902be2009-06-08 12:21:35 +000011545 ApiTestFuzzer::Fuzz();
11546 CHECK(v8_str("x")->Equals(name));
ulan@chromium.org0f13e742014-01-03 15:51:11 +000011547 info.GetReturnValue().Set(v8::Integer::New(info.GetIsolate(), 0));
ager@chromium.orge2902be2009-06-08 12:21:35 +000011548}
11549
11550
11551THREADED_TEST(InterceptorReturningZero) {
11552 CheckInterceptorLoadIC(InterceptorLoadICGetter0,
11553 "o.x == undefined ? 1 : 0",
11554 0);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011555}
11556
11557
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011558static void InterceptorStoreICSetter(
11559 Local<String> key,
11560 Local<Value> value,
11561 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011562 CHECK(v8_str("x")->Equals(key));
11563 CHECK_EQ(42, value->Int32Value());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011564 info.GetReturnValue().Set(value);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011565}
11566
11567
11568// This test should hit the store IC for the interceptor case.
11569THREADED_TEST(InterceptorStoreIC) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011570 v8::Isolate* isolate = CcTest::isolate();
11571 v8::HandleScope scope(isolate);
11572 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011573 templ->SetNamedPropertyHandler(InterceptorLoadICGetter,
vegorov@chromium.org21b5e952010-11-23 10:24:40 +000011574 InterceptorStoreICSetter,
11575 0, 0, 0, v8_str("data"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011576 LocalContext context;
11577 context->Global()->Set(v8_str("o"), templ->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000011578 CompileRun(
11579 "for (var i = 0; i < 1000; i++) {"
11580 " o.x = 42;"
11581 "}");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011582}
11583
11584
ager@chromium.orgeadaf222009-06-16 09:43:10 +000011585THREADED_TEST(InterceptorStoreICWithNoSetter) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011586 v8::Isolate* isolate = CcTest::isolate();
11587 v8::HandleScope scope(isolate);
11588 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.orgeadaf222009-06-16 09:43:10 +000011589 templ->SetNamedPropertyHandler(InterceptorLoadXICGetter);
11590 LocalContext context;
11591 context->Global()->Set(v8_str("o"), templ->NewInstance());
11592 v8::Handle<Value> value = CompileRun(
11593 "for (var i = 0; i < 1000; i++) {"
11594 " o.y = 239;"
11595 "}"
11596 "42 + o.y");
11597 CHECK_EQ(239 + 42, value->Int32Value());
11598}
11599
11600
11601
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011602
11603v8::Handle<Value> call_ic_function;
11604v8::Handle<Value> call_ic_function2;
11605v8::Handle<Value> call_ic_function3;
11606
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011607static void InterceptorCallICGetter(
11608 Local<String> name,
11609 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011610 ApiTestFuzzer::Fuzz();
11611 CHECK(v8_str("x")->Equals(name));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011612 info.GetReturnValue().Set(call_ic_function);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011613}
11614
11615
11616// This test should hit the call IC for the interceptor case.
11617THREADED_TEST(InterceptorCallIC) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011618 v8::Isolate* isolate = CcTest::isolate();
11619 v8::HandleScope scope(isolate);
11620 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011621 templ->SetNamedPropertyHandler(InterceptorCallICGetter);
11622 LocalContext context;
11623 context->Global()->Set(v8_str("o"), templ->NewInstance());
11624 call_ic_function =
11625 v8_compile("function f(x) { return x + 1; }; f")->Run();
11626 v8::Handle<Value> value = CompileRun(
11627 "var result = 0;"
11628 "for (var i = 0; i < 1000; i++) {"
11629 " result = o.x(41);"
11630 "}");
11631 CHECK_EQ(42, value->Int32Value());
11632}
11633
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011634
11635// This test checks that if interceptor doesn't provide
11636// a value, we can fetch regular value.
11637THREADED_TEST(InterceptorCallICSeesOthers) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011638 v8::Isolate* isolate = CcTest::isolate();
11639 v8::HandleScope scope(isolate);
11640 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011641 templ->SetNamedPropertyHandler(NoBlockGetterX);
11642 LocalContext context;
11643 context->Global()->Set(v8_str("o"), templ->NewInstance());
11644 v8::Handle<Value> value = CompileRun(
11645 "o.x = function f(x) { return x + 1; };"
11646 "var result = 0;"
11647 "for (var i = 0; i < 7; i++) {"
11648 " result = o.x(41);"
11649 "}");
11650 CHECK_EQ(42, value->Int32Value());
11651}
11652
11653
11654static v8::Handle<Value> call_ic_function4;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011655static void InterceptorCallICGetter4(
11656 Local<String> name,
11657 const v8::PropertyCallbackInfo<v8::Value>& info) {
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011658 ApiTestFuzzer::Fuzz();
11659 CHECK(v8_str("x")->Equals(name));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011660 info.GetReturnValue().Set(call_ic_function4);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011661}
11662
11663
11664// This test checks that if interceptor provides a function,
11665// even if we cached shadowed variant, interceptor's function
11666// is invoked
11667THREADED_TEST(InterceptorCallICCacheableNotNeeded) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011668 v8::Isolate* isolate = CcTest::isolate();
11669 v8::HandleScope scope(isolate);
11670 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011671 templ->SetNamedPropertyHandler(InterceptorCallICGetter4);
11672 LocalContext context;
11673 context->Global()->Set(v8_str("o"), templ->NewInstance());
11674 call_ic_function4 =
11675 v8_compile("function f(x) { return x - 1; }; f")->Run();
11676 v8::Handle<Value> value = CompileRun(
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +000011677 "Object.getPrototypeOf(o).x = function(x) { return x + 1; };"
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011678 "var result = 0;"
11679 "for (var i = 0; i < 1000; i++) {"
11680 " result = o.x(42);"
11681 "}");
11682 CHECK_EQ(41, value->Int32Value());
11683}
11684
11685
11686// Test the case when we stored cacheable lookup into
11687// a stub, but it got invalidated later on
11688THREADED_TEST(InterceptorCallICInvalidatedCacheable) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011689 v8::Isolate* isolate = CcTest::isolate();
11690 v8::HandleScope scope(isolate);
11691 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011692 templ->SetNamedPropertyHandler(NoBlockGetterX);
11693 LocalContext context;
11694 context->Global()->Set(v8_str("o"), templ->NewInstance());
11695 v8::Handle<Value> value = CompileRun(
11696 "proto1 = new Object();"
11697 "proto2 = new Object();"
11698 "o.__proto__ = proto1;"
11699 "proto1.__proto__ = proto2;"
11700 "proto2.y = function(x) { return x + 1; };"
11701 // Invoke it many times to compile a stub
11702 "for (var i = 0; i < 7; i++) {"
11703 " o.y(42);"
11704 "}"
11705 "proto1.y = function(x) { return x - 1; };"
11706 "var result = 0;"
11707 "for (var i = 0; i < 7; i++) {"
11708 " result += o.y(42);"
11709 "}");
11710 CHECK_EQ(41 * 7, value->Int32Value());
11711}
11712
11713
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011714// This test checks that if interceptor doesn't provide a function,
11715// cached constant function is used
11716THREADED_TEST(InterceptorCallICConstantFunctionUsed) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011717 v8::Isolate* isolate = CcTest::isolate();
11718 v8::HandleScope scope(isolate);
11719 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011720 templ->SetNamedPropertyHandler(NoBlockGetterX);
11721 LocalContext context;
11722 context->Global()->Set(v8_str("o"), templ->NewInstance());
11723 v8::Handle<Value> value = CompileRun(
11724 "function inc(x) { return x + 1; };"
11725 "inc(1);"
11726 "o.x = inc;"
11727 "var result = 0;"
11728 "for (var i = 0; i < 1000; i++) {"
11729 " result = o.x(42);"
11730 "}");
11731 CHECK_EQ(43, value->Int32Value());
11732}
11733
11734
ulan@chromium.org2efb9002012-01-19 15:36:35 +000011735static v8::Handle<Value> call_ic_function5;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011736static void InterceptorCallICGetter5(
11737 Local<String> name,
11738 const v8::PropertyCallbackInfo<v8::Value>& info) {
ulan@chromium.org2efb9002012-01-19 15:36:35 +000011739 ApiTestFuzzer::Fuzz();
11740 if (v8_str("x")->Equals(name))
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011741 info.GetReturnValue().Set(call_ic_function5);
ulan@chromium.org2efb9002012-01-19 15:36:35 +000011742}
11743
11744
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011745// This test checks that if interceptor provides a function,
11746// even if we cached constant function, interceptor's function
11747// is invoked
11748THREADED_TEST(InterceptorCallICConstantFunctionNotNeeded) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011749 v8::Isolate* isolate = CcTest::isolate();
11750 v8::HandleScope scope(isolate);
11751 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011752 templ->SetNamedPropertyHandler(InterceptorCallICGetter5);
11753 LocalContext context;
11754 context->Global()->Set(v8_str("o"), templ->NewInstance());
11755 call_ic_function5 =
11756 v8_compile("function f(x) { return x - 1; }; f")->Run();
11757 v8::Handle<Value> value = CompileRun(
11758 "function inc(x) { return x + 1; };"
11759 "inc(1);"
11760 "o.x = inc;"
11761 "var result = 0;"
11762 "for (var i = 0; i < 1000; i++) {"
11763 " result = o.x(42);"
11764 "}");
11765 CHECK_EQ(41, value->Int32Value());
11766}
11767
11768
ulan@chromium.org2efb9002012-01-19 15:36:35 +000011769static v8::Handle<Value> call_ic_function6;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011770static void InterceptorCallICGetter6(
11771 Local<String> name,
11772 const v8::PropertyCallbackInfo<v8::Value>& info) {
ulan@chromium.org2efb9002012-01-19 15:36:35 +000011773 ApiTestFuzzer::Fuzz();
11774 if (v8_str("x")->Equals(name))
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011775 info.GetReturnValue().Set(call_ic_function6);
ulan@chromium.org2efb9002012-01-19 15:36:35 +000011776}
11777
11778
11779// Same test as above, except the code is wrapped in a function
11780// to test the optimized compiler.
11781THREADED_TEST(InterceptorCallICConstantFunctionNotNeededWrapped) {
11782 i::FLAG_allow_natives_syntax = true;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011783 v8::Isolate* isolate = CcTest::isolate();
11784 v8::HandleScope scope(isolate);
11785 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
ulan@chromium.org2efb9002012-01-19 15:36:35 +000011786 templ->SetNamedPropertyHandler(InterceptorCallICGetter6);
11787 LocalContext context;
11788 context->Global()->Set(v8_str("o"), templ->NewInstance());
11789 call_ic_function6 =
11790 v8_compile("function f(x) { return x - 1; }; f")->Run();
11791 v8::Handle<Value> value = CompileRun(
11792 "function inc(x) { return x + 1; };"
11793 "inc(1);"
11794 "o.x = inc;"
11795 "function test() {"
11796 " var result = 0;"
11797 " for (var i = 0; i < 1000; i++) {"
11798 " result = o.x(42);"
11799 " }"
11800 " return result;"
11801 "};"
11802 "test();"
11803 "test();"
11804 "test();"
11805 "%OptimizeFunctionOnNextCall(test);"
11806 "test()");
11807 CHECK_EQ(41, value->Int32Value());
11808}
11809
11810
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011811// Test the case when we stored constant function into
11812// a stub, but it got invalidated later on
11813THREADED_TEST(InterceptorCallICInvalidatedConstantFunction) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011814 v8::Isolate* isolate = CcTest::isolate();
11815 v8::HandleScope scope(isolate);
11816 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011817 templ->SetNamedPropertyHandler(NoBlockGetterX);
11818 LocalContext context;
11819 context->Global()->Set(v8_str("o"), templ->NewInstance());
11820 v8::Handle<Value> value = CompileRun(
11821 "function inc(x) { return x + 1; };"
11822 "inc(1);"
11823 "proto1 = new Object();"
11824 "proto2 = new Object();"
11825 "o.__proto__ = proto1;"
11826 "proto1.__proto__ = proto2;"
11827 "proto2.y = inc;"
11828 // Invoke it many times to compile a stub
11829 "for (var i = 0; i < 7; i++) {"
11830 " o.y(42);"
11831 "}"
11832 "proto1.y = function(x) { return x - 1; };"
11833 "var result = 0;"
11834 "for (var i = 0; i < 7; i++) {"
11835 " result += o.y(42);"
11836 "}");
11837 CHECK_EQ(41 * 7, value->Int32Value());
11838}
11839
11840
11841// Test the case when we stored constant function into
11842// a stub, but it got invalidated later on due to override on
11843// global object which is between interceptor and constant function' holders.
11844THREADED_TEST(InterceptorCallICInvalidatedConstantFunctionViaGlobal) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011845 v8::Isolate* isolate = CcTest::isolate();
11846 v8::HandleScope scope(isolate);
11847 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011848 templ->SetNamedPropertyHandler(NoBlockGetterX);
11849 LocalContext context;
11850 context->Global()->Set(v8_str("o"), templ->NewInstance());
11851 v8::Handle<Value> value = CompileRun(
11852 "function inc(x) { return x + 1; };"
11853 "inc(1);"
11854 "o.__proto__ = this;"
11855 "this.__proto__.y = inc;"
11856 // Invoke it many times to compile a stub
11857 "for (var i = 0; i < 7; i++) {"
11858 " if (o.y(42) != 43) throw 'oops: ' + o.y(42);"
11859 "}"
11860 "this.y = function(x) { return x - 1; };"
11861 "var result = 0;"
11862 "for (var i = 0; i < 7; i++) {"
11863 " result += o.y(42);"
11864 "}");
11865 CHECK_EQ(41 * 7, value->Int32Value());
11866}
11867
11868
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000011869// Test the case when actual function to call sits on global object.
11870THREADED_TEST(InterceptorCallICCachedFromGlobal) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011871 v8::Isolate* isolate = CcTest::isolate();
11872 v8::HandleScope scope(isolate);
11873 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000011874 templ_o->SetNamedPropertyHandler(NoBlockGetterX);
11875
11876 LocalContext context;
11877 context->Global()->Set(v8_str("o"), templ_o->NewInstance());
11878
11879 v8::Handle<Value> value = CompileRun(
11880 "try {"
11881 " o.__proto__ = this;"
11882 " for (var i = 0; i < 10; i++) {"
11883 " var v = o.parseFloat('239');"
11884 " if (v != 239) throw v;"
11885 // Now it should be ICed and keep a reference to parseFloat.
11886 " }"
11887 " var result = 0;"
11888 " for (var i = 0; i < 10; i++) {"
11889 " result += o.parseFloat('239');"
11890 " }"
11891 " result"
11892 "} catch(e) {"
11893 " e"
11894 "};");
11895 CHECK_EQ(239 * 10, value->Int32Value());
11896}
11897
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011898static void InterceptorCallICFastApi(
11899 Local<String> name,
11900 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.org5c838252010-02-19 08:53:10 +000011901 ApiTestFuzzer::Fuzz();
dslomov@chromium.orgb752d402013-06-18 11:54:54 +000011902 CheckReturnValue(info, FUNCTION_ADDR(InterceptorCallICFastApi));
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000011903 int* call_count =
11904 reinterpret_cast<int*>(v8::External::Cast(*info.Data())->Value());
ager@chromium.org5c838252010-02-19 08:53:10 +000011905 ++(*call_count);
11906 if ((*call_count) % 20 == 0) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011907 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org5c838252010-02-19 08:53:10 +000011908 }
ager@chromium.org5c838252010-02-19 08:53:10 +000011909}
11910
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011911static void FastApiCallback_TrivialSignature(
11912 const v8::FunctionCallbackInfo<v8::Value>& args) {
ager@chromium.org5c838252010-02-19 08:53:10 +000011913 ApiTestFuzzer::Fuzz();
dslomov@chromium.orgb752d402013-06-18 11:54:54 +000011914 CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_TrivialSignature));
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011915 v8::Isolate* isolate = CcTest::isolate();
jkummerow@chromium.org28faa982012-04-13 09:58:30 +000011916 CHECK_EQ(isolate, args.GetIsolate());
ager@chromium.org5c838252010-02-19 08:53:10 +000011917 CHECK_EQ(args.This(), args.Holder());
11918 CHECK(args.Data()->Equals(v8_str("method_data")));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011919 args.GetReturnValue().Set(args[0]->Int32Value() + 1);
ager@chromium.org5c838252010-02-19 08:53:10 +000011920}
11921
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011922static void FastApiCallback_SimpleSignature(
11923 const v8::FunctionCallbackInfo<v8::Value>& args) {
ager@chromium.org5c838252010-02-19 08:53:10 +000011924 ApiTestFuzzer::Fuzz();
dslomov@chromium.orgb752d402013-06-18 11:54:54 +000011925 CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_SimpleSignature));
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011926 v8::Isolate* isolate = CcTest::isolate();
jkummerow@chromium.org28faa982012-04-13 09:58:30 +000011927 CHECK_EQ(isolate, args.GetIsolate());
ager@chromium.org5c838252010-02-19 08:53:10 +000011928 CHECK_EQ(args.This()->GetPrototype(), args.Holder());
11929 CHECK(args.Data()->Equals(v8_str("method_data")));
11930 // Note, we're using HasRealNamedProperty instead of Has to avoid
11931 // invoking the interceptor again.
11932 CHECK(args.Holder()->HasRealNamedProperty(v8_str("foo")));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011933 args.GetReturnValue().Set(args[0]->Int32Value() + 1);
ager@chromium.org5c838252010-02-19 08:53:10 +000011934}
11935
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000011936
ager@chromium.org5c838252010-02-19 08:53:10 +000011937// Helper to maximize the odds of object moving.
11938static void GenerateSomeGarbage() {
11939 CompileRun(
11940 "var garbage;"
11941 "for (var i = 0; i < 1000; i++) {"
11942 " garbage = [1/i, \"garbage\" + i, garbage, {foo: garbage}];"
11943 "}"
11944 "garbage = undefined;");
11945}
11946
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000011947
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011948void DirectApiCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +000011949 static int count = 0;
11950 if (count++ % 3 == 0) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011951 CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
yangguo@chromium.orgd2899aa2012-06-21 11:16:20 +000011952 // This should move the stub
ricow@chromium.org83aa5492011-02-07 12:42:56 +000011953 GenerateSomeGarbage(); // This should ensure the old stub memory is flushed
11954 }
ricow@chromium.org83aa5492011-02-07 12:42:56 +000011955}
11956
11957
11958THREADED_TEST(CallICFastApi_DirectCall_GCMoveStub) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +000011959 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000011960 v8::Isolate* isolate = context->GetIsolate();
11961 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011962 v8::Handle<v8::ObjectTemplate> nativeobject_templ =
11963 v8::ObjectTemplate::New(isolate);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000011964 nativeobject_templ->Set(isolate, "callback",
11965 v8::FunctionTemplate::New(isolate,
11966 DirectApiCallback));
ricow@chromium.org83aa5492011-02-07 12:42:56 +000011967 v8::Local<v8::Object> nativeobject_obj = nativeobject_templ->NewInstance();
11968 context->Global()->Set(v8_str("nativeobject"), nativeobject_obj);
11969 // call the api function multiple times to ensure direct call stub creation.
11970 CompileRun(
11971 "function f() {"
11972 " for (var i = 1; i <= 30; i++) {"
11973 " nativeobject.callback();"
11974 " }"
11975 "}"
11976 "f();");
11977}
11978
11979
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011980void ThrowingDirectApiCallback(
11981 const v8::FunctionCallbackInfo<v8::Value>& args) {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000011982 args.GetIsolate()->ThrowException(v8_str("g"));
ricow@chromium.org83aa5492011-02-07 12:42:56 +000011983}
11984
11985
11986THREADED_TEST(CallICFastApi_DirectCall_Throw) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +000011987 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000011988 v8::Isolate* isolate = context->GetIsolate();
11989 v8::HandleScope scope(isolate);
11990 v8::Handle<v8::ObjectTemplate> nativeobject_templ =
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011991 v8::ObjectTemplate::New(isolate);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000011992 nativeobject_templ->Set(isolate, "callback",
11993 v8::FunctionTemplate::New(isolate,
11994 ThrowingDirectApiCallback));
ricow@chromium.org83aa5492011-02-07 12:42:56 +000011995 v8::Local<v8::Object> nativeobject_obj = nativeobject_templ->NewInstance();
11996 context->Global()->Set(v8_str("nativeobject"), nativeobject_obj);
11997 // call the api function multiple times to ensure direct call stub creation.
11998 v8::Handle<Value> result = CompileRun(
11999 "var result = '';"
12000 "function f() {"
12001 " for (var i = 1; i <= 5; i++) {"
12002 " try { nativeobject.callback(); } catch (e) { result += e; }"
12003 " }"
12004 "}"
12005 "f(); result;");
12006 CHECK_EQ(v8_str("ggggg"), result);
12007}
12008
12009
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000012010static Handle<Value> DoDirectGetter() {
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000012011 if (++p_getter_count % 3 == 0) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000012012 CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000012013 GenerateSomeGarbage();
12014 }
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000012015 return v8_str("Direct Getter Result");
12016}
12017
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000012018static void DirectGetterCallback(
12019 Local<String> name,
12020 const v8::PropertyCallbackInfo<v8::Value>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +000012021 CheckReturnValue(info, FUNCTION_ADDR(DirectGetterCallback));
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000012022 info.GetReturnValue().Set(DoDirectGetter());
12023}
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000012024
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000012025
12026template<typename Accessor>
12027static void LoadICFastApi_DirectCall_GCMoveStub(Accessor accessor) {
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000012028 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012029 v8::Isolate* isolate = context->GetIsolate();
12030 v8::HandleScope scope(isolate);
12031 v8::Handle<v8::ObjectTemplate> obj = v8::ObjectTemplate::New(isolate);
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000012032 obj->SetAccessor(v8_str("p1"), accessor);
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000012033 context->Global()->Set(v8_str("o1"), obj->NewInstance());
12034 p_getter_count = 0;
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000012035 v8::Handle<v8::Value> result = CompileRun(
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000012036 "function f() {"
12037 " for (var i = 0; i < 30; i++) o1.p1;"
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000012038 " return o1.p1"
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000012039 "}"
12040 "f();");
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000012041 CHECK_EQ(v8_str("Direct Getter Result"), result);
12042 CHECK_EQ(31, p_getter_count);
12043}
12044
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012045
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012046THREADED_PROFILED_TEST(LoadICFastApi_DirectCall_GCMoveStub) {
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000012047 LoadICFastApi_DirectCall_GCMoveStub(DirectGetterCallback);
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000012048}
12049
12050
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012051void ThrowingDirectGetterCallback(
12052 Local<String> name,
12053 const v8::PropertyCallbackInfo<v8::Value>& info) {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000012054 info.GetIsolate()->ThrowException(v8_str("g"));
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000012055}
12056
12057
12058THREADED_TEST(LoadICFastApi_DirectCall_Throw) {
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000012059 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012060 v8::Isolate* isolate = context->GetIsolate();
12061 v8::HandleScope scope(isolate);
12062 v8::Handle<v8::ObjectTemplate> obj = v8::ObjectTemplate::New(isolate);
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000012063 obj->SetAccessor(v8_str("p1"), ThrowingDirectGetterCallback);
12064 context->Global()->Set(v8_str("o1"), obj->NewInstance());
12065 v8::Handle<Value> result = CompileRun(
12066 "var result = '';"
12067 "for (var i = 0; i < 5; i++) {"
12068 " try { o1.p1; } catch (e) { result += e; }"
12069 "}"
12070 "result;");
12071 CHECK_EQ(v8_str("ggggg"), result);
12072}
12073
12074
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012075THREADED_PROFILED_TEST(InterceptorCallICFastApi_TrivialSignature) {
ager@chromium.org5c838252010-02-19 08:53:10 +000012076 int interceptor_call_count = 0;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012077 v8::Isolate* isolate = CcTest::isolate();
12078 v8::HandleScope scope(isolate);
12079 v8::Handle<v8::FunctionTemplate> fun_templ =
12080 v8::FunctionTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +000012081 v8::Handle<v8::FunctionTemplate> method_templ =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012082 v8::FunctionTemplate::New(isolate,
12083 FastApiCallback_TrivialSignature,
ager@chromium.org5c838252010-02-19 08:53:10 +000012084 v8_str("method_data"),
12085 v8::Handle<v8::Signature>());
12086 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12087 proto_templ->Set(v8_str("method"), method_templ);
12088 v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
machenbach@chromium.org0cc09502013-11-13 12:20:55 +000012089 templ->SetNamedPropertyHandler(
12090 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012091 v8::External::New(isolate, &interceptor_call_count));
ager@chromium.org5c838252010-02-19 08:53:10 +000012092 LocalContext context;
12093 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12094 GenerateSomeGarbage();
12095 context->Global()->Set(v8_str("o"), fun->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012096 CompileRun(
ager@chromium.org5c838252010-02-19 08:53:10 +000012097 "var result = 0;"
12098 "for (var i = 0; i < 100; i++) {"
12099 " result = o.method(41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012100 "}");
ager@chromium.org5c838252010-02-19 08:53:10 +000012101 CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
12102 CHECK_EQ(100, interceptor_call_count);
12103}
12104
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012105
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012106THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature) {
ager@chromium.org5c838252010-02-19 08:53:10 +000012107 int interceptor_call_count = 0;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012108 v8::Isolate* isolate = CcTest::isolate();
12109 v8::HandleScope scope(isolate);
12110 v8::Handle<v8::FunctionTemplate> fun_templ =
12111 v8::FunctionTemplate::New(isolate);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000012112 v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012113 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12114 v8::Signature::New(isolate, fun_templ));
ager@chromium.org5c838252010-02-19 08:53:10 +000012115 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12116 proto_templ->Set(v8_str("method"), method_templ);
mmassi@chromium.org49a44672012-12-04 13:52:03 +000012117 fun_templ->SetHiddenPrototype(true);
ager@chromium.org5c838252010-02-19 08:53:10 +000012118 v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
machenbach@chromium.org0cc09502013-11-13 12:20:55 +000012119 templ->SetNamedPropertyHandler(
12120 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012121 v8::External::New(isolate, &interceptor_call_count));
ager@chromium.org5c838252010-02-19 08:53:10 +000012122 LocalContext context;
12123 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12124 GenerateSomeGarbage();
12125 context->Global()->Set(v8_str("o"), fun->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012126 CompileRun(
ager@chromium.org5c838252010-02-19 08:53:10 +000012127 "o.foo = 17;"
12128 "var receiver = {};"
12129 "receiver.__proto__ = o;"
12130 "var result = 0;"
12131 "for (var i = 0; i < 100; i++) {"
12132 " result = receiver.method(41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012133 "}");
ager@chromium.org5c838252010-02-19 08:53:10 +000012134 CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
12135 CHECK_EQ(100, interceptor_call_count);
12136}
12137
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012138
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012139THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss1) {
ager@chromium.org5c838252010-02-19 08:53:10 +000012140 int interceptor_call_count = 0;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012141 v8::Isolate* isolate = CcTest::isolate();
12142 v8::HandleScope scope(isolate);
12143 v8::Handle<v8::FunctionTemplate> fun_templ =
12144 v8::FunctionTemplate::New(isolate);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000012145 v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012146 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12147 v8::Signature::New(isolate, fun_templ));
ager@chromium.org5c838252010-02-19 08:53:10 +000012148 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12149 proto_templ->Set(v8_str("method"), method_templ);
mmassi@chromium.org49a44672012-12-04 13:52:03 +000012150 fun_templ->SetHiddenPrototype(true);
ager@chromium.org5c838252010-02-19 08:53:10 +000012151 v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
machenbach@chromium.org0cc09502013-11-13 12:20:55 +000012152 templ->SetNamedPropertyHandler(
12153 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012154 v8::External::New(isolate, &interceptor_call_count));
ager@chromium.org5c838252010-02-19 08:53:10 +000012155 LocalContext context;
12156 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12157 GenerateSomeGarbage();
12158 context->Global()->Set(v8_str("o"), fun->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012159 CompileRun(
ager@chromium.org5c838252010-02-19 08:53:10 +000012160 "o.foo = 17;"
12161 "var receiver = {};"
12162 "receiver.__proto__ = o;"
12163 "var result = 0;"
12164 "var saved_result = 0;"
12165 "for (var i = 0; i < 100; i++) {"
12166 " result = receiver.method(41);"
12167 " if (i == 50) {"
12168 " saved_result = result;"
12169 " receiver = {method: function(x) { return x - 1 }};"
12170 " }"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012171 "}");
ager@chromium.org5c838252010-02-19 08:53:10 +000012172 CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
12173 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
12174 CHECK_GE(interceptor_call_count, 50);
12175}
12176
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012177
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012178THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss2) {
ager@chromium.org5c838252010-02-19 08:53:10 +000012179 int interceptor_call_count = 0;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012180 v8::Isolate* isolate = CcTest::isolate();
12181 v8::HandleScope scope(isolate);
12182 v8::Handle<v8::FunctionTemplate> fun_templ =
12183 v8::FunctionTemplate::New(isolate);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000012184 v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012185 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12186 v8::Signature::New(isolate, fun_templ));
ager@chromium.org5c838252010-02-19 08:53:10 +000012187 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12188 proto_templ->Set(v8_str("method"), method_templ);
mmassi@chromium.org49a44672012-12-04 13:52:03 +000012189 fun_templ->SetHiddenPrototype(true);
ager@chromium.org5c838252010-02-19 08:53:10 +000012190 v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
machenbach@chromium.org0cc09502013-11-13 12:20:55 +000012191 templ->SetNamedPropertyHandler(
12192 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012193 v8::External::New(isolate, &interceptor_call_count));
ager@chromium.org5c838252010-02-19 08:53:10 +000012194 LocalContext context;
12195 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12196 GenerateSomeGarbage();
12197 context->Global()->Set(v8_str("o"), fun->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012198 CompileRun(
ager@chromium.org5c838252010-02-19 08:53:10 +000012199 "o.foo = 17;"
12200 "var receiver = {};"
12201 "receiver.__proto__ = o;"
12202 "var result = 0;"
12203 "var saved_result = 0;"
12204 "for (var i = 0; i < 100; i++) {"
12205 " result = receiver.method(41);"
12206 " if (i == 50) {"
12207 " saved_result = result;"
12208 " o.method = function(x) { return x - 1 };"
12209 " }"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012210 "}");
ager@chromium.org5c838252010-02-19 08:53:10 +000012211 CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
12212 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
12213 CHECK_GE(interceptor_call_count, 50);
12214}
12215
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012216
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012217THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss3) {
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000012218 int interceptor_call_count = 0;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012219 v8::Isolate* isolate = CcTest::isolate();
12220 v8::HandleScope scope(isolate);
12221 v8::Handle<v8::FunctionTemplate> fun_templ =
12222 v8::FunctionTemplate::New(isolate);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000012223 v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012224 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12225 v8::Signature::New(isolate, fun_templ));
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000012226 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12227 proto_templ->Set(v8_str("method"), method_templ);
mmassi@chromium.org49a44672012-12-04 13:52:03 +000012228 fun_templ->SetHiddenPrototype(true);
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000012229 v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
machenbach@chromium.org0cc09502013-11-13 12:20:55 +000012230 templ->SetNamedPropertyHandler(
12231 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012232 v8::External::New(isolate, &interceptor_call_count));
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000012233 LocalContext context;
12234 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12235 GenerateSomeGarbage();
12236 context->Global()->Set(v8_str("o"), fun->NewInstance());
12237 v8::TryCatch try_catch;
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012238 CompileRun(
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000012239 "o.foo = 17;"
12240 "var receiver = {};"
12241 "receiver.__proto__ = o;"
12242 "var result = 0;"
12243 "var saved_result = 0;"
12244 "for (var i = 0; i < 100; i++) {"
12245 " result = receiver.method(41);"
12246 " if (i == 50) {"
12247 " saved_result = result;"
12248 " receiver = 333;"
12249 " }"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012250 "}");
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000012251 CHECK(try_catch.HasCaught());
12252 CHECK_EQ(v8_str("TypeError: Object 333 has no method 'method'"),
12253 try_catch.Exception()->ToString());
12254 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
12255 CHECK_GE(interceptor_call_count, 50);
12256}
12257
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012258
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012259THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_TypeError) {
ager@chromium.org5c838252010-02-19 08:53:10 +000012260 int interceptor_call_count = 0;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012261 v8::Isolate* isolate = CcTest::isolate();
12262 v8::HandleScope scope(isolate);
12263 v8::Handle<v8::FunctionTemplate> fun_templ =
12264 v8::FunctionTemplate::New(isolate);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000012265 v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012266 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12267 v8::Signature::New(isolate, fun_templ));
ager@chromium.org5c838252010-02-19 08:53:10 +000012268 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12269 proto_templ->Set(v8_str("method"), method_templ);
mmassi@chromium.org49a44672012-12-04 13:52:03 +000012270 fun_templ->SetHiddenPrototype(true);
ager@chromium.org5c838252010-02-19 08:53:10 +000012271 v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
machenbach@chromium.org0cc09502013-11-13 12:20:55 +000012272 templ->SetNamedPropertyHandler(
12273 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012274 v8::External::New(isolate, &interceptor_call_count));
ager@chromium.org5c838252010-02-19 08:53:10 +000012275 LocalContext context;
12276 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12277 GenerateSomeGarbage();
12278 context->Global()->Set(v8_str("o"), fun->NewInstance());
12279 v8::TryCatch try_catch;
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012280 CompileRun(
ager@chromium.org5c838252010-02-19 08:53:10 +000012281 "o.foo = 17;"
12282 "var receiver = {};"
12283 "receiver.__proto__ = o;"
12284 "var result = 0;"
12285 "var saved_result = 0;"
12286 "for (var i = 0; i < 100; i++) {"
12287 " result = receiver.method(41);"
12288 " if (i == 50) {"
12289 " saved_result = result;"
12290 " receiver = {method: receiver.method};"
12291 " }"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012292 "}");
ager@chromium.org5c838252010-02-19 08:53:10 +000012293 CHECK(try_catch.HasCaught());
12294 CHECK_EQ(v8_str("TypeError: Illegal invocation"),
12295 try_catch.Exception()->ToString());
12296 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
12297 CHECK_GE(interceptor_call_count, 50);
12298}
12299
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012300
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012301THREADED_PROFILED_TEST(CallICFastApi_TrivialSignature) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012302 v8::Isolate* isolate = CcTest::isolate();
12303 v8::HandleScope scope(isolate);
12304 v8::Handle<v8::FunctionTemplate> fun_templ =
12305 v8::FunctionTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +000012306 v8::Handle<v8::FunctionTemplate> method_templ =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012307 v8::FunctionTemplate::New(isolate,
12308 FastApiCallback_TrivialSignature,
ager@chromium.org5c838252010-02-19 08:53:10 +000012309 v8_str("method_data"),
12310 v8::Handle<v8::Signature>());
12311 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12312 proto_templ->Set(v8_str("method"), method_templ);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000012313 v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012314 USE(templ);
ager@chromium.org5c838252010-02-19 08:53:10 +000012315 LocalContext context;
12316 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12317 GenerateSomeGarbage();
12318 context->Global()->Set(v8_str("o"), fun->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012319 CompileRun(
ager@chromium.org5c838252010-02-19 08:53:10 +000012320 "var result = 0;"
12321 "for (var i = 0; i < 100; i++) {"
12322 " result = o.method(41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012323 "}");
ager@chromium.org5c838252010-02-19 08:53:10 +000012324
12325 CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
12326}
12327
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012328
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012329THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012330 v8::Isolate* isolate = CcTest::isolate();
12331 v8::HandleScope scope(isolate);
12332 v8::Handle<v8::FunctionTemplate> fun_templ =
12333 v8::FunctionTemplate::New(isolate);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000012334 v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012335 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12336 v8::Signature::New(isolate, fun_templ));
ager@chromium.org5c838252010-02-19 08:53:10 +000012337 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12338 proto_templ->Set(v8_str("method"), method_templ);
mmassi@chromium.org49a44672012-12-04 13:52:03 +000012339 fun_templ->SetHiddenPrototype(true);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000012340 v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012341 CHECK(!templ.IsEmpty());
ager@chromium.org5c838252010-02-19 08:53:10 +000012342 LocalContext context;
12343 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12344 GenerateSomeGarbage();
12345 context->Global()->Set(v8_str("o"), fun->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012346 CompileRun(
ager@chromium.org5c838252010-02-19 08:53:10 +000012347 "o.foo = 17;"
12348 "var receiver = {};"
12349 "receiver.__proto__ = o;"
12350 "var result = 0;"
12351 "for (var i = 0; i < 100; i++) {"
12352 " result = receiver.method(41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012353 "}");
ager@chromium.org5c838252010-02-19 08:53:10 +000012354
12355 CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
12356}
12357
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012358
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012359THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss1) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012360 v8::Isolate* isolate = CcTest::isolate();
12361 v8::HandleScope scope(isolate);
12362 v8::Handle<v8::FunctionTemplate> fun_templ =
12363 v8::FunctionTemplate::New(isolate);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000012364 v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012365 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12366 v8::Signature::New(isolate, fun_templ));
ager@chromium.org5c838252010-02-19 08:53:10 +000012367 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12368 proto_templ->Set(v8_str("method"), method_templ);
mmassi@chromium.org49a44672012-12-04 13:52:03 +000012369 fun_templ->SetHiddenPrototype(true);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000012370 v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012371 CHECK(!templ.IsEmpty());
ager@chromium.org5c838252010-02-19 08:53:10 +000012372 LocalContext context;
12373 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12374 GenerateSomeGarbage();
12375 context->Global()->Set(v8_str("o"), fun->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012376 CompileRun(
ager@chromium.org5c838252010-02-19 08:53:10 +000012377 "o.foo = 17;"
12378 "var receiver = {};"
12379 "receiver.__proto__ = o;"
12380 "var result = 0;"
12381 "var saved_result = 0;"
12382 "for (var i = 0; i < 100; i++) {"
12383 " result = receiver.method(41);"
12384 " if (i == 50) {"
12385 " saved_result = result;"
12386 " receiver = {method: function(x) { return x - 1 }};"
12387 " }"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012388 "}");
ager@chromium.org5c838252010-02-19 08:53:10 +000012389 CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
12390 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
12391}
12392
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012393
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012394THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss2) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012395 v8::Isolate* isolate = CcTest::isolate();
12396 v8::HandleScope scope(isolate);
12397 v8::Handle<v8::FunctionTemplate> fun_templ =
12398 v8::FunctionTemplate::New(isolate);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000012399 v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012400 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12401 v8::Signature::New(isolate, fun_templ));
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000012402 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12403 proto_templ->Set(v8_str("method"), method_templ);
mmassi@chromium.org49a44672012-12-04 13:52:03 +000012404 fun_templ->SetHiddenPrototype(true);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000012405 v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012406 CHECK(!templ.IsEmpty());
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000012407 LocalContext context;
12408 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12409 GenerateSomeGarbage();
12410 context->Global()->Set(v8_str("o"), fun->NewInstance());
12411 v8::TryCatch try_catch;
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012412 CompileRun(
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000012413 "o.foo = 17;"
12414 "var receiver = {};"
12415 "receiver.__proto__ = o;"
12416 "var result = 0;"
12417 "var saved_result = 0;"
12418 "for (var i = 0; i < 100; i++) {"
12419 " result = receiver.method(41);"
12420 " if (i == 50) {"
12421 " saved_result = result;"
12422 " receiver = 333;"
12423 " }"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012424 "}");
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000012425 CHECK(try_catch.HasCaught());
12426 CHECK_EQ(v8_str("TypeError: Object 333 has no method 'method'"),
12427 try_catch.Exception()->ToString());
12428 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
12429}
12430
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012431
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012432THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_TypeError) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012433 v8::Isolate* isolate = CcTest::isolate();
12434 v8::HandleScope scope(isolate);
12435 v8::Handle<v8::FunctionTemplate> fun_templ =
12436 v8::FunctionTemplate::New(isolate);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000012437 v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012438 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12439 v8::Signature::New(isolate, fun_templ));
mmassi@chromium.org49a44672012-12-04 13:52:03 +000012440 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12441 proto_templ->Set(v8_str("method"), method_templ);
12442 fun_templ->SetHiddenPrototype(true);
12443 v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
12444 CHECK(!templ.IsEmpty());
12445 LocalContext context;
12446 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12447 GenerateSomeGarbage();
12448 context->Global()->Set(v8_str("o"), fun->NewInstance());
12449 v8::TryCatch try_catch;
12450 CompileRun(
12451 "o.foo = 17;"
12452 "var receiver = {};"
12453 "receiver.__proto__ = o;"
12454 "var result = 0;"
12455 "var saved_result = 0;"
12456 "for (var i = 0; i < 100; i++) {"
12457 " result = receiver.method(41);"
12458 " if (i == 50) {"
12459 " saved_result = result;"
12460 " receiver = Object.create(receiver);"
12461 " }"
12462 "}");
12463 CHECK(try_catch.HasCaught());
12464 CHECK_EQ(v8_str("TypeError: Illegal invocation"),
12465 try_catch.Exception()->ToString());
12466 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
12467}
12468
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000012469
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012470v8::Handle<Value> keyed_call_ic_function;
12471
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012472static void InterceptorKeyedCallICGetter(
12473 Local<String> name,
12474 const v8::PropertyCallbackInfo<v8::Value>& info) {
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012475 ApiTestFuzzer::Fuzz();
12476 if (v8_str("x")->Equals(name)) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012477 info.GetReturnValue().Set(keyed_call_ic_function);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012478 }
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012479}
12480
12481
12482// Test the case when we stored cacheable lookup into
12483// a stub, but the function name changed (to another cacheable function).
12484THREADED_TEST(InterceptorKeyedCallICKeyChange1) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012485 v8::Isolate* isolate = CcTest::isolate();
12486 v8::HandleScope scope(isolate);
12487 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012488 templ->SetNamedPropertyHandler(NoBlockGetterX);
12489 LocalContext context;
12490 context->Global()->Set(v8_str("o"), templ->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012491 CompileRun(
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012492 "proto = new Object();"
12493 "proto.y = function(x) { return x + 1; };"
12494 "proto.z = function(x) { return x - 1; };"
12495 "o.__proto__ = proto;"
12496 "var result = 0;"
12497 "var method = 'y';"
12498 "for (var i = 0; i < 10; i++) {"
12499 " if (i == 5) { method = 'z'; };"
12500 " result += o[method](41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012501 "}");
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012502 CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
12503}
12504
12505
12506// Test the case when we stored cacheable lookup into
12507// a stub, but the function name changed (and the new function is present
12508// both before and after the interceptor in the prototype chain).
12509THREADED_TEST(InterceptorKeyedCallICKeyChange2) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012510 v8::Isolate* isolate = CcTest::isolate();
12511 v8::HandleScope scope(isolate);
12512 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012513 templ->SetNamedPropertyHandler(InterceptorKeyedCallICGetter);
12514 LocalContext context;
12515 context->Global()->Set(v8_str("proto1"), templ->NewInstance());
12516 keyed_call_ic_function =
12517 v8_compile("function f(x) { return x - 1; }; f")->Run();
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012518 CompileRun(
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012519 "o = new Object();"
12520 "proto2 = new Object();"
12521 "o.y = function(x) { return x + 1; };"
12522 "proto2.y = function(x) { return x + 2; };"
12523 "o.__proto__ = proto1;"
12524 "proto1.__proto__ = proto2;"
12525 "var result = 0;"
12526 "var method = 'x';"
12527 "for (var i = 0; i < 10; i++) {"
12528 " if (i == 5) { method = 'y'; };"
12529 " result += o[method](41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012530 "}");
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012531 CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
12532}
12533
12534
12535// Same as InterceptorKeyedCallICKeyChange1 only the cacheable function sit
12536// on the global object.
12537THREADED_TEST(InterceptorKeyedCallICKeyChangeOnGlobal) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012538 v8::Isolate* isolate = CcTest::isolate();
12539 v8::HandleScope scope(isolate);
12540 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012541 templ->SetNamedPropertyHandler(NoBlockGetterX);
12542 LocalContext context;
12543 context->Global()->Set(v8_str("o"), templ->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012544 CompileRun(
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012545 "function inc(x) { return x + 1; };"
12546 "inc(1);"
12547 "function dec(x) { return x - 1; };"
12548 "dec(1);"
12549 "o.__proto__ = this;"
12550 "this.__proto__.x = inc;"
12551 "this.__proto__.y = dec;"
12552 "var result = 0;"
12553 "var method = 'x';"
12554 "for (var i = 0; i < 10; i++) {"
12555 " if (i == 5) { method = 'y'; };"
12556 " result += o[method](41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012557 "}");
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012558 CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
12559}
12560
12561
12562// Test the case when actual function to call sits on global object.
12563THREADED_TEST(InterceptorKeyedCallICFromGlobal) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012564 v8::Isolate* isolate = CcTest::isolate();
12565 v8::HandleScope scope(isolate);
12566 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012567 templ_o->SetNamedPropertyHandler(NoBlockGetterX);
12568 LocalContext context;
12569 context->Global()->Set(v8_str("o"), templ_o->NewInstance());
12570
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012571 CompileRun(
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012572 "function len(x) { return x.length; };"
12573 "o.__proto__ = this;"
12574 "var m = 'parseFloat';"
12575 "var result = 0;"
12576 "for (var i = 0; i < 10; i++) {"
12577 " if (i == 5) {"
12578 " m = 'len';"
12579 " saved_result = result;"
12580 " };"
12581 " result = o[m]('239');"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012582 "}");
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012583 CHECK_EQ(3, context->Global()->Get(v8_str("result"))->Int32Value());
12584 CHECK_EQ(239, context->Global()->Get(v8_str("saved_result"))->Int32Value());
12585}
12586
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012587
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012588// Test the map transition before the interceptor.
12589THREADED_TEST(InterceptorKeyedCallICMapChangeBefore) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012590 v8::Isolate* isolate = CcTest::isolate();
12591 v8::HandleScope scope(isolate);
12592 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012593 templ_o->SetNamedPropertyHandler(NoBlockGetterX);
12594 LocalContext context;
12595 context->Global()->Set(v8_str("proto"), templ_o->NewInstance());
12596
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012597 CompileRun(
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012598 "var o = new Object();"
12599 "o.__proto__ = proto;"
12600 "o.method = function(x) { return x + 1; };"
12601 "var m = 'method';"
12602 "var result = 0;"
12603 "for (var i = 0; i < 10; i++) {"
12604 " if (i == 5) { o.method = function(x) { return x - 1; }; };"
12605 " result += o[m](41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012606 "}");
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012607 CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
12608}
12609
12610
12611// Test the map transition after the interceptor.
12612THREADED_TEST(InterceptorKeyedCallICMapChangeAfter) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012613 v8::Isolate* isolate = CcTest::isolate();
12614 v8::HandleScope scope(isolate);
12615 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012616 templ_o->SetNamedPropertyHandler(NoBlockGetterX);
12617 LocalContext context;
12618 context->Global()->Set(v8_str("o"), templ_o->NewInstance());
12619
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012620 CompileRun(
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012621 "var proto = new Object();"
12622 "o.__proto__ = proto;"
12623 "proto.method = function(x) { return x + 1; };"
12624 "var m = 'method';"
12625 "var result = 0;"
12626 "for (var i = 0; i < 10; i++) {"
12627 " if (i == 5) { proto.method = function(x) { return x - 1; }; };"
12628 " result += o[m](41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012629 "}");
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012630 CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
12631}
12632
12633
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012634static int interceptor_call_count = 0;
12635
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012636static void InterceptorICRefErrorGetter(
12637 Local<String> name,
12638 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012639 ApiTestFuzzer::Fuzz();
12640 if (v8_str("x")->Equals(name) && interceptor_call_count++ < 20) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012641 info.GetReturnValue().Set(call_ic_function2);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012642 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012643}
12644
12645
12646// This test should hit load and call ICs for the interceptor case.
12647// Once in a while, the interceptor will reply that a property was not
12648// found in which case we should get a reference error.
12649THREADED_TEST(InterceptorICReferenceErrors) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012650 v8::Isolate* isolate = CcTest::isolate();
12651 v8::HandleScope scope(isolate);
12652 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012653 templ->SetNamedPropertyHandler(InterceptorICRefErrorGetter);
12654 LocalContext context(0, templ, v8::Handle<Value>());
12655 call_ic_function2 = v8_compile("function h(x) { return x; }; h")->Run();
12656 v8::Handle<Value> value = CompileRun(
12657 "function f() {"
12658 " for (var i = 0; i < 1000; i++) {"
12659 " try { x; } catch(e) { return true; }"
12660 " }"
12661 " return false;"
12662 "};"
12663 "f();");
12664 CHECK_EQ(true, value->BooleanValue());
12665 interceptor_call_count = 0;
12666 value = CompileRun(
12667 "function g() {"
12668 " for (var i = 0; i < 1000; i++) {"
12669 " try { x(42); } catch(e) { return true; }"
12670 " }"
12671 " return false;"
12672 "};"
12673 "g();");
12674 CHECK_EQ(true, value->BooleanValue());
12675}
12676
12677
12678static int interceptor_ic_exception_get_count = 0;
12679
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012680static void InterceptorICExceptionGetter(
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012681 Local<String> name,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012682 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012683 ApiTestFuzzer::Fuzz();
12684 if (v8_str("x")->Equals(name) && ++interceptor_ic_exception_get_count < 20) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012685 info.GetReturnValue().Set(call_ic_function3);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012686 }
12687 if (interceptor_ic_exception_get_count == 20) {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000012688 info.GetIsolate()->ThrowException(v8_num(42));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012689 return;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012690 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012691}
12692
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012693
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012694// Test interceptor load/call IC where the interceptor throws an
12695// exception once in a while.
12696THREADED_TEST(InterceptorICGetterExceptions) {
12697 interceptor_ic_exception_get_count = 0;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012698 v8::Isolate* isolate = CcTest::isolate();
12699 v8::HandleScope scope(isolate);
12700 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012701 templ->SetNamedPropertyHandler(InterceptorICExceptionGetter);
12702 LocalContext context(0, templ, v8::Handle<Value>());
12703 call_ic_function3 = v8_compile("function h(x) { return x; }; h")->Run();
12704 v8::Handle<Value> value = CompileRun(
12705 "function f() {"
12706 " for (var i = 0; i < 100; i++) {"
12707 " try { x; } catch(e) { return true; }"
12708 " }"
12709 " return false;"
12710 "};"
12711 "f();");
12712 CHECK_EQ(true, value->BooleanValue());
12713 interceptor_ic_exception_get_count = 0;
12714 value = CompileRun(
12715 "function f() {"
12716 " for (var i = 0; i < 100; i++) {"
12717 " try { x(42); } catch(e) { return true; }"
12718 " }"
12719 " return false;"
12720 "};"
12721 "f();");
12722 CHECK_EQ(true, value->BooleanValue());
12723}
12724
12725
12726static int interceptor_ic_exception_set_count = 0;
12727
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012728static void InterceptorICExceptionSetter(
12729 Local<String> key,
12730 Local<Value> value,
12731 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012732 ApiTestFuzzer::Fuzz();
12733 if (++interceptor_ic_exception_set_count > 20) {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000012734 info.GetIsolate()->ThrowException(v8_num(42));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012735 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012736}
12737
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012738
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012739// Test interceptor store IC where the interceptor throws an exception
12740// once in a while.
12741THREADED_TEST(InterceptorICSetterExceptions) {
12742 interceptor_ic_exception_set_count = 0;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012743 v8::Isolate* isolate = CcTest::isolate();
12744 v8::HandleScope scope(isolate);
12745 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012746 templ->SetNamedPropertyHandler(0, InterceptorICExceptionSetter);
12747 LocalContext context(0, templ, v8::Handle<Value>());
12748 v8::Handle<Value> value = CompileRun(
12749 "function f() {"
12750 " for (var i = 0; i < 100; i++) {"
12751 " try { x = 42; } catch(e) { return true; }"
12752 " }"
12753 " return false;"
12754 "};"
12755 "f();");
12756 CHECK_EQ(true, value->BooleanValue());
12757}
12758
12759
12760// Test that we ignore null interceptors.
12761THREADED_TEST(NullNamedInterceptor) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012762 v8::Isolate* isolate = CcTest::isolate();
12763 v8::HandleScope scope(isolate);
12764 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012765 templ->SetNamedPropertyHandler(
12766 static_cast<v8::NamedPropertyGetterCallback>(0));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012767 LocalContext context;
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000012768 templ->Set(CcTest::isolate(), "x", v8_num(42));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012769 v8::Handle<v8::Object> obj = templ->NewInstance();
12770 context->Global()->Set(v8_str("obj"), obj);
12771 v8::Handle<Value> value = CompileRun("obj.x");
12772 CHECK(value->IsInt32());
12773 CHECK_EQ(42, value->Int32Value());
12774}
12775
12776
12777// Test that we ignore null interceptors.
12778THREADED_TEST(NullIndexedInterceptor) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012779 v8::Isolate* isolate = CcTest::isolate();
12780 v8::HandleScope scope(isolate);
12781 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012782 templ->SetIndexedPropertyHandler(
12783 static_cast<v8::IndexedPropertyGetterCallback>(0));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012784 LocalContext context;
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000012785 templ->Set(CcTest::isolate(), "42", v8_num(42));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012786 v8::Handle<v8::Object> obj = templ->NewInstance();
12787 context->Global()->Set(v8_str("obj"), obj);
12788 v8::Handle<Value> value = CompileRun("obj[42]");
12789 CHECK(value->IsInt32());
12790 CHECK_EQ(42, value->Int32Value());
12791}
12792
12793
ricow@chromium.org30ce4112010-05-31 10:38:25 +000012794THREADED_TEST(NamedPropertyHandlerGetterAttributes) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012795 v8::Isolate* isolate = CcTest::isolate();
12796 v8::HandleScope scope(isolate);
12797 v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
ricow@chromium.org30ce4112010-05-31 10:38:25 +000012798 templ->InstanceTemplate()->SetNamedPropertyHandler(InterceptorLoadXICGetter);
12799 LocalContext env;
12800 env->Global()->Set(v8_str("obj"),
12801 templ->GetFunction()->NewInstance());
12802 ExpectTrue("obj.x === 42");
12803 ExpectTrue("!obj.propertyIsEnumerable('x')");
12804}
12805
12806
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012807static void ThrowingGetter(Local<String> name,
12808 const v8::PropertyCallbackInfo<v8::Value>& info) {
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012809 ApiTestFuzzer::Fuzz();
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000012810 info.GetIsolate()->ThrowException(Handle<Value>());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012811 info.GetReturnValue().SetUndefined();
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012812}
12813
12814
12815THREADED_TEST(VariousGetPropertiesAndThrowingCallbacks) {
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012816 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000012817 HandleScope scope(context->GetIsolate());
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012818
ulan@chromium.org0f13e742014-01-03 15:51:11 +000012819 Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012820 Local<ObjectTemplate> instance_templ = templ->InstanceTemplate();
12821 instance_templ->SetAccessor(v8_str("f"), ThrowingGetter);
12822
12823 Local<Object> instance = templ->GetFunction()->NewInstance();
12824
ulan@chromium.org0f13e742014-01-03 15:51:11 +000012825 Local<Object> another = Object::New(context->GetIsolate());
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012826 another->SetPrototype(instance);
12827
12828 Local<Object> with_js_getter = CompileRun(
12829 "o = {};\n"
12830 "o.__defineGetter__('f', function() { throw undefined; });\n"
12831 "o\n").As<Object>();
12832 CHECK(!with_js_getter.IsEmpty());
12833
12834 TryCatch try_catch;
12835
12836 Local<Value> result = instance->GetRealNamedProperty(v8_str("f"));
12837 CHECK(try_catch.HasCaught());
12838 try_catch.Reset();
12839 CHECK(result.IsEmpty());
12840
12841 result = another->GetRealNamedProperty(v8_str("f"));
12842 CHECK(try_catch.HasCaught());
12843 try_catch.Reset();
12844 CHECK(result.IsEmpty());
12845
12846 result = another->GetRealNamedPropertyInPrototypeChain(v8_str("f"));
12847 CHECK(try_catch.HasCaught());
12848 try_catch.Reset();
12849 CHECK(result.IsEmpty());
12850
12851 result = another->Get(v8_str("f"));
12852 CHECK(try_catch.HasCaught());
12853 try_catch.Reset();
12854 CHECK(result.IsEmpty());
12855
12856 result = with_js_getter->GetRealNamedProperty(v8_str("f"));
12857 CHECK(try_catch.HasCaught());
12858 try_catch.Reset();
12859 CHECK(result.IsEmpty());
12860
12861 result = with_js_getter->Get(v8_str("f"));
12862 CHECK(try_catch.HasCaught());
12863 try_catch.Reset();
12864 CHECK(result.IsEmpty());
12865}
12866
12867
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012868static void ThrowingCallbackWithTryCatch(
12869 const v8::FunctionCallbackInfo<v8::Value>& args) {
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012870 TryCatch try_catch;
12871 // Verboseness is important: it triggers message delivery which can call into
12872 // external code.
12873 try_catch.SetVerbose(true);
12874 CompileRun("throw 'from JS';");
12875 CHECK(try_catch.HasCaught());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000012876 CHECK(!CcTest::i_isolate()->has_pending_exception());
12877 CHECK(!CcTest::i_isolate()->has_scheduled_exception());
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012878}
12879
12880
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +000012881static int call_depth;
12882
12883
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012884static void WithTryCatch(Handle<Message> message, Handle<Value> data) {
12885 TryCatch try_catch;
12886}
12887
12888
12889static void ThrowFromJS(Handle<Message> message, Handle<Value> data) {
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +000012890 if (--call_depth) CompileRun("throw 'ThrowInJS';");
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012891}
12892
12893
12894static void ThrowViaApi(Handle<Message> message, Handle<Value> data) {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000012895 if (--call_depth) CcTest::isolate()->ThrowException(v8_str("ThrowViaApi"));
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012896}
12897
12898
12899static void WebKitLike(Handle<Message> message, Handle<Value> data) {
12900 Handle<String> errorMessageString = message->Get();
12901 CHECK(!errorMessageString.IsEmpty());
12902 message->GetStackTrace();
12903 message->GetScriptResourceName();
12904}
12905
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012906
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012907THREADED_TEST(ExceptionsDoNotPropagatePastTryCatch) {
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012908 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012909 v8::Isolate* isolate = context->GetIsolate();
12910 HandleScope scope(isolate);
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012911
12912 Local<Function> func =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012913 FunctionTemplate::New(isolate,
12914 ThrowingCallbackWithTryCatch)->GetFunction();
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012915 context->Global()->Set(v8_str("func"), func);
12916
12917 MessageCallback callbacks[] =
12918 { NULL, WebKitLike, ThrowViaApi, ThrowFromJS, WithTryCatch };
12919 for (unsigned i = 0; i < sizeof(callbacks)/sizeof(callbacks[0]); i++) {
12920 MessageCallback callback = callbacks[i];
12921 if (callback != NULL) {
12922 V8::AddMessageListener(callback);
12923 }
ricow@chromium.orgdcebac02011-04-20 09:44:50 +000012924 // Some small number to control number of times message handler should
12925 // throw an exception.
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +000012926 call_depth = 5;
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012927 ExpectFalse(
12928 "var thrown = false;\n"
12929 "try { func(); } catch(e) { thrown = true; }\n"
12930 "thrown\n");
12931 if (callback != NULL) {
12932 V8::RemoveMessageListeners(callback);
12933 }
12934 }
12935}
12936
12937
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012938static void ParentGetter(Local<String> name,
12939 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012940 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012941 info.GetReturnValue().Set(v8_num(1));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012942}
12943
12944
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012945static void ChildGetter(Local<String> name,
12946 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012947 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012948 info.GetReturnValue().Set(v8_num(42));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012949}
12950
12951
12952THREADED_TEST(Overriding) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +000012953 i::FLAG_es5_readonly = true;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012954 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012955 v8::Isolate* isolate = context->GetIsolate();
12956 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012957
12958 // Parent template.
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012959 Local<v8::FunctionTemplate> parent_templ = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012960 Local<ObjectTemplate> parent_instance_templ =
12961 parent_templ->InstanceTemplate();
12962 parent_instance_templ->SetAccessor(v8_str("f"), ParentGetter);
12963
12964 // Template that inherits from the parent template.
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012965 Local<v8::FunctionTemplate> child_templ = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012966 Local<ObjectTemplate> child_instance_templ =
12967 child_templ->InstanceTemplate();
12968 child_templ->Inherit(parent_templ);
12969 // Override 'f'. The child version of 'f' should get called for child
12970 // instances.
12971 child_instance_templ->SetAccessor(v8_str("f"), ChildGetter);
12972 // Add 'g' twice. The 'g' added last should get called for instances.
12973 child_instance_templ->SetAccessor(v8_str("g"), ParentGetter);
12974 child_instance_templ->SetAccessor(v8_str("g"), ChildGetter);
12975
12976 // Add 'h' as an accessor to the proto template with ReadOnly attributes
12977 // so 'h' can be shadowed on the instance object.
12978 Local<ObjectTemplate> child_proto_templ = child_templ->PrototypeTemplate();
12979 child_proto_templ->SetAccessor(v8_str("h"), ParentGetter, 0,
12980 v8::Handle<Value>(), v8::DEFAULT, v8::ReadOnly);
12981
12982 // Add 'i' as an accessor to the instance template with ReadOnly attributes
12983 // but the attribute does not have effect because it is duplicated with
12984 // NULL setter.
12985 child_instance_templ->SetAccessor(v8_str("i"), ChildGetter, 0,
12986 v8::Handle<Value>(), v8::DEFAULT, v8::ReadOnly);
12987
12988
12989
12990 // Instantiate the child template.
12991 Local<v8::Object> instance = child_templ->GetFunction()->NewInstance();
12992
12993 // Check that the child function overrides the parent one.
12994 context->Global()->Set(v8_str("o"), instance);
12995 Local<Value> value = v8_compile("o.f")->Run();
12996 // Check that the 'g' that was added last is hit.
12997 CHECK_EQ(42, value->Int32Value());
12998 value = v8_compile("o.g")->Run();
12999 CHECK_EQ(42, value->Int32Value());
13000
mmassi@chromium.org7028c052012-06-13 11:51:58 +000013001 // Check that 'h' cannot be shadowed.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013002 value = v8_compile("o.h = 3; o.h")->Run();
mmassi@chromium.org7028c052012-06-13 11:51:58 +000013003 CHECK_EQ(1, value->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013004
mmassi@chromium.org7028c052012-06-13 11:51:58 +000013005 // Check that 'i' cannot be shadowed or changed.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013006 value = v8_compile("o.i = 3; o.i")->Run();
13007 CHECK_EQ(42, value->Int32Value());
13008}
13009
13010
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013011static void IsConstructHandler(
13012 const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013013 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013014 args.GetReturnValue().Set(args.IsConstructCall());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013015}
13016
13017
13018THREADED_TEST(IsConstructCall) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000013019 v8::Isolate* isolate = CcTest::isolate();
13020 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013021
13022 // Function template with call handler.
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000013023 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013024 templ->SetCallHandler(IsConstructHandler);
13025
13026 LocalContext context;
13027
13028 context->Global()->Set(v8_str("f"), templ->GetFunction());
13029 Local<Value> value = v8_compile("f()")->Run();
13030 CHECK(!value->BooleanValue());
13031 value = v8_compile("new f()")->Run();
13032 CHECK(value->BooleanValue());
13033}
13034
13035
13036THREADED_TEST(ObjectProtoToString) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000013037 v8::Isolate* isolate = CcTest::isolate();
13038 v8::HandleScope scope(isolate);
13039 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013040 templ->SetClassName(v8_str("MyClass"));
13041
13042 LocalContext context;
13043
13044 Local<String> customized_tostring = v8_str("customized toString");
13045
13046 // Replace Object.prototype.toString
13047 v8_compile("Object.prototype.toString = function() {"
13048 " return 'customized toString';"
13049 "}")->Run();
13050
13051 // Normal ToString call should call replaced Object.prototype.toString
13052 Local<v8::Object> instance = templ->GetFunction()->NewInstance();
13053 Local<String> value = instance->ToString();
13054 CHECK(value->IsString() && value->Equals(customized_tostring));
13055
13056 // ObjectProtoToString should not call replace toString function.
13057 value = instance->ObjectProtoToString();
13058 CHECK(value->IsString() && value->Equals(v8_str("[object MyClass]")));
13059
13060 // Check global
13061 value = context->Global()->ObjectProtoToString();
13062 CHECK(value->IsString() && value->Equals(v8_str("[object global]")));
13063
13064 // Check ordinary object
13065 Local<Value> object = v8_compile("new Object()")->Run();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000013066 value = object.As<v8::Object>()->ObjectProtoToString();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013067 CHECK(value->IsString() && value->Equals(v8_str("[object Object]")));
13068}
13069
13070
ager@chromium.orgbeb25712010-11-29 08:02:25 +000013071THREADED_TEST(ObjectGetConstructorName) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +000013072 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013073 v8::HandleScope scope(context->GetIsolate());
ager@chromium.orgbeb25712010-11-29 08:02:25 +000013074 v8_compile("function Parent() {};"
13075 "function Child() {};"
13076 "Child.prototype = new Parent();"
13077 "var outer = { inner: function() { } };"
13078 "var p = new Parent();"
13079 "var c = new Child();"
13080 "var x = new outer.inner();")->Run();
13081
13082 Local<v8::Value> p = context->Global()->Get(v8_str("p"));
13083 CHECK(p->IsObject() && p->ToObject()->GetConstructorName()->Equals(
13084 v8_str("Parent")));
13085
13086 Local<v8::Value> c = context->Global()->Get(v8_str("c"));
13087 CHECK(c->IsObject() && c->ToObject()->GetConstructorName()->Equals(
13088 v8_str("Child")));
13089
13090 Local<v8::Value> x = context->Global()->Get(v8_str("x"));
13091 CHECK(x->IsObject() && x->ToObject()->GetConstructorName()->Equals(
13092 v8_str("outer.inner")));
13093}
13094
13095
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013096bool ApiTestFuzzer::fuzzing_ = false;
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000013097i::Semaphore ApiTestFuzzer::all_tests_done_(0);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013098int ApiTestFuzzer::active_tests_;
13099int ApiTestFuzzer::tests_being_run_;
13100int ApiTestFuzzer::current_;
13101
13102
13103// We are in a callback and want to switch to another thread (if we
13104// are currently running the thread fuzzing test).
13105void ApiTestFuzzer::Fuzz() {
13106 if (!fuzzing_) return;
13107 ApiTestFuzzer* test = RegisterThreadedTest::nth(current_)->fuzzer_;
13108 test->ContextSwitch();
13109}
13110
13111
13112// Let the next thread go. Since it is also waiting on the V8 lock it may
13113// not start immediately.
13114bool ApiTestFuzzer::NextThread() {
13115 int test_position = GetNextTestNumber();
ager@chromium.orgc4c92722009-11-18 14:12:51 +000013116 const char* test_name = RegisterThreadedTest::nth(current_)->name();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013117 if (test_position == current_) {
ager@chromium.orgc4c92722009-11-18 14:12:51 +000013118 if (kLogThreading)
13119 printf("Stay with %s\n", test_name);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013120 return false;
13121 }
ager@chromium.orgc4c92722009-11-18 14:12:51 +000013122 if (kLogThreading) {
13123 printf("Switch from %s to %s\n",
13124 test_name,
13125 RegisterThreadedTest::nth(test_position)->name());
13126 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013127 current_ = test_position;
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000013128 RegisterThreadedTest::nth(current_)->fuzzer_->gate_.Signal();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013129 return true;
13130}
13131
13132
13133void ApiTestFuzzer::Run() {
13134 // When it is our turn...
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000013135 gate_.Wait();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013136 {
13137 // ... get the V8 lock and start running the test.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013138 v8::Locker locker(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013139 CallTest();
13140 }
13141 // This test finished.
13142 active_ = false;
13143 active_tests_--;
13144 // If it was the last then signal that fact.
13145 if (active_tests_ == 0) {
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000013146 all_tests_done_.Signal();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013147 } else {
13148 // Otherwise select a new test and start that.
13149 NextThread();
13150 }
13151}
13152
13153
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013154static unsigned linear_congruential_generator;
13155
13156
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000013157void ApiTestFuzzer::SetUp(PartOfTest part) {
kasperl@chromium.orgb9123622008-09-17 14:05:56 +000013158 linear_congruential_generator = i::FLAG_testing_prng_seed;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013159 fuzzing_ = true;
lrn@chromium.org1c092762011-05-09 09:42:16 +000013160 int count = RegisterThreadedTest::count();
13161 int start = count * part / (LAST_PART + 1);
13162 int end = (count * (part + 1) / (LAST_PART + 1)) - 1;
13163 active_tests_ = tests_being_run_ = end - start + 1;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013164 for (int i = 0; i < tests_being_run_; i++) {
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000013165 RegisterThreadedTest::nth(i)->fuzzer_ = new ApiTestFuzzer(i + start);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013166 }
13167 for (int i = 0; i < active_tests_; i++) {
13168 RegisterThreadedTest::nth(i)->fuzzer_->Start();
13169 }
13170}
13171
13172
13173static void CallTestNumber(int test_number) {
13174 (RegisterThreadedTest::nth(test_number)->callback())();
13175}
13176
13177
13178void ApiTestFuzzer::RunAllTests() {
13179 // Set off the first test.
13180 current_ = -1;
13181 NextThread();
13182 // Wait till they are all done.
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000013183 all_tests_done_.Wait();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013184}
13185
13186
13187int ApiTestFuzzer::GetNextTestNumber() {
13188 int next_test;
13189 do {
13190 next_test = (linear_congruential_generator >> 16) % tests_being_run_;
13191 linear_congruential_generator *= 1664525u;
13192 linear_congruential_generator += 1013904223u;
13193 } while (!RegisterThreadedTest::nth(next_test)->fuzzer_->active_);
13194 return next_test;
13195}
13196
13197
13198void ApiTestFuzzer::ContextSwitch() {
13199 // If the new thread is the same as the current thread there is nothing to do.
13200 if (NextThread()) {
13201 // Now it can start.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013202 v8::Unlocker unlocker(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013203 // Wait till someone starts us again.
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000013204 gate_.Wait();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013205 // And we're off.
13206 }
13207}
13208
13209
13210void ApiTestFuzzer::TearDown() {
13211 fuzzing_ = false;
ager@chromium.org41826e72009-03-30 13:30:57 +000013212 for (int i = 0; i < RegisterThreadedTest::count(); i++) {
13213 ApiTestFuzzer *fuzzer = RegisterThreadedTest::nth(i)->fuzzer_;
13214 if (fuzzer != NULL) fuzzer->Join();
13215 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013216}
13217
13218
13219// Lets not be needlessly self-referential.
mmassi@chromium.org2f0efde2013-02-06 14:12:58 +000013220TEST(Threading1) {
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000013221 ApiTestFuzzer::SetUp(ApiTestFuzzer::FIRST_PART);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013222 ApiTestFuzzer::RunAllTests();
13223 ApiTestFuzzer::TearDown();
13224}
13225
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000013226
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013227TEST(Threading2) {
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000013228 ApiTestFuzzer::SetUp(ApiTestFuzzer::SECOND_PART);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013229 ApiTestFuzzer::RunAllTests();
13230 ApiTestFuzzer::TearDown();
13231}
13232
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000013233
lrn@chromium.org1c092762011-05-09 09:42:16 +000013234TEST(Threading3) {
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000013235 ApiTestFuzzer::SetUp(ApiTestFuzzer::THIRD_PART);
lrn@chromium.org1c092762011-05-09 09:42:16 +000013236 ApiTestFuzzer::RunAllTests();
13237 ApiTestFuzzer::TearDown();
13238}
13239
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000013240
lrn@chromium.org1c092762011-05-09 09:42:16 +000013241TEST(Threading4) {
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000013242 ApiTestFuzzer::SetUp(ApiTestFuzzer::FOURTH_PART);
lrn@chromium.org1c092762011-05-09 09:42:16 +000013243 ApiTestFuzzer::RunAllTests();
13244 ApiTestFuzzer::TearDown();
13245}
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013246
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000013247
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013248void ApiTestFuzzer::CallTest() {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013249 v8::Isolate::Scope scope(CcTest::isolate());
ager@chromium.orgc4c92722009-11-18 14:12:51 +000013250 if (kLogThreading)
13251 printf("Start test %d\n", test_number_);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013252 CallTestNumber(test_number_);
ager@chromium.orgc4c92722009-11-18 14:12:51 +000013253 if (kLogThreading)
13254 printf("End test %d\n", test_number_);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013255}
13256
13257
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013258static void ThrowInJS(const v8::FunctionCallbackInfo<v8::Value>& args) {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000013259 v8::Isolate* isolate = args.GetIsolate();
13260 CHECK(v8::Locker::IsLocked(isolate));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013261 ApiTestFuzzer::Fuzz();
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000013262 v8::Unlocker unlocker(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013263 const char* code = "throw 7;";
13264 {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000013265 v8::Locker nested_locker(isolate);
13266 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013267 v8::Handle<Value> exception;
13268 { v8::TryCatch try_catch;
13269 v8::Handle<Value> value = CompileRun(code);
13270 CHECK(value.IsEmpty());
13271 CHECK(try_catch.HasCaught());
13272 // Make sure to wrap the exception in a new handle because
13273 // the handle returned from the TryCatch is destroyed
13274 // when the TryCatch is destroyed.
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000013275 exception = Local<Value>::New(isolate, try_catch.Exception());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013276 }
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000013277 args.GetIsolate()->ThrowException(exception);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013278 }
13279}
13280
13281
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013282static void ThrowInJSNoCatch(const v8::FunctionCallbackInfo<v8::Value>& args) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013283 CHECK(v8::Locker::IsLocked(CcTest::isolate()));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013284 ApiTestFuzzer::Fuzz();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013285 v8::Unlocker unlocker(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013286 const char* code = "throw 7;";
13287 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013288 v8::Locker nested_locker(CcTest::isolate());
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013289 v8::HandleScope scope(args.GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013290 v8::Handle<Value> value = CompileRun(code);
13291 CHECK(value.IsEmpty());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013292 args.GetReturnValue().Set(v8_str("foo"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013293 }
13294}
13295
13296
13297// These are locking tests that don't need to be run again
13298// as part of the locking aggregation tests.
13299TEST(NestedLockers) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000013300 v8::Isolate* isolate = CcTest::isolate();
13301 v8::Locker locker(isolate);
13302 CHECK(v8::Locker::IsLocked(isolate));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013303 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013304 v8::HandleScope scope(env->GetIsolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000013305 Local<v8::FunctionTemplate> fun_templ =
13306 v8::FunctionTemplate::New(isolate, ThrowInJS);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013307 Local<Function> fun = fun_templ->GetFunction();
13308 env->Global()->Set(v8_str("throw_in_js"), fun);
13309 Local<Script> script = v8_compile("(function () {"
13310 " try {"
13311 " throw_in_js();"
13312 " return 42;"
13313 " } catch (e) {"
13314 " return e * 13;"
13315 " }"
13316 "})();");
13317 CHECK_EQ(91, script->Run()->Int32Value());
13318}
13319
13320
13321// These are locking tests that don't need to be run again
13322// as part of the locking aggregation tests.
13323TEST(NestedLockersNoTryCatch) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013324 v8::Locker locker(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013325 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013326 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013327 Local<v8::FunctionTemplate> fun_templ =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000013328 v8::FunctionTemplate::New(env->GetIsolate(), ThrowInJSNoCatch);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013329 Local<Function> fun = fun_templ->GetFunction();
13330 env->Global()->Set(v8_str("throw_in_js"), fun);
13331 Local<Script> script = v8_compile("(function () {"
13332 " try {"
13333 " throw_in_js();"
13334 " return 42;"
13335 " } catch (e) {"
13336 " return e * 13;"
13337 " }"
13338 "})();");
13339 CHECK_EQ(91, script->Run()->Int32Value());
13340}
13341
13342
13343THREADED_TEST(RecursiveLocking) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013344 v8::Locker locker(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013345 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013346 v8::Locker locker2(CcTest::isolate());
13347 CHECK(v8::Locker::IsLocked(CcTest::isolate()));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013348 }
13349}
13350
13351
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013352static void UnlockForAMoment(const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013353 ApiTestFuzzer::Fuzz();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013354 v8::Unlocker unlocker(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013355}
13356
13357
13358THREADED_TEST(LockUnlockLock) {
13359 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013360 v8::Locker locker(CcTest::isolate());
13361 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013362 LocalContext env;
13363 Local<v8::FunctionTemplate> fun_templ =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000013364 v8::FunctionTemplate::New(CcTest::isolate(), UnlockForAMoment);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013365 Local<Function> fun = fun_templ->GetFunction();
13366 env->Global()->Set(v8_str("unlock_for_a_moment"), fun);
13367 Local<Script> script = v8_compile("(function () {"
13368 " unlock_for_a_moment();"
13369 " return 42;"
13370 "})();");
13371 CHECK_EQ(42, script->Run()->Int32Value());
13372 }
13373 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013374 v8::Locker locker(CcTest::isolate());
13375 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013376 LocalContext env;
13377 Local<v8::FunctionTemplate> fun_templ =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000013378 v8::FunctionTemplate::New(CcTest::isolate(), UnlockForAMoment);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013379 Local<Function> fun = fun_templ->GetFunction();
13380 env->Global()->Set(v8_str("unlock_for_a_moment"), fun);
13381 Local<Script> script = v8_compile("(function () {"
13382 " unlock_for_a_moment();"
13383 " return 42;"
13384 "})();");
13385 CHECK_EQ(42, script->Run()->Int32Value());
13386 }
13387}
13388
13389
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000013390static int GetGlobalObjectsCount() {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013391 CcTest::heap()->EnsureHeapIsIterable();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013392 int count = 0;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013393 i::HeapIterator it(CcTest::heap());
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000013394 for (i::HeapObject* object = it.next(); object != NULL; object = it.next())
13395 if (object->IsJSGlobalObject()) count++;
13396 return count;
13397}
13398
13399
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000013400static void CheckSurvivingGlobalObjectsCount(int expected) {
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +000013401 // We need to collect all garbage twice to be sure that everything
13402 // has been collected. This is because inline caches are cleared in
13403 // the first garbage collection but some of the maps have already
13404 // been marked at that point. Therefore some of the maps are not
13405 // collected until the second garbage collection.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013406 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
13407 CcTest::heap()->CollectAllGarbage(i::Heap::kMakeHeapIterableMask);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000013408 int count = GetGlobalObjectsCount();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013409#ifdef DEBUG
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013410 if (count != expected) CcTest::heap()->TracePathToGlobal();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013411#endif
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000013412 CHECK_EQ(expected, count);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013413}
13414
13415
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013416TEST(DontLeakGlobalObjects) {
13417 // Regression test for issues 1139850 and 1174891.
13418
kasperl@chromium.orgb9123622008-09-17 14:05:56 +000013419 v8::V8::Initialize();
ager@chromium.org9258b6b2008-09-11 09:11:10 +000013420
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013421 for (int i = 0; i < 5; i++) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013422 { v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013423 LocalContext context;
13424 }
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +000013425 v8::V8::ContextDisposedNotification();
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000013426 CheckSurvivingGlobalObjectsCount(0);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013427
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013428 { v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013429 LocalContext context;
13430 v8_compile("Date")->Run();
13431 }
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +000013432 v8::V8::ContextDisposedNotification();
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000013433 CheckSurvivingGlobalObjectsCount(0);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013434
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013435 { v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013436 LocalContext context;
13437 v8_compile("/aaa/")->Run();
13438 }
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +000013439 v8::V8::ContextDisposedNotification();
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000013440 CheckSurvivingGlobalObjectsCount(0);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013441
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013442 { v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013443 const char* extension_list[] = { "v8/gc" };
13444 v8::ExtensionConfiguration extensions(1, extension_list);
13445 LocalContext context(&extensions);
13446 v8_compile("gc();")->Run();
13447 }
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +000013448 v8::V8::ContextDisposedNotification();
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000013449 CheckSurvivingGlobalObjectsCount(0);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013450 }
13451}
13452
dslomov@chromium.org639bac02013-09-09 11:58:54 +000013453
13454TEST(CopyablePersistent) {
13455 LocalContext context;
13456 v8::Isolate* isolate = context->GetIsolate();
13457 i::GlobalHandles* globals =
13458 reinterpret_cast<i::Isolate*>(isolate)->global_handles();
13459 int initial_handles = globals->global_handles_count();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013460 typedef v8::Persistent<v8::Object, v8::CopyablePersistentTraits<v8::Object> >
13461 CopyableObject;
dslomov@chromium.org639bac02013-09-09 11:58:54 +000013462 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013463 CopyableObject handle1;
dslomov@chromium.org639bac02013-09-09 11:58:54 +000013464 {
13465 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000013466 handle1.Reset(isolate, v8::Object::New(isolate));
dslomov@chromium.org639bac02013-09-09 11:58:54 +000013467 }
13468 CHECK_EQ(initial_handles + 1, globals->global_handles_count());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013469 CopyableObject handle2;
dslomov@chromium.org639bac02013-09-09 11:58:54 +000013470 handle2 = handle1;
13471 CHECK(handle1 == handle2);
13472 CHECK_EQ(initial_handles + 2, globals->global_handles_count());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013473 CopyableObject handle3(handle2);
dslomov@chromium.org639bac02013-09-09 11:58:54 +000013474 CHECK(handle1 == handle3);
13475 CHECK_EQ(initial_handles + 3, globals->global_handles_count());
13476 }
13477 // Verify autodispose
hpayer@chromium.orgc5d49712013-09-11 08:25:48 +000013478 CHECK_EQ(initial_handles, globals->global_handles_count());
dslomov@chromium.org639bac02013-09-09 11:58:54 +000013479}
13480
13481
13482static void WeakApiCallback(
13483 const v8::WeakCallbackData<v8::Object, Persistent<v8::Object> >& data) {
13484 Local<Value> value = data.GetValue()->Get(v8_str("key"));
13485 CHECK_EQ(231, static_cast<int32_t>(Local<v8::Integer>::Cast(value)->Value()));
13486 data.GetParameter()->Reset();
13487 delete data.GetParameter();
13488}
13489
13490
13491TEST(WeakCallbackApi) {
13492 LocalContext context;
13493 v8::Isolate* isolate = context->GetIsolate();
13494 i::GlobalHandles* globals =
13495 reinterpret_cast<i::Isolate*>(isolate)->global_handles();
13496 int initial_handles = globals->global_handles_count();
13497 {
13498 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000013499 v8::Local<v8::Object> obj = v8::Object::New(isolate);
13500 obj->Set(v8_str("key"), v8::Integer::New(isolate, 231));
dslomov@chromium.org639bac02013-09-09 11:58:54 +000013501 v8::Persistent<v8::Object>* handle =
13502 new v8::Persistent<v8::Object>(isolate, obj);
13503 handle->SetWeak<v8::Object, v8::Persistent<v8::Object> >(handle,
13504 WeakApiCallback);
13505 }
13506 reinterpret_cast<i::Isolate*>(isolate)->heap()->
13507 CollectAllGarbage(i::Heap::kNoGCFlags);
13508 // Verify disposed.
13509 CHECK_EQ(initial_handles, globals->global_handles_count());
13510}
13511
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013512
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000013513v8::Persistent<v8::Object> some_object;
13514v8::Persistent<v8::Object> bad_handle;
13515
machenbach@chromium.orgddf38112013-12-04 09:42:52 +000013516void NewPersistentHandleCallback(
13517 const v8::WeakCallbackData<v8::Object, v8::Persistent<v8::Object> >& data) {
13518 v8::HandleScope scope(data.GetIsolate());
13519 bad_handle.Reset(data.GetIsolate(), some_object);
13520 data.GetParameter()->Reset();
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000013521}
13522
13523
13524THREADED_TEST(NewPersistentHandleFromWeakCallback) {
13525 LocalContext context;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000013526 v8::Isolate* isolate = context->GetIsolate();
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000013527
13528 v8::Persistent<v8::Object> handle1, handle2;
13529 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013530 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000013531 some_object.Reset(isolate, v8::Object::New(isolate));
13532 handle1.Reset(isolate, v8::Object::New(isolate));
13533 handle2.Reset(isolate, v8::Object::New(isolate));
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000013534 }
13535 // Note: order is implementation dependent alas: currently
13536 // global handle nodes are processed by PostGarbageCollectionProcessing
13537 // in reverse allocation order, so if second allocated handle is deleted,
13538 // weak callback of the first handle would be able to 'reallocate' it.
machenbach@chromium.orgddf38112013-12-04 09:42:52 +000013539 handle1.SetWeak(&handle1, NewPersistentHandleCallback);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000013540 handle2.Reset();
machenbach@chromium.orgddf38112013-12-04 09:42:52 +000013541 CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000013542}
13543
13544
13545v8::Persistent<v8::Object> to_be_disposed;
13546
machenbach@chromium.orgddf38112013-12-04 09:42:52 +000013547void DisposeAndForceGcCallback(
13548 const v8::WeakCallbackData<v8::Object, v8::Persistent<v8::Object> >& data) {
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000013549 to_be_disposed.Reset();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013550 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
machenbach@chromium.orgddf38112013-12-04 09:42:52 +000013551 data.GetParameter()->Reset();
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000013552}
13553
13554
13555THREADED_TEST(DoNotUseDeletedNodesInSecondLevelGc) {
13556 LocalContext context;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000013557 v8::Isolate* isolate = context->GetIsolate();
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000013558
13559 v8::Persistent<v8::Object> handle1, handle2;
13560 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013561 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000013562 handle1.Reset(isolate, v8::Object::New(isolate));
13563 handle2.Reset(isolate, v8::Object::New(isolate));
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000013564 }
machenbach@chromium.orgddf38112013-12-04 09:42:52 +000013565 handle1.SetWeak(&handle1, DisposeAndForceGcCallback);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000013566 to_be_disposed.Reset(isolate, handle2);
machenbach@chromium.orgddf38112013-12-04 09:42:52 +000013567 CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000013568}
13569
machenbach@chromium.orgddf38112013-12-04 09:42:52 +000013570void DisposingCallback(
13571 const v8::WeakCallbackData<v8::Object, v8::Persistent<v8::Object> >& data) {
13572 data.GetParameter()->Reset();
ager@chromium.orgc4c92722009-11-18 14:12:51 +000013573}
13574
machenbach@chromium.orgddf38112013-12-04 09:42:52 +000013575void HandleCreatingCallback(
13576 const v8::WeakCallbackData<v8::Object, v8::Persistent<v8::Object> >& data) {
13577 v8::HandleScope scope(data.GetIsolate());
ulan@chromium.org0f13e742014-01-03 15:51:11 +000013578 v8::Persistent<v8::Object>(data.GetIsolate(),
13579 v8::Object::New(data.GetIsolate()));
machenbach@chromium.orgddf38112013-12-04 09:42:52 +000013580 data.GetParameter()->Reset();
ager@chromium.orgc4c92722009-11-18 14:12:51 +000013581}
13582
13583
13584THREADED_TEST(NoGlobalHandlesOrphaningDueToWeakCallback) {
13585 LocalContext context;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000013586 v8::Isolate* isolate = context->GetIsolate();
ager@chromium.orgc4c92722009-11-18 14:12:51 +000013587
13588 v8::Persistent<v8::Object> handle1, handle2, handle3;
13589 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013590 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000013591 handle3.Reset(isolate, v8::Object::New(isolate));
13592 handle2.Reset(isolate, v8::Object::New(isolate));
13593 handle1.Reset(isolate, v8::Object::New(isolate));
ager@chromium.orgc4c92722009-11-18 14:12:51 +000013594 }
machenbach@chromium.orgddf38112013-12-04 09:42:52 +000013595 handle2.SetWeak(&handle2, DisposingCallback);
13596 handle3.SetWeak(&handle3, HandleCreatingCallback);
13597 CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
ager@chromium.orgc4c92722009-11-18 14:12:51 +000013598}
13599
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000013600
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013601THREADED_TEST(CheckForCrossContextObjectLiterals) {
kasperl@chromium.orgb9123622008-09-17 14:05:56 +000013602 v8::V8::Initialize();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013603
13604 const int nof = 2;
13605 const char* sources[nof] = {
13606 "try { [ 2, 3, 4 ].forEach(5); } catch(e) { e.toString(); }",
13607 "Object()"
13608 };
13609
13610 for (int i = 0; i < nof; i++) {
13611 const char* source = sources[i];
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013612 { v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013613 LocalContext context;
13614 CompileRun(source);
13615 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013616 { v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013617 LocalContext context;
13618 CompileRun(source);
13619 }
13620 }
13621}
13622
13623
ulan@chromium.org57ff8812013-05-10 08:16:55 +000013624static v8::Handle<Value> NestedScope(v8::Local<Context> env) {
machenbach@chromium.orgafbdadc2013-12-09 16:12:18 +000013625 v8::EscapableHandleScope inner(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013626 env->Enter();
machenbach@chromium.orgafbdadc2013-12-09 16:12:18 +000013627 v8::Local<Value> three = v8_num(3);
13628 v8::Local<Value> value = inner.Escape(three);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013629 env->Exit();
13630 return value;
13631}
13632
13633
13634THREADED_TEST(NestedHandleScopeAndContexts) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013635 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000013636 v8::HandleScope outer(isolate);
13637 v8::Local<Context> env = Context::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013638 env->Enter();
13639 v8::Handle<Value> value = NestedScope(env);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000013640 v8::Handle<String> str(value->ToString());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000013641 CHECK(!str.IsEmpty());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013642 env->Exit();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013643}
13644
13645
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013646static bool MatchPointers(void* key1, void* key2) {
13647 return key1 == key2;
13648}
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013649
13650
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013651struct SymbolInfo {
13652 size_t id;
13653 size_t size;
13654 std::string name;
13655};
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013656
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013657
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013658class SetFunctionEntryHookTest {
13659 public:
13660 SetFunctionEntryHookTest() {
13661 CHECK(instance_ == NULL);
13662 instance_ = this;
13663 }
13664 ~SetFunctionEntryHookTest() {
13665 CHECK(instance_ == this);
13666 instance_ = NULL;
13667 }
13668 void Reset() {
13669 symbols_.clear();
13670 symbol_locations_.clear();
13671 invocations_.clear();
13672 }
13673 void RunTest();
13674 void OnJitEvent(const v8::JitCodeEvent* event);
13675 static void JitEvent(const v8::JitCodeEvent* event) {
13676 CHECK(instance_ != NULL);
13677 instance_->OnJitEvent(event);
13678 }
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013679
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013680 void OnEntryHook(uintptr_t function,
13681 uintptr_t return_addr_location);
13682 static void EntryHook(uintptr_t function,
13683 uintptr_t return_addr_location) {
13684 CHECK(instance_ != NULL);
13685 instance_->OnEntryHook(function, return_addr_location);
13686 }
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000013687
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013688 static void RuntimeCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
13689 CHECK(instance_ != NULL);
13690 args.GetReturnValue().Set(v8_num(42));
13691 }
13692 void RunLoopInNewEnv(v8::Isolate* isolate);
13693
13694 // Records addr as location of symbol.
13695 void InsertSymbolAt(i::Address addr, SymbolInfo* symbol);
13696
13697 // Finds the symbol containing addr
13698 SymbolInfo* FindSymbolForAddr(i::Address addr);
13699 // Returns the number of invocations where the caller name contains
13700 // \p caller_name and the function name contains \p function_name.
13701 int CountInvocations(const char* caller_name,
13702 const char* function_name);
13703
13704 i::Handle<i::JSFunction> foo_func_;
13705 i::Handle<i::JSFunction> bar_func_;
13706
13707 typedef std::map<size_t, SymbolInfo> SymbolMap;
13708 typedef std::map<i::Address, SymbolInfo*> SymbolLocationMap;
13709 typedef std::map<std::pair<SymbolInfo*, SymbolInfo*>, int> InvocationMap;
13710 SymbolMap symbols_;
13711 SymbolLocationMap symbol_locations_;
13712 InvocationMap invocations_;
13713
13714 static SetFunctionEntryHookTest* instance_;
13715};
13716SetFunctionEntryHookTest* SetFunctionEntryHookTest::instance_ = NULL;
13717
13718
13719// Returns true if addr is in the range [start, start+len).
13720static bool Overlaps(i::Address start, size_t len, i::Address addr) {
13721 if (start <= addr && start + len > addr)
13722 return true;
13723
13724 return false;
13725}
13726
13727void SetFunctionEntryHookTest::InsertSymbolAt(i::Address addr,
13728 SymbolInfo* symbol) {
13729 // Insert the symbol at the new location.
13730 SymbolLocationMap::iterator it =
13731 symbol_locations_.insert(std::make_pair(addr, symbol)).first;
13732 // Now erase symbols to the left and right that overlap this one.
13733 while (it != symbol_locations_.begin()) {
13734 SymbolLocationMap::iterator left = it;
13735 --left;
13736 if (!Overlaps(left->first, left->second->size, addr))
13737 break;
13738 symbol_locations_.erase(left);
13739 }
13740
13741 // Now erase symbols to the left and right that overlap this one.
13742 while (true) {
13743 SymbolLocationMap::iterator right = it;
13744 ++right;
13745 if (right == symbol_locations_.end())
13746 break;
13747 if (!Overlaps(addr, symbol->size, right->first))
13748 break;
13749 symbol_locations_.erase(right);
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000013750 }
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013751}
13752
13753
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013754void SetFunctionEntryHookTest::OnJitEvent(const v8::JitCodeEvent* event) {
13755 switch (event->type) {
13756 case v8::JitCodeEvent::CODE_ADDED: {
13757 CHECK(event->code_start != NULL);
13758 CHECK_NE(0, static_cast<int>(event->code_len));
13759 CHECK(event->name.str != NULL);
13760 size_t symbol_id = symbols_.size();
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013761
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013762 // Record the new symbol.
13763 SymbolInfo& info = symbols_[symbol_id];
13764 info.id = symbol_id;
13765 info.size = event->code_len;
13766 info.name.assign(event->name.str, event->name.str + event->name.len);
13767
13768 // And record it's location.
13769 InsertSymbolAt(reinterpret_cast<i::Address>(event->code_start), &info);
13770 }
13771 break;
13772
13773 case v8::JitCodeEvent::CODE_MOVED: {
13774 // We would like to never see code move that we haven't seen before,
13775 // but the code creation event does not happen until the line endings
13776 // have been calculated (this is so that we can report the line in the
13777 // script at which the function source is found, see
13778 // Compiler::RecordFunctionCompilation) and the line endings
13779 // calculations can cause a GC, which can move the newly created code
13780 // before its existence can be logged.
13781 SymbolLocationMap::iterator it(
13782 symbol_locations_.find(
13783 reinterpret_cast<i::Address>(event->code_start)));
13784 if (it != symbol_locations_.end()) {
13785 // Found a symbol at this location, move it.
13786 SymbolInfo* info = it->second;
13787 symbol_locations_.erase(it);
13788 InsertSymbolAt(reinterpret_cast<i::Address>(event->new_code_start),
13789 info);
13790 }
13791 }
13792 default:
13793 break;
13794 }
13795}
13796
13797void SetFunctionEntryHookTest::OnEntryHook(
13798 uintptr_t function, uintptr_t return_addr_location) {
13799 // Get the function's code object.
13800 i::Code* function_code = i::Code::GetCodeFromTargetAddress(
13801 reinterpret_cast<i::Address>(function));
13802 CHECK(function_code != NULL);
13803
13804 // Then try and look up the caller's code object.
13805 i::Address caller = *reinterpret_cast<i::Address*>(return_addr_location);
13806
13807 // Count the invocation.
13808 SymbolInfo* caller_symbol = FindSymbolForAddr(caller);
13809 SymbolInfo* function_symbol =
13810 FindSymbolForAddr(reinterpret_cast<i::Address>(function));
13811 ++invocations_[std::make_pair(caller_symbol, function_symbol)];
13812
13813 if (!bar_func_.is_null() && function_code == bar_func_->code()) {
13814 // Check that we have a symbol for the "bar" function at the right location.
13815 SymbolLocationMap::iterator it(
13816 symbol_locations_.find(function_code->instruction_start()));
13817 CHECK(it != symbol_locations_.end());
13818 }
13819
13820 if (!foo_func_.is_null() && function_code == foo_func_->code()) {
13821 // Check that we have a symbol for "foo" at the right location.
13822 SymbolLocationMap::iterator it(
13823 symbol_locations_.find(function_code->instruction_start()));
13824 CHECK(it != symbol_locations_.end());
13825 }
13826}
13827
13828
13829SymbolInfo* SetFunctionEntryHookTest::FindSymbolForAddr(i::Address addr) {
13830 SymbolLocationMap::iterator it(symbol_locations_.lower_bound(addr));
13831 // Do we have a direct hit on a symbol?
13832 if (it != symbol_locations_.end()) {
13833 if (it->first == addr)
13834 return it->second;
13835 }
13836
13837 // If not a direct hit, it'll have to be the previous symbol.
13838 if (it == symbol_locations_.begin())
13839 return NULL;
13840
13841 --it;
13842 size_t offs = addr - it->first;
13843 if (offs < it->second->size)
13844 return it->second;
13845
13846 return NULL;
13847}
13848
13849
13850int SetFunctionEntryHookTest::CountInvocations(
13851 const char* caller_name, const char* function_name) {
13852 InvocationMap::iterator it(invocations_.begin());
13853 int invocations = 0;
13854 for (; it != invocations_.end(); ++it) {
13855 SymbolInfo* caller = it->first.first;
13856 SymbolInfo* function = it->first.second;
13857
13858 // Filter out non-matching functions.
13859 if (function_name != NULL) {
13860 if (function->name.find(function_name) == std::string::npos)
13861 continue;
13862 }
13863
13864 // Filter out non-matching callers.
13865 if (caller_name != NULL) {
13866 if (caller == NULL)
13867 continue;
13868 if (caller->name.find(caller_name) == std::string::npos)
13869 continue;
13870 }
13871
13872 // It matches add the invocation count to the tally.
13873 invocations += it->second;
13874 }
13875
13876 return invocations;
13877}
13878
13879
13880void SetFunctionEntryHookTest::RunLoopInNewEnv(v8::Isolate* isolate) {
ulan@chromium.org57ff8812013-05-10 08:16:55 +000013881 v8::HandleScope outer(isolate);
13882 v8::Local<Context> env = Context::New(isolate);
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013883 env->Enter();
13884
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000013885 Local<ObjectTemplate> t = ObjectTemplate::New(isolate);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000013886 t->Set(v8_str("asdf"), v8::FunctionTemplate::New(isolate, RuntimeCallback));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013887 env->Global()->Set(v8_str("obj"), t->NewInstance());
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013888
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013889 const char* script =
13890 "function bar() {\n"
13891 " var sum = 0;\n"
13892 " for (i = 0; i < 100; ++i)\n"
13893 " sum = foo(i);\n"
13894 " return sum;\n"
13895 "}\n"
13896 "function foo(i) { return i * i; }\n"
13897 "// Invoke on the runtime function.\n"
13898 "obj.asdf()";
13899 CompileRun(script);
13900 bar_func_ = i::Handle<i::JSFunction>::cast(
13901 v8::Utils::OpenHandle(*env->Global()->Get(v8_str("bar"))));
13902 ASSERT(!bar_func_.is_null());
13903
13904 foo_func_ =
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013905 i::Handle<i::JSFunction>::cast(
13906 v8::Utils::OpenHandle(*env->Global()->Get(v8_str("foo"))));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013907 ASSERT(!foo_func_.is_null());
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013908
13909 v8::Handle<v8::Value> value = CompileRun("bar();");
13910 CHECK(value->IsNumber());
13911 CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value());
13912
13913 // Test the optimized codegen path.
13914 value = CompileRun("%OptimizeFunctionOnNextCall(foo);"
13915 "bar();");
13916 CHECK(value->IsNumber());
13917 CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value());
13918
13919 env->Exit();
13920}
13921
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000013922
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013923void SetFunctionEntryHookTest::RunTest() {
13924 // Work in a new isolate throughout.
13925 v8::Isolate* isolate = v8::Isolate::New();
13926
13927 // Test setting the entry hook on the new isolate.
13928 CHECK(v8::V8::SetFunctionEntryHook(isolate, EntryHook));
13929
13930 // Replacing the hook, once set should fail.
13931 CHECK_EQ(false, v8::V8::SetFunctionEntryHook(isolate, EntryHook));
13932
13933 {
13934 v8::Isolate::Scope scope(isolate);
13935
13936 v8::V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, JitEvent);
13937
13938 RunLoopInNewEnv(isolate);
13939
13940 // Check the exepected invocation counts.
13941 CHECK_EQ(2, CountInvocations(NULL, "bar"));
13942 CHECK_EQ(200, CountInvocations("bar", "foo"));
13943 CHECK_EQ(200, CountInvocations(NULL, "foo"));
13944
13945 // Verify that we have an entry hook on some specific stubs.
13946 CHECK_NE(0, CountInvocations(NULL, "CEntryStub"));
13947 CHECK_NE(0, CountInvocations(NULL, "JSEntryStub"));
13948 CHECK_NE(0, CountInvocations(NULL, "JSEntryTrampoline"));
13949 }
13950 isolate->Dispose();
13951
13952 Reset();
13953
13954 // Make sure a second isolate is unaffected by the previous entry hook.
13955 isolate = v8::Isolate::New();
13956 {
13957 v8::Isolate::Scope scope(isolate);
13958
13959 // Reset the entry count to zero and set the entry hook.
13960 RunLoopInNewEnv(isolate);
13961
13962 // We should record no invocations in this isolate.
13963 CHECK_EQ(0, static_cast<int>(invocations_.size()));
13964 }
13965 // Since the isolate has been used, we shouldn't be able to set an entry
13966 // hook anymore.
13967 CHECK_EQ(false, v8::V8::SetFunctionEntryHook(isolate, EntryHook));
13968
13969 isolate->Dispose();
13970}
13971
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013972
13973TEST(SetFunctionEntryHook) {
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000013974 // FunctionEntryHook does not work well with experimental natives.
13975 // Experimental natives are compiled during snapshot deserialization.
13976 // This test breaks because InstallGetter (function from snapshot that
13977 // only gets called from experimental natives) is compiled with entry hooks.
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013978 i::FLAG_allow_natives_syntax = true;
yangguo@chromium.orgfb377212012-11-16 14:43:43 +000013979 i::FLAG_use_inlining = false;
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013980
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013981 SetFunctionEntryHookTest test;
13982 test.RunTest();
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013983}
13984
13985
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000013986static i::HashMap* code_map = NULL;
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +000013987static i::HashMap* jitcode_line_info = NULL;
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000013988static int saw_bar = 0;
13989static int move_events = 0;
13990
13991
13992static bool FunctionNameIs(const char* expected,
13993 const v8::JitCodeEvent* event) {
13994 // Log lines for functions are of the general form:
13995 // "LazyCompile:<type><function_name>", where the type is one of
13996 // "*", "~" or "".
13997 static const char kPreamble[] = "LazyCompile:";
13998 static size_t kPreambleLen = sizeof(kPreamble) - 1;
13999
14000 if (event->name.len < sizeof(kPreamble) - 1 ||
14001 strncmp(kPreamble, event->name.str, kPreambleLen) != 0) {
14002 return false;
14003 }
14004
14005 const char* tail = event->name.str + kPreambleLen;
14006 size_t tail_len = event->name.len - kPreambleLen;
14007 size_t expected_len = strlen(expected);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000014008 if (tail_len > 1 && (*tail == '*' || *tail == '~')) {
14009 --tail_len;
14010 ++tail;
14011 }
14012
14013 // Check for tails like 'bar :1'.
14014 if (tail_len > expected_len + 2 &&
14015 tail[expected_len] == ' ' &&
14016 tail[expected_len + 1] == ':' &&
14017 tail[expected_len + 2] &&
14018 !strncmp(tail, expected, expected_len)) {
14019 return true;
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014020 }
14021
14022 if (tail_len != expected_len)
14023 return false;
14024
14025 return strncmp(tail, expected, expected_len) == 0;
14026}
14027
14028
14029static void event_handler(const v8::JitCodeEvent* event) {
14030 CHECK(event != NULL);
14031 CHECK(code_map != NULL);
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +000014032 CHECK(jitcode_line_info != NULL);
14033
14034 class DummyJitCodeLineInfo {
14035 };
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014036
14037 switch (event->type) {
14038 case v8::JitCodeEvent::CODE_ADDED: {
14039 CHECK(event->code_start != NULL);
14040 CHECK_NE(0, static_cast<int>(event->code_len));
14041 CHECK(event->name.str != NULL);
14042 i::HashMap::Entry* entry =
14043 code_map->Lookup(event->code_start,
14044 i::ComputePointerHash(event->code_start),
14045 true);
14046 entry->value = reinterpret_cast<void*>(event->code_len);
14047
14048 if (FunctionNameIs("bar", event)) {
14049 ++saw_bar;
14050 }
14051 }
14052 break;
14053
14054 case v8::JitCodeEvent::CODE_MOVED: {
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014055 uint32_t hash = i::ComputePointerHash(event->code_start);
jkummerow@chromium.org78502a92012-09-06 13:50:42 +000014056 // We would like to never see code move that we haven't seen before,
14057 // but the code creation event does not happen until the line endings
14058 // have been calculated (this is so that we can report the line in the
14059 // script at which the function source is found, see
14060 // Compiler::RecordFunctionCompilation) and the line endings
14061 // calculations can cause a GC, which can move the newly created code
14062 // before its existence can be logged.
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014063 i::HashMap::Entry* entry =
14064 code_map->Lookup(event->code_start, hash, false);
jkummerow@chromium.org78502a92012-09-06 13:50:42 +000014065 if (entry != NULL) {
14066 ++move_events;
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014067
jkummerow@chromium.org78502a92012-09-06 13:50:42 +000014068 CHECK_EQ(reinterpret_cast<void*>(event->code_len), entry->value);
14069 code_map->Remove(event->code_start, hash);
14070
14071 entry = code_map->Lookup(event->new_code_start,
14072 i::ComputePointerHash(event->new_code_start),
14073 true);
14074 CHECK(entry != NULL);
14075 entry->value = reinterpret_cast<void*>(event->code_len);
14076 }
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014077 }
14078 break;
14079
14080 case v8::JitCodeEvent::CODE_REMOVED:
14081 // Object/code removal events are currently not dispatched from the GC.
14082 CHECK(false);
14083 break;
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +000014084
14085 // For CODE_START_LINE_INFO_RECORDING event, we will create one
14086 // DummyJitCodeLineInfo data structure pointed by event->user_dat. We
14087 // record it in jitcode_line_info.
14088 case v8::JitCodeEvent::CODE_START_LINE_INFO_RECORDING: {
14089 DummyJitCodeLineInfo* line_info = new DummyJitCodeLineInfo();
14090 v8::JitCodeEvent* temp_event = const_cast<v8::JitCodeEvent*>(event);
14091 temp_event->user_data = line_info;
14092 i::HashMap::Entry* entry =
14093 jitcode_line_info->Lookup(line_info,
14094 i::ComputePointerHash(line_info),
14095 true);
14096 entry->value = reinterpret_cast<void*>(line_info);
14097 }
14098 break;
14099 // For these two events, we will check whether the event->user_data
14100 // data structure is created before during CODE_START_LINE_INFO_RECORDING
14101 // event. And delete it in CODE_END_LINE_INFO_RECORDING event handling.
14102 case v8::JitCodeEvent::CODE_END_LINE_INFO_RECORDING: {
14103 CHECK(event->user_data != NULL);
14104 uint32_t hash = i::ComputePointerHash(event->user_data);
14105 i::HashMap::Entry* entry =
14106 jitcode_line_info->Lookup(event->user_data, hash, false);
14107 CHECK(entry != NULL);
14108 delete reinterpret_cast<DummyJitCodeLineInfo*>(event->user_data);
14109 }
14110 break;
14111
14112 case v8::JitCodeEvent::CODE_ADD_LINE_POS_INFO: {
14113 CHECK(event->user_data != NULL);
14114 uint32_t hash = i::ComputePointerHash(event->user_data);
14115 i::HashMap::Entry* entry =
14116 jitcode_line_info->Lookup(event->user_data, hash, false);
14117 CHECK(entry != NULL);
14118 }
14119 break;
14120
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014121 default:
14122 // Impossible event.
14123 CHECK(false);
14124 break;
14125 }
14126}
14127
14128
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014129UNINITIALIZED_TEST(SetJitCodeEventHandler) {
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +000014130 i::FLAG_stress_compaction = true;
danno@chromium.orgf005df62013-04-30 16:36:45 +000014131 i::FLAG_incremental_marking = false;
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014132 const char* script =
14133 "function bar() {"
14134 " var sum = 0;"
14135 " for (i = 0; i < 100; ++i)"
14136 " sum = foo(i);"
14137 " return sum;"
14138 "}"
14139 "function foo(i) { return i * i; };"
14140 "bar();";
14141
14142 // Run this test in a new isolate to make sure we don't
14143 // have remnants of state from other code.
14144 v8::Isolate* isolate = v8::Isolate::New();
14145 isolate->Enter();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014146 i::Heap* heap = reinterpret_cast<i::Isolate*>(isolate)->heap();
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014147
14148 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014149 v8::HandleScope scope(isolate);
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014150 i::HashMap code(MatchPointers);
14151 code_map = &code;
14152
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +000014153 i::HashMap lineinfo(MatchPointers);
14154 jitcode_line_info = &lineinfo;
14155
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014156 saw_bar = 0;
14157 move_events = 0;
14158
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014159 V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, event_handler);
14160
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014161 // Generate new code objects sparsely distributed across several
14162 // different fragmented code-space pages.
14163 const int kIterations = 10;
14164 for (int i = 0; i < kIterations; ++i) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014165 LocalContext env(isolate);
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +000014166 i::AlwaysAllocateScope always_allocate;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014167 SimulateFullSpace(heap->code_space());
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +000014168 CompileRun(script);
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014169
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +000014170 // Keep a strong reference to the code object in the handle scope.
14171 i::Handle<i::Code> bar_code(i::Handle<i::JSFunction>::cast(
14172 v8::Utils::OpenHandle(*env->Global()->Get(v8_str("bar"))))->code());
14173 i::Handle<i::Code> foo_code(i::Handle<i::JSFunction>::cast(
14174 v8::Utils::OpenHandle(*env->Global()->Get(v8_str("foo"))))->code());
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014175
14176 // Clear the compilation cache to get more wastage.
hpayer@chromium.orgc5d49712013-09-11 08:25:48 +000014177 reinterpret_cast<i::Isolate*>(isolate)->compilation_cache()->Clear();
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014178 }
14179
14180 // Force code movement.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014181 heap->CollectAllAvailableGarbage("TestSetJitCodeEventHandler");
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014182
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +000014183 V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
14184
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014185 CHECK_LE(kIterations, saw_bar);
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +000014186 CHECK_LT(0, move_events);
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014187
14188 code_map = NULL;
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +000014189 jitcode_line_info = NULL;
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014190 }
14191
14192 isolate->Exit();
14193 isolate->Dispose();
14194
14195 // Do this in a new isolate.
14196 isolate = v8::Isolate::New();
14197 isolate->Enter();
14198
14199 // Verify that we get callbacks for existing code objects when we
14200 // request enumeration of existing code.
14201 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014202 v8::HandleScope scope(isolate);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014203 LocalContext env(isolate);
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014204 CompileRun(script);
14205
14206 // Now get code through initial iteration.
14207 i::HashMap code(MatchPointers);
14208 code_map = &code;
14209
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +000014210 i::HashMap lineinfo(MatchPointers);
14211 jitcode_line_info = &lineinfo;
14212
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014213 V8::SetJitCodeEventHandler(v8::kJitCodeEventEnumExisting, event_handler);
14214 V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
14215
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +000014216 jitcode_line_info = NULL;
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014217 // We expect that we got some events. Note that if we could get code removal
14218 // notifications, we could compare two collections, one created by listening
14219 // from the time of creation of an isolate, and the other by subscribing
14220 // with EnumExisting.
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +000014221 CHECK_LT(0, code.occupancy());
14222
14223 code_map = NULL;
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014224 }
14225
14226 isolate->Exit();
14227 isolate->Dispose();
14228}
14229
14230
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000014231THREADED_TEST(ExternalAllocatedMemory) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014232 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000014233 v8::HandleScope outer(isolate);
14234 v8::Local<Context> env(Context::New(isolate));
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000014235 CHECK(!env.IsEmpty());
machenbach@chromium.org7ff76072013-11-21 09:47:43 +000014236 const int64_t kSize = 1024*1024;
14237 int64_t baseline = isolate->AdjustAmountOfExternalAllocatedMemory(0);
14238 CHECK_EQ(baseline + kSize,
14239 isolate->AdjustAmountOfExternalAllocatedMemory(kSize));
danno@chromium.orgf005df62013-04-30 16:36:45 +000014240 CHECK_EQ(baseline,
machenbach@chromium.org7ff76072013-11-21 09:47:43 +000014241 isolate->AdjustAmountOfExternalAllocatedMemory(-kSize));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000014242}
14243
14244
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014245// Regression test for issue 54, object templates with internal fields
14246// but no accessors or interceptors did not get their internal field
14247// count set on instances.
14248THREADED_TEST(Regress54) {
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014249 LocalContext context;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000014250 v8::Isolate* isolate = context->GetIsolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014251 v8::HandleScope outer(isolate);
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014252 static v8::Persistent<v8::ObjectTemplate> templ;
14253 if (templ.IsEmpty()) {
machenbach@chromium.orgafbdadc2013-12-09 16:12:18 +000014254 v8::EscapableHandleScope inner(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000014255 v8::Local<v8::ObjectTemplate> local = v8::ObjectTemplate::New(isolate);
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014256 local->SetInternalFieldCount(1);
machenbach@chromium.orgafbdadc2013-12-09 16:12:18 +000014257 templ.Reset(isolate, inner.Escape(local));
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014258 }
rossberg@chromium.org79e79022013-06-03 15:43:46 +000014259 v8::Handle<v8::Object> result =
14260 v8::Local<v8::ObjectTemplate>::New(isolate, templ)->NewInstance();
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014261 CHECK_EQ(1, result->InternalFieldCount());
14262}
14263
14264
14265// If part of the threaded tests, this test makes ThreadingTest fail
14266// on mac.
14267TEST(CatchStackOverflow) {
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014268 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014269 v8::HandleScope scope(context->GetIsolate());
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014270 v8::TryCatch try_catch;
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000014271 v8::Handle<v8::Script> script = v8::Script::Compile(v8::String::NewFromUtf8(
14272 context->GetIsolate(),
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014273 "function f() {"
14274 " return f();"
14275 "}"
14276 ""
14277 "f();"));
14278 v8::Handle<v8::Value> result = script->Run();
14279 CHECK(result.IsEmpty());
14280}
14281
14282
kasperl@chromium.org7be3c992009-03-12 07:19:55 +000014283static void CheckTryCatchSourceInfo(v8::Handle<v8::Script> script,
14284 const char* resource_name,
14285 int line_offset) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014286 v8::HandleScope scope(CcTest::isolate());
kasperl@chromium.org7be3c992009-03-12 07:19:55 +000014287 v8::TryCatch try_catch;
14288 v8::Handle<v8::Value> result = script->Run();
14289 CHECK(result.IsEmpty());
14290 CHECK(try_catch.HasCaught());
14291 v8::Handle<v8::Message> message = try_catch.Message();
14292 CHECK(!message.IsEmpty());
14293 CHECK_EQ(10 + line_offset, message->GetLineNumber());
14294 CHECK_EQ(91, message->GetStartPosition());
14295 CHECK_EQ(92, message->GetEndPosition());
14296 CHECK_EQ(2, message->GetStartColumn());
14297 CHECK_EQ(3, message->GetEndColumn());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000014298 v8::String::Utf8Value line(message->GetSourceLine());
kasperl@chromium.org7be3c992009-03-12 07:19:55 +000014299 CHECK_EQ(" throw 'nirk';", *line);
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000014300 v8::String::Utf8Value name(message->GetScriptResourceName());
kasperl@chromium.org7be3c992009-03-12 07:19:55 +000014301 CHECK_EQ(resource_name, *name);
14302}
14303
14304
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014305THREADED_TEST(TryCatchSourceInfo) {
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014306 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014307 v8::HandleScope scope(context->GetIsolate());
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000014308 v8::Handle<v8::String> source = v8::String::NewFromUtf8(
14309 context->GetIsolate(),
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014310 "function Foo() {\n"
14311 " return Bar();\n"
14312 "}\n"
14313 "\n"
14314 "function Bar() {\n"
14315 " return Baz();\n"
14316 "}\n"
14317 "\n"
14318 "function Baz() {\n"
14319 " throw 'nirk';\n"
14320 "}\n"
14321 "\n"
14322 "Foo();\n");
kasperl@chromium.org7be3c992009-03-12 07:19:55 +000014323
14324 const char* resource_name;
14325 v8::Handle<v8::Script> script;
14326 resource_name = "test.js";
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000014327 script = v8::Script::Compile(
14328 source, v8::String::NewFromUtf8(context->GetIsolate(), resource_name));
kasperl@chromium.org7be3c992009-03-12 07:19:55 +000014329 CheckTryCatchSourceInfo(script, resource_name, 0);
14330
14331 resource_name = "test1.js";
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000014332 v8::ScriptOrigin origin1(
14333 v8::String::NewFromUtf8(context->GetIsolate(), resource_name));
kasperl@chromium.org7be3c992009-03-12 07:19:55 +000014334 script = v8::Script::Compile(source, &origin1);
14335 CheckTryCatchSourceInfo(script, resource_name, 0);
14336
14337 resource_name = "test2.js";
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000014338 v8::ScriptOrigin origin2(
14339 v8::String::NewFromUtf8(context->GetIsolate(), resource_name),
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014340 v8::Integer::New(context->GetIsolate(), 7));
kasperl@chromium.org7be3c992009-03-12 07:19:55 +000014341 script = v8::Script::Compile(source, &origin2);
14342 CheckTryCatchSourceInfo(script, resource_name, 7);
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014343}
kasperl@chromium.orgb9123622008-09-17 14:05:56 +000014344
14345
14346THREADED_TEST(CompilationCache) {
kasperl@chromium.orgb9123622008-09-17 14:05:56 +000014347 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014348 v8::HandleScope scope(context->GetIsolate());
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000014349 v8::Handle<v8::String> source0 =
14350 v8::String::NewFromUtf8(context->GetIsolate(), "1234");
14351 v8::Handle<v8::String> source1 =
14352 v8::String::NewFromUtf8(context->GetIsolate(), "1234");
14353 v8::Handle<v8::Script> script0 = v8::Script::Compile(
14354 source0, v8::String::NewFromUtf8(context->GetIsolate(), "test.js"));
14355 v8::Handle<v8::Script> script1 = v8::Script::Compile(
14356 source1, v8::String::NewFromUtf8(context->GetIsolate(), "test.js"));
kasperl@chromium.orgb9123622008-09-17 14:05:56 +000014357 v8::Handle<v8::Script> script2 =
14358 v8::Script::Compile(source0); // different origin
14359 CHECK_EQ(1234, script0->Run()->Int32Value());
14360 CHECK_EQ(1234, script1->Run()->Int32Value());
14361 CHECK_EQ(1234, script2->Run()->Int32Value());
14362}
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000014363
14364
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000014365static void FunctionNameCallback(
14366 const v8::FunctionCallbackInfo<v8::Value>& args) {
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000014367 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000014368 args.GetReturnValue().Set(v8_num(42));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000014369}
14370
14371
14372THREADED_TEST(CallbackFunctionName) {
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000014373 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000014374 v8::Isolate* isolate = context->GetIsolate();
14375 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000014376 Local<ObjectTemplate> t = ObjectTemplate::New(isolate);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000014377 t->Set(v8_str("asdf"),
14378 v8::FunctionTemplate::New(isolate, FunctionNameCallback));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000014379 context->Global()->Set(v8_str("obj"), t->NewInstance());
14380 v8::Handle<v8::Value> value = CompileRun("obj.asdf.name");
14381 CHECK(value->IsString());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000014382 v8::String::Utf8Value name(value);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000014383 CHECK_EQ("asdf", *name);
14384}
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014385
14386
14387THREADED_TEST(DateAccess) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014388 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014389 v8::HandleScope scope(context->GetIsolate());
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000014390 v8::Handle<v8::Value> date =
14391 v8::Date::New(context->GetIsolate(), 1224744689038.0);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014392 CHECK(date->IsDate());
danno@chromium.orgd3c42102013-08-01 16:58:23 +000014393 CHECK_EQ(1224744689038.0, date.As<v8::Date>()->ValueOf());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014394}
14395
14396
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014397void CheckProperties(v8::Isolate* isolate,
14398 v8::Handle<v8::Value> val,
14399 int elmc,
14400 const char* elmv[]) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000014401 v8::Handle<v8::Object> obj = val.As<v8::Object>();
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014402 v8::Handle<v8::Array> props = obj->GetPropertyNames();
14403 CHECK_EQ(elmc, props->Length());
14404 for (int i = 0; i < elmc; i++) {
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014405 v8::String::Utf8Value elm(props->Get(v8::Integer::New(isolate, i)));
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014406 CHECK_EQ(elmv[i], *elm);
14407 }
14408}
14409
14410
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014411void CheckOwnProperties(v8::Isolate* isolate,
14412 v8::Handle<v8::Value> val,
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000014413 int elmc,
14414 const char* elmv[]) {
14415 v8::Handle<v8::Object> obj = val.As<v8::Object>();
14416 v8::Handle<v8::Array> props = obj->GetOwnPropertyNames();
14417 CHECK_EQ(elmc, props->Length());
14418 for (int i = 0; i < elmc; i++) {
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014419 v8::String::Utf8Value elm(props->Get(v8::Integer::New(isolate, i)));
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000014420 CHECK_EQ(elmv[i], *elm);
14421 }
14422}
14423
14424
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014425THREADED_TEST(PropertyEnumeration) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014426 LocalContext context;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014427 v8::Isolate* isolate = context->GetIsolate();
14428 v8::HandleScope scope(isolate);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000014429 v8::Handle<v8::Value> obj = v8::Script::Compile(v8::String::NewFromUtf8(
14430 context->GetIsolate(),
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014431 "var result = [];"
14432 "result[0] = {};"
14433 "result[1] = {a: 1, b: 2};"
14434 "result[2] = [1, 2, 3];"
14435 "var proto = {x: 1, y: 2, z: 3};"
14436 "var x = { __proto__: proto, w: 0, z: 1 };"
14437 "result[3] = x;"
14438 "result;"))->Run();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000014439 v8::Handle<v8::Array> elms = obj.As<v8::Array>();
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014440 CHECK_EQ(4, elms->Length());
14441 int elmc0 = 0;
14442 const char** elmv0 = NULL;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014443 CheckProperties(
14444 isolate, elms->Get(v8::Integer::New(isolate, 0)), elmc0, elmv0);
14445 CheckOwnProperties(
14446 isolate, elms->Get(v8::Integer::New(isolate, 0)), elmc0, elmv0);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014447 int elmc1 = 2;
14448 const char* elmv1[] = {"a", "b"};
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014449 CheckProperties(
14450 isolate, elms->Get(v8::Integer::New(isolate, 1)), elmc1, elmv1);
14451 CheckOwnProperties(
14452 isolate, elms->Get(v8::Integer::New(isolate, 1)), elmc1, elmv1);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014453 int elmc2 = 3;
14454 const char* elmv2[] = {"0", "1", "2"};
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014455 CheckProperties(
14456 isolate, elms->Get(v8::Integer::New(isolate, 2)), elmc2, elmv2);
14457 CheckOwnProperties(
14458 isolate, elms->Get(v8::Integer::New(isolate, 2)), elmc2, elmv2);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014459 int elmc3 = 4;
14460 const char* elmv3[] = {"w", "z", "x", "y"};
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014461 CheckProperties(
14462 isolate, elms->Get(v8::Integer::New(isolate, 3)), elmc3, elmv3);
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000014463 int elmc4 = 2;
14464 const char* elmv4[] = {"w", "z"};
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014465 CheckOwnProperties(
14466 isolate, elms->Get(v8::Integer::New(isolate, 3)), elmc4, elmv4);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014467}
ager@chromium.org870a0b62008-11-04 11:43:05 +000014468
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000014469
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000014470THREADED_TEST(PropertyEnumeration2) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000014471 LocalContext context;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014472 v8::Isolate* isolate = context->GetIsolate();
14473 v8::HandleScope scope(isolate);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000014474 v8::Handle<v8::Value> obj = v8::Script::Compile(v8::String::NewFromUtf8(
14475 context->GetIsolate(),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000014476 "var result = [];"
14477 "result[0] = {};"
14478 "result[1] = {a: 1, b: 2};"
14479 "result[2] = [1, 2, 3];"
14480 "var proto = {x: 1, y: 2, z: 3};"
14481 "var x = { __proto__: proto, w: 0, z: 1 };"
14482 "result[3] = x;"
14483 "result;"))->Run();
14484 v8::Handle<v8::Array> elms = obj.As<v8::Array>();
14485 CHECK_EQ(4, elms->Length());
14486 int elmc0 = 0;
14487 const char** elmv0 = NULL;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014488 CheckProperties(isolate,
14489 elms->Get(v8::Integer::New(isolate, 0)), elmc0, elmv0);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000014490
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014491 v8::Handle<v8::Value> val = elms->Get(v8::Integer::New(isolate, 0));
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000014492 v8::Handle<v8::Array> props = val.As<v8::Object>()->GetPropertyNames();
14493 CHECK_EQ(0, props->Length());
14494 for (uint32_t i = 0; i < props->Length(); i++) {
14495 printf("p[%d]\n", i);
14496 }
14497}
ager@chromium.org870a0b62008-11-04 11:43:05 +000014498
ager@chromium.org870a0b62008-11-04 11:43:05 +000014499static bool NamedSetAccessBlocker(Local<v8::Object> obj,
14500 Local<Value> name,
14501 v8::AccessType type,
14502 Local<Value> data) {
14503 return type != v8::ACCESS_SET;
14504}
14505
14506
14507static bool IndexedSetAccessBlocker(Local<v8::Object> obj,
14508 uint32_t key,
14509 v8::AccessType type,
14510 Local<Value> data) {
14511 return type != v8::ACCESS_SET;
14512}
14513
14514
14515THREADED_TEST(DisableAccessChecksWhileConfiguring) {
ager@chromium.org870a0b62008-11-04 11:43:05 +000014516 LocalContext context;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000014517 v8::Isolate* isolate = context->GetIsolate();
14518 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000014519 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org870a0b62008-11-04 11:43:05 +000014520 templ->SetAccessCheckCallbacks(NamedSetAccessBlocker,
14521 IndexedSetAccessBlocker);
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000014522 templ->Set(v8_str("x"), v8::True(isolate));
ager@chromium.org870a0b62008-11-04 11:43:05 +000014523 Local<v8::Object> instance = templ->NewInstance();
14524 context->Global()->Set(v8_str("obj"), instance);
14525 Local<Value> value = CompileRun("obj.x");
14526 CHECK(value->BooleanValue());
14527}
ager@chromium.orga74f0da2008-12-03 16:05:52 +000014528
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000014529
ager@chromium.org32912102009-01-16 10:38:43 +000014530static bool NamedGetAccessBlocker(Local<v8::Object> obj,
14531 Local<Value> name,
14532 v8::AccessType type,
14533 Local<Value> data) {
14534 return false;
14535}
14536
14537
14538static bool IndexedGetAccessBlocker(Local<v8::Object> obj,
14539 uint32_t key,
14540 v8::AccessType type,
14541 Local<Value> data) {
14542 return false;
14543}
14544
14545
14546
14547THREADED_TEST(AccessChecksReenabledCorrectly) {
ager@chromium.org32912102009-01-16 10:38:43 +000014548 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000014549 v8::Isolate* isolate = context->GetIsolate();
14550 v8::HandleScope scope(isolate);
14551 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org32912102009-01-16 10:38:43 +000014552 templ->SetAccessCheckCallbacks(NamedGetAccessBlocker,
14553 IndexedGetAccessBlocker);
14554 templ->Set(v8_str("a"), v8_str("a"));
14555 // Add more than 8 (see kMaxFastProperties) properties
14556 // so that the constructor will force copying map.
14557 // Cannot sprintf, gcc complains unsafety.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000014558 char buf[4];
ager@chromium.org32912102009-01-16 10:38:43 +000014559 for (char i = '0'; i <= '9' ; i++) {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000014560 buf[0] = i;
ager@chromium.org32912102009-01-16 10:38:43 +000014561 for (char j = '0'; j <= '9'; j++) {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000014562 buf[1] = j;
ager@chromium.org32912102009-01-16 10:38:43 +000014563 for (char k = '0'; k <= '9'; k++) {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000014564 buf[2] = k;
14565 buf[3] = 0;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000014566 templ->Set(v8_str(buf), v8::Number::New(isolate, k));
ager@chromium.org32912102009-01-16 10:38:43 +000014567 }
14568 }
14569 }
14570
14571 Local<v8::Object> instance_1 = templ->NewInstance();
14572 context->Global()->Set(v8_str("obj_1"), instance_1);
14573
14574 Local<Value> value_1 = CompileRun("obj_1.a");
14575 CHECK(value_1->IsUndefined());
14576
14577 Local<v8::Object> instance_2 = templ->NewInstance();
14578 context->Global()->Set(v8_str("obj_2"), instance_2);
14579
14580 Local<Value> value_2 = CompileRun("obj_2.a");
14581 CHECK(value_2->IsUndefined());
14582}
ager@chromium.orga74f0da2008-12-03 16:05:52 +000014583
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000014584
ager@chromium.org8bb60582008-12-11 12:02:20 +000014585// This tests that access check information remains on the global
14586// object template when creating contexts.
14587THREADED_TEST(AccessControlRepeatedContextCreation) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014588 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000014589 v8::HandleScope handle_scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000014590 v8::Handle<v8::ObjectTemplate> global_template =
14591 v8::ObjectTemplate::New(isolate);
ager@chromium.org8bb60582008-12-11 12:02:20 +000014592 global_template->SetAccessCheckCallbacks(NamedSetAccessBlocker,
14593 IndexedSetAccessBlocker);
14594 i::Handle<i::ObjectTemplateInfo> internal_template =
14595 v8::Utils::OpenHandle(*global_template);
14596 CHECK(!internal_template->constructor()->IsUndefined());
14597 i::Handle<i::FunctionTemplateInfo> constructor(
14598 i::FunctionTemplateInfo::cast(internal_template->constructor()));
14599 CHECK(!constructor->access_check_info()->IsUndefined());
ulan@chromium.org57ff8812013-05-10 08:16:55 +000014600 v8::Local<Context> context0(Context::New(isolate, NULL, global_template));
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000014601 CHECK(!context0.IsEmpty());
ager@chromium.org8bb60582008-12-11 12:02:20 +000014602 CHECK(!constructor->access_check_info()->IsUndefined());
14603}
14604
14605
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000014606THREADED_TEST(TurnOnAccessCheck) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014607 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000014608 v8::HandleScope handle_scope(isolate);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000014609
14610 // Create an environment with access check to the global object disabled by
14611 // default.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000014612 v8::Handle<v8::ObjectTemplate> global_template =
14613 v8::ObjectTemplate::New(isolate);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000014614 global_template->SetAccessCheckCallbacks(NamedGetAccessBlocker,
14615 IndexedGetAccessBlocker,
14616 v8::Handle<v8::Value>(),
14617 false);
ulan@chromium.org57ff8812013-05-10 08:16:55 +000014618 v8::Local<Context> context = Context::New(isolate, NULL, global_template);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000014619 Context::Scope context_scope(context);
14620
14621 // Set up a property and a number of functions.
14622 context->Global()->Set(v8_str("a"), v8_num(1));
14623 CompileRun("function f1() {return a;}"
14624 "function f2() {return a;}"
14625 "function g1() {return h();}"
14626 "function g2() {return h();}"
14627 "function h() {return 1;}");
14628 Local<Function> f1 =
14629 Local<Function>::Cast(context->Global()->Get(v8_str("f1")));
14630 Local<Function> f2 =
14631 Local<Function>::Cast(context->Global()->Get(v8_str("f2")));
14632 Local<Function> g1 =
14633 Local<Function>::Cast(context->Global()->Get(v8_str("g1")));
14634 Local<Function> g2 =
14635 Local<Function>::Cast(context->Global()->Get(v8_str("g2")));
14636 Local<Function> h =
14637 Local<Function>::Cast(context->Global()->Get(v8_str("h")));
14638
14639 // Get the global object.
14640 v8::Handle<v8::Object> global = context->Global();
14641
14642 // Call f1 one time and f2 a number of times. This will ensure that f1 still
14643 // uses the runtime system to retreive property a whereas f2 uses global load
14644 // inline cache.
14645 CHECK(f1->Call(global, 0, NULL)->Equals(v8_num(1)));
14646 for (int i = 0; i < 4; i++) {
14647 CHECK(f2->Call(global, 0, NULL)->Equals(v8_num(1)));
14648 }
14649
14650 // Same for g1 and g2.
14651 CHECK(g1->Call(global, 0, NULL)->Equals(v8_num(1)));
14652 for (int i = 0; i < 4; i++) {
14653 CHECK(g2->Call(global, 0, NULL)->Equals(v8_num(1)));
14654 }
14655
14656 // Detach the global and turn on access check.
jkummerow@chromium.org113035e2013-12-13 15:13:40 +000014657 Local<Object> hidden_global = Local<Object>::Cast(
14658 context->Global()->GetPrototype());
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000014659 context->DetachGlobal();
jkummerow@chromium.org113035e2013-12-13 15:13:40 +000014660 hidden_global->TurnOnAccessCheck();
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000014661
14662 // Failing access check to property get results in undefined.
14663 CHECK(f1->Call(global, 0, NULL)->IsUndefined());
14664 CHECK(f2->Call(global, 0, NULL)->IsUndefined());
14665
14666 // Failing access check to function call results in exception.
14667 CHECK(g1->Call(global, 0, NULL).IsEmpty());
14668 CHECK(g2->Call(global, 0, NULL).IsEmpty());
14669
14670 // No failing access check when just returning a constant.
14671 CHECK(h->Call(global, 0, NULL)->Equals(v8_num(1)));
14672}
14673
14674
jkummerow@chromium.orgf7a58842012-02-21 10:08:21 +000014675static const char* kPropertyA = "a";
14676static const char* kPropertyH = "h";
kasperl@chromium.orga5551262010-12-07 12:49:48 +000014677
14678static bool NamedGetAccessBlockAandH(Local<v8::Object> obj,
14679 Local<Value> name,
14680 v8::AccessType type,
14681 Local<Value> data) {
jkummerow@chromium.orgf7a58842012-02-21 10:08:21 +000014682 if (!name->IsString()) return false;
14683 i::Handle<i::String> name_handle =
14684 v8::Utils::OpenHandle(String::Cast(*name));
jkummerow@chromium.org59297c72013-01-09 16:32:23 +000014685 return !name_handle->IsUtf8EqualTo(i::CStrVector(kPropertyA))
14686 && !name_handle->IsUtf8EqualTo(i::CStrVector(kPropertyH));
kasperl@chromium.orga5551262010-12-07 12:49:48 +000014687}
14688
14689
jkummerow@chromium.orgf7a58842012-02-21 10:08:21 +000014690THREADED_TEST(TurnOnAccessCheckAndRecompile) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014691 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000014692 v8::HandleScope handle_scope(isolate);
kasperl@chromium.orga5551262010-12-07 12:49:48 +000014693
14694 // Create an environment with access check to the global object disabled by
14695 // default. When the registered access checker will block access to properties
jkummerow@chromium.orgf7a58842012-02-21 10:08:21 +000014696 // a and h.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000014697 v8::Handle<v8::ObjectTemplate> global_template =
14698 v8::ObjectTemplate::New(isolate);
kasperl@chromium.orga5551262010-12-07 12:49:48 +000014699 global_template->SetAccessCheckCallbacks(NamedGetAccessBlockAandH,
14700 IndexedGetAccessBlocker,
14701 v8::Handle<v8::Value>(),
14702 false);
ulan@chromium.org57ff8812013-05-10 08:16:55 +000014703 v8::Local<Context> context = Context::New(isolate, NULL, global_template);
kasperl@chromium.orga5551262010-12-07 12:49:48 +000014704 Context::Scope context_scope(context);
14705
14706 // Set up a property and a number of functions.
14707 context->Global()->Set(v8_str("a"), v8_num(1));
14708 static const char* source = "function f1() {return a;}"
14709 "function f2() {return a;}"
14710 "function g1() {return h();}"
14711 "function g2() {return h();}"
14712 "function h() {return 1;}";
14713
14714 CompileRun(source);
14715 Local<Function> f1;
14716 Local<Function> f2;
14717 Local<Function> g1;
14718 Local<Function> g2;
14719 Local<Function> h;
14720 f1 = Local<Function>::Cast(context->Global()->Get(v8_str("f1")));
14721 f2 = Local<Function>::Cast(context->Global()->Get(v8_str("f2")));
14722 g1 = Local<Function>::Cast(context->Global()->Get(v8_str("g1")));
14723 g2 = Local<Function>::Cast(context->Global()->Get(v8_str("g2")));
14724 h = Local<Function>::Cast(context->Global()->Get(v8_str("h")));
14725
14726 // Get the global object.
14727 v8::Handle<v8::Object> global = context->Global();
14728
14729 // Call f1 one time and f2 a number of times. This will ensure that f1 still
14730 // uses the runtime system to retreive property a whereas f2 uses global load
14731 // inline cache.
14732 CHECK(f1->Call(global, 0, NULL)->Equals(v8_num(1)));
14733 for (int i = 0; i < 4; i++) {
14734 CHECK(f2->Call(global, 0, NULL)->Equals(v8_num(1)));
14735 }
14736
14737 // Same for g1 and g2.
14738 CHECK(g1->Call(global, 0, NULL)->Equals(v8_num(1)));
14739 for (int i = 0; i < 4; i++) {
14740 CHECK(g2->Call(global, 0, NULL)->Equals(v8_num(1)));
14741 }
14742
14743 // Detach the global and turn on access check now blocking access to property
14744 // a and function h.
jkummerow@chromium.org113035e2013-12-13 15:13:40 +000014745 Local<Object> hidden_global = Local<Object>::Cast(
14746 context->Global()->GetPrototype());
kasperl@chromium.orga5551262010-12-07 12:49:48 +000014747 context->DetachGlobal();
jkummerow@chromium.org113035e2013-12-13 15:13:40 +000014748 hidden_global->TurnOnAccessCheck();
kasperl@chromium.orga5551262010-12-07 12:49:48 +000014749
14750 // Failing access check to property get results in undefined.
14751 CHECK(f1->Call(global, 0, NULL)->IsUndefined());
14752 CHECK(f2->Call(global, 0, NULL)->IsUndefined());
14753
14754 // Failing access check to function call results in exception.
14755 CHECK(g1->Call(global, 0, NULL).IsEmpty());
14756 CHECK(g2->Call(global, 0, NULL).IsEmpty());
14757
14758 // No failing access check when just returning a constant.
14759 CHECK(h->Call(global, 0, NULL)->Equals(v8_num(1)));
14760
14761 // Now compile the source again. And get the newly compiled functions, except
14762 // for h for which access is blocked.
14763 CompileRun(source);
jkummerow@chromium.org113035e2013-12-13 15:13:40 +000014764 f1 = Local<Function>::Cast(hidden_global->Get(v8_str("f1")));
14765 f2 = Local<Function>::Cast(hidden_global->Get(v8_str("f2")));
14766 g1 = Local<Function>::Cast(hidden_global->Get(v8_str("g1")));
14767 g2 = Local<Function>::Cast(hidden_global->Get(v8_str("g2")));
14768 CHECK(hidden_global->Get(v8_str("h"))->IsUndefined());
kasperl@chromium.orga5551262010-12-07 12:49:48 +000014769
14770 // Failing access check to property get results in undefined.
14771 CHECK(f1->Call(global, 0, NULL)->IsUndefined());
14772 CHECK(f2->Call(global, 0, NULL)->IsUndefined());
14773
14774 // Failing access check to function call results in exception.
14775 CHECK(g1->Call(global, 0, NULL).IsEmpty());
14776 CHECK(g2->Call(global, 0, NULL).IsEmpty());
14777}
14778
14779
ager@chromium.orga74f0da2008-12-03 16:05:52 +000014780// This test verifies that pre-compilation (aka preparsing) can be called
14781// without initializing the whole VM. Thus we cannot run this test in a
14782// multi-threaded setup.
14783TEST(PreCompile) {
14784 // TODO(155): This test would break without the initialization of V8. This is
14785 // a workaround for now to make this test not fail.
14786 v8::V8::Initialize();
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +000014787 v8::Isolate* isolate = CcTest::isolate();
machenbach@chromium.org4ddd2f12014-01-14 08:13:44 +000014788 HandleScope handle_scope(isolate);
kmillikin@chromium.org9155e252010-05-26 13:27:57 +000014789 const char* script = "function foo(a) { return a+1; }";
machenbach@chromium.org4ddd2f12014-01-14 08:13:44 +000014790 v8::ScriptData* sd = v8::ScriptData::PreCompile(v8::String::NewFromUtf8(
14791 isolate, script, v8::String::kNormalString, i::StrLength(script)));
ager@chromium.orga74f0da2008-12-03 16:05:52 +000014792 CHECK_NE(sd->Length(), 0);
14793 CHECK_NE(sd->Data(), NULL);
fschneider@chromium.org0c20e672010-01-14 15:28:53 +000014794 CHECK(!sd->HasError());
14795 delete sd;
14796}
14797
14798
14799TEST(PreCompileWithError) {
14800 v8::V8::Initialize();
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +000014801 v8::Isolate* isolate = CcTest::isolate();
machenbach@chromium.org4ddd2f12014-01-14 08:13:44 +000014802 HandleScope handle_scope(isolate);
kmillikin@chromium.org9155e252010-05-26 13:27:57 +000014803 const char* script = "function foo(a) { return 1 * * 2; }";
machenbach@chromium.org4ddd2f12014-01-14 08:13:44 +000014804 v8::ScriptData* sd = v8::ScriptData::PreCompile(v8::String::NewFromUtf8(
14805 isolate, script, v8::String::kNormalString, i::StrLength(script)));
fschneider@chromium.org0c20e672010-01-14 15:28:53 +000014806 CHECK(sd->HasError());
14807 delete sd;
14808}
14809
14810
14811TEST(Regress31661) {
14812 v8::V8::Initialize();
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +000014813 v8::Isolate* isolate = CcTest::isolate();
machenbach@chromium.org4ddd2f12014-01-14 08:13:44 +000014814 HandleScope handle_scope(isolate);
kmillikin@chromium.org9155e252010-05-26 13:27:57 +000014815 const char* script = " The Definintive Guide";
machenbach@chromium.org4ddd2f12014-01-14 08:13:44 +000014816 v8::ScriptData* sd = v8::ScriptData::PreCompile(v8::String::NewFromUtf8(
14817 isolate, script, v8::String::kNormalString, i::StrLength(script)));
fschneider@chromium.org0c20e672010-01-14 15:28:53 +000014818 CHECK(sd->HasError());
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000014819 delete sd;
ager@chromium.orga74f0da2008-12-03 16:05:52 +000014820}
14821
14822
kmillikin@chromium.org9155e252010-05-26 13:27:57 +000014823// Tests that ScriptData can be serialized and deserialized.
14824TEST(PreCompileSerialization) {
14825 v8::V8::Initialize();
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +000014826 v8::Isolate* isolate = CcTest::isolate();
machenbach@chromium.org4ddd2f12014-01-14 08:13:44 +000014827 HandleScope handle_scope(isolate);
kmillikin@chromium.org9155e252010-05-26 13:27:57 +000014828 const char* script = "function foo(a) { return a+1; }";
machenbach@chromium.org4ddd2f12014-01-14 08:13:44 +000014829 v8::ScriptData* sd = v8::ScriptData::PreCompile(v8::String::NewFromUtf8(
14830 isolate, script, v8::String::kNormalString, i::StrLength(script)));
kmillikin@chromium.org9155e252010-05-26 13:27:57 +000014831
14832 // Serialize.
14833 int serialized_data_length = sd->Length();
14834 char* serialized_data = i::NewArray<char>(serialized_data_length);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +000014835 i::OS::MemCopy(serialized_data, sd->Data(), serialized_data_length);
kmillikin@chromium.org9155e252010-05-26 13:27:57 +000014836
14837 // Deserialize.
14838 v8::ScriptData* deserialized_sd =
14839 v8::ScriptData::New(serialized_data, serialized_data_length);
14840
14841 // Verify that the original is the same as the deserialized.
14842 CHECK_EQ(sd->Length(), deserialized_sd->Length());
14843 CHECK_EQ(0, memcmp(sd->Data(), deserialized_sd->Data(), sd->Length()));
14844 CHECK_EQ(sd->HasError(), deserialized_sd->HasError());
14845
14846 delete sd;
14847 delete deserialized_sd;
14848}
14849
14850
14851// Attempts to deserialize bad data.
14852TEST(PreCompileDeserializationError) {
14853 v8::V8::Initialize();
14854 const char* data = "DONT CARE";
14855 int invalid_size = 3;
14856 v8::ScriptData* sd = v8::ScriptData::New(data, invalid_size);
14857
14858 CHECK_EQ(0, sd->Length());
14859
14860 delete sd;
14861}
14862
14863
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014864// Attempts to deserialize bad data.
14865TEST(PreCompileInvalidPreparseDataError) {
14866 v8::V8::Initialize();
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +000014867 v8::Isolate* isolate = CcTest::isolate();
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014868 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014869 v8::HandleScope scope(context->GetIsolate());
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014870
14871 const char* script = "function foo(){ return 5;}\n"
14872 "function bar(){ return 6 + 7;} foo();";
machenbach@chromium.org4ddd2f12014-01-14 08:13:44 +000014873 v8::ScriptData* sd = v8::ScriptData::PreCompile(v8::String::NewFromUtf8(
14874 isolate, script, v8::String::kNormalString, i::StrLength(script)));
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014875 CHECK(!sd->HasError());
14876 // ScriptDataImpl private implementation details
ager@chromium.orgbeb25712010-11-29 08:02:25 +000014877 const int kHeaderSize = i::PreparseDataConstants::kHeaderSize;
ager@chromium.org5b2fbee2010-09-08 06:38:15 +000014878 const int kFunctionEntrySize = i::FunctionEntry::kSize;
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014879 const int kFunctionEntryStartOffset = 0;
14880 const int kFunctionEntryEndOffset = 1;
14881 unsigned* sd_data =
14882 reinterpret_cast<unsigned*>(const_cast<char*>(sd->Data()));
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014883
14884 // Overwrite function bar's end position with 0.
14885 sd_data[kHeaderSize + 1 * kFunctionEntrySize + kFunctionEntryEndOffset] = 0;
14886 v8::TryCatch try_catch;
14887
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000014888 Local<String> source = String::NewFromUtf8(isolate, script);
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014889 Local<Script> compiled_script = Script::New(source, NULL, sd);
14890 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000014891 String::Utf8Value exception_value(try_catch.Message()->Get());
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014892 CHECK_EQ("Uncaught SyntaxError: Invalid preparser data for function bar",
14893 *exception_value);
14894
14895 try_catch.Reset();
lrn@chromium.orgd4e9e222011-08-03 12:01:58 +000014896
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014897 // Overwrite function bar's start position with 200. The function entry
lrn@chromium.orgd4e9e222011-08-03 12:01:58 +000014898 // will not be found when searching for it by position and we should fall
14899 // back on eager compilation.
machenbach@chromium.org4ddd2f12014-01-14 08:13:44 +000014900 sd = v8::ScriptData::PreCompile(v8::String::NewFromUtf8(
14901 isolate, script, v8::String::kNormalString, i::StrLength(script)));
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +000014902 sd_data = reinterpret_cast<unsigned*>(const_cast<char*>(sd->Data()));
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014903 sd_data[kHeaderSize + 1 * kFunctionEntrySize + kFunctionEntryStartOffset] =
14904 200;
14905 compiled_script = Script::New(source, NULL, sd);
lrn@chromium.orgd4e9e222011-08-03 12:01:58 +000014906 CHECK(!try_catch.HasCaught());
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014907
14908 delete sd;
14909}
14910
14911
ager@chromium.orga74f0da2008-12-03 16:05:52 +000014912// This tests that we do not allow dictionary load/call inline caches
14913// to use functions that have not yet been compiled. The potential
14914// problem of loading a function that has not yet been compiled can
14915// arise because we share code between contexts via the compilation
14916// cache.
14917THREADED_TEST(DictionaryICLoadedFunction) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014918 v8::HandleScope scope(CcTest::isolate());
ager@chromium.orga74f0da2008-12-03 16:05:52 +000014919 // Test LoadIC.
14920 for (int i = 0; i < 2; i++) {
14921 LocalContext context;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000014922 context->Global()->Set(v8_str("tmp"), v8::True(CcTest::isolate()));
ager@chromium.orga74f0da2008-12-03 16:05:52 +000014923 context->Global()->Delete(v8_str("tmp"));
14924 CompileRun("for (var j = 0; j < 10; j++) new RegExp('');");
14925 }
14926 // Test CallIC.
14927 for (int i = 0; i < 2; i++) {
14928 LocalContext context;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000014929 context->Global()->Set(v8_str("tmp"), v8::True(CcTest::isolate()));
ager@chromium.orga74f0da2008-12-03 16:05:52 +000014930 context->Global()->Delete(v8_str("tmp"));
14931 CompileRun("for (var j = 0; j < 10; j++) RegExp('')");
14932 }
14933}
ager@chromium.orgddb913d2009-01-27 10:01:48 +000014934
14935
14936// Test that cross-context new calls use the context of the callee to
14937// create the new JavaScript object.
14938THREADED_TEST(CrossContextNew) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014939 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000014940 v8::HandleScope scope(isolate);
14941 v8::Local<Context> context0 = Context::New(isolate);
14942 v8::Local<Context> context1 = Context::New(isolate);
ager@chromium.orgddb913d2009-01-27 10:01:48 +000014943
14944 // Allow cross-domain access.
14945 Local<String> token = v8_str("<security token>");
14946 context0->SetSecurityToken(token);
14947 context1->SetSecurityToken(token);
14948
14949 // Set an 'x' property on the Object prototype and define a
14950 // constructor function in context0.
14951 context0->Enter();
14952 CompileRun("Object.prototype.x = 42; function C() {};");
14953 context0->Exit();
14954
14955 // Call the constructor function from context0 and check that the
14956 // result has the 'x' property.
14957 context1->Enter();
14958 context1->Global()->Set(v8_str("other"), context0->Global());
14959 Local<Value> value = CompileRun("var instance = new other.C(); instance.x");
14960 CHECK(value->IsInt32());
14961 CHECK_EQ(42, value->Int32Value());
14962 context1->Exit();
ager@chromium.orgddb913d2009-01-27 10:01:48 +000014963}
ager@chromium.org381abbb2009-02-25 13:23:22 +000014964
14965
ager@chromium.org3b45ab52009-03-19 22:21:34 +000014966// Verify that we can clone an object
14967TEST(ObjectClone) {
ager@chromium.org3b45ab52009-03-19 22:21:34 +000014968 LocalContext env;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014969 v8::Isolate* isolate = env->GetIsolate();
14970 v8::HandleScope scope(isolate);
ager@chromium.org3b45ab52009-03-19 22:21:34 +000014971
14972 const char* sample =
14973 "var rv = {};" \
14974 "rv.alpha = 'hello';" \
14975 "rv.beta = 123;" \
14976 "rv;";
14977
14978 // Create an object, verify basics.
14979 Local<Value> val = CompileRun(sample);
14980 CHECK(val->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000014981 Local<v8::Object> obj = val.As<v8::Object>();
ager@chromium.org3b45ab52009-03-19 22:21:34 +000014982 obj->Set(v8_str("gamma"), v8_str("cloneme"));
14983
14984 CHECK_EQ(v8_str("hello"), obj->Get(v8_str("alpha")));
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014985 CHECK_EQ(v8::Integer::New(isolate, 123), obj->Get(v8_str("beta")));
ager@chromium.org3b45ab52009-03-19 22:21:34 +000014986 CHECK_EQ(v8_str("cloneme"), obj->Get(v8_str("gamma")));
14987
14988 // Clone it.
14989 Local<v8::Object> clone = obj->Clone();
14990 CHECK_EQ(v8_str("hello"), clone->Get(v8_str("alpha")));
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014991 CHECK_EQ(v8::Integer::New(isolate, 123), clone->Get(v8_str("beta")));
ager@chromium.org3b45ab52009-03-19 22:21:34 +000014992 CHECK_EQ(v8_str("cloneme"), clone->Get(v8_str("gamma")));
14993
14994 // Set a property on the clone, verify each object.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014995 clone->Set(v8_str("beta"), v8::Integer::New(isolate, 456));
14996 CHECK_EQ(v8::Integer::New(isolate, 123), obj->Get(v8_str("beta")));
14997 CHECK_EQ(v8::Integer::New(isolate, 456), clone->Get(v8_str("beta")));
ager@chromium.org3b45ab52009-03-19 22:21:34 +000014998}
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000014999
15000
ager@chromium.org5ec48922009-05-05 07:25:34 +000015001class AsciiVectorResource : public v8::String::ExternalAsciiStringResource {
15002 public:
15003 explicit AsciiVectorResource(i::Vector<const char> vector)
15004 : data_(vector) {}
15005 virtual ~AsciiVectorResource() {}
15006 virtual size_t length() const { return data_.length(); }
15007 virtual const char* data() const { return data_.start(); }
15008 private:
15009 i::Vector<const char> data_;
15010};
15011
15012
15013class UC16VectorResource : public v8::String::ExternalStringResource {
15014 public:
15015 explicit UC16VectorResource(i::Vector<const i::uc16> vector)
15016 : data_(vector) {}
15017 virtual ~UC16VectorResource() {}
15018 virtual size_t length() const { return data_.length(); }
15019 virtual const i::uc16* data() const { return data_.start(); }
15020 private:
15021 i::Vector<const i::uc16> data_;
15022};
15023
15024
15025static void MorphAString(i::String* string,
15026 AsciiVectorResource* ascii_resource,
15027 UC16VectorResource* uc16_resource) {
15028 CHECK(i::StringShape(string).IsExternal());
ulan@chromium.org8e8d8822012-11-23 14:36:46 +000015029 if (string->IsOneByteRepresentation()) {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +000015030 // Check old map is not internalized or long.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015031 CHECK(string->map() == CcTest::heap()->external_ascii_string_map());
ager@chromium.org5ec48922009-05-05 07:25:34 +000015032 // Morph external string to be TwoByte string.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015033 string->set_map(CcTest::heap()->external_string_map());
ager@chromium.org5ec48922009-05-05 07:25:34 +000015034 i::ExternalTwoByteString* morphed =
15035 i::ExternalTwoByteString::cast(string);
15036 morphed->set_resource(uc16_resource);
15037 } else {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +000015038 // Check old map is not internalized or long.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015039 CHECK(string->map() == CcTest::heap()->external_string_map());
ager@chromium.org5ec48922009-05-05 07:25:34 +000015040 // Morph external string to be ASCII string.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015041 string->set_map(CcTest::heap()->external_ascii_string_map());
ager@chromium.org5ec48922009-05-05 07:25:34 +000015042 i::ExternalAsciiString* morphed =
15043 i::ExternalAsciiString::cast(string);
15044 morphed->set_resource(ascii_resource);
15045 }
15046}
15047
15048
15049// Test that we can still flatten a string if the components it is built up
15050// from have been turned into 16 bit strings in the mean time.
15051THREADED_TEST(MorphCompositeStringTest) {
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +000015052 char utf_buffer[129];
ager@chromium.org5ec48922009-05-05 07:25:34 +000015053 const char* c_string = "Now is the time for all good men"
15054 " to come to the aid of the party";
15055 uint16_t* two_byte_string = AsciiToTwoByteString(c_string);
15056 {
ager@chromium.org5ec48922009-05-05 07:25:34 +000015057 LocalContext env;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015058 i::Factory* factory = CcTest::i_isolate()->factory();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015059 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org5ec48922009-05-05 07:25:34 +000015060 AsciiVectorResource ascii_resource(
ager@chromium.orgc4c92722009-11-18 14:12:51 +000015061 i::Vector<const char>(c_string, i::StrLength(c_string)));
ager@chromium.org5ec48922009-05-05 07:25:34 +000015062 UC16VectorResource uc16_resource(
ager@chromium.orgc4c92722009-11-18 14:12:51 +000015063 i::Vector<const uint16_t>(two_byte_string,
15064 i::StrLength(c_string)));
ager@chromium.org5ec48922009-05-05 07:25:34 +000015065
15066 Local<String> lhs(v8::Utils::ToLocal(
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000015067 factory->NewExternalStringFromAscii(&ascii_resource)));
ager@chromium.org5ec48922009-05-05 07:25:34 +000015068 Local<String> rhs(v8::Utils::ToLocal(
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000015069 factory->NewExternalStringFromAscii(&ascii_resource)));
ager@chromium.org5ec48922009-05-05 07:25:34 +000015070
15071 env->Global()->Set(v8_str("lhs"), lhs);
15072 env->Global()->Set(v8_str("rhs"), rhs);
15073
15074 CompileRun(
15075 "var cons = lhs + rhs;"
15076 "var slice = lhs.substring(1, lhs.length - 1);"
15077 "var slice_on_cons = (lhs + rhs).substring(1, lhs.length *2 - 1);");
15078
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015079 CHECK(lhs->IsOneByte());
15080 CHECK(rhs->IsOneByte());
rossberg@chromium.org2c067b12012-03-19 11:01:52 +000015081
ager@chromium.org5ec48922009-05-05 07:25:34 +000015082 MorphAString(*v8::Utils::OpenHandle(*lhs), &ascii_resource, &uc16_resource);
15083 MorphAString(*v8::Utils::OpenHandle(*rhs), &ascii_resource, &uc16_resource);
15084
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +000015085 // This should UTF-8 without flattening, since everything is ASCII.
15086 Handle<String> cons = v8_compile("cons")->Run().As<String>();
15087 CHECK_EQ(128, cons->Utf8Length());
15088 int nchars = -1;
15089 CHECK_EQ(129, cons->WriteUtf8(utf_buffer, -1, &nchars));
15090 CHECK_EQ(128, nchars);
15091 CHECK_EQ(0, strcmp(
15092 utf_buffer,
15093 "Now is the time for all good men to come to the aid of the party"
15094 "Now is the time for all good men to come to the aid of the party"));
15095
ager@chromium.org5ec48922009-05-05 07:25:34 +000015096 // Now do some stuff to make sure the strings are flattened, etc.
15097 CompileRun(
15098 "/[^a-z]/.test(cons);"
15099 "/[^a-z]/.test(slice);"
15100 "/[^a-z]/.test(slice_on_cons);");
15101 const char* expected_cons =
15102 "Now is the time for all good men to come to the aid of the party"
15103 "Now is the time for all good men to come to the aid of the party";
15104 const char* expected_slice =
15105 "ow is the time for all good men to come to the aid of the part";
15106 const char* expected_slice_on_cons =
15107 "ow is the time for all good men to come to the aid of the party"
15108 "Now is the time for all good men to come to the aid of the part";
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015109 CHECK_EQ(String::NewFromUtf8(env->GetIsolate(), expected_cons),
ager@chromium.org5ec48922009-05-05 07:25:34 +000015110 env->Global()->Get(v8_str("cons")));
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015111 CHECK_EQ(String::NewFromUtf8(env->GetIsolate(), expected_slice),
ager@chromium.org5ec48922009-05-05 07:25:34 +000015112 env->Global()->Get(v8_str("slice")));
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015113 CHECK_EQ(String::NewFromUtf8(env->GetIsolate(), expected_slice_on_cons),
ager@chromium.org5ec48922009-05-05 07:25:34 +000015114 env->Global()->Get(v8_str("slice_on_cons")));
15115 }
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000015116 i::DeleteArray(two_byte_string);
ager@chromium.org5ec48922009-05-05 07:25:34 +000015117}
15118
15119
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000015120TEST(CompileExternalTwoByteSource) {
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000015121 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015122 v8::HandleScope scope(context->GetIsolate());
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000015123
15124 // This is a very short list of sources, which currently is to check for a
15125 // regression caused by r2703.
15126 const char* ascii_sources[] = {
15127 "0.5",
15128 "-0.5", // This mainly testes PushBack in the Scanner.
15129 "--0.5", // This mainly testes PushBack in the Scanner.
15130 NULL
15131 };
15132
15133 // Compile the sources as external two byte strings.
15134 for (int i = 0; ascii_sources[i] != NULL; i++) {
15135 uint16_t* two_byte_string = AsciiToTwoByteString(ascii_sources[i]);
15136 UC16VectorResource uc16_resource(
ager@chromium.orgc4c92722009-11-18 14:12:51 +000015137 i::Vector<const uint16_t>(two_byte_string,
15138 i::StrLength(ascii_sources[i])));
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000015139 v8::Local<v8::String> source =
15140 v8::String::NewExternal(context->GetIsolate(), &uc16_resource);
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000015141 v8::Script::Compile(source);
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000015142 i::DeleteArray(two_byte_string);
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000015143 }
15144}
15145
15146
mstarzinger@chromium.orgb4968be2013-10-16 09:00:56 +000015147#ifndef V8_INTERPRETED_REGEXP
15148
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +000015149struct RegExpInterruptionData {
15150 int loop_count;
15151 UC16VectorResource* string_resource;
15152 v8::Persistent<v8::String> string;
15153} regexp_interruption_data;
15154
15155
15156class RegExpInterruptionThread : public i::Thread {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015157 public:
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +000015158 explicit RegExpInterruptionThread(v8::Isolate* isolate)
15159 : Thread("TimeoutThread"), isolate_(isolate) {}
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000015160
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +000015161 virtual void Run() {
15162 for (regexp_interruption_data.loop_count = 0;
15163 regexp_interruption_data.loop_count < 7;
15164 regexp_interruption_data.loop_count++) {
15165 i::OS::Sleep(50); // Wait a bit before requesting GC.
15166 reinterpret_cast<i::Isolate*>(isolate_)->stack_guard()->RequestGC();
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015167 }
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +000015168 i::OS::Sleep(50); // Wait a bit before terminating.
15169 v8::V8::TerminateExecution(isolate_);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015170 }
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015171
jkummerow@chromium.orge297f592011-06-08 10:05:15 +000015172 private:
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +000015173 v8::Isolate* isolate_;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015174};
15175
15176
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +000015177void RunBeforeGC(v8::GCType type, v8::GCCallbackFlags flags) {
15178 if (regexp_interruption_data.loop_count != 2) return;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015179 v8::HandleScope scope(CcTest::isolate());
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +000015180 v8::Local<v8::String> string = v8::Local<v8::String>::New(
15181 CcTest::isolate(), regexp_interruption_data.string);
15182 string->MakeExternal(regexp_interruption_data.string_resource);
15183}
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015184
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015185
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +000015186// Test that RegExp execution can be interrupted. Specifically, we test
15187// * interrupting with GC
15188// * turn the subject string from one-byte internal to two-byte external string
15189// * force termination
15190TEST(RegExpInterruption) {
15191 v8::HandleScope scope(CcTest::isolate());
15192 LocalContext env;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015193
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +000015194 RegExpInterruptionThread timeout_thread(CcTest::isolate());
15195
15196 v8::V8::AddGCPrologueCallback(RunBeforeGC);
15197 static const char* ascii_content = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
15198 i::uc16* uc16_content = AsciiToTwoByteString(ascii_content);
15199 v8::Local<v8::String> string = v8_str(ascii_content);
15200
15201 CcTest::global()->Set(v8_str("a"), string);
15202 regexp_interruption_data.string.Reset(CcTest::isolate(), string);
15203 regexp_interruption_data.string_resource = new UC16VectorResource(
15204 i::Vector<const i::uc16>(uc16_content, i::StrLength(ascii_content)));
15205
15206 v8::TryCatch try_catch;
15207 timeout_thread.Start();
15208
15209 CompileRun("/((a*)*)*b/.exec(a)");
15210 CHECK(try_catch.HasTerminated());
15211
15212 timeout_thread.Join();
15213
15214 delete regexp_interruption_data.string_resource;
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015215 regexp_interruption_data.string.Reset();
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015216}
15217
mstarzinger@chromium.orgb4968be2013-10-16 09:00:56 +000015218#endif // V8_INTERPRETED_REGEXP
15219
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015220
mmassi@chromium.org7028c052012-06-13 11:51:58 +000015221// Test that we cannot set a property on the global object if there
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015222// is a read-only property in the prototype chain.
15223TEST(ReadOnlyPropertyInGlobalProto) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +000015224 i::FLAG_es5_readonly = true;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015225 v8::Isolate* isolate = CcTest::isolate();
15226 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000015227 v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015228 LocalContext context(0, templ);
15229 v8::Handle<v8::Object> global = context->Global();
15230 v8::Handle<v8::Object> global_proto =
15231 v8::Handle<v8::Object>::Cast(global->Get(v8_str("__proto__")));
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015232 global_proto->Set(v8_str("x"), v8::Integer::New(isolate, 0), v8::ReadOnly);
15233 global_proto->Set(v8_str("y"), v8::Integer::New(isolate, 0), v8::ReadOnly);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015234 // Check without 'eval' or 'with'.
15235 v8::Handle<v8::Value> res =
15236 CompileRun("function f() { x = 42; return x; }; f()");
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015237 CHECK_EQ(v8::Integer::New(isolate, 0), res);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015238 // Check with 'eval'.
mmassi@chromium.org7028c052012-06-13 11:51:58 +000015239 res = CompileRun("function f() { eval('1'); y = 43; return y; }; f()");
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015240 CHECK_EQ(v8::Integer::New(isolate, 0), res);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015241 // Check with 'with'.
mmassi@chromium.org7028c052012-06-13 11:51:58 +000015242 res = CompileRun("function f() { with (this) { y = 44 }; return y; }; f()");
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015243 CHECK_EQ(v8::Integer::New(isolate, 0), res);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015244}
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015245
15246static int force_set_set_count = 0;
15247static int force_set_get_count = 0;
15248bool pass_on_get = false;
15249
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015250static void ForceSetGetter(v8::Local<v8::String> name,
15251 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015252 force_set_get_count++;
15253 if (pass_on_get) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015254 return;
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015255 }
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015256 info.GetReturnValue().Set(3);
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015257}
15258
15259static void ForceSetSetter(v8::Local<v8::String> name,
15260 v8::Local<v8::Value> value,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015261 const v8::PropertyCallbackInfo<void>& info) {
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015262 force_set_set_count++;
15263}
15264
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015265static void ForceSetInterceptSetter(
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015266 v8::Local<v8::String> name,
15267 v8::Local<v8::Value> value,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015268 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015269 force_set_set_count++;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015270 info.GetReturnValue().SetUndefined();
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015271}
15272
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000015273
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015274TEST(ForceSet) {
15275 force_set_get_count = 0;
15276 force_set_set_count = 0;
15277 pass_on_get = false;
15278
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015279 v8::Isolate* isolate = CcTest::isolate();
15280 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000015281 v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015282 v8::Handle<v8::String> access_property =
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015283 v8::String::NewFromUtf8(isolate, "a");
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015284 templ->SetAccessor(access_property, ForceSetGetter, ForceSetSetter);
15285 LocalContext context(NULL, templ);
15286 v8::Handle<v8::Object> global = context->Global();
15287
15288 // Ordinary properties
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015289 v8::Handle<v8::String> simple_property =
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015290 v8::String::NewFromUtf8(isolate, "p");
15291 global->Set(simple_property, v8::Int32::New(isolate, 4), v8::ReadOnly);
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015292 CHECK_EQ(4, global->Get(simple_property)->Int32Value());
15293 // This should fail because the property is read-only
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015294 global->Set(simple_property, v8::Int32::New(isolate, 5));
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015295 CHECK_EQ(4, global->Get(simple_property)->Int32Value());
15296 // This should succeed even though the property is read-only
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015297 global->ForceSet(simple_property, v8::Int32::New(isolate, 6));
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015298 CHECK_EQ(6, global->Get(simple_property)->Int32Value());
15299
15300 // Accessors
15301 CHECK_EQ(0, force_set_set_count);
15302 CHECK_EQ(0, force_set_get_count);
15303 CHECK_EQ(3, global->Get(access_property)->Int32Value());
15304 // CHECK_EQ the property shouldn't override it, just call the setter
15305 // which in this case does nothing.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015306 global->Set(access_property, v8::Int32::New(isolate, 7));
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015307 CHECK_EQ(3, global->Get(access_property)->Int32Value());
15308 CHECK_EQ(1, force_set_set_count);
15309 CHECK_EQ(2, force_set_get_count);
15310 // Forcing the property to be set should override the accessor without
15311 // calling it
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015312 global->ForceSet(access_property, v8::Int32::New(isolate, 8));
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015313 CHECK_EQ(8, global->Get(access_property)->Int32Value());
15314 CHECK_EQ(1, force_set_set_count);
15315 CHECK_EQ(2, force_set_get_count);
15316}
15317
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000015318
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015319TEST(ForceSetWithInterceptor) {
15320 force_set_get_count = 0;
15321 force_set_set_count = 0;
15322 pass_on_get = false;
15323
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015324 v8::Isolate* isolate = CcTest::isolate();
15325 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000015326 v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015327 templ->SetNamedPropertyHandler(ForceSetGetter, ForceSetInterceptSetter);
15328 LocalContext context(NULL, templ);
15329 v8::Handle<v8::Object> global = context->Global();
15330
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015331 v8::Handle<v8::String> some_property =
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015332 v8::String::NewFromUtf8(isolate, "a");
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015333 CHECK_EQ(0, force_set_set_count);
15334 CHECK_EQ(0, force_set_get_count);
15335 CHECK_EQ(3, global->Get(some_property)->Int32Value());
15336 // Setting the property shouldn't override it, just call the setter
15337 // which in this case does nothing.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015338 global->Set(some_property, v8::Int32::New(isolate, 7));
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015339 CHECK_EQ(3, global->Get(some_property)->Int32Value());
15340 CHECK_EQ(1, force_set_set_count);
15341 CHECK_EQ(2, force_set_get_count);
15342 // Getting the property when the interceptor returns an empty handle
15343 // should yield undefined, since the property isn't present on the
15344 // object itself yet.
15345 pass_on_get = true;
15346 CHECK(global->Get(some_property)->IsUndefined());
15347 CHECK_EQ(1, force_set_set_count);
15348 CHECK_EQ(3, force_set_get_count);
15349 // Forcing the property to be set should cause the value to be
15350 // set locally without calling the interceptor.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015351 global->ForceSet(some_property, v8::Int32::New(isolate, 8));
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015352 CHECK_EQ(8, global->Get(some_property)->Int32Value());
15353 CHECK_EQ(1, force_set_set_count);
15354 CHECK_EQ(4, force_set_get_count);
15355 // Reenabling the interceptor should cause it to take precedence over
15356 // the property
15357 pass_on_get = false;
15358 CHECK_EQ(3, global->Get(some_property)->Int32Value());
15359 CHECK_EQ(1, force_set_set_count);
15360 CHECK_EQ(5, force_set_get_count);
15361 // The interceptor should also work for other properties
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015362 CHECK_EQ(3, global->Get(v8::String::NewFromUtf8(isolate, "b"))
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015363 ->Int32Value());
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015364 CHECK_EQ(1, force_set_set_count);
15365 CHECK_EQ(6, force_set_get_count);
15366}
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000015367
15368
ager@chromium.orge2902be2009-06-08 12:21:35 +000015369THREADED_TEST(ForceDelete) {
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015370 v8::Isolate* isolate = CcTest::isolate();
15371 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000015372 v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
ager@chromium.orge2902be2009-06-08 12:21:35 +000015373 LocalContext context(NULL, templ);
15374 v8::Handle<v8::Object> global = context->Global();
15375
15376 // Ordinary properties
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015377 v8::Handle<v8::String> simple_property =
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015378 v8::String::NewFromUtf8(isolate, "p");
15379 global->Set(simple_property, v8::Int32::New(isolate, 4), v8::DontDelete);
ager@chromium.orge2902be2009-06-08 12:21:35 +000015380 CHECK_EQ(4, global->Get(simple_property)->Int32Value());
15381 // This should fail because the property is dont-delete.
15382 CHECK(!global->Delete(simple_property));
15383 CHECK_EQ(4, global->Get(simple_property)->Int32Value());
15384 // This should succeed even though the property is dont-delete.
15385 CHECK(global->ForceDelete(simple_property));
15386 CHECK(global->Get(simple_property)->IsUndefined());
15387}
15388
15389
15390static int force_delete_interceptor_count = 0;
15391static bool pass_on_delete = false;
15392
15393
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015394static void ForceDeleteDeleter(
ager@chromium.orge2902be2009-06-08 12:21:35 +000015395 v8::Local<v8::String> name,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015396 const v8::PropertyCallbackInfo<v8::Boolean>& info) {
ager@chromium.orge2902be2009-06-08 12:21:35 +000015397 force_delete_interceptor_count++;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015398 if (pass_on_delete) return;
15399 info.GetReturnValue().Set(true);
ager@chromium.orge2902be2009-06-08 12:21:35 +000015400}
15401
15402
15403THREADED_TEST(ForceDeleteWithInterceptor) {
15404 force_delete_interceptor_count = 0;
15405 pass_on_delete = false;
15406
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015407 v8::Isolate* isolate = CcTest::isolate();
15408 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000015409 v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
ager@chromium.orge2902be2009-06-08 12:21:35 +000015410 templ->SetNamedPropertyHandler(0, 0, 0, ForceDeleteDeleter);
15411 LocalContext context(NULL, templ);
15412 v8::Handle<v8::Object> global = context->Global();
15413
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015414 v8::Handle<v8::String> some_property =
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015415 v8::String::NewFromUtf8(isolate, "a");
15416 global->Set(some_property, v8::Integer::New(isolate, 42), v8::DontDelete);
ager@chromium.orge2902be2009-06-08 12:21:35 +000015417
15418 // Deleting a property should get intercepted and nothing should
15419 // happen.
15420 CHECK_EQ(0, force_delete_interceptor_count);
15421 CHECK(global->Delete(some_property));
15422 CHECK_EQ(1, force_delete_interceptor_count);
15423 CHECK_EQ(42, global->Get(some_property)->Int32Value());
15424 // Deleting the property when the interceptor returns an empty
15425 // handle should not delete the property since it is DontDelete.
15426 pass_on_delete = true;
15427 CHECK(!global->Delete(some_property));
15428 CHECK_EQ(2, force_delete_interceptor_count);
15429 CHECK_EQ(42, global->Get(some_property)->Int32Value());
15430 // Forcing the property to be deleted should delete the value
15431 // without calling the interceptor.
15432 CHECK(global->ForceDelete(some_property));
15433 CHECK(global->Get(some_property)->IsUndefined());
15434 CHECK_EQ(2, force_delete_interceptor_count);
15435}
15436
15437
kasperl@chromium.org68ac0092009-07-09 06:00:35 +000015438// Make sure that forcing a delete invalidates any IC stubs, so we
15439// don't read the hole value.
15440THREADED_TEST(ForceDeleteIC) {
kasperl@chromium.org68ac0092009-07-09 06:00:35 +000015441 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015442 v8::HandleScope scope(context->GetIsolate());
kasperl@chromium.org68ac0092009-07-09 06:00:35 +000015443 // Create a DontDelete variable on the global object.
15444 CompileRun("this.__proto__ = { foo: 'horse' };"
15445 "var foo = 'fish';"
15446 "function f() { return foo.length; }");
15447 // Initialize the IC for foo in f.
15448 CompileRun("for (var i = 0; i < 4; i++) f();");
15449 // Make sure the value of foo is correct before the deletion.
15450 CHECK_EQ(4, CompileRun("f()")->Int32Value());
15451 // Force the deletion of foo.
15452 CHECK(context->Global()->ForceDelete(v8_str("foo")));
15453 // Make sure the value for foo is read from the prototype, and that
15454 // we don't get in trouble with reading the deleted cell value
15455 // sentinel.
15456 CHECK_EQ(5, CompileRun("f()")->Int32Value());
15457}
15458
15459
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +000015460TEST(InlinedFunctionAcrossContexts) {
15461 i::FLAG_allow_natives_syntax = true;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015462 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000015463 v8::HandleScope outer_scope(isolate);
15464 v8::Local<v8::Context> ctx1 = v8::Context::New(isolate);
15465 v8::Local<v8::Context> ctx2 = v8::Context::New(isolate);
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +000015466 ctx1->Enter();
15467
15468 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015469 v8::HandleScope inner_scope(CcTest::isolate());
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +000015470 CompileRun("var G = 42; function foo() { return G; }");
15471 v8::Local<v8::Value> foo = ctx1->Global()->Get(v8_str("foo"));
15472 ctx2->Enter();
15473 ctx2->Global()->Set(v8_str("o"), foo);
15474 v8::Local<v8::Value> res = CompileRun(
15475 "function f() { return o(); }"
15476 "for (var i = 0; i < 10; ++i) f();"
15477 "%OptimizeFunctionOnNextCall(f);"
15478 "f();");
15479 CHECK_EQ(42, res->Int32Value());
15480 ctx2->Exit();
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015481 v8::Handle<v8::String> G_property =
15482 v8::String::NewFromUtf8(CcTest::isolate(), "G");
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +000015483 CHECK(ctx1->Global()->ForceDelete(G_property));
15484 ctx2->Enter();
15485 ExpectString(
15486 "(function() {"
15487 " try {"
15488 " return f();"
15489 " } catch(e) {"
15490 " return e.toString();"
15491 " }"
15492 " })()",
15493 "ReferenceError: G is not defined");
15494 ctx2->Exit();
15495 ctx1->Exit();
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +000015496 }
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +000015497}
15498
15499
ulan@chromium.org57ff8812013-05-10 08:16:55 +000015500static v8::Local<Context> calling_context0;
15501static v8::Local<Context> calling_context1;
15502static v8::Local<Context> calling_context2;
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000015503
15504
15505// Check that the call to the callback is initiated in
15506// calling_context2, the directly calling context is calling_context1
15507// and the callback itself is in calling_context0.
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015508static void GetCallingContextCallback(
15509 const v8::FunctionCallbackInfo<v8::Value>& args) {
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000015510 ApiTestFuzzer::Fuzz();
mvstanton@chromium.org40ce96b2013-04-09 09:52:22 +000015511 CHECK(args.GetIsolate()->GetCurrentContext() == calling_context0);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015512 CHECK(args.GetIsolate()->GetCallingContext() == calling_context1);
15513 CHECK(args.GetIsolate()->GetEnteredContext() == calling_context2);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015514 args.GetReturnValue().Set(42);
15515}
15516
15517
15518THREADED_TEST(GetCurrentContextWhenNotInContext) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015519 i::Isolate* isolate = CcTest::i_isolate();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015520 CHECK(isolate != NULL);
15521 CHECK(isolate->context() == NULL);
15522 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
15523 v8::HandleScope scope(v8_isolate);
15524 // The following should not crash, but return an empty handle.
15525 v8::Local<v8::Context> current = v8_isolate->GetCurrentContext();
15526 CHECK(current.IsEmpty());
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000015527}
15528
15529
15530THREADED_TEST(GetCallingContext) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015531 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000015532 v8::HandleScope scope(isolate);
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000015533
ulan@chromium.org57ff8812013-05-10 08:16:55 +000015534 Local<Context> calling_context0(Context::New(isolate));
15535 Local<Context> calling_context1(Context::New(isolate));
15536 Local<Context> calling_context2(Context::New(isolate));
15537 ::calling_context0 = calling_context0;
15538 ::calling_context1 = calling_context1;
15539 ::calling_context2 = calling_context2;
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000015540
15541 // Allow cross-domain access.
15542 Local<String> token = v8_str("<security token>");
15543 calling_context0->SetSecurityToken(token);
15544 calling_context1->SetSecurityToken(token);
15545 calling_context2->SetSecurityToken(token);
15546
15547 // Create an object with a C++ callback in context0.
15548 calling_context0->Enter();
15549 Local<v8::FunctionTemplate> callback_templ =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000015550 v8::FunctionTemplate::New(isolate, GetCallingContextCallback);
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000015551 calling_context0->Global()->Set(v8_str("callback"),
15552 callback_templ->GetFunction());
15553 calling_context0->Exit();
15554
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000015555 // Expose context0 in context1 and set up a function that calls the
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000015556 // callback function.
15557 calling_context1->Enter();
15558 calling_context1->Global()->Set(v8_str("context0"),
15559 calling_context0->Global());
15560 CompileRun("function f() { context0.callback() }");
15561 calling_context1->Exit();
15562
15563 // Expose context1 in context2 and call the callback function in
15564 // context0 indirectly through f in context1.
15565 calling_context2->Enter();
15566 calling_context2->Global()->Set(v8_str("context1"),
15567 calling_context1->Global());
15568 CompileRun("context1.f()");
15569 calling_context2->Exit();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000015570 ::calling_context0.Clear();
15571 ::calling_context1.Clear();
15572 ::calling_context2.Clear();
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000015573}
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000015574
15575
15576// Check that a variable declaration with no explicit initialization
erik.corry@gmail.comed49e962012-04-17 11:57:53 +000015577// value does shadow an existing property in the prototype chain.
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000015578THREADED_TEST(InitGlobalVarInProtoChain) {
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +000015579 i::FLAG_es52_globals = true;
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000015580 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015581 v8::HandleScope scope(context->GetIsolate());
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000015582 // Introduce a variable in the prototype chain.
15583 CompileRun("__proto__.x = 42");
erik.corry@gmail.comed49e962012-04-17 11:57:53 +000015584 v8::Handle<v8::Value> result = CompileRun("var x = 43; x");
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000015585 CHECK(!result->IsUndefined());
erik.corry@gmail.comed49e962012-04-17 11:57:53 +000015586 CHECK_EQ(43, result->Int32Value());
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000015587}
kasperl@chromium.org68ac0092009-07-09 06:00:35 +000015588
15589
15590// Regression test for issue 398.
15591// If a function is added to an object, creating a constant function
15592// field, and the result is cloned, replacing the constant function on the
15593// original should not affect the clone.
15594// See http://code.google.com/p/v8/issues/detail?id=398
15595THREADED_TEST(ReplaceConstantFunction) {
kasperl@chromium.org68ac0092009-07-09 06:00:35 +000015596 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000015597 v8::Isolate* isolate = context->GetIsolate();
15598 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015599 v8::Handle<v8::Object> obj = v8::Object::New(isolate);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000015600 v8::Handle<v8::FunctionTemplate> func_templ =
15601 v8::FunctionTemplate::New(isolate);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015602 v8::Handle<v8::String> foo_string =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000015603 v8::String::NewFromUtf8(isolate, "foo");
kasperl@chromium.org68ac0092009-07-09 06:00:35 +000015604 obj->Set(foo_string, func_templ->GetFunction());
15605 v8::Handle<v8::Object> obj_clone = obj->Clone();
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015606 obj_clone->Set(foo_string,
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000015607 v8::String::NewFromUtf8(isolate, "Hello"));
kasperl@chromium.org68ac0092009-07-09 06:00:35 +000015608 CHECK(!obj->Get(foo_string)->IsUndefined());
15609}
kasperl@chromium.orge959c182009-07-27 08:59:04 +000015610
15611
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015612static void CheckElementValue(i::Isolate* isolate,
15613 int expected,
15614 i::Handle<i::Object> obj,
15615 int offset) {
15616 i::Object* element = obj->GetElement(isolate, offset)->ToObjectChecked();
15617 CHECK_EQ(expected, i::Smi::cast(element)->value());
15618}
15619
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015620
15621THREADED_TEST(PixelArray) {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015622 LocalContext context;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015623 i::Isolate* isolate = CcTest::i_isolate();
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015624 i::Factory* factory = isolate->factory();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015625 v8::HandleScope scope(context->GetIsolate());
ager@chromium.orgc4c92722009-11-18 14:12:51 +000015626 const int kElementCount = 260;
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015627 uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(kElementCount));
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000015628 i::Handle<i::ExternalPixelArray> pixels =
15629 i::Handle<i::ExternalPixelArray>::cast(
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000015630 factory->NewExternalArray(kElementCount,
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000015631 v8::kExternalPixelArray,
15632 pixel_data));
15633 // Force GC to trigger verification.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015634 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015635 for (int i = 0; i < kElementCount; i++) {
ager@chromium.orgc4c92722009-11-18 14:12:51 +000015636 pixels->set(i, i % 256);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015637 }
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000015638 // Force GC to trigger verification.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015639 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015640 for (int i = 0; i < kElementCount; i++) {
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +000015641 CHECK_EQ(i % 256, pixels->get_scalar(i));
ager@chromium.orgc4c92722009-11-18 14:12:51 +000015642 CHECK_EQ(i % 256, pixel_data[i]);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015643 }
15644
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015645 v8::Handle<v8::Object> obj = v8::Object::New(context->GetIsolate());
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015646 i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
15647 // Set the elements to be the pixels.
15648 // jsobj->set_elements(*pixels);
15649 obj->SetIndexedPropertiesToPixelData(pixel_data, kElementCount);
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015650 CheckElementValue(isolate, 1, jsobj, 1);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015651 obj->Set(v8_str("field"), v8::Int32::New(CcTest::isolate(), 1503));
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015652 context->Global()->Set(v8_str("pixels"), obj);
15653 v8::Handle<v8::Value> result = CompileRun("pixels.field");
15654 CHECK_EQ(1503, result->Int32Value());
15655 result = CompileRun("pixels[1]");
15656 CHECK_EQ(1, result->Int32Value());
sgjesse@chromium.org9eceac12009-09-30 07:18:41 +000015657
15658 result = CompileRun("var sum = 0;"
15659 "for (var i = 0; i < 8; i++) {"
15660 " sum += pixels[i] = pixels[i] = -i;"
15661 "}"
15662 "sum;");
15663 CHECK_EQ(-28, result->Int32Value());
15664
15665 result = CompileRun("var sum = 0;"
15666 "for (var i = 0; i < 8; i++) {"
15667 " sum += pixels[i] = pixels[i] = 0;"
15668 "}"
15669 "sum;");
15670 CHECK_EQ(0, result->Int32Value());
15671
15672 result = CompileRun("var sum = 0;"
15673 "for (var i = 0; i < 8; i++) {"
15674 " sum += pixels[i] = pixels[i] = 255;"
15675 "}"
15676 "sum;");
15677 CHECK_EQ(8 * 255, result->Int32Value());
15678
15679 result = CompileRun("var sum = 0;"
15680 "for (var i = 0; i < 8; i++) {"
15681 " sum += pixels[i] = pixels[i] = 256 + i;"
15682 "}"
15683 "sum;");
15684 CHECK_EQ(2076, result->Int32Value());
15685
15686 result = CompileRun("var sum = 0;"
15687 "for (var i = 0; i < 8; i++) {"
15688 " sum += pixels[i] = pixels[i] = i;"
15689 "}"
15690 "sum;");
15691 CHECK_EQ(28, result->Int32Value());
15692
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015693 result = CompileRun("var sum = 0;"
15694 "for (var i = 0; i < 8; i++) {"
15695 " sum += pixels[i];"
15696 "}"
15697 "sum;");
15698 CHECK_EQ(28, result->Int32Value());
15699
ulan@chromium.org09d7ab52013-02-25 15:50:35 +000015700 i::Handle<i::Smi> value(i::Smi::FromInt(2),
15701 reinterpret_cast<i::Isolate*>(context->GetIsolate()));
jkummerow@chromium.org486075a2011-09-07 12:44:28 +000015702 i::Handle<i::Object> no_failure;
yangguo@chromium.orgab30bb82012-02-24 14:41:46 +000015703 no_failure =
15704 i::JSObject::SetElement(jsobj, 1, value, NONE, i::kNonStrictMode);
jkummerow@chromium.org486075a2011-09-07 12:44:28 +000015705 ASSERT(!no_failure.is_null());
15706 i::USE(no_failure);
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015707 CheckElementValue(isolate, 2, jsobj, 1);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015708 *value.location() = i::Smi::FromInt(256);
yangguo@chromium.orgab30bb82012-02-24 14:41:46 +000015709 no_failure =
15710 i::JSObject::SetElement(jsobj, 1, value, NONE, i::kNonStrictMode);
jkummerow@chromium.org486075a2011-09-07 12:44:28 +000015711 ASSERT(!no_failure.is_null());
15712 i::USE(no_failure);
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015713 CheckElementValue(isolate, 255, jsobj, 1);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015714 *value.location() = i::Smi::FromInt(-1);
yangguo@chromium.orgab30bb82012-02-24 14:41:46 +000015715 no_failure =
15716 i::JSObject::SetElement(jsobj, 1, value, NONE, i::kNonStrictMode);
jkummerow@chromium.org486075a2011-09-07 12:44:28 +000015717 ASSERT(!no_failure.is_null());
15718 i::USE(no_failure);
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015719 CheckElementValue(isolate, 0, jsobj, 1);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015720
15721 result = CompileRun("for (var i = 0; i < 8; i++) {"
15722 " pixels[i] = (i * 65) - 109;"
15723 "}"
15724 "pixels[1] + pixels[6];");
15725 CHECK_EQ(255, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015726 CheckElementValue(isolate, 0, jsobj, 0);
15727 CheckElementValue(isolate, 0, jsobj, 1);
15728 CheckElementValue(isolate, 21, jsobj, 2);
15729 CheckElementValue(isolate, 86, jsobj, 3);
15730 CheckElementValue(isolate, 151, jsobj, 4);
15731 CheckElementValue(isolate, 216, jsobj, 5);
15732 CheckElementValue(isolate, 255, jsobj, 6);
15733 CheckElementValue(isolate, 255, jsobj, 7);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015734 result = CompileRun("var sum = 0;"
15735 "for (var i = 0; i < 8; i++) {"
15736 " sum += pixels[i];"
15737 "}"
15738 "sum;");
15739 CHECK_EQ(984, result->Int32Value());
15740
15741 result = CompileRun("for (var i = 0; i < 8; i++) {"
15742 " pixels[i] = (i * 1.1);"
15743 "}"
15744 "pixels[1] + pixels[6];");
15745 CHECK_EQ(8, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015746 CheckElementValue(isolate, 0, jsobj, 0);
15747 CheckElementValue(isolate, 1, jsobj, 1);
15748 CheckElementValue(isolate, 2, jsobj, 2);
15749 CheckElementValue(isolate, 3, jsobj, 3);
15750 CheckElementValue(isolate, 4, jsobj, 4);
15751 CheckElementValue(isolate, 6, jsobj, 5);
15752 CheckElementValue(isolate, 7, jsobj, 6);
15753 CheckElementValue(isolate, 8, jsobj, 7);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015754
15755 result = CompileRun("for (var i = 0; i < 8; i++) {"
15756 " pixels[7] = undefined;"
15757 "}"
15758 "pixels[7];");
15759 CHECK_EQ(0, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015760 CheckElementValue(isolate, 0, jsobj, 7);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015761
15762 result = CompileRun("for (var i = 0; i < 8; i++) {"
15763 " pixels[6] = '2.3';"
15764 "}"
15765 "pixels[6];");
15766 CHECK_EQ(2, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015767 CheckElementValue(isolate, 2, jsobj, 6);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015768
15769 result = CompileRun("for (var i = 0; i < 8; i++) {"
15770 " pixels[5] = NaN;"
15771 "}"
15772 "pixels[5];");
15773 CHECK_EQ(0, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015774 CheckElementValue(isolate, 0, jsobj, 5);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015775
15776 result = CompileRun("for (var i = 0; i < 8; i++) {"
15777 " pixels[8] = Infinity;"
15778 "}"
15779 "pixels[8];");
15780 CHECK_EQ(255, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015781 CheckElementValue(isolate, 255, jsobj, 8);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015782
15783 result = CompileRun("for (var i = 0; i < 8; i++) {"
15784 " pixels[9] = -Infinity;"
15785 "}"
15786 "pixels[9];");
15787 CHECK_EQ(0, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015788 CheckElementValue(isolate, 0, jsobj, 9);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015789
15790 result = CompileRun("pixels[3] = 33;"
15791 "delete pixels[3];"
15792 "pixels[3];");
15793 CHECK_EQ(33, result->Int32Value());
15794
15795 result = CompileRun("pixels[0] = 10; pixels[1] = 11;"
15796 "pixels[2] = 12; pixels[3] = 13;"
15797 "pixels.__defineGetter__('2',"
15798 "function() { return 120; });"
15799 "pixels[2];");
15800 CHECK_EQ(12, result->Int32Value());
15801
15802 result = CompileRun("var js_array = new Array(40);"
15803 "js_array[0] = 77;"
15804 "js_array;");
15805 CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
15806
15807 result = CompileRun("pixels[1] = 23;"
15808 "pixels.__proto__ = [];"
15809 "js_array.__proto__ = pixels;"
15810 "js_array.concat(pixels);");
15811 CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
15812 CHECK_EQ(23, v8::Object::Cast(*result)->Get(v8_str("1"))->Int32Value());
15813
sgjesse@chromium.org9eceac12009-09-30 07:18:41 +000015814 result = CompileRun("pixels[1] = 23;");
15815 CHECK_EQ(23, result->Int32Value());
15816
ager@chromium.orgc4c92722009-11-18 14:12:51 +000015817 // Test for index greater than 255. Regression test for:
15818 // http://code.google.com/p/chromium/issues/detail?id=26337.
15819 result = CompileRun("pixels[256] = 255;");
15820 CHECK_EQ(255, result->Int32Value());
15821 result = CompileRun("var i = 0;"
15822 "for (var j = 0; j < 8; j++) { i = pixels[256]; }"
15823 "i");
15824 CHECK_EQ(255, result->Int32Value());
15825
ricow@chromium.org83aa5492011-02-07 12:42:56 +000015826 // Make sure that pixel array ICs recognize when a non-pixel array
15827 // is passed to it.
15828 result = CompileRun("function pa_load(p) {"
15829 " var sum = 0;"
15830 " for (var j = 0; j < 256; j++) { sum += p[j]; }"
15831 " return sum;"
15832 "}"
15833 "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
15834 "for (var i = 0; i < 10; ++i) { pa_load(pixels); }"
15835 "just_ints = new Object();"
15836 "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
15837 "for (var i = 0; i < 10; ++i) {"
15838 " result = pa_load(just_ints);"
15839 "}"
15840 "result");
15841 CHECK_EQ(32640, result->Int32Value());
15842
15843 // Make sure that pixel array ICs recognize out-of-bound accesses.
15844 result = CompileRun("function pa_load(p, start) {"
15845 " var sum = 0;"
15846 " for (var j = start; j < 256; j++) { sum += p[j]; }"
15847 " return sum;"
15848 "}"
15849 "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
15850 "for (var i = 0; i < 10; ++i) { pa_load(pixels,0); }"
15851 "for (var i = 0; i < 10; ++i) {"
15852 " result = pa_load(pixels,-10);"
15853 "}"
15854 "result");
15855 CHECK_EQ(0, result->Int32Value());
15856
15857 // Make sure that generic ICs properly handles a pixel array.
15858 result = CompileRun("function pa_load(p) {"
15859 " var sum = 0;"
15860 " for (var j = 0; j < 256; j++) { sum += p[j]; }"
15861 " return sum;"
15862 "}"
15863 "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
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) { pa_load(just_ints); }"
15867 "for (var i = 0; i < 10; ++i) {"
15868 " result = pa_load(pixels);"
15869 "}"
15870 "result");
15871 CHECK_EQ(32640, result->Int32Value());
15872
15873 // Make sure that generic load ICs recognize out-of-bound accesses in
15874 // pixel arrays.
15875 result = CompileRun("function pa_load(p, start) {"
15876 " var sum = 0;"
15877 " for (var j = start; j < 256; j++) { sum += p[j]; }"
15878 " return sum;"
15879 "}"
15880 "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
15881 "just_ints = new Object();"
15882 "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
15883 "for (var i = 0; i < 10; ++i) { pa_load(just_ints,0); }"
15884 "for (var i = 0; i < 10; ++i) { pa_load(pixels,0); }"
15885 "for (var i = 0; i < 10; ++i) {"
15886 " result = pa_load(pixels,-10);"
15887 "}"
15888 "result");
15889 CHECK_EQ(0, result->Int32Value());
15890
15891 // Make sure that generic ICs properly handles other types than pixel
15892 // arrays (that the inlined fast pixel array test leaves the right information
15893 // in the right registers).
15894 result = CompileRun("function pa_load(p) {"
15895 " var sum = 0;"
15896 " for (var j = 0; j < 256; j++) { sum += p[j]; }"
15897 " return sum;"
15898 "}"
15899 "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
15900 "just_ints = new Object();"
15901 "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
15902 "for (var i = 0; i < 10; ++i) { pa_load(just_ints); }"
15903 "for (var i = 0; i < 10; ++i) { pa_load(pixels); }"
15904 "sparse_array = new Object();"
15905 "for (var i = 0; i < 256; ++i) { sparse_array[i] = i; }"
15906 "sparse_array[1000000] = 3;"
15907 "for (var i = 0; i < 10; ++i) {"
15908 " result = pa_load(sparse_array);"
15909 "}"
15910 "result");
15911 CHECK_EQ(32640, result->Int32Value());
15912
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +000015913 // Make sure that pixel array store ICs clamp values correctly.
15914 result = CompileRun("function pa_store(p) {"
15915 " for (var j = 0; j < 256; j++) { p[j] = j * 2; }"
15916 "}"
15917 "pa_store(pixels);"
15918 "var sum = 0;"
15919 "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
15920 "sum");
15921 CHECK_EQ(48896, result->Int32Value());
15922
15923 // Make sure that pixel array stores correctly handle accesses outside
15924 // of the pixel array..
15925 result = CompileRun("function pa_store(p,start) {"
15926 " for (var j = 0; j < 256; j++) {"
15927 " p[j+start] = j * 2;"
15928 " }"
15929 "}"
15930 "pa_store(pixels,0);"
15931 "pa_store(pixels,-128);"
15932 "var sum = 0;"
15933 "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
15934 "sum");
15935 CHECK_EQ(65280, result->Int32Value());
15936
15937 // Make sure that the generic store stub correctly handle accesses outside
15938 // of the pixel array..
15939 result = CompileRun("function pa_store(p,start) {"
15940 " for (var j = 0; j < 256; j++) {"
15941 " p[j+start] = j * 2;"
15942 " }"
15943 "}"
15944 "pa_store(pixels,0);"
15945 "just_ints = new Object();"
15946 "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
15947 "pa_store(just_ints, 0);"
15948 "pa_store(pixels,-128);"
15949 "var sum = 0;"
15950 "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
15951 "sum");
15952 CHECK_EQ(65280, result->Int32Value());
15953
15954 // Make sure that the generic keyed store stub clamps pixel array values
15955 // correctly.
15956 result = CompileRun("function pa_store(p) {"
15957 " for (var j = 0; j < 256; j++) { p[j] = j * 2; }"
15958 "}"
15959 "pa_store(pixels);"
15960 "just_ints = new Object();"
15961 "pa_store(just_ints);"
15962 "pa_store(pixels);"
15963 "var sum = 0;"
15964 "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
15965 "sum");
15966 CHECK_EQ(48896, result->Int32Value());
15967
15968 // Make sure that pixel array loads are optimized by crankshaft.
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000015969 result = CompileRun("function pa_load(p) {"
15970 " var sum = 0;"
15971 " for (var i=0; i<256; ++i) {"
15972 " sum += p[i];"
15973 " }"
15974 " return sum; "
15975 "}"
15976 "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000015977 "for (var i = 0; i < 5000; ++i) {"
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000015978 " result = pa_load(pixels);"
15979 "}"
15980 "result");
15981 CHECK_EQ(32640, result->Int32Value());
15982
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000015983 // Make sure that pixel array stores are optimized by crankshaft.
15984 result = CompileRun("function pa_init(p) {"
15985 "for (var i = 0; i < 256; ++i) { p[i] = i; }"
15986 "}"
15987 "function pa_load(p) {"
15988 " var sum = 0;"
15989 " for (var i=0; i<256; ++i) {"
15990 " sum += p[i];"
15991 " }"
15992 " return sum; "
15993 "}"
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000015994 "for (var i = 0; i < 5000; ++i) {"
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000015995 " pa_init(pixels);"
15996 "}"
15997 "result = pa_load(pixels);"
15998 "result");
15999 CHECK_EQ(32640, result->Int32Value());
16000
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000016001 free(pixel_data);
16002}
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000016003
ager@chromium.org96c75b52009-08-26 09:13:16 +000016004
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016005THREADED_TEST(PixelArrayInfo) {
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016006 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016007 v8::HandleScope scope(context->GetIsolate());
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016008 for (int size = 0; size < 100; size += 10) {
16009 uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(size));
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016010 v8::Handle<v8::Object> obj = v8::Object::New(context->GetIsolate());
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016011 obj->SetIndexedPropertiesToPixelData(pixel_data, size);
16012 CHECK(obj->HasIndexedPropertiesInPixelData());
16013 CHECK_EQ(pixel_data, obj->GetIndexedPropertiesPixelData());
16014 CHECK_EQ(size, obj->GetIndexedPropertiesPixelDataLength());
16015 free(pixel_data);
16016 }
16017}
16018
16019
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000016020static void NotHandledIndexedPropertyGetter(
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000016021 uint32_t index,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000016022 const v8::PropertyCallbackInfo<v8::Value>& info) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000016023 ApiTestFuzzer::Fuzz();
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000016024}
16025
16026
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000016027static void NotHandledIndexedPropertySetter(
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000016028 uint32_t index,
16029 Local<Value> value,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000016030 const v8::PropertyCallbackInfo<v8::Value>& info) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000016031 ApiTestFuzzer::Fuzz();
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000016032}
16033
16034
16035THREADED_TEST(PixelArrayWithInterceptor) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000016036 LocalContext context;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000016037 i::Factory* factory = CcTest::i_isolate()->factory();
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000016038 v8::Isolate* isolate = context->GetIsolate();
16039 v8::HandleScope scope(isolate);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000016040 const int kElementCount = 260;
16041 uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(kElementCount));
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000016042 i::Handle<i::ExternalPixelArray> pixels =
16043 i::Handle<i::ExternalPixelArray>::cast(
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000016044 factory->NewExternalArray(kElementCount,
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000016045 v8::kExternalPixelArray,
16046 pixel_data));
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000016047 for (int i = 0; i < kElementCount; i++) {
16048 pixels->set(i, i % 256);
16049 }
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000016050 v8::Handle<v8::ObjectTemplate> templ =
16051 v8::ObjectTemplate::New(context->GetIsolate());
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000016052 templ->SetIndexedPropertyHandler(NotHandledIndexedPropertyGetter,
16053 NotHandledIndexedPropertySetter);
16054 v8::Handle<v8::Object> obj = templ->NewInstance();
16055 obj->SetIndexedPropertiesToPixelData(pixel_data, kElementCount);
16056 context->Global()->Set(v8_str("pixels"), obj);
16057 v8::Handle<v8::Value> result = CompileRun("pixels[1]");
16058 CHECK_EQ(1, result->Int32Value());
16059 result = CompileRun("var sum = 0;"
16060 "for (var i = 0; i < 8; i++) {"
16061 " sum += pixels[i] = pixels[i] = -i;"
16062 "}"
16063 "sum;");
16064 CHECK_EQ(-28, result->Int32Value());
16065 result = CompileRun("pixels.hasOwnProperty('1')");
16066 CHECK(result->BooleanValue());
16067 free(pixel_data);
16068}
16069
16070
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016071static int ExternalArrayElementSize(v8::ExternalArrayType array_type) {
16072 switch (array_type) {
16073 case v8::kExternalByteArray:
16074 case v8::kExternalUnsignedByteArray:
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000016075 case v8::kExternalPixelArray:
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016076 return 1;
16077 break;
16078 case v8::kExternalShortArray:
16079 case v8::kExternalUnsignedShortArray:
16080 return 2;
16081 break;
16082 case v8::kExternalIntArray:
16083 case v8::kExternalUnsignedIntArray:
16084 case v8::kExternalFloatArray:
16085 return 4;
16086 break;
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +000016087 case v8::kExternalDoubleArray:
16088 return 8;
16089 break;
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016090 default:
16091 UNREACHABLE();
16092 return -1;
16093 }
16094 UNREACHABLE();
16095 return -1;
16096}
16097
16098
ager@chromium.org3811b432009-10-28 14:53:37 +000016099template <class ExternalArrayClass, class ElementType>
danno@chromium.orgf005df62013-04-30 16:36:45 +000016100static void ObjectWithExternalArrayTestHelper(
16101 Handle<Context> context,
16102 v8::Handle<Object> obj,
16103 int element_count,
16104 v8::ExternalArrayType array_type,
16105 int64_t low, int64_t high) {
ager@chromium.org3811b432009-10-28 14:53:37 +000016106 i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000016107 i::Isolate* isolate = jsobj->GetIsolate();
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016108 obj->Set(v8_str("field"),
16109 v8::Int32::New(reinterpret_cast<v8::Isolate*>(isolate), 1503));
ager@chromium.org3811b432009-10-28 14:53:37 +000016110 context->Global()->Set(v8_str("ext_array"), obj);
16111 v8::Handle<v8::Value> result = CompileRun("ext_array.field");
16112 CHECK_EQ(1503, result->Int32Value());
16113 result = CompileRun("ext_array[1]");
16114 CHECK_EQ(1, result->Int32Value());
16115
ager@chromium.org3811b432009-10-28 14:53:37 +000016116 // Check assigned smis
16117 result = CompileRun("for (var i = 0; i < 8; i++) {"
16118 " ext_array[i] = i;"
16119 "}"
16120 "var sum = 0;"
16121 "for (var i = 0; i < 8; i++) {"
16122 " sum += ext_array[i];"
16123 "}"
16124 "sum;");
machenbach@chromium.org5c88bc32014-01-17 08:10:36 +000016125
ager@chromium.org3811b432009-10-28 14:53:37 +000016126 CHECK_EQ(28, result->Int32Value());
machenbach@chromium.org5c88bc32014-01-17 08:10:36 +000016127 // Check pass through of assigned smis
16128 result = CompileRun("var sum = 0;"
16129 "for (var i = 0; i < 8; i++) {"
16130 " sum += ext_array[i] = ext_array[i] = -i;"
16131 "}"
16132 "sum;");
16133 CHECK_EQ(-28, result->Int32Value());
16134
ager@chromium.org3811b432009-10-28 14:53:37 +000016135
16136 // Check assigned smis in reverse order
16137 result = CompileRun("for (var i = 8; --i >= 0; ) {"
16138 " ext_array[i] = i;"
16139 "}"
16140 "var sum = 0;"
16141 "for (var i = 0; i < 8; i++) {"
16142 " sum += ext_array[i];"
16143 "}"
16144 "sum;");
16145 CHECK_EQ(28, result->Int32Value());
16146
16147 // Check pass through of assigned HeapNumbers
16148 result = CompileRun("var sum = 0;"
16149 "for (var i = 0; i < 16; i+=2) {"
16150 " sum += ext_array[i] = ext_array[i] = (-i * 0.5);"
16151 "}"
16152 "sum;");
16153 CHECK_EQ(-28, result->Int32Value());
16154
16155 // Check assigned HeapNumbers
16156 result = CompileRun("for (var i = 0; i < 16; i+=2) {"
16157 " ext_array[i] = (i * 0.5);"
16158 "}"
16159 "var sum = 0;"
16160 "for (var i = 0; i < 16; i+=2) {"
16161 " sum += ext_array[i];"
16162 "}"
16163 "sum;");
16164 CHECK_EQ(28, result->Int32Value());
16165
16166 // Check assigned HeapNumbers in reverse order
16167 result = CompileRun("for (var i = 14; i >= 0; i-=2) {"
16168 " ext_array[i] = (i * 0.5);"
16169 "}"
16170 "var sum = 0;"
16171 "for (var i = 0; i < 16; i+=2) {"
16172 " sum += ext_array[i];"
16173 "}"
16174 "sum;");
16175 CHECK_EQ(28, result->Int32Value());
16176
16177 i::ScopedVector<char> test_buf(1024);
16178
16179 // Check legal boundary conditions.
16180 // The repeated loads and stores ensure the ICs are exercised.
16181 const char* boundary_program =
16182 "var res = 0;"
16183 "for (var i = 0; i < 16; i++) {"
16184 " ext_array[i] = %lld;"
16185 " if (i > 8) {"
16186 " res = ext_array[i];"
16187 " }"
16188 "}"
16189 "res;";
16190 i::OS::SNPrintF(test_buf,
16191 boundary_program,
16192 low);
16193 result = CompileRun(test_buf.start());
16194 CHECK_EQ(low, result->IntegerValue());
16195
16196 i::OS::SNPrintF(test_buf,
16197 boundary_program,
16198 high);
16199 result = CompileRun(test_buf.start());
16200 CHECK_EQ(high, result->IntegerValue());
16201
16202 // Check misprediction of type in IC.
16203 result = CompileRun("var tmp_array = ext_array;"
16204 "var sum = 0;"
16205 "for (var i = 0; i < 8; i++) {"
16206 " tmp_array[i] = i;"
16207 " sum += tmp_array[i];"
16208 " if (i == 4) {"
16209 " tmp_array = {};"
16210 " }"
16211 "}"
16212 "sum;");
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000016213 // Force GC to trigger verification.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000016214 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org3811b432009-10-28 14:53:37 +000016215 CHECK_EQ(28, result->Int32Value());
16216
16217 // Make sure out-of-range loads do not throw.
16218 i::OS::SNPrintF(test_buf,
16219 "var caught_exception = false;"
16220 "try {"
16221 " ext_array[%d];"
16222 "} catch (e) {"
16223 " caught_exception = true;"
16224 "}"
16225 "caught_exception;",
danno@chromium.orgf005df62013-04-30 16:36:45 +000016226 element_count);
ager@chromium.org3811b432009-10-28 14:53:37 +000016227 result = CompileRun(test_buf.start());
16228 CHECK_EQ(false, result->BooleanValue());
16229
16230 // Make sure out-of-range stores do not throw.
16231 i::OS::SNPrintF(test_buf,
16232 "var caught_exception = false;"
16233 "try {"
16234 " ext_array[%d] = 1;"
16235 "} catch (e) {"
16236 " caught_exception = true;"
16237 "}"
16238 "caught_exception;",
danno@chromium.orgf005df62013-04-30 16:36:45 +000016239 element_count);
ager@chromium.org3811b432009-10-28 14:53:37 +000016240 result = CompileRun(test_buf.start());
16241 CHECK_EQ(false, result->BooleanValue());
16242
16243 // Check other boundary conditions, values and operations.
16244 result = CompileRun("for (var i = 0; i < 8; i++) {"
16245 " ext_array[7] = undefined;"
16246 "}"
16247 "ext_array[7];");
16248 CHECK_EQ(0, result->Int32Value());
yangguo@chromium.org56454712012-02-16 15:33:53 +000016249 if (array_type == v8::kExternalDoubleArray ||
16250 array_type == v8::kExternalFloatArray) {
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000016251 CHECK_EQ(static_cast<int>(i::OS::nan_value()),
16252 static_cast<int>(
16253 jsobj->GetElement(isolate, 7)->ToObjectChecked()->Number()));
yangguo@chromium.org56454712012-02-16 15:33:53 +000016254 } else {
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000016255 CheckElementValue(isolate, 0, jsobj, 7);
yangguo@chromium.org56454712012-02-16 15:33:53 +000016256 }
ager@chromium.org3811b432009-10-28 14:53:37 +000016257
16258 result = CompileRun("for (var i = 0; i < 8; i++) {"
16259 " ext_array[6] = '2.3';"
16260 "}"
16261 "ext_array[6];");
16262 CHECK_EQ(2, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000016263 CHECK_EQ(2,
16264 static_cast<int>(
16265 jsobj->GetElement(isolate, 6)->ToObjectChecked()->Number()));
ager@chromium.org3811b432009-10-28 14:53:37 +000016266
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +000016267 if (array_type != v8::kExternalFloatArray &&
16268 array_type != v8::kExternalDoubleArray) {
ager@chromium.org3811b432009-10-28 14:53:37 +000016269 // Though the specification doesn't state it, be explicit about
16270 // converting NaNs and +/-Infinity to zero.
16271 result = CompileRun("for (var i = 0; i < 8; i++) {"
16272 " ext_array[i] = 5;"
16273 "}"
16274 "for (var i = 0; i < 8; i++) {"
16275 " ext_array[i] = NaN;"
16276 "}"
16277 "ext_array[5];");
16278 CHECK_EQ(0, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000016279 CheckElementValue(isolate, 0, jsobj, 5);
ager@chromium.org3811b432009-10-28 14:53:37 +000016280
16281 result = CompileRun("for (var i = 0; i < 8; i++) {"
16282 " ext_array[i] = 5;"
16283 "}"
16284 "for (var i = 0; i < 8; i++) {"
16285 " ext_array[i] = Infinity;"
16286 "}"
16287 "ext_array[5];");
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000016288 int expected_value =
16289 (array_type == v8::kExternalPixelArray) ? 255 : 0;
16290 CHECK_EQ(expected_value, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000016291 CheckElementValue(isolate, expected_value, jsobj, 5);
ager@chromium.org3811b432009-10-28 14:53:37 +000016292
16293 result = CompileRun("for (var i = 0; i < 8; i++) {"
16294 " ext_array[i] = 5;"
16295 "}"
16296 "for (var i = 0; i < 8; i++) {"
16297 " ext_array[i] = -Infinity;"
16298 "}"
16299 "ext_array[5];");
16300 CHECK_EQ(0, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000016301 CheckElementValue(isolate, 0, jsobj, 5);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +000016302
16303 // Check truncation behavior of integral arrays.
16304 const char* unsigned_data =
16305 "var source_data = [0.6, 10.6];"
16306 "var expected_results = [0, 10];";
16307 const char* signed_data =
16308 "var source_data = [0.6, 10.6, -0.6, -10.6];"
16309 "var expected_results = [0, 10, 0, -10];";
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000016310 const char* pixel_data =
16311 "var source_data = [0.6, 10.6];"
16312 "var expected_results = [1, 11];";
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +000016313 bool is_unsigned =
16314 (array_type == v8::kExternalUnsignedByteArray ||
16315 array_type == v8::kExternalUnsignedShortArray ||
16316 array_type == v8::kExternalUnsignedIntArray);
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000016317 bool is_pixel_data = array_type == v8::kExternalPixelArray;
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +000016318
16319 i::OS::SNPrintF(test_buf,
16320 "%s"
16321 "var all_passed = true;"
16322 "for (var i = 0; i < source_data.length; i++) {"
16323 " for (var j = 0; j < 8; j++) {"
16324 " ext_array[j] = source_data[i];"
16325 " }"
16326 " all_passed = all_passed &&"
16327 " (ext_array[5] == expected_results[i]);"
16328 "}"
16329 "all_passed;",
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000016330 (is_unsigned ?
16331 unsigned_data :
16332 (is_pixel_data ? pixel_data : signed_data)));
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +000016333 result = CompileRun(test_buf.start());
16334 CHECK_EQ(true, result->BooleanValue());
ager@chromium.org3811b432009-10-28 14:53:37 +000016335 }
16336
danno@chromium.orgf005df62013-04-30 16:36:45 +000016337 i::Handle<ExternalArrayClass> array(
16338 ExternalArrayClass::cast(jsobj->elements()));
16339 for (int i = 0; i < element_count; i++) {
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000016340 array->set(i, static_cast<ElementType>(i));
16341 }
danno@chromium.orgf005df62013-04-30 16:36:45 +000016342
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000016343 // Test complex assignments
16344 result = CompileRun("function ee_op_test_complex_func(sum) {"
16345 " for (var i = 0; i < 40; ++i) {"
16346 " sum += (ext_array[i] += 1);"
16347 " sum += (ext_array[i] -= 1);"
16348 " } "
16349 " return sum;"
16350 "}"
16351 "sum=0;"
16352 "for (var i=0;i<10000;++i) {"
16353 " sum=ee_op_test_complex_func(sum);"
16354 "}"
16355 "sum;");
16356 CHECK_EQ(16000000, result->Int32Value());
16357
16358 // Test count operations
16359 result = CompileRun("function ee_op_test_count_func(sum) {"
16360 " for (var i = 0; i < 40; ++i) {"
16361 " sum += (++ext_array[i]);"
16362 " sum += (--ext_array[i]);"
16363 " } "
16364 " return sum;"
16365 "}"
16366 "sum=0;"
16367 "for (var i=0;i<10000;++i) {"
16368 " sum=ee_op_test_count_func(sum);"
16369 "}"
16370 "sum;");
16371 CHECK_EQ(16000000, result->Int32Value());
16372
ager@chromium.org3811b432009-10-28 14:53:37 +000016373 result = CompileRun("ext_array[3] = 33;"
16374 "delete ext_array[3];"
16375 "ext_array[3];");
16376 CHECK_EQ(33, result->Int32Value());
16377
16378 result = CompileRun("ext_array[0] = 10; ext_array[1] = 11;"
16379 "ext_array[2] = 12; ext_array[3] = 13;"
16380 "ext_array.__defineGetter__('2',"
16381 "function() { return 120; });"
16382 "ext_array[2];");
16383 CHECK_EQ(12, result->Int32Value());
16384
16385 result = CompileRun("var js_array = new Array(40);"
16386 "js_array[0] = 77;"
16387 "js_array;");
16388 CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
16389
16390 result = CompileRun("ext_array[1] = 23;"
16391 "ext_array.__proto__ = [];"
16392 "js_array.__proto__ = ext_array;"
16393 "js_array.concat(ext_array);");
16394 CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
16395 CHECK_EQ(23, v8::Object::Cast(*result)->Get(v8_str("1"))->Int32Value());
16396
16397 result = CompileRun("ext_array[1] = 23;");
16398 CHECK_EQ(23, result->Int32Value());
danno@chromium.orgf005df62013-04-30 16:36:45 +000016399}
16400
16401
machenbach@chromium.org5c88bc32014-01-17 08:10:36 +000016402template <class FixedTypedArrayClass,
16403 i::ElementsKind elements_kind,
16404 class ElementType>
16405static void FixedTypedArrayTestHelper(
16406 v8::ExternalArrayType array_type,
16407 ElementType low,
16408 ElementType high) {
16409 i::FLAG_allow_natives_syntax = true;
16410 LocalContext context;
16411 i::Isolate* isolate = CcTest::i_isolate();
16412 i::Factory* factory = isolate->factory();
16413 v8::HandleScope scope(context->GetIsolate());
16414 const int kElementCount = 260;
16415 i::Handle<FixedTypedArrayClass> fixed_array =
16416 i::Handle<FixedTypedArrayClass>::cast(
16417 factory->NewFixedTypedArray(kElementCount, array_type));
16418 CHECK_EQ(FixedTypedArrayClass::kInstanceType,
16419 fixed_array->map()->instance_type());
16420 CHECK_EQ(kElementCount, fixed_array->length());
16421 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
16422 for (int i = 0; i < kElementCount; i++) {
16423 fixed_array->set(i, static_cast<ElementType>(i));
16424 }
16425 // Force GC to trigger verification.
16426 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
16427 for (int i = 0; i < kElementCount; i++) {
16428 CHECK_EQ(static_cast<int64_t>(static_cast<ElementType>(i)),
16429 static_cast<int64_t>(fixed_array->get_scalar(i)));
16430 }
16431 v8::Handle<v8::Object> obj = v8::Object::New(CcTest::isolate());
16432 i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
16433 i::Handle<i::Map> fixed_array_map =
16434 isolate->factory()->GetElementsTransitionMap(jsobj, elements_kind);
16435 jsobj->set_map(*fixed_array_map);
16436 jsobj->set_elements(*fixed_array);
16437
16438 ObjectWithExternalArrayTestHelper<FixedTypedArrayClass, ElementType>(
16439 context.local(), obj, kElementCount, array_type,
16440 static_cast<int64_t>(low),
16441 static_cast<int64_t>(high));
16442}
16443
16444
16445THREADED_TEST(FixedUint8Array) {
16446 FixedTypedArrayTestHelper<i::FixedUint8Array, i::UINT8_ELEMENTS, uint8_t>(
16447 v8::kExternalUnsignedByteArray,
16448 0x0, 0xFF);
16449}
16450
16451
16452THREADED_TEST(FixedUint8ClampedArray) {
16453 FixedTypedArrayTestHelper<i::FixedUint8ClampedArray,
16454 i::UINT8_CLAMPED_ELEMENTS, uint8_t>(
16455 v8::kExternalPixelArray,
16456 0x0, 0xFF);
16457}
16458
16459
16460THREADED_TEST(FixedInt8Array) {
16461 FixedTypedArrayTestHelper<i::FixedInt8Array, i::INT8_ELEMENTS, int8_t>(
16462 v8::kExternalByteArray,
16463 -0x80, 0x7F);
16464}
16465
16466
16467THREADED_TEST(FixedUint16Array) {
16468 FixedTypedArrayTestHelper<i::FixedUint16Array, i::UINT16_ELEMENTS, uint16_t>(
16469 v8::kExternalUnsignedShortArray,
16470 0x0, 0xFFFF);
16471}
16472
16473
16474THREADED_TEST(FixedInt16Array) {
16475 FixedTypedArrayTestHelper<i::FixedInt16Array, i::INT16_ELEMENTS, int16_t>(
16476 v8::kExternalShortArray,
16477 -0x8000, 0x7FFF);
16478}
16479
16480
16481THREADED_TEST(FixedUint32Array) {
16482 FixedTypedArrayTestHelper<i::FixedUint32Array, i::UINT32_ELEMENTS, uint32_t>(
16483 v8::kExternalUnsignedIntArray,
16484 0x0, UINT_MAX);
16485}
16486
16487
16488THREADED_TEST(FixedInt32Array) {
16489 FixedTypedArrayTestHelper<i::FixedInt32Array, i::INT32_ELEMENTS, int32_t>(
16490 v8::kExternalIntArray,
16491 INT_MIN, INT_MAX);
16492}
16493
16494
16495THREADED_TEST(FixedFloat32Array) {
16496 FixedTypedArrayTestHelper<i::FixedFloat32Array, i::FLOAT32_ELEMENTS, float>(
16497 v8::kExternalFloatArray,
16498 -500, 500);
16499}
16500
16501
16502THREADED_TEST(FixedFloat64Array) {
16503 FixedTypedArrayTestHelper<i::FixedFloat64Array, i::FLOAT64_ELEMENTS, float>(
16504 v8::kExternalDoubleArray,
16505 -500, 500);
16506}
16507
16508
danno@chromium.orgf005df62013-04-30 16:36:45 +000016509template <class ExternalArrayClass, class ElementType>
16510static void ExternalArrayTestHelper(v8::ExternalArrayType array_type,
16511 int64_t low,
16512 int64_t high) {
16513 LocalContext context;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000016514 i::Isolate* isolate = CcTest::i_isolate();
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000016515 i::Factory* factory = isolate->factory();
danno@chromium.orgf005df62013-04-30 16:36:45 +000016516 v8::HandleScope scope(context->GetIsolate());
16517 const int kElementCount = 40;
16518 int element_size = ExternalArrayElementSize(array_type);
16519 ElementType* array_data =
16520 static_cast<ElementType*>(malloc(kElementCount * element_size));
16521 i::Handle<ExternalArrayClass> array =
16522 i::Handle<ExternalArrayClass>::cast(
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000016523 factory->NewExternalArray(kElementCount, array_type, array_data));
danno@chromium.orgf005df62013-04-30 16:36:45 +000016524 // Force GC to trigger verification.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000016525 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
danno@chromium.orgf005df62013-04-30 16:36:45 +000016526 for (int i = 0; i < kElementCount; i++) {
16527 array->set(i, static_cast<ElementType>(i));
16528 }
16529 // Force GC to trigger verification.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000016530 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
danno@chromium.orgf005df62013-04-30 16:36:45 +000016531 for (int i = 0; i < kElementCount; i++) {
16532 CHECK_EQ(static_cast<int64_t>(i),
16533 static_cast<int64_t>(array->get_scalar(i)));
16534 CHECK_EQ(static_cast<int64_t>(i), static_cast<int64_t>(array_data[i]));
16535 }
16536
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016537 v8::Handle<v8::Object> obj = v8::Object::New(context->GetIsolate());
danno@chromium.orgf005df62013-04-30 16:36:45 +000016538 i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
16539 // Set the elements to be the external array.
16540 obj->SetIndexedPropertiesToExternalArrayData(array_data,
16541 array_type,
16542 kElementCount);
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000016543 CHECK_EQ(1,
16544 static_cast<int>(
16545 jsobj->GetElement(isolate, 1)->ToObjectChecked()->Number()));
danno@chromium.orgf005df62013-04-30 16:36:45 +000016546
16547 ObjectWithExternalArrayTestHelper<ExternalArrayClass, ElementType>(
16548 context.local(), obj, kElementCount, array_type, low, high);
16549
16550 v8::Handle<v8::Value> result;
ager@chromium.org3811b432009-10-28 14:53:37 +000016551
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +000016552 // Test more complex manipulations which cause eax to contain values
16553 // that won't be completely overwritten by loads from the arrays.
16554 // This catches bugs in the instructions used for the KeyedLoadIC
16555 // for byte and word types.
16556 {
16557 const int kXSize = 300;
16558 const int kYSize = 300;
16559 const int kLargeElementCount = kXSize * kYSize * 4;
16560 ElementType* large_array_data =
16561 static_cast<ElementType*>(malloc(kLargeElementCount * element_size));
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016562 v8::Handle<v8::Object> large_obj = v8::Object::New(context->GetIsolate());
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +000016563 // Set the elements to be the external array.
16564 large_obj->SetIndexedPropertiesToExternalArrayData(large_array_data,
16565 array_type,
16566 kLargeElementCount);
16567 context->Global()->Set(v8_str("large_array"), large_obj);
16568 // Initialize contents of a few rows.
16569 for (int x = 0; x < 300; x++) {
16570 int row = 0;
16571 int offset = row * 300 * 4;
16572 large_array_data[offset + 4 * x + 0] = (ElementType) 127;
16573 large_array_data[offset + 4 * x + 1] = (ElementType) 0;
16574 large_array_data[offset + 4 * x + 2] = (ElementType) 0;
16575 large_array_data[offset + 4 * x + 3] = (ElementType) 127;
16576 row = 150;
16577 offset = row * 300 * 4;
16578 large_array_data[offset + 4 * x + 0] = (ElementType) 127;
16579 large_array_data[offset + 4 * x + 1] = (ElementType) 0;
16580 large_array_data[offset + 4 * x + 2] = (ElementType) 0;
16581 large_array_data[offset + 4 * x + 3] = (ElementType) 127;
16582 row = 298;
16583 offset = row * 300 * 4;
16584 large_array_data[offset + 4 * x + 0] = (ElementType) 127;
16585 large_array_data[offset + 4 * x + 1] = (ElementType) 0;
16586 large_array_data[offset + 4 * x + 2] = (ElementType) 0;
16587 large_array_data[offset + 4 * x + 3] = (ElementType) 127;
16588 }
16589 // The goal of the code below is to make "offset" large enough
16590 // that the computation of the index (which goes into eax) has
16591 // high bits set which will not be overwritten by a byte or short
16592 // load.
16593 result = CompileRun("var failed = false;"
16594 "var offset = 0;"
16595 "for (var i = 0; i < 300; i++) {"
16596 " if (large_array[4 * i] != 127 ||"
16597 " large_array[4 * i + 1] != 0 ||"
16598 " large_array[4 * i + 2] != 0 ||"
16599 " large_array[4 * i + 3] != 127) {"
16600 " failed = true;"
16601 " }"
16602 "}"
16603 "offset = 150 * 300 * 4;"
16604 "for (var i = 0; i < 300; i++) {"
16605 " if (large_array[offset + 4 * i] != 127 ||"
16606 " large_array[offset + 4 * i + 1] != 0 ||"
16607 " large_array[offset + 4 * i + 2] != 0 ||"
16608 " large_array[offset + 4 * i + 3] != 127) {"
16609 " failed = true;"
16610 " }"
16611 "}"
16612 "offset = 298 * 300 * 4;"
16613 "for (var i = 0; i < 300; i++) {"
16614 " if (large_array[offset + 4 * i] != 127 ||"
16615 " large_array[offset + 4 * i + 1] != 0 ||"
16616 " large_array[offset + 4 * i + 2] != 0 ||"
16617 " large_array[offset + 4 * i + 3] != 127) {"
16618 " failed = true;"
16619 " }"
16620 "}"
16621 "!failed;");
16622 CHECK_EQ(true, result->BooleanValue());
16623 free(large_array_data);
16624 }
16625
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016626 // The "" property descriptor is overloaded to store information about
16627 // the external array. Ensure that setting and accessing the "" property
16628 // works (it should overwrite the information cached about the external
16629 // array in the DescriptorArray) in various situations.
16630 result = CompileRun("ext_array[''] = 23; ext_array['']");
16631 CHECK_EQ(23, result->Int32Value());
16632
16633 // Property "" set after the external array is associated with the object.
16634 {
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_field"),
16637 v8::Int32::New(context->GetIsolate(), 256));
16638 obj2->Set(v8_str(""), v8::Int32::New(context->GetIsolate(), 1503));
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016639 // Set the elements to be the external array.
16640 obj2->SetIndexedPropertiesToExternalArrayData(array_data,
16641 array_type,
16642 kElementCount);
16643 context->Global()->Set(v8_str("ext_array"), obj2);
16644 result = CompileRun("ext_array['']");
16645 CHECK_EQ(1503, result->Int32Value());
16646 }
16647
16648 // Property "" set after the external array is associated with the object.
16649 {
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016650 v8::Handle<v8::Object> obj2 = v8::Object::New(context->GetIsolate());
16651 obj2->Set(v8_str("ee_test_field_2"),
16652 v8::Int32::New(context->GetIsolate(), 256));
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016653 // Set the elements to be the external array.
16654 obj2->SetIndexedPropertiesToExternalArrayData(array_data,
16655 array_type,
16656 kElementCount);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016657 obj2->Set(v8_str(""), v8::Int32::New(context->GetIsolate(), 1503));
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016658 context->Global()->Set(v8_str("ext_array"), obj2);
16659 result = CompileRun("ext_array['']");
16660 CHECK_EQ(1503, result->Int32Value());
16661 }
16662
16663 // Should reuse the map from previous test.
16664 {
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016665 v8::Handle<v8::Object> obj2 = v8::Object::New(context->GetIsolate());
16666 obj2->Set(v8_str("ee_test_field_2"),
16667 v8::Int32::New(context->GetIsolate(), 256));
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016668 // Set the elements to be the external array. Should re-use the map
16669 // from previous test.
16670 obj2->SetIndexedPropertiesToExternalArrayData(array_data,
16671 array_type,
16672 kElementCount);
16673 context->Global()->Set(v8_str("ext_array"), obj2);
16674 result = CompileRun("ext_array['']");
16675 }
16676
16677 // Property "" is a constant function that shouldn't not be interfered with
16678 // when an external array is set.
16679 {
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016680 v8::Handle<v8::Object> obj2 = v8::Object::New(context->GetIsolate());
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016681 // Start
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016682 obj2->Set(v8_str("ee_test_field3"),
16683 v8::Int32::New(context->GetIsolate(), 256));
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016684
16685 // Add a constant function to an object.
16686 context->Global()->Set(v8_str("ext_array"), obj2);
16687 result = CompileRun("ext_array[''] = function() {return 1503;};"
16688 "ext_array['']();");
16689
16690 // Add an external array transition to the same map that
16691 // has the constant transition.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016692 v8::Handle<v8::Object> obj3 = v8::Object::New(context->GetIsolate());
16693 obj3->Set(v8_str("ee_test_field3"),
16694 v8::Int32::New(context->GetIsolate(), 256));
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016695 obj3->SetIndexedPropertiesToExternalArrayData(array_data,
16696 array_type,
16697 kElementCount);
16698 context->Global()->Set(v8_str("ext_array"), obj3);
16699 }
16700
16701 // If a external array transition is in the map, it should get clobbered
16702 // by a constant function.
16703 {
16704 // Add an external array transition.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016705 v8::Handle<v8::Object> obj3 = v8::Object::New(context->GetIsolate());
16706 obj3->Set(v8_str("ee_test_field4"),
16707 v8::Int32::New(context->GetIsolate(), 256));
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016708 obj3->SetIndexedPropertiesToExternalArrayData(array_data,
16709 array_type,
16710 kElementCount);
16711
16712 // Add a constant function to the same map that just got an external array
16713 // transition.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016714 v8::Handle<v8::Object> obj2 = v8::Object::New(context->GetIsolate());
16715 obj2->Set(v8_str("ee_test_field4"),
16716 v8::Int32::New(context->GetIsolate(), 256));
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016717 context->Global()->Set(v8_str("ext_array"), obj2);
16718 result = CompileRun("ext_array[''] = function() {return 1503;};"
16719 "ext_array['']();");
16720 }
16721
ager@chromium.org3811b432009-10-28 14:53:37 +000016722 free(array_data);
16723}
16724
16725
16726THREADED_TEST(ExternalByteArray) {
lrn@chromium.org32d961d2010-06-30 09:09:34 +000016727 ExternalArrayTestHelper<i::ExternalByteArray, int8_t>(
ager@chromium.org3811b432009-10-28 14:53:37 +000016728 v8::kExternalByteArray,
16729 -128,
16730 127);
16731}
16732
16733
16734THREADED_TEST(ExternalUnsignedByteArray) {
lrn@chromium.org32d961d2010-06-30 09:09:34 +000016735 ExternalArrayTestHelper<i::ExternalUnsignedByteArray, uint8_t>(
ager@chromium.org3811b432009-10-28 14:53:37 +000016736 v8::kExternalUnsignedByteArray,
16737 0,
16738 255);
16739}
16740
16741
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000016742THREADED_TEST(ExternalPixelArray) {
16743 ExternalArrayTestHelper<i::ExternalPixelArray, uint8_t>(
16744 v8::kExternalPixelArray,
16745 0,
16746 255);
16747}
16748
16749
ager@chromium.org3811b432009-10-28 14:53:37 +000016750THREADED_TEST(ExternalShortArray) {
lrn@chromium.org32d961d2010-06-30 09:09:34 +000016751 ExternalArrayTestHelper<i::ExternalShortArray, int16_t>(
ager@chromium.org3811b432009-10-28 14:53:37 +000016752 v8::kExternalShortArray,
16753 -32768,
16754 32767);
16755}
16756
16757
16758THREADED_TEST(ExternalUnsignedShortArray) {
lrn@chromium.org32d961d2010-06-30 09:09:34 +000016759 ExternalArrayTestHelper<i::ExternalUnsignedShortArray, uint16_t>(
ager@chromium.org3811b432009-10-28 14:53:37 +000016760 v8::kExternalUnsignedShortArray,
16761 0,
16762 65535);
16763}
16764
16765
16766THREADED_TEST(ExternalIntArray) {
lrn@chromium.org32d961d2010-06-30 09:09:34 +000016767 ExternalArrayTestHelper<i::ExternalIntArray, int32_t>(
ager@chromium.org3811b432009-10-28 14:53:37 +000016768 v8::kExternalIntArray,
16769 INT_MIN, // -2147483648
16770 INT_MAX); // 2147483647
16771}
16772
16773
16774THREADED_TEST(ExternalUnsignedIntArray) {
lrn@chromium.org32d961d2010-06-30 09:09:34 +000016775 ExternalArrayTestHelper<i::ExternalUnsignedIntArray, uint32_t>(
ager@chromium.org3811b432009-10-28 14:53:37 +000016776 v8::kExternalUnsignedIntArray,
16777 0,
16778 UINT_MAX); // 4294967295
16779}
16780
16781
16782THREADED_TEST(ExternalFloatArray) {
lrn@chromium.org32d961d2010-06-30 09:09:34 +000016783 ExternalArrayTestHelper<i::ExternalFloatArray, float>(
ager@chromium.org3811b432009-10-28 14:53:37 +000016784 v8::kExternalFloatArray,
16785 -500,
16786 500);
16787}
16788
16789
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +000016790THREADED_TEST(ExternalDoubleArray) {
16791 ExternalArrayTestHelper<i::ExternalDoubleArray, double>(
16792 v8::kExternalDoubleArray,
16793 -500,
16794 500);
16795}
16796
16797
ager@chromium.org3811b432009-10-28 14:53:37 +000016798THREADED_TEST(ExternalArrays) {
16799 TestExternalByteArray();
16800 TestExternalUnsignedByteArray();
16801 TestExternalShortArray();
16802 TestExternalUnsignedShortArray();
16803 TestExternalIntArray();
16804 TestExternalUnsignedIntArray();
16805 TestExternalFloatArray();
16806}
16807
16808
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016809void ExternalArrayInfoTestHelper(v8::ExternalArrayType array_type) {
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016810 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016811 v8::HandleScope scope(context->GetIsolate());
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016812 for (int size = 0; size < 100; size += 10) {
16813 int element_size = ExternalArrayElementSize(array_type);
16814 void* external_data = malloc(size * element_size);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016815 v8::Handle<v8::Object> obj = v8::Object::New(context->GetIsolate());
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016816 obj->SetIndexedPropertiesToExternalArrayData(
16817 external_data, array_type, size);
16818 CHECK(obj->HasIndexedPropertiesInExternalArrayData());
16819 CHECK_EQ(external_data, obj->GetIndexedPropertiesExternalArrayData());
16820 CHECK_EQ(array_type, obj->GetIndexedPropertiesExternalArrayDataType());
16821 CHECK_EQ(size, obj->GetIndexedPropertiesExternalArrayDataLength());
16822 free(external_data);
16823 }
16824}
16825
16826
16827THREADED_TEST(ExternalArrayInfo) {
16828 ExternalArrayInfoTestHelper(v8::kExternalByteArray);
16829 ExternalArrayInfoTestHelper(v8::kExternalUnsignedByteArray);
16830 ExternalArrayInfoTestHelper(v8::kExternalShortArray);
16831 ExternalArrayInfoTestHelper(v8::kExternalUnsignedShortArray);
16832 ExternalArrayInfoTestHelper(v8::kExternalIntArray);
16833 ExternalArrayInfoTestHelper(v8::kExternalUnsignedIntArray);
16834 ExternalArrayInfoTestHelper(v8::kExternalFloatArray);
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +000016835 ExternalArrayInfoTestHelper(v8::kExternalDoubleArray);
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000016836 ExternalArrayInfoTestHelper(v8::kExternalPixelArray);
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016837}
16838
16839
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016840void ExtArrayLimitsHelper(v8::Isolate* isolate,
16841 v8::ExternalArrayType array_type,
16842 int size) {
16843 v8::Handle<v8::Object> obj = v8::Object::New(isolate);
danno@chromium.org412fa512012-09-14 13:28:26 +000016844 v8::V8::SetFatalErrorHandler(StoringErrorCallback);
16845 last_location = last_message = NULL;
16846 obj->SetIndexedPropertiesToExternalArrayData(NULL, array_type, size);
16847 CHECK(!obj->HasIndexedPropertiesInExternalArrayData());
16848 CHECK_NE(NULL, last_location);
16849 CHECK_NE(NULL, last_message);
16850}
16851
16852
16853TEST(ExternalArrayLimits) {
danno@chromium.org412fa512012-09-14 13:28:26 +000016854 LocalContext context;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016855 v8::Isolate* isolate = context->GetIsolate();
16856 v8::HandleScope scope(isolate);
16857 ExtArrayLimitsHelper(isolate, v8::kExternalByteArray, 0x40000000);
16858 ExtArrayLimitsHelper(isolate, v8::kExternalByteArray, 0xffffffff);
16859 ExtArrayLimitsHelper(isolate, v8::kExternalUnsignedByteArray, 0x40000000);
16860 ExtArrayLimitsHelper(isolate, v8::kExternalUnsignedByteArray, 0xffffffff);
16861 ExtArrayLimitsHelper(isolate, v8::kExternalShortArray, 0x40000000);
16862 ExtArrayLimitsHelper(isolate, v8::kExternalShortArray, 0xffffffff);
16863 ExtArrayLimitsHelper(isolate, v8::kExternalUnsignedShortArray, 0x40000000);
16864 ExtArrayLimitsHelper(isolate, v8::kExternalUnsignedShortArray, 0xffffffff);
16865 ExtArrayLimitsHelper(isolate, v8::kExternalIntArray, 0x40000000);
16866 ExtArrayLimitsHelper(isolate, v8::kExternalIntArray, 0xffffffff);
16867 ExtArrayLimitsHelper(isolate, v8::kExternalUnsignedIntArray, 0x40000000);
16868 ExtArrayLimitsHelper(isolate, v8::kExternalUnsignedIntArray, 0xffffffff);
16869 ExtArrayLimitsHelper(isolate, v8::kExternalFloatArray, 0x40000000);
16870 ExtArrayLimitsHelper(isolate, v8::kExternalFloatArray, 0xffffffff);
16871 ExtArrayLimitsHelper(isolate, v8::kExternalDoubleArray, 0x40000000);
16872 ExtArrayLimitsHelper(isolate, v8::kExternalDoubleArray, 0xffffffff);
16873 ExtArrayLimitsHelper(isolate, v8::kExternalPixelArray, 0x40000000);
16874 ExtArrayLimitsHelper(isolate, v8::kExternalPixelArray, 0xffffffff);
danno@chromium.org412fa512012-09-14 13:28:26 +000016875}
16876
16877
danno@chromium.orgf005df62013-04-30 16:36:45 +000016878template <typename ElementType, typename TypedArray,
16879 class ExternalArrayClass>
16880void TypedArrayTestHelper(v8::ExternalArrayType array_type,
16881 int64_t low, int64_t high) {
16882 const int kElementCount = 50;
danno@chromium.orgf005df62013-04-30 16:36:45 +000016883
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +000016884 i::ScopedVector<ElementType> backing_store(kElementCount+2);
16885
danno@chromium.orgf005df62013-04-30 16:36:45 +000016886 LocalContext env;
16887 v8::Isolate* isolate = env->GetIsolate();
16888 v8::HandleScope handle_scope(isolate);
16889
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000016890 Local<v8::ArrayBuffer> ab =
16891 v8::ArrayBuffer::New(isolate, backing_store.start(),
16892 (kElementCount + 2) * sizeof(ElementType));
danno@chromium.orgf005df62013-04-30 16:36:45 +000016893 Local<TypedArray> ta =
16894 TypedArray::New(ab, 2*sizeof(ElementType), kElementCount);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000016895 CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
danno@chromium.orgf005df62013-04-30 16:36:45 +000016896 CHECK_EQ(kElementCount, static_cast<int>(ta->Length()));
16897 CHECK_EQ(2*sizeof(ElementType), static_cast<int>(ta->ByteOffset()));
16898 CHECK_EQ(kElementCount*sizeof(ElementType),
16899 static_cast<int>(ta->ByteLength()));
16900 CHECK_EQ(ab, ta->Buffer());
16901
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +000016902 ElementType* data = backing_store.start() + 2;
danno@chromium.orgf005df62013-04-30 16:36:45 +000016903 for (int i = 0; i < kElementCount; i++) {
16904 data[i] = static_cast<ElementType>(i);
16905 }
16906
16907 ObjectWithExternalArrayTestHelper<ExternalArrayClass, ElementType>(
16908 env.local(), ta, kElementCount, array_type, low, high);
16909}
16910
16911
16912THREADED_TEST(Uint8Array) {
16913 TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::ExternalUnsignedByteArray>(
16914 v8::kExternalUnsignedByteArray, 0, 0xFF);
16915}
16916
16917
16918THREADED_TEST(Int8Array) {
16919 TypedArrayTestHelper<int8_t, v8::Int8Array, i::ExternalByteArray>(
16920 v8::kExternalByteArray, -0x80, 0x7F);
16921}
16922
16923
16924THREADED_TEST(Uint16Array) {
16925 TypedArrayTestHelper<uint16_t,
16926 v8::Uint16Array,
16927 i::ExternalUnsignedShortArray>(
16928 v8::kExternalUnsignedShortArray, 0, 0xFFFF);
16929}
16930
16931
16932THREADED_TEST(Int16Array) {
16933 TypedArrayTestHelper<int16_t, v8::Int16Array, i::ExternalShortArray>(
16934 v8::kExternalShortArray, -0x8000, 0x7FFF);
16935}
16936
16937
16938THREADED_TEST(Uint32Array) {
16939 TypedArrayTestHelper<uint32_t, v8::Uint32Array, i::ExternalUnsignedIntArray>(
16940 v8::kExternalUnsignedIntArray, 0, UINT_MAX);
16941}
16942
16943
16944THREADED_TEST(Int32Array) {
16945 TypedArrayTestHelper<int32_t, v8::Int32Array, i::ExternalIntArray>(
16946 v8::kExternalIntArray, INT_MIN, INT_MAX);
16947}
16948
16949
16950THREADED_TEST(Float32Array) {
16951 TypedArrayTestHelper<float, v8::Float32Array, i::ExternalFloatArray>(
16952 v8::kExternalFloatArray, -500, 500);
16953}
16954
16955
16956THREADED_TEST(Float64Array) {
16957 TypedArrayTestHelper<double, v8::Float64Array, i::ExternalDoubleArray>(
16958 v8::kExternalDoubleArray, -500, 500);
16959}
16960
16961
ulan@chromium.org57ff8812013-05-10 08:16:55 +000016962THREADED_TEST(Uint8ClampedArray) {
16963 TypedArrayTestHelper<uint8_t, v8::Uint8ClampedArray, i::ExternalPixelArray>(
16964 v8::kExternalPixelArray, 0, 0xFF);
16965}
16966
16967
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000016968THREADED_TEST(DataView) {
16969 const int kSize = 50;
16970
16971 i::ScopedVector<uint8_t> backing_store(kSize+2);
16972
16973 LocalContext env;
16974 v8::Isolate* isolate = env->GetIsolate();
16975 v8::HandleScope handle_scope(isolate);
16976
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000016977 Local<v8::ArrayBuffer> ab =
16978 v8::ArrayBuffer::New(isolate, backing_store.start(), 2 + kSize);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000016979 Local<v8::DataView> dv =
16980 v8::DataView::New(ab, 2, kSize);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000016981 CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000016982 CHECK_EQ(2, static_cast<int>(dv->ByteOffset()));
16983 CHECK_EQ(kSize, static_cast<int>(dv->ByteLength()));
16984 CHECK_EQ(ab, dv->Buffer());
16985}
16986
16987
16988#define IS_ARRAY_BUFFER_VIEW_TEST(View) \
16989 THREADED_TEST(Is##View) { \
ulan@chromium.org57ff8812013-05-10 08:16:55 +000016990 LocalContext env; \
16991 v8::Isolate* isolate = env->GetIsolate(); \
16992 v8::HandleScope handle_scope(isolate); \
16993 \
16994 Handle<Value> result = CompileRun( \
16995 "var ab = new ArrayBuffer(128);" \
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000016996 "new " #View "(ab)"); \
16997 CHECK(result->IsArrayBufferView()); \
16998 CHECK(result->Is##View()); \
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000016999 CheckInternalFieldsAreZero<v8::ArrayBufferView>(result.As<v8::View>()); \
ulan@chromium.org57ff8812013-05-10 08:16:55 +000017000 }
17001
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017002IS_ARRAY_BUFFER_VIEW_TEST(Uint8Array)
17003IS_ARRAY_BUFFER_VIEW_TEST(Int8Array)
17004IS_ARRAY_BUFFER_VIEW_TEST(Uint16Array)
17005IS_ARRAY_BUFFER_VIEW_TEST(Int16Array)
17006IS_ARRAY_BUFFER_VIEW_TEST(Uint32Array)
17007IS_ARRAY_BUFFER_VIEW_TEST(Int32Array)
17008IS_ARRAY_BUFFER_VIEW_TEST(Float32Array)
17009IS_ARRAY_BUFFER_VIEW_TEST(Float64Array)
17010IS_ARRAY_BUFFER_VIEW_TEST(Uint8ClampedArray)
17011IS_ARRAY_BUFFER_VIEW_TEST(DataView)
ulan@chromium.org57ff8812013-05-10 08:16:55 +000017012
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017013#undef IS_ARRAY_BUFFER_VIEW_TEST
ulan@chromium.org57ff8812013-05-10 08:16:55 +000017014
17015
17016
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000017017THREADED_TEST(ScriptContextDependence) {
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000017018 LocalContext c1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017019 v8::HandleScope scope(c1->GetIsolate());
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000017020 const char *source = "foo";
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017021 v8::Handle<v8::Script> dep =
17022 v8::Script::Compile(v8::String::NewFromUtf8(c1->GetIsolate(), source));
17023 v8::Handle<v8::Script> indep =
17024 v8::Script::New(v8::String::NewFromUtf8(c1->GetIsolate(), source));
17025 c1->Global()->Set(v8::String::NewFromUtf8(c1->GetIsolate(), "foo"),
ulan@chromium.org0f13e742014-01-03 15:51:11 +000017026 v8::Integer::New(c1->GetIsolate(), 100));
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000017027 CHECK_EQ(dep->Run()->Int32Value(), 100);
17028 CHECK_EQ(indep->Run()->Int32Value(), 100);
17029 LocalContext c2;
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017030 c2->Global()->Set(v8::String::NewFromUtf8(c2->GetIsolate(), "foo"),
ulan@chromium.org0f13e742014-01-03 15:51:11 +000017031 v8::Integer::New(c2->GetIsolate(), 101));
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000017032 CHECK_EQ(dep->Run()->Int32Value(), 100);
17033 CHECK_EQ(indep->Run()->Int32Value(), 101);
17034}
17035
ager@chromium.org96c75b52009-08-26 09:13:16 +000017036
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000017037THREADED_TEST(StackTrace) {
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000017038 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017039 v8::HandleScope scope(context->GetIsolate());
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000017040 v8::TryCatch try_catch;
17041 const char *source = "function foo() { FAIL.FAIL; }; foo();";
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017042 v8::Handle<v8::String> src =
17043 v8::String::NewFromUtf8(context->GetIsolate(), source);
17044 v8::Handle<v8::String> origin =
17045 v8::String::NewFromUtf8(context->GetIsolate(), "stack-trace-test");
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000017046 v8::Script::New(src, origin)->Run();
17047 CHECK(try_catch.HasCaught());
17048 v8::String::Utf8Value stack(try_catch.StackTrace());
17049 CHECK(strstr(*stack, "at foo (stack-trace-test") != NULL);
17050}
ager@chromium.org96c75b52009-08-26 09:13:16 +000017051
17052
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017053// Checks that a StackFrame has certain expected values.
17054void checkStackFrame(const char* expected_script_name,
17055 const char* expected_func_name, int expected_line_number,
17056 int expected_column, bool is_eval, bool is_constructor,
17057 v8::Handle<v8::StackFrame> frame) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017058 v8::HandleScope scope(CcTest::isolate());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017059 v8::String::Utf8Value func_name(frame->GetFunctionName());
17060 v8::String::Utf8Value script_name(frame->GetScriptName());
17061 if (*script_name == NULL) {
17062 // The situation where there is no associated script, like for evals.
17063 CHECK(expected_script_name == NULL);
17064 } else {
17065 CHECK(strstr(*script_name, expected_script_name) != NULL);
17066 }
17067 CHECK(strstr(*func_name, expected_func_name) != NULL);
17068 CHECK_EQ(expected_line_number, frame->GetLineNumber());
17069 CHECK_EQ(expected_column, frame->GetColumn());
17070 CHECK_EQ(is_eval, frame->IsEval());
17071 CHECK_EQ(is_constructor, frame->IsConstructor());
17072}
17073
17074
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017075void AnalyzeStackInNativeCode(const v8::FunctionCallbackInfo<v8::Value>& args) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017076 v8::HandleScope scope(args.GetIsolate());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017077 const char* origin = "capture-stack-trace-test";
17078 const int kOverviewTest = 1;
17079 const int kDetailedTest = 2;
17080
17081 ASSERT(args.Length() == 1);
17082
17083 int testGroup = args[0]->Int32Value();
17084 if (testGroup == kOverviewTest) {
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017085 v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
17086 args.GetIsolate(), 10, v8::StackTrace::kOverview);
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017087 CHECK_EQ(4, stackTrace->GetFrameCount());
17088 checkStackFrame(origin, "bar", 2, 10, false, false,
17089 stackTrace->GetFrame(0));
17090 checkStackFrame(origin, "foo", 6, 3, false, false,
17091 stackTrace->GetFrame(1));
whesse@chromium.org030d38e2011-07-13 13:23:34 +000017092 // This is the source string inside the eval which has the call to foo.
17093 checkStackFrame(NULL, "", 1, 5, false, false,
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017094 stackTrace->GetFrame(2));
whesse@chromium.org030d38e2011-07-13 13:23:34 +000017095 // The last frame is an anonymous function which has the initial eval call.
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017096 checkStackFrame(origin, "", 8, 7, false, false,
17097 stackTrace->GetFrame(3));
17098
17099 CHECK(stackTrace->AsArray()->IsArray());
17100 } else if (testGroup == kDetailedTest) {
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017101 v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
17102 args.GetIsolate(), 10, v8::StackTrace::kDetailed);
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017103 CHECK_EQ(4, stackTrace->GetFrameCount());
17104 checkStackFrame(origin, "bat", 4, 22, false, false,
17105 stackTrace->GetFrame(0));
17106 checkStackFrame(origin, "baz", 8, 3, false, true,
17107 stackTrace->GetFrame(1));
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +000017108#ifdef ENABLE_DEBUGGER_SUPPORT
17109 bool is_eval = true;
17110#else // ENABLE_DEBUGGER_SUPPORT
17111 bool is_eval = false;
17112#endif // ENABLE_DEBUGGER_SUPPORT
17113
whesse@chromium.org030d38e2011-07-13 13:23:34 +000017114 // This is the source string inside the eval which has the call to baz.
17115 checkStackFrame(NULL, "", 1, 5, is_eval, false,
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017116 stackTrace->GetFrame(2));
whesse@chromium.org030d38e2011-07-13 13:23:34 +000017117 // The last frame is an anonymous function which has the initial eval call.
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017118 checkStackFrame(origin, "", 10, 1, false, false,
17119 stackTrace->GetFrame(3));
17120
17121 CHECK(stackTrace->AsArray()->IsArray());
17122 }
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017123}
17124
17125
17126// Tests the C++ StackTrace API.
kasperl@chromium.orga5551262010-12-07 12:49:48 +000017127// TODO(3074796): Reenable this as a THREADED_TEST once it passes.
17128// THREADED_TEST(CaptureStackTrace) {
17129TEST(CaptureStackTrace) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017130 v8::Isolate* isolate = CcTest::isolate();
17131 v8::HandleScope scope(isolate);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017132 v8::Handle<v8::String> origin =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017133 v8::String::NewFromUtf8(isolate, "capture-stack-trace-test");
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000017134 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017135 templ->Set(v8_str("AnalyzeStackInNativeCode"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017136 v8::FunctionTemplate::New(isolate, AnalyzeStackInNativeCode));
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017137 LocalContext context(0, templ);
17138
17139 // Test getting OVERVIEW information. Should ignore information that is not
17140 // script name, function name, line number, and column offset.
17141 const char *overview_source =
17142 "function bar() {\n"
17143 " var y; AnalyzeStackInNativeCode(1);\n"
17144 "}\n"
17145 "function foo() {\n"
17146 "\n"
17147 " bar();\n"
17148 "}\n"
17149 "var x;eval('new foo();');";
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017150 v8::Handle<v8::String> overview_src =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017151 v8::String::NewFromUtf8(isolate, overview_source);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000017152 v8::Handle<Value> overview_result(
17153 v8::Script::New(overview_src, origin)->Run());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000017154 CHECK(!overview_result.IsEmpty());
17155 CHECK(overview_result->IsObject());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017156
17157 // Test getting DETAILED information.
17158 const char *detailed_source =
17159 "function bat() {AnalyzeStackInNativeCode(2);\n"
17160 "}\n"
17161 "\n"
17162 "function baz() {\n"
17163 " bat();\n"
17164 "}\n"
17165 "eval('new baz();');";
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017166 v8::Handle<v8::String> detailed_src =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017167 v8::String::NewFromUtf8(isolate, detailed_source);
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017168 // Make the script using a non-zero line and column offset.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000017169 v8::Handle<v8::Integer> line_offset = v8::Integer::New(isolate, 3);
17170 v8::Handle<v8::Integer> column_offset = v8::Integer::New(isolate, 5);
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017171 v8::ScriptOrigin detailed_origin(origin, line_offset, column_offset);
17172 v8::Handle<v8::Script> detailed_script(
17173 v8::Script::New(detailed_src, &detailed_origin));
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000017174 v8::Handle<Value> detailed_result(detailed_script->Run());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000017175 CHECK(!detailed_result.IsEmpty());
17176 CHECK(detailed_result->IsObject());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017177}
17178
17179
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000017180static void StackTraceForUncaughtExceptionListener(
17181 v8::Handle<v8::Message> message,
17182 v8::Handle<Value>) {
17183 v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
17184 CHECK_EQ(2, stack_trace->GetFrameCount());
17185 checkStackFrame("origin", "foo", 2, 3, false, false,
17186 stack_trace->GetFrame(0));
17187 checkStackFrame("origin", "bar", 5, 3, false, false,
17188 stack_trace->GetFrame(1));
17189}
17190
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000017191
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000017192TEST(CaptureStackTraceForUncaughtException) {
17193 report_count = 0;
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000017194 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017195 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000017196 v8::V8::AddMessageListener(StackTraceForUncaughtExceptionListener);
17197 v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
17198
17199 Script::Compile(v8_str("function foo() {\n"
17200 " throw 1;\n"
17201 "};\n"
17202 "function bar() {\n"
17203 " foo();\n"
17204 "};"),
17205 v8_str("origin"))->Run();
17206 v8::Local<v8::Object> global = env->Global();
17207 Local<Value> trouble = global->Get(v8_str("bar"));
17208 CHECK(trouble->IsFunction());
17209 Function::Cast(*trouble)->Call(global, 0, NULL);
17210 v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
17211 v8::V8::RemoveMessageListeners(StackTraceForUncaughtExceptionListener);
17212}
17213
17214
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000017215TEST(CaptureStackTraceForUncaughtExceptionAndSetters) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000017216 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017217 v8::HandleScope scope(env->GetIsolate());
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000017218 v8::V8::SetCaptureStackTraceForUncaughtExceptions(true,
17219 1024,
17220 v8::StackTrace::kDetailed);
17221
17222 CompileRun(
17223 "var setters = ['column', 'lineNumber', 'scriptName',\n"
17224 " 'scriptNameOrSourceURL', 'functionName', 'isEval',\n"
17225 " 'isConstructor'];\n"
17226 "for (var i = 0; i < setters.length; i++) {\n"
17227 " var prop = setters[i];\n"
17228 " Object.prototype.__defineSetter__(prop, function() { throw prop; });\n"
17229 "}\n");
17230 CompileRun("throw 'exception';");
17231 v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
17232}
17233
17234
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000017235static void RethrowStackTraceHandler(v8::Handle<v8::Message> message,
17236 v8::Handle<v8::Value> data) {
17237 // Use the frame where JavaScript is called from.
17238 v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
17239 CHECK(!stack_trace.IsEmpty());
17240 int frame_count = stack_trace->GetFrameCount();
17241 CHECK_EQ(3, frame_count);
17242 int line_number[] = {1, 2, 5};
17243 for (int i = 0; i < frame_count; i++) {
17244 CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
17245 }
17246}
17247
17248
17249// Test that we only return the stack trace at the site where the exception
17250// is first thrown (not where it is rethrown).
17251TEST(RethrowStackTrace) {
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000017252 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017253 v8::HandleScope scope(env->GetIsolate());
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000017254 // We make sure that
17255 // - the stack trace of the ReferenceError in g() is reported.
17256 // - the stack trace is not overwritten when e1 is rethrown by t().
17257 // - the stack trace of e2 does not overwrite that of e1.
17258 const char* source =
17259 "function g() { error; } \n"
17260 "function f() { g(); } \n"
17261 "function t(e) { throw e; } \n"
17262 "try { \n"
17263 " f(); \n"
17264 "} catch (e1) { \n"
17265 " try { \n"
17266 " error; \n"
17267 " } catch (e2) { \n"
17268 " t(e1); \n"
17269 " } \n"
17270 "} \n";
17271 v8::V8::AddMessageListener(RethrowStackTraceHandler);
17272 v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
17273 CompileRun(source);
17274 v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
17275 v8::V8::RemoveMessageListeners(RethrowStackTraceHandler);
17276}
17277
17278
17279static void RethrowPrimitiveStackTraceHandler(v8::Handle<v8::Message> message,
17280 v8::Handle<v8::Value> data) {
17281 v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
17282 CHECK(!stack_trace.IsEmpty());
17283 int frame_count = stack_trace->GetFrameCount();
17284 CHECK_EQ(2, frame_count);
17285 int line_number[] = {3, 7};
17286 for (int i = 0; i < frame_count; i++) {
17287 CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
17288 }
17289}
17290
17291
17292// Test that we do not recognize identity for primitive exceptions.
17293TEST(RethrowPrimitiveStackTrace) {
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000017294 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017295 v8::HandleScope scope(env->GetIsolate());
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000017296 // We do not capture stack trace for non Error objects on creation time.
17297 // Instead, we capture the stack trace on last throw.
17298 const char* source =
17299 "function g() { throw 404; } \n"
17300 "function f() { g(); } \n"
17301 "function t(e) { throw e; } \n"
17302 "try { \n"
17303 " f(); \n"
17304 "} catch (e1) { \n"
17305 " t(e1) \n"
17306 "} \n";
17307 v8::V8::AddMessageListener(RethrowPrimitiveStackTraceHandler);
17308 v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
17309 CompileRun(source);
17310 v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
17311 v8::V8::RemoveMessageListeners(RethrowPrimitiveStackTraceHandler);
17312}
17313
17314
17315static void RethrowExistingStackTraceHandler(v8::Handle<v8::Message> message,
17316 v8::Handle<v8::Value> data) {
17317 // Use the frame where JavaScript is called from.
17318 v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
17319 CHECK(!stack_trace.IsEmpty());
17320 CHECK_EQ(1, stack_trace->GetFrameCount());
17321 CHECK_EQ(1, stack_trace->GetFrame(0)->GetLineNumber());
17322}
17323
17324
17325// Test that the stack trace is captured when the error object is created and
17326// not where it is thrown.
17327TEST(RethrowExistingStackTrace) {
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000017328 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017329 v8::HandleScope scope(env->GetIsolate());
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000017330 const char* source =
17331 "var e = new Error(); \n"
17332 "throw e; \n";
17333 v8::V8::AddMessageListener(RethrowExistingStackTraceHandler);
17334 v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
17335 CompileRun(source);
17336 v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
17337 v8::V8::RemoveMessageListeners(RethrowExistingStackTraceHandler);
17338}
17339
17340
17341static void RethrowBogusErrorStackTraceHandler(v8::Handle<v8::Message> message,
17342 v8::Handle<v8::Value> data) {
17343 // Use the frame where JavaScript is called from.
17344 v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
17345 CHECK(!stack_trace.IsEmpty());
17346 CHECK_EQ(1, stack_trace->GetFrameCount());
17347 CHECK_EQ(2, stack_trace->GetFrame(0)->GetLineNumber());
17348}
17349
17350
17351// Test that the stack trace is captured where the bogus Error object is thrown.
17352TEST(RethrowBogusErrorStackTrace) {
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000017353 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017354 v8::HandleScope scope(env->GetIsolate());
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000017355 const char* source =
17356 "var e = {__proto__: new Error()} \n"
17357 "throw e; \n";
17358 v8::V8::AddMessageListener(RethrowBogusErrorStackTraceHandler);
17359 v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
17360 CompileRun(source);
17361 v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
17362 v8::V8::RemoveMessageListeners(RethrowBogusErrorStackTraceHandler);
17363}
17364
17365
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017366void AnalyzeStackOfEvalWithSourceURL(
17367 const v8::FunctionCallbackInfo<v8::Value>& args) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017368 v8::HandleScope scope(args.GetIsolate());
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017369 v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
17370 args.GetIsolate(), 10, v8::StackTrace::kDetailed);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000017371 CHECK_EQ(5, stackTrace->GetFrameCount());
17372 v8::Handle<v8::String> url = v8_str("eval_url");
17373 for (int i = 0; i < 3; i++) {
17374 v8::Handle<v8::String> name =
17375 stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
17376 CHECK(!name.IsEmpty());
17377 CHECK_EQ(url, name);
17378 }
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000017379}
17380
17381
17382TEST(SourceURLInStackTrace) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017383 v8::Isolate* isolate = CcTest::isolate();
17384 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000017385 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000017386 templ->Set(v8_str("AnalyzeStackOfEvalWithSourceURL"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017387 v8::FunctionTemplate::New(isolate,
17388 AnalyzeStackOfEvalWithSourceURL));
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000017389 LocalContext context(0, templ);
17390
17391 const char *source =
17392 "function outer() {\n"
17393 "function bar() {\n"
17394 " AnalyzeStackOfEvalWithSourceURL();\n"
17395 "}\n"
17396 "function foo() {\n"
17397 "\n"
17398 " bar();\n"
17399 "}\n"
17400 "foo();\n"
17401 "}\n"
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000017402 "eval('(' + outer +')()%s');";
17403
17404 i::ScopedVector<char> code(1024);
17405 i::OS::SNPrintF(code, source, "//# sourceURL=eval_url");
17406 CHECK(CompileRun(code.start())->IsUndefined());
17407 i::OS::SNPrintF(code, source, "//@ sourceURL=eval_url");
17408 CHECK(CompileRun(code.start())->IsUndefined());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000017409}
17410
17411
jkummerow@chromium.org8fa5bd92013-09-02 11:45:09 +000017412static int scriptIdInStack[2];
17413
17414void AnalyzeScriptIdInStack(
17415 const v8::FunctionCallbackInfo<v8::Value>& args) {
17416 v8::HandleScope scope(args.GetIsolate());
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017417 v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
17418 args.GetIsolate(), 10, v8::StackTrace::kScriptId);
jkummerow@chromium.org8fa5bd92013-09-02 11:45:09 +000017419 CHECK_EQ(2, stackTrace->GetFrameCount());
17420 for (int i = 0; i < 2; i++) {
17421 scriptIdInStack[i] = stackTrace->GetFrame(i)->GetScriptId();
17422 }
17423}
17424
17425
17426TEST(ScriptIdInStackTrace) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017427 v8::Isolate* isolate = CcTest::isolate();
17428 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000017429 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
jkummerow@chromium.org8fa5bd92013-09-02 11:45:09 +000017430 templ->Set(v8_str("AnalyzeScriptIdInStack"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017431 v8::FunctionTemplate::New(isolate, AnalyzeScriptIdInStack));
jkummerow@chromium.org8fa5bd92013-09-02 11:45:09 +000017432 LocalContext context(0, templ);
17433
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017434 v8::Handle<v8::String> scriptSource = v8::String::NewFromUtf8(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017435 isolate,
jkummerow@chromium.org8fa5bd92013-09-02 11:45:09 +000017436 "function foo() {\n"
17437 " AnalyzeScriptIdInStack();"
17438 "}\n"
17439 "foo();\n");
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017440 v8::ScriptOrigin origin =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017441 v8::ScriptOrigin(v8::String::NewFromUtf8(isolate, "test"));
jkummerow@chromium.org8fa5bd92013-09-02 11:45:09 +000017442 v8::Local<v8::Script> script(v8::Script::Compile(scriptSource, &origin));
17443 script->Run();
17444 for (int i = 0; i < 2; i++) {
17445 CHECK(scriptIdInStack[i] != v8::Message::kNoScriptIdInfo);
17446 CHECK_EQ(scriptIdInStack[i], script->GetId());
17447 }
17448}
17449
17450
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017451void AnalyzeStackOfInlineScriptWithSourceURL(
17452 const v8::FunctionCallbackInfo<v8::Value>& args) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017453 v8::HandleScope scope(args.GetIsolate());
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017454 v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
17455 args.GetIsolate(), 10, v8::StackTrace::kDetailed);
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017456 CHECK_EQ(4, stackTrace->GetFrameCount());
17457 v8::Handle<v8::String> url = v8_str("url");
17458 for (int i = 0; i < 3; i++) {
17459 v8::Handle<v8::String> name =
17460 stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
17461 CHECK(!name.IsEmpty());
17462 CHECK_EQ(url, name);
17463 }
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017464}
17465
17466
17467TEST(InlineScriptWithSourceURLInStackTrace) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000017468 v8::Isolate* isolate = CcTest::isolate();
17469 v8::HandleScope scope(isolate);
17470 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017471 templ->Set(v8_str("AnalyzeStackOfInlineScriptWithSourceURL"),
17472 v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017473 CcTest::isolate(), AnalyzeStackOfInlineScriptWithSourceURL));
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017474 LocalContext context(0, templ);
17475
17476 const char *source =
17477 "function outer() {\n"
17478 "function bar() {\n"
17479 " AnalyzeStackOfInlineScriptWithSourceURL();\n"
17480 "}\n"
17481 "function foo() {\n"
17482 "\n"
17483 " bar();\n"
17484 "}\n"
17485 "foo();\n"
17486 "}\n"
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000017487 "outer()\n%s";
17488
17489 i::ScopedVector<char> code(1024);
17490 i::OS::SNPrintF(code, source, "//# sourceURL=source_url");
17491 CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
17492 i::OS::SNPrintF(code, source, "//@ sourceURL=source_url");
17493 CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017494}
17495
17496
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017497void AnalyzeStackOfDynamicScriptWithSourceURL(
17498 const v8::FunctionCallbackInfo<v8::Value>& args) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017499 v8::HandleScope scope(args.GetIsolate());
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017500 v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
17501 args.GetIsolate(), 10, v8::StackTrace::kDetailed);
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017502 CHECK_EQ(4, stackTrace->GetFrameCount());
17503 v8::Handle<v8::String> url = v8_str("source_url");
17504 for (int i = 0; i < 3; i++) {
17505 v8::Handle<v8::String> name =
17506 stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
17507 CHECK(!name.IsEmpty());
17508 CHECK_EQ(url, name);
17509 }
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017510}
17511
17512
17513TEST(DynamicWithSourceURLInStackTrace) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000017514 v8::Isolate* isolate = CcTest::isolate();
17515 v8::HandleScope scope(isolate);
17516 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017517 templ->Set(v8_str("AnalyzeStackOfDynamicScriptWithSourceURL"),
17518 v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017519 CcTest::isolate(), AnalyzeStackOfDynamicScriptWithSourceURL));
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017520 LocalContext context(0, templ);
17521
17522 const char *source =
17523 "function outer() {\n"
17524 "function bar() {\n"
17525 " AnalyzeStackOfDynamicScriptWithSourceURL();\n"
17526 "}\n"
17527 "function foo() {\n"
17528 "\n"
17529 " bar();\n"
17530 "}\n"
17531 "foo();\n"
17532 "}\n"
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000017533 "outer()\n%s";
17534
17535 i::ScopedVector<char> code(1024);
17536 i::OS::SNPrintF(code, source, "//# sourceURL=source_url");
17537 CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
17538 i::OS::SNPrintF(code, source, "//@ sourceURL=source_url");
17539 CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017540}
17541
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000017542
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017543static void CreateGarbageInOldSpace() {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017544 i::Factory* factory = CcTest::i_isolate()->factory();
17545 v8::HandleScope scope(CcTest::isolate());
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017546 i::AlwaysAllocateScope always_allocate;
17547 for (int i = 0; i < 1000; i++) {
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000017548 factory->NewFixedArray(1000, i::TENURED);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017549 }
svenpanne@chromium.orgecb9dd62011-12-01 08:22:35 +000017550}
17551
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000017552
svenpanne@chromium.orgecb9dd62011-12-01 08:22:35 +000017553// Test that idle notification can be handled and eventually returns true.
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017554TEST(IdleNotification) {
17555 const intptr_t MB = 1024 * 1024;
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017556 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017557 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017558 intptr_t initial_size = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017559 CreateGarbageInOldSpace();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017560 intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017561 CHECK_GT(size_with_garbage, initial_size + MB);
17562 bool finished = false;
17563 for (int i = 0; i < 200 && !finished; i++) {
17564 finished = v8::V8::IdleNotification();
17565 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017566 intptr_t final_size = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017567 CHECK(finished);
17568 CHECK_LT(final_size, initial_size + 1);
17569}
17570
17571
17572// Test that idle notification can be handled and eventually collects garbage.
yangguo@chromium.org56454712012-02-16 15:33:53 +000017573TEST(IdleNotificationWithSmallHint) {
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017574 const intptr_t MB = 1024 * 1024;
17575 const int IdlePauseInMs = 900;
svenpanne@chromium.orgecb9dd62011-12-01 08:22:35 +000017576 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017577 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017578 intptr_t initial_size = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017579 CreateGarbageInOldSpace();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017580 intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017581 CHECK_GT(size_with_garbage, initial_size + MB);
17582 bool finished = false;
17583 for (int i = 0; i < 200 && !finished; i++) {
17584 finished = v8::V8::IdleNotification(IdlePauseInMs);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017585 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017586 intptr_t final_size = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017587 CHECK(finished);
17588 CHECK_LT(final_size, initial_size + 1);
yangguo@chromium.org56454712012-02-16 15:33:53 +000017589}
17590
17591
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017592// Test that idle notification can be handled and eventually collects garbage.
yangguo@chromium.org56454712012-02-16 15:33:53 +000017593TEST(IdleNotificationWithLargeHint) {
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017594 const intptr_t MB = 1024 * 1024;
17595 const int IdlePauseInMs = 900;
yangguo@chromium.org56454712012-02-16 15:33:53 +000017596 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017597 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017598 intptr_t initial_size = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017599 CreateGarbageInOldSpace();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017600 intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017601 CHECK_GT(size_with_garbage, initial_size + MB);
17602 bool finished = false;
17603 for (int i = 0; i < 200 && !finished; i++) {
17604 finished = v8::V8::IdleNotification(IdlePauseInMs);
yangguo@chromium.org56454712012-02-16 15:33:53 +000017605 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017606 intptr_t final_size = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017607 CHECK(finished);
17608 CHECK_LT(final_size, initial_size + 1);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017609}
17610
17611
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017612TEST(Regress2107) {
17613 const intptr_t MB = 1024 * 1024;
17614 const int kShortIdlePauseInMs = 100;
17615 const int kLongIdlePauseInMs = 1000;
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017616 LocalContext env;
ulan@chromium.org57ff8812013-05-10 08:16:55 +000017617 v8::Isolate* isolate = env->GetIsolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017618 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017619 intptr_t initial_size = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017620 // Send idle notification to start a round of incremental GCs.
17621 v8::V8::IdleNotification(kShortIdlePauseInMs);
17622 // Emulate 7 page reloads.
17623 for (int i = 0; i < 7; i++) {
ulan@chromium.org57ff8812013-05-10 08:16:55 +000017624 {
17625 v8::HandleScope inner_scope(env->GetIsolate());
17626 v8::Local<v8::Context> ctx = v8::Context::New(isolate);
17627 ctx->Enter();
17628 CreateGarbageInOldSpace();
17629 ctx->Exit();
17630 }
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017631 v8::V8::ContextDisposedNotification();
17632 v8::V8::IdleNotification(kLongIdlePauseInMs);
17633 }
17634 // Create garbage and check that idle notification still collects it.
17635 CreateGarbageInOldSpace();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017636 intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017637 CHECK_GT(size_with_garbage, initial_size + MB);
17638 bool finished = false;
17639 for (int i = 0; i < 200 && !finished; i++) {
17640 finished = v8::V8::IdleNotification(kShortIdlePauseInMs);
17641 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017642 intptr_t final_size = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017643 CHECK_LT(final_size, initial_size + 1);
17644}
17645
machenbach@chromium.orgb5be0a92013-11-15 10:32:41 +000017646
17647TEST(Regress2333) {
17648 LocalContext env;
17649 for (int i = 0; i < 3; i++) {
17650 CcTest::heap()->PerformScavenge();
17651 }
17652}
17653
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017654static uint32_t* stack_limit;
17655
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017656static void GetStackLimitCallback(
17657 const v8::FunctionCallbackInfo<v8::Value>& args) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000017658 stack_limit = reinterpret_cast<uint32_t*>(
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017659 CcTest::i_isolate()->stack_guard()->real_climit());
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017660}
17661
17662
17663// Uses the address of a local variable to determine the stack top now.
17664// Given a size, returns an address that is that far from the current
17665// top of stack.
17666static uint32_t* ComputeStackLimit(uint32_t size) {
17667 uint32_t* answer = &size - (size / sizeof(size));
17668 // If the size is very large and the stack is very near the bottom of
17669 // memory then the calculation above may wrap around and give an address
17670 // that is above the (downwards-growing) stack. In that case we return
17671 // a very low address.
17672 if (answer > &size) return reinterpret_cast<uint32_t*>(sizeof(size));
17673 return answer;
17674}
17675
17676
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +000017677// We need at least 165kB for an x64 debug build with clang and ASAN.
17678static const int stack_breathing_room = 256 * i::KB;
17679
17680
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017681TEST(SetResourceConstraints) {
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +000017682 uint32_t* set_limit = ComputeStackLimit(stack_breathing_room);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017683
17684 // Set stack limit.
17685 v8::ResourceConstraints constraints;
17686 constraints.set_stack_limit(set_limit);
machenbach@chromium.org7ff76072013-11-21 09:47:43 +000017687 CHECK(v8::SetResourceConstraints(CcTest::isolate(), &constraints));
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017688
17689 // Execute a script.
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017690 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017691 v8::HandleScope scope(env->GetIsolate());
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017692 Local<v8::FunctionTemplate> fun_templ =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017693 v8::FunctionTemplate::New(env->GetIsolate(), GetStackLimitCallback);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017694 Local<Function> fun = fun_templ->GetFunction();
17695 env->Global()->Set(v8_str("get_stack_limit"), fun);
17696 CompileRun("get_stack_limit();");
17697
17698 CHECK(stack_limit == set_limit);
17699}
17700
17701
17702TEST(SetResourceConstraintsInThread) {
17703 uint32_t* set_limit;
17704 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017705 v8::Locker locker(CcTest::isolate());
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +000017706 set_limit = ComputeStackLimit(stack_breathing_room);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017707
17708 // Set stack limit.
17709 v8::ResourceConstraints constraints;
17710 constraints.set_stack_limit(set_limit);
machenbach@chromium.org7ff76072013-11-21 09:47:43 +000017711 CHECK(v8::SetResourceConstraints(CcTest::isolate(), &constraints));
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017712
17713 // Execute a script.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017714 v8::HandleScope scope(CcTest::isolate());
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017715 LocalContext env;
17716 Local<v8::FunctionTemplate> fun_templ =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017717 v8::FunctionTemplate::New(CcTest::isolate(), GetStackLimitCallback);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017718 Local<Function> fun = fun_templ->GetFunction();
17719 env->Global()->Set(v8_str("get_stack_limit"), fun);
17720 CompileRun("get_stack_limit();");
17721
17722 CHECK(stack_limit == set_limit);
17723 }
17724 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017725 v8::Locker locker(CcTest::isolate());
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017726 CHECK(stack_limit == set_limit);
17727 }
ager@chromium.org96c75b52009-08-26 09:13:16 +000017728}
ager@chromium.org3811b432009-10-28 14:53:37 +000017729
17730
17731THREADED_TEST(GetHeapStatistics) {
ager@chromium.org3811b432009-10-28 14:53:37 +000017732 LocalContext c1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017733 v8::HandleScope scope(c1->GetIsolate());
ager@chromium.org3811b432009-10-28 14:53:37 +000017734 v8::HeapStatistics heap_statistics;
ager@chromium.orgc4c92722009-11-18 14:12:51 +000017735 CHECK_EQ(static_cast<int>(heap_statistics.total_heap_size()), 0);
17736 CHECK_EQ(static_cast<int>(heap_statistics.used_heap_size()), 0);
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +000017737 c1->GetIsolate()->GetHeapStatistics(&heap_statistics);
ager@chromium.orgc4c92722009-11-18 14:12:51 +000017738 CHECK_NE(static_cast<int>(heap_statistics.total_heap_size()), 0);
17739 CHECK_NE(static_cast<int>(heap_statistics.used_heap_size()), 0);
ager@chromium.org3811b432009-10-28 14:53:37 +000017740}
17741
17742
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017743class VisitorImpl : public v8::ExternalResourceVisitor {
17744 public:
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017745 explicit VisitorImpl(TestResource** resource) {
17746 for (int i = 0; i < 4; i++) {
17747 resource_[i] = resource[i];
17748 found_resource_[i] = false;
17749 }
17750 }
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017751 virtual ~VisitorImpl() {}
17752 virtual void VisitExternalString(v8::Handle<v8::String> string) {
17753 if (!string->IsExternal()) {
17754 CHECK(string->IsExternalAscii());
17755 return;
17756 }
17757 v8::String::ExternalStringResource* resource =
17758 string->GetExternalStringResource();
17759 CHECK(resource);
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017760 for (int i = 0; i < 4; i++) {
17761 if (resource_[i] == resource) {
17762 CHECK(!found_resource_[i]);
17763 found_resource_[i] = true;
17764 }
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017765 }
17766 }
17767 void CheckVisitedResources() {
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017768 for (int i = 0; i < 4; i++) {
17769 CHECK(found_resource_[i]);
17770 }
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017771 }
17772
17773 private:
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017774 v8::String::ExternalStringResource* resource_[4];
17775 bool found_resource_[4];
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017776};
17777
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000017778
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017779TEST(VisitExternalStrings) {
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017780 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017781 v8::HandleScope scope(env->GetIsolate());
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017782 const char* string = "Some string";
17783 uint16_t* two_byte_string = AsciiToTwoByteString(string);
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017784 TestResource* resource[4];
17785 resource[0] = new TestResource(two_byte_string);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017786 v8::Local<v8::String> string0 =
17787 v8::String::NewExternal(env->GetIsolate(), resource[0]);
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017788 resource[1] = new TestResource(two_byte_string);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017789 v8::Local<v8::String> string1 =
17790 v8::String::NewExternal(env->GetIsolate(), resource[1]);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017791
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017792 // Externalized symbol.
17793 resource[2] = new TestResource(two_byte_string);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017794 v8::Local<v8::String> string2 = v8::String::NewFromUtf8(
17795 env->GetIsolate(), string, v8::String::kInternalizedString);
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017796 CHECK(string2->MakeExternal(resource[2]));
17797
17798 // Symbolized External.
17799 resource[3] = new TestResource(AsciiToTwoByteString("Some other string"));
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017800 v8::Local<v8::String> string3 =
17801 v8::String::NewExternal(env->GetIsolate(), resource[3]);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017802 CcTest::heap()->CollectAllAvailableGarbage(); // Tenure string.
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017803 // Turn into a symbol.
17804 i::Handle<i::String> string3_i = v8::Utils::OpenHandle(*string3);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017805 CHECK(!CcTest::heap()->InternalizeString(*string3_i)->IsFailure());
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +000017806 CHECK(string3_i->IsInternalizedString());
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017807
17808 // We need to add usages for string* to avoid warnings in GCC 4.7
17809 CHECK(string0->IsExternal());
ulan@chromium.org2efb9002012-01-19 15:36:35 +000017810 CHECK(string1->IsExternal());
17811 CHECK(string2->IsExternal());
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017812 CHECK(string3->IsExternal());
ulan@chromium.org2efb9002012-01-19 15:36:35 +000017813
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017814 VisitorImpl visitor(resource);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017815 v8::V8::VisitExternalResources(&visitor);
17816 visitor.CheckVisitedResources();
17817}
17818
17819
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017820TEST(ExternalStringCollectedAtTearDown) {
17821 int destroyed = 0;
17822 v8::Isolate* isolate = v8::Isolate::New();
17823 { v8::Isolate::Scope isolate_scope(isolate);
17824 v8::HandleScope handle_scope(isolate);
17825 const char* s = "One string to test them all, one string to find them.";
17826 TestAsciiResource* inscription =
17827 new TestAsciiResource(i::StrDup(s), &destroyed);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017828 v8::Local<v8::String> ring = v8::String::NewExternal(isolate, inscription);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017829 // Ring is still alive. Orcs are roaming freely across our lands.
17830 CHECK_EQ(0, destroyed);
17831 USE(ring);
17832 }
17833
17834 isolate->Dispose();
17835 // Ring has been destroyed. Free Peoples of Middle-earth Rejoice.
17836 CHECK_EQ(1, destroyed);
17837}
17838
17839
jkummerow@chromium.org113035e2013-12-13 15:13:40 +000017840TEST(ExternalInternalizedStringCollectedAtTearDown) {
17841 int destroyed = 0;
17842 v8::Isolate* isolate = v8::Isolate::New();
17843 { v8::Isolate::Scope isolate_scope(isolate);
17844 LocalContext env(isolate);
17845 v8::HandleScope handle_scope(isolate);
17846 CompileRun("var ring = 'One string to test them all';");
17847 const char* s = "One string to test them all";
17848 TestAsciiResource* inscription =
17849 new TestAsciiResource(i::StrDup(s), &destroyed);
17850 v8::Local<v8::String> ring = CompileRun("ring")->ToString();
17851 CHECK(v8::Utils::OpenHandle(*ring)->IsInternalizedString());
17852 ring->MakeExternal(inscription);
17853 // Ring is still alive. Orcs are roaming freely across our lands.
17854 CHECK_EQ(0, destroyed);
17855 USE(ring);
17856 }
17857
17858 isolate->Dispose();
17859 // Ring has been destroyed. Free Peoples of Middle-earth Rejoice.
17860 CHECK_EQ(1, destroyed);
17861}
17862
17863
17864TEST(ExternalInternalizedStringCollectedAtGC) {
17865 int destroyed = 0;
17866 { LocalContext env;
17867 v8::HandleScope handle_scope(env->GetIsolate());
17868 CompileRun("var ring = 'One string to test them all';");
17869 const char* s = "One string to test them all";
17870 TestAsciiResource* inscription =
17871 new TestAsciiResource(i::StrDup(s), &destroyed);
17872 v8::Local<v8::String> ring = CompileRun("ring")->ToString();
17873 CHECK(v8::Utils::OpenHandle(*ring)->IsInternalizedString());
17874 ring->MakeExternal(inscription);
17875 // Ring is still alive. Orcs are roaming freely across our lands.
17876 CHECK_EQ(0, destroyed);
17877 USE(ring);
17878 }
17879
17880 // Garbage collector deals swift blows to evil.
17881 CcTest::i_isolate()->compilation_cache()->Clear();
17882 CcTest::heap()->CollectAllAvailableGarbage();
17883
17884 // Ring has been destroyed. Free Peoples of Middle-earth Rejoice.
17885 CHECK_EQ(1, destroyed);
17886}
17887
17888
ager@chromium.org3811b432009-10-28 14:53:37 +000017889static double DoubleFromBits(uint64_t value) {
17890 double target;
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +000017891 i::OS::MemCopy(&target, &value, sizeof(target));
ager@chromium.org3811b432009-10-28 14:53:37 +000017892 return target;
17893}
17894
17895
17896static uint64_t DoubleToBits(double value) {
17897 uint64_t target;
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +000017898 i::OS::MemCopy(&target, &value, sizeof(target));
ager@chromium.org3811b432009-10-28 14:53:37 +000017899 return target;
17900}
17901
17902
17903static double DoubleToDateTime(double input) {
17904 double date_limit = 864e13;
ulan@chromium.org77ca49a2013-04-22 09:43:56 +000017905 if (std::isnan(input) || input < -date_limit || input > date_limit) {
ager@chromium.org3811b432009-10-28 14:53:37 +000017906 return i::OS::nan_value();
17907 }
machenbach@chromium.orge31286d2014-01-15 10:29:52 +000017908 return (input < 0) ? -(std::floor(-input)) : std::floor(input);
ager@chromium.org3811b432009-10-28 14:53:37 +000017909}
17910
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000017911
ager@chromium.org3811b432009-10-28 14:53:37 +000017912// We don't have a consistent way to write 64-bit constants syntactically, so we
17913// split them into two 32-bit constants and combine them programmatically.
17914static double DoubleFromBits(uint32_t high_bits, uint32_t low_bits) {
17915 return DoubleFromBits((static_cast<uint64_t>(high_bits) << 32) | low_bits);
17916}
17917
17918
17919THREADED_TEST(QuietSignalingNaNs) {
ager@chromium.org3811b432009-10-28 14:53:37 +000017920 LocalContext context;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000017921 v8::Isolate* isolate = context->GetIsolate();
17922 v8::HandleScope scope(isolate);
ager@chromium.org3811b432009-10-28 14:53:37 +000017923 v8::TryCatch try_catch;
17924
17925 // Special double values.
17926 double snan = DoubleFromBits(0x7ff00000, 0x00000001);
17927 double qnan = DoubleFromBits(0x7ff80000, 0x00000000);
17928 double infinity = DoubleFromBits(0x7ff00000, 0x00000000);
17929 double max_normal = DoubleFromBits(0x7fefffff, 0xffffffffu);
17930 double min_normal = DoubleFromBits(0x00100000, 0x00000000);
17931 double max_denormal = DoubleFromBits(0x000fffff, 0xffffffffu);
17932 double min_denormal = DoubleFromBits(0x00000000, 0x00000001);
17933
17934 // Date values are capped at +/-100000000 days (times 864e5 ms per day)
17935 // on either side of the epoch.
17936 double date_limit = 864e13;
17937
17938 double test_values[] = {
17939 snan,
17940 qnan,
17941 infinity,
17942 max_normal,
17943 date_limit + 1,
17944 date_limit,
17945 min_normal,
17946 max_denormal,
17947 min_denormal,
17948 0,
17949 -0,
17950 -min_denormal,
17951 -max_denormal,
17952 -min_normal,
17953 -date_limit,
17954 -date_limit - 1,
17955 -max_normal,
17956 -infinity,
17957 -qnan,
17958 -snan
17959 };
17960 int num_test_values = 20;
17961
17962 for (int i = 0; i < num_test_values; i++) {
17963 double test_value = test_values[i];
17964
17965 // Check that Number::New preserves non-NaNs and quiets SNaNs.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000017966 v8::Handle<v8::Value> number = v8::Number::New(isolate, test_value);
ager@chromium.org3811b432009-10-28 14:53:37 +000017967 double stored_number = number->NumberValue();
ulan@chromium.org77ca49a2013-04-22 09:43:56 +000017968 if (!std::isnan(test_value)) {
ager@chromium.org3811b432009-10-28 14:53:37 +000017969 CHECK_EQ(test_value, stored_number);
17970 } else {
17971 uint64_t stored_bits = DoubleToBits(stored_number);
17972 // Check if quiet nan (bits 51..62 all set).
danno@chromium.orgc612e022011-11-10 11:38:15 +000017973#if defined(V8_TARGET_ARCH_MIPS) && !defined(USE_SIMULATOR)
17974 // Most significant fraction bit for quiet nan is set to 0
17975 // on MIPS architecture. Allowed by IEEE-754.
17976 CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
17977#else
ager@chromium.org3811b432009-10-28 14:53:37 +000017978 CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
danno@chromium.orgc612e022011-11-10 11:38:15 +000017979#endif
ager@chromium.org3811b432009-10-28 14:53:37 +000017980 }
17981
17982 // Check that Date::New preserves non-NaNs in the date range and
17983 // quiets SNaNs.
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017984 v8::Handle<v8::Value> date =
ulan@chromium.org0f13e742014-01-03 15:51:11 +000017985 v8::Date::New(isolate, test_value);
ager@chromium.org3811b432009-10-28 14:53:37 +000017986 double expected_stored_date = DoubleToDateTime(test_value);
17987 double stored_date = date->NumberValue();
ulan@chromium.org77ca49a2013-04-22 09:43:56 +000017988 if (!std::isnan(expected_stored_date)) {
ager@chromium.org3811b432009-10-28 14:53:37 +000017989 CHECK_EQ(expected_stored_date, stored_date);
17990 } else {
17991 uint64_t stored_bits = DoubleToBits(stored_date);
17992 // Check if quiet nan (bits 51..62 all set).
danno@chromium.orgc612e022011-11-10 11:38:15 +000017993#if defined(V8_TARGET_ARCH_MIPS) && !defined(USE_SIMULATOR)
17994 // Most significant fraction bit for quiet nan is set to 0
17995 // on MIPS architecture. Allowed by IEEE-754.
17996 CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
17997#else
ager@chromium.org3811b432009-10-28 14:53:37 +000017998 CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
danno@chromium.orgc612e022011-11-10 11:38:15 +000017999#endif
ager@chromium.org3811b432009-10-28 14:53:37 +000018000 }
18001 }
18002}
christian.plesner.hansen@gmail.comb9ce6372009-11-03 11:38:18 +000018003
18004
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018005static void SpaghettiIncident(
18006 const v8::FunctionCallbackInfo<v8::Value>& args) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018007 v8::HandleScope scope(args.GetIsolate());
christian.plesner.hansen@gmail.comb9ce6372009-11-03 11:38:18 +000018008 v8::TryCatch tc;
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000018009 v8::Handle<v8::String> str(args[0]->ToString());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000018010 USE(str);
christian.plesner.hansen@gmail.comb9ce6372009-11-03 11:38:18 +000018011 if (tc.HasCaught())
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018012 tc.ReThrow();
christian.plesner.hansen@gmail.comb9ce6372009-11-03 11:38:18 +000018013}
18014
18015
18016// Test that an exception can be propagated down through a spaghetti
18017// stack using ReThrow.
18018THREADED_TEST(SpaghettiStackReThrow) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000018019 v8::Isolate* isolate = CcTest::isolate();
18020 v8::HandleScope scope(isolate);
christian.plesner.hansen@gmail.comb9ce6372009-11-03 11:38:18 +000018021 LocalContext context;
18022 context->Global()->Set(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000018023 v8::String::NewFromUtf8(isolate, "s"),
18024 v8::FunctionTemplate::New(isolate, SpaghettiIncident)->GetFunction());
christian.plesner.hansen@gmail.comb9ce6372009-11-03 11:38:18 +000018025 v8::TryCatch try_catch;
18026 CompileRun(
18027 "var i = 0;"
18028 "var o = {"
18029 " toString: function () {"
18030 " if (i == 10) {"
18031 " throw 'Hey!';"
18032 " } else {"
18033 " i++;"
18034 " return s(o);"
18035 " }"
18036 " }"
18037 "};"
18038 "s(o);");
18039 CHECK(try_catch.HasCaught());
18040 v8::String::Utf8Value value(try_catch.Exception());
18041 CHECK_EQ(0, strcmp(*value, "Hey!"));
18042}
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018043
18044
sgjesse@chromium.org98180592009-12-02 08:17:28 +000018045TEST(Regress528) {
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018046 v8::V8::Initialize();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018047 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000018048 v8::HandleScope scope(isolate);
18049 v8::Local<Context> other_context;
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018050 int gc_count;
18051
ager@chromium.org60121232009-12-03 11:25:37 +000018052 // Create a context used to keep the code from aging in the compilation
18053 // cache.
ulan@chromium.org57ff8812013-05-10 08:16:55 +000018054 other_context = Context::New(isolate);
ager@chromium.org60121232009-12-03 11:25:37 +000018055
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018056 // Context-dependent context data creates reference from the compilation
18057 // cache to the global object.
ager@chromium.org60121232009-12-03 11:25:37 +000018058 const char* source_simple = "1";
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018059 {
ulan@chromium.org57ff8812013-05-10 08:16:55 +000018060 v8::HandleScope scope(isolate);
18061 v8::Local<Context> context = Context::New(isolate);
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018062
18063 context->Enter();
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018064 Local<v8::String> obj = v8::String::NewFromUtf8(isolate, "");
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000018065 context->SetEmbedderData(0, obj);
ager@chromium.org60121232009-12-03 11:25:37 +000018066 CompileRun(source_simple);
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018067 context->Exit();
18068 }
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000018069 v8::V8::ContextDisposedNotification();
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018070 for (gc_count = 1; gc_count < 10; gc_count++) {
ager@chromium.org60121232009-12-03 11:25:37 +000018071 other_context->Enter();
18072 CompileRun(source_simple);
18073 other_context->Exit();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018074 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org60121232009-12-03 11:25:37 +000018075 if (GetGlobalObjectsCount() == 1) break;
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018076 }
ager@chromium.org60121232009-12-03 11:25:37 +000018077 CHECK_GE(2, gc_count);
18078 CHECK_EQ(1, GetGlobalObjectsCount());
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018079
18080 // Eval in a function creates reference from the compilation cache to the
18081 // global object.
ager@chromium.org60121232009-12-03 11:25:37 +000018082 const char* source_eval = "function f(){eval('1')}; f()";
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018083 {
ulan@chromium.org57ff8812013-05-10 08:16:55 +000018084 v8::HandleScope scope(isolate);
18085 v8::Local<Context> context = Context::New(isolate);
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018086
18087 context->Enter();
ager@chromium.org60121232009-12-03 11:25:37 +000018088 CompileRun(source_eval);
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018089 context->Exit();
18090 }
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000018091 v8::V8::ContextDisposedNotification();
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018092 for (gc_count = 1; gc_count < 10; gc_count++) {
ager@chromium.org60121232009-12-03 11:25:37 +000018093 other_context->Enter();
18094 CompileRun(source_eval);
18095 other_context->Exit();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018096 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org60121232009-12-03 11:25:37 +000018097 if (GetGlobalObjectsCount() == 1) break;
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018098 }
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +000018099 CHECK_GE(2, gc_count);
sgjesse@chromium.org98180592009-12-02 08:17:28 +000018100 CHECK_EQ(1, GetGlobalObjectsCount());
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018101
18102 // Looking up the line number for an exception creates reference from the
18103 // compilation cache to the global object.
ager@chromium.org60121232009-12-03 11:25:37 +000018104 const char* source_exception = "function f(){throw 1;} f()";
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018105 {
ulan@chromium.org57ff8812013-05-10 08:16:55 +000018106 v8::HandleScope scope(isolate);
18107 v8::Local<Context> context = Context::New(isolate);
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018108
18109 context->Enter();
18110 v8::TryCatch try_catch;
ager@chromium.org60121232009-12-03 11:25:37 +000018111 CompileRun(source_exception);
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018112 CHECK(try_catch.HasCaught());
18113 v8::Handle<v8::Message> message = try_catch.Message();
18114 CHECK(!message.IsEmpty());
18115 CHECK_EQ(1, message->GetLineNumber());
18116 context->Exit();
18117 }
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +000018118 v8::V8::ContextDisposedNotification();
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018119 for (gc_count = 1; gc_count < 10; gc_count++) {
ager@chromium.org60121232009-12-03 11:25:37 +000018120 other_context->Enter();
18121 CompileRun(source_exception);
18122 other_context->Exit();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018123 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org60121232009-12-03 11:25:37 +000018124 if (GetGlobalObjectsCount() == 1) break;
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018125 }
ager@chromium.org60121232009-12-03 11:25:37 +000018126 CHECK_GE(2, gc_count);
18127 CHECK_EQ(1, GetGlobalObjectsCount());
18128
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000018129 v8::V8::ContextDisposedNotification();
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018130}
ager@chromium.org5c838252010-02-19 08:53:10 +000018131
18132
18133THREADED_TEST(ScriptOrigin) {
ager@chromium.org5c838252010-02-19 08:53:10 +000018134 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018135 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018136 v8::ScriptOrigin origin =
18137 v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
18138 v8::Handle<v8::String> script = v8::String::NewFromUtf8(
18139 env->GetIsolate(), "function f() {}\n\nfunction g() {}");
ager@chromium.org5c838252010-02-19 08:53:10 +000018140 v8::Script::Compile(script, &origin)->Run();
18141 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018142 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
ager@chromium.org5c838252010-02-19 08:53:10 +000018143 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018144 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
ager@chromium.org5c838252010-02-19 08:53:10 +000018145
18146 v8::ScriptOrigin script_origin_f = f->GetScriptOrigin();
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000018147 CHECK_EQ("test", *v8::String::Utf8Value(script_origin_f.ResourceName()));
ager@chromium.org5c838252010-02-19 08:53:10 +000018148 CHECK_EQ(0, script_origin_f.ResourceLineOffset()->Int32Value());
18149
18150 v8::ScriptOrigin script_origin_g = g->GetScriptOrigin();
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000018151 CHECK_EQ("test", *v8::String::Utf8Value(script_origin_g.ResourceName()));
ager@chromium.org5c838252010-02-19 08:53:10 +000018152 CHECK_EQ(0, script_origin_g.ResourceLineOffset()->Int32Value());
18153}
18154
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000018155
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000018156THREADED_TEST(FunctionGetInferredName) {
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000018157 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018158 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018159 v8::ScriptOrigin origin =
18160 v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
18161 v8::Handle<v8::String> script = v8::String::NewFromUtf8(
18162 env->GetIsolate(),
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000018163 "var foo = { bar : { baz : function() {}}}; var f = foo.bar.baz;");
18164 v8::Script::Compile(script, &origin)->Run();
18165 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018166 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000018167 CHECK_EQ("foo.bar.baz", *v8::String::Utf8Value(f->GetInferredName()));
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000018168}
ager@chromium.org5c838252010-02-19 08:53:10 +000018169
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000018170
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +000018171THREADED_TEST(FunctionGetDisplayName) {
18172 LocalContext env;
18173 v8::HandleScope scope(env->GetIsolate());
18174 const char* code = "var error = false;"
18175 "function a() { this.x = 1; };"
18176 "a.displayName = 'display_a';"
18177 "var b = (function() {"
18178 " var f = function() { this.x = 2; };"
18179 " f.displayName = 'display_b';"
18180 " return f;"
18181 "})();"
18182 "var c = function() {};"
18183 "c.__defineGetter__('displayName', function() {"
18184 " error = true;"
18185 " throw new Error();"
18186 "});"
18187 "function d() {};"
18188 "d.__defineGetter__('displayName', function() {"
18189 " error = true;"
18190 " return 'wrong_display_name';"
18191 "});"
18192 "function e() {};"
18193 "e.displayName = 'wrong_display_name';"
18194 "e.__defineSetter__('displayName', function() {"
18195 " error = true;"
18196 " throw new Error();"
18197 "});"
18198 "function f() {};"
18199 "f.displayName = { 'foo': 6, toString: function() {"
18200 " error = true;"
18201 " return 'wrong_display_name';"
18202 "}};"
18203 "var g = function() {"
18204 " arguments.callee.displayName = 'set_in_runtime';"
18205 "}; g();"
18206 ;
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018207 v8::ScriptOrigin origin =
18208 v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
18209 v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), code), &origin)
18210 ->Run();
18211 v8::Local<v8::Value> error =
18212 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "error"));
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +000018213 v8::Local<v8::Function> a = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018214 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "a")));
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +000018215 v8::Local<v8::Function> b = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018216 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "b")));
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +000018217 v8::Local<v8::Function> c = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018218 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "c")));
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +000018219 v8::Local<v8::Function> d = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018220 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "d")));
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +000018221 v8::Local<v8::Function> e = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018222 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "e")));
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +000018223 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018224 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +000018225 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018226 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +000018227 CHECK_EQ(false, error->BooleanValue());
18228 CHECK_EQ("display_a", *v8::String::Utf8Value(a->GetDisplayName()));
18229 CHECK_EQ("display_b", *v8::String::Utf8Value(b->GetDisplayName()));
18230 CHECK(c->GetDisplayName()->IsUndefined());
18231 CHECK(d->GetDisplayName()->IsUndefined());
18232 CHECK(e->GetDisplayName()->IsUndefined());
18233 CHECK(f->GetDisplayName()->IsUndefined());
18234 CHECK_EQ("set_in_runtime", *v8::String::Utf8Value(g->GetDisplayName()));
18235}
18236
18237
ager@chromium.org5c838252010-02-19 08:53:10 +000018238THREADED_TEST(ScriptLineNumber) {
ager@chromium.org5c838252010-02-19 08:53:10 +000018239 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018240 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018241 v8::ScriptOrigin origin =
18242 v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
18243 v8::Handle<v8::String> script = v8::String::NewFromUtf8(
18244 env->GetIsolate(), "function f() {}\n\nfunction g() {}");
ager@chromium.org5c838252010-02-19 08:53:10 +000018245 v8::Script::Compile(script, &origin)->Run();
18246 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018247 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
ager@chromium.org5c838252010-02-19 08:53:10 +000018248 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018249 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
ager@chromium.org5c838252010-02-19 08:53:10 +000018250 CHECK_EQ(0, f->GetScriptLineNumber());
18251 CHECK_EQ(2, g->GetScriptLineNumber());
18252}
18253
18254
danno@chromium.orgc612e022011-11-10 11:38:15 +000018255THREADED_TEST(ScriptColumnNumber) {
danno@chromium.orgc612e022011-11-10 11:38:15 +000018256 LocalContext env;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018257 v8::Isolate* isolate = env->GetIsolate();
18258 v8::HandleScope scope(isolate);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018259 v8::ScriptOrigin origin =
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018260 v8::ScriptOrigin(v8::String::NewFromUtf8(isolate, "test"),
18261 v8::Integer::New(isolate, 3),
18262 v8::Integer::New(isolate, 2));
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018263 v8::Handle<v8::String> script = v8::String::NewFromUtf8(
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018264 isolate, "function foo() {}\n\n function bar() {}");
danno@chromium.orgc612e022011-11-10 11:38:15 +000018265 v8::Script::Compile(script, &origin)->Run();
18266 v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018267 env->Global()->Get(v8::String::NewFromUtf8(isolate, "foo")));
danno@chromium.orgc612e022011-11-10 11:38:15 +000018268 v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018269 env->Global()->Get(v8::String::NewFromUtf8(isolate, "bar")));
danno@chromium.orgc612e022011-11-10 11:38:15 +000018270 CHECK_EQ(14, foo->GetScriptColumnNumber());
18271 CHECK_EQ(17, bar->GetScriptColumnNumber());
18272}
18273
18274
bmeurer@chromium.orgdb783292013-10-23 06:51:00 +000018275THREADED_TEST(FunctionIsBuiltin) {
18276 LocalContext env;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018277 v8::Isolate* isolate = env->GetIsolate();
18278 v8::HandleScope scope(isolate);
bmeurer@chromium.orgdb783292013-10-23 06:51:00 +000018279 v8::Local<v8::Function> f;
18280 f = v8::Local<v8::Function>::Cast(CompileRun("Math.floor"));
18281 CHECK(f->IsBuiltin());
18282 f = v8::Local<v8::Function>::Cast(CompileRun("Object"));
18283 CHECK(f->IsBuiltin());
18284 f = v8::Local<v8::Function>::Cast(CompileRun("Object.__defineSetter__"));
18285 CHECK(f->IsBuiltin());
18286 f = v8::Local<v8::Function>::Cast(CompileRun("Array.prototype.toString"));
18287 CHECK(f->IsBuiltin());
18288 f = v8::Local<v8::Function>::Cast(CompileRun("function a() {}; a;"));
18289 CHECK(!f->IsBuiltin());
18290}
18291
18292
danno@chromium.orgc612e022011-11-10 11:38:15 +000018293THREADED_TEST(FunctionGetScriptId) {
danno@chromium.orgc612e022011-11-10 11:38:15 +000018294 LocalContext env;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018295 v8::Isolate* isolate = env->GetIsolate();
18296 v8::HandleScope scope(isolate);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018297 v8::ScriptOrigin origin =
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018298 v8::ScriptOrigin(v8::String::NewFromUtf8(isolate, "test"),
18299 v8::Integer::New(isolate, 3),
18300 v8::Integer::New(isolate, 2));
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018301 v8::Handle<v8::String> scriptSource = v8::String::NewFromUtf8(
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018302 isolate, "function foo() {}\n\n function bar() {}");
danno@chromium.orgc612e022011-11-10 11:38:15 +000018303 v8::Local<v8::Script> script(v8::Script::Compile(scriptSource, &origin));
18304 script->Run();
18305 v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018306 env->Global()->Get(v8::String::NewFromUtf8(isolate, "foo")));
danno@chromium.orgc612e022011-11-10 11:38:15 +000018307 v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018308 env->Global()->Get(v8::String::NewFromUtf8(isolate, "bar")));
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018309 CHECK_EQ(script->GetId(), foo->ScriptId());
18310 CHECK_EQ(script->GetId(), bar->ScriptId());
danno@chromium.orgc612e022011-11-10 11:38:15 +000018311}
18312
18313
yangguo@chromium.org49546742013-12-23 16:17:49 +000018314THREADED_TEST(FunctionGetBoundFunction) {
18315 LocalContext env;
18316 v8::HandleScope scope(env->GetIsolate());
18317 v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::NewFromUtf8(
18318 env->GetIsolate(), "test"));
18319 v8::Handle<v8::String> script = v8::String::NewFromUtf8(
18320 env->GetIsolate(),
18321 "var a = new Object();\n"
18322 "a.x = 1;\n"
18323 "function f () { return this.x };\n"
18324 "var g = f.bind(a);\n"
18325 "var b = g();");
18326 v8::Script::Compile(script, &origin)->Run();
18327 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
18328 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
18329 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
18330 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
18331 CHECK(g->GetBoundFunction()->IsFunction());
18332 Local<v8::Function> original_function = Local<v8::Function>::Cast(
18333 g->GetBoundFunction());
18334 CHECK_EQ(f->GetName(), original_function->GetName());
18335 CHECK_EQ(f->GetScriptLineNumber(), original_function->GetScriptLineNumber());
18336 CHECK_EQ(f->GetScriptColumnNumber(),
18337 original_function->GetScriptColumnNumber());
18338}
18339
18340
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018341static void GetterWhichReturns42(
18342 Local<String> name,
18343 const v8::PropertyCallbackInfo<v8::Value>& info) {
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000018344 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
18345 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018346 info.GetReturnValue().Set(v8_num(42));
ager@chromium.org5c838252010-02-19 08:53:10 +000018347}
18348
18349
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018350static void SetterWhichSetsYOnThisTo23(
18351 Local<String> name,
18352 Local<Value> value,
18353 const v8::PropertyCallbackInfo<void>& info) {
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000018354 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
18355 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
ager@chromium.org5c838252010-02-19 08:53:10 +000018356 info.This()->Set(v8_str("y"), v8_num(23));
18357}
18358
18359
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018360void FooGetInterceptor(Local<String> name,
18361 const v8::PropertyCallbackInfo<v8::Value>& info) {
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000018362 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
18363 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018364 if (!name->Equals(v8_str("foo"))) return;
18365 info.GetReturnValue().Set(v8_num(42));
erik.corry@gmail.com88767242012-08-08 14:43:45 +000018366}
18367
18368
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018369void FooSetInterceptor(Local<String> name,
18370 Local<Value> value,
18371 const v8::PropertyCallbackInfo<v8::Value>& info) {
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000018372 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
18373 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018374 if (!name->Equals(v8_str("foo"))) return;
erik.corry@gmail.com88767242012-08-08 14:43:45 +000018375 info.This()->Set(v8_str("y"), v8_num(23));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018376 info.GetReturnValue().Set(v8_num(23));
erik.corry@gmail.com88767242012-08-08 14:43:45 +000018377}
18378
18379
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000018380TEST(SetterOnConstructorPrototype) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000018381 v8::Isolate* isolate = CcTest::isolate();
18382 v8::HandleScope scope(isolate);
18383 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +000018384 templ->SetAccessor(v8_str("x"),
18385 GetterWhichReturns42,
18386 SetterWhichSetsYOnThisTo23);
18387 LocalContext context;
18388 context->Global()->Set(v8_str("P"), templ->NewInstance());
18389 CompileRun("function C1() {"
18390 " this.x = 23;"
18391 "};"
18392 "C1.prototype = P;"
18393 "function C2() {"
18394 " this.x = 23"
18395 "};"
18396 "C2.prototype = { };"
18397 "C2.prototype.__proto__ = P;");
18398
18399 v8::Local<v8::Script> script;
18400 script = v8::Script::Compile(v8_str("new C1();"));
18401 for (int i = 0; i < 10; i++) {
18402 v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
18403 CHECK_EQ(42, c1->Get(v8_str("x"))->Int32Value());
18404 CHECK_EQ(23, c1->Get(v8_str("y"))->Int32Value());
18405 }
18406
18407 script = v8::Script::Compile(v8_str("new C2();"));
18408 for (int i = 0; i < 10; i++) {
18409 v8::Handle<v8::Object> c2 = v8::Handle<v8::Object>::Cast(script->Run());
18410 CHECK_EQ(42, c2->Get(v8_str("x"))->Int32Value());
18411 CHECK_EQ(23, c2->Get(v8_str("y"))->Int32Value());
18412 }
18413}
18414
18415
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018416static void NamedPropertyGetterWhichReturns42(
18417 Local<String> name,
18418 const v8::PropertyCallbackInfo<v8::Value>& info) {
18419 info.GetReturnValue().Set(v8_num(42));
ager@chromium.org5c838252010-02-19 08:53:10 +000018420}
18421
18422
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018423static void NamedPropertySetterWhichSetsYOnThisTo23(
18424 Local<String> name,
18425 Local<Value> value,
18426 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.org5c838252010-02-19 08:53:10 +000018427 if (name->Equals(v8_str("x"))) {
18428 info.This()->Set(v8_str("y"), v8_num(23));
18429 }
ager@chromium.org5c838252010-02-19 08:53:10 +000018430}
18431
18432
18433THREADED_TEST(InterceptorOnConstructorPrototype) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000018434 v8::Isolate* isolate = CcTest::isolate();
18435 v8::HandleScope scope(isolate);
18436 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +000018437 templ->SetNamedPropertyHandler(NamedPropertyGetterWhichReturns42,
18438 NamedPropertySetterWhichSetsYOnThisTo23);
18439 LocalContext context;
18440 context->Global()->Set(v8_str("P"), templ->NewInstance());
18441 CompileRun("function C1() {"
18442 " this.x = 23;"
18443 "};"
18444 "C1.prototype = P;"
18445 "function C2() {"
18446 " this.x = 23"
18447 "};"
18448 "C2.prototype = { };"
18449 "C2.prototype.__proto__ = P;");
18450
18451 v8::Local<v8::Script> script;
18452 script = v8::Script::Compile(v8_str("new C1();"));
18453 for (int i = 0; i < 10; i++) {
18454 v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
18455 CHECK_EQ(23, c1->Get(v8_str("x"))->Int32Value());
18456 CHECK_EQ(42, c1->Get(v8_str("y"))->Int32Value());
18457 }
18458
18459 script = v8::Script::Compile(v8_str("new C2();"));
18460 for (int i = 0; i < 10; i++) {
18461 v8::Handle<v8::Object> c2 = v8::Handle<v8::Object>::Cast(script->Run());
18462 CHECK_EQ(23, c2->Get(v8_str("x"))->Int32Value());
18463 CHECK_EQ(42, c2->Get(v8_str("y"))->Int32Value());
18464 }
18465}
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000018466
18467
danno@chromium.orgf005df62013-04-30 16:36:45 +000018468TEST(Regress618) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000018469 const char* source = "function C1() {"
18470 " this.x = 23;"
18471 "};"
18472 "C1.prototype = P;";
18473
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000018474 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000018475 v8::Isolate* isolate = context->GetIsolate();
18476 v8::HandleScope scope(isolate);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000018477 v8::Local<v8::Script> script;
18478
18479 // Use a simple object as prototype.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000018480 v8::Local<v8::Object> prototype = v8::Object::New(isolate);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000018481 prototype->Set(v8_str("y"), v8_num(42));
18482 context->Global()->Set(v8_str("P"), prototype);
18483
18484 // This compile will add the code to the compilation cache.
18485 CompileRun(source);
18486
18487 script = v8::Script::Compile(v8_str("new C1();"));
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +000018488 // Allow enough iterations for the inobject slack tracking logic
18489 // to finalize instance size and install the fast construct stub.
18490 for (int i = 0; i < 256; i++) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000018491 v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
18492 CHECK_EQ(23, c1->Get(v8_str("x"))->Int32Value());
18493 CHECK_EQ(42, c1->Get(v8_str("y"))->Int32Value());
18494 }
18495
18496 // Use an API object with accessors as prototype.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000018497 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000018498 templ->SetAccessor(v8_str("x"),
18499 GetterWhichReturns42,
18500 SetterWhichSetsYOnThisTo23);
18501 context->Global()->Set(v8_str("P"), templ->NewInstance());
18502
18503 // This compile will get the code from the compilation cache.
18504 CompileRun(source);
18505
18506 script = v8::Script::Compile(v8_str("new C1();"));
18507 for (int i = 0; i < 10; i++) {
18508 v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
18509 CHECK_EQ(42, c1->Get(v8_str("x"))->Int32Value());
18510 CHECK_EQ(23, c1->Get(v8_str("y"))->Int32Value());
18511 }
18512}
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018513
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018514v8::Isolate* gc_callbacks_isolate = NULL;
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018515int prologue_call_count = 0;
18516int epilogue_call_count = 0;
18517int prologue_call_count_second = 0;
18518int epilogue_call_count_second = 0;
18519
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018520void PrologueCallback(v8::GCType, v8::GCCallbackFlags flags) {
18521 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018522 ++prologue_call_count;
18523}
18524
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000018525
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018526void PrologueCallback(v8::Isolate* isolate,
18527 v8::GCType,
18528 v8::GCCallbackFlags flags) {
18529 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
18530 CHECK_EQ(gc_callbacks_isolate, isolate);
18531 ++prologue_call_count;
18532}
18533
18534
18535void EpilogueCallback(v8::GCType, v8::GCCallbackFlags flags) {
18536 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018537 ++epilogue_call_count;
18538}
18539
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000018540
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018541void EpilogueCallback(v8::Isolate* isolate,
18542 v8::GCType,
18543 v8::GCCallbackFlags flags) {
18544 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
18545 CHECK_EQ(gc_callbacks_isolate, isolate);
18546 ++epilogue_call_count;
18547}
18548
18549
18550void PrologueCallbackSecond(v8::GCType, v8::GCCallbackFlags flags) {
18551 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018552 ++prologue_call_count_second;
18553}
18554
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000018555
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018556void PrologueCallbackSecond(v8::Isolate* isolate,
18557 v8::GCType,
18558 v8::GCCallbackFlags flags) {
18559 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
18560 CHECK_EQ(gc_callbacks_isolate, isolate);
18561 ++prologue_call_count_second;
18562}
18563
18564
18565void EpilogueCallbackSecond(v8::GCType, v8::GCCallbackFlags flags) {
18566 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018567 ++epilogue_call_count_second;
18568}
18569
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000018570
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018571void EpilogueCallbackSecond(v8::Isolate* isolate,
18572 v8::GCType,
18573 v8::GCCallbackFlags flags) {
18574 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
18575 CHECK_EQ(gc_callbacks_isolate, isolate);
18576 ++epilogue_call_count_second;
18577}
18578
18579
18580TEST(GCCallbacksOld) {
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018581 LocalContext context;
18582
18583 v8::V8::AddGCPrologueCallback(PrologueCallback);
18584 v8::V8::AddGCEpilogueCallback(EpilogueCallback);
18585 CHECK_EQ(0, prologue_call_count);
18586 CHECK_EQ(0, epilogue_call_count);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018587 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018588 CHECK_EQ(1, prologue_call_count);
18589 CHECK_EQ(1, epilogue_call_count);
18590 v8::V8::AddGCPrologueCallback(PrologueCallbackSecond);
18591 v8::V8::AddGCEpilogueCallback(EpilogueCallbackSecond);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018592 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018593 CHECK_EQ(2, prologue_call_count);
18594 CHECK_EQ(2, epilogue_call_count);
18595 CHECK_EQ(1, prologue_call_count_second);
18596 CHECK_EQ(1, epilogue_call_count_second);
18597 v8::V8::RemoveGCPrologueCallback(PrologueCallback);
18598 v8::V8::RemoveGCEpilogueCallback(EpilogueCallback);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018599 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018600 CHECK_EQ(2, prologue_call_count);
18601 CHECK_EQ(2, epilogue_call_count);
18602 CHECK_EQ(2, prologue_call_count_second);
18603 CHECK_EQ(2, epilogue_call_count_second);
18604 v8::V8::RemoveGCPrologueCallback(PrologueCallbackSecond);
18605 v8::V8::RemoveGCEpilogueCallback(EpilogueCallbackSecond);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018606 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
18607 CHECK_EQ(2, prologue_call_count);
18608 CHECK_EQ(2, epilogue_call_count);
18609 CHECK_EQ(2, prologue_call_count_second);
18610 CHECK_EQ(2, epilogue_call_count_second);
18611}
18612
18613
18614TEST(GCCallbacks) {
18615 LocalContext context;
18616 v8::Isolate* isolate = context->GetIsolate();
18617 gc_callbacks_isolate = isolate;
18618 isolate->AddGCPrologueCallback(PrologueCallback);
18619 isolate->AddGCEpilogueCallback(EpilogueCallback);
18620 CHECK_EQ(0, prologue_call_count);
18621 CHECK_EQ(0, epilogue_call_count);
18622 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
18623 CHECK_EQ(1, prologue_call_count);
18624 CHECK_EQ(1, epilogue_call_count);
18625 isolate->AddGCPrologueCallback(PrologueCallbackSecond);
18626 isolate->AddGCEpilogueCallback(EpilogueCallbackSecond);
18627 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
18628 CHECK_EQ(2, prologue_call_count);
18629 CHECK_EQ(2, epilogue_call_count);
18630 CHECK_EQ(1, prologue_call_count_second);
18631 CHECK_EQ(1, epilogue_call_count_second);
18632 isolate->RemoveGCPrologueCallback(PrologueCallback);
18633 isolate->RemoveGCEpilogueCallback(EpilogueCallback);
18634 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
18635 CHECK_EQ(2, prologue_call_count);
18636 CHECK_EQ(2, epilogue_call_count);
18637 CHECK_EQ(2, prologue_call_count_second);
18638 CHECK_EQ(2, epilogue_call_count_second);
18639 isolate->RemoveGCPrologueCallback(PrologueCallbackSecond);
18640 isolate->RemoveGCEpilogueCallback(EpilogueCallbackSecond);
18641 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018642 CHECK_EQ(2, prologue_call_count);
18643 CHECK_EQ(2, epilogue_call_count);
18644 CHECK_EQ(2, prologue_call_count_second);
18645 CHECK_EQ(2, epilogue_call_count_second);
18646}
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018647
18648
18649THREADED_TEST(AddToJSFunctionResultCache) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018650 i::FLAG_stress_compaction = false;
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018651 i::FLAG_allow_natives_syntax = true;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018652 v8::HandleScope scope(CcTest::isolate());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018653
18654 LocalContext context;
18655
18656 const char* code =
18657 "(function() {"
18658 " var key0 = 'a';"
18659 " var key1 = 'b';"
18660 " var r0 = %_GetFromCache(0, key0);"
18661 " var r1 = %_GetFromCache(0, key1);"
18662 " var r0_ = %_GetFromCache(0, key0);"
18663 " if (r0 !== r0_)"
18664 " return 'Different results for ' + key0 + ': ' + r0 + ' vs. ' + r0_;"
18665 " var r1_ = %_GetFromCache(0, key1);"
18666 " if (r1 !== r1_)"
18667 " return 'Different results for ' + key1 + ': ' + r1 + ' vs. ' + r1_;"
18668 " return 'PASSED';"
18669 "})()";
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018670 CcTest::heap()->ClearJSFunctionResultCaches();
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018671 ExpectString(code, "PASSED");
18672}
18673
18674
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018675THREADED_TEST(FillJSFunctionResultCache) {
18676 i::FLAG_allow_natives_syntax = true;
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018677 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018678 v8::HandleScope scope(context->GetIsolate());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018679
18680 const char* code =
18681 "(function() {"
18682 " var k = 'a';"
18683 " var r = %_GetFromCache(0, k);"
18684 " for (var i = 0; i < 16; i++) {"
18685 " %_GetFromCache(0, 'a' + i);"
18686 " };"
18687 " if (r === %_GetFromCache(0, k))"
18688 " return 'FAILED: k0CacheSize is too small';"
18689 " return 'PASSED';"
18690 "})()";
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018691 CcTest::heap()->ClearJSFunctionResultCaches();
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018692 ExpectString(code, "PASSED");
18693}
18694
18695
18696THREADED_TEST(RoundRobinGetFromCache) {
18697 i::FLAG_allow_natives_syntax = true;
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018698 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018699 v8::HandleScope scope(context->GetIsolate());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018700
18701 const char* code =
18702 "(function() {"
18703 " var keys = [];"
18704 " for (var i = 0; i < 16; i++) keys.push(i);"
18705 " var values = [];"
18706 " for (var i = 0; i < 16; i++) values[i] = %_GetFromCache(0, keys[i]);"
18707 " for (var i = 0; i < 16; i++) {"
18708 " var v = %_GetFromCache(0, keys[i]);"
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000018709 " if (v.toString() !== values[i].toString())"
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018710 " return 'Wrong value for ' + "
18711 " keys[i] + ': ' + v + ' vs. ' + values[i];"
18712 " };"
18713 " return 'PASSED';"
18714 "})()";
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018715 CcTest::heap()->ClearJSFunctionResultCaches();
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018716 ExpectString(code, "PASSED");
18717}
18718
18719
18720THREADED_TEST(ReverseGetFromCache) {
18721 i::FLAG_allow_natives_syntax = true;
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018722 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018723 v8::HandleScope scope(context->GetIsolate());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018724
18725 const char* code =
18726 "(function() {"
18727 " var keys = [];"
18728 " for (var i = 0; i < 16; i++) keys.push(i);"
18729 " var values = [];"
18730 " for (var i = 0; i < 16; i++) values[i] = %_GetFromCache(0, keys[i]);"
18731 " for (var i = 15; i >= 16; i--) {"
18732 " var v = %_GetFromCache(0, keys[i]);"
18733 " if (v !== values[i])"
18734 " return 'Wrong value for ' + "
18735 " keys[i] + ': ' + v + ' vs. ' + values[i];"
18736 " };"
18737 " return 'PASSED';"
18738 "})()";
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018739 CcTest::heap()->ClearJSFunctionResultCaches();
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018740 ExpectString(code, "PASSED");
18741}
18742
18743
18744THREADED_TEST(TestEviction) {
18745 i::FLAG_allow_natives_syntax = true;
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018746 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018747 v8::HandleScope scope(context->GetIsolate());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018748
18749 const char* code =
18750 "(function() {"
18751 " for (var i = 0; i < 2*16; i++) {"
18752 " %_GetFromCache(0, 'a' + i);"
18753 " };"
18754 " return 'PASSED';"
18755 "})()";
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018756 CcTest::heap()->ClearJSFunctionResultCaches();
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018757 ExpectString(code, "PASSED");
18758}
lrn@chromium.org32d961d2010-06-30 09:09:34 +000018759
18760
18761THREADED_TEST(TwoByteStringInAsciiCons) {
18762 // See Chromium issue 47824.
lrn@chromium.org32d961d2010-06-30 09:09:34 +000018763 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018764 v8::HandleScope scope(context->GetIsolate());
18765
lrn@chromium.org32d961d2010-06-30 09:09:34 +000018766 const char* init_code =
18767 "var str1 = 'abelspendabel';"
18768 "var str2 = str1 + str1 + str1;"
18769 "str2;";
18770 Local<Value> result = CompileRun(init_code);
18771
ricow@chromium.orgddd545c2011-08-24 12:02:41 +000018772 Local<Value> indexof = CompileRun("str2.indexOf('els')");
18773 Local<Value> lastindexof = CompileRun("str2.lastIndexOf('dab')");
18774
lrn@chromium.org32d961d2010-06-30 09:09:34 +000018775 CHECK(result->IsString());
18776 i::Handle<i::String> string = v8::Utils::OpenHandle(String::Cast(*result));
18777 int length = string->length();
ulan@chromium.org8e8d8822012-11-23 14:36:46 +000018778 CHECK(string->IsOneByteRepresentation());
lrn@chromium.org32d961d2010-06-30 09:09:34 +000018779
18780 FlattenString(string);
18781 i::Handle<i::String> flat_string = FlattenGetString(string);
18782
ulan@chromium.org8e8d8822012-11-23 14:36:46 +000018783 CHECK(string->IsOneByteRepresentation());
18784 CHECK(flat_string->IsOneByteRepresentation());
lrn@chromium.org32d961d2010-06-30 09:09:34 +000018785
18786 // Create external resource.
18787 uint16_t* uc16_buffer = new uint16_t[length + 1];
18788
18789 i::String::WriteToFlat(*flat_string, uc16_buffer, 0, length);
18790 uc16_buffer[length] = 0;
18791
18792 TestResource resource(uc16_buffer);
18793
18794 flat_string->MakeExternal(&resource);
18795
18796 CHECK(flat_string->IsTwoByteRepresentation());
18797
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +000018798 // If the cons string has been short-circuited, skip the following checks.
18799 if (!string.is_identical_to(flat_string)) {
18800 // At this point, we should have a Cons string which is flat and ASCII,
18801 // with a first half that is a two-byte string (although it only contains
18802 // ASCII characters). This is a valid sequence of steps, and it can happen
18803 // in real pages.
18804 CHECK(string->IsOneByteRepresentation());
18805 i::ConsString* cons = i::ConsString::cast(*string);
18806 CHECK_EQ(0, cons->second()->length());
18807 CHECK(cons->first()->IsTwoByteRepresentation());
18808 }
lrn@chromium.org32d961d2010-06-30 09:09:34 +000018809
18810 // Check that some string operations work.
18811
18812 // Atom RegExp.
18813 Local<Value> reresult = CompileRun("str2.match(/abel/g).length;");
18814 CHECK_EQ(6, reresult->Int32Value());
18815
18816 // Nonatom RegExp.
18817 reresult = CompileRun("str2.match(/abe./g).length;");
18818 CHECK_EQ(6, reresult->Int32Value());
18819
18820 reresult = CompileRun("str2.search(/bel/g);");
18821 CHECK_EQ(1, reresult->Int32Value());
18822
18823 reresult = CompileRun("str2.search(/be./g);");
18824 CHECK_EQ(1, reresult->Int32Value());
18825
18826 ExpectTrue("/bel/g.test(str2);");
18827
18828 ExpectTrue("/be./g.test(str2);");
18829
18830 reresult = CompileRun("/bel/g.exec(str2);");
18831 CHECK(!reresult->IsNull());
18832
18833 reresult = CompileRun("/be./g.exec(str2);");
18834 CHECK(!reresult->IsNull());
18835
18836 ExpectString("str2.substring(2, 10);", "elspenda");
18837
18838 ExpectString("str2.substring(2, 20);", "elspendabelabelspe");
18839
18840 ExpectString("str2.charAt(2);", "e");
18841
ricow@chromium.orgddd545c2011-08-24 12:02:41 +000018842 ExpectObject("str2.indexOf('els');", indexof);
18843
18844 ExpectObject("str2.lastIndexOf('dab');", lastindexof);
18845
lrn@chromium.org32d961d2010-06-30 09:09:34 +000018846 reresult = CompileRun("str2.charCodeAt(2);");
18847 CHECK_EQ(static_cast<int32_t>('e'), reresult->Int32Value());
18848}
ager@chromium.orgea4f62e2010-08-16 16:28:43 +000018849
18850
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000018851TEST(ContainsOnlyOneByte) {
18852 v8::V8::Initialize();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018853 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000018854 v8::HandleScope scope(isolate);
18855 // Make a buffer long enough that it won't automatically be converted.
verwaest@chromium.org8a00e822013-06-10 15:11:22 +000018856 const int length = 512;
18857 // Ensure word aligned assignment.
18858 const int aligned_length = length*sizeof(uintptr_t)/sizeof(uint16_t);
18859 i::SmartArrayPointer<uintptr_t>
18860 aligned_contents(new uintptr_t[aligned_length]);
machenbach@chromium.orgafbdadc2013-12-09 16:12:18 +000018861 uint16_t* string_contents =
18862 reinterpret_cast<uint16_t*>(aligned_contents.get());
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000018863 // Set to contain only one byte.
18864 for (int i = 0; i < length-1; i++) {
18865 string_contents[i] = 0x41;
18866 }
18867 string_contents[length-1] = 0;
18868 // Simple case.
18869 Handle<String> string;
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000018870 string = String::NewExternal(isolate, new TestResource(string_contents));
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000018871 CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
18872 // Counter example.
verwaest@chromium.org8a00e822013-06-10 15:11:22 +000018873 string = String::NewFromTwoByte(isolate, string_contents);
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000018874 CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
18875 // Test left right and balanced cons strings.
18876 Handle<String> base = String::NewFromUtf8(isolate, "a");
18877 Handle<String> left = base;
18878 Handle<String> right = base;
18879 for (int i = 0; i < 1000; i++) {
18880 left = String::Concat(base, left);
18881 right = String::Concat(right, base);
18882 }
18883 Handle<String> balanced = String::Concat(left, base);
18884 balanced = String::Concat(balanced, right);
18885 Handle<String> cons_strings[] = {left, balanced, right};
18886 Handle<String> two_byte =
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000018887 String::NewExternal(isolate, new TestResource(string_contents));
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000018888 for (size_t i = 0; i < ARRAY_SIZE(cons_strings); i++) {
18889 // Base assumptions.
18890 string = cons_strings[i];
18891 CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
18892 // Test left and right concatentation.
18893 string = String::Concat(two_byte, cons_strings[i]);
18894 CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
18895 string = String::Concat(cons_strings[i], two_byte);
18896 CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
18897 }
verwaest@chromium.org8a00e822013-06-10 15:11:22 +000018898 // Set bits in different positions
18899 // for strings of different lengths and alignments.
18900 for (int alignment = 0; alignment < 7; alignment++) {
18901 for (int size = 2; alignment + size < length; size *= 2) {
18902 int zero_offset = size + alignment;
18903 string_contents[zero_offset] = 0;
18904 for (int i = 0; i < size; i++) {
18905 int shift = 8 + (i % 7);
18906 string_contents[alignment + i] = 1 << shift;
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000018907 string = String::NewExternal(
18908 isolate, new TestResource(string_contents + alignment));
verwaest@chromium.org8a00e822013-06-10 15:11:22 +000018909 CHECK_EQ(size, string->Length());
18910 CHECK(!string->ContainsOnlyOneByte());
18911 string_contents[alignment + i] = 0x41;
18912 }
18913 string_contents[zero_offset] = 0x41;
18914 }
18915 }
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000018916}
18917
18918
ager@chromium.orgea4f62e2010-08-16 16:28:43 +000018919// Failed access check callback that performs a GC on each invocation.
18920void FailedAccessCheckCallbackGC(Local<v8::Object> target,
18921 v8::AccessType type,
18922 Local<v8::Value> data) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018923 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.orgea4f62e2010-08-16 16:28:43 +000018924}
18925
18926
18927TEST(GCInFailedAccessCheckCallback) {
18928 // Install a failed access check callback that performs a GC on each
18929 // invocation. Then force the callback to be called from va
18930
18931 v8::V8::Initialize();
18932 v8::V8::SetFailedAccessCheckCallbackFunction(&FailedAccessCheckCallbackGC);
18933
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000018934 v8::Isolate* isolate = CcTest::isolate();
18935 v8::HandleScope scope(isolate);
ager@chromium.orgea4f62e2010-08-16 16:28:43 +000018936
18937 // Create an ObjectTemplate for global objects and install access
18938 // check callbacks that will block access.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000018939 v8::Handle<v8::ObjectTemplate> global_template =
18940 v8::ObjectTemplate::New(isolate);
ager@chromium.orgea4f62e2010-08-16 16:28:43 +000018941 global_template->SetAccessCheckCallbacks(NamedGetAccessBlocker,
18942 IndexedGetAccessBlocker,
18943 v8::Handle<v8::Value>(),
18944 false);
18945
18946 // Create a context and set an x property on it's global object.
18947 LocalContext context0(NULL, global_template);
18948 context0->Global()->Set(v8_str("x"), v8_num(42));
18949 v8::Handle<v8::Object> global0 = context0->Global();
18950
18951 // Create a context with a different security token so that the
18952 // failed access check callback will be called on each access.
18953 LocalContext context1(NULL, global_template);
18954 context1->Global()->Set(v8_str("other"), global0);
18955
18956 // Get property with failed access check.
18957 ExpectUndefined("other.x");
18958
18959 // Get element with failed access check.
18960 ExpectUndefined("other[0]");
18961
18962 // Set property with failed access check.
18963 v8::Handle<v8::Value> result = CompileRun("other.x = new Object()");
18964 CHECK(result->IsObject());
18965
18966 // Set element with failed access check.
18967 result = CompileRun("other[0] = new Object()");
18968 CHECK(result->IsObject());
18969
18970 // Get property attribute with failed access check.
18971 ExpectFalse("\'x\' in other");
18972
18973 // Get property attribute for element with failed access check.
18974 ExpectFalse("0 in other");
18975
18976 // Delete property.
18977 ExpectFalse("delete other.x");
18978
18979 // Delete element.
18980 CHECK_EQ(false, global0->Delete(0));
18981
18982 // DefineAccessor.
18983 CHECK_EQ(false,
18984 global0->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("x")));
18985
18986 // Define JavaScript accessor.
18987 ExpectUndefined("Object.prototype.__defineGetter__.call("
18988 " other, \'x\', function() { return 42; })");
18989
18990 // LookupAccessor.
18991 ExpectUndefined("Object.prototype.__lookupGetter__.call("
18992 " other, \'x\')");
18993
18994 // HasLocalElement.
18995 ExpectFalse("Object.prototype.hasOwnProperty.call(other, \'0\')");
18996
18997 CHECK_EQ(false, global0->HasRealIndexedProperty(0));
18998 CHECK_EQ(false, global0->HasRealNamedProperty(v8_str("x")));
18999 CHECK_EQ(false, global0->HasRealNamedCallbackProperty(v8_str("x")));
19000
19001 // Reset the failed access check callback so it does not influence
19002 // the other tests.
19003 v8::V8::SetFailedAccessCheckCallbackFunction(NULL);
19004}
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019005
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019006
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019007TEST(IsolateNewDispose) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019008 v8::Isolate* current_isolate = CcTest::isolate();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019009 v8::Isolate* isolate = v8::Isolate::New();
19010 CHECK(isolate != NULL);
19011 CHECK(!reinterpret_cast<i::Isolate*>(isolate)->IsDefaultIsolate());
19012 CHECK(current_isolate != isolate);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019013 CHECK(current_isolate == CcTest::isolate());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019014
19015 v8::V8::SetFatalErrorHandler(StoringErrorCallback);
19016 last_location = last_message = NULL;
19017 isolate->Dispose();
19018 CHECK_EQ(last_location, NULL);
19019 CHECK_EQ(last_message, NULL);
19020}
19021
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019022
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019023UNINITIALIZED_TEST(DisposeIsolateWhenInUse) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019024 v8::Isolate* isolate = v8::Isolate::New();
19025 CHECK(isolate);
19026 isolate->Enter();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019027 v8::HandleScope scope(isolate);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019028 LocalContext context(isolate);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019029 // Run something in this isolate.
19030 ExpectTrue("true");
19031 v8::V8::SetFatalErrorHandler(StoringErrorCallback);
19032 last_location = last_message = NULL;
19033 // Still entered, should fail.
19034 isolate->Dispose();
19035 CHECK_NE(last_location, NULL);
19036 CHECK_NE(last_message, NULL);
19037}
19038
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019039
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019040TEST(RunTwoIsolatesOnSingleThread) {
19041 // Run isolate 1.
19042 v8::Isolate* isolate1 = v8::Isolate::New();
19043 isolate1->Enter();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000019044 v8::Persistent<v8::Context> context1;
19045 {
19046 v8::HandleScope scope(isolate1);
19047 context1.Reset(isolate1, Context::New(isolate1));
19048 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019049
19050 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019051 v8::HandleScope scope(isolate1);
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000019052 v8::Local<v8::Context> context =
19053 v8::Local<v8::Context>::New(isolate1, context1);
19054 v8::Context::Scope context_scope(context);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019055 // Run something in new isolate.
19056 CompileRun("var foo = 'isolate 1';");
19057 ExpectString("function f() { return foo; }; f()", "isolate 1");
19058 }
19059
19060 // Run isolate 2.
19061 v8::Isolate* isolate2 = v8::Isolate::New();
19062 v8::Persistent<v8::Context> context2;
19063
19064 {
19065 v8::Isolate::Scope iscope(isolate2);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019066 v8::HandleScope scope(isolate2);
ulan@chromium.org57ff8812013-05-10 08:16:55 +000019067 context2.Reset(isolate2, Context::New(isolate2));
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000019068 v8::Local<v8::Context> context =
19069 v8::Local<v8::Context>::New(isolate2, context2);
19070 v8::Context::Scope context_scope(context);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019071
19072 // Run something in new isolate.
19073 CompileRun("var foo = 'isolate 2';");
19074 ExpectString("function f() { return foo; }; f()", "isolate 2");
19075 }
19076
19077 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019078 v8::HandleScope scope(isolate1);
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000019079 v8::Local<v8::Context> context =
19080 v8::Local<v8::Context>::New(isolate1, context1);
19081 v8::Context::Scope context_scope(context);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019082 // Now again in isolate 1
19083 ExpectString("function f() { return foo; }; f()", "isolate 1");
19084 }
19085
19086 isolate1->Exit();
19087
19088 // Run some stuff in default isolate.
ulan@chromium.org57ff8812013-05-10 08:16:55 +000019089 v8::Persistent<v8::Context> context_default;
19090 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019091 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000019092 v8::Isolate::Scope iscope(isolate);
19093 v8::HandleScope scope(isolate);
19094 context_default.Reset(isolate, Context::New(isolate));
19095 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019096
19097 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019098 v8::HandleScope scope(CcTest::isolate());
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000019099 v8::Local<v8::Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019100 v8::Local<v8::Context>::New(CcTest::isolate(), context_default);
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000019101 v8::Context::Scope context_scope(context);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019102 // Variables in other isolates should be not available, verify there
19103 // is an exception.
19104 ExpectTrue("function f() {"
19105 " try {"
19106 " foo;"
19107 " return false;"
19108 " } catch(e) {"
19109 " return true;"
19110 " }"
19111 "};"
19112 "var isDefaultIsolate = true;"
19113 "f()");
19114 }
19115
19116 isolate1->Enter();
19117
19118 {
19119 v8::Isolate::Scope iscope(isolate2);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019120 v8::HandleScope scope(isolate2);
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000019121 v8::Local<v8::Context> context =
19122 v8::Local<v8::Context>::New(isolate2, context2);
19123 v8::Context::Scope context_scope(context);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019124 ExpectString("function f() { return foo; }; f()", "isolate 2");
19125 }
19126
19127 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019128 v8::HandleScope scope(v8::Isolate::GetCurrent());
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000019129 v8::Local<v8::Context> context =
19130 v8::Local<v8::Context>::New(v8::Isolate::GetCurrent(), context1);
19131 v8::Context::Scope context_scope(context);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019132 ExpectString("function f() { return foo; }; f()", "isolate 1");
19133 }
19134
19135 {
19136 v8::Isolate::Scope iscope(isolate2);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000019137 context2.Reset();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019138 }
19139
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000019140 context1.Reset();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019141 isolate1->Exit();
19142
19143 v8::V8::SetFatalErrorHandler(StoringErrorCallback);
19144 last_location = last_message = NULL;
19145
19146 isolate1->Dispose();
19147 CHECK_EQ(last_location, NULL);
19148 CHECK_EQ(last_message, NULL);
19149
19150 isolate2->Dispose();
19151 CHECK_EQ(last_location, NULL);
19152 CHECK_EQ(last_message, NULL);
19153
19154 // Check that default isolate still runs.
19155 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019156 v8::HandleScope scope(CcTest::isolate());
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000019157 v8::Local<v8::Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019158 v8::Local<v8::Context>::New(CcTest::isolate(), context_default);
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000019159 v8::Context::Scope context_scope(context);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019160 ExpectTrue("function f() { return isDefaultIsolate; }; f()");
19161 }
19162}
19163
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019164
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019165static int CalcFibonacci(v8::Isolate* isolate, int limit) {
19166 v8::Isolate::Scope isolate_scope(isolate);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019167 v8::HandleScope scope(isolate);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019168 LocalContext context(isolate);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019169 i::ScopedVector<char> code(1024);
19170 i::OS::SNPrintF(code, "function fib(n) {"
19171 " if (n <= 2) return 1;"
19172 " return fib(n-1) + fib(n-2);"
19173 "}"
19174 "fib(%d)", limit);
19175 Local<Value> value = CompileRun(code.start());
19176 CHECK(value->IsNumber());
19177 return static_cast<int>(value->NumberValue());
19178}
19179
19180class IsolateThread : public v8::internal::Thread {
19181 public:
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000019182 IsolateThread(v8::Isolate* isolate, int fib_limit)
19183 : Thread("IsolateThread"),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019184 isolate_(isolate),
19185 fib_limit_(fib_limit),
19186 result_(0) { }
19187
19188 void Run() {
19189 result_ = CalcFibonacci(isolate_, fib_limit_);
19190 }
19191
19192 int result() { return result_; }
19193
19194 private:
19195 v8::Isolate* isolate_;
19196 int fib_limit_;
19197 int result_;
19198};
19199
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019200
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019201TEST(MultipleIsolatesOnIndividualThreads) {
19202 v8::Isolate* isolate1 = v8::Isolate::New();
19203 v8::Isolate* isolate2 = v8::Isolate::New();
19204
19205 IsolateThread thread1(isolate1, 21);
19206 IsolateThread thread2(isolate2, 12);
19207
19208 // Compute some fibonacci numbers on 3 threads in 3 isolates.
19209 thread1.Start();
19210 thread2.Start();
19211
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019212 int result1 = CalcFibonacci(CcTest::isolate(), 21);
19213 int result2 = CalcFibonacci(CcTest::isolate(), 12);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019214
19215 thread1.Join();
19216 thread2.Join();
19217
19218 // Compare results. The actual fibonacci numbers for 12 and 21 are taken
19219 // (I'm lazy!) from http://en.wikipedia.org/wiki/Fibonacci_number
19220 CHECK_EQ(result1, 10946);
19221 CHECK_EQ(result2, 144);
19222 CHECK_EQ(result1, thread1.result());
19223 CHECK_EQ(result2, thread2.result());
19224
19225 isolate1->Dispose();
19226 isolate2->Dispose();
19227}
19228
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019229
lrn@chromium.org1c092762011-05-09 09:42:16 +000019230TEST(IsolateDifferentContexts) {
19231 v8::Isolate* isolate = v8::Isolate::New();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000019232 Local<v8::Context> context;
lrn@chromium.org1c092762011-05-09 09:42:16 +000019233 {
19234 v8::Isolate::Scope isolate_scope(isolate);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019235 v8::HandleScope handle_scope(isolate);
ulan@chromium.org57ff8812013-05-10 08:16:55 +000019236 context = v8::Context::New(isolate);
lrn@chromium.org1c092762011-05-09 09:42:16 +000019237 v8::Context::Scope context_scope(context);
19238 Local<Value> v = CompileRun("2");
19239 CHECK(v->IsNumber());
19240 CHECK_EQ(2, static_cast<int>(v->NumberValue()));
19241 }
19242 {
19243 v8::Isolate::Scope isolate_scope(isolate);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019244 v8::HandleScope handle_scope(isolate);
ulan@chromium.org57ff8812013-05-10 08:16:55 +000019245 context = v8::Context::New(isolate);
lrn@chromium.org1c092762011-05-09 09:42:16 +000019246 v8::Context::Scope context_scope(context);
19247 Local<Value> v = CompileRun("22");
19248 CHECK(v->IsNumber());
19249 CHECK_EQ(22, static_cast<int>(v->NumberValue()));
19250 }
19251}
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019252
19253class InitDefaultIsolateThread : public v8::internal::Thread {
19254 public:
sgjesse@chromium.orge0599052011-03-25 07:34:35 +000019255 enum TestCase {
19256 IgnoreOOM,
19257 SetResourceConstraints,
19258 SetFatalHandler,
19259 SetCounterFunction,
19260 SetCreateHistogramFunction,
19261 SetAddHistogramSampleFunction
19262 };
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019263
19264 explicit InitDefaultIsolateThread(TestCase testCase)
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000019265 : Thread("InitDefaultIsolateThread"),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019266 testCase_(testCase),
19267 result_(false) { }
19268
19269 void Run() {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019270 v8::Isolate* isolate = v8::Isolate::New();
19271 isolate->Enter();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019272 switch (testCase_) {
19273 case IgnoreOOM:
19274 v8::V8::IgnoreOutOfMemoryException();
19275 break;
19276
19277 case SetResourceConstraints: {
19278 static const int K = 1024;
19279 v8::ResourceConstraints constraints;
19280 constraints.set_max_young_space_size(256 * K);
19281 constraints.set_max_old_space_size(4 * K * K);
machenbach@chromium.org7ff76072013-11-21 09:47:43 +000019282 v8::SetResourceConstraints(CcTest::isolate(), &constraints);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019283 break;
19284 }
19285
19286 case SetFatalHandler:
19287 v8::V8::SetFatalErrorHandler(NULL);
19288 break;
sgjesse@chromium.orge0599052011-03-25 07:34:35 +000019289
19290 case SetCounterFunction:
19291 v8::V8::SetCounterFunction(NULL);
19292 break;
19293
19294 case SetCreateHistogramFunction:
19295 v8::V8::SetCreateHistogramFunction(NULL);
19296 break;
19297
19298 case SetAddHistogramSampleFunction:
19299 v8::V8::SetAddHistogramSampleFunction(NULL);
19300 break;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019301 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019302 isolate->Exit();
19303 isolate->Dispose();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019304 result_ = true;
19305 }
19306
19307 bool result() { return result_; }
19308
19309 private:
19310 TestCase testCase_;
19311 bool result_;
19312};
19313
19314
19315static void InitializeTestHelper(InitDefaultIsolateThread::TestCase testCase) {
19316 InitDefaultIsolateThread thread(testCase);
19317 thread.Start();
19318 thread.Join();
19319 CHECK_EQ(thread.result(), true);
19320}
19321
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019322
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019323TEST(InitializeDefaultIsolateOnSecondaryThread1) {
19324 InitializeTestHelper(InitDefaultIsolateThread::IgnoreOOM);
19325}
19326
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019327
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019328TEST(InitializeDefaultIsolateOnSecondaryThread2) {
19329 InitializeTestHelper(InitDefaultIsolateThread::SetResourceConstraints);
19330}
19331
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019332
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019333TEST(InitializeDefaultIsolateOnSecondaryThread3) {
19334 InitializeTestHelper(InitDefaultIsolateThread::SetFatalHandler);
19335}
19336
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019337
sgjesse@chromium.orge0599052011-03-25 07:34:35 +000019338TEST(InitializeDefaultIsolateOnSecondaryThread4) {
19339 InitializeTestHelper(InitDefaultIsolateThread::SetCounterFunction);
19340}
19341
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019342
sgjesse@chromium.orge0599052011-03-25 07:34:35 +000019343TEST(InitializeDefaultIsolateOnSecondaryThread5) {
19344 InitializeTestHelper(InitDefaultIsolateThread::SetCreateHistogramFunction);
19345}
19346
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019347
sgjesse@chromium.orge0599052011-03-25 07:34:35 +000019348TEST(InitializeDefaultIsolateOnSecondaryThread6) {
19349 InitializeTestHelper(InitDefaultIsolateThread::SetAddHistogramSampleFunction);
19350}
19351
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019352
19353TEST(StringCheckMultipleContexts) {
19354 const char* code =
19355 "(function() { return \"a\".charAt(0); })()";
19356
19357 {
19358 // Run the code twice in the first context to initialize the call IC.
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019359 LocalContext context1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019360 v8::HandleScope scope(context1->GetIsolate());
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019361 ExpectString(code, "a");
19362 ExpectString(code, "a");
19363 }
19364
19365 {
19366 // Change the String.prototype in the second context and check
19367 // that the right function gets called.
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019368 LocalContext context2;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019369 v8::HandleScope scope(context2->GetIsolate());
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019370 CompileRun("String.prototype.charAt = function() { return \"not a\"; }");
19371 ExpectString(code, "not a");
19372 }
19373}
19374
19375
19376TEST(NumberCheckMultipleContexts) {
19377 const char* code =
19378 "(function() { return (42).toString(); })()";
19379
19380 {
19381 // Run the code twice in the first context to initialize the call IC.
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019382 LocalContext context1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019383 v8::HandleScope scope(context1->GetIsolate());
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019384 ExpectString(code, "42");
19385 ExpectString(code, "42");
19386 }
19387
19388 {
19389 // Change the Number.prototype in the second context and check
19390 // that the right function gets called.
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019391 LocalContext context2;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019392 v8::HandleScope scope(context2->GetIsolate());
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019393 CompileRun("Number.prototype.toString = function() { return \"not 42\"; }");
19394 ExpectString(code, "not 42");
19395 }
19396}
19397
19398
19399TEST(BooleanCheckMultipleContexts) {
19400 const char* code =
19401 "(function() { return true.toString(); })()";
19402
19403 {
19404 // Run the code twice in the first context to initialize the call IC.
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019405 LocalContext context1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019406 v8::HandleScope scope(context1->GetIsolate());
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019407 ExpectString(code, "true");
19408 ExpectString(code, "true");
19409 }
19410
19411 {
19412 // Change the Boolean.prototype in the second context and check
19413 // that the right function gets called.
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019414 LocalContext context2;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019415 v8::HandleScope scope(context2->GetIsolate());
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019416 CompileRun("Boolean.prototype.toString = function() { return \"\"; }");
19417 ExpectString(code, "");
19418 }
19419}
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019420
19421
19422TEST(DontDeleteCellLoadIC) {
19423 const char* function_code =
19424 "function readCell() { while (true) { return cell; } }";
19425
19426 {
19427 // Run the code twice in the first context to initialize the load
19428 // IC for a don't delete cell.
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019429 LocalContext context1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019430 v8::HandleScope scope(context1->GetIsolate());
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019431 CompileRun("var cell = \"first\";");
19432 ExpectBoolean("delete cell", false);
19433 CompileRun(function_code);
19434 ExpectString("readCell()", "first");
19435 ExpectString("readCell()", "first");
19436 }
19437
19438 {
19439 // Use a deletable cell in the second context.
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019440 LocalContext context2;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019441 v8::HandleScope scope(context2->GetIsolate());
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019442 CompileRun("cell = \"second\";");
19443 CompileRun(function_code);
19444 ExpectString("readCell()", "second");
19445 ExpectBoolean("delete cell", true);
19446 ExpectString("(function() {"
19447 " try {"
19448 " return readCell();"
19449 " } catch(e) {"
19450 " return e.toString();"
19451 " }"
19452 "})()",
19453 "ReferenceError: cell is not defined");
19454 CompileRun("cell = \"new_second\";");
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019455 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019456 ExpectString("readCell()", "new_second");
19457 ExpectString("readCell()", "new_second");
19458 }
19459}
19460
19461
19462TEST(DontDeleteCellLoadICForceDelete) {
19463 const char* function_code =
19464 "function readCell() { while (true) { return cell; } }";
19465
19466 // Run the code twice to initialize the load IC for a don't delete
19467 // cell.
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019468 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019469 v8::HandleScope scope(context->GetIsolate());
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019470 CompileRun("var cell = \"value\";");
19471 ExpectBoolean("delete cell", false);
19472 CompileRun(function_code);
19473 ExpectString("readCell()", "value");
19474 ExpectString("readCell()", "value");
19475
19476 // Delete the cell using the API and check the inlined code works
19477 // correctly.
19478 CHECK(context->Global()->ForceDelete(v8_str("cell")));
19479 ExpectString("(function() {"
19480 " try {"
19481 " return readCell();"
19482 " } catch(e) {"
19483 " return e.toString();"
19484 " }"
19485 "})()",
19486 "ReferenceError: cell is not defined");
19487}
19488
19489
19490TEST(DontDeleteCellLoadICAPI) {
19491 const char* function_code =
19492 "function readCell() { while (true) { return cell; } }";
19493
19494 // Run the code twice to initialize the load IC for a don't delete
19495 // cell created using the API.
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019496 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019497 v8::HandleScope scope(context->GetIsolate());
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019498 context->Global()->Set(v8_str("cell"), v8_str("value"), v8::DontDelete);
19499 ExpectBoolean("delete cell", false);
19500 CompileRun(function_code);
19501 ExpectString("readCell()", "value");
19502 ExpectString("readCell()", "value");
19503
19504 // Delete the cell using the API and check the inlined code works
19505 // correctly.
19506 CHECK(context->Global()->ForceDelete(v8_str("cell")));
19507 ExpectString("(function() {"
19508 " try {"
19509 " return readCell();"
19510 " } catch(e) {"
19511 " return e.toString();"
19512 " }"
19513 "})()",
19514 "ReferenceError: cell is not defined");
19515}
19516
19517
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000019518class Visitor42 : public v8::PersistentHandleVisitor {
19519 public:
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000019520 explicit Visitor42(v8::Persistent<v8::Object>* object)
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000019521 : counter_(0), object_(object) { }
19522
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000019523 virtual void VisitPersistentHandle(Persistent<Value>* value,
19524 uint16_t class_id) {
19525 if (class_id != 42) return;
19526 CHECK_EQ(42, value->WrapperClassId());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019527 v8::Isolate* isolate = CcTest::isolate();
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000019528 v8::HandleScope handle_scope(isolate);
19529 v8::Handle<v8::Value> handle = v8::Local<v8::Value>::New(isolate, *value);
19530 v8::Handle<v8::Value> object =
19531 v8::Local<v8::Object>::New(isolate, *object_);
19532 CHECK(handle->IsObject());
19533 CHECK_EQ(Handle<Object>::Cast(handle), object);
19534 ++counter_;
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000019535 }
19536
19537 int counter_;
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000019538 v8::Persistent<v8::Object>* object_;
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000019539};
19540
19541
19542TEST(PersistentHandleVisitor) {
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000019543 LocalContext context;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000019544 v8::Isolate* isolate = context->GetIsolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019545 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000019546 v8::Persistent<v8::Object> object(isolate, v8::Object::New(isolate));
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000019547 CHECK_EQ(0, object.WrapperClassId());
19548 object.SetWrapperClassId(42);
19549 CHECK_EQ(42, object.WrapperClassId());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000019550
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000019551 Visitor42 visitor(&object);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000019552 v8::V8::VisitHandlesWithClassIds(&visitor);
19553 CHECK_EQ(1, visitor.counter_);
19554
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000019555 object.Reset();
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000019556}
19557
19558
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000019559TEST(WrapperClassId) {
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000019560 LocalContext context;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000019561 v8::Isolate* isolate = context->GetIsolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019562 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000019563 v8::Persistent<v8::Object> object(isolate, v8::Object::New(isolate));
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000019564 CHECK_EQ(0, object.WrapperClassId());
19565 object.SetWrapperClassId(65535);
19566 CHECK_EQ(65535, object.WrapperClassId());
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000019567 object.Reset();
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000019568}
19569
19570
yangguo@chromium.org003650e2013-01-24 16:31:08 +000019571TEST(PersistentHandleInNewSpaceVisitor) {
yangguo@chromium.org003650e2013-01-24 16:31:08 +000019572 LocalContext context;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000019573 v8::Isolate* isolate = context->GetIsolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019574 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000019575 v8::Persistent<v8::Object> object1(isolate, v8::Object::New(isolate));
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000019576 CHECK_EQ(0, object1.WrapperClassId());
19577 object1.SetWrapperClassId(42);
19578 CHECK_EQ(42, object1.WrapperClassId());
yangguo@chromium.org003650e2013-01-24 16:31:08 +000019579
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019580 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
yangguo@chromium.org003650e2013-01-24 16:31:08 +000019581
ulan@chromium.org0f13e742014-01-03 15:51:11 +000019582 v8::Persistent<v8::Object> object2(isolate, v8::Object::New(isolate));
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000019583 CHECK_EQ(0, object2.WrapperClassId());
19584 object2.SetWrapperClassId(42);
19585 CHECK_EQ(42, object2.WrapperClassId());
yangguo@chromium.org003650e2013-01-24 16:31:08 +000019586
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000019587 Visitor42 visitor(&object2);
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000019588 v8::V8::VisitHandlesForPartialDependence(isolate, &visitor);
yangguo@chromium.org003650e2013-01-24 16:31:08 +000019589 CHECK_EQ(1, visitor.counter_);
19590
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000019591 object1.Reset();
19592 object2.Reset();
yangguo@chromium.org003650e2013-01-24 16:31:08 +000019593}
19594
19595
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019596TEST(RegExp) {
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019597 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019598 v8::HandleScope scope(context->GetIsolate());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019599
19600 v8::Handle<v8::RegExp> re = v8::RegExp::New(v8_str("foo"), v8::RegExp::kNone);
19601 CHECK(re->IsRegExp());
19602 CHECK(re->GetSource()->Equals(v8_str("foo")));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000019603 CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019604
19605 re = v8::RegExp::New(v8_str("bar"),
19606 static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
19607 v8::RegExp::kGlobal));
19608 CHECK(re->IsRegExp());
19609 CHECK(re->GetSource()->Equals(v8_str("bar")));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000019610 CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kGlobal,
19611 static_cast<int>(re->GetFlags()));
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019612
19613 re = v8::RegExp::New(v8_str("baz"),
19614 static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
19615 v8::RegExp::kMultiline));
19616 CHECK(re->IsRegExp());
19617 CHECK(re->GetSource()->Equals(v8_str("baz")));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000019618 CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
19619 static_cast<int>(re->GetFlags()));
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019620
19621 re = CompileRun("/quux/").As<v8::RegExp>();
19622 CHECK(re->IsRegExp());
19623 CHECK(re->GetSource()->Equals(v8_str("quux")));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000019624 CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019625
19626 re = CompileRun("/quux/gm").As<v8::RegExp>();
19627 CHECK(re->IsRegExp());
19628 CHECK(re->GetSource()->Equals(v8_str("quux")));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000019629 CHECK_EQ(v8::RegExp::kGlobal | v8::RegExp::kMultiline,
19630 static_cast<int>(re->GetFlags()));
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019631
19632 // Override the RegExp constructor and check the API constructor
19633 // still works.
19634 CompileRun("RegExp = function() {}");
19635
19636 re = v8::RegExp::New(v8_str("foobar"), v8::RegExp::kNone);
19637 CHECK(re->IsRegExp());
19638 CHECK(re->GetSource()->Equals(v8_str("foobar")));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000019639 CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019640
19641 re = v8::RegExp::New(v8_str("foobarbaz"),
19642 static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
19643 v8::RegExp::kMultiline));
19644 CHECK(re->IsRegExp());
19645 CHECK(re->GetSource()->Equals(v8_str("foobarbaz")));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000019646 CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
19647 static_cast<int>(re->GetFlags()));
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019648
19649 context->Global()->Set(v8_str("re"), re);
19650 ExpectTrue("re.test('FoobarbaZ')");
19651
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000019652 // RegExps are objects on which you can set properties.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000019653 re->Set(v8_str("property"), v8::Integer::New(context->GetIsolate(), 32));
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000019654 v8::Handle<v8::Value> value(CompileRun("re.property"));
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000019655 CHECK_EQ(32, value->Int32Value());
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000019656
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019657 v8::TryCatch try_catch;
19658 re = v8::RegExp::New(v8_str("foo["), v8::RegExp::kNone);
19659 CHECK(re.IsEmpty());
19660 CHECK(try_catch.HasCaught());
19661 context->Global()->Set(v8_str("ex"), try_catch.Exception());
19662 ExpectTrue("ex instanceof SyntaxError");
19663}
19664
19665
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000019666THREADED_TEST(Equals) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000019667 LocalContext localContext;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019668 v8::HandleScope handleScope(localContext->GetIsolate());
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000019669
19670 v8::Handle<v8::Object> globalProxy = localContext->Global();
19671 v8::Handle<Value> global = globalProxy->GetPrototype();
19672
19673 CHECK(global->StrictEquals(global));
19674 CHECK(!global->StrictEquals(globalProxy));
19675 CHECK(!globalProxy->StrictEquals(global));
19676 CHECK(globalProxy->StrictEquals(globalProxy));
19677
19678 CHECK(global->Equals(global));
19679 CHECK(!global->Equals(globalProxy));
19680 CHECK(!globalProxy->Equals(global));
19681 CHECK(globalProxy->Equals(globalProxy));
19682}
19683
19684
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019685static void Getter(v8::Local<v8::String> property,
19686 const v8::PropertyCallbackInfo<v8::Value>& info ) {
19687 info.GetReturnValue().Set(v8_str("42!"));
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019688}
19689
19690
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019691static void Enumerator(const v8::PropertyCallbackInfo<v8::Array>& info) {
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000019692 v8::Handle<v8::Array> result = v8::Array::New(info.GetIsolate());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019693 result->Set(0, v8_str("universalAnswer"));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019694 info.GetReturnValue().Set(result);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019695}
19696
19697
19698TEST(NamedEnumeratorAndForIn) {
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019699 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000019700 v8::Isolate* isolate = context->GetIsolate();
19701 v8::HandleScope handle_scope(isolate);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019702 v8::Context::Scope context_scope(context.local());
19703
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000019704 v8::Handle<v8::ObjectTemplate> tmpl = v8::ObjectTemplate::New(isolate);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019705 tmpl->SetNamedPropertyHandler(Getter, NULL, NULL, NULL, Enumerator);
19706 context->Global()->Set(v8_str("o"), tmpl->NewInstance());
19707 v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
19708 "var result = []; for (var k in o) result.push(k); result"));
19709 CHECK_EQ(1, result->Length());
19710 CHECK_EQ(v8_str("universalAnswer"), result->Get(0));
19711}
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +000019712
19713
19714TEST(DefinePropertyPostDetach) {
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +000019715 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019716 v8::HandleScope scope(context->GetIsolate());
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +000019717 v8::Handle<v8::Object> proxy = context->Global();
19718 v8::Handle<v8::Function> define_property =
19719 CompileRun("(function() {"
19720 " Object.defineProperty("
19721 " this,"
19722 " 1,"
19723 " { configurable: true, enumerable: true, value: 3 });"
19724 "})").As<Function>();
19725 context->DetachGlobal();
19726 define_property->Call(proxy, 0, NULL);
19727}
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000019728
19729
19730static void InstallContextId(v8::Handle<Context> context, int id) {
19731 Context::Scope scope(context);
19732 CompileRun("Object.prototype").As<Object>()->
ulan@chromium.org0f13e742014-01-03 15:51:11 +000019733 Set(v8_str("context_id"), v8::Integer::New(context->GetIsolate(), id));
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000019734}
19735
19736
19737static void CheckContextId(v8::Handle<Object> object, int expected) {
19738 CHECK_EQ(expected, object->Get(v8_str("context_id"))->Int32Value());
19739}
19740
19741
19742THREADED_TEST(CreationContext) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000019743 v8::Isolate* isolate = CcTest::isolate();
19744 HandleScope handle_scope(isolate);
19745 Handle<Context> context1 = Context::New(isolate);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000019746 InstallContextId(context1, 1);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000019747 Handle<Context> context2 = Context::New(isolate);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000019748 InstallContextId(context2, 2);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000019749 Handle<Context> context3 = Context::New(isolate);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000019750 InstallContextId(context3, 3);
19751
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000019752 Local<v8::FunctionTemplate> tmpl = v8::FunctionTemplate::New(isolate);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000019753
19754 Local<Object> object1;
19755 Local<Function> func1;
19756 {
19757 Context::Scope scope(context1);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000019758 object1 = Object::New(isolate);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000019759 func1 = tmpl->GetFunction();
19760 }
19761
19762 Local<Object> object2;
19763 Local<Function> func2;
19764 {
19765 Context::Scope scope(context2);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000019766 object2 = Object::New(isolate);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000019767 func2 = tmpl->GetFunction();
19768 }
19769
19770 Local<Object> instance1;
19771 Local<Object> instance2;
19772
19773 {
19774 Context::Scope scope(context3);
19775 instance1 = func1->NewInstance();
19776 instance2 = func2->NewInstance();
19777 }
19778
19779 CHECK(object1->CreationContext() == context1);
19780 CheckContextId(object1, 1);
19781 CHECK(func1->CreationContext() == context1);
19782 CheckContextId(func1, 1);
19783 CHECK(instance1->CreationContext() == context1);
19784 CheckContextId(instance1, 1);
19785 CHECK(object2->CreationContext() == context2);
19786 CheckContextId(object2, 2);
19787 CHECK(func2->CreationContext() == context2);
19788 CheckContextId(func2, 2);
19789 CHECK(instance2->CreationContext() == context2);
19790 CheckContextId(instance2, 2);
19791
19792 {
19793 Context::Scope scope(context1);
19794 CHECK(object1->CreationContext() == context1);
19795 CheckContextId(object1, 1);
19796 CHECK(func1->CreationContext() == context1);
19797 CheckContextId(func1, 1);
19798 CHECK(instance1->CreationContext() == context1);
19799 CheckContextId(instance1, 1);
19800 CHECK(object2->CreationContext() == context2);
19801 CheckContextId(object2, 2);
19802 CHECK(func2->CreationContext() == context2);
19803 CheckContextId(func2, 2);
19804 CHECK(instance2->CreationContext() == context2);
19805 CheckContextId(instance2, 2);
19806 }
19807
19808 {
19809 Context::Scope scope(context2);
19810 CHECK(object1->CreationContext() == context1);
19811 CheckContextId(object1, 1);
19812 CHECK(func1->CreationContext() == context1);
19813 CheckContextId(func1, 1);
19814 CHECK(instance1->CreationContext() == context1);
19815 CheckContextId(instance1, 1);
19816 CHECK(object2->CreationContext() == context2);
19817 CheckContextId(object2, 2);
19818 CHECK(func2->CreationContext() == context2);
19819 CheckContextId(func2, 2);
19820 CHECK(instance2->CreationContext() == context2);
19821 CheckContextId(instance2, 2);
19822 }
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000019823}
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019824
19825
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +000019826THREADED_TEST(CreationContextOfJsFunction) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019827 HandleScope handle_scope(CcTest::isolate());
19828 Handle<Context> context = Context::New(CcTest::isolate());
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +000019829 InstallContextId(context, 1);
19830
19831 Local<Object> function;
19832 {
19833 Context::Scope scope(context);
19834 function = CompileRun("function foo() {}; foo").As<Object>();
19835 }
19836
19837 CHECK(function->CreationContext() == context);
19838 CheckContextId(function, 1);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +000019839}
19840
19841
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019842void HasOwnPropertyIndexedPropertyGetter(
19843 uint32_t index,
19844 const v8::PropertyCallbackInfo<v8::Value>& info) {
19845 if (index == 42) info.GetReturnValue().Set(v8_str("yes"));
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019846}
19847
19848
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019849void HasOwnPropertyNamedPropertyGetter(
19850 Local<String> property,
19851 const v8::PropertyCallbackInfo<v8::Value>& info) {
19852 if (property->Equals(v8_str("foo"))) info.GetReturnValue().Set(v8_str("yes"));
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019853}
19854
19855
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019856void HasOwnPropertyIndexedPropertyQuery(
19857 uint32_t index, const v8::PropertyCallbackInfo<v8::Integer>& info) {
19858 if (index == 42) info.GetReturnValue().Set(1);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019859}
19860
19861
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019862void HasOwnPropertyNamedPropertyQuery(
19863 Local<String> property,
19864 const v8::PropertyCallbackInfo<v8::Integer>& info) {
19865 if (property->Equals(v8_str("foo"))) info.GetReturnValue().Set(1);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019866}
19867
19868
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019869void HasOwnPropertyNamedPropertyQuery2(
19870 Local<String> property,
19871 const v8::PropertyCallbackInfo<v8::Integer>& info) {
19872 if (property->Equals(v8_str("bar"))) info.GetReturnValue().Set(1);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019873}
19874
19875
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019876void HasOwnPropertyAccessorGetter(
19877 Local<String> property,
19878 const v8::PropertyCallbackInfo<v8::Value>& info) {
19879 info.GetReturnValue().Set(v8_str("yes"));
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019880}
19881
19882
19883TEST(HasOwnProperty) {
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019884 LocalContext env;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000019885 v8::Isolate* isolate = env->GetIsolate();
19886 v8::HandleScope scope(isolate);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019887 { // Check normal properties and defined getters.
19888 Handle<Value> value = CompileRun(
19889 "function Foo() {"
19890 " this.foo = 11;"
19891 " this.__defineGetter__('baz', function() { return 1; });"
19892 "};"
19893 "function Bar() { "
19894 " this.bar = 13;"
19895 " this.__defineGetter__('bla', function() { return 2; });"
19896 "};"
19897 "Bar.prototype = new Foo();"
19898 "new Bar();");
19899 CHECK(value->IsObject());
19900 Handle<Object> object = value->ToObject();
19901 CHECK(object->Has(v8_str("foo")));
19902 CHECK(!object->HasOwnProperty(v8_str("foo")));
19903 CHECK(object->HasOwnProperty(v8_str("bar")));
19904 CHECK(object->Has(v8_str("baz")));
19905 CHECK(!object->HasOwnProperty(v8_str("baz")));
19906 CHECK(object->HasOwnProperty(v8_str("bla")));
19907 }
19908 { // Check named getter interceptors.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000019909 Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019910 templ->SetNamedPropertyHandler(HasOwnPropertyNamedPropertyGetter);
19911 Handle<Object> instance = templ->NewInstance();
19912 CHECK(!instance->HasOwnProperty(v8_str("42")));
19913 CHECK(instance->HasOwnProperty(v8_str("foo")));
19914 CHECK(!instance->HasOwnProperty(v8_str("bar")));
19915 }
19916 { // Check indexed getter interceptors.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000019917 Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019918 templ->SetIndexedPropertyHandler(HasOwnPropertyIndexedPropertyGetter);
19919 Handle<Object> instance = templ->NewInstance();
19920 CHECK(instance->HasOwnProperty(v8_str("42")));
19921 CHECK(!instance->HasOwnProperty(v8_str("43")));
19922 CHECK(!instance->HasOwnProperty(v8_str("foo")));
19923 }
19924 { // Check named query interceptors.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000019925 Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019926 templ->SetNamedPropertyHandler(0, 0, HasOwnPropertyNamedPropertyQuery);
19927 Handle<Object> instance = templ->NewInstance();
19928 CHECK(instance->HasOwnProperty(v8_str("foo")));
19929 CHECK(!instance->HasOwnProperty(v8_str("bar")));
19930 }
19931 { // Check indexed query interceptors.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000019932 Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019933 templ->SetIndexedPropertyHandler(0, 0, HasOwnPropertyIndexedPropertyQuery);
19934 Handle<Object> instance = templ->NewInstance();
19935 CHECK(instance->HasOwnProperty(v8_str("42")));
19936 CHECK(!instance->HasOwnProperty(v8_str("41")));
19937 }
19938 { // Check callbacks.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000019939 Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019940 templ->SetAccessor(v8_str("foo"), HasOwnPropertyAccessorGetter);
19941 Handle<Object> instance = templ->NewInstance();
19942 CHECK(instance->HasOwnProperty(v8_str("foo")));
19943 CHECK(!instance->HasOwnProperty(v8_str("bar")));
19944 }
19945 { // Check that query wins on disagreement.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000019946 Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019947 templ->SetNamedPropertyHandler(HasOwnPropertyNamedPropertyGetter,
19948 0,
19949 HasOwnPropertyNamedPropertyQuery2);
19950 Handle<Object> instance = templ->NewInstance();
19951 CHECK(!instance->HasOwnProperty(v8_str("foo")));
19952 CHECK(instance->HasOwnProperty(v8_str("bar")));
19953 }
19954}
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000019955
19956
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +000019957TEST(IndexedInterceptorWithStringProto) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000019958 v8::Isolate* isolate = CcTest::isolate();
19959 v8::HandleScope scope(isolate);
19960 Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +000019961 templ->SetIndexedPropertyHandler(NULL,
19962 NULL,
19963 HasOwnPropertyIndexedPropertyQuery);
19964 LocalContext context;
19965 context->Global()->Set(v8_str("obj"), templ->NewInstance());
19966 CompileRun("var s = new String('foobar'); obj.__proto__ = s;");
19967 // These should be intercepted.
19968 CHECK(CompileRun("42 in obj")->BooleanValue());
19969 CHECK(CompileRun("'42' in obj")->BooleanValue());
19970 // These should fall through to the String prototype.
19971 CHECK(CompileRun("0 in obj")->BooleanValue());
19972 CHECK(CompileRun("'0' in obj")->BooleanValue());
19973 // And these should both fail.
19974 CHECK(!CompileRun("32 in obj")->BooleanValue());
19975 CHECK(!CompileRun("'32' in obj")->BooleanValue());
19976}
19977
19978
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000019979void CheckCodeGenerationAllowed() {
19980 Handle<Value> result = CompileRun("eval('42')");
19981 CHECK_EQ(42, result->Int32Value());
19982 result = CompileRun("(function(e) { return e('42'); })(eval)");
19983 CHECK_EQ(42, result->Int32Value());
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000019984 result = CompileRun("var f = new Function('return 42'); f()");
19985 CHECK_EQ(42, result->Int32Value());
19986}
19987
19988
19989void CheckCodeGenerationDisallowed() {
19990 TryCatch try_catch;
19991
19992 Handle<Value> result = CompileRun("eval('42')");
19993 CHECK(result.IsEmpty());
19994 CHECK(try_catch.HasCaught());
19995 try_catch.Reset();
19996
19997 result = CompileRun("(function(e) { return e('42'); })(eval)");
19998 CHECK(result.IsEmpty());
19999 CHECK(try_catch.HasCaught());
20000 try_catch.Reset();
20001
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000020002 result = CompileRun("var f = new Function('return 42'); f()");
20003 CHECK(result.IsEmpty());
20004 CHECK(try_catch.HasCaught());
20005}
20006
20007
20008bool CodeGenerationAllowed(Local<Context> context) {
20009 ApiTestFuzzer::Fuzz();
20010 return true;
20011}
20012
20013
20014bool CodeGenerationDisallowed(Local<Context> context) {
20015 ApiTestFuzzer::Fuzz();
20016 return false;
20017}
20018
20019
20020THREADED_TEST(AllowCodeGenFromStrings) {
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000020021 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020022 v8::HandleScope scope(context->GetIsolate());
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000020023
ager@chromium.orgea91cc52011-05-23 06:06:11 +000020024 // eval and the Function constructor allowed by default.
jkummerow@chromium.org1145ef82012-02-02 16:21:15 +000020025 CHECK(context->IsCodeGenerationFromStringsAllowed());
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000020026 CheckCodeGenerationAllowed();
20027
ager@chromium.orgea91cc52011-05-23 06:06:11 +000020028 // Disallow eval and the Function constructor.
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000020029 context->AllowCodeGenerationFromStrings(false);
jkummerow@chromium.org1145ef82012-02-02 16:21:15 +000020030 CHECK(!context->IsCodeGenerationFromStringsAllowed());
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000020031 CheckCodeGenerationDisallowed();
20032
20033 // Allow again.
20034 context->AllowCodeGenerationFromStrings(true);
20035 CheckCodeGenerationAllowed();
20036
20037 // Disallow but setting a global callback that will allow the calls.
20038 context->AllowCodeGenerationFromStrings(false);
20039 V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationAllowed);
jkummerow@chromium.org1145ef82012-02-02 16:21:15 +000020040 CHECK(!context->IsCodeGenerationFromStringsAllowed());
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000020041 CheckCodeGenerationAllowed();
20042
20043 // Set a callback that disallows the code generation.
20044 V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationDisallowed);
jkummerow@chromium.org1145ef82012-02-02 16:21:15 +000020045 CHECK(!context->IsCodeGenerationFromStringsAllowed());
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000020046 CheckCodeGenerationDisallowed();
20047}
lrn@chromium.org1c092762011-05-09 09:42:16 +000020048
20049
ulan@chromium.org56c14af2012-09-20 12:51:09 +000020050TEST(SetErrorMessageForCodeGenFromStrings) {
ulan@chromium.org56c14af2012-09-20 12:51:09 +000020051 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020052 v8::HandleScope scope(context->GetIsolate());
ulan@chromium.org56c14af2012-09-20 12:51:09 +000020053 TryCatch try_catch;
20054
20055 Handle<String> message = v8_str("Message") ;
20056 Handle<String> expected_message = v8_str("Uncaught EvalError: Message");
20057 V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationDisallowed);
20058 context->AllowCodeGenerationFromStrings(false);
20059 context->SetErrorMessageForCodeGenerationFromStrings(message);
20060 Handle<Value> result = CompileRun("eval('42')");
20061 CHECK(result.IsEmpty());
20062 CHECK(try_catch.HasCaught());
20063 Handle<String> actual_message = try_catch.Message()->Get();
20064 CHECK(expected_message->Equals(actual_message));
20065}
20066
20067
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000020068static void NonObjectThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
lrn@chromium.org1c092762011-05-09 09:42:16 +000020069}
20070
20071
20072THREADED_TEST(CallAPIFunctionOnNonObject) {
lrn@chromium.org1c092762011-05-09 09:42:16 +000020073 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000020074 v8::Isolate* isolate = context->GetIsolate();
20075 v8::HandleScope scope(isolate);
20076 Handle<FunctionTemplate> templ =
20077 v8::FunctionTemplate::New(isolate, NonObjectThis);
lrn@chromium.org1c092762011-05-09 09:42:16 +000020078 Handle<Function> function = templ->GetFunction();
20079 context->Global()->Set(v8_str("f"), function);
20080 TryCatch try_catch;
20081 CompileRun("f.call(2)");
lrn@chromium.org1c092762011-05-09 09:42:16 +000020082}
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000020083
20084
20085// Regression test for issue 1470.
20086THREADED_TEST(ReadOnlyIndexedProperties) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000020087 v8::Isolate* isolate = CcTest::isolate();
20088 v8::HandleScope scope(isolate);
20089 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000020090
20091 LocalContext context;
20092 Local<v8::Object> obj = templ->NewInstance();
20093 context->Global()->Set(v8_str("obj"), obj);
20094 obj->Set(v8_str("1"), v8_str("DONT_CHANGE"), v8::ReadOnly);
20095 obj->Set(v8_str("1"), v8_str("foobar"));
20096 CHECK_EQ(v8_str("DONT_CHANGE"), obj->Get(v8_str("1")));
20097 obj->Set(v8_num(2), v8_str("DONT_CHANGE"), v8::ReadOnly);
20098 obj->Set(v8_num(2), v8_str("foobar"));
20099 CHECK_EQ(v8_str("DONT_CHANGE"), obj->Get(v8_num(2)));
20100
20101 // Test non-smi case.
20102 obj->Set(v8_str("2000000000"), v8_str("DONT_CHANGE"), v8::ReadOnly);
20103 obj->Set(v8_str("2000000000"), v8_str("foobar"));
20104 CHECK_EQ(v8_str("DONT_CHANGE"), obj->Get(v8_str("2000000000")));
20105}
ricow@chromium.org4f693d62011-07-04 14:01:31 +000020106
20107
20108THREADED_TEST(Regress1516) {
ricow@chromium.org4f693d62011-07-04 14:01:31 +000020109 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020110 v8::HandleScope scope(context->GetIsolate());
20111
20112 { v8::HandleScope temp_scope(context->GetIsolate());
ricow@chromium.org4f693d62011-07-04 14:01:31 +000020113 CompileRun("({'a': 0})");
20114 }
20115
20116 int elements;
20117 { i::MapCache* map_cache =
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020118 i::MapCache::cast(CcTest::i_isolate()->context()->map_cache());
ricow@chromium.org4f693d62011-07-04 14:01:31 +000020119 elements = map_cache->NumberOfElements();
20120 CHECK_LE(1, elements);
20121 }
20122
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020123 CcTest::heap()->CollectAllGarbage(
yangguo@chromium.orgd2899aa2012-06-21 11:16:20 +000020124 i::Heap::kAbortIncrementalMarkingMask);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020125 { i::Object* raw_map_cache = CcTest::i_isolate()->context()->map_cache();
20126 if (raw_map_cache != CcTest::heap()->undefined_value()) {
ricow@chromium.org4f693d62011-07-04 14:01:31 +000020127 i::MapCache* map_cache = i::MapCache::cast(raw_map_cache);
20128 CHECK_GT(elements, map_cache->NumberOfElements());
20129 }
20130 }
20131}
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020132
20133
20134static bool BlockProtoNamedSecurityTestCallback(Local<v8::Object> global,
20135 Local<Value> name,
20136 v8::AccessType type,
20137 Local<Value> data) {
20138 // Only block read access to __proto__.
20139 if (type == v8::ACCESS_GET &&
20140 name->IsString() &&
20141 name->ToString()->Length() == 9 &&
20142 name->ToString()->Utf8Length() == 9) {
20143 char buffer[10];
20144 CHECK_EQ(10, name->ToString()->WriteUtf8(buffer));
20145 return strncmp(buffer, "__proto__", 9) != 0;
20146 }
20147
20148 return true;
20149}
20150
20151
20152THREADED_TEST(Regress93759) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020153 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000020154 HandleScope scope(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020155
20156 // Template for object with security check.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000020157 Local<ObjectTemplate> no_proto_template = v8::ObjectTemplate::New(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020158 // We don't do indexing, so any callback can be used for that.
20159 no_proto_template->SetAccessCheckCallbacks(
20160 BlockProtoNamedSecurityTestCallback,
20161 IndexedSecurityTestCallback);
20162
20163 // Templates for objects with hidden prototypes and possibly security check.
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000020164 Local<FunctionTemplate> hidden_proto_template =
20165 v8::FunctionTemplate::New(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020166 hidden_proto_template->SetHiddenPrototype(true);
20167
20168 Local<FunctionTemplate> protected_hidden_proto_template =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000020169 v8::FunctionTemplate::New(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020170 protected_hidden_proto_template->InstanceTemplate()->SetAccessCheckCallbacks(
20171 BlockProtoNamedSecurityTestCallback,
20172 IndexedSecurityTestCallback);
20173 protected_hidden_proto_template->SetHiddenPrototype(true);
20174
20175 // Context for "foreign" objects used in test.
ulan@chromium.org57ff8812013-05-10 08:16:55 +000020176 Local<Context> context = v8::Context::New(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020177 context->Enter();
20178
20179 // Plain object, no security check.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000020180 Local<Object> simple_object = Object::New(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020181
20182 // Object with explicit security check.
20183 Local<Object> protected_object =
20184 no_proto_template->NewInstance();
20185
20186 // JSGlobalProxy object, always have security check.
20187 Local<Object> proxy_object =
20188 context->Global();
20189
20190 // Global object, the prototype of proxy_object. No security checks.
20191 Local<Object> global_object =
20192 proxy_object->GetPrototype()->ToObject();
20193
20194 // Hidden prototype without security check.
20195 Local<Object> hidden_prototype =
20196 hidden_proto_template->GetFunction()->NewInstance();
20197 Local<Object> object_with_hidden =
ulan@chromium.org0f13e742014-01-03 15:51:11 +000020198 Object::New(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020199 object_with_hidden->SetPrototype(hidden_prototype);
20200
20201 // Hidden prototype with security check on the hidden prototype.
20202 Local<Object> protected_hidden_prototype =
20203 protected_hidden_proto_template->GetFunction()->NewInstance();
20204 Local<Object> object_with_protected_hidden =
ulan@chromium.org0f13e742014-01-03 15:51:11 +000020205 Object::New(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020206 object_with_protected_hidden->SetPrototype(protected_hidden_prototype);
20207
20208 context->Exit();
20209
20210 // Template for object for second context. Values to test are put on it as
20211 // properties.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000020212 Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020213 global_template->Set(v8_str("simple"), simple_object);
20214 global_template->Set(v8_str("protected"), protected_object);
20215 global_template->Set(v8_str("global"), global_object);
20216 global_template->Set(v8_str("proxy"), proxy_object);
20217 global_template->Set(v8_str("hidden"), object_with_hidden);
20218 global_template->Set(v8_str("phidden"), object_with_protected_hidden);
20219
20220 LocalContext context2(NULL, global_template);
20221
20222 Local<Value> result1 = CompileRun("Object.getPrototypeOf(simple)");
20223 CHECK(result1->Equals(simple_object->GetPrototype()));
20224
20225 Local<Value> result2 = CompileRun("Object.getPrototypeOf(protected)");
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000020226 CHECK(result2->Equals(Undefined(isolate)));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020227
20228 Local<Value> result3 = CompileRun("Object.getPrototypeOf(global)");
20229 CHECK(result3->Equals(global_object->GetPrototype()));
20230
20231 Local<Value> result4 = CompileRun("Object.getPrototypeOf(proxy)");
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000020232 CHECK(result4->Equals(Undefined(isolate)));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020233
20234 Local<Value> result5 = CompileRun("Object.getPrototypeOf(hidden)");
20235 CHECK(result5->Equals(
20236 object_with_hidden->GetPrototype()->ToObject()->GetPrototype()));
20237
20238 Local<Value> result6 = CompileRun("Object.getPrototypeOf(phidden)");
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000020239 CHECK(result6->Equals(Undefined(isolate)));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020240}
20241
20242
jkummerow@chromium.org212d9642012-05-11 15:02:09 +000020243THREADED_TEST(Regress125988) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020244 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000020245 Handle<FunctionTemplate> intercept = FunctionTemplate::New(CcTest::isolate());
jkummerow@chromium.org212d9642012-05-11 15:02:09 +000020246 AddInterceptor(intercept, EmptyInterceptorGetter, EmptyInterceptorSetter);
20247 LocalContext env;
20248 env->Global()->Set(v8_str("Intercept"), intercept->GetFunction());
20249 CompileRun("var a = new Object();"
20250 "var b = new Intercept();"
20251 "var c = new Object();"
20252 "c.__proto__ = b;"
20253 "b.__proto__ = a;"
20254 "a.x = 23;"
20255 "for (var i = 0; i < 3; i++) c.x;");
20256 ExpectBoolean("c.hasOwnProperty('x')", false);
20257 ExpectInt32("c.x", 23);
20258 CompileRun("a.y = 42;"
20259 "for (var i = 0; i < 3; i++) c.x;");
20260 ExpectBoolean("c.hasOwnProperty('x')", false);
20261 ExpectInt32("c.x", 23);
20262 ExpectBoolean("c.hasOwnProperty('y')", false);
20263 ExpectInt32("c.y", 42);
20264}
20265
20266
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020267static void TestReceiver(Local<Value> expected_result,
20268 Local<Value> expected_receiver,
20269 const char* code) {
20270 Local<Value> result = CompileRun(code);
20271 CHECK(result->IsObject());
20272 CHECK(expected_receiver->Equals(result->ToObject()->Get(1)));
20273 CHECK(expected_result->Equals(result->ToObject()->Get(0)));
20274}
20275
20276
20277THREADED_TEST(ForeignFunctionReceiver) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020278 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000020279 HandleScope scope(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020280
20281 // Create two contexts with different "id" properties ('i' and 'o').
20282 // Call a function both from its own context and from a the foreign
20283 // context, and see what "this" is bound to (returning both "this"
20284 // and "this.id" for comparison).
20285
ulan@chromium.org57ff8812013-05-10 08:16:55 +000020286 Local<Context> foreign_context = v8::Context::New(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020287 foreign_context->Enter();
20288 Local<Value> foreign_function =
20289 CompileRun("function func() { return { 0: this.id, "
20290 " 1: this, "
20291 " toString: function() { "
20292 " return this[0];"
20293 " }"
20294 " };"
20295 "}"
20296 "var id = 'i';"
20297 "func;");
20298 CHECK(foreign_function->IsFunction());
20299 foreign_context->Exit();
20300
20301 LocalContext context;
20302
20303 Local<String> password = v8_str("Password");
20304 // Don't get hit by security checks when accessing foreign_context's
20305 // global receiver (aka. global proxy).
20306 context->SetSecurityToken(password);
20307 foreign_context->SetSecurityToken(password);
20308
20309 Local<String> i = v8_str("i");
20310 Local<String> o = v8_str("o");
20311 Local<String> id = v8_str("id");
20312
20313 CompileRun("function ownfunc() { return { 0: this.id, "
20314 " 1: this, "
20315 " toString: function() { "
20316 " return this[0];"
20317 " }"
20318 " };"
20319 "}"
20320 "var id = 'o';"
20321 "ownfunc");
20322 context->Global()->Set(v8_str("func"), foreign_function);
20323
20324 // Sanity check the contexts.
20325 CHECK(i->Equals(foreign_context->Global()->Get(id)));
20326 CHECK(o->Equals(context->Global()->Get(id)));
20327
20328 // Checking local function's receiver.
20329 // Calling function using its call/apply methods.
20330 TestReceiver(o, context->Global(), "ownfunc.call()");
20331 TestReceiver(o, context->Global(), "ownfunc.apply()");
20332 // Making calls through built-in functions.
20333 TestReceiver(o, context->Global(), "[1].map(ownfunc)[0]");
20334 CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/,ownfunc)[1]")));
20335 CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/g,ownfunc)[1]")));
20336 CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/g,ownfunc)[3]")));
20337 // Calling with environment record as base.
20338 TestReceiver(o, context->Global(), "ownfunc()");
20339 // Calling with no base.
20340 TestReceiver(o, context->Global(), "(1,ownfunc)()");
20341
20342 // Checking foreign function return value.
20343 // Calling function using its call/apply methods.
20344 TestReceiver(i, foreign_context->Global(), "func.call()");
20345 TestReceiver(i, foreign_context->Global(), "func.apply()");
20346 // Calling function using another context's call/apply methods.
20347 TestReceiver(i, foreign_context->Global(),
20348 "Function.prototype.call.call(func)");
20349 TestReceiver(i, foreign_context->Global(),
20350 "Function.prototype.call.apply(func)");
20351 TestReceiver(i, foreign_context->Global(),
20352 "Function.prototype.apply.call(func)");
20353 TestReceiver(i, foreign_context->Global(),
20354 "Function.prototype.apply.apply(func)");
20355 // Making calls through built-in functions.
20356 TestReceiver(i, foreign_context->Global(), "[1].map(func)[0]");
20357 // ToString(func()) is func()[0], i.e., the returned this.id.
20358 CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/,func)[1]")));
20359 CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/g,func)[1]")));
20360 CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/g,func)[3]")));
20361
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020362 // Calling with environment record as base.
rossberg@chromium.org9ed27462014-01-07 14:16:41 +000020363 TestReceiver(i, foreign_context->Global(), "func()");
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020364 // Calling with no base.
rossberg@chromium.org9ed27462014-01-07 14:16:41 +000020365 TestReceiver(i, foreign_context->Global(), "(1,func)()");
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020366}
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020367
20368
20369uint8_t callback_fired = 0;
20370
20371
20372void CallCompletedCallback1() {
20373 i::OS::Print("Firing callback 1.\n");
20374 callback_fired ^= 1; // Toggle first bit.
20375}
20376
20377
20378void CallCompletedCallback2() {
20379 i::OS::Print("Firing callback 2.\n");
20380 callback_fired ^= 2; // Toggle second bit.
20381}
20382
20383
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000020384void RecursiveCall(const v8::FunctionCallbackInfo<v8::Value>& args) {
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020385 int32_t level = args[0]->Int32Value();
20386 if (level < 3) {
20387 level++;
20388 i::OS::Print("Entering recursion level %d.\n", level);
20389 char script[64];
20390 i::Vector<char> script_vector(script, sizeof(script));
20391 i::OS::SNPrintF(script_vector, "recursion(%d)", level);
20392 CompileRun(script_vector.start());
20393 i::OS::Print("Leaving recursion level %d.\n", level);
20394 CHECK_EQ(0, callback_fired);
20395 } else {
20396 i::OS::Print("Recursion ends.\n");
20397 CHECK_EQ(0, callback_fired);
20398 }
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020399}
20400
20401
20402TEST(CallCompletedCallback) {
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020403 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020404 v8::HandleScope scope(env->GetIsolate());
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020405 v8::Handle<v8::FunctionTemplate> recursive_runtime =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000020406 v8::FunctionTemplate::New(env->GetIsolate(), RecursiveCall);
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020407 env->Global()->Set(v8_str("recursion"),
20408 recursive_runtime->GetFunction());
20409 // Adding the same callback a second time has no effect.
20410 v8::V8::AddCallCompletedCallback(CallCompletedCallback1);
20411 v8::V8::AddCallCompletedCallback(CallCompletedCallback1);
20412 v8::V8::AddCallCompletedCallback(CallCompletedCallback2);
20413 i::OS::Print("--- Script (1) ---\n");
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000020414 Local<Script> script = v8::Script::Compile(
20415 v8::String::NewFromUtf8(env->GetIsolate(), "recursion(0)"));
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020416 script->Run();
20417 CHECK_EQ(3, callback_fired);
20418
20419 i::OS::Print("\n--- Script (2) ---\n");
20420 callback_fired = 0;
20421 v8::V8::RemoveCallCompletedCallback(CallCompletedCallback1);
20422 script->Run();
20423 CHECK_EQ(2, callback_fired);
20424
20425 i::OS::Print("\n--- Function ---\n");
20426 callback_fired = 0;
20427 Local<Function> recursive_function =
20428 Local<Function>::Cast(env->Global()->Get(v8_str("recursion")));
20429 v8::Handle<Value> args[] = { v8_num(0) };
20430 recursive_function->Call(env->Global(), 1, args);
20431 CHECK_EQ(2, callback_fired);
20432}
20433
20434
20435void CallCompletedCallbackNoException() {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020436 v8::HandleScope scope(CcTest::isolate());
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020437 CompileRun("1+1;");
20438}
20439
20440
20441void CallCompletedCallbackException() {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020442 v8::HandleScope scope(CcTest::isolate());
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020443 CompileRun("throw 'second exception';");
20444}
20445
20446
20447TEST(CallCompletedCallbackOneException) {
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020448 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020449 v8::HandleScope scope(env->GetIsolate());
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020450 v8::V8::AddCallCompletedCallback(CallCompletedCallbackNoException);
20451 CompileRun("throw 'exception';");
20452}
20453
20454
20455TEST(CallCompletedCallbackTwoExceptions) {
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020456 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020457 v8::HandleScope scope(env->GetIsolate());
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020458 v8::V8::AddCallCompletedCallback(CallCompletedCallbackException);
20459 CompileRun("throw 'first exception';");
20460}
ulan@chromium.org812308e2012-02-29 15:58:45 +000020461
20462
20463static int probes_counter = 0;
20464static int misses_counter = 0;
20465static int updates_counter = 0;
20466
20467
20468static int* LookupCounter(const char* name) {
20469 if (strcmp(name, "c:V8.MegamorphicStubCacheProbes") == 0) {
20470 return &probes_counter;
20471 } else if (strcmp(name, "c:V8.MegamorphicStubCacheMisses") == 0) {
20472 return &misses_counter;
20473 } else if (strcmp(name, "c:V8.MegamorphicStubCacheUpdates") == 0) {
20474 return &updates_counter;
20475 }
20476 return NULL;
20477}
20478
20479
20480static const char* kMegamorphicTestProgram =
20481 "function ClassA() { };"
20482 "function ClassB() { };"
20483 "ClassA.prototype.foo = function() { };"
20484 "ClassB.prototype.foo = function() { };"
20485 "function fooify(obj) { obj.foo(); };"
20486 "var a = new ClassA();"
20487 "var b = new ClassB();"
20488 "for (var i = 0; i < 10000; i++) {"
20489 " fooify(a);"
20490 " fooify(b);"
20491 "}";
20492
20493
20494static void StubCacheHelper(bool primary) {
20495 V8::SetCounterFunction(LookupCounter);
20496 USE(kMegamorphicTestProgram);
20497#ifdef DEBUG
20498 i::FLAG_native_code_counters = true;
20499 if (primary) {
20500 i::FLAG_test_primary_stub_cache = true;
20501 } else {
20502 i::FLAG_test_secondary_stub_cache = true;
20503 }
20504 i::FLAG_crankshaft = false;
ulan@chromium.org812308e2012-02-29 15:58:45 +000020505 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020506 v8::HandleScope scope(env->GetIsolate());
ulan@chromium.org812308e2012-02-29 15:58:45 +000020507 int initial_probes = probes_counter;
20508 int initial_misses = misses_counter;
20509 int initial_updates = updates_counter;
20510 CompileRun(kMegamorphicTestProgram);
20511 int probes = probes_counter - initial_probes;
20512 int misses = misses_counter - initial_misses;
20513 int updates = updates_counter - initial_updates;
20514 CHECK_LT(updates, 10);
20515 CHECK_LT(misses, 10);
20516 CHECK_GE(probes, 10000);
20517#endif
20518}
20519
20520
20521TEST(SecondaryStubCache) {
20522 StubCacheHelper(true);
20523}
20524
20525
20526TEST(PrimaryStubCache) {
20527 StubCacheHelper(false);
20528}
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020529
20530
verwaest@chromium.org057bd502013-11-06 12:03:29 +000020531static int cow_arrays_created_runtime = 0;
20532
20533
20534static int* LookupCounterCOWArrays(const char* name) {
20535 if (strcmp(name, "c:V8.COWArraysCreatedRuntime") == 0) {
20536 return &cow_arrays_created_runtime;
20537 }
20538 return NULL;
20539}
20540
20541
20542TEST(CheckCOWArraysCreatedRuntimeCounter) {
20543 V8::SetCounterFunction(LookupCounterCOWArrays);
20544#ifdef DEBUG
20545 i::FLAG_native_code_counters = true;
20546 LocalContext env;
20547 v8::HandleScope scope(env->GetIsolate());
20548 int initial_cow_arrays = cow_arrays_created_runtime;
20549 CompileRun("var o = [1, 2, 3];");
20550 CHECK_EQ(1, cow_arrays_created_runtime - initial_cow_arrays);
20551 CompileRun("var o = {foo: [4, 5, 6], bar: [3, 0]};");
20552 CHECK_EQ(3, cow_arrays_created_runtime - initial_cow_arrays);
20553 CompileRun("var o = {foo: [1, 2, 3, [4, 5, 6]], bar: 'hi'};");
20554 CHECK_EQ(4, cow_arrays_created_runtime - initial_cow_arrays);
20555#endif
20556}
20557
20558
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020559TEST(StaticGetters) {
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020560 LocalContext context;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020561 i::Factory* factory = CcTest::i_isolate()->factory();
20562 v8::Isolate* isolate = CcTest::isolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020563 v8::HandleScope scope(isolate);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000020564 i::Handle<i::Object> undefined_value = factory->undefined_value();
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020565 CHECK(*v8::Utils::OpenHandle(*v8::Undefined(isolate)) == *undefined_value);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000020566 i::Handle<i::Object> null_value = factory->null_value();
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020567 CHECK(*v8::Utils::OpenHandle(*v8::Null(isolate)) == *null_value);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000020568 i::Handle<i::Object> true_value = factory->true_value();
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020569 CHECK(*v8::Utils::OpenHandle(*v8::True(isolate)) == *true_value);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000020570 i::Handle<i::Object> false_value = factory->false_value();
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020571 CHECK(*v8::Utils::OpenHandle(*v8::False(isolate)) == *false_value);
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020572}
20573
20574
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020575UNINITIALIZED_TEST(IsolateEmbedderData) {
20576 CcTest::DisableAutomaticDispose();
20577 v8::Isolate* isolate = v8::Isolate::New();
20578 isolate->Enter();
hpayer@chromium.orgc5d49712013-09-11 08:25:48 +000020579 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
machenbach@chromium.org7ff76072013-11-21 09:47:43 +000020580 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
20581 CHECK_EQ(NULL, isolate->GetData(slot));
20582 CHECK_EQ(NULL, i_isolate->GetData(slot));
20583 }
20584 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
20585 void* data = reinterpret_cast<void*>(0xacce55ed + slot);
20586 isolate->SetData(slot, data);
20587 }
20588 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
20589 void* data = reinterpret_cast<void*>(0xacce55ed + slot);
20590 CHECK_EQ(data, isolate->GetData(slot));
20591 CHECK_EQ(data, i_isolate->GetData(slot));
20592 }
20593 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
20594 void* data = reinterpret_cast<void*>(0xdecea5ed + slot);
20595 isolate->SetData(slot, data);
20596 }
20597 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
20598 void* data = reinterpret_cast<void*>(0xdecea5ed + slot);
20599 CHECK_EQ(data, isolate->GetData(slot));
20600 CHECK_EQ(data, i_isolate->GetData(slot));
20601 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020602 isolate->Exit();
20603 isolate->Dispose();
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020604}
20605
20606
20607TEST(StringEmpty) {
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020608 LocalContext context;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020609 i::Factory* factory = CcTest::i_isolate()->factory();
20610 v8::Isolate* isolate = CcTest::isolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020611 v8::HandleScope scope(isolate);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000020612 i::Handle<i::Object> empty_string = factory->empty_string();
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020613 CHECK(*v8::Utils::OpenHandle(*v8::String::Empty(isolate)) == *empty_string);
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020614}
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020615
20616
20617static int instance_checked_getter_count = 0;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000020618static void InstanceCheckedGetter(
20619 Local<String> name,
20620 const v8::PropertyCallbackInfo<v8::Value>& info) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020621 CHECK_EQ(name, v8_str("foo"));
20622 instance_checked_getter_count++;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000020623 info.GetReturnValue().Set(v8_num(11));
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020624}
20625
20626
20627static int instance_checked_setter_count = 0;
20628static void InstanceCheckedSetter(Local<String> name,
20629 Local<Value> value,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000020630 const v8::PropertyCallbackInfo<void>& info) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020631 CHECK_EQ(name, v8_str("foo"));
20632 CHECK_EQ(value, v8_num(23));
20633 instance_checked_setter_count++;
20634}
20635
20636
20637static void CheckInstanceCheckedResult(int getters,
20638 int setters,
20639 bool expects_callbacks,
20640 TryCatch* try_catch) {
20641 if (expects_callbacks) {
20642 CHECK(!try_catch->HasCaught());
20643 CHECK_EQ(getters, instance_checked_getter_count);
20644 CHECK_EQ(setters, instance_checked_setter_count);
20645 } else {
20646 CHECK(try_catch->HasCaught());
20647 CHECK_EQ(0, instance_checked_getter_count);
20648 CHECK_EQ(0, instance_checked_setter_count);
20649 }
20650 try_catch->Reset();
20651}
20652
20653
20654static void CheckInstanceCheckedAccessors(bool expects_callbacks) {
20655 instance_checked_getter_count = 0;
20656 instance_checked_setter_count = 0;
20657 TryCatch try_catch;
20658
20659 // Test path through generic runtime code.
20660 CompileRun("obj.foo");
20661 CheckInstanceCheckedResult(1, 0, expects_callbacks, &try_catch);
20662 CompileRun("obj.foo = 23");
20663 CheckInstanceCheckedResult(1, 1, expects_callbacks, &try_catch);
20664
20665 // Test path through generated LoadIC and StoredIC.
20666 CompileRun("function test_get(o) { o.foo; }"
20667 "test_get(obj);");
20668 CheckInstanceCheckedResult(2, 1, expects_callbacks, &try_catch);
20669 CompileRun("test_get(obj);");
20670 CheckInstanceCheckedResult(3, 1, expects_callbacks, &try_catch);
20671 CompileRun("test_get(obj);");
20672 CheckInstanceCheckedResult(4, 1, expects_callbacks, &try_catch);
20673 CompileRun("function test_set(o) { o.foo = 23; }"
20674 "test_set(obj);");
20675 CheckInstanceCheckedResult(4, 2, expects_callbacks, &try_catch);
20676 CompileRun("test_set(obj);");
20677 CheckInstanceCheckedResult(4, 3, expects_callbacks, &try_catch);
20678 CompileRun("test_set(obj);");
20679 CheckInstanceCheckedResult(4, 4, expects_callbacks, &try_catch);
20680
20681 // Test path through optimized code.
20682 CompileRun("%OptimizeFunctionOnNextCall(test_get);"
20683 "test_get(obj);");
20684 CheckInstanceCheckedResult(5, 4, expects_callbacks, &try_catch);
20685 CompileRun("%OptimizeFunctionOnNextCall(test_set);"
20686 "test_set(obj);");
20687 CheckInstanceCheckedResult(5, 5, expects_callbacks, &try_catch);
20688
20689 // Cleanup so that closures start out fresh in next check.
20690 CompileRun("%DeoptimizeFunction(test_get);"
20691 "%ClearFunctionTypeFeedback(test_get);"
20692 "%DeoptimizeFunction(test_set);"
20693 "%ClearFunctionTypeFeedback(test_set);");
20694}
20695
20696
20697THREADED_TEST(InstanceCheckOnInstanceAccessor) {
20698 v8::internal::FLAG_allow_natives_syntax = true;
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020699 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020700 v8::HandleScope scope(context->GetIsolate());
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020701
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000020702 Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020703 Local<ObjectTemplate> inst = templ->InstanceTemplate();
20704 inst->SetAccessor(v8_str("foo"),
20705 InstanceCheckedGetter, InstanceCheckedSetter,
20706 Handle<Value>(),
20707 v8::DEFAULT,
20708 v8::None,
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000020709 v8::AccessorSignature::New(context->GetIsolate(), templ));
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020710 context->Global()->Set(v8_str("f"), templ->GetFunction());
20711
20712 printf("Testing positive ...\n");
20713 CompileRun("var obj = new f();");
20714 CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
20715 CheckInstanceCheckedAccessors(true);
20716
20717 printf("Testing negative ...\n");
20718 CompileRun("var obj = {};"
20719 "obj.__proto__ = new f();");
20720 CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
20721 CheckInstanceCheckedAccessors(false);
20722}
20723
20724
20725THREADED_TEST(InstanceCheckOnInstanceAccessorWithInterceptor) {
20726 v8::internal::FLAG_allow_natives_syntax = true;
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020727 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020728 v8::HandleScope scope(context->GetIsolate());
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020729
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000020730 Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020731 Local<ObjectTemplate> inst = templ->InstanceTemplate();
20732 AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter);
20733 inst->SetAccessor(v8_str("foo"),
20734 InstanceCheckedGetter, InstanceCheckedSetter,
20735 Handle<Value>(),
20736 v8::DEFAULT,
20737 v8::None,
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000020738 v8::AccessorSignature::New(context->GetIsolate(), templ));
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020739 context->Global()->Set(v8_str("f"), templ->GetFunction());
20740
20741 printf("Testing positive ...\n");
20742 CompileRun("var obj = new f();");
20743 CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
20744 CheckInstanceCheckedAccessors(true);
20745
20746 printf("Testing negative ...\n");
20747 CompileRun("var obj = {};"
20748 "obj.__proto__ = new f();");
20749 CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
20750 CheckInstanceCheckedAccessors(false);
20751}
20752
20753
20754THREADED_TEST(InstanceCheckOnPrototypeAccessor) {
20755 v8::internal::FLAG_allow_natives_syntax = true;
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020756 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020757 v8::HandleScope scope(context->GetIsolate());
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020758
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000020759 Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020760 Local<ObjectTemplate> proto = templ->PrototypeTemplate();
20761 proto->SetAccessor(v8_str("foo"),
20762 InstanceCheckedGetter, InstanceCheckedSetter,
20763 Handle<Value>(),
20764 v8::DEFAULT,
20765 v8::None,
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000020766 v8::AccessorSignature::New(context->GetIsolate(), templ));
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020767 context->Global()->Set(v8_str("f"), templ->GetFunction());
20768
20769 printf("Testing positive ...\n");
20770 CompileRun("var obj = new f();");
20771 CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
20772 CheckInstanceCheckedAccessors(true);
20773
20774 printf("Testing negative ...\n");
20775 CompileRun("var obj = {};"
20776 "obj.__proto__ = new f();");
20777 CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
20778 CheckInstanceCheckedAccessors(false);
20779
20780 printf("Testing positive with modified prototype chain ...\n");
20781 CompileRun("var obj = new f();"
20782 "var pro = {};"
20783 "pro.__proto__ = obj.__proto__;"
20784 "obj.__proto__ = pro;");
20785 CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
20786 CheckInstanceCheckedAccessors(true);
20787}
20788
20789
20790TEST(TryFinallyMessage) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020791 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020792 v8::HandleScope scope(context->GetIsolate());
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020793 {
20794 // Test that the original error message is not lost if there is a
20795 // recursive call into Javascript is done in the finally block, e.g. to
20796 // initialize an IC. (crbug.com/129171)
20797 TryCatch try_catch;
20798 const char* trigger_ic =
20799 "try { \n"
20800 " throw new Error('test'); \n"
20801 "} finally { \n"
20802 " var x = 0; \n"
20803 " x++; \n" // Trigger an IC initialization here.
20804 "} \n";
20805 CompileRun(trigger_ic);
20806 CHECK(try_catch.HasCaught());
20807 Local<Message> message = try_catch.Message();
20808 CHECK(!message.IsEmpty());
20809 CHECK_EQ(2, message->GetLineNumber());
20810 }
20811
20812 {
20813 // Test that the original exception message is indeed overwritten if
20814 // a new error is thrown in the finally block.
20815 TryCatch try_catch;
20816 const char* throw_again =
20817 "try { \n"
20818 " throw new Error('test'); \n"
20819 "} finally { \n"
20820 " var x = 0; \n"
20821 " x++; \n"
20822 " throw new Error('again'); \n" // This is the new uncaught error.
20823 "} \n";
20824 CompileRun(throw_again);
20825 CHECK(try_catch.HasCaught());
20826 Local<Message> message = try_catch.Message();
20827 CHECK(!message.IsEmpty());
20828 CHECK_EQ(6, message->GetLineNumber());
20829 }
20830}
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000020831
20832
erik.corry@gmail.com88767242012-08-08 14:43:45 +000020833static void Helper137002(bool do_store,
20834 bool polymorphic,
20835 bool remove_accessor,
20836 bool interceptor) {
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000020837 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000020838 Local<ObjectTemplate> templ = ObjectTemplate::New(context->GetIsolate());
erik.corry@gmail.com88767242012-08-08 14:43:45 +000020839 if (interceptor) {
20840 templ->SetNamedPropertyHandler(FooGetInterceptor, FooSetInterceptor);
20841 } else {
20842 templ->SetAccessor(v8_str("foo"),
20843 GetterWhichReturns42,
20844 SetterWhichSetsYOnThisTo23);
20845 }
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000020846 context->Global()->Set(v8_str("obj"), templ->NewInstance());
20847
20848 // Turn monomorphic on slow object with native accessor, then turn
20849 // polymorphic, finally optimize to create negative lookup and fail.
erik.corry@gmail.com88767242012-08-08 14:43:45 +000020850 CompileRun(do_store ?
20851 "function f(x) { x.foo = void 0; }" :
20852 "function f(x) { return x.foo; }");
20853 CompileRun("obj.y = void 0;");
20854 if (!interceptor) {
20855 CompileRun("%OptimizeObjectForAddingMultipleProperties(obj, 1);");
20856 }
20857 CompileRun("obj.__proto__ = null;"
20858 "f(obj); f(obj); f(obj);");
20859 if (polymorphic) {
20860 CompileRun("f({});");
20861 }
20862 CompileRun("obj.y = void 0;"
20863 "%OptimizeFunctionOnNextCall(f);");
20864 if (remove_accessor) {
20865 CompileRun("delete obj.foo;");
20866 }
20867 CompileRun("var result = f(obj);");
20868 if (do_store) {
20869 CompileRun("result = obj.y;");
20870 }
20871 if (remove_accessor && !interceptor) {
20872 CHECK(context->Global()->Get(v8_str("result"))->IsUndefined());
20873 } else {
20874 CHECK_EQ(do_store ? 23 : 42,
20875 context->Global()->Get(v8_str("result"))->Int32Value());
20876 }
20877}
20878
20879
20880THREADED_TEST(Regress137002a) {
20881 i::FLAG_allow_natives_syntax = true;
20882 i::FLAG_compilation_cache = false;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020883 v8::HandleScope scope(CcTest::isolate());
erik.corry@gmail.com88767242012-08-08 14:43:45 +000020884 for (int i = 0; i < 16; i++) {
20885 Helper137002(i & 8, i & 4, i & 2, i & 1);
20886 }
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000020887}
20888
20889
20890THREADED_TEST(Regress137002b) {
20891 i::FLAG_allow_natives_syntax = true;
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000020892 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000020893 v8::Isolate* isolate = context->GetIsolate();
20894 v8::HandleScope scope(isolate);
20895 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000020896 templ->SetAccessor(v8_str("foo"),
20897 GetterWhichReturns42,
20898 SetterWhichSetsYOnThisTo23);
20899 context->Global()->Set(v8_str("obj"), templ->NewInstance());
20900
20901 // Turn monomorphic on slow object with native accessor, then just
20902 // delete the property and fail.
erik.corry@gmail.com88767242012-08-08 14:43:45 +000020903 CompileRun("function load(x) { return x.foo; }"
20904 "function store(x) { x.foo = void 0; }"
20905 "function keyed_load(x, key) { return x[key]; }"
20906 // Second version of function has a different source (add void 0)
20907 // so that it does not share code with the first version. This
20908 // ensures that the ICs are monomorphic.
20909 "function load2(x) { void 0; return x.foo; }"
20910 "function store2(x) { void 0; x.foo = void 0; }"
20911 "function keyed_load2(x, key) { void 0; return x[key]; }"
20912
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000020913 "obj.y = void 0;"
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000020914 "obj.__proto__ = null;"
erik.corry@gmail.com88767242012-08-08 14:43:45 +000020915 "var subobj = {};"
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000020916 "subobj.y = void 0;"
erik.corry@gmail.com88767242012-08-08 14:43:45 +000020917 "subobj.__proto__ = obj;"
20918 "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
20919
20920 // Make the ICs monomorphic.
20921 "load(obj); load(obj);"
20922 "load2(subobj); load2(subobj);"
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000020923 "store(obj); store(obj);"
20924 "store2(subobj); store2(subobj);"
erik.corry@gmail.com88767242012-08-08 14:43:45 +000020925 "keyed_load(obj, 'foo'); keyed_load(obj, 'foo');"
20926 "keyed_load2(subobj, 'foo'); keyed_load2(subobj, 'foo');"
20927
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000020928 // Actually test the shiny new ICs and better not crash. This
20929 // serves as a regression test for issue 142088 as well.
20930 "load(obj);"
20931 "load2(subobj);"
20932 "store(obj);"
20933 "store2(subobj);"
20934 "keyed_load(obj, 'foo');"
20935 "keyed_load2(subobj, 'foo');"
20936
erik.corry@gmail.com88767242012-08-08 14:43:45 +000020937 // Delete the accessor. It better not be called any more now.
20938 "delete obj.foo;"
20939 "obj.y = void 0;"
20940 "subobj.y = void 0;"
20941
20942 "var load_result = load(obj);"
20943 "var load_result2 = load2(subobj);"
20944 "var keyed_load_result = keyed_load(obj, 'foo');"
20945 "var keyed_load_result2 = keyed_load2(subobj, 'foo');"
20946 "store(obj);"
20947 "store2(subobj);"
20948 "var y_from_obj = obj.y;"
20949 "var y_from_subobj = subobj.y;");
20950 CHECK(context->Global()->Get(v8_str("load_result"))->IsUndefined());
20951 CHECK(context->Global()->Get(v8_str("load_result2"))->IsUndefined());
20952 CHECK(context->Global()->Get(v8_str("keyed_load_result"))->IsUndefined());
20953 CHECK(context->Global()->Get(v8_str("keyed_load_result2"))->IsUndefined());
20954 CHECK(context->Global()->Get(v8_str("y_from_obj"))->IsUndefined());
20955 CHECK(context->Global()->Get(v8_str("y_from_subobj"))->IsUndefined());
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000020956}
verwaest@chromium.org753aee42012-07-17 16:15:42 +000020957
20958
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000020959THREADED_TEST(Regress142088) {
20960 i::FLAG_allow_natives_syntax = true;
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000020961 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000020962 v8::Isolate* isolate = context->GetIsolate();
20963 v8::HandleScope scope(isolate);
20964 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000020965 templ->SetAccessor(v8_str("foo"),
20966 GetterWhichReturns42,
20967 SetterWhichSetsYOnThisTo23);
20968 context->Global()->Set(v8_str("obj"), templ->NewInstance());
20969
20970 CompileRun("function load(x) { return x.foo; }"
20971 "var o = Object.create(obj);"
20972 "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
20973 "load(o); load(o); load(o); load(o);");
20974}
20975
20976
verwaest@chromium.org753aee42012-07-17 16:15:42 +000020977THREADED_TEST(Regress137496) {
20978 i::FLAG_expose_gc = true;
verwaest@chromium.org753aee42012-07-17 16:15:42 +000020979 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020980 v8::HandleScope scope(context->GetIsolate());
verwaest@chromium.org753aee42012-07-17 16:15:42 +000020981
20982 // Compile a try-finally clause where the finally block causes a GC
20983 // while there still is a message pending for external reporting.
20984 TryCatch try_catch;
20985 try_catch.SetVerbose(true);
20986 CompileRun("try { throw new Error(); } finally { gc(); }");
20987 CHECK(try_catch.HasCaught());
20988}
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000020989
20990
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000020991THREADED_TEST(Regress149912) {
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000020992 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020993 v8::HandleScope scope(context->GetIsolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000020994 Handle<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000020995 AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter);
20996 context->Global()->Set(v8_str("Bug"), templ->GetFunction());
20997 CompileRun("Number.prototype.__proto__ = new Bug; var x = 0; x.foo();");
20998}
20999
21000
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000021001THREADED_TEST(Regress157124) {
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000021002 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000021003 v8::Isolate* isolate = context->GetIsolate();
21004 v8::HandleScope scope(isolate);
21005 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000021006 Local<Object> obj = templ->NewInstance();
21007 obj->GetIdentityHash();
21008 obj->DeleteHiddenValue(v8_str("Bug"));
21009}
21010
21011
ulan@chromium.org6e196bf2013-03-13 09:38:22 +000021012THREADED_TEST(Regress2535) {
21013 i::FLAG_harmony_collections = true;
ulan@chromium.org6e196bf2013-03-13 09:38:22 +000021014 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000021015 v8::HandleScope scope(context->GetIsolate());
ulan@chromium.org6e196bf2013-03-13 09:38:22 +000021016 Local<Value> set_value = CompileRun("new Set();");
danno@chromium.orgf95d4b92013-06-13 14:40:17 +000021017 Local<Object> set_object(Local<Object>::Cast(set_value));
ulan@chromium.org6e196bf2013-03-13 09:38:22 +000021018 CHECK_EQ(0, set_object->InternalFieldCount());
21019 Local<Value> map_value = CompileRun("new Map();");
danno@chromium.orgf95d4b92013-06-13 14:40:17 +000021020 Local<Object> map_object(Local<Object>::Cast(map_value));
ulan@chromium.org6e196bf2013-03-13 09:38:22 +000021021 CHECK_EQ(0, map_object->InternalFieldCount());
21022}
21023
21024
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000021025THREADED_TEST(Regress2746) {
21026 LocalContext context;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000021027 v8::Isolate* isolate = context->GetIsolate();
21028 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000021029 Local<Object> obj = Object::New(isolate);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000021030 Local<String> key = String::NewFromUtf8(context->GetIsolate(), "key");
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000021031 obj->SetHiddenValue(key, v8::Undefined(isolate));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000021032 Local<Value> value = obj->GetHiddenValue(key);
21033 CHECK(!value.IsEmpty());
21034 CHECK(value->IsUndefined());
21035}
21036
21037
jkummerow@chromium.org10480472013-07-17 08:22:15 +000021038THREADED_TEST(Regress260106) {
21039 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000021040 v8::Isolate* isolate = context->GetIsolate();
21041 v8::HandleScope scope(isolate);
21042 Local<FunctionTemplate> templ = FunctionTemplate::New(isolate,
21043 DummyCallHandler);
jkummerow@chromium.org10480472013-07-17 08:22:15 +000021044 CompileRun("for (var i = 0; i < 128; i++) Object.prototype[i] = 0;");
21045 Local<Function> function = templ->GetFunction();
21046 CHECK(!function.IsEmpty());
21047 CHECK(function->IsFunction());
21048}
21049
21050
danno@chromium.org59400602013-08-13 17:09:37 +000021051THREADED_TEST(JSONParseObject) {
21052 LocalContext context;
21053 HandleScope scope(context->GetIsolate());
21054 Local<Value> obj = v8::JSON::Parse(v8_str("{\"x\":42}"));
21055 Handle<Object> global = context->Global();
21056 global->Set(v8_str("obj"), obj);
21057 ExpectString("JSON.stringify(obj)", "{\"x\":42}");
21058}
21059
21060
21061THREADED_TEST(JSONParseNumber) {
21062 LocalContext context;
21063 HandleScope scope(context->GetIsolate());
21064 Local<Value> obj = v8::JSON::Parse(v8_str("42"));
21065 Handle<Object> global = context->Global();
21066 global->Set(v8_str("obj"), obj);
21067 ExpectString("JSON.stringify(obj)", "42");
21068}
21069
21070
verwaest@chromium.org662436e2013-08-28 08:41:27 +000021071#if V8_OS_POSIX
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000021072class ThreadInterruptTest {
21073 public:
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000021074 ThreadInterruptTest() : sem_(0), sem_value_(0) { }
21075 ~ThreadInterruptTest() {}
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000021076
21077 void RunTest() {
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000021078 InterruptThread i_thread(this);
21079 i_thread.Start();
21080
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000021081 sem_.Wait();
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000021082 CHECK_EQ(kExpectedValue, sem_value_);
21083 }
21084
21085 private:
21086 static const int kExpectedValue = 1;
21087
21088 class InterruptThread : public i::Thread {
21089 public:
21090 explicit InterruptThread(ThreadInterruptTest* test)
21091 : Thread("InterruptThread"), test_(test) {}
21092
21093 virtual void Run() {
21094 struct sigaction action;
21095
21096 // Ensure that we'll enter waiting condition
21097 i::OS::Sleep(100);
21098
21099 // Setup signal handler
21100 memset(&action, 0, sizeof(action));
21101 action.sa_handler = SignalHandler;
21102 sigaction(SIGCHLD, &action, NULL);
21103
21104 // Send signal
21105 kill(getpid(), SIGCHLD);
21106
21107 // Ensure that if wait has returned because of error
21108 i::OS::Sleep(100);
21109
21110 // Set value and signal semaphore
21111 test_->sem_value_ = 1;
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000021112 test_->sem_.Signal();
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000021113 }
21114
21115 static void SignalHandler(int signal) {
21116 }
21117
21118 private:
21119 ThreadInterruptTest* test_;
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000021120 };
21121
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000021122 i::Semaphore sem_;
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000021123 volatile int sem_value_;
21124};
21125
21126
21127THREADED_TEST(SemaphoreInterruption) {
21128 ThreadInterruptTest().RunTest();
21129}
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000021130
danno@chromium.org169691d2013-07-15 08:01:13 +000021131
hpayer@chromium.orgea9b8ba2013-12-20 19:22:39 +000021132#endif // V8_OS_POSIX
21133
21134
danno@chromium.org169691d2013-07-15 08:01:13 +000021135static bool NamedAccessAlwaysBlocked(Local<v8::Object> global,
21136 Local<Value> name,
21137 v8::AccessType type,
21138 Local<Value> data) {
21139 i::PrintF("Named access blocked.\n");
21140 return false;
21141}
21142
21143
21144static bool IndexAccessAlwaysBlocked(Local<v8::Object> global,
21145 uint32_t key,
21146 v8::AccessType type,
21147 Local<Value> data) {
21148 i::PrintF("Indexed access blocked.\n");
21149 return false;
21150}
21151
21152
21153void UnreachableCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
21154 CHECK(false);
21155}
21156
21157
21158TEST(JSONStringifyAccessCheck) {
21159 v8::V8::Initialize();
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000021160 v8::Isolate* isolate = CcTest::isolate();
21161 v8::HandleScope scope(isolate);
danno@chromium.org169691d2013-07-15 08:01:13 +000021162
21163 // Create an ObjectTemplate for global objects and install access
21164 // check callbacks that will block access.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000021165 v8::Handle<v8::ObjectTemplate> global_template =
21166 v8::ObjectTemplate::New(isolate);
danno@chromium.org169691d2013-07-15 08:01:13 +000021167 global_template->SetAccessCheckCallbacks(NamedAccessAlwaysBlocked,
21168 IndexAccessAlwaysBlocked);
21169
21170 // Create a context and set an x property on it's global object.
21171 LocalContext context0(NULL, global_template);
21172 v8::Handle<v8::Object> global0 = context0->Global();
21173 global0->Set(v8_str("x"), v8_num(42));
21174 ExpectString("JSON.stringify(this)", "{\"x\":42}");
21175
21176 for (int i = 0; i < 2; i++) {
21177 if (i == 1) {
21178 // Install a toJSON function on the second run.
21179 v8::Handle<v8::FunctionTemplate> toJSON =
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000021180 v8::FunctionTemplate::New(isolate, UnreachableCallback);
danno@chromium.org169691d2013-07-15 08:01:13 +000021181
21182 global0->Set(v8_str("toJSON"), toJSON->GetFunction());
21183 }
21184 // Create a context with a different security token so that the
21185 // failed access check callback will be called on each access.
21186 LocalContext context1(NULL, global_template);
21187 context1->Global()->Set(v8_str("other"), global0);
21188
21189 ExpectString("JSON.stringify(other)", "{}");
21190 ExpectString("JSON.stringify({ 'a' : other, 'b' : ['c'] })",
21191 "{\"a\":{},\"b\":[\"c\"]}");
21192 ExpectString("JSON.stringify([other, 'b', 'c'])",
21193 "[{},\"b\",\"c\"]");
21194
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000021195 v8::Handle<v8::Array> array = v8::Array::New(isolate, 2);
danno@chromium.org169691d2013-07-15 08:01:13 +000021196 array->Set(0, v8_str("a"));
21197 array->Set(1, v8_str("b"));
21198 context1->Global()->Set(v8_str("array"), array);
21199 ExpectString("JSON.stringify(array)", "[\"a\",\"b\"]");
21200 array->TurnOnAccessCheck();
21201 ExpectString("JSON.stringify(array)", "[]");
21202 ExpectString("JSON.stringify([array])", "[[]]");
21203 ExpectString("JSON.stringify({'a' : array})", "{\"a\":[]}");
21204 }
21205}
21206
21207
21208bool access_check_fail_thrown = false;
21209bool catch_callback_called = false;
21210
21211
21212// Failed access check callback that performs a GC on each invocation.
21213void FailedAccessCheckThrows(Local<v8::Object> target,
21214 v8::AccessType type,
21215 Local<v8::Value> data) {
21216 access_check_fail_thrown = true;
21217 i::PrintF("Access check failed. Error thrown.\n");
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000021218 CcTest::isolate()->ThrowException(
21219 v8::Exception::Error(v8_str("cross context")));
danno@chromium.org169691d2013-07-15 08:01:13 +000021220}
21221
21222
21223void CatcherCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
21224 for (int i = 0; i < args.Length(); i++) {
21225 i::PrintF("%s\n", *String::Utf8Value(args[i]));
21226 }
21227 catch_callback_called = true;
21228}
21229
21230
21231void HasOwnPropertyCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
21232 args[0]->ToObject()->HasOwnProperty(args[1]->ToString());
21233}
21234
21235
21236void CheckCorrectThrow(const char* script) {
21237 // Test that the script, when wrapped into a try-catch, triggers the catch
21238 // clause due to failed access check throwing an exception.
21239 // The subsequent try-catch should run without any exception.
21240 access_check_fail_thrown = false;
21241 catch_callback_called = false;
21242 i::ScopedVector<char> source(1024);
21243 i::OS::SNPrintF(source, "try { %s; } catch (e) { catcher(e); }", script);
21244 CompileRun(source.start());
21245 CHECK(access_check_fail_thrown);
21246 CHECK(catch_callback_called);
21247
21248 access_check_fail_thrown = false;
21249 catch_callback_called = false;
21250 CompileRun("try { [1, 2, 3].sort(); } catch (e) { catcher(e) };");
21251 CHECK(!access_check_fail_thrown);
21252 CHECK(!catch_callback_called);
21253}
21254
21255
21256TEST(AccessCheckThrows) {
21257 i::FLAG_allow_natives_syntax = true;
21258 v8::V8::Initialize();
21259 v8::V8::SetFailedAccessCheckCallbackFunction(&FailedAccessCheckThrows);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000021260 v8::Isolate* isolate = CcTest::isolate();
21261 v8::HandleScope scope(isolate);
danno@chromium.org169691d2013-07-15 08:01:13 +000021262
21263 // Create an ObjectTemplate for global objects and install access
21264 // check callbacks that will block access.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000021265 v8::Handle<v8::ObjectTemplate> global_template =
21266 v8::ObjectTemplate::New(isolate);
danno@chromium.org169691d2013-07-15 08:01:13 +000021267 global_template->SetAccessCheckCallbacks(NamedAccessAlwaysBlocked,
21268 IndexAccessAlwaysBlocked);
21269
21270 // Create a context and set an x property on it's global object.
21271 LocalContext context0(NULL, global_template);
21272 context0->Global()->Set(v8_str("x"), v8_num(42));
21273 v8::Handle<v8::Object> global0 = context0->Global();
21274
21275 // Create a context with a different security token so that the
21276 // failed access check callback will be called on each access.
21277 LocalContext context1(NULL, global_template);
21278 context1->Global()->Set(v8_str("other"), global0);
21279
21280 v8::Handle<v8::FunctionTemplate> catcher_fun =
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000021281 v8::FunctionTemplate::New(isolate, CatcherCallback);
danno@chromium.org169691d2013-07-15 08:01:13 +000021282 context1->Global()->Set(v8_str("catcher"), catcher_fun->GetFunction());
21283
21284 v8::Handle<v8::FunctionTemplate> has_own_property_fun =
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000021285 v8::FunctionTemplate::New(isolate, HasOwnPropertyCallback);
danno@chromium.org169691d2013-07-15 08:01:13 +000021286 context1->Global()->Set(v8_str("has_own_property"),
21287 has_own_property_fun->GetFunction());
21288
21289 { v8::TryCatch try_catch;
21290 access_check_fail_thrown = false;
21291 CompileRun("other.x;");
21292 CHECK(access_check_fail_thrown);
21293 CHECK(try_catch.HasCaught());
21294 }
21295
21296 CheckCorrectThrow("other.x");
21297 CheckCorrectThrow("other[1]");
21298 CheckCorrectThrow("JSON.stringify(other)");
21299 CheckCorrectThrow("has_own_property(other, 'x')");
21300 CheckCorrectThrow("%GetProperty(other, 'x')");
21301 CheckCorrectThrow("%SetProperty(other, 'x', 'foo', 1, 0)");
21302 CheckCorrectThrow("%IgnoreAttributesAndSetProperty(other, 'x', 'foo')");
21303 CheckCorrectThrow("%DeleteProperty(other, 'x', 0)");
21304 CheckCorrectThrow("%DeleteProperty(other, '1', 0)");
21305 CheckCorrectThrow("%HasLocalProperty(other, 'x')");
21306 CheckCorrectThrow("%HasProperty(other, 'x')");
21307 CheckCorrectThrow("%HasElement(other, 1)");
21308 CheckCorrectThrow("%IsPropertyEnumerable(other, 'x')");
21309 CheckCorrectThrow("%GetPropertyNames(other)");
machenbach@chromium.org03453962014-01-10 14:16:31 +000021310 // PROPERTY_ATTRIBUTES_NONE = 0
21311 CheckCorrectThrow("%GetLocalPropertyNames(other, 0)");
danno@chromium.org169691d2013-07-15 08:01:13 +000021312 CheckCorrectThrow("%DefineOrRedefineAccessorProperty("
21313 "other, 'x', null, null, 1)");
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +000021314
21315 // Reset the failed access check callback so it does not influence
21316 // the other tests.
21317 v8::V8::SetFailedAccessCheckCallbackFunction(NULL);
danno@chromium.org169691d2013-07-15 08:01:13 +000021318}
21319
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000021320
21321THREADED_TEST(Regress256330) {
21322 i::FLAG_allow_natives_syntax = true;
21323 LocalContext context;
21324 v8::HandleScope scope(context->GetIsolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000021325 Handle<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000021326 AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter);
21327 context->Global()->Set(v8_str("Bug"), templ->GetFunction());
21328 CompileRun("\"use strict\"; var o = new Bug;"
21329 "function f(o) { o.x = 10; };"
21330 "f(o); f(o); f(o);"
21331 "%OptimizeFunctionOnNextCall(f);"
21332 "f(o);");
21333 ExpectBoolean("%GetOptimizationStatus(f) != 2", true);
21334}
21335
21336
21337THREADED_TEST(CrankshaftInterceptorSetter) {
21338 i::FLAG_allow_natives_syntax = true;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000021339 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000021340 Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000021341 AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
21342 LocalContext env;
21343 env->Global()->Set(v8_str("Obj"), templ->GetFunction());
21344 CompileRun("var obj = new Obj;"
21345 // Initialize fields to avoid transitions later.
21346 "obj.age = 0;"
21347 "obj.accessor_age = 42;"
21348 "function setter(i) { this.accessor_age = i; };"
21349 "function getter() { return this.accessor_age; };"
21350 "function setAge(i) { obj.age = i; };"
21351 "Object.defineProperty(obj, 'age', { get:getter, set:setter });"
21352 "setAge(1);"
21353 "setAge(2);"
21354 "setAge(3);"
21355 "%OptimizeFunctionOnNextCall(setAge);"
21356 "setAge(4);");
21357 // All stores went through the interceptor.
21358 ExpectInt32("obj.interceptor_age", 4);
21359 ExpectInt32("obj.accessor_age", 42);
21360}
21361
21362
21363THREADED_TEST(CrankshaftInterceptorGetter) {
21364 i::FLAG_allow_natives_syntax = true;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000021365 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000021366 Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000021367 AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
21368 LocalContext env;
21369 env->Global()->Set(v8_str("Obj"), templ->GetFunction());
21370 CompileRun("var obj = new Obj;"
21371 // Initialize fields to avoid transitions later.
21372 "obj.age = 1;"
21373 "obj.accessor_age = 42;"
21374 "function getter() { return this.accessor_age; };"
21375 "function getAge() { return obj.interceptor_age; };"
21376 "Object.defineProperty(obj, 'interceptor_age', { get:getter });"
21377 "getAge();"
21378 "getAge();"
21379 "getAge();"
21380 "%OptimizeFunctionOnNextCall(getAge);");
21381 // Access through interceptor.
21382 ExpectInt32("getAge()", 1);
21383}
21384
21385
21386THREADED_TEST(CrankshaftInterceptorFieldRead) {
21387 i::FLAG_allow_natives_syntax = true;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000021388 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000021389 Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000021390 AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
21391 LocalContext env;
21392 env->Global()->Set(v8_str("Obj"), templ->GetFunction());
21393 CompileRun("var obj = new Obj;"
21394 "obj.__proto__.interceptor_age = 42;"
21395 "obj.age = 100;"
21396 "function getAge() { return obj.interceptor_age; };");
21397 ExpectInt32("getAge();", 100);
21398 ExpectInt32("getAge();", 100);
21399 ExpectInt32("getAge();", 100);
21400 CompileRun("%OptimizeFunctionOnNextCall(getAge);");
21401 // Access through interceptor.
21402 ExpectInt32("getAge();", 100);
21403}
21404
21405
21406THREADED_TEST(CrankshaftInterceptorFieldWrite) {
21407 i::FLAG_allow_natives_syntax = true;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000021408 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000021409 Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000021410 AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
21411 LocalContext env;
21412 env->Global()->Set(v8_str("Obj"), templ->GetFunction());
21413 CompileRun("var obj = new Obj;"
21414 "obj.age = 100000;"
21415 "function setAge(i) { obj.age = i };"
21416 "setAge(100);"
21417 "setAge(101);"
21418 "setAge(102);"
21419 "%OptimizeFunctionOnNextCall(setAge);"
21420 "setAge(103);");
21421 ExpectInt32("obj.age", 100000);
21422 ExpectInt32("obj.interceptor_age", 103);
21423}
21424
dslomov@chromium.org639bac02013-09-09 11:58:54 +000021425
hpayer@chromium.orgea9b8ba2013-12-20 19:22:39 +000021426class RequestInterruptTestBase {
21427 public:
21428 RequestInterruptTestBase()
21429 : env_(),
21430 isolate_(env_->GetIsolate()),
21431 sem_(0),
21432 warmup_(20000),
21433 should_continue_(true) {
21434 }
21435
21436 virtual ~RequestInterruptTestBase() { }
21437
21438 virtual void TestBody() = 0;
21439
21440 void RunTest() {
21441 InterruptThread i_thread(this);
21442 i_thread.Start();
21443
21444 v8::HandleScope handle_scope(isolate_);
21445
21446 TestBody();
21447
21448 isolate_->ClearInterrupt();
21449
21450 // Verify we arrived here because interruptor was called
21451 // not due to a bug causing us to exit the loop too early.
21452 CHECK(!should_continue());
21453 }
21454
21455 void WakeUpInterruptor() {
21456 sem_.Signal();
21457 }
21458
21459 bool should_continue() const { return should_continue_; }
21460
21461 bool ShouldContinue() {
21462 if (warmup_ > 0) {
21463 if (--warmup_ == 0) {
21464 WakeUpInterruptor();
21465 }
21466 }
21467
21468 return should_continue_;
21469 }
21470
21471 protected:
21472 static void ShouldContinueCallback(
21473 const v8::FunctionCallbackInfo<Value>& info) {
21474 RequestInterruptTestBase* test =
21475 reinterpret_cast<RequestInterruptTestBase*>(
21476 info.Data().As<v8::External>()->Value());
21477 info.GetReturnValue().Set(test->ShouldContinue());
21478 }
21479
21480 class InterruptThread : public i::Thread {
21481 public:
21482 explicit InterruptThread(RequestInterruptTestBase* test)
21483 : Thread("RequestInterruptTest"), test_(test) {}
21484
21485 virtual void Run() {
21486 test_->sem_.Wait();
21487 test_->isolate_->RequestInterrupt(&OnInterrupt, test_);
21488 }
21489
21490 static void OnInterrupt(v8::Isolate* isolate, void* data) {
21491 reinterpret_cast<RequestInterruptTestBase*>(data)->
21492 should_continue_ = false;
21493 }
21494
21495 private:
21496 RequestInterruptTestBase* test_;
21497 };
21498
21499 LocalContext env_;
21500 v8::Isolate* isolate_;
21501 i::Semaphore sem_;
21502 int warmup_;
21503 bool should_continue_;
21504};
21505
21506
21507class RequestInterruptTestWithFunctionCall : public RequestInterruptTestBase {
21508 public:
21509 virtual void TestBody() {
21510 Local<Function> func = Function::New(
21511 isolate_, ShouldContinueCallback, v8::External::New(isolate_, this));
21512 env_->Global()->Set(v8_str("ShouldContinue"), func);
21513
21514 CompileRun("while (ShouldContinue()) { }");
21515 }
21516};
21517
21518
21519class RequestInterruptTestWithMethodCall : public RequestInterruptTestBase {
21520 public:
21521 virtual void TestBody() {
21522 v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
21523 v8::Local<v8::Template> proto = t->PrototypeTemplate();
21524 proto->Set(v8_str("shouldContinue"), Function::New(
21525 isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
21526 env_->Global()->Set(v8_str("Klass"), t->GetFunction());
21527
21528 CompileRun("var obj = new Klass; while (obj.shouldContinue()) { }");
21529 }
21530};
21531
21532
21533class RequestInterruptTestWithAccessor : public RequestInterruptTestBase {
21534 public:
21535 virtual void TestBody() {
21536 v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
21537 v8::Local<v8::Template> proto = t->PrototypeTemplate();
21538 proto->SetAccessorProperty(v8_str("shouldContinue"), FunctionTemplate::New(
21539 isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
21540 env_->Global()->Set(v8_str("Klass"), t->GetFunction());
21541
21542 CompileRun("var obj = new Klass; while (obj.shouldContinue) { }");
21543 }
21544};
21545
21546
21547class RequestInterruptTestWithNativeAccessor : public RequestInterruptTestBase {
21548 public:
21549 virtual void TestBody() {
21550 v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
21551 t->InstanceTemplate()->SetNativeDataProperty(
21552 v8_str("shouldContinue"),
21553 &ShouldContinueNativeGetter,
21554 NULL,
21555 v8::External::New(isolate_, this));
21556 env_->Global()->Set(v8_str("Klass"), t->GetFunction());
21557
21558 CompileRun("var obj = new Klass; while (obj.shouldContinue) { }");
21559 }
21560
21561 private:
21562 static void ShouldContinueNativeGetter(
21563 Local<String> property,
21564 const v8::PropertyCallbackInfo<v8::Value>& info) {
21565 RequestInterruptTestBase* test =
21566 reinterpret_cast<RequestInterruptTestBase*>(
21567 info.Data().As<v8::External>()->Value());
21568 info.GetReturnValue().Set(test->ShouldContinue());
21569 }
21570};
21571
21572
21573class RequestInterruptTestWithMethodCallAndInterceptor
21574 : public RequestInterruptTestBase {
21575 public:
21576 virtual void TestBody() {
21577 v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
21578 v8::Local<v8::Template> proto = t->PrototypeTemplate();
21579 proto->Set(v8_str("shouldContinue"), Function::New(
21580 isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
21581 v8::Local<v8::ObjectTemplate> instance_template = t->InstanceTemplate();
21582 instance_template->SetNamedPropertyHandler(EmptyInterceptor);
21583
21584 env_->Global()->Set(v8_str("Klass"), t->GetFunction());
21585
21586 CompileRun("var obj = new Klass; while (obj.shouldContinue()) { }");
21587 }
21588
21589 private:
21590 static void EmptyInterceptor(
21591 Local<String> property,
21592 const v8::PropertyCallbackInfo<v8::Value>& info) {
21593 }
21594};
21595
21596
21597class RequestInterruptTestWithMathAbs : public RequestInterruptTestBase {
21598 public:
21599 virtual void TestBody() {
21600 env_->Global()->Set(v8_str("WakeUpInterruptor"), Function::New(
21601 isolate_,
21602 WakeUpInterruptorCallback,
21603 v8::External::New(isolate_, this)));
21604
21605 env_->Global()->Set(v8_str("ShouldContinue"), Function::New(
21606 isolate_,
21607 ShouldContinueCallback,
21608 v8::External::New(isolate_, this)));
21609
21610 i::FLAG_allow_natives_syntax = true;
21611 CompileRun("function loopish(o) {"
21612 " var pre = 10;"
21613 " while (o.abs(1) > 0) {"
21614 " if (o.abs(1) >= 0 && !ShouldContinue()) break;"
21615 " if (pre > 0) {"
21616 " if (--pre === 0) WakeUpInterruptor(o === Math);"
21617 " }"
21618 " }"
21619 "}"
21620 "var i = 50;"
21621 "var obj = {abs: function () { return i-- }, x: null};"
21622 "delete obj.x;"
21623 "loopish(obj);"
21624 "%OptimizeFunctionOnNextCall(loopish);"
21625 "loopish(Math);");
21626
21627 i::FLAG_allow_natives_syntax = false;
21628 }
21629
21630 private:
21631 static void WakeUpInterruptorCallback(
21632 const v8::FunctionCallbackInfo<Value>& info) {
21633 if (!info[0]->BooleanValue()) return;
21634
21635 RequestInterruptTestBase* test =
21636 reinterpret_cast<RequestInterruptTestBase*>(
21637 info.Data().As<v8::External>()->Value());
21638 test->WakeUpInterruptor();
21639 }
21640
21641 static void ShouldContinueCallback(
21642 const v8::FunctionCallbackInfo<Value>& info) {
21643 RequestInterruptTestBase* test =
21644 reinterpret_cast<RequestInterruptTestBase*>(
21645 info.Data().As<v8::External>()->Value());
21646 info.GetReturnValue().Set(test->should_continue());
21647 }
21648};
21649
21650
21651TEST(RequestInterruptTestWithFunctionCall) {
21652 RequestInterruptTestWithFunctionCall().RunTest();
21653}
21654
21655
21656TEST(RequestInterruptTestWithMethodCall) {
21657 RequestInterruptTestWithMethodCall().RunTest();
21658}
21659
21660
21661TEST(RequestInterruptTestWithAccessor) {
21662 RequestInterruptTestWithAccessor().RunTest();
21663}
21664
21665
21666TEST(RequestInterruptTestWithNativeAccessor) {
21667 RequestInterruptTestWithNativeAccessor().RunTest();
21668}
21669
21670
21671TEST(RequestInterruptTestWithMethodCallAndInterceptor) {
21672 RequestInterruptTestWithMethodCallAndInterceptor().RunTest();
21673}
21674
21675
21676TEST(RequestInterruptTestWithMathAbs) {
21677 RequestInterruptTestWithMathAbs().RunTest();
21678}
dslomov@chromium.org639bac02013-09-09 11:58:54 +000021679
21680
21681static Local<Value> function_new_expected_env;
21682static void FunctionNewCallback(const v8::FunctionCallbackInfo<Value>& info) {
21683 CHECK_EQ(function_new_expected_env, info.Data());
21684 info.GetReturnValue().Set(17);
21685}
21686
21687
21688THREADED_TEST(FunctionNew) {
21689 LocalContext env;
21690 v8::Isolate* isolate = env->GetIsolate();
21691 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000021692 Local<Object> data = v8::Object::New(isolate);
dslomov@chromium.org639bac02013-09-09 11:58:54 +000021693 function_new_expected_env = data;
21694 Local<Function> func = Function::New(isolate, FunctionNewCallback, data);
21695 env->Global()->Set(v8_str("func"), func);
21696 Local<Value> result = CompileRun("func();");
ulan@chromium.org0f13e742014-01-03 15:51:11 +000021697 CHECK_EQ(v8::Integer::New(isolate, 17), result);
dslomov@chromium.org639bac02013-09-09 11:58:54 +000021698 // Verify function not cached
21699 int serial_number =
21700 i::Smi::cast(v8::Utils::OpenHandle(*func)
21701 ->shared()->get_api_func_data()->serial_number())->value();
21702 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
21703 i::Object* elm = i_isolate->native_context()->function_cache()
21704 ->GetElementNoExceptionThrown(i_isolate, serial_number);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000021705 CHECK(elm->IsUndefined());
21706 // Verify that each Function::New creates a new function instance
ulan@chromium.org0f13e742014-01-03 15:51:11 +000021707 Local<Object> data2 = v8::Object::New(isolate);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000021708 function_new_expected_env = data2;
21709 Local<Function> func2 = Function::New(isolate, FunctionNewCallback, data2);
21710 CHECK(!func2->IsNull());
21711 CHECK_NE(func, func2);
21712 env->Global()->Set(v8_str("func2"), func2);
21713 Local<Value> result2 = CompileRun("func2();");
ulan@chromium.org0f13e742014-01-03 15:51:11 +000021714 CHECK_EQ(v8::Integer::New(isolate, 17), result2);
dslomov@chromium.org639bac02013-09-09 11:58:54 +000021715}
21716
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000021717
21718TEST(EscapeableHandleScope) {
21719 HandleScope outer_scope(CcTest::isolate());
21720 LocalContext context;
21721 const int runs = 10;
21722 Local<String> values[runs];
21723 for (int i = 0; i < runs; i++) {
21724 v8::EscapableHandleScope inner_scope(CcTest::isolate());
21725 Local<String> value;
21726 if (i != 0) value = v8_str("escape value");
21727 values[i] = inner_scope.Escape(value);
21728 }
21729 for (int i = 0; i < runs; i++) {
21730 Local<String> expected;
21731 if (i != 0) {
21732 CHECK_EQ(v8_str("escape value"), values[i]);
21733 } else {
21734 CHECK(values[i].IsEmpty());
21735 }
21736 }
21737}