blob: 839ddd9858f5cb43bae637531c55742a601a328b [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
16116 // Check pass through of assigned smis
16117 result = CompileRun("var sum = 0;"
16118 "for (var i = 0; i < 8; i++) {"
16119 " sum += ext_array[i] = ext_array[i] = -i;"
16120 "}"
16121 "sum;");
16122 CHECK_EQ(-28, result->Int32Value());
16123
16124 // Check assigned smis
16125 result = CompileRun("for (var i = 0; i < 8; i++) {"
16126 " ext_array[i] = i;"
16127 "}"
16128 "var sum = 0;"
16129 "for (var i = 0; i < 8; i++) {"
16130 " sum += ext_array[i];"
16131 "}"
16132 "sum;");
16133 CHECK_EQ(28, result->Int32Value());
16134
16135 // Check assigned smis in reverse order
16136 result = CompileRun("for (var i = 8; --i >= 0; ) {"
16137 " ext_array[i] = i;"
16138 "}"
16139 "var sum = 0;"
16140 "for (var i = 0; i < 8; i++) {"
16141 " sum += ext_array[i];"
16142 "}"
16143 "sum;");
16144 CHECK_EQ(28, result->Int32Value());
16145
16146 // Check pass through of assigned HeapNumbers
16147 result = CompileRun("var sum = 0;"
16148 "for (var i = 0; i < 16; i+=2) {"
16149 " sum += ext_array[i] = ext_array[i] = (-i * 0.5);"
16150 "}"
16151 "sum;");
16152 CHECK_EQ(-28, result->Int32Value());
16153
16154 // Check assigned HeapNumbers
16155 result = CompileRun("for (var i = 0; i < 16; i+=2) {"
16156 " ext_array[i] = (i * 0.5);"
16157 "}"
16158 "var sum = 0;"
16159 "for (var i = 0; i < 16; i+=2) {"
16160 " sum += ext_array[i];"
16161 "}"
16162 "sum;");
16163 CHECK_EQ(28, result->Int32Value());
16164
16165 // Check assigned HeapNumbers in reverse order
16166 result = CompileRun("for (var i = 14; i >= 0; i-=2) {"
16167 " ext_array[i] = (i * 0.5);"
16168 "}"
16169 "var sum = 0;"
16170 "for (var i = 0; i < 16; i+=2) {"
16171 " sum += ext_array[i];"
16172 "}"
16173 "sum;");
16174 CHECK_EQ(28, result->Int32Value());
16175
16176 i::ScopedVector<char> test_buf(1024);
16177
16178 // Check legal boundary conditions.
16179 // The repeated loads and stores ensure the ICs are exercised.
16180 const char* boundary_program =
16181 "var res = 0;"
16182 "for (var i = 0; i < 16; i++) {"
16183 " ext_array[i] = %lld;"
16184 " if (i > 8) {"
16185 " res = ext_array[i];"
16186 " }"
16187 "}"
16188 "res;";
16189 i::OS::SNPrintF(test_buf,
16190 boundary_program,
16191 low);
16192 result = CompileRun(test_buf.start());
16193 CHECK_EQ(low, result->IntegerValue());
16194
16195 i::OS::SNPrintF(test_buf,
16196 boundary_program,
16197 high);
16198 result = CompileRun(test_buf.start());
16199 CHECK_EQ(high, result->IntegerValue());
16200
16201 // Check misprediction of type in IC.
16202 result = CompileRun("var tmp_array = ext_array;"
16203 "var sum = 0;"
16204 "for (var i = 0; i < 8; i++) {"
16205 " tmp_array[i] = i;"
16206 " sum += tmp_array[i];"
16207 " if (i == 4) {"
16208 " tmp_array = {};"
16209 " }"
16210 "}"
16211 "sum;");
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000016212 // Force GC to trigger verification.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000016213 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org3811b432009-10-28 14:53:37 +000016214 CHECK_EQ(28, result->Int32Value());
16215
16216 // Make sure out-of-range loads do not throw.
16217 i::OS::SNPrintF(test_buf,
16218 "var caught_exception = false;"
16219 "try {"
16220 " ext_array[%d];"
16221 "} catch (e) {"
16222 " caught_exception = true;"
16223 "}"
16224 "caught_exception;",
danno@chromium.orgf005df62013-04-30 16:36:45 +000016225 element_count);
ager@chromium.org3811b432009-10-28 14:53:37 +000016226 result = CompileRun(test_buf.start());
16227 CHECK_EQ(false, result->BooleanValue());
16228
16229 // Make sure out-of-range stores do not throw.
16230 i::OS::SNPrintF(test_buf,
16231 "var caught_exception = false;"
16232 "try {"
16233 " ext_array[%d] = 1;"
16234 "} catch (e) {"
16235 " caught_exception = true;"
16236 "}"
16237 "caught_exception;",
danno@chromium.orgf005df62013-04-30 16:36:45 +000016238 element_count);
ager@chromium.org3811b432009-10-28 14:53:37 +000016239 result = CompileRun(test_buf.start());
16240 CHECK_EQ(false, result->BooleanValue());
16241
16242 // Check other boundary conditions, values and operations.
16243 result = CompileRun("for (var i = 0; i < 8; i++) {"
16244 " ext_array[7] = undefined;"
16245 "}"
16246 "ext_array[7];");
16247 CHECK_EQ(0, result->Int32Value());
yangguo@chromium.org56454712012-02-16 15:33:53 +000016248 if (array_type == v8::kExternalDoubleArray ||
16249 array_type == v8::kExternalFloatArray) {
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000016250 CHECK_EQ(static_cast<int>(i::OS::nan_value()),
16251 static_cast<int>(
16252 jsobj->GetElement(isolate, 7)->ToObjectChecked()->Number()));
yangguo@chromium.org56454712012-02-16 15:33:53 +000016253 } else {
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000016254 CheckElementValue(isolate, 0, jsobj, 7);
yangguo@chromium.org56454712012-02-16 15:33:53 +000016255 }
ager@chromium.org3811b432009-10-28 14:53:37 +000016256
16257 result = CompileRun("for (var i = 0; i < 8; i++) {"
16258 " ext_array[6] = '2.3';"
16259 "}"
16260 "ext_array[6];");
16261 CHECK_EQ(2, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000016262 CHECK_EQ(2,
16263 static_cast<int>(
16264 jsobj->GetElement(isolate, 6)->ToObjectChecked()->Number()));
ager@chromium.org3811b432009-10-28 14:53:37 +000016265
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +000016266 if (array_type != v8::kExternalFloatArray &&
16267 array_type != v8::kExternalDoubleArray) {
ager@chromium.org3811b432009-10-28 14:53:37 +000016268 // Though the specification doesn't state it, be explicit about
16269 // converting NaNs and +/-Infinity to zero.
16270 result = CompileRun("for (var i = 0; i < 8; i++) {"
16271 " ext_array[i] = 5;"
16272 "}"
16273 "for (var i = 0; i < 8; i++) {"
16274 " ext_array[i] = NaN;"
16275 "}"
16276 "ext_array[5];");
16277 CHECK_EQ(0, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000016278 CheckElementValue(isolate, 0, jsobj, 5);
ager@chromium.org3811b432009-10-28 14:53:37 +000016279
16280 result = CompileRun("for (var i = 0; i < 8; i++) {"
16281 " ext_array[i] = 5;"
16282 "}"
16283 "for (var i = 0; i < 8; i++) {"
16284 " ext_array[i] = Infinity;"
16285 "}"
16286 "ext_array[5];");
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000016287 int expected_value =
16288 (array_type == v8::kExternalPixelArray) ? 255 : 0;
16289 CHECK_EQ(expected_value, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000016290 CheckElementValue(isolate, expected_value, jsobj, 5);
ager@chromium.org3811b432009-10-28 14:53:37 +000016291
16292 result = CompileRun("for (var i = 0; i < 8; i++) {"
16293 " ext_array[i] = 5;"
16294 "}"
16295 "for (var i = 0; i < 8; i++) {"
16296 " ext_array[i] = -Infinity;"
16297 "}"
16298 "ext_array[5];");
16299 CHECK_EQ(0, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000016300 CheckElementValue(isolate, 0, jsobj, 5);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +000016301
16302 // Check truncation behavior of integral arrays.
16303 const char* unsigned_data =
16304 "var source_data = [0.6, 10.6];"
16305 "var expected_results = [0, 10];";
16306 const char* signed_data =
16307 "var source_data = [0.6, 10.6, -0.6, -10.6];"
16308 "var expected_results = [0, 10, 0, -10];";
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000016309 const char* pixel_data =
16310 "var source_data = [0.6, 10.6];"
16311 "var expected_results = [1, 11];";
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +000016312 bool is_unsigned =
16313 (array_type == v8::kExternalUnsignedByteArray ||
16314 array_type == v8::kExternalUnsignedShortArray ||
16315 array_type == v8::kExternalUnsignedIntArray);
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000016316 bool is_pixel_data = array_type == v8::kExternalPixelArray;
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +000016317
16318 i::OS::SNPrintF(test_buf,
16319 "%s"
16320 "var all_passed = true;"
16321 "for (var i = 0; i < source_data.length; i++) {"
16322 " for (var j = 0; j < 8; j++) {"
16323 " ext_array[j] = source_data[i];"
16324 " }"
16325 " all_passed = all_passed &&"
16326 " (ext_array[5] == expected_results[i]);"
16327 "}"
16328 "all_passed;",
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000016329 (is_unsigned ?
16330 unsigned_data :
16331 (is_pixel_data ? pixel_data : signed_data)));
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +000016332 result = CompileRun(test_buf.start());
16333 CHECK_EQ(true, result->BooleanValue());
ager@chromium.org3811b432009-10-28 14:53:37 +000016334 }
16335
danno@chromium.orgf005df62013-04-30 16:36:45 +000016336 i::Handle<ExternalArrayClass> array(
16337 ExternalArrayClass::cast(jsobj->elements()));
16338 for (int i = 0; i < element_count; i++) {
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000016339 array->set(i, static_cast<ElementType>(i));
16340 }
danno@chromium.orgf005df62013-04-30 16:36:45 +000016341
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000016342 // Test complex assignments
16343 result = CompileRun("function ee_op_test_complex_func(sum) {"
16344 " for (var i = 0; i < 40; ++i) {"
16345 " sum += (ext_array[i] += 1);"
16346 " sum += (ext_array[i] -= 1);"
16347 " } "
16348 " return sum;"
16349 "}"
16350 "sum=0;"
16351 "for (var i=0;i<10000;++i) {"
16352 " sum=ee_op_test_complex_func(sum);"
16353 "}"
16354 "sum;");
16355 CHECK_EQ(16000000, result->Int32Value());
16356
16357 // Test count operations
16358 result = CompileRun("function ee_op_test_count_func(sum) {"
16359 " for (var i = 0; i < 40; ++i) {"
16360 " sum += (++ext_array[i]);"
16361 " sum += (--ext_array[i]);"
16362 " } "
16363 " return sum;"
16364 "}"
16365 "sum=0;"
16366 "for (var i=0;i<10000;++i) {"
16367 " sum=ee_op_test_count_func(sum);"
16368 "}"
16369 "sum;");
16370 CHECK_EQ(16000000, result->Int32Value());
16371
ager@chromium.org3811b432009-10-28 14:53:37 +000016372 result = CompileRun("ext_array[3] = 33;"
16373 "delete ext_array[3];"
16374 "ext_array[3];");
16375 CHECK_EQ(33, result->Int32Value());
16376
16377 result = CompileRun("ext_array[0] = 10; ext_array[1] = 11;"
16378 "ext_array[2] = 12; ext_array[3] = 13;"
16379 "ext_array.__defineGetter__('2',"
16380 "function() { return 120; });"
16381 "ext_array[2];");
16382 CHECK_EQ(12, result->Int32Value());
16383
16384 result = CompileRun("var js_array = new Array(40);"
16385 "js_array[0] = 77;"
16386 "js_array;");
16387 CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
16388
16389 result = CompileRun("ext_array[1] = 23;"
16390 "ext_array.__proto__ = [];"
16391 "js_array.__proto__ = ext_array;"
16392 "js_array.concat(ext_array);");
16393 CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
16394 CHECK_EQ(23, v8::Object::Cast(*result)->Get(v8_str("1"))->Int32Value());
16395
16396 result = CompileRun("ext_array[1] = 23;");
16397 CHECK_EQ(23, result->Int32Value());
danno@chromium.orgf005df62013-04-30 16:36:45 +000016398}
16399
16400
16401template <class ExternalArrayClass, class ElementType>
16402static void ExternalArrayTestHelper(v8::ExternalArrayType array_type,
16403 int64_t low,
16404 int64_t high) {
16405 LocalContext context;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000016406 i::Isolate* isolate = CcTest::i_isolate();
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000016407 i::Factory* factory = isolate->factory();
danno@chromium.orgf005df62013-04-30 16:36:45 +000016408 v8::HandleScope scope(context->GetIsolate());
16409 const int kElementCount = 40;
16410 int element_size = ExternalArrayElementSize(array_type);
16411 ElementType* array_data =
16412 static_cast<ElementType*>(malloc(kElementCount * element_size));
16413 i::Handle<ExternalArrayClass> array =
16414 i::Handle<ExternalArrayClass>::cast(
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000016415 factory->NewExternalArray(kElementCount, array_type, array_data));
danno@chromium.orgf005df62013-04-30 16:36:45 +000016416 // Force GC to trigger verification.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000016417 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
danno@chromium.orgf005df62013-04-30 16:36:45 +000016418 for (int i = 0; i < kElementCount; i++) {
16419 array->set(i, static_cast<ElementType>(i));
16420 }
16421 // Force GC to trigger verification.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000016422 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
danno@chromium.orgf005df62013-04-30 16:36:45 +000016423 for (int i = 0; i < kElementCount; i++) {
16424 CHECK_EQ(static_cast<int64_t>(i),
16425 static_cast<int64_t>(array->get_scalar(i)));
16426 CHECK_EQ(static_cast<int64_t>(i), static_cast<int64_t>(array_data[i]));
16427 }
16428
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016429 v8::Handle<v8::Object> obj = v8::Object::New(context->GetIsolate());
danno@chromium.orgf005df62013-04-30 16:36:45 +000016430 i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
16431 // Set the elements to be the external array.
16432 obj->SetIndexedPropertiesToExternalArrayData(array_data,
16433 array_type,
16434 kElementCount);
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000016435 CHECK_EQ(1,
16436 static_cast<int>(
16437 jsobj->GetElement(isolate, 1)->ToObjectChecked()->Number()));
danno@chromium.orgf005df62013-04-30 16:36:45 +000016438
16439 ObjectWithExternalArrayTestHelper<ExternalArrayClass, ElementType>(
16440 context.local(), obj, kElementCount, array_type, low, high);
16441
16442 v8::Handle<v8::Value> result;
ager@chromium.org3811b432009-10-28 14:53:37 +000016443
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +000016444 // Test more complex manipulations which cause eax to contain values
16445 // that won't be completely overwritten by loads from the arrays.
16446 // This catches bugs in the instructions used for the KeyedLoadIC
16447 // for byte and word types.
16448 {
16449 const int kXSize = 300;
16450 const int kYSize = 300;
16451 const int kLargeElementCount = kXSize * kYSize * 4;
16452 ElementType* large_array_data =
16453 static_cast<ElementType*>(malloc(kLargeElementCount * element_size));
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016454 v8::Handle<v8::Object> large_obj = v8::Object::New(context->GetIsolate());
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +000016455 // Set the elements to be the external array.
16456 large_obj->SetIndexedPropertiesToExternalArrayData(large_array_data,
16457 array_type,
16458 kLargeElementCount);
16459 context->Global()->Set(v8_str("large_array"), large_obj);
16460 // Initialize contents of a few rows.
16461 for (int x = 0; x < 300; x++) {
16462 int row = 0;
16463 int offset = row * 300 * 4;
16464 large_array_data[offset + 4 * x + 0] = (ElementType) 127;
16465 large_array_data[offset + 4 * x + 1] = (ElementType) 0;
16466 large_array_data[offset + 4 * x + 2] = (ElementType) 0;
16467 large_array_data[offset + 4 * x + 3] = (ElementType) 127;
16468 row = 150;
16469 offset = row * 300 * 4;
16470 large_array_data[offset + 4 * x + 0] = (ElementType) 127;
16471 large_array_data[offset + 4 * x + 1] = (ElementType) 0;
16472 large_array_data[offset + 4 * x + 2] = (ElementType) 0;
16473 large_array_data[offset + 4 * x + 3] = (ElementType) 127;
16474 row = 298;
16475 offset = row * 300 * 4;
16476 large_array_data[offset + 4 * x + 0] = (ElementType) 127;
16477 large_array_data[offset + 4 * x + 1] = (ElementType) 0;
16478 large_array_data[offset + 4 * x + 2] = (ElementType) 0;
16479 large_array_data[offset + 4 * x + 3] = (ElementType) 127;
16480 }
16481 // The goal of the code below is to make "offset" large enough
16482 // that the computation of the index (which goes into eax) has
16483 // high bits set which will not be overwritten by a byte or short
16484 // load.
16485 result = CompileRun("var failed = false;"
16486 "var offset = 0;"
16487 "for (var i = 0; i < 300; i++) {"
16488 " if (large_array[4 * i] != 127 ||"
16489 " large_array[4 * i + 1] != 0 ||"
16490 " large_array[4 * i + 2] != 0 ||"
16491 " large_array[4 * i + 3] != 127) {"
16492 " failed = true;"
16493 " }"
16494 "}"
16495 "offset = 150 * 300 * 4;"
16496 "for (var i = 0; i < 300; i++) {"
16497 " if (large_array[offset + 4 * i] != 127 ||"
16498 " large_array[offset + 4 * i + 1] != 0 ||"
16499 " large_array[offset + 4 * i + 2] != 0 ||"
16500 " large_array[offset + 4 * i + 3] != 127) {"
16501 " failed = true;"
16502 " }"
16503 "}"
16504 "offset = 298 * 300 * 4;"
16505 "for (var i = 0; i < 300; i++) {"
16506 " if (large_array[offset + 4 * i] != 127 ||"
16507 " large_array[offset + 4 * i + 1] != 0 ||"
16508 " large_array[offset + 4 * i + 2] != 0 ||"
16509 " large_array[offset + 4 * i + 3] != 127) {"
16510 " failed = true;"
16511 " }"
16512 "}"
16513 "!failed;");
16514 CHECK_EQ(true, result->BooleanValue());
16515 free(large_array_data);
16516 }
16517
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016518 // The "" property descriptor is overloaded to store information about
16519 // the external array. Ensure that setting and accessing the "" property
16520 // works (it should overwrite the information cached about the external
16521 // array in the DescriptorArray) in various situations.
16522 result = CompileRun("ext_array[''] = 23; ext_array['']");
16523 CHECK_EQ(23, result->Int32Value());
16524
16525 // Property "" set after the external array is associated with the object.
16526 {
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016527 v8::Handle<v8::Object> obj2 = v8::Object::New(context->GetIsolate());
16528 obj2->Set(v8_str("ee_test_field"),
16529 v8::Int32::New(context->GetIsolate(), 256));
16530 obj2->Set(v8_str(""), v8::Int32::New(context->GetIsolate(), 1503));
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016531 // Set the elements to be the external array.
16532 obj2->SetIndexedPropertiesToExternalArrayData(array_data,
16533 array_type,
16534 kElementCount);
16535 context->Global()->Set(v8_str("ext_array"), obj2);
16536 result = CompileRun("ext_array['']");
16537 CHECK_EQ(1503, result->Int32Value());
16538 }
16539
16540 // Property "" set after the external array is associated with the object.
16541 {
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016542 v8::Handle<v8::Object> obj2 = v8::Object::New(context->GetIsolate());
16543 obj2->Set(v8_str("ee_test_field_2"),
16544 v8::Int32::New(context->GetIsolate(), 256));
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016545 // Set the elements to be the external array.
16546 obj2->SetIndexedPropertiesToExternalArrayData(array_data,
16547 array_type,
16548 kElementCount);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016549 obj2->Set(v8_str(""), v8::Int32::New(context->GetIsolate(), 1503));
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016550 context->Global()->Set(v8_str("ext_array"), obj2);
16551 result = CompileRun("ext_array['']");
16552 CHECK_EQ(1503, result->Int32Value());
16553 }
16554
16555 // Should reuse the map from previous test.
16556 {
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016557 v8::Handle<v8::Object> obj2 = v8::Object::New(context->GetIsolate());
16558 obj2->Set(v8_str("ee_test_field_2"),
16559 v8::Int32::New(context->GetIsolate(), 256));
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016560 // Set the elements to be the external array. Should re-use the map
16561 // from previous test.
16562 obj2->SetIndexedPropertiesToExternalArrayData(array_data,
16563 array_type,
16564 kElementCount);
16565 context->Global()->Set(v8_str("ext_array"), obj2);
16566 result = CompileRun("ext_array['']");
16567 }
16568
16569 // Property "" is a constant function that shouldn't not be interfered with
16570 // when an external array is set.
16571 {
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016572 v8::Handle<v8::Object> obj2 = v8::Object::New(context->GetIsolate());
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016573 // Start
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016574 obj2->Set(v8_str("ee_test_field3"),
16575 v8::Int32::New(context->GetIsolate(), 256));
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016576
16577 // Add a constant function to an object.
16578 context->Global()->Set(v8_str("ext_array"), obj2);
16579 result = CompileRun("ext_array[''] = function() {return 1503;};"
16580 "ext_array['']();");
16581
16582 // Add an external array transition to the same map that
16583 // has the constant transition.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016584 v8::Handle<v8::Object> obj3 = v8::Object::New(context->GetIsolate());
16585 obj3->Set(v8_str("ee_test_field3"),
16586 v8::Int32::New(context->GetIsolate(), 256));
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016587 obj3->SetIndexedPropertiesToExternalArrayData(array_data,
16588 array_type,
16589 kElementCount);
16590 context->Global()->Set(v8_str("ext_array"), obj3);
16591 }
16592
16593 // If a external array transition is in the map, it should get clobbered
16594 // by a constant function.
16595 {
16596 // Add an external array transition.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016597 v8::Handle<v8::Object> obj3 = v8::Object::New(context->GetIsolate());
16598 obj3->Set(v8_str("ee_test_field4"),
16599 v8::Int32::New(context->GetIsolate(), 256));
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016600 obj3->SetIndexedPropertiesToExternalArrayData(array_data,
16601 array_type,
16602 kElementCount);
16603
16604 // Add a constant function to the same map that just got an external array
16605 // transition.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016606 v8::Handle<v8::Object> obj2 = v8::Object::New(context->GetIsolate());
16607 obj2->Set(v8_str("ee_test_field4"),
16608 v8::Int32::New(context->GetIsolate(), 256));
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016609 context->Global()->Set(v8_str("ext_array"), obj2);
16610 result = CompileRun("ext_array[''] = function() {return 1503;};"
16611 "ext_array['']();");
16612 }
16613
ager@chromium.org3811b432009-10-28 14:53:37 +000016614 free(array_data);
16615}
16616
16617
16618THREADED_TEST(ExternalByteArray) {
lrn@chromium.org32d961d2010-06-30 09:09:34 +000016619 ExternalArrayTestHelper<i::ExternalByteArray, int8_t>(
ager@chromium.org3811b432009-10-28 14:53:37 +000016620 v8::kExternalByteArray,
16621 -128,
16622 127);
16623}
16624
16625
16626THREADED_TEST(ExternalUnsignedByteArray) {
lrn@chromium.org32d961d2010-06-30 09:09:34 +000016627 ExternalArrayTestHelper<i::ExternalUnsignedByteArray, uint8_t>(
ager@chromium.org3811b432009-10-28 14:53:37 +000016628 v8::kExternalUnsignedByteArray,
16629 0,
16630 255);
16631}
16632
16633
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000016634THREADED_TEST(ExternalPixelArray) {
16635 ExternalArrayTestHelper<i::ExternalPixelArray, uint8_t>(
16636 v8::kExternalPixelArray,
16637 0,
16638 255);
16639}
16640
16641
ager@chromium.org3811b432009-10-28 14:53:37 +000016642THREADED_TEST(ExternalShortArray) {
lrn@chromium.org32d961d2010-06-30 09:09:34 +000016643 ExternalArrayTestHelper<i::ExternalShortArray, int16_t>(
ager@chromium.org3811b432009-10-28 14:53:37 +000016644 v8::kExternalShortArray,
16645 -32768,
16646 32767);
16647}
16648
16649
16650THREADED_TEST(ExternalUnsignedShortArray) {
lrn@chromium.org32d961d2010-06-30 09:09:34 +000016651 ExternalArrayTestHelper<i::ExternalUnsignedShortArray, uint16_t>(
ager@chromium.org3811b432009-10-28 14:53:37 +000016652 v8::kExternalUnsignedShortArray,
16653 0,
16654 65535);
16655}
16656
16657
16658THREADED_TEST(ExternalIntArray) {
lrn@chromium.org32d961d2010-06-30 09:09:34 +000016659 ExternalArrayTestHelper<i::ExternalIntArray, int32_t>(
ager@chromium.org3811b432009-10-28 14:53:37 +000016660 v8::kExternalIntArray,
16661 INT_MIN, // -2147483648
16662 INT_MAX); // 2147483647
16663}
16664
16665
16666THREADED_TEST(ExternalUnsignedIntArray) {
lrn@chromium.org32d961d2010-06-30 09:09:34 +000016667 ExternalArrayTestHelper<i::ExternalUnsignedIntArray, uint32_t>(
ager@chromium.org3811b432009-10-28 14:53:37 +000016668 v8::kExternalUnsignedIntArray,
16669 0,
16670 UINT_MAX); // 4294967295
16671}
16672
16673
16674THREADED_TEST(ExternalFloatArray) {
lrn@chromium.org32d961d2010-06-30 09:09:34 +000016675 ExternalArrayTestHelper<i::ExternalFloatArray, float>(
ager@chromium.org3811b432009-10-28 14:53:37 +000016676 v8::kExternalFloatArray,
16677 -500,
16678 500);
16679}
16680
16681
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +000016682THREADED_TEST(ExternalDoubleArray) {
16683 ExternalArrayTestHelper<i::ExternalDoubleArray, double>(
16684 v8::kExternalDoubleArray,
16685 -500,
16686 500);
16687}
16688
16689
ager@chromium.org3811b432009-10-28 14:53:37 +000016690THREADED_TEST(ExternalArrays) {
16691 TestExternalByteArray();
16692 TestExternalUnsignedByteArray();
16693 TestExternalShortArray();
16694 TestExternalUnsignedShortArray();
16695 TestExternalIntArray();
16696 TestExternalUnsignedIntArray();
16697 TestExternalFloatArray();
16698}
16699
16700
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016701void ExternalArrayInfoTestHelper(v8::ExternalArrayType array_type) {
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016702 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016703 v8::HandleScope scope(context->GetIsolate());
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016704 for (int size = 0; size < 100; size += 10) {
16705 int element_size = ExternalArrayElementSize(array_type);
16706 void* external_data = malloc(size * element_size);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016707 v8::Handle<v8::Object> obj = v8::Object::New(context->GetIsolate());
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016708 obj->SetIndexedPropertiesToExternalArrayData(
16709 external_data, array_type, size);
16710 CHECK(obj->HasIndexedPropertiesInExternalArrayData());
16711 CHECK_EQ(external_data, obj->GetIndexedPropertiesExternalArrayData());
16712 CHECK_EQ(array_type, obj->GetIndexedPropertiesExternalArrayDataType());
16713 CHECK_EQ(size, obj->GetIndexedPropertiesExternalArrayDataLength());
16714 free(external_data);
16715 }
16716}
16717
16718
16719THREADED_TEST(ExternalArrayInfo) {
16720 ExternalArrayInfoTestHelper(v8::kExternalByteArray);
16721 ExternalArrayInfoTestHelper(v8::kExternalUnsignedByteArray);
16722 ExternalArrayInfoTestHelper(v8::kExternalShortArray);
16723 ExternalArrayInfoTestHelper(v8::kExternalUnsignedShortArray);
16724 ExternalArrayInfoTestHelper(v8::kExternalIntArray);
16725 ExternalArrayInfoTestHelper(v8::kExternalUnsignedIntArray);
16726 ExternalArrayInfoTestHelper(v8::kExternalFloatArray);
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +000016727 ExternalArrayInfoTestHelper(v8::kExternalDoubleArray);
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000016728 ExternalArrayInfoTestHelper(v8::kExternalPixelArray);
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016729}
16730
16731
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016732void ExtArrayLimitsHelper(v8::Isolate* isolate,
16733 v8::ExternalArrayType array_type,
16734 int size) {
16735 v8::Handle<v8::Object> obj = v8::Object::New(isolate);
danno@chromium.org412fa512012-09-14 13:28:26 +000016736 v8::V8::SetFatalErrorHandler(StoringErrorCallback);
16737 last_location = last_message = NULL;
16738 obj->SetIndexedPropertiesToExternalArrayData(NULL, array_type, size);
16739 CHECK(!obj->HasIndexedPropertiesInExternalArrayData());
16740 CHECK_NE(NULL, last_location);
16741 CHECK_NE(NULL, last_message);
16742}
16743
16744
16745TEST(ExternalArrayLimits) {
danno@chromium.org412fa512012-09-14 13:28:26 +000016746 LocalContext context;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016747 v8::Isolate* isolate = context->GetIsolate();
16748 v8::HandleScope scope(isolate);
16749 ExtArrayLimitsHelper(isolate, v8::kExternalByteArray, 0x40000000);
16750 ExtArrayLimitsHelper(isolate, v8::kExternalByteArray, 0xffffffff);
16751 ExtArrayLimitsHelper(isolate, v8::kExternalUnsignedByteArray, 0x40000000);
16752 ExtArrayLimitsHelper(isolate, v8::kExternalUnsignedByteArray, 0xffffffff);
16753 ExtArrayLimitsHelper(isolate, v8::kExternalShortArray, 0x40000000);
16754 ExtArrayLimitsHelper(isolate, v8::kExternalShortArray, 0xffffffff);
16755 ExtArrayLimitsHelper(isolate, v8::kExternalUnsignedShortArray, 0x40000000);
16756 ExtArrayLimitsHelper(isolate, v8::kExternalUnsignedShortArray, 0xffffffff);
16757 ExtArrayLimitsHelper(isolate, v8::kExternalIntArray, 0x40000000);
16758 ExtArrayLimitsHelper(isolate, v8::kExternalIntArray, 0xffffffff);
16759 ExtArrayLimitsHelper(isolate, v8::kExternalUnsignedIntArray, 0x40000000);
16760 ExtArrayLimitsHelper(isolate, v8::kExternalUnsignedIntArray, 0xffffffff);
16761 ExtArrayLimitsHelper(isolate, v8::kExternalFloatArray, 0x40000000);
16762 ExtArrayLimitsHelper(isolate, v8::kExternalFloatArray, 0xffffffff);
16763 ExtArrayLimitsHelper(isolate, v8::kExternalDoubleArray, 0x40000000);
16764 ExtArrayLimitsHelper(isolate, v8::kExternalDoubleArray, 0xffffffff);
16765 ExtArrayLimitsHelper(isolate, v8::kExternalPixelArray, 0x40000000);
16766 ExtArrayLimitsHelper(isolate, v8::kExternalPixelArray, 0xffffffff);
danno@chromium.org412fa512012-09-14 13:28:26 +000016767}
16768
16769
danno@chromium.orgf005df62013-04-30 16:36:45 +000016770template <typename ElementType, typename TypedArray,
16771 class ExternalArrayClass>
16772void TypedArrayTestHelper(v8::ExternalArrayType array_type,
16773 int64_t low, int64_t high) {
16774 const int kElementCount = 50;
danno@chromium.orgf005df62013-04-30 16:36:45 +000016775
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +000016776 i::ScopedVector<ElementType> backing_store(kElementCount+2);
16777
danno@chromium.orgf005df62013-04-30 16:36:45 +000016778 LocalContext env;
16779 v8::Isolate* isolate = env->GetIsolate();
16780 v8::HandleScope handle_scope(isolate);
16781
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000016782 Local<v8::ArrayBuffer> ab =
16783 v8::ArrayBuffer::New(isolate, backing_store.start(),
16784 (kElementCount + 2) * sizeof(ElementType));
danno@chromium.orgf005df62013-04-30 16:36:45 +000016785 Local<TypedArray> ta =
16786 TypedArray::New(ab, 2*sizeof(ElementType), kElementCount);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000016787 CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
danno@chromium.orgf005df62013-04-30 16:36:45 +000016788 CHECK_EQ(kElementCount, static_cast<int>(ta->Length()));
16789 CHECK_EQ(2*sizeof(ElementType), static_cast<int>(ta->ByteOffset()));
16790 CHECK_EQ(kElementCount*sizeof(ElementType),
16791 static_cast<int>(ta->ByteLength()));
16792 CHECK_EQ(ab, ta->Buffer());
16793
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +000016794 ElementType* data = backing_store.start() + 2;
danno@chromium.orgf005df62013-04-30 16:36:45 +000016795 for (int i = 0; i < kElementCount; i++) {
16796 data[i] = static_cast<ElementType>(i);
16797 }
16798
16799 ObjectWithExternalArrayTestHelper<ExternalArrayClass, ElementType>(
16800 env.local(), ta, kElementCount, array_type, low, high);
16801}
16802
16803
16804THREADED_TEST(Uint8Array) {
16805 TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::ExternalUnsignedByteArray>(
16806 v8::kExternalUnsignedByteArray, 0, 0xFF);
16807}
16808
16809
16810THREADED_TEST(Int8Array) {
16811 TypedArrayTestHelper<int8_t, v8::Int8Array, i::ExternalByteArray>(
16812 v8::kExternalByteArray, -0x80, 0x7F);
16813}
16814
16815
16816THREADED_TEST(Uint16Array) {
16817 TypedArrayTestHelper<uint16_t,
16818 v8::Uint16Array,
16819 i::ExternalUnsignedShortArray>(
16820 v8::kExternalUnsignedShortArray, 0, 0xFFFF);
16821}
16822
16823
16824THREADED_TEST(Int16Array) {
16825 TypedArrayTestHelper<int16_t, v8::Int16Array, i::ExternalShortArray>(
16826 v8::kExternalShortArray, -0x8000, 0x7FFF);
16827}
16828
16829
16830THREADED_TEST(Uint32Array) {
16831 TypedArrayTestHelper<uint32_t, v8::Uint32Array, i::ExternalUnsignedIntArray>(
16832 v8::kExternalUnsignedIntArray, 0, UINT_MAX);
16833}
16834
16835
16836THREADED_TEST(Int32Array) {
16837 TypedArrayTestHelper<int32_t, v8::Int32Array, i::ExternalIntArray>(
16838 v8::kExternalIntArray, INT_MIN, INT_MAX);
16839}
16840
16841
16842THREADED_TEST(Float32Array) {
16843 TypedArrayTestHelper<float, v8::Float32Array, i::ExternalFloatArray>(
16844 v8::kExternalFloatArray, -500, 500);
16845}
16846
16847
16848THREADED_TEST(Float64Array) {
16849 TypedArrayTestHelper<double, v8::Float64Array, i::ExternalDoubleArray>(
16850 v8::kExternalDoubleArray, -500, 500);
16851}
16852
16853
ulan@chromium.org57ff8812013-05-10 08:16:55 +000016854THREADED_TEST(Uint8ClampedArray) {
16855 TypedArrayTestHelper<uint8_t, v8::Uint8ClampedArray, i::ExternalPixelArray>(
16856 v8::kExternalPixelArray, 0, 0xFF);
16857}
16858
16859
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000016860THREADED_TEST(DataView) {
16861 const int kSize = 50;
16862
16863 i::ScopedVector<uint8_t> backing_store(kSize+2);
16864
16865 LocalContext env;
16866 v8::Isolate* isolate = env->GetIsolate();
16867 v8::HandleScope handle_scope(isolate);
16868
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000016869 Local<v8::ArrayBuffer> ab =
16870 v8::ArrayBuffer::New(isolate, backing_store.start(), 2 + kSize);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000016871 Local<v8::DataView> dv =
16872 v8::DataView::New(ab, 2, kSize);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000016873 CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000016874 CHECK_EQ(2, static_cast<int>(dv->ByteOffset()));
16875 CHECK_EQ(kSize, static_cast<int>(dv->ByteLength()));
16876 CHECK_EQ(ab, dv->Buffer());
16877}
16878
16879
16880#define IS_ARRAY_BUFFER_VIEW_TEST(View) \
16881 THREADED_TEST(Is##View) { \
ulan@chromium.org57ff8812013-05-10 08:16:55 +000016882 LocalContext env; \
16883 v8::Isolate* isolate = env->GetIsolate(); \
16884 v8::HandleScope handle_scope(isolate); \
16885 \
16886 Handle<Value> result = CompileRun( \
16887 "var ab = new ArrayBuffer(128);" \
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000016888 "new " #View "(ab)"); \
16889 CHECK(result->IsArrayBufferView()); \
16890 CHECK(result->Is##View()); \
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000016891 CheckInternalFieldsAreZero<v8::ArrayBufferView>(result.As<v8::View>()); \
ulan@chromium.org57ff8812013-05-10 08:16:55 +000016892 }
16893
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000016894IS_ARRAY_BUFFER_VIEW_TEST(Uint8Array)
16895IS_ARRAY_BUFFER_VIEW_TEST(Int8Array)
16896IS_ARRAY_BUFFER_VIEW_TEST(Uint16Array)
16897IS_ARRAY_BUFFER_VIEW_TEST(Int16Array)
16898IS_ARRAY_BUFFER_VIEW_TEST(Uint32Array)
16899IS_ARRAY_BUFFER_VIEW_TEST(Int32Array)
16900IS_ARRAY_BUFFER_VIEW_TEST(Float32Array)
16901IS_ARRAY_BUFFER_VIEW_TEST(Float64Array)
16902IS_ARRAY_BUFFER_VIEW_TEST(Uint8ClampedArray)
16903IS_ARRAY_BUFFER_VIEW_TEST(DataView)
ulan@chromium.org57ff8812013-05-10 08:16:55 +000016904
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000016905#undef IS_ARRAY_BUFFER_VIEW_TEST
ulan@chromium.org57ff8812013-05-10 08:16:55 +000016906
16907
16908
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000016909THREADED_TEST(ScriptContextDependence) {
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000016910 LocalContext c1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016911 v8::HandleScope scope(c1->GetIsolate());
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000016912 const char *source = "foo";
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000016913 v8::Handle<v8::Script> dep =
16914 v8::Script::Compile(v8::String::NewFromUtf8(c1->GetIsolate(), source));
16915 v8::Handle<v8::Script> indep =
16916 v8::Script::New(v8::String::NewFromUtf8(c1->GetIsolate(), source));
16917 c1->Global()->Set(v8::String::NewFromUtf8(c1->GetIsolate(), "foo"),
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016918 v8::Integer::New(c1->GetIsolate(), 100));
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000016919 CHECK_EQ(dep->Run()->Int32Value(), 100);
16920 CHECK_EQ(indep->Run()->Int32Value(), 100);
16921 LocalContext c2;
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000016922 c2->Global()->Set(v8::String::NewFromUtf8(c2->GetIsolate(), "foo"),
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016923 v8::Integer::New(c2->GetIsolate(), 101));
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000016924 CHECK_EQ(dep->Run()->Int32Value(), 100);
16925 CHECK_EQ(indep->Run()->Int32Value(), 101);
16926}
16927
ager@chromium.org96c75b52009-08-26 09:13:16 +000016928
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000016929THREADED_TEST(StackTrace) {
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000016930 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016931 v8::HandleScope scope(context->GetIsolate());
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000016932 v8::TryCatch try_catch;
16933 const char *source = "function foo() { FAIL.FAIL; }; foo();";
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000016934 v8::Handle<v8::String> src =
16935 v8::String::NewFromUtf8(context->GetIsolate(), source);
16936 v8::Handle<v8::String> origin =
16937 v8::String::NewFromUtf8(context->GetIsolate(), "stack-trace-test");
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000016938 v8::Script::New(src, origin)->Run();
16939 CHECK(try_catch.HasCaught());
16940 v8::String::Utf8Value stack(try_catch.StackTrace());
16941 CHECK(strstr(*stack, "at foo (stack-trace-test") != NULL);
16942}
ager@chromium.org96c75b52009-08-26 09:13:16 +000016943
16944
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000016945// Checks that a StackFrame has certain expected values.
16946void checkStackFrame(const char* expected_script_name,
16947 const char* expected_func_name, int expected_line_number,
16948 int expected_column, bool is_eval, bool is_constructor,
16949 v8::Handle<v8::StackFrame> frame) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000016950 v8::HandleScope scope(CcTest::isolate());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000016951 v8::String::Utf8Value func_name(frame->GetFunctionName());
16952 v8::String::Utf8Value script_name(frame->GetScriptName());
16953 if (*script_name == NULL) {
16954 // The situation where there is no associated script, like for evals.
16955 CHECK(expected_script_name == NULL);
16956 } else {
16957 CHECK(strstr(*script_name, expected_script_name) != NULL);
16958 }
16959 CHECK(strstr(*func_name, expected_func_name) != NULL);
16960 CHECK_EQ(expected_line_number, frame->GetLineNumber());
16961 CHECK_EQ(expected_column, frame->GetColumn());
16962 CHECK_EQ(is_eval, frame->IsEval());
16963 CHECK_EQ(is_constructor, frame->IsConstructor());
16964}
16965
16966
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000016967void AnalyzeStackInNativeCode(const v8::FunctionCallbackInfo<v8::Value>& args) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016968 v8::HandleScope scope(args.GetIsolate());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000016969 const char* origin = "capture-stack-trace-test";
16970 const int kOverviewTest = 1;
16971 const int kDetailedTest = 2;
16972
16973 ASSERT(args.Length() == 1);
16974
16975 int testGroup = args[0]->Int32Value();
16976 if (testGroup == kOverviewTest) {
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000016977 v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
16978 args.GetIsolate(), 10, v8::StackTrace::kOverview);
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000016979 CHECK_EQ(4, stackTrace->GetFrameCount());
16980 checkStackFrame(origin, "bar", 2, 10, false, false,
16981 stackTrace->GetFrame(0));
16982 checkStackFrame(origin, "foo", 6, 3, false, false,
16983 stackTrace->GetFrame(1));
whesse@chromium.org030d38e2011-07-13 13:23:34 +000016984 // This is the source string inside the eval which has the call to foo.
16985 checkStackFrame(NULL, "", 1, 5, false, false,
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000016986 stackTrace->GetFrame(2));
whesse@chromium.org030d38e2011-07-13 13:23:34 +000016987 // The last frame is an anonymous function which has the initial eval call.
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000016988 checkStackFrame(origin, "", 8, 7, false, false,
16989 stackTrace->GetFrame(3));
16990
16991 CHECK(stackTrace->AsArray()->IsArray());
16992 } else if (testGroup == kDetailedTest) {
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000016993 v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
16994 args.GetIsolate(), 10, v8::StackTrace::kDetailed);
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000016995 CHECK_EQ(4, stackTrace->GetFrameCount());
16996 checkStackFrame(origin, "bat", 4, 22, false, false,
16997 stackTrace->GetFrame(0));
16998 checkStackFrame(origin, "baz", 8, 3, false, true,
16999 stackTrace->GetFrame(1));
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +000017000#ifdef ENABLE_DEBUGGER_SUPPORT
17001 bool is_eval = true;
17002#else // ENABLE_DEBUGGER_SUPPORT
17003 bool is_eval = false;
17004#endif // ENABLE_DEBUGGER_SUPPORT
17005
whesse@chromium.org030d38e2011-07-13 13:23:34 +000017006 // This is the source string inside the eval which has the call to baz.
17007 checkStackFrame(NULL, "", 1, 5, is_eval, false,
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017008 stackTrace->GetFrame(2));
whesse@chromium.org030d38e2011-07-13 13:23:34 +000017009 // The last frame is an anonymous function which has the initial eval call.
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017010 checkStackFrame(origin, "", 10, 1, false, false,
17011 stackTrace->GetFrame(3));
17012
17013 CHECK(stackTrace->AsArray()->IsArray());
17014 }
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017015}
17016
17017
17018// Tests the C++ StackTrace API.
kasperl@chromium.orga5551262010-12-07 12:49:48 +000017019// TODO(3074796): Reenable this as a THREADED_TEST once it passes.
17020// THREADED_TEST(CaptureStackTrace) {
17021TEST(CaptureStackTrace) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017022 v8::Isolate* isolate = CcTest::isolate();
17023 v8::HandleScope scope(isolate);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017024 v8::Handle<v8::String> origin =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017025 v8::String::NewFromUtf8(isolate, "capture-stack-trace-test");
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000017026 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017027 templ->Set(v8_str("AnalyzeStackInNativeCode"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017028 v8::FunctionTemplate::New(isolate, AnalyzeStackInNativeCode));
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017029 LocalContext context(0, templ);
17030
17031 // Test getting OVERVIEW information. Should ignore information that is not
17032 // script name, function name, line number, and column offset.
17033 const char *overview_source =
17034 "function bar() {\n"
17035 " var y; AnalyzeStackInNativeCode(1);\n"
17036 "}\n"
17037 "function foo() {\n"
17038 "\n"
17039 " bar();\n"
17040 "}\n"
17041 "var x;eval('new foo();');";
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017042 v8::Handle<v8::String> overview_src =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017043 v8::String::NewFromUtf8(isolate, overview_source);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000017044 v8::Handle<Value> overview_result(
17045 v8::Script::New(overview_src, origin)->Run());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000017046 CHECK(!overview_result.IsEmpty());
17047 CHECK(overview_result->IsObject());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017048
17049 // Test getting DETAILED information.
17050 const char *detailed_source =
17051 "function bat() {AnalyzeStackInNativeCode(2);\n"
17052 "}\n"
17053 "\n"
17054 "function baz() {\n"
17055 " bat();\n"
17056 "}\n"
17057 "eval('new baz();');";
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017058 v8::Handle<v8::String> detailed_src =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017059 v8::String::NewFromUtf8(isolate, detailed_source);
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017060 // Make the script using a non-zero line and column offset.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000017061 v8::Handle<v8::Integer> line_offset = v8::Integer::New(isolate, 3);
17062 v8::Handle<v8::Integer> column_offset = v8::Integer::New(isolate, 5);
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017063 v8::ScriptOrigin detailed_origin(origin, line_offset, column_offset);
17064 v8::Handle<v8::Script> detailed_script(
17065 v8::Script::New(detailed_src, &detailed_origin));
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000017066 v8::Handle<Value> detailed_result(detailed_script->Run());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000017067 CHECK(!detailed_result.IsEmpty());
17068 CHECK(detailed_result->IsObject());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017069}
17070
17071
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000017072static void StackTraceForUncaughtExceptionListener(
17073 v8::Handle<v8::Message> message,
17074 v8::Handle<Value>) {
17075 v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
17076 CHECK_EQ(2, stack_trace->GetFrameCount());
17077 checkStackFrame("origin", "foo", 2, 3, false, false,
17078 stack_trace->GetFrame(0));
17079 checkStackFrame("origin", "bar", 5, 3, false, false,
17080 stack_trace->GetFrame(1));
17081}
17082
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000017083
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000017084TEST(CaptureStackTraceForUncaughtException) {
17085 report_count = 0;
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000017086 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017087 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000017088 v8::V8::AddMessageListener(StackTraceForUncaughtExceptionListener);
17089 v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
17090
17091 Script::Compile(v8_str("function foo() {\n"
17092 " throw 1;\n"
17093 "};\n"
17094 "function bar() {\n"
17095 " foo();\n"
17096 "};"),
17097 v8_str("origin"))->Run();
17098 v8::Local<v8::Object> global = env->Global();
17099 Local<Value> trouble = global->Get(v8_str("bar"));
17100 CHECK(trouble->IsFunction());
17101 Function::Cast(*trouble)->Call(global, 0, NULL);
17102 v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
17103 v8::V8::RemoveMessageListeners(StackTraceForUncaughtExceptionListener);
17104}
17105
17106
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000017107TEST(CaptureStackTraceForUncaughtExceptionAndSetters) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000017108 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017109 v8::HandleScope scope(env->GetIsolate());
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000017110 v8::V8::SetCaptureStackTraceForUncaughtExceptions(true,
17111 1024,
17112 v8::StackTrace::kDetailed);
17113
17114 CompileRun(
17115 "var setters = ['column', 'lineNumber', 'scriptName',\n"
17116 " 'scriptNameOrSourceURL', 'functionName', 'isEval',\n"
17117 " 'isConstructor'];\n"
17118 "for (var i = 0; i < setters.length; i++) {\n"
17119 " var prop = setters[i];\n"
17120 " Object.prototype.__defineSetter__(prop, function() { throw prop; });\n"
17121 "}\n");
17122 CompileRun("throw 'exception';");
17123 v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
17124}
17125
17126
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000017127static void RethrowStackTraceHandler(v8::Handle<v8::Message> message,
17128 v8::Handle<v8::Value> data) {
17129 // Use the frame where JavaScript is called from.
17130 v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
17131 CHECK(!stack_trace.IsEmpty());
17132 int frame_count = stack_trace->GetFrameCount();
17133 CHECK_EQ(3, frame_count);
17134 int line_number[] = {1, 2, 5};
17135 for (int i = 0; i < frame_count; i++) {
17136 CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
17137 }
17138}
17139
17140
17141// Test that we only return the stack trace at the site where the exception
17142// is first thrown (not where it is rethrown).
17143TEST(RethrowStackTrace) {
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000017144 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017145 v8::HandleScope scope(env->GetIsolate());
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000017146 // We make sure that
17147 // - the stack trace of the ReferenceError in g() is reported.
17148 // - the stack trace is not overwritten when e1 is rethrown by t().
17149 // - the stack trace of e2 does not overwrite that of e1.
17150 const char* source =
17151 "function g() { error; } \n"
17152 "function f() { g(); } \n"
17153 "function t(e) { throw e; } \n"
17154 "try { \n"
17155 " f(); \n"
17156 "} catch (e1) { \n"
17157 " try { \n"
17158 " error; \n"
17159 " } catch (e2) { \n"
17160 " t(e1); \n"
17161 " } \n"
17162 "} \n";
17163 v8::V8::AddMessageListener(RethrowStackTraceHandler);
17164 v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
17165 CompileRun(source);
17166 v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
17167 v8::V8::RemoveMessageListeners(RethrowStackTraceHandler);
17168}
17169
17170
17171static void RethrowPrimitiveStackTraceHandler(v8::Handle<v8::Message> message,
17172 v8::Handle<v8::Value> data) {
17173 v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
17174 CHECK(!stack_trace.IsEmpty());
17175 int frame_count = stack_trace->GetFrameCount();
17176 CHECK_EQ(2, frame_count);
17177 int line_number[] = {3, 7};
17178 for (int i = 0; i < frame_count; i++) {
17179 CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
17180 }
17181}
17182
17183
17184// Test that we do not recognize identity for primitive exceptions.
17185TEST(RethrowPrimitiveStackTrace) {
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000017186 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017187 v8::HandleScope scope(env->GetIsolate());
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000017188 // We do not capture stack trace for non Error objects on creation time.
17189 // Instead, we capture the stack trace on last throw.
17190 const char* source =
17191 "function g() { throw 404; } \n"
17192 "function f() { g(); } \n"
17193 "function t(e) { throw e; } \n"
17194 "try { \n"
17195 " f(); \n"
17196 "} catch (e1) { \n"
17197 " t(e1) \n"
17198 "} \n";
17199 v8::V8::AddMessageListener(RethrowPrimitiveStackTraceHandler);
17200 v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
17201 CompileRun(source);
17202 v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
17203 v8::V8::RemoveMessageListeners(RethrowPrimitiveStackTraceHandler);
17204}
17205
17206
17207static void RethrowExistingStackTraceHandler(v8::Handle<v8::Message> message,
17208 v8::Handle<v8::Value> data) {
17209 // Use the frame where JavaScript is called from.
17210 v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
17211 CHECK(!stack_trace.IsEmpty());
17212 CHECK_EQ(1, stack_trace->GetFrameCount());
17213 CHECK_EQ(1, stack_trace->GetFrame(0)->GetLineNumber());
17214}
17215
17216
17217// Test that the stack trace is captured when the error object is created and
17218// not where it is thrown.
17219TEST(RethrowExistingStackTrace) {
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000017220 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017221 v8::HandleScope scope(env->GetIsolate());
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000017222 const char* source =
17223 "var e = new Error(); \n"
17224 "throw e; \n";
17225 v8::V8::AddMessageListener(RethrowExistingStackTraceHandler);
17226 v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
17227 CompileRun(source);
17228 v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
17229 v8::V8::RemoveMessageListeners(RethrowExistingStackTraceHandler);
17230}
17231
17232
17233static void RethrowBogusErrorStackTraceHandler(v8::Handle<v8::Message> message,
17234 v8::Handle<v8::Value> data) {
17235 // Use the frame where JavaScript is called from.
17236 v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
17237 CHECK(!stack_trace.IsEmpty());
17238 CHECK_EQ(1, stack_trace->GetFrameCount());
17239 CHECK_EQ(2, stack_trace->GetFrame(0)->GetLineNumber());
17240}
17241
17242
17243// Test that the stack trace is captured where the bogus Error object is thrown.
17244TEST(RethrowBogusErrorStackTrace) {
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000017245 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017246 v8::HandleScope scope(env->GetIsolate());
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000017247 const char* source =
17248 "var e = {__proto__: new Error()} \n"
17249 "throw e; \n";
17250 v8::V8::AddMessageListener(RethrowBogusErrorStackTraceHandler);
17251 v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
17252 CompileRun(source);
17253 v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
17254 v8::V8::RemoveMessageListeners(RethrowBogusErrorStackTraceHandler);
17255}
17256
17257
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017258void AnalyzeStackOfEvalWithSourceURL(
17259 const v8::FunctionCallbackInfo<v8::Value>& args) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017260 v8::HandleScope scope(args.GetIsolate());
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017261 v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
17262 args.GetIsolate(), 10, v8::StackTrace::kDetailed);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000017263 CHECK_EQ(5, stackTrace->GetFrameCount());
17264 v8::Handle<v8::String> url = v8_str("eval_url");
17265 for (int i = 0; i < 3; i++) {
17266 v8::Handle<v8::String> name =
17267 stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
17268 CHECK(!name.IsEmpty());
17269 CHECK_EQ(url, name);
17270 }
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000017271}
17272
17273
17274TEST(SourceURLInStackTrace) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017275 v8::Isolate* isolate = CcTest::isolate();
17276 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000017277 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000017278 templ->Set(v8_str("AnalyzeStackOfEvalWithSourceURL"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017279 v8::FunctionTemplate::New(isolate,
17280 AnalyzeStackOfEvalWithSourceURL));
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000017281 LocalContext context(0, templ);
17282
17283 const char *source =
17284 "function outer() {\n"
17285 "function bar() {\n"
17286 " AnalyzeStackOfEvalWithSourceURL();\n"
17287 "}\n"
17288 "function foo() {\n"
17289 "\n"
17290 " bar();\n"
17291 "}\n"
17292 "foo();\n"
17293 "}\n"
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000017294 "eval('(' + outer +')()%s');";
17295
17296 i::ScopedVector<char> code(1024);
17297 i::OS::SNPrintF(code, source, "//# sourceURL=eval_url");
17298 CHECK(CompileRun(code.start())->IsUndefined());
17299 i::OS::SNPrintF(code, source, "//@ sourceURL=eval_url");
17300 CHECK(CompileRun(code.start())->IsUndefined());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000017301}
17302
17303
jkummerow@chromium.org8fa5bd92013-09-02 11:45:09 +000017304static int scriptIdInStack[2];
17305
17306void AnalyzeScriptIdInStack(
17307 const v8::FunctionCallbackInfo<v8::Value>& args) {
17308 v8::HandleScope scope(args.GetIsolate());
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017309 v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
17310 args.GetIsolate(), 10, v8::StackTrace::kScriptId);
jkummerow@chromium.org8fa5bd92013-09-02 11:45:09 +000017311 CHECK_EQ(2, stackTrace->GetFrameCount());
17312 for (int i = 0; i < 2; i++) {
17313 scriptIdInStack[i] = stackTrace->GetFrame(i)->GetScriptId();
17314 }
17315}
17316
17317
17318TEST(ScriptIdInStackTrace) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017319 v8::Isolate* isolate = CcTest::isolate();
17320 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000017321 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
jkummerow@chromium.org8fa5bd92013-09-02 11:45:09 +000017322 templ->Set(v8_str("AnalyzeScriptIdInStack"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017323 v8::FunctionTemplate::New(isolate, AnalyzeScriptIdInStack));
jkummerow@chromium.org8fa5bd92013-09-02 11:45:09 +000017324 LocalContext context(0, templ);
17325
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017326 v8::Handle<v8::String> scriptSource = v8::String::NewFromUtf8(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017327 isolate,
jkummerow@chromium.org8fa5bd92013-09-02 11:45:09 +000017328 "function foo() {\n"
17329 " AnalyzeScriptIdInStack();"
17330 "}\n"
17331 "foo();\n");
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017332 v8::ScriptOrigin origin =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017333 v8::ScriptOrigin(v8::String::NewFromUtf8(isolate, "test"));
jkummerow@chromium.org8fa5bd92013-09-02 11:45:09 +000017334 v8::Local<v8::Script> script(v8::Script::Compile(scriptSource, &origin));
17335 script->Run();
17336 for (int i = 0; i < 2; i++) {
17337 CHECK(scriptIdInStack[i] != v8::Message::kNoScriptIdInfo);
17338 CHECK_EQ(scriptIdInStack[i], script->GetId());
17339 }
17340}
17341
17342
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017343void AnalyzeStackOfInlineScriptWithSourceURL(
17344 const v8::FunctionCallbackInfo<v8::Value>& args) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017345 v8::HandleScope scope(args.GetIsolate());
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017346 v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
17347 args.GetIsolate(), 10, v8::StackTrace::kDetailed);
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017348 CHECK_EQ(4, stackTrace->GetFrameCount());
17349 v8::Handle<v8::String> url = v8_str("url");
17350 for (int i = 0; i < 3; i++) {
17351 v8::Handle<v8::String> name =
17352 stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
17353 CHECK(!name.IsEmpty());
17354 CHECK_EQ(url, name);
17355 }
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017356}
17357
17358
17359TEST(InlineScriptWithSourceURLInStackTrace) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000017360 v8::Isolate* isolate = CcTest::isolate();
17361 v8::HandleScope scope(isolate);
17362 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017363 templ->Set(v8_str("AnalyzeStackOfInlineScriptWithSourceURL"),
17364 v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017365 CcTest::isolate(), AnalyzeStackOfInlineScriptWithSourceURL));
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017366 LocalContext context(0, templ);
17367
17368 const char *source =
17369 "function outer() {\n"
17370 "function bar() {\n"
17371 " AnalyzeStackOfInlineScriptWithSourceURL();\n"
17372 "}\n"
17373 "function foo() {\n"
17374 "\n"
17375 " bar();\n"
17376 "}\n"
17377 "foo();\n"
17378 "}\n"
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000017379 "outer()\n%s";
17380
17381 i::ScopedVector<char> code(1024);
17382 i::OS::SNPrintF(code, source, "//# sourceURL=source_url");
17383 CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
17384 i::OS::SNPrintF(code, source, "//@ sourceURL=source_url");
17385 CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017386}
17387
17388
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017389void AnalyzeStackOfDynamicScriptWithSourceURL(
17390 const v8::FunctionCallbackInfo<v8::Value>& args) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017391 v8::HandleScope scope(args.GetIsolate());
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017392 v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
17393 args.GetIsolate(), 10, v8::StackTrace::kDetailed);
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017394 CHECK_EQ(4, stackTrace->GetFrameCount());
17395 v8::Handle<v8::String> url = v8_str("source_url");
17396 for (int i = 0; i < 3; i++) {
17397 v8::Handle<v8::String> name =
17398 stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
17399 CHECK(!name.IsEmpty());
17400 CHECK_EQ(url, name);
17401 }
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017402}
17403
17404
17405TEST(DynamicWithSourceURLInStackTrace) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000017406 v8::Isolate* isolate = CcTest::isolate();
17407 v8::HandleScope scope(isolate);
17408 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017409 templ->Set(v8_str("AnalyzeStackOfDynamicScriptWithSourceURL"),
17410 v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017411 CcTest::isolate(), AnalyzeStackOfDynamicScriptWithSourceURL));
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017412 LocalContext context(0, templ);
17413
17414 const char *source =
17415 "function outer() {\n"
17416 "function bar() {\n"
17417 " AnalyzeStackOfDynamicScriptWithSourceURL();\n"
17418 "}\n"
17419 "function foo() {\n"
17420 "\n"
17421 " bar();\n"
17422 "}\n"
17423 "foo();\n"
17424 "}\n"
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000017425 "outer()\n%s";
17426
17427 i::ScopedVector<char> code(1024);
17428 i::OS::SNPrintF(code, source, "//# sourceURL=source_url");
17429 CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
17430 i::OS::SNPrintF(code, source, "//@ sourceURL=source_url");
17431 CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017432}
17433
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000017434
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017435static void CreateGarbageInOldSpace() {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017436 i::Factory* factory = CcTest::i_isolate()->factory();
17437 v8::HandleScope scope(CcTest::isolate());
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017438 i::AlwaysAllocateScope always_allocate;
17439 for (int i = 0; i < 1000; i++) {
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000017440 factory->NewFixedArray(1000, i::TENURED);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017441 }
svenpanne@chromium.orgecb9dd62011-12-01 08:22:35 +000017442}
17443
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000017444
svenpanne@chromium.orgecb9dd62011-12-01 08:22:35 +000017445// Test that idle notification can be handled and eventually returns true.
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017446TEST(IdleNotification) {
17447 const intptr_t MB = 1024 * 1024;
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017448 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017449 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017450 intptr_t initial_size = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017451 CreateGarbageInOldSpace();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017452 intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017453 CHECK_GT(size_with_garbage, initial_size + MB);
17454 bool finished = false;
17455 for (int i = 0; i < 200 && !finished; i++) {
17456 finished = v8::V8::IdleNotification();
17457 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017458 intptr_t final_size = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017459 CHECK(finished);
17460 CHECK_LT(final_size, initial_size + 1);
17461}
17462
17463
17464// Test that idle notification can be handled and eventually collects garbage.
yangguo@chromium.org56454712012-02-16 15:33:53 +000017465TEST(IdleNotificationWithSmallHint) {
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017466 const intptr_t MB = 1024 * 1024;
17467 const int IdlePauseInMs = 900;
svenpanne@chromium.orgecb9dd62011-12-01 08:22:35 +000017468 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017469 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017470 intptr_t initial_size = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017471 CreateGarbageInOldSpace();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017472 intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017473 CHECK_GT(size_with_garbage, initial_size + MB);
17474 bool finished = false;
17475 for (int i = 0; i < 200 && !finished; i++) {
17476 finished = v8::V8::IdleNotification(IdlePauseInMs);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017477 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017478 intptr_t final_size = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017479 CHECK(finished);
17480 CHECK_LT(final_size, initial_size + 1);
yangguo@chromium.org56454712012-02-16 15:33:53 +000017481}
17482
17483
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017484// Test that idle notification can be handled and eventually collects garbage.
yangguo@chromium.org56454712012-02-16 15:33:53 +000017485TEST(IdleNotificationWithLargeHint) {
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017486 const intptr_t MB = 1024 * 1024;
17487 const int IdlePauseInMs = 900;
yangguo@chromium.org56454712012-02-16 15:33:53 +000017488 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017489 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017490 intptr_t initial_size = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017491 CreateGarbageInOldSpace();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017492 intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017493 CHECK_GT(size_with_garbage, initial_size + MB);
17494 bool finished = false;
17495 for (int i = 0; i < 200 && !finished; i++) {
17496 finished = v8::V8::IdleNotification(IdlePauseInMs);
yangguo@chromium.org56454712012-02-16 15:33:53 +000017497 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017498 intptr_t final_size = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017499 CHECK(finished);
17500 CHECK_LT(final_size, initial_size + 1);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017501}
17502
17503
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017504TEST(Regress2107) {
17505 const intptr_t MB = 1024 * 1024;
17506 const int kShortIdlePauseInMs = 100;
17507 const int kLongIdlePauseInMs = 1000;
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017508 LocalContext env;
ulan@chromium.org57ff8812013-05-10 08:16:55 +000017509 v8::Isolate* isolate = env->GetIsolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017510 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017511 intptr_t initial_size = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017512 // Send idle notification to start a round of incremental GCs.
17513 v8::V8::IdleNotification(kShortIdlePauseInMs);
17514 // Emulate 7 page reloads.
17515 for (int i = 0; i < 7; i++) {
ulan@chromium.org57ff8812013-05-10 08:16:55 +000017516 {
17517 v8::HandleScope inner_scope(env->GetIsolate());
17518 v8::Local<v8::Context> ctx = v8::Context::New(isolate);
17519 ctx->Enter();
17520 CreateGarbageInOldSpace();
17521 ctx->Exit();
17522 }
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017523 v8::V8::ContextDisposedNotification();
17524 v8::V8::IdleNotification(kLongIdlePauseInMs);
17525 }
17526 // Create garbage and check that idle notification still collects it.
17527 CreateGarbageInOldSpace();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017528 intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017529 CHECK_GT(size_with_garbage, initial_size + MB);
17530 bool finished = false;
17531 for (int i = 0; i < 200 && !finished; i++) {
17532 finished = v8::V8::IdleNotification(kShortIdlePauseInMs);
17533 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017534 intptr_t final_size = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017535 CHECK_LT(final_size, initial_size + 1);
17536}
17537
machenbach@chromium.orgb5be0a92013-11-15 10:32:41 +000017538
17539TEST(Regress2333) {
17540 LocalContext env;
17541 for (int i = 0; i < 3; i++) {
17542 CcTest::heap()->PerformScavenge();
17543 }
17544}
17545
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017546static uint32_t* stack_limit;
17547
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017548static void GetStackLimitCallback(
17549 const v8::FunctionCallbackInfo<v8::Value>& args) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000017550 stack_limit = reinterpret_cast<uint32_t*>(
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017551 CcTest::i_isolate()->stack_guard()->real_climit());
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017552}
17553
17554
17555// Uses the address of a local variable to determine the stack top now.
17556// Given a size, returns an address that is that far from the current
17557// top of stack.
17558static uint32_t* ComputeStackLimit(uint32_t size) {
17559 uint32_t* answer = &size - (size / sizeof(size));
17560 // If the size is very large and the stack is very near the bottom of
17561 // memory then the calculation above may wrap around and give an address
17562 // that is above the (downwards-growing) stack. In that case we return
17563 // a very low address.
17564 if (answer > &size) return reinterpret_cast<uint32_t*>(sizeof(size));
17565 return answer;
17566}
17567
17568
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +000017569// We need at least 165kB for an x64 debug build with clang and ASAN.
17570static const int stack_breathing_room = 256 * i::KB;
17571
17572
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017573TEST(SetResourceConstraints) {
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +000017574 uint32_t* set_limit = ComputeStackLimit(stack_breathing_room);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017575
17576 // Set stack limit.
17577 v8::ResourceConstraints constraints;
17578 constraints.set_stack_limit(set_limit);
machenbach@chromium.org7ff76072013-11-21 09:47:43 +000017579 CHECK(v8::SetResourceConstraints(CcTest::isolate(), &constraints));
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017580
17581 // Execute a script.
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017582 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017583 v8::HandleScope scope(env->GetIsolate());
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017584 Local<v8::FunctionTemplate> fun_templ =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017585 v8::FunctionTemplate::New(env->GetIsolate(), GetStackLimitCallback);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017586 Local<Function> fun = fun_templ->GetFunction();
17587 env->Global()->Set(v8_str("get_stack_limit"), fun);
17588 CompileRun("get_stack_limit();");
17589
17590 CHECK(stack_limit == set_limit);
17591}
17592
17593
17594TEST(SetResourceConstraintsInThread) {
17595 uint32_t* set_limit;
17596 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017597 v8::Locker locker(CcTest::isolate());
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +000017598 set_limit = ComputeStackLimit(stack_breathing_room);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017599
17600 // Set stack limit.
17601 v8::ResourceConstraints constraints;
17602 constraints.set_stack_limit(set_limit);
machenbach@chromium.org7ff76072013-11-21 09:47:43 +000017603 CHECK(v8::SetResourceConstraints(CcTest::isolate(), &constraints));
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017604
17605 // Execute a script.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017606 v8::HandleScope scope(CcTest::isolate());
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017607 LocalContext env;
17608 Local<v8::FunctionTemplate> fun_templ =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017609 v8::FunctionTemplate::New(CcTest::isolate(), GetStackLimitCallback);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017610 Local<Function> fun = fun_templ->GetFunction();
17611 env->Global()->Set(v8_str("get_stack_limit"), fun);
17612 CompileRun("get_stack_limit();");
17613
17614 CHECK(stack_limit == set_limit);
17615 }
17616 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017617 v8::Locker locker(CcTest::isolate());
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017618 CHECK(stack_limit == set_limit);
17619 }
ager@chromium.org96c75b52009-08-26 09:13:16 +000017620}
ager@chromium.org3811b432009-10-28 14:53:37 +000017621
17622
17623THREADED_TEST(GetHeapStatistics) {
ager@chromium.org3811b432009-10-28 14:53:37 +000017624 LocalContext c1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017625 v8::HandleScope scope(c1->GetIsolate());
ager@chromium.org3811b432009-10-28 14:53:37 +000017626 v8::HeapStatistics heap_statistics;
ager@chromium.orgc4c92722009-11-18 14:12:51 +000017627 CHECK_EQ(static_cast<int>(heap_statistics.total_heap_size()), 0);
17628 CHECK_EQ(static_cast<int>(heap_statistics.used_heap_size()), 0);
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +000017629 c1->GetIsolate()->GetHeapStatistics(&heap_statistics);
ager@chromium.orgc4c92722009-11-18 14:12:51 +000017630 CHECK_NE(static_cast<int>(heap_statistics.total_heap_size()), 0);
17631 CHECK_NE(static_cast<int>(heap_statistics.used_heap_size()), 0);
ager@chromium.org3811b432009-10-28 14:53:37 +000017632}
17633
17634
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017635class VisitorImpl : public v8::ExternalResourceVisitor {
17636 public:
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017637 explicit VisitorImpl(TestResource** resource) {
17638 for (int i = 0; i < 4; i++) {
17639 resource_[i] = resource[i];
17640 found_resource_[i] = false;
17641 }
17642 }
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017643 virtual ~VisitorImpl() {}
17644 virtual void VisitExternalString(v8::Handle<v8::String> string) {
17645 if (!string->IsExternal()) {
17646 CHECK(string->IsExternalAscii());
17647 return;
17648 }
17649 v8::String::ExternalStringResource* resource =
17650 string->GetExternalStringResource();
17651 CHECK(resource);
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017652 for (int i = 0; i < 4; i++) {
17653 if (resource_[i] == resource) {
17654 CHECK(!found_resource_[i]);
17655 found_resource_[i] = true;
17656 }
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017657 }
17658 }
17659 void CheckVisitedResources() {
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017660 for (int i = 0; i < 4; i++) {
17661 CHECK(found_resource_[i]);
17662 }
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017663 }
17664
17665 private:
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017666 v8::String::ExternalStringResource* resource_[4];
17667 bool found_resource_[4];
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017668};
17669
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000017670
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017671TEST(VisitExternalStrings) {
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017672 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017673 v8::HandleScope scope(env->GetIsolate());
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017674 const char* string = "Some string";
17675 uint16_t* two_byte_string = AsciiToTwoByteString(string);
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017676 TestResource* resource[4];
17677 resource[0] = new TestResource(two_byte_string);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017678 v8::Local<v8::String> string0 =
17679 v8::String::NewExternal(env->GetIsolate(), resource[0]);
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017680 resource[1] = new TestResource(two_byte_string);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017681 v8::Local<v8::String> string1 =
17682 v8::String::NewExternal(env->GetIsolate(), resource[1]);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017683
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017684 // Externalized symbol.
17685 resource[2] = new TestResource(two_byte_string);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017686 v8::Local<v8::String> string2 = v8::String::NewFromUtf8(
17687 env->GetIsolate(), string, v8::String::kInternalizedString);
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017688 CHECK(string2->MakeExternal(resource[2]));
17689
17690 // Symbolized External.
17691 resource[3] = new TestResource(AsciiToTwoByteString("Some other string"));
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017692 v8::Local<v8::String> string3 =
17693 v8::String::NewExternal(env->GetIsolate(), resource[3]);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017694 CcTest::heap()->CollectAllAvailableGarbage(); // Tenure string.
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017695 // Turn into a symbol.
17696 i::Handle<i::String> string3_i = v8::Utils::OpenHandle(*string3);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017697 CHECK(!CcTest::heap()->InternalizeString(*string3_i)->IsFailure());
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +000017698 CHECK(string3_i->IsInternalizedString());
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017699
17700 // We need to add usages for string* to avoid warnings in GCC 4.7
17701 CHECK(string0->IsExternal());
ulan@chromium.org2efb9002012-01-19 15:36:35 +000017702 CHECK(string1->IsExternal());
17703 CHECK(string2->IsExternal());
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017704 CHECK(string3->IsExternal());
ulan@chromium.org2efb9002012-01-19 15:36:35 +000017705
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017706 VisitorImpl visitor(resource);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017707 v8::V8::VisitExternalResources(&visitor);
17708 visitor.CheckVisitedResources();
17709}
17710
17711
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017712TEST(ExternalStringCollectedAtTearDown) {
17713 int destroyed = 0;
17714 v8::Isolate* isolate = v8::Isolate::New();
17715 { v8::Isolate::Scope isolate_scope(isolate);
17716 v8::HandleScope handle_scope(isolate);
17717 const char* s = "One string to test them all, one string to find them.";
17718 TestAsciiResource* inscription =
17719 new TestAsciiResource(i::StrDup(s), &destroyed);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017720 v8::Local<v8::String> ring = v8::String::NewExternal(isolate, inscription);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017721 // Ring is still alive. Orcs are roaming freely across our lands.
17722 CHECK_EQ(0, destroyed);
17723 USE(ring);
17724 }
17725
17726 isolate->Dispose();
17727 // Ring has been destroyed. Free Peoples of Middle-earth Rejoice.
17728 CHECK_EQ(1, destroyed);
17729}
17730
17731
jkummerow@chromium.org113035e2013-12-13 15:13:40 +000017732TEST(ExternalInternalizedStringCollectedAtTearDown) {
17733 int destroyed = 0;
17734 v8::Isolate* isolate = v8::Isolate::New();
17735 { v8::Isolate::Scope isolate_scope(isolate);
17736 LocalContext env(isolate);
17737 v8::HandleScope handle_scope(isolate);
17738 CompileRun("var ring = 'One string to test them all';");
17739 const char* s = "One string to test them all";
17740 TestAsciiResource* inscription =
17741 new TestAsciiResource(i::StrDup(s), &destroyed);
17742 v8::Local<v8::String> ring = CompileRun("ring")->ToString();
17743 CHECK(v8::Utils::OpenHandle(*ring)->IsInternalizedString());
17744 ring->MakeExternal(inscription);
17745 // Ring is still alive. Orcs are roaming freely across our lands.
17746 CHECK_EQ(0, destroyed);
17747 USE(ring);
17748 }
17749
17750 isolate->Dispose();
17751 // Ring has been destroyed. Free Peoples of Middle-earth Rejoice.
17752 CHECK_EQ(1, destroyed);
17753}
17754
17755
17756TEST(ExternalInternalizedStringCollectedAtGC) {
17757 int destroyed = 0;
17758 { LocalContext env;
17759 v8::HandleScope handle_scope(env->GetIsolate());
17760 CompileRun("var ring = 'One string to test them all';");
17761 const char* s = "One string to test them all";
17762 TestAsciiResource* inscription =
17763 new TestAsciiResource(i::StrDup(s), &destroyed);
17764 v8::Local<v8::String> ring = CompileRun("ring")->ToString();
17765 CHECK(v8::Utils::OpenHandle(*ring)->IsInternalizedString());
17766 ring->MakeExternal(inscription);
17767 // Ring is still alive. Orcs are roaming freely across our lands.
17768 CHECK_EQ(0, destroyed);
17769 USE(ring);
17770 }
17771
17772 // Garbage collector deals swift blows to evil.
17773 CcTest::i_isolate()->compilation_cache()->Clear();
17774 CcTest::heap()->CollectAllAvailableGarbage();
17775
17776 // Ring has been destroyed. Free Peoples of Middle-earth Rejoice.
17777 CHECK_EQ(1, destroyed);
17778}
17779
17780
ager@chromium.org3811b432009-10-28 14:53:37 +000017781static double DoubleFromBits(uint64_t value) {
17782 double target;
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +000017783 i::OS::MemCopy(&target, &value, sizeof(target));
ager@chromium.org3811b432009-10-28 14:53:37 +000017784 return target;
17785}
17786
17787
17788static uint64_t DoubleToBits(double value) {
17789 uint64_t target;
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +000017790 i::OS::MemCopy(&target, &value, sizeof(target));
ager@chromium.org3811b432009-10-28 14:53:37 +000017791 return target;
17792}
17793
17794
17795static double DoubleToDateTime(double input) {
17796 double date_limit = 864e13;
ulan@chromium.org77ca49a2013-04-22 09:43:56 +000017797 if (std::isnan(input) || input < -date_limit || input > date_limit) {
ager@chromium.org3811b432009-10-28 14:53:37 +000017798 return i::OS::nan_value();
17799 }
17800 return (input < 0) ? -(floor(-input)) : floor(input);
17801}
17802
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000017803
ager@chromium.org3811b432009-10-28 14:53:37 +000017804// We don't have a consistent way to write 64-bit constants syntactically, so we
17805// split them into two 32-bit constants and combine them programmatically.
17806static double DoubleFromBits(uint32_t high_bits, uint32_t low_bits) {
17807 return DoubleFromBits((static_cast<uint64_t>(high_bits) << 32) | low_bits);
17808}
17809
17810
17811THREADED_TEST(QuietSignalingNaNs) {
ager@chromium.org3811b432009-10-28 14:53:37 +000017812 LocalContext context;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000017813 v8::Isolate* isolate = context->GetIsolate();
17814 v8::HandleScope scope(isolate);
ager@chromium.org3811b432009-10-28 14:53:37 +000017815 v8::TryCatch try_catch;
17816
17817 // Special double values.
17818 double snan = DoubleFromBits(0x7ff00000, 0x00000001);
17819 double qnan = DoubleFromBits(0x7ff80000, 0x00000000);
17820 double infinity = DoubleFromBits(0x7ff00000, 0x00000000);
17821 double max_normal = DoubleFromBits(0x7fefffff, 0xffffffffu);
17822 double min_normal = DoubleFromBits(0x00100000, 0x00000000);
17823 double max_denormal = DoubleFromBits(0x000fffff, 0xffffffffu);
17824 double min_denormal = DoubleFromBits(0x00000000, 0x00000001);
17825
17826 // Date values are capped at +/-100000000 days (times 864e5 ms per day)
17827 // on either side of the epoch.
17828 double date_limit = 864e13;
17829
17830 double test_values[] = {
17831 snan,
17832 qnan,
17833 infinity,
17834 max_normal,
17835 date_limit + 1,
17836 date_limit,
17837 min_normal,
17838 max_denormal,
17839 min_denormal,
17840 0,
17841 -0,
17842 -min_denormal,
17843 -max_denormal,
17844 -min_normal,
17845 -date_limit,
17846 -date_limit - 1,
17847 -max_normal,
17848 -infinity,
17849 -qnan,
17850 -snan
17851 };
17852 int num_test_values = 20;
17853
17854 for (int i = 0; i < num_test_values; i++) {
17855 double test_value = test_values[i];
17856
17857 // Check that Number::New preserves non-NaNs and quiets SNaNs.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000017858 v8::Handle<v8::Value> number = v8::Number::New(isolate, test_value);
ager@chromium.org3811b432009-10-28 14:53:37 +000017859 double stored_number = number->NumberValue();
ulan@chromium.org77ca49a2013-04-22 09:43:56 +000017860 if (!std::isnan(test_value)) {
ager@chromium.org3811b432009-10-28 14:53:37 +000017861 CHECK_EQ(test_value, stored_number);
17862 } else {
17863 uint64_t stored_bits = DoubleToBits(stored_number);
17864 // Check if quiet nan (bits 51..62 all set).
danno@chromium.orgc612e022011-11-10 11:38:15 +000017865#if defined(V8_TARGET_ARCH_MIPS) && !defined(USE_SIMULATOR)
17866 // Most significant fraction bit for quiet nan is set to 0
17867 // on MIPS architecture. Allowed by IEEE-754.
17868 CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
17869#else
ager@chromium.org3811b432009-10-28 14:53:37 +000017870 CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
danno@chromium.orgc612e022011-11-10 11:38:15 +000017871#endif
ager@chromium.org3811b432009-10-28 14:53:37 +000017872 }
17873
17874 // Check that Date::New preserves non-NaNs in the date range and
17875 // quiets SNaNs.
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017876 v8::Handle<v8::Value> date =
ulan@chromium.org0f13e742014-01-03 15:51:11 +000017877 v8::Date::New(isolate, test_value);
ager@chromium.org3811b432009-10-28 14:53:37 +000017878 double expected_stored_date = DoubleToDateTime(test_value);
17879 double stored_date = date->NumberValue();
ulan@chromium.org77ca49a2013-04-22 09:43:56 +000017880 if (!std::isnan(expected_stored_date)) {
ager@chromium.org3811b432009-10-28 14:53:37 +000017881 CHECK_EQ(expected_stored_date, stored_date);
17882 } else {
17883 uint64_t stored_bits = DoubleToBits(stored_date);
17884 // Check if quiet nan (bits 51..62 all set).
danno@chromium.orgc612e022011-11-10 11:38:15 +000017885#if defined(V8_TARGET_ARCH_MIPS) && !defined(USE_SIMULATOR)
17886 // Most significant fraction bit for quiet nan is set to 0
17887 // on MIPS architecture. Allowed by IEEE-754.
17888 CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
17889#else
ager@chromium.org3811b432009-10-28 14:53:37 +000017890 CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
danno@chromium.orgc612e022011-11-10 11:38:15 +000017891#endif
ager@chromium.org3811b432009-10-28 14:53:37 +000017892 }
17893 }
17894}
christian.plesner.hansen@gmail.comb9ce6372009-11-03 11:38:18 +000017895
17896
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017897static void SpaghettiIncident(
17898 const v8::FunctionCallbackInfo<v8::Value>& args) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017899 v8::HandleScope scope(args.GetIsolate());
christian.plesner.hansen@gmail.comb9ce6372009-11-03 11:38:18 +000017900 v8::TryCatch tc;
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000017901 v8::Handle<v8::String> str(args[0]->ToString());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000017902 USE(str);
christian.plesner.hansen@gmail.comb9ce6372009-11-03 11:38:18 +000017903 if (tc.HasCaught())
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017904 tc.ReThrow();
christian.plesner.hansen@gmail.comb9ce6372009-11-03 11:38:18 +000017905}
17906
17907
17908// Test that an exception can be propagated down through a spaghetti
17909// stack using ReThrow.
17910THREADED_TEST(SpaghettiStackReThrow) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017911 v8::Isolate* isolate = CcTest::isolate();
17912 v8::HandleScope scope(isolate);
christian.plesner.hansen@gmail.comb9ce6372009-11-03 11:38:18 +000017913 LocalContext context;
17914 context->Global()->Set(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017915 v8::String::NewFromUtf8(isolate, "s"),
17916 v8::FunctionTemplate::New(isolate, SpaghettiIncident)->GetFunction());
christian.plesner.hansen@gmail.comb9ce6372009-11-03 11:38:18 +000017917 v8::TryCatch try_catch;
17918 CompileRun(
17919 "var i = 0;"
17920 "var o = {"
17921 " toString: function () {"
17922 " if (i == 10) {"
17923 " throw 'Hey!';"
17924 " } else {"
17925 " i++;"
17926 " return s(o);"
17927 " }"
17928 " }"
17929 "};"
17930 "s(o);");
17931 CHECK(try_catch.HasCaught());
17932 v8::String::Utf8Value value(try_catch.Exception());
17933 CHECK_EQ(0, strcmp(*value, "Hey!"));
17934}
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000017935
17936
sgjesse@chromium.org98180592009-12-02 08:17:28 +000017937TEST(Regress528) {
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000017938 v8::V8::Initialize();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017939 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000017940 v8::HandleScope scope(isolate);
17941 v8::Local<Context> other_context;
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000017942 int gc_count;
17943
ager@chromium.org60121232009-12-03 11:25:37 +000017944 // Create a context used to keep the code from aging in the compilation
17945 // cache.
ulan@chromium.org57ff8812013-05-10 08:16:55 +000017946 other_context = Context::New(isolate);
ager@chromium.org60121232009-12-03 11:25:37 +000017947
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000017948 // Context-dependent context data creates reference from the compilation
17949 // cache to the global object.
ager@chromium.org60121232009-12-03 11:25:37 +000017950 const char* source_simple = "1";
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000017951 {
ulan@chromium.org57ff8812013-05-10 08:16:55 +000017952 v8::HandleScope scope(isolate);
17953 v8::Local<Context> context = Context::New(isolate);
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000017954
17955 context->Enter();
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017956 Local<v8::String> obj = v8::String::NewFromUtf8(isolate, "");
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000017957 context->SetEmbedderData(0, obj);
ager@chromium.org60121232009-12-03 11:25:37 +000017958 CompileRun(source_simple);
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000017959 context->Exit();
17960 }
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000017961 v8::V8::ContextDisposedNotification();
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000017962 for (gc_count = 1; gc_count < 10; gc_count++) {
ager@chromium.org60121232009-12-03 11:25:37 +000017963 other_context->Enter();
17964 CompileRun(source_simple);
17965 other_context->Exit();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017966 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org60121232009-12-03 11:25:37 +000017967 if (GetGlobalObjectsCount() == 1) break;
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000017968 }
ager@chromium.org60121232009-12-03 11:25:37 +000017969 CHECK_GE(2, gc_count);
17970 CHECK_EQ(1, GetGlobalObjectsCount());
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000017971
17972 // Eval in a function creates reference from the compilation cache to the
17973 // global object.
ager@chromium.org60121232009-12-03 11:25:37 +000017974 const char* source_eval = "function f(){eval('1')}; f()";
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000017975 {
ulan@chromium.org57ff8812013-05-10 08:16:55 +000017976 v8::HandleScope scope(isolate);
17977 v8::Local<Context> context = Context::New(isolate);
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000017978
17979 context->Enter();
ager@chromium.org60121232009-12-03 11:25:37 +000017980 CompileRun(source_eval);
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000017981 context->Exit();
17982 }
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000017983 v8::V8::ContextDisposedNotification();
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000017984 for (gc_count = 1; gc_count < 10; gc_count++) {
ager@chromium.org60121232009-12-03 11:25:37 +000017985 other_context->Enter();
17986 CompileRun(source_eval);
17987 other_context->Exit();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017988 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org60121232009-12-03 11:25:37 +000017989 if (GetGlobalObjectsCount() == 1) break;
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000017990 }
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +000017991 CHECK_GE(2, gc_count);
sgjesse@chromium.org98180592009-12-02 08:17:28 +000017992 CHECK_EQ(1, GetGlobalObjectsCount());
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000017993
17994 // Looking up the line number for an exception creates reference from the
17995 // compilation cache to the global object.
ager@chromium.org60121232009-12-03 11:25:37 +000017996 const char* source_exception = "function f(){throw 1;} f()";
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000017997 {
ulan@chromium.org57ff8812013-05-10 08:16:55 +000017998 v8::HandleScope scope(isolate);
17999 v8::Local<Context> context = Context::New(isolate);
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018000
18001 context->Enter();
18002 v8::TryCatch try_catch;
ager@chromium.org60121232009-12-03 11:25:37 +000018003 CompileRun(source_exception);
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018004 CHECK(try_catch.HasCaught());
18005 v8::Handle<v8::Message> message = try_catch.Message();
18006 CHECK(!message.IsEmpty());
18007 CHECK_EQ(1, message->GetLineNumber());
18008 context->Exit();
18009 }
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +000018010 v8::V8::ContextDisposedNotification();
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018011 for (gc_count = 1; gc_count < 10; gc_count++) {
ager@chromium.org60121232009-12-03 11:25:37 +000018012 other_context->Enter();
18013 CompileRun(source_exception);
18014 other_context->Exit();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018015 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org60121232009-12-03 11:25:37 +000018016 if (GetGlobalObjectsCount() == 1) break;
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018017 }
ager@chromium.org60121232009-12-03 11:25:37 +000018018 CHECK_GE(2, gc_count);
18019 CHECK_EQ(1, GetGlobalObjectsCount());
18020
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000018021 v8::V8::ContextDisposedNotification();
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018022}
ager@chromium.org5c838252010-02-19 08:53:10 +000018023
18024
18025THREADED_TEST(ScriptOrigin) {
ager@chromium.org5c838252010-02-19 08:53:10 +000018026 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018027 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018028 v8::ScriptOrigin origin =
18029 v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
18030 v8::Handle<v8::String> script = v8::String::NewFromUtf8(
18031 env->GetIsolate(), "function f() {}\n\nfunction g() {}");
ager@chromium.org5c838252010-02-19 08:53:10 +000018032 v8::Script::Compile(script, &origin)->Run();
18033 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018034 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
ager@chromium.org5c838252010-02-19 08:53:10 +000018035 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018036 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
ager@chromium.org5c838252010-02-19 08:53:10 +000018037
18038 v8::ScriptOrigin script_origin_f = f->GetScriptOrigin();
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000018039 CHECK_EQ("test", *v8::String::Utf8Value(script_origin_f.ResourceName()));
ager@chromium.org5c838252010-02-19 08:53:10 +000018040 CHECK_EQ(0, script_origin_f.ResourceLineOffset()->Int32Value());
18041
18042 v8::ScriptOrigin script_origin_g = g->GetScriptOrigin();
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000018043 CHECK_EQ("test", *v8::String::Utf8Value(script_origin_g.ResourceName()));
ager@chromium.org5c838252010-02-19 08:53:10 +000018044 CHECK_EQ(0, script_origin_g.ResourceLineOffset()->Int32Value());
18045}
18046
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000018047
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000018048THREADED_TEST(FunctionGetInferredName) {
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000018049 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018050 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018051 v8::ScriptOrigin origin =
18052 v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
18053 v8::Handle<v8::String> script = v8::String::NewFromUtf8(
18054 env->GetIsolate(),
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000018055 "var foo = { bar : { baz : function() {}}}; var f = foo.bar.baz;");
18056 v8::Script::Compile(script, &origin)->Run();
18057 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018058 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000018059 CHECK_EQ("foo.bar.baz", *v8::String::Utf8Value(f->GetInferredName()));
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000018060}
ager@chromium.org5c838252010-02-19 08:53:10 +000018061
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000018062
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +000018063THREADED_TEST(FunctionGetDisplayName) {
18064 LocalContext env;
18065 v8::HandleScope scope(env->GetIsolate());
18066 const char* code = "var error = false;"
18067 "function a() { this.x = 1; };"
18068 "a.displayName = 'display_a';"
18069 "var b = (function() {"
18070 " var f = function() { this.x = 2; };"
18071 " f.displayName = 'display_b';"
18072 " return f;"
18073 "})();"
18074 "var c = function() {};"
18075 "c.__defineGetter__('displayName', function() {"
18076 " error = true;"
18077 " throw new Error();"
18078 "});"
18079 "function d() {};"
18080 "d.__defineGetter__('displayName', function() {"
18081 " error = true;"
18082 " return 'wrong_display_name';"
18083 "});"
18084 "function e() {};"
18085 "e.displayName = 'wrong_display_name';"
18086 "e.__defineSetter__('displayName', function() {"
18087 " error = true;"
18088 " throw new Error();"
18089 "});"
18090 "function f() {};"
18091 "f.displayName = { 'foo': 6, toString: function() {"
18092 " error = true;"
18093 " return 'wrong_display_name';"
18094 "}};"
18095 "var g = function() {"
18096 " arguments.callee.displayName = 'set_in_runtime';"
18097 "}; g();"
18098 ;
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018099 v8::ScriptOrigin origin =
18100 v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
18101 v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), code), &origin)
18102 ->Run();
18103 v8::Local<v8::Value> error =
18104 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "error"));
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +000018105 v8::Local<v8::Function> a = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018106 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "a")));
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +000018107 v8::Local<v8::Function> b = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018108 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "b")));
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +000018109 v8::Local<v8::Function> c = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018110 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "c")));
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +000018111 v8::Local<v8::Function> d = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018112 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "d")));
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +000018113 v8::Local<v8::Function> e = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018114 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "e")));
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +000018115 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018116 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +000018117 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018118 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +000018119 CHECK_EQ(false, error->BooleanValue());
18120 CHECK_EQ("display_a", *v8::String::Utf8Value(a->GetDisplayName()));
18121 CHECK_EQ("display_b", *v8::String::Utf8Value(b->GetDisplayName()));
18122 CHECK(c->GetDisplayName()->IsUndefined());
18123 CHECK(d->GetDisplayName()->IsUndefined());
18124 CHECK(e->GetDisplayName()->IsUndefined());
18125 CHECK(f->GetDisplayName()->IsUndefined());
18126 CHECK_EQ("set_in_runtime", *v8::String::Utf8Value(g->GetDisplayName()));
18127}
18128
18129
ager@chromium.org5c838252010-02-19 08:53:10 +000018130THREADED_TEST(ScriptLineNumber) {
ager@chromium.org5c838252010-02-19 08:53:10 +000018131 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018132 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018133 v8::ScriptOrigin origin =
18134 v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
18135 v8::Handle<v8::String> script = v8::String::NewFromUtf8(
18136 env->GetIsolate(), "function f() {}\n\nfunction g() {}");
ager@chromium.org5c838252010-02-19 08:53:10 +000018137 v8::Script::Compile(script, &origin)->Run();
18138 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018139 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
ager@chromium.org5c838252010-02-19 08:53:10 +000018140 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018141 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
ager@chromium.org5c838252010-02-19 08:53:10 +000018142 CHECK_EQ(0, f->GetScriptLineNumber());
18143 CHECK_EQ(2, g->GetScriptLineNumber());
18144}
18145
18146
danno@chromium.orgc612e022011-11-10 11:38:15 +000018147THREADED_TEST(ScriptColumnNumber) {
danno@chromium.orgc612e022011-11-10 11:38:15 +000018148 LocalContext env;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018149 v8::Isolate* isolate = env->GetIsolate();
18150 v8::HandleScope scope(isolate);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018151 v8::ScriptOrigin origin =
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018152 v8::ScriptOrigin(v8::String::NewFromUtf8(isolate, "test"),
18153 v8::Integer::New(isolate, 3),
18154 v8::Integer::New(isolate, 2));
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018155 v8::Handle<v8::String> script = v8::String::NewFromUtf8(
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018156 isolate, "function foo() {}\n\n function bar() {}");
danno@chromium.orgc612e022011-11-10 11:38:15 +000018157 v8::Script::Compile(script, &origin)->Run();
18158 v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018159 env->Global()->Get(v8::String::NewFromUtf8(isolate, "foo")));
danno@chromium.orgc612e022011-11-10 11:38:15 +000018160 v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018161 env->Global()->Get(v8::String::NewFromUtf8(isolate, "bar")));
danno@chromium.orgc612e022011-11-10 11:38:15 +000018162 CHECK_EQ(14, foo->GetScriptColumnNumber());
18163 CHECK_EQ(17, bar->GetScriptColumnNumber());
18164}
18165
18166
bmeurer@chromium.orgdb783292013-10-23 06:51:00 +000018167THREADED_TEST(FunctionIsBuiltin) {
18168 LocalContext env;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018169 v8::Isolate* isolate = env->GetIsolate();
18170 v8::HandleScope scope(isolate);
bmeurer@chromium.orgdb783292013-10-23 06:51:00 +000018171 v8::Local<v8::Function> f;
18172 f = v8::Local<v8::Function>::Cast(CompileRun("Math.floor"));
18173 CHECK(f->IsBuiltin());
18174 f = v8::Local<v8::Function>::Cast(CompileRun("Object"));
18175 CHECK(f->IsBuiltin());
18176 f = v8::Local<v8::Function>::Cast(CompileRun("Object.__defineSetter__"));
18177 CHECK(f->IsBuiltin());
18178 f = v8::Local<v8::Function>::Cast(CompileRun("Array.prototype.toString"));
18179 CHECK(f->IsBuiltin());
18180 f = v8::Local<v8::Function>::Cast(CompileRun("function a() {}; a;"));
18181 CHECK(!f->IsBuiltin());
18182}
18183
18184
danno@chromium.orgc612e022011-11-10 11:38:15 +000018185THREADED_TEST(FunctionGetScriptId) {
danno@chromium.orgc612e022011-11-10 11:38:15 +000018186 LocalContext env;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018187 v8::Isolate* isolate = env->GetIsolate();
18188 v8::HandleScope scope(isolate);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018189 v8::ScriptOrigin origin =
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018190 v8::ScriptOrigin(v8::String::NewFromUtf8(isolate, "test"),
18191 v8::Integer::New(isolate, 3),
18192 v8::Integer::New(isolate, 2));
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018193 v8::Handle<v8::String> scriptSource = v8::String::NewFromUtf8(
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018194 isolate, "function foo() {}\n\n function bar() {}");
danno@chromium.orgc612e022011-11-10 11:38:15 +000018195 v8::Local<v8::Script> script(v8::Script::Compile(scriptSource, &origin));
18196 script->Run();
18197 v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018198 env->Global()->Get(v8::String::NewFromUtf8(isolate, "foo")));
danno@chromium.orgc612e022011-11-10 11:38:15 +000018199 v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018200 env->Global()->Get(v8::String::NewFromUtf8(isolate, "bar")));
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018201 CHECK_EQ(script->GetId(), foo->ScriptId());
18202 CHECK_EQ(script->GetId(), bar->ScriptId());
danno@chromium.orgc612e022011-11-10 11:38:15 +000018203}
18204
18205
yangguo@chromium.org49546742013-12-23 16:17:49 +000018206THREADED_TEST(FunctionGetBoundFunction) {
18207 LocalContext env;
18208 v8::HandleScope scope(env->GetIsolate());
18209 v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::NewFromUtf8(
18210 env->GetIsolate(), "test"));
18211 v8::Handle<v8::String> script = v8::String::NewFromUtf8(
18212 env->GetIsolate(),
18213 "var a = new Object();\n"
18214 "a.x = 1;\n"
18215 "function f () { return this.x };\n"
18216 "var g = f.bind(a);\n"
18217 "var b = g();");
18218 v8::Script::Compile(script, &origin)->Run();
18219 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
18220 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
18221 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
18222 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
18223 CHECK(g->GetBoundFunction()->IsFunction());
18224 Local<v8::Function> original_function = Local<v8::Function>::Cast(
18225 g->GetBoundFunction());
18226 CHECK_EQ(f->GetName(), original_function->GetName());
18227 CHECK_EQ(f->GetScriptLineNumber(), original_function->GetScriptLineNumber());
18228 CHECK_EQ(f->GetScriptColumnNumber(),
18229 original_function->GetScriptColumnNumber());
18230}
18231
18232
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018233static void GetterWhichReturns42(
18234 Local<String> name,
18235 const v8::PropertyCallbackInfo<v8::Value>& info) {
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000018236 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
18237 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018238 info.GetReturnValue().Set(v8_num(42));
ager@chromium.org5c838252010-02-19 08:53:10 +000018239}
18240
18241
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018242static void SetterWhichSetsYOnThisTo23(
18243 Local<String> name,
18244 Local<Value> value,
18245 const v8::PropertyCallbackInfo<void>& info) {
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000018246 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
18247 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
ager@chromium.org5c838252010-02-19 08:53:10 +000018248 info.This()->Set(v8_str("y"), v8_num(23));
18249}
18250
18251
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018252void FooGetInterceptor(Local<String> name,
18253 const v8::PropertyCallbackInfo<v8::Value>& info) {
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000018254 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
18255 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018256 if (!name->Equals(v8_str("foo"))) return;
18257 info.GetReturnValue().Set(v8_num(42));
erik.corry@gmail.com88767242012-08-08 14:43:45 +000018258}
18259
18260
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018261void FooSetInterceptor(Local<String> name,
18262 Local<Value> value,
18263 const v8::PropertyCallbackInfo<v8::Value>& info) {
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000018264 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
18265 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018266 if (!name->Equals(v8_str("foo"))) return;
erik.corry@gmail.com88767242012-08-08 14:43:45 +000018267 info.This()->Set(v8_str("y"), v8_num(23));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018268 info.GetReturnValue().Set(v8_num(23));
erik.corry@gmail.com88767242012-08-08 14:43:45 +000018269}
18270
18271
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000018272TEST(SetterOnConstructorPrototype) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000018273 v8::Isolate* isolate = CcTest::isolate();
18274 v8::HandleScope scope(isolate);
18275 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +000018276 templ->SetAccessor(v8_str("x"),
18277 GetterWhichReturns42,
18278 SetterWhichSetsYOnThisTo23);
18279 LocalContext context;
18280 context->Global()->Set(v8_str("P"), templ->NewInstance());
18281 CompileRun("function C1() {"
18282 " this.x = 23;"
18283 "};"
18284 "C1.prototype = P;"
18285 "function C2() {"
18286 " this.x = 23"
18287 "};"
18288 "C2.prototype = { };"
18289 "C2.prototype.__proto__ = P;");
18290
18291 v8::Local<v8::Script> script;
18292 script = v8::Script::Compile(v8_str("new C1();"));
18293 for (int i = 0; i < 10; i++) {
18294 v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
18295 CHECK_EQ(42, c1->Get(v8_str("x"))->Int32Value());
18296 CHECK_EQ(23, c1->Get(v8_str("y"))->Int32Value());
18297 }
18298
18299 script = v8::Script::Compile(v8_str("new C2();"));
18300 for (int i = 0; i < 10; i++) {
18301 v8::Handle<v8::Object> c2 = v8::Handle<v8::Object>::Cast(script->Run());
18302 CHECK_EQ(42, c2->Get(v8_str("x"))->Int32Value());
18303 CHECK_EQ(23, c2->Get(v8_str("y"))->Int32Value());
18304 }
18305}
18306
18307
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018308static void NamedPropertyGetterWhichReturns42(
18309 Local<String> name,
18310 const v8::PropertyCallbackInfo<v8::Value>& info) {
18311 info.GetReturnValue().Set(v8_num(42));
ager@chromium.org5c838252010-02-19 08:53:10 +000018312}
18313
18314
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018315static void NamedPropertySetterWhichSetsYOnThisTo23(
18316 Local<String> name,
18317 Local<Value> value,
18318 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.org5c838252010-02-19 08:53:10 +000018319 if (name->Equals(v8_str("x"))) {
18320 info.This()->Set(v8_str("y"), v8_num(23));
18321 }
ager@chromium.org5c838252010-02-19 08:53:10 +000018322}
18323
18324
18325THREADED_TEST(InterceptorOnConstructorPrototype) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000018326 v8::Isolate* isolate = CcTest::isolate();
18327 v8::HandleScope scope(isolate);
18328 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +000018329 templ->SetNamedPropertyHandler(NamedPropertyGetterWhichReturns42,
18330 NamedPropertySetterWhichSetsYOnThisTo23);
18331 LocalContext context;
18332 context->Global()->Set(v8_str("P"), templ->NewInstance());
18333 CompileRun("function C1() {"
18334 " this.x = 23;"
18335 "};"
18336 "C1.prototype = P;"
18337 "function C2() {"
18338 " this.x = 23"
18339 "};"
18340 "C2.prototype = { };"
18341 "C2.prototype.__proto__ = P;");
18342
18343 v8::Local<v8::Script> script;
18344 script = v8::Script::Compile(v8_str("new C1();"));
18345 for (int i = 0; i < 10; i++) {
18346 v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
18347 CHECK_EQ(23, c1->Get(v8_str("x"))->Int32Value());
18348 CHECK_EQ(42, c1->Get(v8_str("y"))->Int32Value());
18349 }
18350
18351 script = v8::Script::Compile(v8_str("new C2();"));
18352 for (int i = 0; i < 10; i++) {
18353 v8::Handle<v8::Object> c2 = v8::Handle<v8::Object>::Cast(script->Run());
18354 CHECK_EQ(23, c2->Get(v8_str("x"))->Int32Value());
18355 CHECK_EQ(42, c2->Get(v8_str("y"))->Int32Value());
18356 }
18357}
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000018358
18359
danno@chromium.orgf005df62013-04-30 16:36:45 +000018360TEST(Regress618) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000018361 const char* source = "function C1() {"
18362 " this.x = 23;"
18363 "};"
18364 "C1.prototype = P;";
18365
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000018366 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000018367 v8::Isolate* isolate = context->GetIsolate();
18368 v8::HandleScope scope(isolate);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000018369 v8::Local<v8::Script> script;
18370
18371 // Use a simple object as prototype.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000018372 v8::Local<v8::Object> prototype = v8::Object::New(isolate);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000018373 prototype->Set(v8_str("y"), v8_num(42));
18374 context->Global()->Set(v8_str("P"), prototype);
18375
18376 // This compile will add the code to the compilation cache.
18377 CompileRun(source);
18378
18379 script = v8::Script::Compile(v8_str("new C1();"));
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +000018380 // Allow enough iterations for the inobject slack tracking logic
18381 // to finalize instance size and install the fast construct stub.
18382 for (int i = 0; i < 256; i++) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000018383 v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
18384 CHECK_EQ(23, c1->Get(v8_str("x"))->Int32Value());
18385 CHECK_EQ(42, c1->Get(v8_str("y"))->Int32Value());
18386 }
18387
18388 // Use an API object with accessors as prototype.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000018389 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000018390 templ->SetAccessor(v8_str("x"),
18391 GetterWhichReturns42,
18392 SetterWhichSetsYOnThisTo23);
18393 context->Global()->Set(v8_str("P"), templ->NewInstance());
18394
18395 // This compile will get the code from the compilation cache.
18396 CompileRun(source);
18397
18398 script = v8::Script::Compile(v8_str("new C1();"));
18399 for (int i = 0; i < 10; i++) {
18400 v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
18401 CHECK_EQ(42, c1->Get(v8_str("x"))->Int32Value());
18402 CHECK_EQ(23, c1->Get(v8_str("y"))->Int32Value());
18403 }
18404}
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018405
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018406v8::Isolate* gc_callbacks_isolate = NULL;
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018407int prologue_call_count = 0;
18408int epilogue_call_count = 0;
18409int prologue_call_count_second = 0;
18410int epilogue_call_count_second = 0;
18411
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018412void PrologueCallback(v8::GCType, v8::GCCallbackFlags flags) {
18413 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018414 ++prologue_call_count;
18415}
18416
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000018417
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018418void PrologueCallback(v8::Isolate* isolate,
18419 v8::GCType,
18420 v8::GCCallbackFlags flags) {
18421 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
18422 CHECK_EQ(gc_callbacks_isolate, isolate);
18423 ++prologue_call_count;
18424}
18425
18426
18427void EpilogueCallback(v8::GCType, v8::GCCallbackFlags flags) {
18428 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018429 ++epilogue_call_count;
18430}
18431
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000018432
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018433void EpilogueCallback(v8::Isolate* isolate,
18434 v8::GCType,
18435 v8::GCCallbackFlags flags) {
18436 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
18437 CHECK_EQ(gc_callbacks_isolate, isolate);
18438 ++epilogue_call_count;
18439}
18440
18441
18442void PrologueCallbackSecond(v8::GCType, v8::GCCallbackFlags flags) {
18443 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018444 ++prologue_call_count_second;
18445}
18446
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000018447
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018448void PrologueCallbackSecond(v8::Isolate* isolate,
18449 v8::GCType,
18450 v8::GCCallbackFlags flags) {
18451 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
18452 CHECK_EQ(gc_callbacks_isolate, isolate);
18453 ++prologue_call_count_second;
18454}
18455
18456
18457void EpilogueCallbackSecond(v8::GCType, v8::GCCallbackFlags flags) {
18458 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018459 ++epilogue_call_count_second;
18460}
18461
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000018462
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018463void EpilogueCallbackSecond(v8::Isolate* isolate,
18464 v8::GCType,
18465 v8::GCCallbackFlags flags) {
18466 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
18467 CHECK_EQ(gc_callbacks_isolate, isolate);
18468 ++epilogue_call_count_second;
18469}
18470
18471
18472TEST(GCCallbacksOld) {
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018473 LocalContext context;
18474
18475 v8::V8::AddGCPrologueCallback(PrologueCallback);
18476 v8::V8::AddGCEpilogueCallback(EpilogueCallback);
18477 CHECK_EQ(0, prologue_call_count);
18478 CHECK_EQ(0, epilogue_call_count);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018479 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018480 CHECK_EQ(1, prologue_call_count);
18481 CHECK_EQ(1, epilogue_call_count);
18482 v8::V8::AddGCPrologueCallback(PrologueCallbackSecond);
18483 v8::V8::AddGCEpilogueCallback(EpilogueCallbackSecond);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018484 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018485 CHECK_EQ(2, prologue_call_count);
18486 CHECK_EQ(2, epilogue_call_count);
18487 CHECK_EQ(1, prologue_call_count_second);
18488 CHECK_EQ(1, epilogue_call_count_second);
18489 v8::V8::RemoveGCPrologueCallback(PrologueCallback);
18490 v8::V8::RemoveGCEpilogueCallback(EpilogueCallback);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018491 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018492 CHECK_EQ(2, prologue_call_count);
18493 CHECK_EQ(2, epilogue_call_count);
18494 CHECK_EQ(2, prologue_call_count_second);
18495 CHECK_EQ(2, epilogue_call_count_second);
18496 v8::V8::RemoveGCPrologueCallback(PrologueCallbackSecond);
18497 v8::V8::RemoveGCEpilogueCallback(EpilogueCallbackSecond);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018498 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
18499 CHECK_EQ(2, prologue_call_count);
18500 CHECK_EQ(2, epilogue_call_count);
18501 CHECK_EQ(2, prologue_call_count_second);
18502 CHECK_EQ(2, epilogue_call_count_second);
18503}
18504
18505
18506TEST(GCCallbacks) {
18507 LocalContext context;
18508 v8::Isolate* isolate = context->GetIsolate();
18509 gc_callbacks_isolate = isolate;
18510 isolate->AddGCPrologueCallback(PrologueCallback);
18511 isolate->AddGCEpilogueCallback(EpilogueCallback);
18512 CHECK_EQ(0, prologue_call_count);
18513 CHECK_EQ(0, epilogue_call_count);
18514 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
18515 CHECK_EQ(1, prologue_call_count);
18516 CHECK_EQ(1, epilogue_call_count);
18517 isolate->AddGCPrologueCallback(PrologueCallbackSecond);
18518 isolate->AddGCEpilogueCallback(EpilogueCallbackSecond);
18519 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
18520 CHECK_EQ(2, prologue_call_count);
18521 CHECK_EQ(2, epilogue_call_count);
18522 CHECK_EQ(1, prologue_call_count_second);
18523 CHECK_EQ(1, epilogue_call_count_second);
18524 isolate->RemoveGCPrologueCallback(PrologueCallback);
18525 isolate->RemoveGCEpilogueCallback(EpilogueCallback);
18526 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
18527 CHECK_EQ(2, prologue_call_count);
18528 CHECK_EQ(2, epilogue_call_count);
18529 CHECK_EQ(2, prologue_call_count_second);
18530 CHECK_EQ(2, epilogue_call_count_second);
18531 isolate->RemoveGCPrologueCallback(PrologueCallbackSecond);
18532 isolate->RemoveGCEpilogueCallback(EpilogueCallbackSecond);
18533 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018534 CHECK_EQ(2, prologue_call_count);
18535 CHECK_EQ(2, epilogue_call_count);
18536 CHECK_EQ(2, prologue_call_count_second);
18537 CHECK_EQ(2, epilogue_call_count_second);
18538}
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018539
18540
18541THREADED_TEST(AddToJSFunctionResultCache) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018542 i::FLAG_stress_compaction = false;
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018543 i::FLAG_allow_natives_syntax = true;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018544 v8::HandleScope scope(CcTest::isolate());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018545
18546 LocalContext context;
18547
18548 const char* code =
18549 "(function() {"
18550 " var key0 = 'a';"
18551 " var key1 = 'b';"
18552 " var r0 = %_GetFromCache(0, key0);"
18553 " var r1 = %_GetFromCache(0, key1);"
18554 " var r0_ = %_GetFromCache(0, key0);"
18555 " if (r0 !== r0_)"
18556 " return 'Different results for ' + key0 + ': ' + r0 + ' vs. ' + r0_;"
18557 " var r1_ = %_GetFromCache(0, key1);"
18558 " if (r1 !== r1_)"
18559 " return 'Different results for ' + key1 + ': ' + r1 + ' vs. ' + r1_;"
18560 " return 'PASSED';"
18561 "})()";
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018562 CcTest::heap()->ClearJSFunctionResultCaches();
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018563 ExpectString(code, "PASSED");
18564}
18565
18566
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018567THREADED_TEST(FillJSFunctionResultCache) {
18568 i::FLAG_allow_natives_syntax = true;
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018569 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018570 v8::HandleScope scope(context->GetIsolate());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018571
18572 const char* code =
18573 "(function() {"
18574 " var k = 'a';"
18575 " var r = %_GetFromCache(0, k);"
18576 " for (var i = 0; i < 16; i++) {"
18577 " %_GetFromCache(0, 'a' + i);"
18578 " };"
18579 " if (r === %_GetFromCache(0, k))"
18580 " return 'FAILED: k0CacheSize is too small';"
18581 " return 'PASSED';"
18582 "})()";
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018583 CcTest::heap()->ClearJSFunctionResultCaches();
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018584 ExpectString(code, "PASSED");
18585}
18586
18587
18588THREADED_TEST(RoundRobinGetFromCache) {
18589 i::FLAG_allow_natives_syntax = true;
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018590 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018591 v8::HandleScope scope(context->GetIsolate());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018592
18593 const char* code =
18594 "(function() {"
18595 " var keys = [];"
18596 " for (var i = 0; i < 16; i++) keys.push(i);"
18597 " var values = [];"
18598 " for (var i = 0; i < 16; i++) values[i] = %_GetFromCache(0, keys[i]);"
18599 " for (var i = 0; i < 16; i++) {"
18600 " var v = %_GetFromCache(0, keys[i]);"
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000018601 " if (v.toString() !== values[i].toString())"
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018602 " return 'Wrong value for ' + "
18603 " keys[i] + ': ' + v + ' vs. ' + values[i];"
18604 " };"
18605 " return 'PASSED';"
18606 "})()";
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018607 CcTest::heap()->ClearJSFunctionResultCaches();
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018608 ExpectString(code, "PASSED");
18609}
18610
18611
18612THREADED_TEST(ReverseGetFromCache) {
18613 i::FLAG_allow_natives_syntax = true;
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018614 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018615 v8::HandleScope scope(context->GetIsolate());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018616
18617 const char* code =
18618 "(function() {"
18619 " var keys = [];"
18620 " for (var i = 0; i < 16; i++) keys.push(i);"
18621 " var values = [];"
18622 " for (var i = 0; i < 16; i++) values[i] = %_GetFromCache(0, keys[i]);"
18623 " for (var i = 15; i >= 16; i--) {"
18624 " var v = %_GetFromCache(0, keys[i]);"
18625 " if (v !== values[i])"
18626 " return 'Wrong value for ' + "
18627 " keys[i] + ': ' + v + ' vs. ' + values[i];"
18628 " };"
18629 " return 'PASSED';"
18630 "})()";
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018631 CcTest::heap()->ClearJSFunctionResultCaches();
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018632 ExpectString(code, "PASSED");
18633}
18634
18635
18636THREADED_TEST(TestEviction) {
18637 i::FLAG_allow_natives_syntax = true;
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018638 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018639 v8::HandleScope scope(context->GetIsolate());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018640
18641 const char* code =
18642 "(function() {"
18643 " for (var i = 0; i < 2*16; i++) {"
18644 " %_GetFromCache(0, 'a' + i);"
18645 " };"
18646 " return 'PASSED';"
18647 "})()";
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018648 CcTest::heap()->ClearJSFunctionResultCaches();
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018649 ExpectString(code, "PASSED");
18650}
lrn@chromium.org32d961d2010-06-30 09:09:34 +000018651
18652
18653THREADED_TEST(TwoByteStringInAsciiCons) {
18654 // See Chromium issue 47824.
lrn@chromium.org32d961d2010-06-30 09:09:34 +000018655 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018656 v8::HandleScope scope(context->GetIsolate());
18657
lrn@chromium.org32d961d2010-06-30 09:09:34 +000018658 const char* init_code =
18659 "var str1 = 'abelspendabel';"
18660 "var str2 = str1 + str1 + str1;"
18661 "str2;";
18662 Local<Value> result = CompileRun(init_code);
18663
ricow@chromium.orgddd545c2011-08-24 12:02:41 +000018664 Local<Value> indexof = CompileRun("str2.indexOf('els')");
18665 Local<Value> lastindexof = CompileRun("str2.lastIndexOf('dab')");
18666
lrn@chromium.org32d961d2010-06-30 09:09:34 +000018667 CHECK(result->IsString());
18668 i::Handle<i::String> string = v8::Utils::OpenHandle(String::Cast(*result));
18669 int length = string->length();
ulan@chromium.org8e8d8822012-11-23 14:36:46 +000018670 CHECK(string->IsOneByteRepresentation());
lrn@chromium.org32d961d2010-06-30 09:09:34 +000018671
18672 FlattenString(string);
18673 i::Handle<i::String> flat_string = FlattenGetString(string);
18674
ulan@chromium.org8e8d8822012-11-23 14:36:46 +000018675 CHECK(string->IsOneByteRepresentation());
18676 CHECK(flat_string->IsOneByteRepresentation());
lrn@chromium.org32d961d2010-06-30 09:09:34 +000018677
18678 // Create external resource.
18679 uint16_t* uc16_buffer = new uint16_t[length + 1];
18680
18681 i::String::WriteToFlat(*flat_string, uc16_buffer, 0, length);
18682 uc16_buffer[length] = 0;
18683
18684 TestResource resource(uc16_buffer);
18685
18686 flat_string->MakeExternal(&resource);
18687
18688 CHECK(flat_string->IsTwoByteRepresentation());
18689
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +000018690 // If the cons string has been short-circuited, skip the following checks.
18691 if (!string.is_identical_to(flat_string)) {
18692 // At this point, we should have a Cons string which is flat and ASCII,
18693 // with a first half that is a two-byte string (although it only contains
18694 // ASCII characters). This is a valid sequence of steps, and it can happen
18695 // in real pages.
18696 CHECK(string->IsOneByteRepresentation());
18697 i::ConsString* cons = i::ConsString::cast(*string);
18698 CHECK_EQ(0, cons->second()->length());
18699 CHECK(cons->first()->IsTwoByteRepresentation());
18700 }
lrn@chromium.org32d961d2010-06-30 09:09:34 +000018701
18702 // Check that some string operations work.
18703
18704 // Atom RegExp.
18705 Local<Value> reresult = CompileRun("str2.match(/abel/g).length;");
18706 CHECK_EQ(6, reresult->Int32Value());
18707
18708 // Nonatom RegExp.
18709 reresult = CompileRun("str2.match(/abe./g).length;");
18710 CHECK_EQ(6, reresult->Int32Value());
18711
18712 reresult = CompileRun("str2.search(/bel/g);");
18713 CHECK_EQ(1, reresult->Int32Value());
18714
18715 reresult = CompileRun("str2.search(/be./g);");
18716 CHECK_EQ(1, reresult->Int32Value());
18717
18718 ExpectTrue("/bel/g.test(str2);");
18719
18720 ExpectTrue("/be./g.test(str2);");
18721
18722 reresult = CompileRun("/bel/g.exec(str2);");
18723 CHECK(!reresult->IsNull());
18724
18725 reresult = CompileRun("/be./g.exec(str2);");
18726 CHECK(!reresult->IsNull());
18727
18728 ExpectString("str2.substring(2, 10);", "elspenda");
18729
18730 ExpectString("str2.substring(2, 20);", "elspendabelabelspe");
18731
18732 ExpectString("str2.charAt(2);", "e");
18733
ricow@chromium.orgddd545c2011-08-24 12:02:41 +000018734 ExpectObject("str2.indexOf('els');", indexof);
18735
18736 ExpectObject("str2.lastIndexOf('dab');", lastindexof);
18737
lrn@chromium.org32d961d2010-06-30 09:09:34 +000018738 reresult = CompileRun("str2.charCodeAt(2);");
18739 CHECK_EQ(static_cast<int32_t>('e'), reresult->Int32Value());
18740}
ager@chromium.orgea4f62e2010-08-16 16:28:43 +000018741
18742
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000018743TEST(ContainsOnlyOneByte) {
18744 v8::V8::Initialize();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018745 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000018746 v8::HandleScope scope(isolate);
18747 // Make a buffer long enough that it won't automatically be converted.
verwaest@chromium.org8a00e822013-06-10 15:11:22 +000018748 const int length = 512;
18749 // Ensure word aligned assignment.
18750 const int aligned_length = length*sizeof(uintptr_t)/sizeof(uint16_t);
18751 i::SmartArrayPointer<uintptr_t>
18752 aligned_contents(new uintptr_t[aligned_length]);
machenbach@chromium.orgafbdadc2013-12-09 16:12:18 +000018753 uint16_t* string_contents =
18754 reinterpret_cast<uint16_t*>(aligned_contents.get());
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000018755 // Set to contain only one byte.
18756 for (int i = 0; i < length-1; i++) {
18757 string_contents[i] = 0x41;
18758 }
18759 string_contents[length-1] = 0;
18760 // Simple case.
18761 Handle<String> string;
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000018762 string = String::NewExternal(isolate, new TestResource(string_contents));
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000018763 CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
18764 // Counter example.
verwaest@chromium.org8a00e822013-06-10 15:11:22 +000018765 string = String::NewFromTwoByte(isolate, string_contents);
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000018766 CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
18767 // Test left right and balanced cons strings.
18768 Handle<String> base = String::NewFromUtf8(isolate, "a");
18769 Handle<String> left = base;
18770 Handle<String> right = base;
18771 for (int i = 0; i < 1000; i++) {
18772 left = String::Concat(base, left);
18773 right = String::Concat(right, base);
18774 }
18775 Handle<String> balanced = String::Concat(left, base);
18776 balanced = String::Concat(balanced, right);
18777 Handle<String> cons_strings[] = {left, balanced, right};
18778 Handle<String> two_byte =
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000018779 String::NewExternal(isolate, new TestResource(string_contents));
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000018780 for (size_t i = 0; i < ARRAY_SIZE(cons_strings); i++) {
18781 // Base assumptions.
18782 string = cons_strings[i];
18783 CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
18784 // Test left and right concatentation.
18785 string = String::Concat(two_byte, cons_strings[i]);
18786 CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
18787 string = String::Concat(cons_strings[i], two_byte);
18788 CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
18789 }
verwaest@chromium.org8a00e822013-06-10 15:11:22 +000018790 // Set bits in different positions
18791 // for strings of different lengths and alignments.
18792 for (int alignment = 0; alignment < 7; alignment++) {
18793 for (int size = 2; alignment + size < length; size *= 2) {
18794 int zero_offset = size + alignment;
18795 string_contents[zero_offset] = 0;
18796 for (int i = 0; i < size; i++) {
18797 int shift = 8 + (i % 7);
18798 string_contents[alignment + i] = 1 << shift;
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000018799 string = String::NewExternal(
18800 isolate, new TestResource(string_contents + alignment));
verwaest@chromium.org8a00e822013-06-10 15:11:22 +000018801 CHECK_EQ(size, string->Length());
18802 CHECK(!string->ContainsOnlyOneByte());
18803 string_contents[alignment + i] = 0x41;
18804 }
18805 string_contents[zero_offset] = 0x41;
18806 }
18807 }
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000018808}
18809
18810
ager@chromium.orgea4f62e2010-08-16 16:28:43 +000018811// Failed access check callback that performs a GC on each invocation.
18812void FailedAccessCheckCallbackGC(Local<v8::Object> target,
18813 v8::AccessType type,
18814 Local<v8::Value> data) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018815 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.orgea4f62e2010-08-16 16:28:43 +000018816}
18817
18818
18819TEST(GCInFailedAccessCheckCallback) {
18820 // Install a failed access check callback that performs a GC on each
18821 // invocation. Then force the callback to be called from va
18822
18823 v8::V8::Initialize();
18824 v8::V8::SetFailedAccessCheckCallbackFunction(&FailedAccessCheckCallbackGC);
18825
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000018826 v8::Isolate* isolate = CcTest::isolate();
18827 v8::HandleScope scope(isolate);
ager@chromium.orgea4f62e2010-08-16 16:28:43 +000018828
18829 // Create an ObjectTemplate for global objects and install access
18830 // check callbacks that will block access.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000018831 v8::Handle<v8::ObjectTemplate> global_template =
18832 v8::ObjectTemplate::New(isolate);
ager@chromium.orgea4f62e2010-08-16 16:28:43 +000018833 global_template->SetAccessCheckCallbacks(NamedGetAccessBlocker,
18834 IndexedGetAccessBlocker,
18835 v8::Handle<v8::Value>(),
18836 false);
18837
18838 // Create a context and set an x property on it's global object.
18839 LocalContext context0(NULL, global_template);
18840 context0->Global()->Set(v8_str("x"), v8_num(42));
18841 v8::Handle<v8::Object> global0 = context0->Global();
18842
18843 // Create a context with a different security token so that the
18844 // failed access check callback will be called on each access.
18845 LocalContext context1(NULL, global_template);
18846 context1->Global()->Set(v8_str("other"), global0);
18847
18848 // Get property with failed access check.
18849 ExpectUndefined("other.x");
18850
18851 // Get element with failed access check.
18852 ExpectUndefined("other[0]");
18853
18854 // Set property with failed access check.
18855 v8::Handle<v8::Value> result = CompileRun("other.x = new Object()");
18856 CHECK(result->IsObject());
18857
18858 // Set element with failed access check.
18859 result = CompileRun("other[0] = new Object()");
18860 CHECK(result->IsObject());
18861
18862 // Get property attribute with failed access check.
18863 ExpectFalse("\'x\' in other");
18864
18865 // Get property attribute for element with failed access check.
18866 ExpectFalse("0 in other");
18867
18868 // Delete property.
18869 ExpectFalse("delete other.x");
18870
18871 // Delete element.
18872 CHECK_EQ(false, global0->Delete(0));
18873
18874 // DefineAccessor.
18875 CHECK_EQ(false,
18876 global0->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("x")));
18877
18878 // Define JavaScript accessor.
18879 ExpectUndefined("Object.prototype.__defineGetter__.call("
18880 " other, \'x\', function() { return 42; })");
18881
18882 // LookupAccessor.
18883 ExpectUndefined("Object.prototype.__lookupGetter__.call("
18884 " other, \'x\')");
18885
18886 // HasLocalElement.
18887 ExpectFalse("Object.prototype.hasOwnProperty.call(other, \'0\')");
18888
18889 CHECK_EQ(false, global0->HasRealIndexedProperty(0));
18890 CHECK_EQ(false, global0->HasRealNamedProperty(v8_str("x")));
18891 CHECK_EQ(false, global0->HasRealNamedCallbackProperty(v8_str("x")));
18892
18893 // Reset the failed access check callback so it does not influence
18894 // the other tests.
18895 v8::V8::SetFailedAccessCheckCallbackFunction(NULL);
18896}
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000018897
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000018898
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000018899TEST(IsolateNewDispose) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018900 v8::Isolate* current_isolate = CcTest::isolate();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000018901 v8::Isolate* isolate = v8::Isolate::New();
18902 CHECK(isolate != NULL);
18903 CHECK(!reinterpret_cast<i::Isolate*>(isolate)->IsDefaultIsolate());
18904 CHECK(current_isolate != isolate);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018905 CHECK(current_isolate == CcTest::isolate());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000018906
18907 v8::V8::SetFatalErrorHandler(StoringErrorCallback);
18908 last_location = last_message = NULL;
18909 isolate->Dispose();
18910 CHECK_EQ(last_location, NULL);
18911 CHECK_EQ(last_message, NULL);
18912}
18913
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000018914
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018915UNINITIALIZED_TEST(DisposeIsolateWhenInUse) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000018916 v8::Isolate* isolate = v8::Isolate::New();
18917 CHECK(isolate);
18918 isolate->Enter();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018919 v8::HandleScope scope(isolate);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018920 LocalContext context(isolate);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000018921 // Run something in this isolate.
18922 ExpectTrue("true");
18923 v8::V8::SetFatalErrorHandler(StoringErrorCallback);
18924 last_location = last_message = NULL;
18925 // Still entered, should fail.
18926 isolate->Dispose();
18927 CHECK_NE(last_location, NULL);
18928 CHECK_NE(last_message, NULL);
18929}
18930
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000018931
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000018932TEST(RunTwoIsolatesOnSingleThread) {
18933 // Run isolate 1.
18934 v8::Isolate* isolate1 = v8::Isolate::New();
18935 isolate1->Enter();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000018936 v8::Persistent<v8::Context> context1;
18937 {
18938 v8::HandleScope scope(isolate1);
18939 context1.Reset(isolate1, Context::New(isolate1));
18940 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000018941
18942 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018943 v8::HandleScope scope(isolate1);
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000018944 v8::Local<v8::Context> context =
18945 v8::Local<v8::Context>::New(isolate1, context1);
18946 v8::Context::Scope context_scope(context);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000018947 // Run something in new isolate.
18948 CompileRun("var foo = 'isolate 1';");
18949 ExpectString("function f() { return foo; }; f()", "isolate 1");
18950 }
18951
18952 // Run isolate 2.
18953 v8::Isolate* isolate2 = v8::Isolate::New();
18954 v8::Persistent<v8::Context> context2;
18955
18956 {
18957 v8::Isolate::Scope iscope(isolate2);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018958 v8::HandleScope scope(isolate2);
ulan@chromium.org57ff8812013-05-10 08:16:55 +000018959 context2.Reset(isolate2, Context::New(isolate2));
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000018960 v8::Local<v8::Context> context =
18961 v8::Local<v8::Context>::New(isolate2, context2);
18962 v8::Context::Scope context_scope(context);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000018963
18964 // Run something in new isolate.
18965 CompileRun("var foo = 'isolate 2';");
18966 ExpectString("function f() { return foo; }; f()", "isolate 2");
18967 }
18968
18969 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018970 v8::HandleScope scope(isolate1);
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000018971 v8::Local<v8::Context> context =
18972 v8::Local<v8::Context>::New(isolate1, context1);
18973 v8::Context::Scope context_scope(context);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000018974 // Now again in isolate 1
18975 ExpectString("function f() { return foo; }; f()", "isolate 1");
18976 }
18977
18978 isolate1->Exit();
18979
18980 // Run some stuff in default isolate.
ulan@chromium.org57ff8812013-05-10 08:16:55 +000018981 v8::Persistent<v8::Context> context_default;
18982 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018983 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000018984 v8::Isolate::Scope iscope(isolate);
18985 v8::HandleScope scope(isolate);
18986 context_default.Reset(isolate, Context::New(isolate));
18987 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000018988
18989 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018990 v8::HandleScope scope(CcTest::isolate());
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000018991 v8::Local<v8::Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018992 v8::Local<v8::Context>::New(CcTest::isolate(), context_default);
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000018993 v8::Context::Scope context_scope(context);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000018994 // Variables in other isolates should be not available, verify there
18995 // is an exception.
18996 ExpectTrue("function f() {"
18997 " try {"
18998 " foo;"
18999 " return false;"
19000 " } catch(e) {"
19001 " return true;"
19002 " }"
19003 "};"
19004 "var isDefaultIsolate = true;"
19005 "f()");
19006 }
19007
19008 isolate1->Enter();
19009
19010 {
19011 v8::Isolate::Scope iscope(isolate2);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019012 v8::HandleScope scope(isolate2);
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000019013 v8::Local<v8::Context> context =
19014 v8::Local<v8::Context>::New(isolate2, context2);
19015 v8::Context::Scope context_scope(context);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019016 ExpectString("function f() { return foo; }; f()", "isolate 2");
19017 }
19018
19019 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019020 v8::HandleScope scope(v8::Isolate::GetCurrent());
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000019021 v8::Local<v8::Context> context =
19022 v8::Local<v8::Context>::New(v8::Isolate::GetCurrent(), context1);
19023 v8::Context::Scope context_scope(context);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019024 ExpectString("function f() { return foo; }; f()", "isolate 1");
19025 }
19026
19027 {
19028 v8::Isolate::Scope iscope(isolate2);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000019029 context2.Reset();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019030 }
19031
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000019032 context1.Reset();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019033 isolate1->Exit();
19034
19035 v8::V8::SetFatalErrorHandler(StoringErrorCallback);
19036 last_location = last_message = NULL;
19037
19038 isolate1->Dispose();
19039 CHECK_EQ(last_location, NULL);
19040 CHECK_EQ(last_message, NULL);
19041
19042 isolate2->Dispose();
19043 CHECK_EQ(last_location, NULL);
19044 CHECK_EQ(last_message, NULL);
19045
19046 // Check that default isolate still runs.
19047 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019048 v8::HandleScope scope(CcTest::isolate());
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000019049 v8::Local<v8::Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019050 v8::Local<v8::Context>::New(CcTest::isolate(), context_default);
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000019051 v8::Context::Scope context_scope(context);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019052 ExpectTrue("function f() { return isDefaultIsolate; }; f()");
19053 }
19054}
19055
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019056
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019057static int CalcFibonacci(v8::Isolate* isolate, int limit) {
19058 v8::Isolate::Scope isolate_scope(isolate);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019059 v8::HandleScope scope(isolate);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019060 LocalContext context(isolate);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019061 i::ScopedVector<char> code(1024);
19062 i::OS::SNPrintF(code, "function fib(n) {"
19063 " if (n <= 2) return 1;"
19064 " return fib(n-1) + fib(n-2);"
19065 "}"
19066 "fib(%d)", limit);
19067 Local<Value> value = CompileRun(code.start());
19068 CHECK(value->IsNumber());
19069 return static_cast<int>(value->NumberValue());
19070}
19071
19072class IsolateThread : public v8::internal::Thread {
19073 public:
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000019074 IsolateThread(v8::Isolate* isolate, int fib_limit)
19075 : Thread("IsolateThread"),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019076 isolate_(isolate),
19077 fib_limit_(fib_limit),
19078 result_(0) { }
19079
19080 void Run() {
19081 result_ = CalcFibonacci(isolate_, fib_limit_);
19082 }
19083
19084 int result() { return result_; }
19085
19086 private:
19087 v8::Isolate* isolate_;
19088 int fib_limit_;
19089 int result_;
19090};
19091
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019092
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019093TEST(MultipleIsolatesOnIndividualThreads) {
19094 v8::Isolate* isolate1 = v8::Isolate::New();
19095 v8::Isolate* isolate2 = v8::Isolate::New();
19096
19097 IsolateThread thread1(isolate1, 21);
19098 IsolateThread thread2(isolate2, 12);
19099
19100 // Compute some fibonacci numbers on 3 threads in 3 isolates.
19101 thread1.Start();
19102 thread2.Start();
19103
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019104 int result1 = CalcFibonacci(CcTest::isolate(), 21);
19105 int result2 = CalcFibonacci(CcTest::isolate(), 12);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019106
19107 thread1.Join();
19108 thread2.Join();
19109
19110 // Compare results. The actual fibonacci numbers for 12 and 21 are taken
19111 // (I'm lazy!) from http://en.wikipedia.org/wiki/Fibonacci_number
19112 CHECK_EQ(result1, 10946);
19113 CHECK_EQ(result2, 144);
19114 CHECK_EQ(result1, thread1.result());
19115 CHECK_EQ(result2, thread2.result());
19116
19117 isolate1->Dispose();
19118 isolate2->Dispose();
19119}
19120
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019121
lrn@chromium.org1c092762011-05-09 09:42:16 +000019122TEST(IsolateDifferentContexts) {
19123 v8::Isolate* isolate = v8::Isolate::New();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000019124 Local<v8::Context> context;
lrn@chromium.org1c092762011-05-09 09:42:16 +000019125 {
19126 v8::Isolate::Scope isolate_scope(isolate);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019127 v8::HandleScope handle_scope(isolate);
ulan@chromium.org57ff8812013-05-10 08:16:55 +000019128 context = v8::Context::New(isolate);
lrn@chromium.org1c092762011-05-09 09:42:16 +000019129 v8::Context::Scope context_scope(context);
19130 Local<Value> v = CompileRun("2");
19131 CHECK(v->IsNumber());
19132 CHECK_EQ(2, static_cast<int>(v->NumberValue()));
19133 }
19134 {
19135 v8::Isolate::Scope isolate_scope(isolate);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019136 v8::HandleScope handle_scope(isolate);
ulan@chromium.org57ff8812013-05-10 08:16:55 +000019137 context = v8::Context::New(isolate);
lrn@chromium.org1c092762011-05-09 09:42:16 +000019138 v8::Context::Scope context_scope(context);
19139 Local<Value> v = CompileRun("22");
19140 CHECK(v->IsNumber());
19141 CHECK_EQ(22, static_cast<int>(v->NumberValue()));
19142 }
19143}
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019144
19145class InitDefaultIsolateThread : public v8::internal::Thread {
19146 public:
sgjesse@chromium.orge0599052011-03-25 07:34:35 +000019147 enum TestCase {
19148 IgnoreOOM,
19149 SetResourceConstraints,
19150 SetFatalHandler,
19151 SetCounterFunction,
19152 SetCreateHistogramFunction,
19153 SetAddHistogramSampleFunction
19154 };
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019155
19156 explicit InitDefaultIsolateThread(TestCase testCase)
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000019157 : Thread("InitDefaultIsolateThread"),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019158 testCase_(testCase),
19159 result_(false) { }
19160
19161 void Run() {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019162 v8::Isolate* isolate = v8::Isolate::New();
19163 isolate->Enter();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019164 switch (testCase_) {
19165 case IgnoreOOM:
19166 v8::V8::IgnoreOutOfMemoryException();
19167 break;
19168
19169 case SetResourceConstraints: {
19170 static const int K = 1024;
19171 v8::ResourceConstraints constraints;
19172 constraints.set_max_young_space_size(256 * K);
19173 constraints.set_max_old_space_size(4 * K * K);
machenbach@chromium.org7ff76072013-11-21 09:47:43 +000019174 v8::SetResourceConstraints(CcTest::isolate(), &constraints);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019175 break;
19176 }
19177
19178 case SetFatalHandler:
19179 v8::V8::SetFatalErrorHandler(NULL);
19180 break;
sgjesse@chromium.orge0599052011-03-25 07:34:35 +000019181
19182 case SetCounterFunction:
19183 v8::V8::SetCounterFunction(NULL);
19184 break;
19185
19186 case SetCreateHistogramFunction:
19187 v8::V8::SetCreateHistogramFunction(NULL);
19188 break;
19189
19190 case SetAddHistogramSampleFunction:
19191 v8::V8::SetAddHistogramSampleFunction(NULL);
19192 break;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019193 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019194 isolate->Exit();
19195 isolate->Dispose();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019196 result_ = true;
19197 }
19198
19199 bool result() { return result_; }
19200
19201 private:
19202 TestCase testCase_;
19203 bool result_;
19204};
19205
19206
19207static void InitializeTestHelper(InitDefaultIsolateThread::TestCase testCase) {
19208 InitDefaultIsolateThread thread(testCase);
19209 thread.Start();
19210 thread.Join();
19211 CHECK_EQ(thread.result(), true);
19212}
19213
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019214
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019215TEST(InitializeDefaultIsolateOnSecondaryThread1) {
19216 InitializeTestHelper(InitDefaultIsolateThread::IgnoreOOM);
19217}
19218
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019219
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019220TEST(InitializeDefaultIsolateOnSecondaryThread2) {
19221 InitializeTestHelper(InitDefaultIsolateThread::SetResourceConstraints);
19222}
19223
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019224
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019225TEST(InitializeDefaultIsolateOnSecondaryThread3) {
19226 InitializeTestHelper(InitDefaultIsolateThread::SetFatalHandler);
19227}
19228
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019229
sgjesse@chromium.orge0599052011-03-25 07:34:35 +000019230TEST(InitializeDefaultIsolateOnSecondaryThread4) {
19231 InitializeTestHelper(InitDefaultIsolateThread::SetCounterFunction);
19232}
19233
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019234
sgjesse@chromium.orge0599052011-03-25 07:34:35 +000019235TEST(InitializeDefaultIsolateOnSecondaryThread5) {
19236 InitializeTestHelper(InitDefaultIsolateThread::SetCreateHistogramFunction);
19237}
19238
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019239
sgjesse@chromium.orge0599052011-03-25 07:34:35 +000019240TEST(InitializeDefaultIsolateOnSecondaryThread6) {
19241 InitializeTestHelper(InitDefaultIsolateThread::SetAddHistogramSampleFunction);
19242}
19243
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019244
19245TEST(StringCheckMultipleContexts) {
19246 const char* code =
19247 "(function() { return \"a\".charAt(0); })()";
19248
19249 {
19250 // Run the code twice in the first context to initialize the call IC.
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019251 LocalContext context1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019252 v8::HandleScope scope(context1->GetIsolate());
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019253 ExpectString(code, "a");
19254 ExpectString(code, "a");
19255 }
19256
19257 {
19258 // Change the String.prototype in the second context and check
19259 // that the right function gets called.
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019260 LocalContext context2;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019261 v8::HandleScope scope(context2->GetIsolate());
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019262 CompileRun("String.prototype.charAt = function() { return \"not a\"; }");
19263 ExpectString(code, "not a");
19264 }
19265}
19266
19267
19268TEST(NumberCheckMultipleContexts) {
19269 const char* code =
19270 "(function() { return (42).toString(); })()";
19271
19272 {
19273 // Run the code twice in the first context to initialize the call IC.
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019274 LocalContext context1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019275 v8::HandleScope scope(context1->GetIsolate());
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019276 ExpectString(code, "42");
19277 ExpectString(code, "42");
19278 }
19279
19280 {
19281 // Change the Number.prototype in the second context and check
19282 // that the right function gets called.
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019283 LocalContext context2;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019284 v8::HandleScope scope(context2->GetIsolate());
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019285 CompileRun("Number.prototype.toString = function() { return \"not 42\"; }");
19286 ExpectString(code, "not 42");
19287 }
19288}
19289
19290
19291TEST(BooleanCheckMultipleContexts) {
19292 const char* code =
19293 "(function() { return true.toString(); })()";
19294
19295 {
19296 // Run the code twice in the first context to initialize the call IC.
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019297 LocalContext context1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019298 v8::HandleScope scope(context1->GetIsolate());
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019299 ExpectString(code, "true");
19300 ExpectString(code, "true");
19301 }
19302
19303 {
19304 // Change the Boolean.prototype in the second context and check
19305 // that the right function gets called.
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019306 LocalContext context2;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019307 v8::HandleScope scope(context2->GetIsolate());
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019308 CompileRun("Boolean.prototype.toString = function() { return \"\"; }");
19309 ExpectString(code, "");
19310 }
19311}
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019312
19313
19314TEST(DontDeleteCellLoadIC) {
19315 const char* function_code =
19316 "function readCell() { while (true) { return cell; } }";
19317
19318 {
19319 // Run the code twice in the first context to initialize the load
19320 // IC for a don't delete cell.
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019321 LocalContext context1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019322 v8::HandleScope scope(context1->GetIsolate());
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019323 CompileRun("var cell = \"first\";");
19324 ExpectBoolean("delete cell", false);
19325 CompileRun(function_code);
19326 ExpectString("readCell()", "first");
19327 ExpectString("readCell()", "first");
19328 }
19329
19330 {
19331 // Use a deletable cell in the second context.
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019332 LocalContext context2;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019333 v8::HandleScope scope(context2->GetIsolate());
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019334 CompileRun("cell = \"second\";");
19335 CompileRun(function_code);
19336 ExpectString("readCell()", "second");
19337 ExpectBoolean("delete cell", true);
19338 ExpectString("(function() {"
19339 " try {"
19340 " return readCell();"
19341 " } catch(e) {"
19342 " return e.toString();"
19343 " }"
19344 "})()",
19345 "ReferenceError: cell is not defined");
19346 CompileRun("cell = \"new_second\";");
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019347 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019348 ExpectString("readCell()", "new_second");
19349 ExpectString("readCell()", "new_second");
19350 }
19351}
19352
19353
19354TEST(DontDeleteCellLoadICForceDelete) {
19355 const char* function_code =
19356 "function readCell() { while (true) { return cell; } }";
19357
19358 // Run the code twice to initialize the load IC for a don't delete
19359 // cell.
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019360 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019361 v8::HandleScope scope(context->GetIsolate());
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019362 CompileRun("var cell = \"value\";");
19363 ExpectBoolean("delete cell", false);
19364 CompileRun(function_code);
19365 ExpectString("readCell()", "value");
19366 ExpectString("readCell()", "value");
19367
19368 // Delete the cell using the API and check the inlined code works
19369 // correctly.
19370 CHECK(context->Global()->ForceDelete(v8_str("cell")));
19371 ExpectString("(function() {"
19372 " try {"
19373 " return readCell();"
19374 " } catch(e) {"
19375 " return e.toString();"
19376 " }"
19377 "})()",
19378 "ReferenceError: cell is not defined");
19379}
19380
19381
19382TEST(DontDeleteCellLoadICAPI) {
19383 const char* function_code =
19384 "function readCell() { while (true) { return cell; } }";
19385
19386 // Run the code twice to initialize the load IC for a don't delete
19387 // cell created using the API.
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019388 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019389 v8::HandleScope scope(context->GetIsolate());
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019390 context->Global()->Set(v8_str("cell"), v8_str("value"), v8::DontDelete);
19391 ExpectBoolean("delete cell", false);
19392 CompileRun(function_code);
19393 ExpectString("readCell()", "value");
19394 ExpectString("readCell()", "value");
19395
19396 // Delete the cell using the API and check the inlined code works
19397 // correctly.
19398 CHECK(context->Global()->ForceDelete(v8_str("cell")));
19399 ExpectString("(function() {"
19400 " try {"
19401 " return readCell();"
19402 " } catch(e) {"
19403 " return e.toString();"
19404 " }"
19405 "})()",
19406 "ReferenceError: cell is not defined");
19407}
19408
19409
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000019410class Visitor42 : public v8::PersistentHandleVisitor {
19411 public:
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000019412 explicit Visitor42(v8::Persistent<v8::Object>* object)
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000019413 : counter_(0), object_(object) { }
19414
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000019415 virtual void VisitPersistentHandle(Persistent<Value>* value,
19416 uint16_t class_id) {
19417 if (class_id != 42) return;
19418 CHECK_EQ(42, value->WrapperClassId());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019419 v8::Isolate* isolate = CcTest::isolate();
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000019420 v8::HandleScope handle_scope(isolate);
19421 v8::Handle<v8::Value> handle = v8::Local<v8::Value>::New(isolate, *value);
19422 v8::Handle<v8::Value> object =
19423 v8::Local<v8::Object>::New(isolate, *object_);
19424 CHECK(handle->IsObject());
19425 CHECK_EQ(Handle<Object>::Cast(handle), object);
19426 ++counter_;
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000019427 }
19428
19429 int counter_;
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000019430 v8::Persistent<v8::Object>* object_;
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000019431};
19432
19433
19434TEST(PersistentHandleVisitor) {
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000019435 LocalContext context;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000019436 v8::Isolate* isolate = context->GetIsolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019437 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000019438 v8::Persistent<v8::Object> object(isolate, v8::Object::New(isolate));
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000019439 CHECK_EQ(0, object.WrapperClassId());
19440 object.SetWrapperClassId(42);
19441 CHECK_EQ(42, object.WrapperClassId());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000019442
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000019443 Visitor42 visitor(&object);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000019444 v8::V8::VisitHandlesWithClassIds(&visitor);
19445 CHECK_EQ(1, visitor.counter_);
19446
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000019447 object.Reset();
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000019448}
19449
19450
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000019451TEST(WrapperClassId) {
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000019452 LocalContext context;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000019453 v8::Isolate* isolate = context->GetIsolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019454 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000019455 v8::Persistent<v8::Object> object(isolate, v8::Object::New(isolate));
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000019456 CHECK_EQ(0, object.WrapperClassId());
19457 object.SetWrapperClassId(65535);
19458 CHECK_EQ(65535, object.WrapperClassId());
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000019459 object.Reset();
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000019460}
19461
19462
yangguo@chromium.org003650e2013-01-24 16:31:08 +000019463TEST(PersistentHandleInNewSpaceVisitor) {
yangguo@chromium.org003650e2013-01-24 16:31:08 +000019464 LocalContext context;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000019465 v8::Isolate* isolate = context->GetIsolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019466 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000019467 v8::Persistent<v8::Object> object1(isolate, v8::Object::New(isolate));
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000019468 CHECK_EQ(0, object1.WrapperClassId());
19469 object1.SetWrapperClassId(42);
19470 CHECK_EQ(42, object1.WrapperClassId());
yangguo@chromium.org003650e2013-01-24 16:31:08 +000019471
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019472 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
yangguo@chromium.org003650e2013-01-24 16:31:08 +000019473
ulan@chromium.org0f13e742014-01-03 15:51:11 +000019474 v8::Persistent<v8::Object> object2(isolate, v8::Object::New(isolate));
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000019475 CHECK_EQ(0, object2.WrapperClassId());
19476 object2.SetWrapperClassId(42);
19477 CHECK_EQ(42, object2.WrapperClassId());
yangguo@chromium.org003650e2013-01-24 16:31:08 +000019478
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000019479 Visitor42 visitor(&object2);
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000019480 v8::V8::VisitHandlesForPartialDependence(isolate, &visitor);
yangguo@chromium.org003650e2013-01-24 16:31:08 +000019481 CHECK_EQ(1, visitor.counter_);
19482
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000019483 object1.Reset();
19484 object2.Reset();
yangguo@chromium.org003650e2013-01-24 16:31:08 +000019485}
19486
19487
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019488TEST(RegExp) {
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019489 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019490 v8::HandleScope scope(context->GetIsolate());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019491
19492 v8::Handle<v8::RegExp> re = v8::RegExp::New(v8_str("foo"), v8::RegExp::kNone);
19493 CHECK(re->IsRegExp());
19494 CHECK(re->GetSource()->Equals(v8_str("foo")));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000019495 CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019496
19497 re = v8::RegExp::New(v8_str("bar"),
19498 static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
19499 v8::RegExp::kGlobal));
19500 CHECK(re->IsRegExp());
19501 CHECK(re->GetSource()->Equals(v8_str("bar")));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000019502 CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kGlobal,
19503 static_cast<int>(re->GetFlags()));
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019504
19505 re = v8::RegExp::New(v8_str("baz"),
19506 static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
19507 v8::RegExp::kMultiline));
19508 CHECK(re->IsRegExp());
19509 CHECK(re->GetSource()->Equals(v8_str("baz")));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000019510 CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
19511 static_cast<int>(re->GetFlags()));
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019512
19513 re = CompileRun("/quux/").As<v8::RegExp>();
19514 CHECK(re->IsRegExp());
19515 CHECK(re->GetSource()->Equals(v8_str("quux")));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000019516 CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019517
19518 re = CompileRun("/quux/gm").As<v8::RegExp>();
19519 CHECK(re->IsRegExp());
19520 CHECK(re->GetSource()->Equals(v8_str("quux")));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000019521 CHECK_EQ(v8::RegExp::kGlobal | v8::RegExp::kMultiline,
19522 static_cast<int>(re->GetFlags()));
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019523
19524 // Override the RegExp constructor and check the API constructor
19525 // still works.
19526 CompileRun("RegExp = function() {}");
19527
19528 re = v8::RegExp::New(v8_str("foobar"), v8::RegExp::kNone);
19529 CHECK(re->IsRegExp());
19530 CHECK(re->GetSource()->Equals(v8_str("foobar")));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000019531 CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019532
19533 re = v8::RegExp::New(v8_str("foobarbaz"),
19534 static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
19535 v8::RegExp::kMultiline));
19536 CHECK(re->IsRegExp());
19537 CHECK(re->GetSource()->Equals(v8_str("foobarbaz")));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000019538 CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
19539 static_cast<int>(re->GetFlags()));
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019540
19541 context->Global()->Set(v8_str("re"), re);
19542 ExpectTrue("re.test('FoobarbaZ')");
19543
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000019544 // RegExps are objects on which you can set properties.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000019545 re->Set(v8_str("property"), v8::Integer::New(context->GetIsolate(), 32));
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000019546 v8::Handle<v8::Value> value(CompileRun("re.property"));
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000019547 CHECK_EQ(32, value->Int32Value());
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000019548
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019549 v8::TryCatch try_catch;
19550 re = v8::RegExp::New(v8_str("foo["), v8::RegExp::kNone);
19551 CHECK(re.IsEmpty());
19552 CHECK(try_catch.HasCaught());
19553 context->Global()->Set(v8_str("ex"), try_catch.Exception());
19554 ExpectTrue("ex instanceof SyntaxError");
19555}
19556
19557
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000019558THREADED_TEST(Equals) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000019559 LocalContext localContext;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019560 v8::HandleScope handleScope(localContext->GetIsolate());
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000019561
19562 v8::Handle<v8::Object> globalProxy = localContext->Global();
19563 v8::Handle<Value> global = globalProxy->GetPrototype();
19564
19565 CHECK(global->StrictEquals(global));
19566 CHECK(!global->StrictEquals(globalProxy));
19567 CHECK(!globalProxy->StrictEquals(global));
19568 CHECK(globalProxy->StrictEquals(globalProxy));
19569
19570 CHECK(global->Equals(global));
19571 CHECK(!global->Equals(globalProxy));
19572 CHECK(!globalProxy->Equals(global));
19573 CHECK(globalProxy->Equals(globalProxy));
19574}
19575
19576
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019577static void Getter(v8::Local<v8::String> property,
19578 const v8::PropertyCallbackInfo<v8::Value>& info ) {
19579 info.GetReturnValue().Set(v8_str("42!"));
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019580}
19581
19582
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019583static void Enumerator(const v8::PropertyCallbackInfo<v8::Array>& info) {
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000019584 v8::Handle<v8::Array> result = v8::Array::New(info.GetIsolate());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019585 result->Set(0, v8_str("universalAnswer"));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019586 info.GetReturnValue().Set(result);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019587}
19588
19589
19590TEST(NamedEnumeratorAndForIn) {
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019591 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000019592 v8::Isolate* isolate = context->GetIsolate();
19593 v8::HandleScope handle_scope(isolate);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019594 v8::Context::Scope context_scope(context.local());
19595
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000019596 v8::Handle<v8::ObjectTemplate> tmpl = v8::ObjectTemplate::New(isolate);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019597 tmpl->SetNamedPropertyHandler(Getter, NULL, NULL, NULL, Enumerator);
19598 context->Global()->Set(v8_str("o"), tmpl->NewInstance());
19599 v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
19600 "var result = []; for (var k in o) result.push(k); result"));
19601 CHECK_EQ(1, result->Length());
19602 CHECK_EQ(v8_str("universalAnswer"), result->Get(0));
19603}
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +000019604
19605
19606TEST(DefinePropertyPostDetach) {
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +000019607 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019608 v8::HandleScope scope(context->GetIsolate());
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +000019609 v8::Handle<v8::Object> proxy = context->Global();
19610 v8::Handle<v8::Function> define_property =
19611 CompileRun("(function() {"
19612 " Object.defineProperty("
19613 " this,"
19614 " 1,"
19615 " { configurable: true, enumerable: true, value: 3 });"
19616 "})").As<Function>();
19617 context->DetachGlobal();
19618 define_property->Call(proxy, 0, NULL);
19619}
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000019620
19621
19622static void InstallContextId(v8::Handle<Context> context, int id) {
19623 Context::Scope scope(context);
19624 CompileRun("Object.prototype").As<Object>()->
ulan@chromium.org0f13e742014-01-03 15:51:11 +000019625 Set(v8_str("context_id"), v8::Integer::New(context->GetIsolate(), id));
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000019626}
19627
19628
19629static void CheckContextId(v8::Handle<Object> object, int expected) {
19630 CHECK_EQ(expected, object->Get(v8_str("context_id"))->Int32Value());
19631}
19632
19633
19634THREADED_TEST(CreationContext) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000019635 v8::Isolate* isolate = CcTest::isolate();
19636 HandleScope handle_scope(isolate);
19637 Handle<Context> context1 = Context::New(isolate);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000019638 InstallContextId(context1, 1);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000019639 Handle<Context> context2 = Context::New(isolate);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000019640 InstallContextId(context2, 2);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000019641 Handle<Context> context3 = Context::New(isolate);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000019642 InstallContextId(context3, 3);
19643
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000019644 Local<v8::FunctionTemplate> tmpl = v8::FunctionTemplate::New(isolate);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000019645
19646 Local<Object> object1;
19647 Local<Function> func1;
19648 {
19649 Context::Scope scope(context1);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000019650 object1 = Object::New(isolate);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000019651 func1 = tmpl->GetFunction();
19652 }
19653
19654 Local<Object> object2;
19655 Local<Function> func2;
19656 {
19657 Context::Scope scope(context2);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000019658 object2 = Object::New(isolate);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000019659 func2 = tmpl->GetFunction();
19660 }
19661
19662 Local<Object> instance1;
19663 Local<Object> instance2;
19664
19665 {
19666 Context::Scope scope(context3);
19667 instance1 = func1->NewInstance();
19668 instance2 = func2->NewInstance();
19669 }
19670
19671 CHECK(object1->CreationContext() == context1);
19672 CheckContextId(object1, 1);
19673 CHECK(func1->CreationContext() == context1);
19674 CheckContextId(func1, 1);
19675 CHECK(instance1->CreationContext() == context1);
19676 CheckContextId(instance1, 1);
19677 CHECK(object2->CreationContext() == context2);
19678 CheckContextId(object2, 2);
19679 CHECK(func2->CreationContext() == context2);
19680 CheckContextId(func2, 2);
19681 CHECK(instance2->CreationContext() == context2);
19682 CheckContextId(instance2, 2);
19683
19684 {
19685 Context::Scope scope(context1);
19686 CHECK(object1->CreationContext() == context1);
19687 CheckContextId(object1, 1);
19688 CHECK(func1->CreationContext() == context1);
19689 CheckContextId(func1, 1);
19690 CHECK(instance1->CreationContext() == context1);
19691 CheckContextId(instance1, 1);
19692 CHECK(object2->CreationContext() == context2);
19693 CheckContextId(object2, 2);
19694 CHECK(func2->CreationContext() == context2);
19695 CheckContextId(func2, 2);
19696 CHECK(instance2->CreationContext() == context2);
19697 CheckContextId(instance2, 2);
19698 }
19699
19700 {
19701 Context::Scope scope(context2);
19702 CHECK(object1->CreationContext() == context1);
19703 CheckContextId(object1, 1);
19704 CHECK(func1->CreationContext() == context1);
19705 CheckContextId(func1, 1);
19706 CHECK(instance1->CreationContext() == context1);
19707 CheckContextId(instance1, 1);
19708 CHECK(object2->CreationContext() == context2);
19709 CheckContextId(object2, 2);
19710 CHECK(func2->CreationContext() == context2);
19711 CheckContextId(func2, 2);
19712 CHECK(instance2->CreationContext() == context2);
19713 CheckContextId(instance2, 2);
19714 }
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000019715}
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019716
19717
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +000019718THREADED_TEST(CreationContextOfJsFunction) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019719 HandleScope handle_scope(CcTest::isolate());
19720 Handle<Context> context = Context::New(CcTest::isolate());
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +000019721 InstallContextId(context, 1);
19722
19723 Local<Object> function;
19724 {
19725 Context::Scope scope(context);
19726 function = CompileRun("function foo() {}; foo").As<Object>();
19727 }
19728
19729 CHECK(function->CreationContext() == context);
19730 CheckContextId(function, 1);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +000019731}
19732
19733
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019734void HasOwnPropertyIndexedPropertyGetter(
19735 uint32_t index,
19736 const v8::PropertyCallbackInfo<v8::Value>& info) {
19737 if (index == 42) info.GetReturnValue().Set(v8_str("yes"));
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019738}
19739
19740
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019741void HasOwnPropertyNamedPropertyGetter(
19742 Local<String> property,
19743 const v8::PropertyCallbackInfo<v8::Value>& info) {
19744 if (property->Equals(v8_str("foo"))) info.GetReturnValue().Set(v8_str("yes"));
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019745}
19746
19747
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019748void HasOwnPropertyIndexedPropertyQuery(
19749 uint32_t index, const v8::PropertyCallbackInfo<v8::Integer>& info) {
19750 if (index == 42) info.GetReturnValue().Set(1);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019751}
19752
19753
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019754void HasOwnPropertyNamedPropertyQuery(
19755 Local<String> property,
19756 const v8::PropertyCallbackInfo<v8::Integer>& info) {
19757 if (property->Equals(v8_str("foo"))) info.GetReturnValue().Set(1);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019758}
19759
19760
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019761void HasOwnPropertyNamedPropertyQuery2(
19762 Local<String> property,
19763 const v8::PropertyCallbackInfo<v8::Integer>& info) {
19764 if (property->Equals(v8_str("bar"))) info.GetReturnValue().Set(1);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019765}
19766
19767
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019768void HasOwnPropertyAccessorGetter(
19769 Local<String> property,
19770 const v8::PropertyCallbackInfo<v8::Value>& info) {
19771 info.GetReturnValue().Set(v8_str("yes"));
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019772}
19773
19774
19775TEST(HasOwnProperty) {
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019776 LocalContext env;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000019777 v8::Isolate* isolate = env->GetIsolate();
19778 v8::HandleScope scope(isolate);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019779 { // Check normal properties and defined getters.
19780 Handle<Value> value = CompileRun(
19781 "function Foo() {"
19782 " this.foo = 11;"
19783 " this.__defineGetter__('baz', function() { return 1; });"
19784 "};"
19785 "function Bar() { "
19786 " this.bar = 13;"
19787 " this.__defineGetter__('bla', function() { return 2; });"
19788 "};"
19789 "Bar.prototype = new Foo();"
19790 "new Bar();");
19791 CHECK(value->IsObject());
19792 Handle<Object> object = value->ToObject();
19793 CHECK(object->Has(v8_str("foo")));
19794 CHECK(!object->HasOwnProperty(v8_str("foo")));
19795 CHECK(object->HasOwnProperty(v8_str("bar")));
19796 CHECK(object->Has(v8_str("baz")));
19797 CHECK(!object->HasOwnProperty(v8_str("baz")));
19798 CHECK(object->HasOwnProperty(v8_str("bla")));
19799 }
19800 { // Check named getter interceptors.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000019801 Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019802 templ->SetNamedPropertyHandler(HasOwnPropertyNamedPropertyGetter);
19803 Handle<Object> instance = templ->NewInstance();
19804 CHECK(!instance->HasOwnProperty(v8_str("42")));
19805 CHECK(instance->HasOwnProperty(v8_str("foo")));
19806 CHECK(!instance->HasOwnProperty(v8_str("bar")));
19807 }
19808 { // Check indexed getter interceptors.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000019809 Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019810 templ->SetIndexedPropertyHandler(HasOwnPropertyIndexedPropertyGetter);
19811 Handle<Object> instance = templ->NewInstance();
19812 CHECK(instance->HasOwnProperty(v8_str("42")));
19813 CHECK(!instance->HasOwnProperty(v8_str("43")));
19814 CHECK(!instance->HasOwnProperty(v8_str("foo")));
19815 }
19816 { // Check named query interceptors.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000019817 Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019818 templ->SetNamedPropertyHandler(0, 0, HasOwnPropertyNamedPropertyQuery);
19819 Handle<Object> instance = templ->NewInstance();
19820 CHECK(instance->HasOwnProperty(v8_str("foo")));
19821 CHECK(!instance->HasOwnProperty(v8_str("bar")));
19822 }
19823 { // Check indexed query interceptors.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000019824 Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019825 templ->SetIndexedPropertyHandler(0, 0, HasOwnPropertyIndexedPropertyQuery);
19826 Handle<Object> instance = templ->NewInstance();
19827 CHECK(instance->HasOwnProperty(v8_str("42")));
19828 CHECK(!instance->HasOwnProperty(v8_str("41")));
19829 }
19830 { // Check callbacks.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000019831 Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019832 templ->SetAccessor(v8_str("foo"), HasOwnPropertyAccessorGetter);
19833 Handle<Object> instance = templ->NewInstance();
19834 CHECK(instance->HasOwnProperty(v8_str("foo")));
19835 CHECK(!instance->HasOwnProperty(v8_str("bar")));
19836 }
19837 { // Check that query wins on disagreement.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000019838 Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019839 templ->SetNamedPropertyHandler(HasOwnPropertyNamedPropertyGetter,
19840 0,
19841 HasOwnPropertyNamedPropertyQuery2);
19842 Handle<Object> instance = templ->NewInstance();
19843 CHECK(!instance->HasOwnProperty(v8_str("foo")));
19844 CHECK(instance->HasOwnProperty(v8_str("bar")));
19845 }
19846}
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000019847
19848
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +000019849TEST(IndexedInterceptorWithStringProto) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000019850 v8::Isolate* isolate = CcTest::isolate();
19851 v8::HandleScope scope(isolate);
19852 Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +000019853 templ->SetIndexedPropertyHandler(NULL,
19854 NULL,
19855 HasOwnPropertyIndexedPropertyQuery);
19856 LocalContext context;
19857 context->Global()->Set(v8_str("obj"), templ->NewInstance());
19858 CompileRun("var s = new String('foobar'); obj.__proto__ = s;");
19859 // These should be intercepted.
19860 CHECK(CompileRun("42 in obj")->BooleanValue());
19861 CHECK(CompileRun("'42' in obj")->BooleanValue());
19862 // These should fall through to the String prototype.
19863 CHECK(CompileRun("0 in obj")->BooleanValue());
19864 CHECK(CompileRun("'0' in obj")->BooleanValue());
19865 // And these should both fail.
19866 CHECK(!CompileRun("32 in obj")->BooleanValue());
19867 CHECK(!CompileRun("'32' in obj")->BooleanValue());
19868}
19869
19870
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000019871void CheckCodeGenerationAllowed() {
19872 Handle<Value> result = CompileRun("eval('42')");
19873 CHECK_EQ(42, result->Int32Value());
19874 result = CompileRun("(function(e) { return e('42'); })(eval)");
19875 CHECK_EQ(42, result->Int32Value());
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000019876 result = CompileRun("var f = new Function('return 42'); f()");
19877 CHECK_EQ(42, result->Int32Value());
19878}
19879
19880
19881void CheckCodeGenerationDisallowed() {
19882 TryCatch try_catch;
19883
19884 Handle<Value> result = CompileRun("eval('42')");
19885 CHECK(result.IsEmpty());
19886 CHECK(try_catch.HasCaught());
19887 try_catch.Reset();
19888
19889 result = CompileRun("(function(e) { return e('42'); })(eval)");
19890 CHECK(result.IsEmpty());
19891 CHECK(try_catch.HasCaught());
19892 try_catch.Reset();
19893
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000019894 result = CompileRun("var f = new Function('return 42'); f()");
19895 CHECK(result.IsEmpty());
19896 CHECK(try_catch.HasCaught());
19897}
19898
19899
19900bool CodeGenerationAllowed(Local<Context> context) {
19901 ApiTestFuzzer::Fuzz();
19902 return true;
19903}
19904
19905
19906bool CodeGenerationDisallowed(Local<Context> context) {
19907 ApiTestFuzzer::Fuzz();
19908 return false;
19909}
19910
19911
19912THREADED_TEST(AllowCodeGenFromStrings) {
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000019913 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019914 v8::HandleScope scope(context->GetIsolate());
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000019915
ager@chromium.orgea91cc52011-05-23 06:06:11 +000019916 // eval and the Function constructor allowed by default.
jkummerow@chromium.org1145ef82012-02-02 16:21:15 +000019917 CHECK(context->IsCodeGenerationFromStringsAllowed());
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000019918 CheckCodeGenerationAllowed();
19919
ager@chromium.orgea91cc52011-05-23 06:06:11 +000019920 // Disallow eval and the Function constructor.
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000019921 context->AllowCodeGenerationFromStrings(false);
jkummerow@chromium.org1145ef82012-02-02 16:21:15 +000019922 CHECK(!context->IsCodeGenerationFromStringsAllowed());
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000019923 CheckCodeGenerationDisallowed();
19924
19925 // Allow again.
19926 context->AllowCodeGenerationFromStrings(true);
19927 CheckCodeGenerationAllowed();
19928
19929 // Disallow but setting a global callback that will allow the calls.
19930 context->AllowCodeGenerationFromStrings(false);
19931 V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationAllowed);
jkummerow@chromium.org1145ef82012-02-02 16:21:15 +000019932 CHECK(!context->IsCodeGenerationFromStringsAllowed());
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000019933 CheckCodeGenerationAllowed();
19934
19935 // Set a callback that disallows the code generation.
19936 V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationDisallowed);
jkummerow@chromium.org1145ef82012-02-02 16:21:15 +000019937 CHECK(!context->IsCodeGenerationFromStringsAllowed());
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000019938 CheckCodeGenerationDisallowed();
19939}
lrn@chromium.org1c092762011-05-09 09:42:16 +000019940
19941
ulan@chromium.org56c14af2012-09-20 12:51:09 +000019942TEST(SetErrorMessageForCodeGenFromStrings) {
ulan@chromium.org56c14af2012-09-20 12:51:09 +000019943 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019944 v8::HandleScope scope(context->GetIsolate());
ulan@chromium.org56c14af2012-09-20 12:51:09 +000019945 TryCatch try_catch;
19946
19947 Handle<String> message = v8_str("Message") ;
19948 Handle<String> expected_message = v8_str("Uncaught EvalError: Message");
19949 V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationDisallowed);
19950 context->AllowCodeGenerationFromStrings(false);
19951 context->SetErrorMessageForCodeGenerationFromStrings(message);
19952 Handle<Value> result = CompileRun("eval('42')");
19953 CHECK(result.IsEmpty());
19954 CHECK(try_catch.HasCaught());
19955 Handle<String> actual_message = try_catch.Message()->Get();
19956 CHECK(expected_message->Equals(actual_message));
19957}
19958
19959
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019960static void NonObjectThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
lrn@chromium.org1c092762011-05-09 09:42:16 +000019961}
19962
19963
19964THREADED_TEST(CallAPIFunctionOnNonObject) {
lrn@chromium.org1c092762011-05-09 09:42:16 +000019965 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000019966 v8::Isolate* isolate = context->GetIsolate();
19967 v8::HandleScope scope(isolate);
19968 Handle<FunctionTemplate> templ =
19969 v8::FunctionTemplate::New(isolate, NonObjectThis);
lrn@chromium.org1c092762011-05-09 09:42:16 +000019970 Handle<Function> function = templ->GetFunction();
19971 context->Global()->Set(v8_str("f"), function);
19972 TryCatch try_catch;
19973 CompileRun("f.call(2)");
lrn@chromium.org1c092762011-05-09 09:42:16 +000019974}
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000019975
19976
19977// Regression test for issue 1470.
19978THREADED_TEST(ReadOnlyIndexedProperties) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000019979 v8::Isolate* isolate = CcTest::isolate();
19980 v8::HandleScope scope(isolate);
19981 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000019982
19983 LocalContext context;
19984 Local<v8::Object> obj = templ->NewInstance();
19985 context->Global()->Set(v8_str("obj"), obj);
19986 obj->Set(v8_str("1"), v8_str("DONT_CHANGE"), v8::ReadOnly);
19987 obj->Set(v8_str("1"), v8_str("foobar"));
19988 CHECK_EQ(v8_str("DONT_CHANGE"), obj->Get(v8_str("1")));
19989 obj->Set(v8_num(2), v8_str("DONT_CHANGE"), v8::ReadOnly);
19990 obj->Set(v8_num(2), v8_str("foobar"));
19991 CHECK_EQ(v8_str("DONT_CHANGE"), obj->Get(v8_num(2)));
19992
19993 // Test non-smi case.
19994 obj->Set(v8_str("2000000000"), v8_str("DONT_CHANGE"), v8::ReadOnly);
19995 obj->Set(v8_str("2000000000"), v8_str("foobar"));
19996 CHECK_EQ(v8_str("DONT_CHANGE"), obj->Get(v8_str("2000000000")));
19997}
ricow@chromium.org4f693d62011-07-04 14:01:31 +000019998
19999
20000THREADED_TEST(Regress1516) {
ricow@chromium.org4f693d62011-07-04 14:01:31 +000020001 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020002 v8::HandleScope scope(context->GetIsolate());
20003
20004 { v8::HandleScope temp_scope(context->GetIsolate());
ricow@chromium.org4f693d62011-07-04 14:01:31 +000020005 CompileRun("({'a': 0})");
20006 }
20007
20008 int elements;
20009 { i::MapCache* map_cache =
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020010 i::MapCache::cast(CcTest::i_isolate()->context()->map_cache());
ricow@chromium.org4f693d62011-07-04 14:01:31 +000020011 elements = map_cache->NumberOfElements();
20012 CHECK_LE(1, elements);
20013 }
20014
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020015 CcTest::heap()->CollectAllGarbage(
yangguo@chromium.orgd2899aa2012-06-21 11:16:20 +000020016 i::Heap::kAbortIncrementalMarkingMask);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020017 { i::Object* raw_map_cache = CcTest::i_isolate()->context()->map_cache();
20018 if (raw_map_cache != CcTest::heap()->undefined_value()) {
ricow@chromium.org4f693d62011-07-04 14:01:31 +000020019 i::MapCache* map_cache = i::MapCache::cast(raw_map_cache);
20020 CHECK_GT(elements, map_cache->NumberOfElements());
20021 }
20022 }
20023}
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020024
20025
20026static bool BlockProtoNamedSecurityTestCallback(Local<v8::Object> global,
20027 Local<Value> name,
20028 v8::AccessType type,
20029 Local<Value> data) {
20030 // Only block read access to __proto__.
20031 if (type == v8::ACCESS_GET &&
20032 name->IsString() &&
20033 name->ToString()->Length() == 9 &&
20034 name->ToString()->Utf8Length() == 9) {
20035 char buffer[10];
20036 CHECK_EQ(10, name->ToString()->WriteUtf8(buffer));
20037 return strncmp(buffer, "__proto__", 9) != 0;
20038 }
20039
20040 return true;
20041}
20042
20043
20044THREADED_TEST(Regress93759) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020045 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000020046 HandleScope scope(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020047
20048 // Template for object with security check.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000020049 Local<ObjectTemplate> no_proto_template = v8::ObjectTemplate::New(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020050 // We don't do indexing, so any callback can be used for that.
20051 no_proto_template->SetAccessCheckCallbacks(
20052 BlockProtoNamedSecurityTestCallback,
20053 IndexedSecurityTestCallback);
20054
20055 // Templates for objects with hidden prototypes and possibly security check.
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000020056 Local<FunctionTemplate> hidden_proto_template =
20057 v8::FunctionTemplate::New(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020058 hidden_proto_template->SetHiddenPrototype(true);
20059
20060 Local<FunctionTemplate> protected_hidden_proto_template =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000020061 v8::FunctionTemplate::New(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020062 protected_hidden_proto_template->InstanceTemplate()->SetAccessCheckCallbacks(
20063 BlockProtoNamedSecurityTestCallback,
20064 IndexedSecurityTestCallback);
20065 protected_hidden_proto_template->SetHiddenPrototype(true);
20066
20067 // Context for "foreign" objects used in test.
ulan@chromium.org57ff8812013-05-10 08:16:55 +000020068 Local<Context> context = v8::Context::New(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020069 context->Enter();
20070
20071 // Plain object, no security check.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000020072 Local<Object> simple_object = Object::New(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020073
20074 // Object with explicit security check.
20075 Local<Object> protected_object =
20076 no_proto_template->NewInstance();
20077
20078 // JSGlobalProxy object, always have security check.
20079 Local<Object> proxy_object =
20080 context->Global();
20081
20082 // Global object, the prototype of proxy_object. No security checks.
20083 Local<Object> global_object =
20084 proxy_object->GetPrototype()->ToObject();
20085
20086 // Hidden prototype without security check.
20087 Local<Object> hidden_prototype =
20088 hidden_proto_template->GetFunction()->NewInstance();
20089 Local<Object> object_with_hidden =
ulan@chromium.org0f13e742014-01-03 15:51:11 +000020090 Object::New(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020091 object_with_hidden->SetPrototype(hidden_prototype);
20092
20093 // Hidden prototype with security check on the hidden prototype.
20094 Local<Object> protected_hidden_prototype =
20095 protected_hidden_proto_template->GetFunction()->NewInstance();
20096 Local<Object> object_with_protected_hidden =
ulan@chromium.org0f13e742014-01-03 15:51:11 +000020097 Object::New(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020098 object_with_protected_hidden->SetPrototype(protected_hidden_prototype);
20099
20100 context->Exit();
20101
20102 // Template for object for second context. Values to test are put on it as
20103 // properties.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000020104 Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020105 global_template->Set(v8_str("simple"), simple_object);
20106 global_template->Set(v8_str("protected"), protected_object);
20107 global_template->Set(v8_str("global"), global_object);
20108 global_template->Set(v8_str("proxy"), proxy_object);
20109 global_template->Set(v8_str("hidden"), object_with_hidden);
20110 global_template->Set(v8_str("phidden"), object_with_protected_hidden);
20111
20112 LocalContext context2(NULL, global_template);
20113
20114 Local<Value> result1 = CompileRun("Object.getPrototypeOf(simple)");
20115 CHECK(result1->Equals(simple_object->GetPrototype()));
20116
20117 Local<Value> result2 = CompileRun("Object.getPrototypeOf(protected)");
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000020118 CHECK(result2->Equals(Undefined(isolate)));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020119
20120 Local<Value> result3 = CompileRun("Object.getPrototypeOf(global)");
20121 CHECK(result3->Equals(global_object->GetPrototype()));
20122
20123 Local<Value> result4 = CompileRun("Object.getPrototypeOf(proxy)");
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000020124 CHECK(result4->Equals(Undefined(isolate)));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020125
20126 Local<Value> result5 = CompileRun("Object.getPrototypeOf(hidden)");
20127 CHECK(result5->Equals(
20128 object_with_hidden->GetPrototype()->ToObject()->GetPrototype()));
20129
20130 Local<Value> result6 = CompileRun("Object.getPrototypeOf(phidden)");
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000020131 CHECK(result6->Equals(Undefined(isolate)));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020132}
20133
20134
jkummerow@chromium.org212d9642012-05-11 15:02:09 +000020135THREADED_TEST(Regress125988) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020136 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000020137 Handle<FunctionTemplate> intercept = FunctionTemplate::New(CcTest::isolate());
jkummerow@chromium.org212d9642012-05-11 15:02:09 +000020138 AddInterceptor(intercept, EmptyInterceptorGetter, EmptyInterceptorSetter);
20139 LocalContext env;
20140 env->Global()->Set(v8_str("Intercept"), intercept->GetFunction());
20141 CompileRun("var a = new Object();"
20142 "var b = new Intercept();"
20143 "var c = new Object();"
20144 "c.__proto__ = b;"
20145 "b.__proto__ = a;"
20146 "a.x = 23;"
20147 "for (var i = 0; i < 3; i++) c.x;");
20148 ExpectBoolean("c.hasOwnProperty('x')", false);
20149 ExpectInt32("c.x", 23);
20150 CompileRun("a.y = 42;"
20151 "for (var i = 0; i < 3; i++) c.x;");
20152 ExpectBoolean("c.hasOwnProperty('x')", false);
20153 ExpectInt32("c.x", 23);
20154 ExpectBoolean("c.hasOwnProperty('y')", false);
20155 ExpectInt32("c.y", 42);
20156}
20157
20158
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020159static void TestReceiver(Local<Value> expected_result,
20160 Local<Value> expected_receiver,
20161 const char* code) {
20162 Local<Value> result = CompileRun(code);
20163 CHECK(result->IsObject());
20164 CHECK(expected_receiver->Equals(result->ToObject()->Get(1)));
20165 CHECK(expected_result->Equals(result->ToObject()->Get(0)));
20166}
20167
20168
20169THREADED_TEST(ForeignFunctionReceiver) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020170 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000020171 HandleScope scope(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020172
20173 // Create two contexts with different "id" properties ('i' and 'o').
20174 // Call a function both from its own context and from a the foreign
20175 // context, and see what "this" is bound to (returning both "this"
20176 // and "this.id" for comparison).
20177
ulan@chromium.org57ff8812013-05-10 08:16:55 +000020178 Local<Context> foreign_context = v8::Context::New(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020179 foreign_context->Enter();
20180 Local<Value> foreign_function =
20181 CompileRun("function func() { return { 0: this.id, "
20182 " 1: this, "
20183 " toString: function() { "
20184 " return this[0];"
20185 " }"
20186 " };"
20187 "}"
20188 "var id = 'i';"
20189 "func;");
20190 CHECK(foreign_function->IsFunction());
20191 foreign_context->Exit();
20192
20193 LocalContext context;
20194
20195 Local<String> password = v8_str("Password");
20196 // Don't get hit by security checks when accessing foreign_context's
20197 // global receiver (aka. global proxy).
20198 context->SetSecurityToken(password);
20199 foreign_context->SetSecurityToken(password);
20200
20201 Local<String> i = v8_str("i");
20202 Local<String> o = v8_str("o");
20203 Local<String> id = v8_str("id");
20204
20205 CompileRun("function ownfunc() { return { 0: this.id, "
20206 " 1: this, "
20207 " toString: function() { "
20208 " return this[0];"
20209 " }"
20210 " };"
20211 "}"
20212 "var id = 'o';"
20213 "ownfunc");
20214 context->Global()->Set(v8_str("func"), foreign_function);
20215
20216 // Sanity check the contexts.
20217 CHECK(i->Equals(foreign_context->Global()->Get(id)));
20218 CHECK(o->Equals(context->Global()->Get(id)));
20219
20220 // Checking local function's receiver.
20221 // Calling function using its call/apply methods.
20222 TestReceiver(o, context->Global(), "ownfunc.call()");
20223 TestReceiver(o, context->Global(), "ownfunc.apply()");
20224 // Making calls through built-in functions.
20225 TestReceiver(o, context->Global(), "[1].map(ownfunc)[0]");
20226 CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/,ownfunc)[1]")));
20227 CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/g,ownfunc)[1]")));
20228 CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/g,ownfunc)[3]")));
20229 // Calling with environment record as base.
20230 TestReceiver(o, context->Global(), "ownfunc()");
20231 // Calling with no base.
20232 TestReceiver(o, context->Global(), "(1,ownfunc)()");
20233
20234 // Checking foreign function return value.
20235 // Calling function using its call/apply methods.
20236 TestReceiver(i, foreign_context->Global(), "func.call()");
20237 TestReceiver(i, foreign_context->Global(), "func.apply()");
20238 // Calling function using another context's call/apply methods.
20239 TestReceiver(i, foreign_context->Global(),
20240 "Function.prototype.call.call(func)");
20241 TestReceiver(i, foreign_context->Global(),
20242 "Function.prototype.call.apply(func)");
20243 TestReceiver(i, foreign_context->Global(),
20244 "Function.prototype.apply.call(func)");
20245 TestReceiver(i, foreign_context->Global(),
20246 "Function.prototype.apply.apply(func)");
20247 // Making calls through built-in functions.
20248 TestReceiver(i, foreign_context->Global(), "[1].map(func)[0]");
20249 // ToString(func()) is func()[0], i.e., the returned this.id.
20250 CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/,func)[1]")));
20251 CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/g,func)[1]")));
20252 CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/g,func)[3]")));
20253
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020254 // Calling with environment record as base.
rossberg@chromium.org9ed27462014-01-07 14:16:41 +000020255 TestReceiver(i, foreign_context->Global(), "func()");
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020256 // Calling with no base.
rossberg@chromium.org9ed27462014-01-07 14:16:41 +000020257 TestReceiver(i, foreign_context->Global(), "(1,func)()");
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020258}
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020259
20260
20261uint8_t callback_fired = 0;
20262
20263
20264void CallCompletedCallback1() {
20265 i::OS::Print("Firing callback 1.\n");
20266 callback_fired ^= 1; // Toggle first bit.
20267}
20268
20269
20270void CallCompletedCallback2() {
20271 i::OS::Print("Firing callback 2.\n");
20272 callback_fired ^= 2; // Toggle second bit.
20273}
20274
20275
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000020276void RecursiveCall(const v8::FunctionCallbackInfo<v8::Value>& args) {
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020277 int32_t level = args[0]->Int32Value();
20278 if (level < 3) {
20279 level++;
20280 i::OS::Print("Entering recursion level %d.\n", level);
20281 char script[64];
20282 i::Vector<char> script_vector(script, sizeof(script));
20283 i::OS::SNPrintF(script_vector, "recursion(%d)", level);
20284 CompileRun(script_vector.start());
20285 i::OS::Print("Leaving recursion level %d.\n", level);
20286 CHECK_EQ(0, callback_fired);
20287 } else {
20288 i::OS::Print("Recursion ends.\n");
20289 CHECK_EQ(0, callback_fired);
20290 }
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020291}
20292
20293
20294TEST(CallCompletedCallback) {
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020295 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020296 v8::HandleScope scope(env->GetIsolate());
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020297 v8::Handle<v8::FunctionTemplate> recursive_runtime =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000020298 v8::FunctionTemplate::New(env->GetIsolate(), RecursiveCall);
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020299 env->Global()->Set(v8_str("recursion"),
20300 recursive_runtime->GetFunction());
20301 // Adding the same callback a second time has no effect.
20302 v8::V8::AddCallCompletedCallback(CallCompletedCallback1);
20303 v8::V8::AddCallCompletedCallback(CallCompletedCallback1);
20304 v8::V8::AddCallCompletedCallback(CallCompletedCallback2);
20305 i::OS::Print("--- Script (1) ---\n");
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000020306 Local<Script> script = v8::Script::Compile(
20307 v8::String::NewFromUtf8(env->GetIsolate(), "recursion(0)"));
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020308 script->Run();
20309 CHECK_EQ(3, callback_fired);
20310
20311 i::OS::Print("\n--- Script (2) ---\n");
20312 callback_fired = 0;
20313 v8::V8::RemoveCallCompletedCallback(CallCompletedCallback1);
20314 script->Run();
20315 CHECK_EQ(2, callback_fired);
20316
20317 i::OS::Print("\n--- Function ---\n");
20318 callback_fired = 0;
20319 Local<Function> recursive_function =
20320 Local<Function>::Cast(env->Global()->Get(v8_str("recursion")));
20321 v8::Handle<Value> args[] = { v8_num(0) };
20322 recursive_function->Call(env->Global(), 1, args);
20323 CHECK_EQ(2, callback_fired);
20324}
20325
20326
20327void CallCompletedCallbackNoException() {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020328 v8::HandleScope scope(CcTest::isolate());
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020329 CompileRun("1+1;");
20330}
20331
20332
20333void CallCompletedCallbackException() {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020334 v8::HandleScope scope(CcTest::isolate());
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020335 CompileRun("throw 'second exception';");
20336}
20337
20338
20339TEST(CallCompletedCallbackOneException) {
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020340 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020341 v8::HandleScope scope(env->GetIsolate());
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020342 v8::V8::AddCallCompletedCallback(CallCompletedCallbackNoException);
20343 CompileRun("throw 'exception';");
20344}
20345
20346
20347TEST(CallCompletedCallbackTwoExceptions) {
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020348 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020349 v8::HandleScope scope(env->GetIsolate());
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020350 v8::V8::AddCallCompletedCallback(CallCompletedCallbackException);
20351 CompileRun("throw 'first exception';");
20352}
ulan@chromium.org812308e2012-02-29 15:58:45 +000020353
20354
20355static int probes_counter = 0;
20356static int misses_counter = 0;
20357static int updates_counter = 0;
20358
20359
20360static int* LookupCounter(const char* name) {
20361 if (strcmp(name, "c:V8.MegamorphicStubCacheProbes") == 0) {
20362 return &probes_counter;
20363 } else if (strcmp(name, "c:V8.MegamorphicStubCacheMisses") == 0) {
20364 return &misses_counter;
20365 } else if (strcmp(name, "c:V8.MegamorphicStubCacheUpdates") == 0) {
20366 return &updates_counter;
20367 }
20368 return NULL;
20369}
20370
20371
20372static const char* kMegamorphicTestProgram =
20373 "function ClassA() { };"
20374 "function ClassB() { };"
20375 "ClassA.prototype.foo = function() { };"
20376 "ClassB.prototype.foo = function() { };"
20377 "function fooify(obj) { obj.foo(); };"
20378 "var a = new ClassA();"
20379 "var b = new ClassB();"
20380 "for (var i = 0; i < 10000; i++) {"
20381 " fooify(a);"
20382 " fooify(b);"
20383 "}";
20384
20385
20386static void StubCacheHelper(bool primary) {
20387 V8::SetCounterFunction(LookupCounter);
20388 USE(kMegamorphicTestProgram);
20389#ifdef DEBUG
20390 i::FLAG_native_code_counters = true;
20391 if (primary) {
20392 i::FLAG_test_primary_stub_cache = true;
20393 } else {
20394 i::FLAG_test_secondary_stub_cache = true;
20395 }
20396 i::FLAG_crankshaft = false;
ulan@chromium.org812308e2012-02-29 15:58:45 +000020397 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020398 v8::HandleScope scope(env->GetIsolate());
ulan@chromium.org812308e2012-02-29 15:58:45 +000020399 int initial_probes = probes_counter;
20400 int initial_misses = misses_counter;
20401 int initial_updates = updates_counter;
20402 CompileRun(kMegamorphicTestProgram);
20403 int probes = probes_counter - initial_probes;
20404 int misses = misses_counter - initial_misses;
20405 int updates = updates_counter - initial_updates;
20406 CHECK_LT(updates, 10);
20407 CHECK_LT(misses, 10);
20408 CHECK_GE(probes, 10000);
20409#endif
20410}
20411
20412
20413TEST(SecondaryStubCache) {
20414 StubCacheHelper(true);
20415}
20416
20417
20418TEST(PrimaryStubCache) {
20419 StubCacheHelper(false);
20420}
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020421
20422
verwaest@chromium.org057bd502013-11-06 12:03:29 +000020423static int cow_arrays_created_runtime = 0;
20424
20425
20426static int* LookupCounterCOWArrays(const char* name) {
20427 if (strcmp(name, "c:V8.COWArraysCreatedRuntime") == 0) {
20428 return &cow_arrays_created_runtime;
20429 }
20430 return NULL;
20431}
20432
20433
20434TEST(CheckCOWArraysCreatedRuntimeCounter) {
20435 V8::SetCounterFunction(LookupCounterCOWArrays);
20436#ifdef DEBUG
20437 i::FLAG_native_code_counters = true;
20438 LocalContext env;
20439 v8::HandleScope scope(env->GetIsolate());
20440 int initial_cow_arrays = cow_arrays_created_runtime;
20441 CompileRun("var o = [1, 2, 3];");
20442 CHECK_EQ(1, cow_arrays_created_runtime - initial_cow_arrays);
20443 CompileRun("var o = {foo: [4, 5, 6], bar: [3, 0]};");
20444 CHECK_EQ(3, cow_arrays_created_runtime - initial_cow_arrays);
20445 CompileRun("var o = {foo: [1, 2, 3, [4, 5, 6]], bar: 'hi'};");
20446 CHECK_EQ(4, cow_arrays_created_runtime - initial_cow_arrays);
20447#endif
20448}
20449
20450
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020451TEST(StaticGetters) {
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020452 LocalContext context;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020453 i::Factory* factory = CcTest::i_isolate()->factory();
20454 v8::Isolate* isolate = CcTest::isolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020455 v8::HandleScope scope(isolate);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000020456 i::Handle<i::Object> undefined_value = factory->undefined_value();
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020457 CHECK(*v8::Utils::OpenHandle(*v8::Undefined(isolate)) == *undefined_value);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000020458 i::Handle<i::Object> null_value = factory->null_value();
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020459 CHECK(*v8::Utils::OpenHandle(*v8::Null(isolate)) == *null_value);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000020460 i::Handle<i::Object> true_value = factory->true_value();
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020461 CHECK(*v8::Utils::OpenHandle(*v8::True(isolate)) == *true_value);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000020462 i::Handle<i::Object> false_value = factory->false_value();
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020463 CHECK(*v8::Utils::OpenHandle(*v8::False(isolate)) == *false_value);
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020464}
20465
20466
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020467UNINITIALIZED_TEST(IsolateEmbedderData) {
20468 CcTest::DisableAutomaticDispose();
20469 v8::Isolate* isolate = v8::Isolate::New();
20470 isolate->Enter();
hpayer@chromium.orgc5d49712013-09-11 08:25:48 +000020471 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
machenbach@chromium.org7ff76072013-11-21 09:47:43 +000020472 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
20473 CHECK_EQ(NULL, isolate->GetData(slot));
20474 CHECK_EQ(NULL, i_isolate->GetData(slot));
20475 }
20476 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
20477 void* data = reinterpret_cast<void*>(0xacce55ed + slot);
20478 isolate->SetData(slot, data);
20479 }
20480 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
20481 void* data = reinterpret_cast<void*>(0xacce55ed + slot);
20482 CHECK_EQ(data, isolate->GetData(slot));
20483 CHECK_EQ(data, i_isolate->GetData(slot));
20484 }
20485 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
20486 void* data = reinterpret_cast<void*>(0xdecea5ed + slot);
20487 isolate->SetData(slot, data);
20488 }
20489 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
20490 void* data = reinterpret_cast<void*>(0xdecea5ed + slot);
20491 CHECK_EQ(data, isolate->GetData(slot));
20492 CHECK_EQ(data, i_isolate->GetData(slot));
20493 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020494 isolate->Exit();
20495 isolate->Dispose();
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020496}
20497
20498
20499TEST(StringEmpty) {
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020500 LocalContext context;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020501 i::Factory* factory = CcTest::i_isolate()->factory();
20502 v8::Isolate* isolate = CcTest::isolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020503 v8::HandleScope scope(isolate);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000020504 i::Handle<i::Object> empty_string = factory->empty_string();
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020505 CHECK(*v8::Utils::OpenHandle(*v8::String::Empty(isolate)) == *empty_string);
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020506}
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020507
20508
20509static int instance_checked_getter_count = 0;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000020510static void InstanceCheckedGetter(
20511 Local<String> name,
20512 const v8::PropertyCallbackInfo<v8::Value>& info) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020513 CHECK_EQ(name, v8_str("foo"));
20514 instance_checked_getter_count++;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000020515 info.GetReturnValue().Set(v8_num(11));
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020516}
20517
20518
20519static int instance_checked_setter_count = 0;
20520static void InstanceCheckedSetter(Local<String> name,
20521 Local<Value> value,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000020522 const v8::PropertyCallbackInfo<void>& info) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020523 CHECK_EQ(name, v8_str("foo"));
20524 CHECK_EQ(value, v8_num(23));
20525 instance_checked_setter_count++;
20526}
20527
20528
20529static void CheckInstanceCheckedResult(int getters,
20530 int setters,
20531 bool expects_callbacks,
20532 TryCatch* try_catch) {
20533 if (expects_callbacks) {
20534 CHECK(!try_catch->HasCaught());
20535 CHECK_EQ(getters, instance_checked_getter_count);
20536 CHECK_EQ(setters, instance_checked_setter_count);
20537 } else {
20538 CHECK(try_catch->HasCaught());
20539 CHECK_EQ(0, instance_checked_getter_count);
20540 CHECK_EQ(0, instance_checked_setter_count);
20541 }
20542 try_catch->Reset();
20543}
20544
20545
20546static void CheckInstanceCheckedAccessors(bool expects_callbacks) {
20547 instance_checked_getter_count = 0;
20548 instance_checked_setter_count = 0;
20549 TryCatch try_catch;
20550
20551 // Test path through generic runtime code.
20552 CompileRun("obj.foo");
20553 CheckInstanceCheckedResult(1, 0, expects_callbacks, &try_catch);
20554 CompileRun("obj.foo = 23");
20555 CheckInstanceCheckedResult(1, 1, expects_callbacks, &try_catch);
20556
20557 // Test path through generated LoadIC and StoredIC.
20558 CompileRun("function test_get(o) { o.foo; }"
20559 "test_get(obj);");
20560 CheckInstanceCheckedResult(2, 1, expects_callbacks, &try_catch);
20561 CompileRun("test_get(obj);");
20562 CheckInstanceCheckedResult(3, 1, expects_callbacks, &try_catch);
20563 CompileRun("test_get(obj);");
20564 CheckInstanceCheckedResult(4, 1, expects_callbacks, &try_catch);
20565 CompileRun("function test_set(o) { o.foo = 23; }"
20566 "test_set(obj);");
20567 CheckInstanceCheckedResult(4, 2, expects_callbacks, &try_catch);
20568 CompileRun("test_set(obj);");
20569 CheckInstanceCheckedResult(4, 3, expects_callbacks, &try_catch);
20570 CompileRun("test_set(obj);");
20571 CheckInstanceCheckedResult(4, 4, expects_callbacks, &try_catch);
20572
20573 // Test path through optimized code.
20574 CompileRun("%OptimizeFunctionOnNextCall(test_get);"
20575 "test_get(obj);");
20576 CheckInstanceCheckedResult(5, 4, expects_callbacks, &try_catch);
20577 CompileRun("%OptimizeFunctionOnNextCall(test_set);"
20578 "test_set(obj);");
20579 CheckInstanceCheckedResult(5, 5, expects_callbacks, &try_catch);
20580
20581 // Cleanup so that closures start out fresh in next check.
20582 CompileRun("%DeoptimizeFunction(test_get);"
20583 "%ClearFunctionTypeFeedback(test_get);"
20584 "%DeoptimizeFunction(test_set);"
20585 "%ClearFunctionTypeFeedback(test_set);");
20586}
20587
20588
20589THREADED_TEST(InstanceCheckOnInstanceAccessor) {
20590 v8::internal::FLAG_allow_natives_syntax = true;
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020591 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020592 v8::HandleScope scope(context->GetIsolate());
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020593
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000020594 Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020595 Local<ObjectTemplate> inst = templ->InstanceTemplate();
20596 inst->SetAccessor(v8_str("foo"),
20597 InstanceCheckedGetter, InstanceCheckedSetter,
20598 Handle<Value>(),
20599 v8::DEFAULT,
20600 v8::None,
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000020601 v8::AccessorSignature::New(context->GetIsolate(), templ));
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020602 context->Global()->Set(v8_str("f"), templ->GetFunction());
20603
20604 printf("Testing positive ...\n");
20605 CompileRun("var obj = new f();");
20606 CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
20607 CheckInstanceCheckedAccessors(true);
20608
20609 printf("Testing negative ...\n");
20610 CompileRun("var obj = {};"
20611 "obj.__proto__ = new f();");
20612 CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
20613 CheckInstanceCheckedAccessors(false);
20614}
20615
20616
20617THREADED_TEST(InstanceCheckOnInstanceAccessorWithInterceptor) {
20618 v8::internal::FLAG_allow_natives_syntax = true;
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020619 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020620 v8::HandleScope scope(context->GetIsolate());
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020621
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000020622 Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020623 Local<ObjectTemplate> inst = templ->InstanceTemplate();
20624 AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter);
20625 inst->SetAccessor(v8_str("foo"),
20626 InstanceCheckedGetter, InstanceCheckedSetter,
20627 Handle<Value>(),
20628 v8::DEFAULT,
20629 v8::None,
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000020630 v8::AccessorSignature::New(context->GetIsolate(), templ));
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020631 context->Global()->Set(v8_str("f"), templ->GetFunction());
20632
20633 printf("Testing positive ...\n");
20634 CompileRun("var obj = new f();");
20635 CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
20636 CheckInstanceCheckedAccessors(true);
20637
20638 printf("Testing negative ...\n");
20639 CompileRun("var obj = {};"
20640 "obj.__proto__ = new f();");
20641 CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
20642 CheckInstanceCheckedAccessors(false);
20643}
20644
20645
20646THREADED_TEST(InstanceCheckOnPrototypeAccessor) {
20647 v8::internal::FLAG_allow_natives_syntax = true;
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020648 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020649 v8::HandleScope scope(context->GetIsolate());
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020650
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000020651 Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020652 Local<ObjectTemplate> proto = templ->PrototypeTemplate();
20653 proto->SetAccessor(v8_str("foo"),
20654 InstanceCheckedGetter, InstanceCheckedSetter,
20655 Handle<Value>(),
20656 v8::DEFAULT,
20657 v8::None,
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000020658 v8::AccessorSignature::New(context->GetIsolate(), templ));
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020659 context->Global()->Set(v8_str("f"), templ->GetFunction());
20660
20661 printf("Testing positive ...\n");
20662 CompileRun("var obj = new f();");
20663 CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
20664 CheckInstanceCheckedAccessors(true);
20665
20666 printf("Testing negative ...\n");
20667 CompileRun("var obj = {};"
20668 "obj.__proto__ = new f();");
20669 CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
20670 CheckInstanceCheckedAccessors(false);
20671
20672 printf("Testing positive with modified prototype chain ...\n");
20673 CompileRun("var obj = new f();"
20674 "var pro = {};"
20675 "pro.__proto__ = obj.__proto__;"
20676 "obj.__proto__ = pro;");
20677 CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
20678 CheckInstanceCheckedAccessors(true);
20679}
20680
20681
20682TEST(TryFinallyMessage) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020683 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020684 v8::HandleScope scope(context->GetIsolate());
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020685 {
20686 // Test that the original error message is not lost if there is a
20687 // recursive call into Javascript is done in the finally block, e.g. to
20688 // initialize an IC. (crbug.com/129171)
20689 TryCatch try_catch;
20690 const char* trigger_ic =
20691 "try { \n"
20692 " throw new Error('test'); \n"
20693 "} finally { \n"
20694 " var x = 0; \n"
20695 " x++; \n" // Trigger an IC initialization here.
20696 "} \n";
20697 CompileRun(trigger_ic);
20698 CHECK(try_catch.HasCaught());
20699 Local<Message> message = try_catch.Message();
20700 CHECK(!message.IsEmpty());
20701 CHECK_EQ(2, message->GetLineNumber());
20702 }
20703
20704 {
20705 // Test that the original exception message is indeed overwritten if
20706 // a new error is thrown in the finally block.
20707 TryCatch try_catch;
20708 const char* throw_again =
20709 "try { \n"
20710 " throw new Error('test'); \n"
20711 "} finally { \n"
20712 " var x = 0; \n"
20713 " x++; \n"
20714 " throw new Error('again'); \n" // This is the new uncaught error.
20715 "} \n";
20716 CompileRun(throw_again);
20717 CHECK(try_catch.HasCaught());
20718 Local<Message> message = try_catch.Message();
20719 CHECK(!message.IsEmpty());
20720 CHECK_EQ(6, message->GetLineNumber());
20721 }
20722}
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000020723
20724
erik.corry@gmail.com88767242012-08-08 14:43:45 +000020725static void Helper137002(bool do_store,
20726 bool polymorphic,
20727 bool remove_accessor,
20728 bool interceptor) {
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000020729 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000020730 Local<ObjectTemplate> templ = ObjectTemplate::New(context->GetIsolate());
erik.corry@gmail.com88767242012-08-08 14:43:45 +000020731 if (interceptor) {
20732 templ->SetNamedPropertyHandler(FooGetInterceptor, FooSetInterceptor);
20733 } else {
20734 templ->SetAccessor(v8_str("foo"),
20735 GetterWhichReturns42,
20736 SetterWhichSetsYOnThisTo23);
20737 }
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000020738 context->Global()->Set(v8_str("obj"), templ->NewInstance());
20739
20740 // Turn monomorphic on slow object with native accessor, then turn
20741 // polymorphic, finally optimize to create negative lookup and fail.
erik.corry@gmail.com88767242012-08-08 14:43:45 +000020742 CompileRun(do_store ?
20743 "function f(x) { x.foo = void 0; }" :
20744 "function f(x) { return x.foo; }");
20745 CompileRun("obj.y = void 0;");
20746 if (!interceptor) {
20747 CompileRun("%OptimizeObjectForAddingMultipleProperties(obj, 1);");
20748 }
20749 CompileRun("obj.__proto__ = null;"
20750 "f(obj); f(obj); f(obj);");
20751 if (polymorphic) {
20752 CompileRun("f({});");
20753 }
20754 CompileRun("obj.y = void 0;"
20755 "%OptimizeFunctionOnNextCall(f);");
20756 if (remove_accessor) {
20757 CompileRun("delete obj.foo;");
20758 }
20759 CompileRun("var result = f(obj);");
20760 if (do_store) {
20761 CompileRun("result = obj.y;");
20762 }
20763 if (remove_accessor && !interceptor) {
20764 CHECK(context->Global()->Get(v8_str("result"))->IsUndefined());
20765 } else {
20766 CHECK_EQ(do_store ? 23 : 42,
20767 context->Global()->Get(v8_str("result"))->Int32Value());
20768 }
20769}
20770
20771
20772THREADED_TEST(Regress137002a) {
20773 i::FLAG_allow_natives_syntax = true;
20774 i::FLAG_compilation_cache = false;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020775 v8::HandleScope scope(CcTest::isolate());
erik.corry@gmail.com88767242012-08-08 14:43:45 +000020776 for (int i = 0; i < 16; i++) {
20777 Helper137002(i & 8, i & 4, i & 2, i & 1);
20778 }
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000020779}
20780
20781
20782THREADED_TEST(Regress137002b) {
20783 i::FLAG_allow_natives_syntax = true;
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000020784 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000020785 v8::Isolate* isolate = context->GetIsolate();
20786 v8::HandleScope scope(isolate);
20787 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000020788 templ->SetAccessor(v8_str("foo"),
20789 GetterWhichReturns42,
20790 SetterWhichSetsYOnThisTo23);
20791 context->Global()->Set(v8_str("obj"), templ->NewInstance());
20792
20793 // Turn monomorphic on slow object with native accessor, then just
20794 // delete the property and fail.
erik.corry@gmail.com88767242012-08-08 14:43:45 +000020795 CompileRun("function load(x) { return x.foo; }"
20796 "function store(x) { x.foo = void 0; }"
20797 "function keyed_load(x, key) { return x[key]; }"
20798 // Second version of function has a different source (add void 0)
20799 // so that it does not share code with the first version. This
20800 // ensures that the ICs are monomorphic.
20801 "function load2(x) { void 0; return x.foo; }"
20802 "function store2(x) { void 0; x.foo = void 0; }"
20803 "function keyed_load2(x, key) { void 0; return x[key]; }"
20804
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000020805 "obj.y = void 0;"
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000020806 "obj.__proto__ = null;"
erik.corry@gmail.com88767242012-08-08 14:43:45 +000020807 "var subobj = {};"
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000020808 "subobj.y = void 0;"
erik.corry@gmail.com88767242012-08-08 14:43:45 +000020809 "subobj.__proto__ = obj;"
20810 "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
20811
20812 // Make the ICs monomorphic.
20813 "load(obj); load(obj);"
20814 "load2(subobj); load2(subobj);"
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000020815 "store(obj); store(obj);"
20816 "store2(subobj); store2(subobj);"
erik.corry@gmail.com88767242012-08-08 14:43:45 +000020817 "keyed_load(obj, 'foo'); keyed_load(obj, 'foo');"
20818 "keyed_load2(subobj, 'foo'); keyed_load2(subobj, 'foo');"
20819
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000020820 // Actually test the shiny new ICs and better not crash. This
20821 // serves as a regression test for issue 142088 as well.
20822 "load(obj);"
20823 "load2(subobj);"
20824 "store(obj);"
20825 "store2(subobj);"
20826 "keyed_load(obj, 'foo');"
20827 "keyed_load2(subobj, 'foo');"
20828
erik.corry@gmail.com88767242012-08-08 14:43:45 +000020829 // Delete the accessor. It better not be called any more now.
20830 "delete obj.foo;"
20831 "obj.y = void 0;"
20832 "subobj.y = void 0;"
20833
20834 "var load_result = load(obj);"
20835 "var load_result2 = load2(subobj);"
20836 "var keyed_load_result = keyed_load(obj, 'foo');"
20837 "var keyed_load_result2 = keyed_load2(subobj, 'foo');"
20838 "store(obj);"
20839 "store2(subobj);"
20840 "var y_from_obj = obj.y;"
20841 "var y_from_subobj = subobj.y;");
20842 CHECK(context->Global()->Get(v8_str("load_result"))->IsUndefined());
20843 CHECK(context->Global()->Get(v8_str("load_result2"))->IsUndefined());
20844 CHECK(context->Global()->Get(v8_str("keyed_load_result"))->IsUndefined());
20845 CHECK(context->Global()->Get(v8_str("keyed_load_result2"))->IsUndefined());
20846 CHECK(context->Global()->Get(v8_str("y_from_obj"))->IsUndefined());
20847 CHECK(context->Global()->Get(v8_str("y_from_subobj"))->IsUndefined());
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000020848}
verwaest@chromium.org753aee42012-07-17 16:15:42 +000020849
20850
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000020851THREADED_TEST(Regress142088) {
20852 i::FLAG_allow_natives_syntax = true;
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000020853 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000020854 v8::Isolate* isolate = context->GetIsolate();
20855 v8::HandleScope scope(isolate);
20856 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000020857 templ->SetAccessor(v8_str("foo"),
20858 GetterWhichReturns42,
20859 SetterWhichSetsYOnThisTo23);
20860 context->Global()->Set(v8_str("obj"), templ->NewInstance());
20861
20862 CompileRun("function load(x) { return x.foo; }"
20863 "var o = Object.create(obj);"
20864 "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
20865 "load(o); load(o); load(o); load(o);");
20866}
20867
20868
verwaest@chromium.org753aee42012-07-17 16:15:42 +000020869THREADED_TEST(Regress137496) {
20870 i::FLAG_expose_gc = true;
verwaest@chromium.org753aee42012-07-17 16:15:42 +000020871 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020872 v8::HandleScope scope(context->GetIsolate());
verwaest@chromium.org753aee42012-07-17 16:15:42 +000020873
20874 // Compile a try-finally clause where the finally block causes a GC
20875 // while there still is a message pending for external reporting.
20876 TryCatch try_catch;
20877 try_catch.SetVerbose(true);
20878 CompileRun("try { throw new Error(); } finally { gc(); }");
20879 CHECK(try_catch.HasCaught());
20880}
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000020881
20882
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000020883THREADED_TEST(Regress149912) {
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000020884 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020885 v8::HandleScope scope(context->GetIsolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000020886 Handle<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000020887 AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter);
20888 context->Global()->Set(v8_str("Bug"), templ->GetFunction());
20889 CompileRun("Number.prototype.__proto__ = new Bug; var x = 0; x.foo();");
20890}
20891
20892
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000020893THREADED_TEST(Regress157124) {
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000020894 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000020895 v8::Isolate* isolate = context->GetIsolate();
20896 v8::HandleScope scope(isolate);
20897 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000020898 Local<Object> obj = templ->NewInstance();
20899 obj->GetIdentityHash();
20900 obj->DeleteHiddenValue(v8_str("Bug"));
20901}
20902
20903
ulan@chromium.org6e196bf2013-03-13 09:38:22 +000020904THREADED_TEST(Regress2535) {
20905 i::FLAG_harmony_collections = true;
ulan@chromium.org6e196bf2013-03-13 09:38:22 +000020906 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020907 v8::HandleScope scope(context->GetIsolate());
ulan@chromium.org6e196bf2013-03-13 09:38:22 +000020908 Local<Value> set_value = CompileRun("new Set();");
danno@chromium.orgf95d4b92013-06-13 14:40:17 +000020909 Local<Object> set_object(Local<Object>::Cast(set_value));
ulan@chromium.org6e196bf2013-03-13 09:38:22 +000020910 CHECK_EQ(0, set_object->InternalFieldCount());
20911 Local<Value> map_value = CompileRun("new Map();");
danno@chromium.orgf95d4b92013-06-13 14:40:17 +000020912 Local<Object> map_object(Local<Object>::Cast(map_value));
ulan@chromium.org6e196bf2013-03-13 09:38:22 +000020913 CHECK_EQ(0, map_object->InternalFieldCount());
20914}
20915
20916
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000020917THREADED_TEST(Regress2746) {
20918 LocalContext context;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000020919 v8::Isolate* isolate = context->GetIsolate();
20920 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000020921 Local<Object> obj = Object::New(isolate);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000020922 Local<String> key = String::NewFromUtf8(context->GetIsolate(), "key");
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000020923 obj->SetHiddenValue(key, v8::Undefined(isolate));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000020924 Local<Value> value = obj->GetHiddenValue(key);
20925 CHECK(!value.IsEmpty());
20926 CHECK(value->IsUndefined());
20927}
20928
20929
jkummerow@chromium.org10480472013-07-17 08:22:15 +000020930THREADED_TEST(Regress260106) {
20931 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000020932 v8::Isolate* isolate = context->GetIsolate();
20933 v8::HandleScope scope(isolate);
20934 Local<FunctionTemplate> templ = FunctionTemplate::New(isolate,
20935 DummyCallHandler);
jkummerow@chromium.org10480472013-07-17 08:22:15 +000020936 CompileRun("for (var i = 0; i < 128; i++) Object.prototype[i] = 0;");
20937 Local<Function> function = templ->GetFunction();
20938 CHECK(!function.IsEmpty());
20939 CHECK(function->IsFunction());
20940}
20941
20942
danno@chromium.org59400602013-08-13 17:09:37 +000020943THREADED_TEST(JSONParseObject) {
20944 LocalContext context;
20945 HandleScope scope(context->GetIsolate());
20946 Local<Value> obj = v8::JSON::Parse(v8_str("{\"x\":42}"));
20947 Handle<Object> global = context->Global();
20948 global->Set(v8_str("obj"), obj);
20949 ExpectString("JSON.stringify(obj)", "{\"x\":42}");
20950}
20951
20952
20953THREADED_TEST(JSONParseNumber) {
20954 LocalContext context;
20955 HandleScope scope(context->GetIsolate());
20956 Local<Value> obj = v8::JSON::Parse(v8_str("42"));
20957 Handle<Object> global = context->Global();
20958 global->Set(v8_str("obj"), obj);
20959 ExpectString("JSON.stringify(obj)", "42");
20960}
20961
20962
verwaest@chromium.org662436e2013-08-28 08:41:27 +000020963#if V8_OS_POSIX
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000020964class ThreadInterruptTest {
20965 public:
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000020966 ThreadInterruptTest() : sem_(0), sem_value_(0) { }
20967 ~ThreadInterruptTest() {}
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000020968
20969 void RunTest() {
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000020970 InterruptThread i_thread(this);
20971 i_thread.Start();
20972
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000020973 sem_.Wait();
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000020974 CHECK_EQ(kExpectedValue, sem_value_);
20975 }
20976
20977 private:
20978 static const int kExpectedValue = 1;
20979
20980 class InterruptThread : public i::Thread {
20981 public:
20982 explicit InterruptThread(ThreadInterruptTest* test)
20983 : Thread("InterruptThread"), test_(test) {}
20984
20985 virtual void Run() {
20986 struct sigaction action;
20987
20988 // Ensure that we'll enter waiting condition
20989 i::OS::Sleep(100);
20990
20991 // Setup signal handler
20992 memset(&action, 0, sizeof(action));
20993 action.sa_handler = SignalHandler;
20994 sigaction(SIGCHLD, &action, NULL);
20995
20996 // Send signal
20997 kill(getpid(), SIGCHLD);
20998
20999 // Ensure that if wait has returned because of error
21000 i::OS::Sleep(100);
21001
21002 // Set value and signal semaphore
21003 test_->sem_value_ = 1;
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000021004 test_->sem_.Signal();
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000021005 }
21006
21007 static void SignalHandler(int signal) {
21008 }
21009
21010 private:
21011 ThreadInterruptTest* test_;
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000021012 };
21013
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000021014 i::Semaphore sem_;
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000021015 volatile int sem_value_;
21016};
21017
21018
21019THREADED_TEST(SemaphoreInterruption) {
21020 ThreadInterruptTest().RunTest();
21021}
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000021022
danno@chromium.org169691d2013-07-15 08:01:13 +000021023
hpayer@chromium.orgea9b8ba2013-12-20 19:22:39 +000021024#endif // V8_OS_POSIX
21025
21026
danno@chromium.org169691d2013-07-15 08:01:13 +000021027static bool NamedAccessAlwaysBlocked(Local<v8::Object> global,
21028 Local<Value> name,
21029 v8::AccessType type,
21030 Local<Value> data) {
21031 i::PrintF("Named access blocked.\n");
21032 return false;
21033}
21034
21035
21036static bool IndexAccessAlwaysBlocked(Local<v8::Object> global,
21037 uint32_t key,
21038 v8::AccessType type,
21039 Local<Value> data) {
21040 i::PrintF("Indexed access blocked.\n");
21041 return false;
21042}
21043
21044
21045void UnreachableCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
21046 CHECK(false);
21047}
21048
21049
21050TEST(JSONStringifyAccessCheck) {
21051 v8::V8::Initialize();
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000021052 v8::Isolate* isolate = CcTest::isolate();
21053 v8::HandleScope scope(isolate);
danno@chromium.org169691d2013-07-15 08:01:13 +000021054
21055 // Create an ObjectTemplate for global objects and install access
21056 // check callbacks that will block access.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000021057 v8::Handle<v8::ObjectTemplate> global_template =
21058 v8::ObjectTemplate::New(isolate);
danno@chromium.org169691d2013-07-15 08:01:13 +000021059 global_template->SetAccessCheckCallbacks(NamedAccessAlwaysBlocked,
21060 IndexAccessAlwaysBlocked);
21061
21062 // Create a context and set an x property on it's global object.
21063 LocalContext context0(NULL, global_template);
21064 v8::Handle<v8::Object> global0 = context0->Global();
21065 global0->Set(v8_str("x"), v8_num(42));
21066 ExpectString("JSON.stringify(this)", "{\"x\":42}");
21067
21068 for (int i = 0; i < 2; i++) {
21069 if (i == 1) {
21070 // Install a toJSON function on the second run.
21071 v8::Handle<v8::FunctionTemplate> toJSON =
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000021072 v8::FunctionTemplate::New(isolate, UnreachableCallback);
danno@chromium.org169691d2013-07-15 08:01:13 +000021073
21074 global0->Set(v8_str("toJSON"), toJSON->GetFunction());
21075 }
21076 // Create a context with a different security token so that the
21077 // failed access check callback will be called on each access.
21078 LocalContext context1(NULL, global_template);
21079 context1->Global()->Set(v8_str("other"), global0);
21080
21081 ExpectString("JSON.stringify(other)", "{}");
21082 ExpectString("JSON.stringify({ 'a' : other, 'b' : ['c'] })",
21083 "{\"a\":{},\"b\":[\"c\"]}");
21084 ExpectString("JSON.stringify([other, 'b', 'c'])",
21085 "[{},\"b\",\"c\"]");
21086
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000021087 v8::Handle<v8::Array> array = v8::Array::New(isolate, 2);
danno@chromium.org169691d2013-07-15 08:01:13 +000021088 array->Set(0, v8_str("a"));
21089 array->Set(1, v8_str("b"));
21090 context1->Global()->Set(v8_str("array"), array);
21091 ExpectString("JSON.stringify(array)", "[\"a\",\"b\"]");
21092 array->TurnOnAccessCheck();
21093 ExpectString("JSON.stringify(array)", "[]");
21094 ExpectString("JSON.stringify([array])", "[[]]");
21095 ExpectString("JSON.stringify({'a' : array})", "{\"a\":[]}");
21096 }
21097}
21098
21099
21100bool access_check_fail_thrown = false;
21101bool catch_callback_called = false;
21102
21103
21104// Failed access check callback that performs a GC on each invocation.
21105void FailedAccessCheckThrows(Local<v8::Object> target,
21106 v8::AccessType type,
21107 Local<v8::Value> data) {
21108 access_check_fail_thrown = true;
21109 i::PrintF("Access check failed. Error thrown.\n");
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000021110 CcTest::isolate()->ThrowException(
21111 v8::Exception::Error(v8_str("cross context")));
danno@chromium.org169691d2013-07-15 08:01:13 +000021112}
21113
21114
21115void CatcherCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
21116 for (int i = 0; i < args.Length(); i++) {
21117 i::PrintF("%s\n", *String::Utf8Value(args[i]));
21118 }
21119 catch_callback_called = true;
21120}
21121
21122
21123void HasOwnPropertyCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
21124 args[0]->ToObject()->HasOwnProperty(args[1]->ToString());
21125}
21126
21127
21128void CheckCorrectThrow(const char* script) {
21129 // Test that the script, when wrapped into a try-catch, triggers the catch
21130 // clause due to failed access check throwing an exception.
21131 // The subsequent try-catch should run without any exception.
21132 access_check_fail_thrown = false;
21133 catch_callback_called = false;
21134 i::ScopedVector<char> source(1024);
21135 i::OS::SNPrintF(source, "try { %s; } catch (e) { catcher(e); }", script);
21136 CompileRun(source.start());
21137 CHECK(access_check_fail_thrown);
21138 CHECK(catch_callback_called);
21139
21140 access_check_fail_thrown = false;
21141 catch_callback_called = false;
21142 CompileRun("try { [1, 2, 3].sort(); } catch (e) { catcher(e) };");
21143 CHECK(!access_check_fail_thrown);
21144 CHECK(!catch_callback_called);
21145}
21146
21147
21148TEST(AccessCheckThrows) {
21149 i::FLAG_allow_natives_syntax = true;
21150 v8::V8::Initialize();
21151 v8::V8::SetFailedAccessCheckCallbackFunction(&FailedAccessCheckThrows);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000021152 v8::Isolate* isolate = CcTest::isolate();
21153 v8::HandleScope scope(isolate);
danno@chromium.org169691d2013-07-15 08:01:13 +000021154
21155 // Create an ObjectTemplate for global objects and install access
21156 // check callbacks that will block access.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000021157 v8::Handle<v8::ObjectTemplate> global_template =
21158 v8::ObjectTemplate::New(isolate);
danno@chromium.org169691d2013-07-15 08:01:13 +000021159 global_template->SetAccessCheckCallbacks(NamedAccessAlwaysBlocked,
21160 IndexAccessAlwaysBlocked);
21161
21162 // Create a context and set an x property on it's global object.
21163 LocalContext context0(NULL, global_template);
21164 context0->Global()->Set(v8_str("x"), v8_num(42));
21165 v8::Handle<v8::Object> global0 = context0->Global();
21166
21167 // Create a context with a different security token so that the
21168 // failed access check callback will be called on each access.
21169 LocalContext context1(NULL, global_template);
21170 context1->Global()->Set(v8_str("other"), global0);
21171
21172 v8::Handle<v8::FunctionTemplate> catcher_fun =
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000021173 v8::FunctionTemplate::New(isolate, CatcherCallback);
danno@chromium.org169691d2013-07-15 08:01:13 +000021174 context1->Global()->Set(v8_str("catcher"), catcher_fun->GetFunction());
21175
21176 v8::Handle<v8::FunctionTemplate> has_own_property_fun =
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000021177 v8::FunctionTemplate::New(isolate, HasOwnPropertyCallback);
danno@chromium.org169691d2013-07-15 08:01:13 +000021178 context1->Global()->Set(v8_str("has_own_property"),
21179 has_own_property_fun->GetFunction());
21180
21181 { v8::TryCatch try_catch;
21182 access_check_fail_thrown = false;
21183 CompileRun("other.x;");
21184 CHECK(access_check_fail_thrown);
21185 CHECK(try_catch.HasCaught());
21186 }
21187
21188 CheckCorrectThrow("other.x");
21189 CheckCorrectThrow("other[1]");
21190 CheckCorrectThrow("JSON.stringify(other)");
21191 CheckCorrectThrow("has_own_property(other, 'x')");
21192 CheckCorrectThrow("%GetProperty(other, 'x')");
21193 CheckCorrectThrow("%SetProperty(other, 'x', 'foo', 1, 0)");
21194 CheckCorrectThrow("%IgnoreAttributesAndSetProperty(other, 'x', 'foo')");
21195 CheckCorrectThrow("%DeleteProperty(other, 'x', 0)");
21196 CheckCorrectThrow("%DeleteProperty(other, '1', 0)");
21197 CheckCorrectThrow("%HasLocalProperty(other, 'x')");
21198 CheckCorrectThrow("%HasProperty(other, 'x')");
21199 CheckCorrectThrow("%HasElement(other, 1)");
21200 CheckCorrectThrow("%IsPropertyEnumerable(other, 'x')");
21201 CheckCorrectThrow("%GetPropertyNames(other)");
machenbach@chromium.org03453962014-01-10 14:16:31 +000021202 // PROPERTY_ATTRIBUTES_NONE = 0
21203 CheckCorrectThrow("%GetLocalPropertyNames(other, 0)");
danno@chromium.org169691d2013-07-15 08:01:13 +000021204 CheckCorrectThrow("%DefineOrRedefineAccessorProperty("
21205 "other, 'x', null, null, 1)");
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +000021206
21207 // Reset the failed access check callback so it does not influence
21208 // the other tests.
21209 v8::V8::SetFailedAccessCheckCallbackFunction(NULL);
danno@chromium.org169691d2013-07-15 08:01:13 +000021210}
21211
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000021212
21213THREADED_TEST(Regress256330) {
21214 i::FLAG_allow_natives_syntax = true;
21215 LocalContext context;
21216 v8::HandleScope scope(context->GetIsolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000021217 Handle<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000021218 AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter);
21219 context->Global()->Set(v8_str("Bug"), templ->GetFunction());
21220 CompileRun("\"use strict\"; var o = new Bug;"
21221 "function f(o) { o.x = 10; };"
21222 "f(o); f(o); f(o);"
21223 "%OptimizeFunctionOnNextCall(f);"
21224 "f(o);");
21225 ExpectBoolean("%GetOptimizationStatus(f) != 2", true);
21226}
21227
21228
21229THREADED_TEST(CrankshaftInterceptorSetter) {
21230 i::FLAG_allow_natives_syntax = true;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000021231 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000021232 Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000021233 AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
21234 LocalContext env;
21235 env->Global()->Set(v8_str("Obj"), templ->GetFunction());
21236 CompileRun("var obj = new Obj;"
21237 // Initialize fields to avoid transitions later.
21238 "obj.age = 0;"
21239 "obj.accessor_age = 42;"
21240 "function setter(i) { this.accessor_age = i; };"
21241 "function getter() { return this.accessor_age; };"
21242 "function setAge(i) { obj.age = i; };"
21243 "Object.defineProperty(obj, 'age', { get:getter, set:setter });"
21244 "setAge(1);"
21245 "setAge(2);"
21246 "setAge(3);"
21247 "%OptimizeFunctionOnNextCall(setAge);"
21248 "setAge(4);");
21249 // All stores went through the interceptor.
21250 ExpectInt32("obj.interceptor_age", 4);
21251 ExpectInt32("obj.accessor_age", 42);
21252}
21253
21254
21255THREADED_TEST(CrankshaftInterceptorGetter) {
21256 i::FLAG_allow_natives_syntax = true;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000021257 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000021258 Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000021259 AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
21260 LocalContext env;
21261 env->Global()->Set(v8_str("Obj"), templ->GetFunction());
21262 CompileRun("var obj = new Obj;"
21263 // Initialize fields to avoid transitions later.
21264 "obj.age = 1;"
21265 "obj.accessor_age = 42;"
21266 "function getter() { return this.accessor_age; };"
21267 "function getAge() { return obj.interceptor_age; };"
21268 "Object.defineProperty(obj, 'interceptor_age', { get:getter });"
21269 "getAge();"
21270 "getAge();"
21271 "getAge();"
21272 "%OptimizeFunctionOnNextCall(getAge);");
21273 // Access through interceptor.
21274 ExpectInt32("getAge()", 1);
21275}
21276
21277
21278THREADED_TEST(CrankshaftInterceptorFieldRead) {
21279 i::FLAG_allow_natives_syntax = true;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000021280 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000021281 Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000021282 AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
21283 LocalContext env;
21284 env->Global()->Set(v8_str("Obj"), templ->GetFunction());
21285 CompileRun("var obj = new Obj;"
21286 "obj.__proto__.interceptor_age = 42;"
21287 "obj.age = 100;"
21288 "function getAge() { return obj.interceptor_age; };");
21289 ExpectInt32("getAge();", 100);
21290 ExpectInt32("getAge();", 100);
21291 ExpectInt32("getAge();", 100);
21292 CompileRun("%OptimizeFunctionOnNextCall(getAge);");
21293 // Access through interceptor.
21294 ExpectInt32("getAge();", 100);
21295}
21296
21297
21298THREADED_TEST(CrankshaftInterceptorFieldWrite) {
21299 i::FLAG_allow_natives_syntax = true;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000021300 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000021301 Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000021302 AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
21303 LocalContext env;
21304 env->Global()->Set(v8_str("Obj"), templ->GetFunction());
21305 CompileRun("var obj = new Obj;"
21306 "obj.age = 100000;"
21307 "function setAge(i) { obj.age = i };"
21308 "setAge(100);"
21309 "setAge(101);"
21310 "setAge(102);"
21311 "%OptimizeFunctionOnNextCall(setAge);"
21312 "setAge(103);");
21313 ExpectInt32("obj.age", 100000);
21314 ExpectInt32("obj.interceptor_age", 103);
21315}
21316
dslomov@chromium.org639bac02013-09-09 11:58:54 +000021317
hpayer@chromium.orgea9b8ba2013-12-20 19:22:39 +000021318class RequestInterruptTestBase {
21319 public:
21320 RequestInterruptTestBase()
21321 : env_(),
21322 isolate_(env_->GetIsolate()),
21323 sem_(0),
21324 warmup_(20000),
21325 should_continue_(true) {
21326 }
21327
21328 virtual ~RequestInterruptTestBase() { }
21329
21330 virtual void TestBody() = 0;
21331
21332 void RunTest() {
21333 InterruptThread i_thread(this);
21334 i_thread.Start();
21335
21336 v8::HandleScope handle_scope(isolate_);
21337
21338 TestBody();
21339
21340 isolate_->ClearInterrupt();
21341
21342 // Verify we arrived here because interruptor was called
21343 // not due to a bug causing us to exit the loop too early.
21344 CHECK(!should_continue());
21345 }
21346
21347 void WakeUpInterruptor() {
21348 sem_.Signal();
21349 }
21350
21351 bool should_continue() const { return should_continue_; }
21352
21353 bool ShouldContinue() {
21354 if (warmup_ > 0) {
21355 if (--warmup_ == 0) {
21356 WakeUpInterruptor();
21357 }
21358 }
21359
21360 return should_continue_;
21361 }
21362
21363 protected:
21364 static void ShouldContinueCallback(
21365 const v8::FunctionCallbackInfo<Value>& info) {
21366 RequestInterruptTestBase* test =
21367 reinterpret_cast<RequestInterruptTestBase*>(
21368 info.Data().As<v8::External>()->Value());
21369 info.GetReturnValue().Set(test->ShouldContinue());
21370 }
21371
21372 class InterruptThread : public i::Thread {
21373 public:
21374 explicit InterruptThread(RequestInterruptTestBase* test)
21375 : Thread("RequestInterruptTest"), test_(test) {}
21376
21377 virtual void Run() {
21378 test_->sem_.Wait();
21379 test_->isolate_->RequestInterrupt(&OnInterrupt, test_);
21380 }
21381
21382 static void OnInterrupt(v8::Isolate* isolate, void* data) {
21383 reinterpret_cast<RequestInterruptTestBase*>(data)->
21384 should_continue_ = false;
21385 }
21386
21387 private:
21388 RequestInterruptTestBase* test_;
21389 };
21390
21391 LocalContext env_;
21392 v8::Isolate* isolate_;
21393 i::Semaphore sem_;
21394 int warmup_;
21395 bool should_continue_;
21396};
21397
21398
21399class RequestInterruptTestWithFunctionCall : public RequestInterruptTestBase {
21400 public:
21401 virtual void TestBody() {
21402 Local<Function> func = Function::New(
21403 isolate_, ShouldContinueCallback, v8::External::New(isolate_, this));
21404 env_->Global()->Set(v8_str("ShouldContinue"), func);
21405
21406 CompileRun("while (ShouldContinue()) { }");
21407 }
21408};
21409
21410
21411class RequestInterruptTestWithMethodCall : public RequestInterruptTestBase {
21412 public:
21413 virtual void TestBody() {
21414 v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
21415 v8::Local<v8::Template> proto = t->PrototypeTemplate();
21416 proto->Set(v8_str("shouldContinue"), Function::New(
21417 isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
21418 env_->Global()->Set(v8_str("Klass"), t->GetFunction());
21419
21420 CompileRun("var obj = new Klass; while (obj.shouldContinue()) { }");
21421 }
21422};
21423
21424
21425class RequestInterruptTestWithAccessor : public RequestInterruptTestBase {
21426 public:
21427 virtual void TestBody() {
21428 v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
21429 v8::Local<v8::Template> proto = t->PrototypeTemplate();
21430 proto->SetAccessorProperty(v8_str("shouldContinue"), FunctionTemplate::New(
21431 isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
21432 env_->Global()->Set(v8_str("Klass"), t->GetFunction());
21433
21434 CompileRun("var obj = new Klass; while (obj.shouldContinue) { }");
21435 }
21436};
21437
21438
21439class RequestInterruptTestWithNativeAccessor : public RequestInterruptTestBase {
21440 public:
21441 virtual void TestBody() {
21442 v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
21443 t->InstanceTemplate()->SetNativeDataProperty(
21444 v8_str("shouldContinue"),
21445 &ShouldContinueNativeGetter,
21446 NULL,
21447 v8::External::New(isolate_, this));
21448 env_->Global()->Set(v8_str("Klass"), t->GetFunction());
21449
21450 CompileRun("var obj = new Klass; while (obj.shouldContinue) { }");
21451 }
21452
21453 private:
21454 static void ShouldContinueNativeGetter(
21455 Local<String> property,
21456 const v8::PropertyCallbackInfo<v8::Value>& info) {
21457 RequestInterruptTestBase* test =
21458 reinterpret_cast<RequestInterruptTestBase*>(
21459 info.Data().As<v8::External>()->Value());
21460 info.GetReturnValue().Set(test->ShouldContinue());
21461 }
21462};
21463
21464
21465class RequestInterruptTestWithMethodCallAndInterceptor
21466 : public RequestInterruptTestBase {
21467 public:
21468 virtual void TestBody() {
21469 v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
21470 v8::Local<v8::Template> proto = t->PrototypeTemplate();
21471 proto->Set(v8_str("shouldContinue"), Function::New(
21472 isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
21473 v8::Local<v8::ObjectTemplate> instance_template = t->InstanceTemplate();
21474 instance_template->SetNamedPropertyHandler(EmptyInterceptor);
21475
21476 env_->Global()->Set(v8_str("Klass"), t->GetFunction());
21477
21478 CompileRun("var obj = new Klass; while (obj.shouldContinue()) { }");
21479 }
21480
21481 private:
21482 static void EmptyInterceptor(
21483 Local<String> property,
21484 const v8::PropertyCallbackInfo<v8::Value>& info) {
21485 }
21486};
21487
21488
21489class RequestInterruptTestWithMathAbs : public RequestInterruptTestBase {
21490 public:
21491 virtual void TestBody() {
21492 env_->Global()->Set(v8_str("WakeUpInterruptor"), Function::New(
21493 isolate_,
21494 WakeUpInterruptorCallback,
21495 v8::External::New(isolate_, this)));
21496
21497 env_->Global()->Set(v8_str("ShouldContinue"), Function::New(
21498 isolate_,
21499 ShouldContinueCallback,
21500 v8::External::New(isolate_, this)));
21501
21502 i::FLAG_allow_natives_syntax = true;
21503 CompileRun("function loopish(o) {"
21504 " var pre = 10;"
21505 " while (o.abs(1) > 0) {"
21506 " if (o.abs(1) >= 0 && !ShouldContinue()) break;"
21507 " if (pre > 0) {"
21508 " if (--pre === 0) WakeUpInterruptor(o === Math);"
21509 " }"
21510 " }"
21511 "}"
21512 "var i = 50;"
21513 "var obj = {abs: function () { return i-- }, x: null};"
21514 "delete obj.x;"
21515 "loopish(obj);"
21516 "%OptimizeFunctionOnNextCall(loopish);"
21517 "loopish(Math);");
21518
21519 i::FLAG_allow_natives_syntax = false;
21520 }
21521
21522 private:
21523 static void WakeUpInterruptorCallback(
21524 const v8::FunctionCallbackInfo<Value>& info) {
21525 if (!info[0]->BooleanValue()) return;
21526
21527 RequestInterruptTestBase* test =
21528 reinterpret_cast<RequestInterruptTestBase*>(
21529 info.Data().As<v8::External>()->Value());
21530 test->WakeUpInterruptor();
21531 }
21532
21533 static void ShouldContinueCallback(
21534 const v8::FunctionCallbackInfo<Value>& info) {
21535 RequestInterruptTestBase* test =
21536 reinterpret_cast<RequestInterruptTestBase*>(
21537 info.Data().As<v8::External>()->Value());
21538 info.GetReturnValue().Set(test->should_continue());
21539 }
21540};
21541
21542
21543TEST(RequestInterruptTestWithFunctionCall) {
21544 RequestInterruptTestWithFunctionCall().RunTest();
21545}
21546
21547
21548TEST(RequestInterruptTestWithMethodCall) {
21549 RequestInterruptTestWithMethodCall().RunTest();
21550}
21551
21552
21553TEST(RequestInterruptTestWithAccessor) {
21554 RequestInterruptTestWithAccessor().RunTest();
21555}
21556
21557
21558TEST(RequestInterruptTestWithNativeAccessor) {
21559 RequestInterruptTestWithNativeAccessor().RunTest();
21560}
21561
21562
21563TEST(RequestInterruptTestWithMethodCallAndInterceptor) {
21564 RequestInterruptTestWithMethodCallAndInterceptor().RunTest();
21565}
21566
21567
21568TEST(RequestInterruptTestWithMathAbs) {
21569 RequestInterruptTestWithMathAbs().RunTest();
21570}
dslomov@chromium.org639bac02013-09-09 11:58:54 +000021571
21572
21573static Local<Value> function_new_expected_env;
21574static void FunctionNewCallback(const v8::FunctionCallbackInfo<Value>& info) {
21575 CHECK_EQ(function_new_expected_env, info.Data());
21576 info.GetReturnValue().Set(17);
21577}
21578
21579
21580THREADED_TEST(FunctionNew) {
21581 LocalContext env;
21582 v8::Isolate* isolate = env->GetIsolate();
21583 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000021584 Local<Object> data = v8::Object::New(isolate);
dslomov@chromium.org639bac02013-09-09 11:58:54 +000021585 function_new_expected_env = data;
21586 Local<Function> func = Function::New(isolate, FunctionNewCallback, data);
21587 env->Global()->Set(v8_str("func"), func);
21588 Local<Value> result = CompileRun("func();");
ulan@chromium.org0f13e742014-01-03 15:51:11 +000021589 CHECK_EQ(v8::Integer::New(isolate, 17), result);
dslomov@chromium.org639bac02013-09-09 11:58:54 +000021590 // Verify function not cached
21591 int serial_number =
21592 i::Smi::cast(v8::Utils::OpenHandle(*func)
21593 ->shared()->get_api_func_data()->serial_number())->value();
21594 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
21595 i::Object* elm = i_isolate->native_context()->function_cache()
21596 ->GetElementNoExceptionThrown(i_isolate, serial_number);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000021597 CHECK(elm->IsUndefined());
21598 // Verify that each Function::New creates a new function instance
ulan@chromium.org0f13e742014-01-03 15:51:11 +000021599 Local<Object> data2 = v8::Object::New(isolate);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000021600 function_new_expected_env = data2;
21601 Local<Function> func2 = Function::New(isolate, FunctionNewCallback, data2);
21602 CHECK(!func2->IsNull());
21603 CHECK_NE(func, func2);
21604 env->Global()->Set(v8_str("func2"), func2);
21605 Local<Value> result2 = CompileRun("func2();");
ulan@chromium.org0f13e742014-01-03 15:51:11 +000021606 CHECK_EQ(v8::Integer::New(isolate, 17), result2);
dslomov@chromium.org639bac02013-09-09 11:58:54 +000021607}
21608
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000021609
21610TEST(EscapeableHandleScope) {
21611 HandleScope outer_scope(CcTest::isolate());
21612 LocalContext context;
21613 const int runs = 10;
21614 Local<String> values[runs];
21615 for (int i = 0; i < runs; i++) {
21616 v8::EscapableHandleScope inner_scope(CcTest::isolate());
21617 Local<String> value;
21618 if (i != 0) value = v8_str("escape value");
21619 values[i] = inner_scope.Escape(value);
21620 }
21621 for (int i = 0; i < runs; i++) {
21622 Local<String> expected;
21623 if (i != 0) {
21624 CHECK_EQ(v8_str("escape value"), values[i]);
21625 } else {
21626 CHECK(values[i].IsEmpty());
21627 }
21628 }
21629}