blob: 447cd261ce9daba049a74c8cb4797641f2a246fb [file] [log] [blame]
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001// Copyright 2012 the V8 project authors. All rights reserved.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
verwaest@chromium.org662436e2013-08-28 08:41:27 +000028#include <climits>
29#include <csignal>
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000030#include <string>
31#include <map>
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000032
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000033#include "v8.h"
34
verwaest@chromium.org662436e2013-08-28 08:41:27 +000035#if V8_OS_POSIX
36#include <unistd.h> // NOLINT
37#endif
38
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000039#include "api.h"
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +000040#include "arguments.h"
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000041#include "cctest.h"
machenbach@chromium.orgc1789ee2013-07-05 07:09:57 +000042#include "compilation-cache.h"
43#include "cpu-profiler.h"
44#include "execution.h"
45#include "isolate.h"
46#include "objects.h"
ager@chromium.org5b2fbee2010-09-08 06:38:15 +000047#include "parser.h"
machenbach@chromium.orgc1789ee2013-07-05 07:09:57 +000048#include "platform.h"
49#include "snapshot.h"
erik.corry@gmail.com4a6c3272010-11-18 12:04:40 +000050#include "unicode-inl.h"
machenbach@chromium.orgc1789ee2013-07-05 07:09:57 +000051#include "utils.h"
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +000052#include "vm-state.h"
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000053
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +000054static const bool kLogThreading = false;
ager@chromium.orgc4c92722009-11-18 14:12:51 +000055
danno@chromium.orgd3c42102013-08-01 16:58:23 +000056using ::v8::Boolean;
57using ::v8::BooleanObject;
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +000058using ::v8::Context;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000059using ::v8::Extension;
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +000060using ::v8::Function;
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000061using ::v8::FunctionTemplate;
62using ::v8::Handle;
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +000063using ::v8::HandleScope;
64using ::v8::Local;
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000065using ::v8::Message;
66using ::v8::MessageCallback;
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +000067using ::v8::Object;
68using ::v8::ObjectTemplate;
69using ::v8::Persistent;
70using ::v8::Script;
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000071using ::v8::StackTrace;
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +000072using ::v8::String;
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000073using ::v8::TryCatch;
74using ::v8::Undefined;
danno@chromium.orgca29dd82013-04-26 11:59:48 +000075using ::v8::UniqueId;
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +000076using ::v8::V8;
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000077using ::v8::Value;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000078
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000079
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000080#define THREADED_PROFILED_TEST(Name) \
81 static void Test##Name(); \
82 TEST(Name##WithProfiler) { \
83 RunWithProfiler(&Test##Name); \
84 } \
85 THREADED_TEST(Name)
machenbach@chromium.org528ce022013-09-23 14:09:36 +000086
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000087
88void RunWithProfiler(void (*test)()) {
89 LocalContext env;
90 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000091 v8::Local<v8::String> profile_name =
92 v8::String::NewFromUtf8(env->GetIsolate(), "my_profile1");
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000093 v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler();
94
95 cpu_profiler->StartCpuProfiling(profile_name);
96 (*test)();
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000097 reinterpret_cast<i::CpuProfiler*>(cpu_profiler)->DeleteAllProfiles();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000098}
99
100
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +0000101static void ExpectString(const char* code, const char* expected) {
102 Local<Value> result = CompileRun(code);
103 CHECK(result->IsString());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +0000104 String::Utf8Value utf8(result);
105 CHECK_EQ(expected, *utf8);
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +0000106}
107
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000108
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000109static void ExpectInt32(const char* code, int expected) {
110 Local<Value> result = CompileRun(code);
111 CHECK(result->IsInt32());
112 CHECK_EQ(expected, result->Int32Value());
113}
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +0000114
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000115
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +0000116static void ExpectBoolean(const char* code, bool expected) {
117 Local<Value> result = CompileRun(code);
118 CHECK(result->IsBoolean());
119 CHECK_EQ(expected, result->BooleanValue());
120}
121
122
kmillikin@chromium.org9155e252010-05-26 13:27:57 +0000123static void ExpectTrue(const char* code) {
124 ExpectBoolean(code, true);
125}
126
127
ager@chromium.orgea4f62e2010-08-16 16:28:43 +0000128static void ExpectFalse(const char* code) {
129 ExpectBoolean(code, false);
130}
131
132
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +0000133static void ExpectObject(const char* code, Local<Value> expected) {
134 Local<Value> result = CompileRun(code);
135 CHECK(result->Equals(expected));
136}
137
138
ager@chromium.orgea4f62e2010-08-16 16:28:43 +0000139static void ExpectUndefined(const char* code) {
140 Local<Value> result = CompileRun(code);
141 CHECK(result->IsUndefined());
142}
143
144
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000145static int signature_callback_count;
jkummerow@chromium.org2c9426b2013-09-05 16:31:13 +0000146static Local<Value> signature_expected_receiver;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000147static void IncrementingSignatureCallback(
148 const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000149 ApiTestFuzzer::Fuzz();
150 signature_callback_count++;
jkummerow@chromium.org2c9426b2013-09-05 16:31:13 +0000151 CHECK_EQ(signature_expected_receiver, args.Holder());
152 CHECK_EQ(signature_expected_receiver, args.This());
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000153 v8::Handle<v8::Array> result =
154 v8::Array::New(args.GetIsolate(), args.Length());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000155 for (int i = 0; i < args.Length(); i++)
ulan@chromium.org0f13e742014-01-03 15:51:11 +0000156 result->Set(v8::Integer::New(args.GetIsolate(), i), args[i]);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000157 args.GetReturnValue().Set(result);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000158}
159
160
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000161static void SignatureCallback(
162 const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000163 ApiTestFuzzer::Fuzz();
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000164 v8::Handle<v8::Array> result =
165 v8::Array::New(args.GetIsolate(), args.Length());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000166 for (int i = 0; i < args.Length(); i++) {
ulan@chromium.org0f13e742014-01-03 15:51:11 +0000167 result->Set(v8::Integer::New(args.GetIsolate(), i), args[i]);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000168 }
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000169 args.GetReturnValue().Set(result);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000170}
171
172
dslomov@chromium.org639bac02013-09-09 11:58:54 +0000173// Tests that call v8::V8::Dispose() cannot be threaded.
174TEST(InitializeAndDisposeOnce) {
175 CHECK(v8::V8::Initialize());
176 CHECK(v8::V8::Dispose());
177}
178
179
180// Tests that call v8::V8::Dispose() cannot be threaded.
181TEST(InitializeAndDisposeMultiple) {
182 for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
183 for (int i = 0; i < 3; ++i) CHECK(v8::V8::Initialize());
184 for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
185 // TODO(mstarzinger): This should fail gracefully instead of asserting.
186 // for (int i = 0; i < 3; ++i) CHECK(v8::V8::Initialize());
187 for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
188}
189
190
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000191THREADED_TEST(Handles) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000192 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000193 Local<Context> local_env;
194 {
195 LocalContext env;
196 local_env = env.local();
197 }
198
199 // Local context should still be live.
200 CHECK(!local_env.IsEmpty());
201 local_env->Enter();
202
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +0000203 v8::Handle<v8::Primitive> undef = v8::Undefined(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000204 CHECK(!undef.IsEmpty());
205 CHECK(undef->IsUndefined());
206
207 const char* c_source = "1 + 2 + 3";
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000208 Local<String> source = String::NewFromUtf8(CcTest::isolate(), c_source);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000209 Local<Script> script = Script::Compile(source);
210 CHECK_EQ(6, script->Run()->Int32Value());
211
212 local_env->Exit();
213}
214
215
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000216THREADED_TEST(IsolateOfContext) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000217 v8::HandleScope scope(CcTest::isolate());
218 v8::Handle<Context> env = Context::New(CcTest::isolate());
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000219
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000220 CHECK(!env->GetIsolate()->InContext());
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000221 CHECK(env->GetIsolate() == CcTest::isolate());
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000222 env->Enter();
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000223 CHECK(env->GetIsolate()->InContext());
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000224 CHECK(env->GetIsolate() == CcTest::isolate());
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000225 env->Exit();
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000226 CHECK(!env->GetIsolate()->InContext());
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000227 CHECK(env->GetIsolate() == CcTest::isolate());
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000228}
229
230
dslomov@chromium.org639bac02013-09-09 11:58:54 +0000231static void TestSignature(const char* loop_js, Local<Value> receiver) {
232 i::ScopedVector<char> source(200);
233 i::OS::SNPrintF(source,
234 "for (var i = 0; i < 10; i++) {"
235 " %s"
236 "}",
237 loop_js);
238 signature_callback_count = 0;
239 signature_expected_receiver = receiver;
240 bool expected_to_throw = receiver.IsEmpty();
241 v8::TryCatch try_catch;
242 CompileRun(source.start());
243 CHECK_EQ(expected_to_throw, try_catch.HasCaught());
244 if (!expected_to_throw) {
245 CHECK_EQ(10, signature_callback_count);
246 } else {
247 CHECK_EQ(v8_str("TypeError: Illegal invocation"),
248 try_catch.Exception()->ToString());
249 }
250}
251
252
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000253THREADED_TEST(ReceiverSignature) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000254 LocalContext env;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +0000255 v8::Isolate* isolate = env->GetIsolate();
256 v8::HandleScope scope(isolate);
dslomov@chromium.org639bac02013-09-09 11:58:54 +0000257 // Setup templates.
hpayer@chromium.org4f99be92013-12-18 16:23:55 +0000258 v8::Handle<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(isolate);
259 v8::Handle<v8::Signature> sig = v8::Signature::New(isolate, fun);
dslomov@chromium.org639bac02013-09-09 11:58:54 +0000260 v8::Handle<v8::FunctionTemplate> callback_sig =
261 v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +0000262 isolate, IncrementingSignatureCallback, Local<Value>(), sig);
dslomov@chromium.org639bac02013-09-09 11:58:54 +0000263 v8::Handle<v8::FunctionTemplate> callback =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +0000264 v8::FunctionTemplate::New(isolate, IncrementingSignatureCallback);
265 v8::Handle<v8::FunctionTemplate> sub_fun = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000266 sub_fun->Inherit(fun);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +0000267 v8::Handle<v8::FunctionTemplate> unrel_fun =
268 v8::FunctionTemplate::New(isolate);
dslomov@chromium.org639bac02013-09-09 11:58:54 +0000269 // Install properties.
270 v8::Handle<v8::ObjectTemplate> fun_proto = fun->PrototypeTemplate();
271 fun_proto->Set(v8_str("prop_sig"), callback_sig);
272 fun_proto->Set(v8_str("prop"), callback);
273 fun_proto->SetAccessorProperty(
274 v8_str("accessor_sig"), callback_sig, callback_sig);
275 fun_proto->SetAccessorProperty(v8_str("accessor"), callback, callback);
276 // Instantiate templates.
277 Local<Value> fun_instance = fun->InstanceTemplate()->NewInstance();
278 Local<Value> sub_fun_instance = sub_fun->InstanceTemplate()->NewInstance();
279 // Setup global variables.
280 env->Global()->Set(v8_str("Fun"), fun->GetFunction());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000281 env->Global()->Set(v8_str("UnrelFun"), unrel_fun->GetFunction());
dslomov@chromium.org639bac02013-09-09 11:58:54 +0000282 env->Global()->Set(v8_str("fun_instance"), fun_instance);
283 env->Global()->Set(v8_str("sub_fun_instance"), sub_fun_instance);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000284 CompileRun(
dslomov@chromium.org639bac02013-09-09 11:58:54 +0000285 "var accessor_sig_key = 'accessor_sig';"
286 "var accessor_key = 'accessor';"
287 "var prop_sig_key = 'prop_sig';"
288 "var prop_key = 'prop';"
289 ""
290 "function copy_props(obj) {"
291 " var keys = [accessor_sig_key, accessor_key, prop_sig_key, prop_key];"
292 " var source = Fun.prototype;"
293 " for (var i in keys) {"
294 " var key = keys[i];"
295 " var desc = Object.getOwnPropertyDescriptor(source, key);"
296 " Object.defineProperty(obj, key, desc);"
297 " }"
298 "}"
299 ""
300 "var obj = {};"
301 "copy_props(obj);"
302 "var unrel = new UnrelFun();"
303 "copy_props(unrel);");
304 // Test with and without ICs
305 const char* test_objects[] = {
306 "fun_instance", "sub_fun_instance", "obj", "unrel" };
307 unsigned bad_signature_start_offset = 2;
308 for (unsigned i = 0; i < ARRAY_SIZE(test_objects); i++) {
309 i::ScopedVector<char> source(200);
310 i::OS::SNPrintF(
311 source, "var test_object = %s; test_object", test_objects[i]);
312 Local<Value> test_object = CompileRun(source.start());
313 TestSignature("test_object.prop();", test_object);
314 TestSignature("test_object.accessor;", test_object);
315 TestSignature("test_object[accessor_key];", test_object);
316 TestSignature("test_object.accessor = 1;", test_object);
317 TestSignature("test_object[accessor_key] = 1;", test_object);
318 if (i >= bad_signature_start_offset) test_object = Local<Value>();
319 TestSignature("test_object.prop_sig();", test_object);
320 TestSignature("test_object.accessor_sig;", test_object);
321 TestSignature("test_object[accessor_sig_key];", test_object);
322 TestSignature("test_object.accessor_sig = 1;", test_object);
323 TestSignature("test_object[accessor_sig_key] = 1;", test_object);
324 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000325}
326
327
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000328THREADED_TEST(ArgumentSignature) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000329 LocalContext env;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +0000330 v8::Isolate* isolate = env->GetIsolate();
331 v8::HandleScope scope(isolate);
332 v8::Handle<v8::FunctionTemplate> cons = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000333 cons->SetClassName(v8_str("Cons"));
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000334 v8::Handle<v8::Signature> sig = v8::Signature::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +0000335 isolate, v8::Handle<v8::FunctionTemplate>(), 1, &cons);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000336 v8::Handle<v8::FunctionTemplate> fun =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +0000337 v8::FunctionTemplate::New(isolate,
338 SignatureCallback,
339 v8::Handle<Value>(),
340 sig);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000341 env->Global()->Set(v8_str("Cons"), cons->GetFunction());
342 env->Global()->Set(v8_str("Fun1"), fun->GetFunction());
343
344 v8::Handle<Value> value1 = CompileRun("Fun1(4) == '';");
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000345 CHECK(value1->IsTrue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000346
347 v8::Handle<Value> value2 = CompileRun("Fun1(new Cons()) == '[object Cons]';");
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000348 CHECK(value2->IsTrue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000349
350 v8::Handle<Value> value3 = CompileRun("Fun1() == '';");
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000351 CHECK(value3->IsTrue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000352
hpayer@chromium.org4f99be92013-12-18 16:23:55 +0000353 v8::Handle<v8::FunctionTemplate> cons1 = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000354 cons1->SetClassName(v8_str("Cons1"));
hpayer@chromium.org4f99be92013-12-18 16:23:55 +0000355 v8::Handle<v8::FunctionTemplate> cons2 = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000356 cons2->SetClassName(v8_str("Cons2"));
hpayer@chromium.org4f99be92013-12-18 16:23:55 +0000357 v8::Handle<v8::FunctionTemplate> cons3 = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000358 cons3->SetClassName(v8_str("Cons3"));
359
360 v8::Handle<v8::FunctionTemplate> args[3] = { cons1, cons2, cons3 };
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000361 v8::Handle<v8::Signature> wsig = v8::Signature::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +0000362 isolate, v8::Handle<v8::FunctionTemplate>(), 3, args);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000363 v8::Handle<v8::FunctionTemplate> fun2 =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +0000364 v8::FunctionTemplate::New(isolate,
365 SignatureCallback,
366 v8::Handle<Value>(),
367 wsig);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000368
369 env->Global()->Set(v8_str("Cons1"), cons1->GetFunction());
370 env->Global()->Set(v8_str("Cons2"), cons2->GetFunction());
371 env->Global()->Set(v8_str("Cons3"), cons3->GetFunction());
372 env->Global()->Set(v8_str("Fun2"), fun2->GetFunction());
373 v8::Handle<Value> value4 = CompileRun(
374 "Fun2(new Cons1(), new Cons2(), new Cons3()) =="
375 "'[object Cons1],[object Cons2],[object Cons3]'");
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000376 CHECK(value4->IsTrue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000377
378 v8::Handle<Value> value5 = CompileRun(
379 "Fun2(new Cons1(), new Cons2(), 5) == '[object Cons1],[object Cons2],'");
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000380 CHECK(value5->IsTrue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000381
382 v8::Handle<Value> value6 = CompileRun(
383 "Fun2(new Cons3(), new Cons2(), new Cons1()) == ',[object Cons2],'");
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000384 CHECK(value6->IsTrue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000385
386 v8::Handle<Value> value7 = CompileRun(
387 "Fun2(new Cons1(), new Cons2(), new Cons3(), 'd') == "
388 "'[object Cons1],[object Cons2],[object Cons3],d';");
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000389 CHECK(value7->IsTrue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000390
391 v8::Handle<Value> value8 = CompileRun(
392 "Fun2(new Cons1(), new Cons2()) == '[object Cons1],[object Cons2]'");
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000393 CHECK(value8->IsTrue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000394}
395
396
397THREADED_TEST(HulIgennem) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000398 LocalContext env;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +0000399 v8::Isolate* isolate = env->GetIsolate();
400 v8::HandleScope scope(isolate);
401 v8::Handle<v8::Primitive> undef = v8::Undefined(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000402 Local<String> undef_str = undef->ToString();
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000403 char* value = i::NewArray<char>(undef_str->Utf8Length() + 1);
404 undef_str->WriteUtf8(value);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000405 CHECK_EQ(0, strcmp(value, "undefined"));
406 i::DeleteArray(value);
407}
408
409
410THREADED_TEST(Access) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000411 LocalContext env;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +0000412 v8::Isolate* isolate = env->GetIsolate();
413 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +0000414 Local<v8::Object> obj = v8::Object::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000415 Local<Value> foo_before = obj->Get(v8_str("foo"));
416 CHECK(foo_before->IsUndefined());
417 Local<String> bar_str = v8_str("bar");
418 obj->Set(v8_str("foo"), bar_str);
419 Local<Value> foo_after = obj->Get(v8_str("foo"));
420 CHECK(!foo_after->IsUndefined());
421 CHECK(foo_after->IsString());
422 CHECK_EQ(bar_str, foo_after);
423}
424
425
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000426THREADED_TEST(AccessElement) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000427 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000428 v8::HandleScope scope(env->GetIsolate());
ulan@chromium.org0f13e742014-01-03 15:51:11 +0000429 Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000430 Local<Value> before = obj->Get(1);
431 CHECK(before->IsUndefined());
432 Local<String> bar_str = v8_str("bar");
433 obj->Set(1, bar_str);
434 Local<Value> after = obj->Get(1);
435 CHECK(!after->IsUndefined());
436 CHECK(after->IsString());
437 CHECK_EQ(bar_str, after);
438
439 Local<v8::Array> value = CompileRun("[\"a\", \"b\"]").As<v8::Array>();
440 CHECK_EQ(v8_str("a"), value->Get(0));
441 CHECK_EQ(v8_str("b"), value->Get(1));
442}
443
444
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000445THREADED_TEST(Script) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000446 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000447 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000448 const char* c_source = "1 + 2 + 3";
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000449 Local<String> source = String::NewFromUtf8(env->GetIsolate(), c_source);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000450 Local<Script> script = Script::Compile(source);
451 CHECK_EQ(6, script->Run()->Int32Value());
452}
453
454
455static uint16_t* AsciiToTwoByteString(const char* source) {
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000456 int array_length = i::StrLength(source) + 1;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000457 uint16_t* converted = i::NewArray<uint16_t>(array_length);
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000458 for (int i = 0; i < array_length; i++) converted[i] = source[i];
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000459 return converted;
460}
461
462
463class TestResource: public String::ExternalStringResource {
464 public:
machenbach@chromium.org57a54ac2014-01-31 14:01:53 +0000465 TestResource(uint16_t* data, int* counter = NULL, bool owning_data = true)
466 : data_(data), length_(0), counter_(counter), owning_data_(owning_data) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000467 while (data[length_]) ++length_;
468 }
469
470 ~TestResource() {
machenbach@chromium.org57a54ac2014-01-31 14:01:53 +0000471 if (owning_data_) i::DeleteArray(data_);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000472 if (counter_ != NULL) ++*counter_;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000473 }
474
475 const uint16_t* data() const {
476 return data_;
477 }
478
479 size_t length() const {
480 return length_;
481 }
machenbach@chromium.org57a54ac2014-01-31 14:01:53 +0000482
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000483 private:
484 uint16_t* data_;
485 size_t length_;
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000486 int* counter_;
machenbach@chromium.org57a54ac2014-01-31 14:01:53 +0000487 bool owning_data_;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000488};
489
490
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000491class TestAsciiResource: public String::ExternalAsciiStringResource {
492 public:
machenbach@chromium.org57a54ac2014-01-31 14:01:53 +0000493 TestAsciiResource(const char* data, int* counter = NULL, size_t offset = 0)
494 : orig_data_(data),
495 data_(data + offset),
496 length_(strlen(data) - offset),
497 counter_(counter) { }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000498
499 ~TestAsciiResource() {
machenbach@chromium.org57a54ac2014-01-31 14:01:53 +0000500 i::DeleteArray(orig_data_);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000501 if (counter_ != NULL) ++*counter_;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000502 }
503
504 const char* data() const {
505 return data_;
506 }
507
508 size_t length() const {
509 return length_;
510 }
machenbach@chromium.org57a54ac2014-01-31 14:01:53 +0000511
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000512 private:
machenbach@chromium.org57a54ac2014-01-31 14:01:53 +0000513 const char* orig_data_;
ager@chromium.org5ec48922009-05-05 07:25:34 +0000514 const char* data_;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000515 size_t length_;
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000516 int* counter_;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000517};
518
519
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000520THREADED_TEST(ScriptUsingStringResource) {
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000521 int dispose_count = 0;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000522 const char* c_source = "1 + 2 * 3";
523 uint16_t* two_byte_source = AsciiToTwoByteString(c_source);
524 {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000525 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000526 v8::HandleScope scope(env->GetIsolate());
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000527 TestResource* resource = new TestResource(two_byte_source, &dispose_count);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000528 Local<String> source = String::NewExternal(env->GetIsolate(), resource);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000529 Local<Script> script = Script::Compile(source);
530 Local<Value> value = script->Run();
531 CHECK(value->IsNumber());
532 CHECK_EQ(7, value->Int32Value());
533 CHECK(source->IsExternal());
534 CHECK_EQ(resource,
535 static_cast<TestResource*>(source->GetExternalStringResource()));
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000536 String::Encoding encoding = String::UNKNOWN_ENCODING;
537 CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
538 source->GetExternalStringResourceBase(&encoding));
539 CHECK_EQ(String::TWO_BYTE_ENCODING, encoding);
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000540 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000541 CHECK_EQ(0, dispose_count);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000542 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000543 CcTest::i_isolate()->compilation_cache()->Clear();
544 CcTest::heap()->CollectAllAvailableGarbage();
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000545 CHECK_EQ(1, dispose_count);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000546}
547
548
549THREADED_TEST(ScriptUsingAsciiStringResource) {
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000550 int dispose_count = 0;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000551 const char* c_source = "1 + 2 * 3";
552 {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000553 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000554 v8::HandleScope scope(env->GetIsolate());
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000555 TestAsciiResource* resource = new TestAsciiResource(i::StrDup(c_source),
556 &dispose_count);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000557 Local<String> source = String::NewExternal(env->GetIsolate(), resource);
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000558 CHECK(source->IsExternalAscii());
559 CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
560 source->GetExternalAsciiStringResource());
561 String::Encoding encoding = String::UNKNOWN_ENCODING;
562 CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
563 source->GetExternalStringResourceBase(&encoding));
564 CHECK_EQ(String::ASCII_ENCODING, encoding);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000565 Local<Script> script = Script::Compile(source);
566 Local<Value> value = script->Run();
567 CHECK(value->IsNumber());
568 CHECK_EQ(7, value->Int32Value());
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000569 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000570 CHECK_EQ(0, dispose_count);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000571 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000572 CcTest::i_isolate()->compilation_cache()->Clear();
573 CcTest::heap()->CollectAllAvailableGarbage();
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000574 CHECK_EQ(1, dispose_count);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000575}
576
577
ager@chromium.org6f10e412009-02-13 10:11:16 +0000578THREADED_TEST(ScriptMakingExternalString) {
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000579 int dispose_count = 0;
ager@chromium.org6f10e412009-02-13 10:11:16 +0000580 uint16_t* two_byte_source = AsciiToTwoByteString("1 + 2 * 3");
581 {
ager@chromium.org6f10e412009-02-13 10:11:16 +0000582 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000583 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000584 Local<String> source =
585 String::NewFromTwoByte(env->GetIsolate(), two_byte_source);
ager@chromium.org5c838252010-02-19 08:53:10 +0000586 // Trigger GCs so that the newly allocated string moves to old gen.
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000587 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
588 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000589 CHECK_EQ(source->IsExternal(), false);
590 CHECK_EQ(source->IsExternalAscii(), false);
591 String::Encoding encoding = String::UNKNOWN_ENCODING;
592 CHECK_EQ(NULL, source->GetExternalStringResourceBase(&encoding));
593 CHECK_EQ(String::ASCII_ENCODING, encoding);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000594 bool success = source->MakeExternal(new TestResource(two_byte_source,
595 &dispose_count));
ager@chromium.org6f10e412009-02-13 10:11:16 +0000596 CHECK(success);
597 Local<Script> script = Script::Compile(source);
598 Local<Value> value = script->Run();
599 CHECK(value->IsNumber());
600 CHECK_EQ(7, value->Int32Value());
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000601 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000602 CHECK_EQ(0, dispose_count);
ager@chromium.org6f10e412009-02-13 10:11:16 +0000603 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000604 CcTest::i_isolate()->compilation_cache()->Clear();
605 CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000606 CHECK_EQ(1, dispose_count);
ager@chromium.org6f10e412009-02-13 10:11:16 +0000607}
608
609
610THREADED_TEST(ScriptMakingExternalAsciiString) {
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000611 int dispose_count = 0;
ager@chromium.org6f10e412009-02-13 10:11:16 +0000612 const char* c_source = "1 + 2 * 3";
613 {
ager@chromium.org6f10e412009-02-13 10:11:16 +0000614 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000615 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org6f10e412009-02-13 10:11:16 +0000616 Local<String> source = v8_str(c_source);
ager@chromium.org5c838252010-02-19 08:53:10 +0000617 // Trigger GCs so that the newly allocated string moves to old gen.
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000618 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
619 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
ager@chromium.org6f10e412009-02-13 10:11:16 +0000620 bool success = source->MakeExternal(
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000621 new TestAsciiResource(i::StrDup(c_source), &dispose_count));
ager@chromium.org6f10e412009-02-13 10:11:16 +0000622 CHECK(success);
623 Local<Script> script = Script::Compile(source);
624 Local<Value> value = script->Run();
625 CHECK(value->IsNumber());
626 CHECK_EQ(7, value->Int32Value());
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000627 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000628 CHECK_EQ(0, dispose_count);
ager@chromium.org6f10e412009-02-13 10:11:16 +0000629 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000630 CcTest::i_isolate()->compilation_cache()->Clear();
631 CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000632 CHECK_EQ(1, dispose_count);
ager@chromium.org6f10e412009-02-13 10:11:16 +0000633}
634
635
ager@chromium.org5c838252010-02-19 08:53:10 +0000636TEST(MakingExternalStringConditions) {
ager@chromium.org5c838252010-02-19 08:53:10 +0000637 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000638 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org5c838252010-02-19 08:53:10 +0000639
640 // Free some space in the new space so that we can check freshness.
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000641 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
642 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
ager@chromium.org5c838252010-02-19 08:53:10 +0000643
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000644 uint16_t* two_byte_string = AsciiToTwoByteString("s1");
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000645 Local<String> small_string =
646 String::NewFromTwoByte(env->GetIsolate(), two_byte_string);
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000647 i::DeleteArray(two_byte_string);
648
ager@chromium.org5c838252010-02-19 08:53:10 +0000649 // We should refuse to externalize newly created small string.
650 CHECK(!small_string->CanMakeExternal());
651 // Trigger GCs so that the newly allocated string moves to old gen.
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000652 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
653 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
ager@chromium.org5c838252010-02-19 08:53:10 +0000654 // Old space strings should be accepted.
655 CHECK(small_string->CanMakeExternal());
656
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000657 two_byte_string = AsciiToTwoByteString("small string 2");
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000658 small_string = String::NewFromTwoByte(env->GetIsolate(), two_byte_string);
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000659 i::DeleteArray(two_byte_string);
660
ager@chromium.org5c838252010-02-19 08:53:10 +0000661 // We should refuse externalizing newly created small string.
662 CHECK(!small_string->CanMakeExternal());
663 for (int i = 0; i < 100; i++) {
664 String::Value value(small_string);
665 }
666 // Frequently used strings should be accepted.
667 CHECK(small_string->CanMakeExternal());
668
669 const int buf_size = 10 * 1024;
670 char* buf = i::NewArray<char>(buf_size);
671 memset(buf, 'a', buf_size);
672 buf[buf_size - 1] = '\0';
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000673
674 two_byte_string = AsciiToTwoByteString(buf);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000675 Local<String> large_string =
676 String::NewFromTwoByte(env->GetIsolate(), two_byte_string);
ager@chromium.org5c838252010-02-19 08:53:10 +0000677 i::DeleteArray(buf);
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000678 i::DeleteArray(two_byte_string);
ager@chromium.org5c838252010-02-19 08:53:10 +0000679 // Large strings should be immediately accepted.
680 CHECK(large_string->CanMakeExternal());
681}
682
683
684TEST(MakingExternalAsciiStringConditions) {
ager@chromium.org5c838252010-02-19 08:53:10 +0000685 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000686 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org5c838252010-02-19 08:53:10 +0000687
688 // Free some space in the new space so that we can check freshness.
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000689 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
690 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
ager@chromium.org5c838252010-02-19 08:53:10 +0000691
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000692 Local<String> small_string = String::NewFromUtf8(env->GetIsolate(), "s1");
ager@chromium.org5c838252010-02-19 08:53:10 +0000693 // We should refuse to externalize newly created small string.
694 CHECK(!small_string->CanMakeExternal());
695 // Trigger GCs so that the newly allocated string moves to old gen.
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000696 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
697 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
ager@chromium.org5c838252010-02-19 08:53:10 +0000698 // Old space strings should be accepted.
699 CHECK(small_string->CanMakeExternal());
700
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000701 small_string = String::NewFromUtf8(env->GetIsolate(), "small string 2");
ager@chromium.org5c838252010-02-19 08:53:10 +0000702 // We should refuse externalizing newly created small string.
703 CHECK(!small_string->CanMakeExternal());
704 for (int i = 0; i < 100; i++) {
705 String::Value value(small_string);
706 }
707 // Frequently used strings should be accepted.
708 CHECK(small_string->CanMakeExternal());
709
710 const int buf_size = 10 * 1024;
711 char* buf = i::NewArray<char>(buf_size);
712 memset(buf, 'a', buf_size);
713 buf[buf_size - 1] = '\0';
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000714 Local<String> large_string = String::NewFromUtf8(env->GetIsolate(), buf);
ager@chromium.org5c838252010-02-19 08:53:10 +0000715 i::DeleteArray(buf);
716 // Large strings should be immediately accepted.
717 CHECK(large_string->CanMakeExternal());
718}
719
720
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000721TEST(MakingExternalUnalignedAsciiString) {
722 LocalContext env;
723 v8::HandleScope scope(env->GetIsolate());
724
725 CompileRun("function cons(a, b) { return a + b; }"
726 "function slice(a) { return a.substring(1); }");
727 // Create a cons string that will land in old pointer space.
728 Local<String> cons = Local<String>::Cast(CompileRun(
729 "cons('abcdefghijklm', 'nopqrstuvwxyz');"));
730 // Create a sliced string that will land in old pointer space.
731 Local<String> slice = Local<String>::Cast(CompileRun(
732 "slice('abcdefghijklmnopqrstuvwxyz');"));
733
734 // Trigger GCs so that the newly allocated string moves to old gen.
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000735 SimulateFullSpace(CcTest::heap()->old_pointer_space());
736 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
737 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000738
739 // Turn into external string with unaligned resource data.
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000740 const char* c_cons = "_abcdefghijklmnopqrstuvwxyz";
741 bool success = cons->MakeExternal(
machenbach@chromium.org0a730362014-02-05 03:04:56 +0000742 new TestAsciiResource(i::StrDup(c_cons), NULL, 1));
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000743 CHECK(success);
744 const char* c_slice = "_bcdefghijklmnopqrstuvwxyz";
745 success = slice->MakeExternal(
machenbach@chromium.org0a730362014-02-05 03:04:56 +0000746 new TestAsciiResource(i::StrDup(c_slice), NULL, 1));
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000747 CHECK(success);
748
749 // Trigger GCs and force evacuation.
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000750 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
751 CcTest::heap()->CollectAllGarbage(i::Heap::kReduceMemoryFootprintMask);
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000752}
753
754
ager@chromium.org6f10e412009-02-13 10:11:16 +0000755THREADED_TEST(UsingExternalString) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000756 i::Factory* factory = CcTest::i_isolate()->factory();
ager@chromium.orge2902be2009-06-08 12:21:35 +0000757 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000758 v8::HandleScope scope(CcTest::isolate());
ager@chromium.orge2902be2009-06-08 12:21:35 +0000759 uint16_t* two_byte_string = AsciiToTwoByteString("test string");
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000760 Local<String> string = String::NewExternal(
761 CcTest::isolate(), new TestResource(two_byte_string));
ager@chromium.orge2902be2009-06-08 12:21:35 +0000762 i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
763 // Trigger GCs so that the newly allocated string moves to old gen.
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000764 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
765 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000766 i::Handle<i::String> isymbol =
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000767 factory->InternalizedStringFromString(istring);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000768 CHECK(isymbol->IsInternalizedString());
ager@chromium.orge2902be2009-06-08 12:21:35 +0000769 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000770 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
771 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org6f10e412009-02-13 10:11:16 +0000772}
773
774
775THREADED_TEST(UsingExternalAsciiString) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000776 i::Factory* factory = CcTest::i_isolate()->factory();
ager@chromium.orge2902be2009-06-08 12:21:35 +0000777 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000778 v8::HandleScope scope(CcTest::isolate());
ager@chromium.orge2902be2009-06-08 12:21:35 +0000779 const char* one_byte_string = "test string";
780 Local<String> string = String::NewExternal(
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000781 CcTest::isolate(), new TestAsciiResource(i::StrDup(one_byte_string)));
ager@chromium.orge2902be2009-06-08 12:21:35 +0000782 i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
783 // Trigger GCs so that the newly allocated string moves to old gen.
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000784 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
785 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000786 i::Handle<i::String> isymbol =
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000787 factory->InternalizedStringFromString(istring);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000788 CHECK(isymbol->IsInternalizedString());
ager@chromium.orge2902be2009-06-08 12:21:35 +0000789 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000790 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
791 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org6f10e412009-02-13 10:11:16 +0000792}
793
794
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000795THREADED_TEST(ScavengeExternalString) {
svenpanne@chromium.org83130cf2012-11-30 10:13:25 +0000796 i::FLAG_stress_compaction = false;
797 i::FLAG_gc_global = false;
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000798 int dispose_count = 0;
lrn@chromium.orgc34f5802010-04-28 12:53:43 +0000799 bool in_new_space = false;
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000800 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000801 v8::HandleScope scope(CcTest::isolate());
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000802 uint16_t* two_byte_string = AsciiToTwoByteString("test string");
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000803 Local<String> string = String::NewExternal(
804 CcTest::isolate(), new TestResource(two_byte_string, &dispose_count));
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000805 i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000806 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
807 in_new_space = CcTest::heap()->InNewSpace(*istring);
808 CHECK(in_new_space || CcTest::heap()->old_data_space()->Contains(*istring));
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000809 CHECK_EQ(0, dispose_count);
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000810 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000811 CcTest::heap()->CollectGarbage(
812 in_new_space ? i::NEW_SPACE : i::OLD_DATA_SPACE);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000813 CHECK_EQ(1, dispose_count);
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000814}
815
816
817THREADED_TEST(ScavengeExternalAsciiString) {
svenpanne@chromium.org83130cf2012-11-30 10:13:25 +0000818 i::FLAG_stress_compaction = false;
819 i::FLAG_gc_global = false;
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000820 int dispose_count = 0;
lrn@chromium.orgc34f5802010-04-28 12:53:43 +0000821 bool in_new_space = false;
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000822 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000823 v8::HandleScope scope(CcTest::isolate());
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000824 const char* one_byte_string = "test string";
825 Local<String> string = String::NewExternal(
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000826 CcTest::isolate(),
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000827 new TestAsciiResource(i::StrDup(one_byte_string), &dispose_count));
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000828 i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000829 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
830 in_new_space = CcTest::heap()->InNewSpace(*istring);
831 CHECK(in_new_space || CcTest::heap()->old_data_space()->Contains(*istring));
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000832 CHECK_EQ(0, dispose_count);
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000833 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000834 CcTest::heap()->CollectGarbage(
835 in_new_space ? i::NEW_SPACE : i::OLD_DATA_SPACE);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000836 CHECK_EQ(1, dispose_count);
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000837}
838
839
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000840class TestAsciiResourceWithDisposeControl: public TestAsciiResource {
841 public:
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000842 // Only used by non-threaded tests, so it can use static fields.
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000843 static int dispose_calls;
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000844 static int dispose_count;
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000845
846 TestAsciiResourceWithDisposeControl(const char* data, bool dispose)
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000847 : TestAsciiResource(data, &dispose_count),
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000848 dispose_(dispose) { }
849
850 void Dispose() {
851 ++dispose_calls;
852 if (dispose_) delete this;
853 }
854 private:
855 bool dispose_;
856};
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000857
858
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000859int TestAsciiResourceWithDisposeControl::dispose_count = 0;
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000860int TestAsciiResourceWithDisposeControl::dispose_calls = 0;
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000861
862
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000863TEST(ExternalStringWithDisposeHandling) {
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000864 const char* c_source = "1 + 2 * 3";
865
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000866 // Use a stack allocated external string resource allocated object.
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000867 TestAsciiResourceWithDisposeControl::dispose_count = 0;
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000868 TestAsciiResourceWithDisposeControl::dispose_calls = 0;
869 TestAsciiResourceWithDisposeControl res_stack(i::StrDup(c_source), false);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000870 {
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000871 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000872 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000873 Local<String> source = String::NewExternal(env->GetIsolate(), &res_stack);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000874 Local<Script> script = Script::Compile(source);
875 Local<Value> value = script->Run();
876 CHECK(value->IsNumber());
877 CHECK_EQ(7, value->Int32Value());
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000878 CcTest::heap()->CollectAllAvailableGarbage();
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000879 CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000880 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000881 CcTest::i_isolate()->compilation_cache()->Clear();
882 CcTest::heap()->CollectAllAvailableGarbage();
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000883 CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_calls);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000884 CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000885
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000886 // Use a heap allocated external string resource allocated object.
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000887 TestAsciiResourceWithDisposeControl::dispose_count = 0;
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000888 TestAsciiResourceWithDisposeControl::dispose_calls = 0;
889 TestAsciiResource* res_heap =
890 new TestAsciiResourceWithDisposeControl(i::StrDup(c_source), true);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000891 {
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000892 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000893 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000894 Local<String> source = String::NewExternal(env->GetIsolate(), res_heap);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000895 Local<Script> script = Script::Compile(source);
896 Local<Value> value = script->Run();
897 CHECK(value->IsNumber());
898 CHECK_EQ(7, value->Int32Value());
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000899 CcTest::heap()->CollectAllAvailableGarbage();
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000900 CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000901 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000902 CcTest::i_isolate()->compilation_cache()->Clear();
903 CcTest::heap()->CollectAllAvailableGarbage();
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000904 CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_calls);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000905 CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_count);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000906}
907
908
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000909THREADED_TEST(StringConcat) {
910 {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000911 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000912 v8::HandleScope scope(env->GetIsolate());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000913 const char* one_byte_string_1 = "function a_times_t";
914 const char* two_byte_string_1 = "wo_plus_b(a, b) {return ";
915 const char* one_byte_extern_1 = "a * 2 + b;} a_times_two_plus_b(4, 8) + ";
916 const char* two_byte_extern_1 = "a_times_two_plus_b(4, 8) + ";
917 const char* one_byte_string_2 = "a_times_two_plus_b(4, 8) + ";
918 const char* two_byte_string_2 = "a_times_two_plus_b(4, 8) + ";
919 const char* two_byte_extern_2 = "a_times_two_plus_b(1, 2);";
920 Local<String> left = v8_str(one_byte_string_1);
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000921
922 uint16_t* two_byte_source = AsciiToTwoByteString(two_byte_string_1);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000923 Local<String> right =
924 String::NewFromTwoByte(env->GetIsolate(), two_byte_source);
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000925 i::DeleteArray(two_byte_source);
926
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000927 Local<String> source = String::Concat(left, right);
928 right = String::NewExternal(
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000929 env->GetIsolate(), new TestAsciiResource(i::StrDup(one_byte_extern_1)));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000930 source = String::Concat(source, right);
931 right = String::NewExternal(
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000932 env->GetIsolate(),
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000933 new TestResource(AsciiToTwoByteString(two_byte_extern_1)));
934 source = String::Concat(source, right);
935 right = v8_str(one_byte_string_2);
936 source = String::Concat(source, right);
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000937
938 two_byte_source = AsciiToTwoByteString(two_byte_string_2);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000939 right = String::NewFromTwoByte(env->GetIsolate(), two_byte_source);
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000940 i::DeleteArray(two_byte_source);
941
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000942 source = String::Concat(source, right);
943 right = String::NewExternal(
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000944 env->GetIsolate(),
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000945 new TestResource(AsciiToTwoByteString(two_byte_extern_2)));
946 source = String::Concat(source, right);
947 Local<Script> script = Script::Compile(source);
948 Local<Value> value = script->Run();
949 CHECK(value->IsNumber());
950 CHECK_EQ(68, value->Int32Value());
951 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000952 CcTest::i_isolate()->compilation_cache()->Clear();
953 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
954 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000955}
956
957
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000958THREADED_TEST(GlobalProperties) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000959 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000960 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000961 v8::Handle<v8::Object> global = env->Global();
962 global->Set(v8_str("pi"), v8_num(3.1415926));
963 Local<Value> pi = global->Get(v8_str("pi"));
964 CHECK_EQ(3.1415926, pi->NumberValue());
965}
966
967
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +0000968template<typename T>
dslomov@chromium.orgb752d402013-06-18 11:54:54 +0000969static void CheckReturnValue(const T& t, i::Address callback) {
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +0000970 v8::ReturnValue<v8::Value> rv = t.GetReturnValue();
971 i::Object** o = *reinterpret_cast<i::Object***>(&rv);
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000972 CHECK_EQ(CcTest::isolate(), t.GetIsolate());
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +0000973 CHECK_EQ(t.GetIsolate(), rv.GetIsolate());
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +0000974 CHECK((*o)->IsTheHole() || (*o)->IsUndefined());
verwaest@chromium.org8a00e822013-06-10 15:11:22 +0000975 // Verify reset
976 bool is_runtime = (*o)->IsTheHole();
977 rv.Set(true);
978 CHECK(!(*o)->IsTheHole() && !(*o)->IsUndefined());
979 rv.Set(v8::Handle<v8::Object>());
980 CHECK((*o)->IsTheHole() || (*o)->IsUndefined());
981 CHECK_EQ(is_runtime, (*o)->IsTheHole());
dslomov@chromium.orgb752d402013-06-18 11:54:54 +0000982
983 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(t.GetIsolate());
984 // If CPU profiler is active check that when API callback is invoked
985 // VMState is set to EXTERNAL.
986 if (isolate->cpu_profiler()->is_profiling()) {
987 CHECK_EQ(i::EXTERNAL, isolate->current_vm_state());
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +0000988 CHECK(isolate->external_callback_scope());
989 CHECK_EQ(callback, isolate->external_callback_scope()->callback());
dslomov@chromium.orgb752d402013-06-18 11:54:54 +0000990 }
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +0000991}
992
dslomov@chromium.orgb752d402013-06-18 11:54:54 +0000993
994static void handle_callback_impl(const v8::FunctionCallbackInfo<Value>& info,
995 i::Address callback) {
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +0000996 ApiTestFuzzer::Fuzz();
dslomov@chromium.orgb752d402013-06-18 11:54:54 +0000997 CheckReturnValue(info, callback);
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +0000998 info.GetReturnValue().Set(v8_str("bad value"));
999 info.GetReturnValue().Set(v8_num(102));
1000}
1001
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001002
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001003static void handle_callback(const v8::FunctionCallbackInfo<Value>& info) {
1004 return handle_callback_impl(info, FUNCTION_ADDR(handle_callback));
1005}
1006
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001007
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00001008static void handle_callback_2(const v8::FunctionCallbackInfo<Value>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001009 return handle_callback_impl(info, FUNCTION_ADDR(handle_callback_2));
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00001010}
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001011
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001012static void construct_callback(
1013 const v8::FunctionCallbackInfo<Value>& info) {
1014 ApiTestFuzzer::Fuzz();
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001015 CheckReturnValue(info, FUNCTION_ADDR(construct_callback));
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001016 info.This()->Set(v8_str("x"), v8_num(1));
1017 info.This()->Set(v8_str("y"), v8_num(2));
1018 info.GetReturnValue().Set(v8_str("bad value"));
1019 info.GetReturnValue().Set(info.This());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +00001020}
1021
1022
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001023static void Return239Callback(
1024 Local<String> name, const v8::PropertyCallbackInfo<Value>& info) {
1025 ApiTestFuzzer::Fuzz();
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001026 CheckReturnValue(info, FUNCTION_ADDR(Return239Callback));
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001027 info.GetReturnValue().Set(v8_str("bad value"));
1028 info.GetReturnValue().Set(v8_num(239));
1029}
1030
1031
1032template<typename Handler>
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00001033static void TestFunctionTemplateInitializer(Handler handler,
1034 Handler handler_2) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001035 // Test constructor calls.
1036 {
1037 LocalContext env;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001038 v8::Isolate* isolate = env->GetIsolate();
1039 v8::HandleScope scope(isolate);
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001040
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001041 Local<v8::FunctionTemplate> fun_templ =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001042 v8::FunctionTemplate::New(isolate, handler);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001043 Local<Function> fun = fun_templ->GetFunction();
1044 env->Global()->Set(v8_str("obj"), fun);
1045 Local<Script> script = v8_compile("obj()");
1046 for (int i = 0; i < 30; i++) {
1047 CHECK_EQ(102, script->Run()->Int32Value());
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001048 }
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001049 }
1050 // Use SetCallHandler to initialize a function template, should work like
1051 // the previous one.
1052 {
1053 LocalContext env;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001054 v8::Isolate* isolate = env->GetIsolate();
1055 v8::HandleScope scope(isolate);
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001056
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001057 Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(isolate);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001058 fun_templ->SetCallHandler(handler_2);
1059 Local<Function> fun = fun_templ->GetFunction();
1060 env->Global()->Set(v8_str("obj"), fun);
1061 Local<Script> script = v8_compile("obj()");
1062 for (int i = 0; i < 30; i++) {
1063 CHECK_EQ(102, script->Run()->Int32Value());
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001064 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001065 }
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001066}
1067
1068
1069template<typename Constructor, typename Accessor>
1070static void TestFunctionTemplateAccessor(Constructor constructor,
1071 Accessor accessor) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001072 LocalContext env;
1073 v8::HandleScope scope(env->GetIsolate());
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001074
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001075 Local<v8::FunctionTemplate> fun_templ =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001076 v8::FunctionTemplate::New(env->GetIsolate(), constructor);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001077 fun_templ->SetClassName(v8_str("funky"));
1078 fun_templ->InstanceTemplate()->SetAccessor(v8_str("m"), accessor);
1079 Local<Function> fun = fun_templ->GetFunction();
1080 env->Global()->Set(v8_str("obj"), fun);
1081 Local<Value> result = v8_compile("(new obj()).toString()")->Run();
1082 CHECK_EQ(v8_str("[object funky]"), result);
1083 CompileRun("var obj_instance = new obj();");
1084 Local<Script> script;
1085 script = v8_compile("obj_instance.x");
1086 for (int i = 0; i < 30; i++) {
1087 CHECK_EQ(1, script->Run()->Int32Value());
1088 }
1089 script = v8_compile("obj_instance.m");
1090 for (int i = 0; i < 30; i++) {
1091 CHECK_EQ(239, script->Run()->Int32Value());
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001092 }
1093}
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001094
ager@chromium.orgb61a0d12010-10-13 08:35:23 +00001095
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001096THREADED_PROFILED_TEST(FunctionTemplate) {
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00001097 TestFunctionTemplateInitializer(handle_callback, handle_callback_2);
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001098 TestFunctionTemplateAccessor(construct_callback, Return239Callback);
1099}
1100
1101
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001102static void SimpleCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
1103 ApiTestFuzzer::Fuzz();
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001104 CheckReturnValue(info, FUNCTION_ADDR(SimpleCallback));
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001105 info.GetReturnValue().Set(v8_num(51423 + info.Length()));
1106}
1107
1108
1109template<typename Callback>
1110static void TestSimpleCallback(Callback callback) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001111 LocalContext env;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00001112 v8::Isolate* isolate = env->GetIsolate();
1113 v8::HandleScope scope(isolate);
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001114
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00001115 v8::Handle<v8::ObjectTemplate> object_template =
1116 v8::ObjectTemplate::New(isolate);
1117 object_template->Set(isolate, "callback",
1118 v8::FunctionTemplate::New(isolate, callback));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001119 v8::Local<v8::Object> object = object_template->NewInstance();
1120 (*env)->Global()->Set(v8_str("callback_object"), object);
1121 v8::Handle<v8::Script> script;
1122 script = v8_compile("callback_object.callback(17)");
1123 for (int i = 0; i < 30; i++) {
1124 CHECK_EQ(51424, script->Run()->Int32Value());
1125 }
1126 script = v8_compile("callback_object.callback(17, 24)");
1127 for (int i = 0; i < 30; i++) {
1128 CHECK_EQ(51425, script->Run()->Int32Value());
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001129 }
1130}
1131
1132
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001133THREADED_PROFILED_TEST(SimpleCallback) {
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001134 TestSimpleCallback(SimpleCallback);
1135}
1136
1137
1138template<typename T>
1139void FastReturnValueCallback(const v8::FunctionCallbackInfo<v8::Value>& info);
1140
1141// constant return values
danno@chromium.org1fd77d52013-06-07 16:01:45 +00001142static int32_t fast_return_value_int32 = 471;
1143static uint32_t fast_return_value_uint32 = 571;
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001144static const double kFastReturnValueDouble = 2.7;
1145// variable return values
1146static bool fast_return_value_bool = false;
ulan@chromium.org837a67e2013-06-11 15:39:48 +00001147enum ReturnValueOddball {
1148 kNullReturnValue,
1149 kUndefinedReturnValue,
1150 kEmptyStringReturnValue
1151};
1152static ReturnValueOddball fast_return_value_void;
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00001153static bool fast_return_value_object_is_empty = false;
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001154
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001155// Helper function to avoid compiler error: insufficient contextual information
1156// to determine type when applying FUNCTION_ADDR to a template function.
1157static i::Address address_of(v8::FunctionCallback callback) {
1158 return FUNCTION_ADDR(callback);
1159}
1160
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001161template<>
1162void FastReturnValueCallback<int32_t>(
1163 const v8::FunctionCallbackInfo<v8::Value>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001164 CheckReturnValue(info, address_of(FastReturnValueCallback<int32_t>));
danno@chromium.org1fd77d52013-06-07 16:01:45 +00001165 info.GetReturnValue().Set(fast_return_value_int32);
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001166}
1167
1168template<>
1169void FastReturnValueCallback<uint32_t>(
1170 const v8::FunctionCallbackInfo<v8::Value>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001171 CheckReturnValue(info, address_of(FastReturnValueCallback<uint32_t>));
danno@chromium.org1fd77d52013-06-07 16:01:45 +00001172 info.GetReturnValue().Set(fast_return_value_uint32);
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001173}
1174
1175template<>
1176void FastReturnValueCallback<double>(
1177 const v8::FunctionCallbackInfo<v8::Value>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001178 CheckReturnValue(info, address_of(FastReturnValueCallback<double>));
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +00001179 info.GetReturnValue().Set(kFastReturnValueDouble);
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001180}
1181
1182template<>
1183void FastReturnValueCallback<bool>(
1184 const v8::FunctionCallbackInfo<v8::Value>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001185 CheckReturnValue(info, address_of(FastReturnValueCallback<bool>));
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +00001186 info.GetReturnValue().Set(fast_return_value_bool);
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001187}
1188
1189template<>
1190void FastReturnValueCallback<void>(
1191 const v8::FunctionCallbackInfo<v8::Value>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001192 CheckReturnValue(info, address_of(FastReturnValueCallback<void>));
ulan@chromium.org837a67e2013-06-11 15:39:48 +00001193 switch (fast_return_value_void) {
1194 case kNullReturnValue:
1195 info.GetReturnValue().SetNull();
1196 break;
1197 case kUndefinedReturnValue:
1198 info.GetReturnValue().SetUndefined();
1199 break;
1200 case kEmptyStringReturnValue:
1201 info.GetReturnValue().SetEmptyString();
1202 break;
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001203 }
1204}
1205
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +00001206template<>
1207void FastReturnValueCallback<Object>(
1208 const v8::FunctionCallbackInfo<v8::Value>& info) {
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00001209 v8::Handle<v8::Object> object;
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001210 if (!fast_return_value_object_is_empty) {
1211 object = Object::New(info.GetIsolate());
1212 }
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00001213 info.GetReturnValue().Set(object);
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +00001214}
1215
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001216template<typename T>
1217Handle<Value> TestFastReturnValues() {
1218 LocalContext env;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00001219 v8::Isolate* isolate = env->GetIsolate();
1220 v8::EscapableHandleScope scope(isolate);
1221 v8::Handle<v8::ObjectTemplate> object_template =
1222 v8::ObjectTemplate::New(isolate);
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001223 v8::FunctionCallback callback = &FastReturnValueCallback<T>;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00001224 object_template->Set(isolate, "callback",
1225 v8::FunctionTemplate::New(isolate, callback));
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001226 v8::Local<v8::Object> object = object_template->NewInstance();
1227 (*env)->Global()->Set(v8_str("callback_object"), object);
machenbach@chromium.orgafbdadc2013-12-09 16:12:18 +00001228 return scope.Escape(CompileRun("callback_object.callback()"));
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001229}
1230
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001231
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001232THREADED_PROFILED_TEST(FastReturnValues) {
danno@chromium.org1fd77d52013-06-07 16:01:45 +00001233 LocalContext env;
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001234 v8::HandleScope scope(CcTest::isolate());
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001235 v8::Handle<v8::Value> value;
danno@chromium.org1fd77d52013-06-07 16:01:45 +00001236 // check int32_t and uint32_t
1237 int32_t int_values[] = {
1238 0, 234, -723,
1239 i::Smi::kMinValue, i::Smi::kMaxValue
1240 };
1241 for (size_t i = 0; i < ARRAY_SIZE(int_values); i++) {
1242 for (int modifier = -1; modifier <= 1; modifier++) {
1243 int int_value = int_values[i] + modifier;
1244 // check int32_t
1245 fast_return_value_int32 = int_value;
1246 value = TestFastReturnValues<int32_t>();
1247 CHECK(value->IsInt32());
1248 CHECK(fast_return_value_int32 == value->Int32Value());
1249 // check uint32_t
1250 fast_return_value_uint32 = static_cast<uint32_t>(int_value);
1251 value = TestFastReturnValues<uint32_t>();
1252 CHECK(value->IsUint32());
1253 CHECK(fast_return_value_uint32 == value->Uint32Value());
1254 }
1255 }
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001256 // check double
1257 value = TestFastReturnValues<double>();
1258 CHECK(value->IsNumber());
1259 CHECK_EQ(kFastReturnValueDouble, value->ToNumber()->Value());
1260 // check bool values
1261 for (int i = 0; i < 2; i++) {
1262 fast_return_value_bool = i == 0;
1263 value = TestFastReturnValues<bool>();
1264 CHECK(value->IsBoolean());
1265 CHECK_EQ(fast_return_value_bool, value->ToBoolean()->Value());
1266 }
1267 // check oddballs
ulan@chromium.org837a67e2013-06-11 15:39:48 +00001268 ReturnValueOddball oddballs[] = {
1269 kNullReturnValue,
1270 kUndefinedReturnValue,
1271 kEmptyStringReturnValue
1272 };
1273 for (size_t i = 0; i < ARRAY_SIZE(oddballs); i++) {
1274 fast_return_value_void = oddballs[i];
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001275 value = TestFastReturnValues<void>();
ulan@chromium.org837a67e2013-06-11 15:39:48 +00001276 switch (fast_return_value_void) {
1277 case kNullReturnValue:
1278 CHECK(value->IsNull());
1279 break;
1280 case kUndefinedReturnValue:
1281 CHECK(value->IsUndefined());
1282 break;
1283 case kEmptyStringReturnValue:
1284 CHECK(value->IsString());
1285 CHECK_EQ(0, v8::String::Cast(*value)->Length());
1286 break;
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001287 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001288 }
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00001289 // check handles
1290 fast_return_value_object_is_empty = false;
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +00001291 value = TestFastReturnValues<Object>();
1292 CHECK(value->IsObject());
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00001293 fast_return_value_object_is_empty = true;
1294 value = TestFastReturnValues<Object>();
1295 CHECK(value->IsUndefined());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001296}
1297
1298
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001299THREADED_TEST(FunctionTemplateSetLength) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001300 LocalContext env;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001301 v8::Isolate* isolate = env->GetIsolate();
1302 v8::HandleScope scope(isolate);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001303 {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001304 Local<v8::FunctionTemplate> fun_templ =
1305 v8::FunctionTemplate::New(isolate,
1306 handle_callback,
1307 Handle<v8::Value>(),
1308 Handle<v8::Signature>(),
1309 23);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001310 Local<Function> fun = fun_templ->GetFunction();
1311 env->Global()->Set(v8_str("obj"), fun);
1312 Local<Script> script = v8_compile("obj.length");
1313 CHECK_EQ(23, script->Run()->Int32Value());
1314 }
1315 {
1316 Local<v8::FunctionTemplate> fun_templ =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001317 v8::FunctionTemplate::New(isolate, handle_callback);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001318 fun_templ->SetLength(22);
1319 Local<Function> fun = fun_templ->GetFunction();
1320 env->Global()->Set(v8_str("obj"), fun);
1321 Local<Script> script = v8_compile("obj.length");
1322 CHECK_EQ(22, script->Run()->Int32Value());
1323 }
1324 {
1325 // Without setting length it defaults to 0.
1326 Local<v8::FunctionTemplate> fun_templ =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001327 v8::FunctionTemplate::New(isolate, handle_callback);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001328 Local<Function> fun = fun_templ->GetFunction();
1329 env->Global()->Set(v8_str("obj"), fun);
1330 Local<Script> script = v8_compile("obj.length");
1331 CHECK_EQ(0, script->Run()->Int32Value());
1332 }
1333}
1334
1335
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001336static void* expected_ptr;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001337static void callback(const v8::FunctionCallbackInfo<v8::Value>& args) {
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00001338 void* ptr = v8::External::Cast(*args.Data())->Value();
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001339 CHECK_EQ(expected_ptr, ptr);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001340 args.GetReturnValue().Set(true);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001341}
1342
1343
1344static void TestExternalPointerWrapping() {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001345 LocalContext env;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001346 v8::Isolate* isolate = env->GetIsolate();
1347 v8::HandleScope scope(isolate);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001348
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00001349 v8::Handle<v8::Value> data =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001350 v8::External::New(isolate, expected_ptr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001351
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001352 v8::Handle<v8::Object> obj = v8::Object::New(isolate);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001353 obj->Set(v8_str("func"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001354 v8::FunctionTemplate::New(isolate, callback, data)->GetFunction());
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001355 env->Global()->Set(v8_str("obj"), obj);
1356
1357 CHECK(CompileRun(
1358 "function foo() {\n"
1359 " for (var i = 0; i < 13; i++) obj.func();\n"
1360 "}\n"
1361 "foo(), true")->BooleanValue());
1362}
1363
1364
1365THREADED_TEST(ExternalWrap) {
1366 // Check heap allocated object.
1367 int* ptr = new int;
1368 expected_ptr = ptr;
1369 TestExternalPointerWrapping();
1370 delete ptr;
1371
1372 // Check stack allocated object.
1373 int foo;
1374 expected_ptr = &foo;
1375 TestExternalPointerWrapping();
1376
1377 // Check not aligned addresses.
1378 const int n = 100;
1379 char* s = new char[n];
1380 for (int i = 0; i < n; i++) {
1381 expected_ptr = s + i;
1382 TestExternalPointerWrapping();
1383 }
1384
1385 delete[] s;
1386
1387 // Check several invalid addresses.
1388 expected_ptr = reinterpret_cast<void*>(1);
1389 TestExternalPointerWrapping();
1390
1391 expected_ptr = reinterpret_cast<void*>(0xdeadbeef);
1392 TestExternalPointerWrapping();
1393
1394 expected_ptr = reinterpret_cast<void*>(0xdeadbeef + 1);
1395 TestExternalPointerWrapping();
1396
1397#if defined(V8_HOST_ARCH_X64)
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001398 // Check a value with a leading 1 bit in x64 Smi encoding.
1399 expected_ptr = reinterpret_cast<void*>(0x400000000);
1400 TestExternalPointerWrapping();
1401
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001402 expected_ptr = reinterpret_cast<void*>(0xdeadbeefdeadbeef);
1403 TestExternalPointerWrapping();
1404
1405 expected_ptr = reinterpret_cast<void*>(0xdeadbeefdeadbeef + 1);
1406 TestExternalPointerWrapping();
1407#endif
1408}
1409
1410
sgjesse@chromium.org900d3b72009-08-07 11:24:25 +00001411THREADED_TEST(FindInstanceInPrototypeChain) {
sgjesse@chromium.org900d3b72009-08-07 11:24:25 +00001412 LocalContext env;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001413 v8::Isolate* isolate = env->GetIsolate();
1414 v8::HandleScope scope(isolate);
sgjesse@chromium.org900d3b72009-08-07 11:24:25 +00001415
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001416 Local<v8::FunctionTemplate> base = v8::FunctionTemplate::New(isolate);
1417 Local<v8::FunctionTemplate> derived = v8::FunctionTemplate::New(isolate);
1418 Local<v8::FunctionTemplate> other = v8::FunctionTemplate::New(isolate);
sgjesse@chromium.org900d3b72009-08-07 11:24:25 +00001419 derived->Inherit(base);
1420
1421 Local<v8::Function> base_function = base->GetFunction();
1422 Local<v8::Function> derived_function = derived->GetFunction();
1423 Local<v8::Function> other_function = other->GetFunction();
1424
1425 Local<v8::Object> base_instance = base_function->NewInstance();
1426 Local<v8::Object> derived_instance = derived_function->NewInstance();
1427 Local<v8::Object> derived_instance2 = derived_function->NewInstance();
1428 Local<v8::Object> other_instance = other_function->NewInstance();
1429 derived_instance2->Set(v8_str("__proto__"), derived_instance);
1430 other_instance->Set(v8_str("__proto__"), derived_instance2);
1431
1432 // base_instance is only an instance of base.
1433 CHECK_EQ(base_instance,
1434 base_instance->FindInstanceInPrototypeChain(base));
1435 CHECK(base_instance->FindInstanceInPrototypeChain(derived).IsEmpty());
1436 CHECK(base_instance->FindInstanceInPrototypeChain(other).IsEmpty());
1437
1438 // derived_instance is an instance of base and derived.
1439 CHECK_EQ(derived_instance,
1440 derived_instance->FindInstanceInPrototypeChain(base));
1441 CHECK_EQ(derived_instance,
1442 derived_instance->FindInstanceInPrototypeChain(derived));
1443 CHECK(derived_instance->FindInstanceInPrototypeChain(other).IsEmpty());
1444
1445 // other_instance is an instance of other and its immediate
1446 // prototype derived_instance2 is an instance of base and derived.
1447 // Note, derived_instance is an instance of base and derived too,
1448 // but it comes after derived_instance2 in the prototype chain of
1449 // other_instance.
1450 CHECK_EQ(derived_instance2,
1451 other_instance->FindInstanceInPrototypeChain(base));
1452 CHECK_EQ(derived_instance2,
1453 other_instance->FindInstanceInPrototypeChain(derived));
1454 CHECK_EQ(other_instance,
1455 other_instance->FindInstanceInPrototypeChain(other));
1456}
1457
1458
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001459THREADED_TEST(TinyInteger) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001460 LocalContext env;
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001461 v8::Isolate* isolate = env->GetIsolate();
1462 v8::HandleScope scope(isolate);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001463
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001464 int32_t value = 239;
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001465 Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001466 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001467
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001468 value_obj = v8::Integer::New(isolate, value);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001469 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001470}
1471
1472
1473THREADED_TEST(BigSmiInteger) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001474 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001475 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001476 v8::Isolate* isolate = CcTest::isolate();
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001477
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001478 int32_t value = i::Smi::kMaxValue;
1479 // We cannot add one to a Smi::kMaxValue without wrapping.
verwaest@chromium.org662436e2013-08-28 08:41:27 +00001480 if (i::SmiValuesAre31Bits()) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001481 CHECK(i::Smi::IsValid(value));
1482 CHECK(!i::Smi::IsValid(value + 1));
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001483
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001484 Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001485 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001486
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001487 value_obj = v8::Integer::New(isolate, value);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001488 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001489 }
1490}
1491
1492
1493THREADED_TEST(BigInteger) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001494 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001495 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001496 v8::Isolate* isolate = CcTest::isolate();
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001497
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001498 // We cannot add one to a Smi::kMaxValue without wrapping.
verwaest@chromium.org662436e2013-08-28 08:41:27 +00001499 if (i::SmiValuesAre31Bits()) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001500 // The casts allow this to compile, even if Smi::kMaxValue is 2^31-1.
1501 // The code will not be run in that case, due to the "if" guard.
1502 int32_t value =
1503 static_cast<int32_t>(static_cast<uint32_t>(i::Smi::kMaxValue) + 1);
1504 CHECK(value > i::Smi::kMaxValue);
1505 CHECK(!i::Smi::IsValid(value));
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001506
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001507 Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001508 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001509
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001510 value_obj = v8::Integer::New(isolate, value);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001511 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001512 }
1513}
1514
1515
1516THREADED_TEST(TinyUnsignedInteger) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001517 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001518 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001519 v8::Isolate* isolate = CcTest::isolate();
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001520
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001521 uint32_t value = 239;
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001522
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001523 Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001524 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001525
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001526 value_obj = v8::Integer::NewFromUnsigned(isolate, value);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001527 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001528}
1529
1530
1531THREADED_TEST(BigUnsignedSmiInteger) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001532 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001533 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001534 v8::Isolate* isolate = CcTest::isolate();
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001535
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001536 uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue);
1537 CHECK(i::Smi::IsValid(value));
1538 CHECK(!i::Smi::IsValid(value + 1));
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001539
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001540 Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001541 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001542
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001543 value_obj = v8::Integer::NewFromUnsigned(isolate, value);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001544 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001545}
1546
1547
1548THREADED_TEST(BigUnsignedInteger) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001549 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001550 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001551 v8::Isolate* isolate = CcTest::isolate();
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001552
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001553 uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue) + 1;
1554 CHECK(value > static_cast<uint32_t>(i::Smi::kMaxValue));
1555 CHECK(!i::Smi::IsValid(value));
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001556
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001557 Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001558 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001559
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001560 value_obj = v8::Integer::NewFromUnsigned(isolate, value);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001561 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001562}
1563
1564
1565THREADED_TEST(OutOfSignedRangeUnsignedInteger) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001566 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001567 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001568 v8::Isolate* isolate = CcTest::isolate();
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001569
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001570 uint32_t INT32_MAX_AS_UINT = (1U << 31) - 1;
1571 uint32_t value = INT32_MAX_AS_UINT + 1;
1572 CHECK(value > INT32_MAX_AS_UINT); // No overflow.
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001573
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001574 Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001575 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001576
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001577 value_obj = v8::Integer::NewFromUnsigned(isolate, value);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001578 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001579}
1580
1581
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001582THREADED_TEST(IsNativeError) {
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001583 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001584 v8::HandleScope scope(env->GetIsolate());
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001585 v8::Handle<Value> syntax_error = CompileRun(
1586 "var out = 0; try { eval(\"#\"); } catch(x) { out = x; } out; ");
1587 CHECK(syntax_error->IsNativeError());
1588 v8::Handle<Value> not_error = CompileRun("{a:42}");
1589 CHECK(!not_error->IsNativeError());
1590 v8::Handle<Value> not_object = CompileRun("42");
1591 CHECK(!not_object->IsNativeError());
1592}
1593
1594
1595THREADED_TEST(StringObject) {
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001596 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001597 v8::HandleScope scope(env->GetIsolate());
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001598 v8::Handle<Value> boxed_string = CompileRun("new String(\"test\")");
1599 CHECK(boxed_string->IsStringObject());
1600 v8::Handle<Value> unboxed_string = CompileRun("\"test\"");
1601 CHECK(!unboxed_string->IsStringObject());
1602 v8::Handle<Value> boxed_not_string = CompileRun("new Number(42)");
1603 CHECK(!boxed_not_string->IsStringObject());
1604 v8::Handle<Value> not_object = CompileRun("0");
1605 CHECK(!not_object->IsStringObject());
1606 v8::Handle<v8::StringObject> as_boxed = boxed_string.As<v8::StringObject>();
1607 CHECK(!as_boxed.IsEmpty());
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001608 Local<v8::String> the_string = as_boxed->ValueOf();
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001609 CHECK(!the_string.IsEmpty());
1610 ExpectObject("\"test\"", the_string);
1611 v8::Handle<v8::Value> new_boxed_string = v8::StringObject::New(the_string);
1612 CHECK(new_boxed_string->IsStringObject());
1613 as_boxed = new_boxed_string.As<v8::StringObject>();
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001614 the_string = as_boxed->ValueOf();
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001615 CHECK(!the_string.IsEmpty());
1616 ExpectObject("\"test\"", the_string);
1617}
1618
1619
1620THREADED_TEST(NumberObject) {
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001621 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001622 v8::HandleScope scope(env->GetIsolate());
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001623 v8::Handle<Value> boxed_number = CompileRun("new Number(42)");
1624 CHECK(boxed_number->IsNumberObject());
1625 v8::Handle<Value> unboxed_number = CompileRun("42");
1626 CHECK(!unboxed_number->IsNumberObject());
1627 v8::Handle<Value> boxed_not_number = CompileRun("new Boolean(false)");
1628 CHECK(!boxed_not_number->IsNumberObject());
1629 v8::Handle<v8::NumberObject> as_boxed = boxed_number.As<v8::NumberObject>();
1630 CHECK(!as_boxed.IsEmpty());
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001631 double the_number = as_boxed->ValueOf();
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001632 CHECK_EQ(42.0, the_number);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00001633 v8::Handle<v8::Value> new_boxed_number =
1634 v8::NumberObject::New(env->GetIsolate(), 43);
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001635 CHECK(new_boxed_number->IsNumberObject());
1636 as_boxed = new_boxed_number.As<v8::NumberObject>();
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001637 the_number = as_boxed->ValueOf();
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001638 CHECK_EQ(43.0, the_number);
1639}
1640
1641
1642THREADED_TEST(BooleanObject) {
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001643 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001644 v8::HandleScope scope(env->GetIsolate());
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001645 v8::Handle<Value> boxed_boolean = CompileRun("new Boolean(true)");
1646 CHECK(boxed_boolean->IsBooleanObject());
1647 v8::Handle<Value> unboxed_boolean = CompileRun("true");
1648 CHECK(!unboxed_boolean->IsBooleanObject());
1649 v8::Handle<Value> boxed_not_boolean = CompileRun("new Number(42)");
1650 CHECK(!boxed_not_boolean->IsBooleanObject());
1651 v8::Handle<v8::BooleanObject> as_boxed =
1652 boxed_boolean.As<v8::BooleanObject>();
1653 CHECK(!as_boxed.IsEmpty());
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001654 bool the_boolean = as_boxed->ValueOf();
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001655 CHECK_EQ(true, the_boolean);
1656 v8::Handle<v8::Value> boxed_true = v8::BooleanObject::New(true);
1657 v8::Handle<v8::Value> boxed_false = v8::BooleanObject::New(false);
1658 CHECK(boxed_true->IsBooleanObject());
1659 CHECK(boxed_false->IsBooleanObject());
1660 as_boxed = boxed_true.As<v8::BooleanObject>();
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001661 CHECK_EQ(true, as_boxed->ValueOf());
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001662 as_boxed = boxed_false.As<v8::BooleanObject>();
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001663 CHECK_EQ(false, as_boxed->ValueOf());
1664}
1665
1666
1667THREADED_TEST(PrimitiveAndWrappedBooleans) {
1668 LocalContext env;
1669 v8::HandleScope scope(env->GetIsolate());
1670
machenbach@chromium.org37be4082013-11-26 13:50:38 +00001671 Local<Value> primitive_false = Boolean::New(env->GetIsolate(), false);
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001672 CHECK(primitive_false->IsBoolean());
1673 CHECK(!primitive_false->IsBooleanObject());
1674 CHECK(!primitive_false->BooleanValue());
1675 CHECK(!primitive_false->IsTrue());
1676 CHECK(primitive_false->IsFalse());
1677
1678 Local<Value> false_value = BooleanObject::New(false);
1679 CHECK(!false_value->IsBoolean());
1680 CHECK(false_value->IsBooleanObject());
1681 CHECK(false_value->BooleanValue());
1682 CHECK(!false_value->IsTrue());
1683 CHECK(!false_value->IsFalse());
1684
1685 Local<BooleanObject> false_boolean_object = false_value.As<BooleanObject>();
1686 CHECK(!false_boolean_object->IsBoolean());
1687 CHECK(false_boolean_object->IsBooleanObject());
1688 // TODO(svenpanne) Uncomment when BooleanObject::BooleanValue() is deleted.
1689 // CHECK(false_boolean_object->BooleanValue());
1690 CHECK(!false_boolean_object->ValueOf());
1691 CHECK(!false_boolean_object->IsTrue());
1692 CHECK(!false_boolean_object->IsFalse());
1693
machenbach@chromium.org37be4082013-11-26 13:50:38 +00001694 Local<Value> primitive_true = Boolean::New(env->GetIsolate(), true);
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001695 CHECK(primitive_true->IsBoolean());
1696 CHECK(!primitive_true->IsBooleanObject());
1697 CHECK(primitive_true->BooleanValue());
1698 CHECK(primitive_true->IsTrue());
1699 CHECK(!primitive_true->IsFalse());
1700
1701 Local<Value> true_value = BooleanObject::New(true);
1702 CHECK(!true_value->IsBoolean());
1703 CHECK(true_value->IsBooleanObject());
1704 CHECK(true_value->BooleanValue());
1705 CHECK(!true_value->IsTrue());
1706 CHECK(!true_value->IsFalse());
1707
1708 Local<BooleanObject> true_boolean_object = true_value.As<BooleanObject>();
1709 CHECK(!true_boolean_object->IsBoolean());
1710 CHECK(true_boolean_object->IsBooleanObject());
1711 // TODO(svenpanne) Uncomment when BooleanObject::BooleanValue() is deleted.
1712 // CHECK(true_boolean_object->BooleanValue());
1713 CHECK(true_boolean_object->ValueOf());
1714 CHECK(!true_boolean_object->IsTrue());
1715 CHECK(!true_boolean_object->IsFalse());
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001716}
1717
1718
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001719THREADED_TEST(Number) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001720 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001721 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001722 double PI = 3.1415926;
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001723 Local<v8::Number> pi_obj = v8::Number::New(env->GetIsolate(), PI);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001724 CHECK_EQ(PI, pi_obj->NumberValue());
1725}
1726
1727
1728THREADED_TEST(ToNumber) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001729 LocalContext env;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00001730 v8::Isolate* isolate = CcTest::isolate();
1731 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001732 Local<String> str = v8_str("3.1415926");
1733 CHECK_EQ(3.1415926, str->NumberValue());
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00001734 v8::Handle<v8::Boolean> t = v8::True(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001735 CHECK_EQ(1.0, t->NumberValue());
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00001736 v8::Handle<v8::Boolean> f = v8::False(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001737 CHECK_EQ(0.0, f->NumberValue());
1738}
1739
1740
1741THREADED_TEST(Date) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001742 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001743 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001744 double PI = 3.1415926;
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00001745 Local<Value> date = v8::Date::New(env->GetIsolate(), PI);
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +00001746 CHECK_EQ(3.0, date->NumberValue());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001747 date.As<v8::Date>()->Set(v8_str("property"),
1748 v8::Integer::New(env->GetIsolate(), 42));
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +00001749 CHECK_EQ(42, date.As<v8::Date>()->Get(v8_str("property"))->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001750}
1751
1752
1753THREADED_TEST(Boolean) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001754 LocalContext env;
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001755 v8::Isolate* isolate = env->GetIsolate();
1756 v8::HandleScope scope(isolate);
1757 v8::Handle<v8::Boolean> t = v8::True(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001758 CHECK(t->Value());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001759 v8::Handle<v8::Boolean> f = v8::False(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001760 CHECK(!f->Value());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001761 v8::Handle<v8::Primitive> u = v8::Undefined(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001762 CHECK(!u->BooleanValue());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001763 v8::Handle<v8::Primitive> n = v8::Null(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001764 CHECK(!n->BooleanValue());
1765 v8::Handle<String> str1 = v8_str("");
1766 CHECK(!str1->BooleanValue());
1767 v8::Handle<String> str2 = v8_str("x");
1768 CHECK(str2->BooleanValue());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001769 CHECK(!v8::Number::New(isolate, 0)->BooleanValue());
1770 CHECK(v8::Number::New(isolate, -1)->BooleanValue());
1771 CHECK(v8::Number::New(isolate, 1)->BooleanValue());
1772 CHECK(v8::Number::New(isolate, 42)->BooleanValue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001773 CHECK(!v8_compile("NaN")->Run()->BooleanValue());
1774}
1775
1776
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001777static void DummyCallHandler(const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001778 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001779 args.GetReturnValue().Set(v8_num(13.4));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001780}
1781
1782
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001783static void GetM(Local<String> name,
1784 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001785 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001786 info.GetReturnValue().Set(v8_num(876));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001787}
1788
1789
1790THREADED_TEST(GlobalPrototype) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001791 v8::Isolate* isolate = CcTest::isolate();
1792 v8::HandleScope scope(isolate);
1793 v8::Handle<v8::FunctionTemplate> func_templ =
1794 v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001795 func_templ->PrototypeTemplate()->Set(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001796 isolate, "dummy", v8::FunctionTemplate::New(isolate, DummyCallHandler));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001797 v8::Handle<ObjectTemplate> templ = func_templ->InstanceTemplate();
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001798 templ->Set(isolate, "x", v8_num(200));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001799 templ->SetAccessor(v8_str("m"), GetM);
1800 LocalContext env(0, templ);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001801 v8::Handle<Script> script(v8_compile("dummy()"));
1802 v8::Handle<Value> result(script->Run());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001803 CHECK_EQ(13.4, result->NumberValue());
1804 CHECK_EQ(200, v8_compile("x")->Run()->Int32Value());
1805 CHECK_EQ(876, v8_compile("m")->Run()->Int32Value());
1806}
1807
1808
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001809THREADED_TEST(ObjectTemplate) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001810 v8::Isolate* isolate = CcTest::isolate();
1811 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00001812 Local<ObjectTemplate> templ1 = ObjectTemplate::New(isolate);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001813 templ1->Set(isolate, "x", v8_num(10));
1814 templ1->Set(isolate, "y", v8_num(13));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001815 LocalContext env;
1816 Local<v8::Object> instance1 = templ1->NewInstance();
1817 env->Global()->Set(v8_str("p"), instance1);
1818 CHECK(v8_compile("(p.x == 10)")->Run()->BooleanValue());
1819 CHECK(v8_compile("(p.y == 13)")->Run()->BooleanValue());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001820 Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(isolate);
1821 fun->PrototypeTemplate()->Set(isolate, "nirk", v8_num(123));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001822 Local<ObjectTemplate> templ2 = fun->InstanceTemplate();
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001823 templ2->Set(isolate, "a", v8_num(12));
1824 templ2->Set(isolate, "b", templ1);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001825 Local<v8::Object> instance2 = templ2->NewInstance();
1826 env->Global()->Set(v8_str("q"), instance2);
1827 CHECK(v8_compile("(q.nirk == 123)")->Run()->BooleanValue());
1828 CHECK(v8_compile("(q.a == 12)")->Run()->BooleanValue());
1829 CHECK(v8_compile("(q.b.x == 10)")->Run()->BooleanValue());
1830 CHECK(v8_compile("(q.b.y == 13)")->Run()->BooleanValue());
1831}
1832
1833
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001834static void GetFlabby(const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001835 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001836 args.GetReturnValue().Set(v8_num(17.2));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001837}
1838
1839
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001840static void GetKnurd(Local<String> property,
1841 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001842 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001843 info.GetReturnValue().Set(v8_num(15.2));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001844}
1845
1846
1847THREADED_TEST(DescriptorInheritance) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001848 v8::Isolate* isolate = CcTest::isolate();
1849 v8::HandleScope scope(isolate);
1850 v8::Handle<v8::FunctionTemplate> super = v8::FunctionTemplate::New(isolate);
1851 super->PrototypeTemplate()->Set(isolate, "flabby",
1852 v8::FunctionTemplate::New(isolate,
1853 GetFlabby));
1854 super->PrototypeTemplate()->Set(isolate, "PI", v8_num(3.14));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001855
1856 super->InstanceTemplate()->SetAccessor(v8_str("knurd"), GetKnurd);
1857
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001858 v8::Handle<v8::FunctionTemplate> base1 = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001859 base1->Inherit(super);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001860 base1->PrototypeTemplate()->Set(isolate, "v1", v8_num(20.1));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001861
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001862 v8::Handle<v8::FunctionTemplate> base2 = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001863 base2->Inherit(super);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001864 base2->PrototypeTemplate()->Set(isolate, "v2", v8_num(10.1));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001865
1866 LocalContext env;
1867
1868 env->Global()->Set(v8_str("s"), super->GetFunction());
1869 env->Global()->Set(v8_str("base1"), base1->GetFunction());
1870 env->Global()->Set(v8_str("base2"), base2->GetFunction());
1871
1872 // Checks right __proto__ chain.
1873 CHECK(CompileRun("base1.prototype.__proto__ == s.prototype")->BooleanValue());
1874 CHECK(CompileRun("base2.prototype.__proto__ == s.prototype")->BooleanValue());
1875
1876 CHECK(v8_compile("s.prototype.PI == 3.14")->Run()->BooleanValue());
1877
1878 // Instance accessor should not be visible on function object or its prototype
1879 CHECK(CompileRun("s.knurd == undefined")->BooleanValue());
1880 CHECK(CompileRun("s.prototype.knurd == undefined")->BooleanValue());
1881 CHECK(CompileRun("base1.prototype.knurd == undefined")->BooleanValue());
1882
1883 env->Global()->Set(v8_str("obj"),
1884 base1->GetFunction()->NewInstance());
1885 CHECK_EQ(17.2, v8_compile("obj.flabby()")->Run()->NumberValue());
1886 CHECK(v8_compile("'flabby' in obj")->Run()->BooleanValue());
1887 CHECK_EQ(15.2, v8_compile("obj.knurd")->Run()->NumberValue());
1888 CHECK(v8_compile("'knurd' in obj")->Run()->BooleanValue());
1889 CHECK_EQ(20.1, v8_compile("obj.v1")->Run()->NumberValue());
1890
1891 env->Global()->Set(v8_str("obj2"),
1892 base2->GetFunction()->NewInstance());
1893 CHECK_EQ(17.2, v8_compile("obj2.flabby()")->Run()->NumberValue());
1894 CHECK(v8_compile("'flabby' in obj2")->Run()->BooleanValue());
1895 CHECK_EQ(15.2, v8_compile("obj2.knurd")->Run()->NumberValue());
1896 CHECK(v8_compile("'knurd' in obj2")->Run()->BooleanValue());
1897 CHECK_EQ(10.1, v8_compile("obj2.v2")->Run()->NumberValue());
1898
1899 // base1 and base2 cannot cross reference to each's prototype
1900 CHECK(v8_compile("obj.v2")->Run()->IsUndefined());
1901 CHECK(v8_compile("obj2.v1")->Run()->IsUndefined());
1902}
1903
1904
1905int echo_named_call_count;
1906
1907
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001908static void EchoNamedProperty(Local<String> name,
1909 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001910 ApiTestFuzzer::Fuzz();
1911 CHECK_EQ(v8_str("data"), info.Data());
1912 echo_named_call_count++;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001913 info.GetReturnValue().Set(name);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001914}
1915
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001916
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001917// Helper functions for Interceptor/Accessor interaction tests
1918
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001919void SimpleAccessorGetter(Local<String> name,
1920 const v8::PropertyCallbackInfo<v8::Value>& info) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001921 Handle<Object> self = info.This();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001922 info.GetReturnValue().Set(
1923 self->Get(String::Concat(v8_str("accessor_"), name)));
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001924}
1925
1926void SimpleAccessorSetter(Local<String> name, Local<Value> value,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001927 const v8::PropertyCallbackInfo<void>& info) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001928 Handle<Object> self = info.This();
1929 self->Set(String::Concat(v8_str("accessor_"), name), value);
1930}
1931
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001932void EmptyInterceptorGetter(Local<String> name,
1933 const v8::PropertyCallbackInfo<v8::Value>& info) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001934}
1935
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001936void EmptyInterceptorSetter(Local<String> name,
1937 Local<Value> value,
1938 const v8::PropertyCallbackInfo<v8::Value>& info) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001939}
1940
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001941void InterceptorGetter(Local<String> name,
1942 const v8::PropertyCallbackInfo<v8::Value>& info) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001943 // Intercept names that start with 'interceptor_'.
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00001944 String::Utf8Value utf8(name);
1945 char* name_str = *utf8;
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001946 char prefix[] = "interceptor_";
1947 int i;
1948 for (i = 0; name_str[i] && prefix[i]; ++i) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001949 if (name_str[i] != prefix[i]) return;
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001950 }
1951 Handle<Object> self = info.This();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001952 info.GetReturnValue().Set(self->GetHiddenValue(v8_str(name_str + i)));
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001953}
1954
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001955void InterceptorSetter(Local<String> name,
1956 Local<Value> value,
1957 const v8::PropertyCallbackInfo<v8::Value>& info) {
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +00001958 // Intercept accesses that set certain integer values, for which the name does
1959 // not start with 'accessor_'.
1960 String::Utf8Value utf8(name);
1961 char* name_str = *utf8;
1962 char prefix[] = "accessor_";
1963 int i;
1964 for (i = 0; name_str[i] && prefix[i]; ++i) {
1965 if (name_str[i] != prefix[i]) break;
1966 }
1967 if (!prefix[i]) return;
1968
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001969 if (value->IsInt32() && value->Int32Value() < 10000) {
1970 Handle<Object> self = info.This();
1971 self->SetHiddenValue(name, value);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001972 info.GetReturnValue().Set(value);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001973 }
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001974}
1975
1976void AddAccessor(Handle<FunctionTemplate> templ,
1977 Handle<String> name,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001978 v8::AccessorGetterCallback getter,
1979 v8::AccessorSetterCallback setter) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001980 templ->PrototypeTemplate()->SetAccessor(name, getter, setter);
1981}
1982
1983void AddInterceptor(Handle<FunctionTemplate> templ,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001984 v8::NamedPropertyGetterCallback getter,
1985 v8::NamedPropertySetterCallback setter) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001986 templ->InstanceTemplate()->SetNamedPropertyHandler(getter, setter);
1987}
1988
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001989
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001990THREADED_TEST(EmptyInterceptorDoesNotShadowAccessors) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001991 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001992 Handle<FunctionTemplate> parent = FunctionTemplate::New(CcTest::isolate());
1993 Handle<FunctionTemplate> child = FunctionTemplate::New(CcTest::isolate());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001994 child->Inherit(parent);
1995 AddAccessor(parent, v8_str("age"),
1996 SimpleAccessorGetter, SimpleAccessorSetter);
1997 AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter);
1998 LocalContext env;
1999 env->Global()->Set(v8_str("Child"), child->GetFunction());
2000 CompileRun("var child = new Child;"
2001 "child.age = 10;");
2002 ExpectBoolean("child.hasOwnProperty('age')", false);
2003 ExpectInt32("child.age", 10);
2004 ExpectInt32("child.accessor_age", 10);
2005}
2006
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002007
machenbach@chromium.orgbbbda922014-01-23 09:38:20 +00002008THREADED_TEST(EmptyInterceptorBreakTransitions) {
2009 v8::HandleScope scope(CcTest::isolate());
2010 Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
2011 AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter);
2012 LocalContext env;
2013 env->Global()->Set(v8_str("Constructor"), templ->GetFunction());
2014 CompileRun("var o1 = new Constructor;"
2015 "o1.a = 1;" // Ensure a and x share the descriptor array.
2016 "Object.defineProperty(o1, 'x', {value: 10});");
2017 CompileRun("var o2 = new Constructor;"
2018 "o2.a = 1;"
2019 "Object.defineProperty(o2, 'x', {value: 10});");
2020}
2021
2022
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002023THREADED_TEST(EmptyInterceptorDoesNotShadowJSAccessors) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002024 v8::Isolate* isolate = CcTest::isolate();
2025 v8::HandleScope scope(isolate);
2026 Handle<FunctionTemplate> parent = FunctionTemplate::New(isolate);
2027 Handle<FunctionTemplate> child = FunctionTemplate::New(isolate);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002028 child->Inherit(parent);
2029 AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter);
2030 LocalContext env;
2031 env->Global()->Set(v8_str("Child"), child->GetFunction());
2032 CompileRun("var child = new Child;"
2033 "var parent = child.__proto__;"
2034 "Object.defineProperty(parent, 'age', "
2035 " {get: function(){ return this.accessor_age; }, "
2036 " set: function(v){ this.accessor_age = v; }, "
2037 " enumerable: true, configurable: true});"
2038 "child.age = 10;");
2039 ExpectBoolean("child.hasOwnProperty('age')", false);
2040 ExpectInt32("child.age", 10);
2041 ExpectInt32("child.accessor_age", 10);
2042}
2043
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002044
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002045THREADED_TEST(EmptyInterceptorDoesNotAffectJSProperties) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002046 v8::Isolate* isolate = CcTest::isolate();
2047 v8::HandleScope scope(isolate);
2048 Handle<FunctionTemplate> parent = FunctionTemplate::New(isolate);
2049 Handle<FunctionTemplate> child = FunctionTemplate::New(isolate);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002050 child->Inherit(parent);
2051 AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter);
2052 LocalContext env;
2053 env->Global()->Set(v8_str("Child"), child->GetFunction());
2054 CompileRun("var child = new Child;"
2055 "var parent = child.__proto__;"
2056 "parent.name = 'Alice';");
2057 ExpectBoolean("child.hasOwnProperty('name')", false);
2058 ExpectString("child.name", "Alice");
2059 CompileRun("child.name = 'Bob';");
2060 ExpectString("child.name", "Bob");
2061 ExpectBoolean("child.hasOwnProperty('name')", true);
2062 ExpectString("parent.name", "Alice");
2063}
2064
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002065
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002066THREADED_TEST(SwitchFromInterceptorToAccessor) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002067 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002068 Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
danno@chromium.orgbf0c8202011-12-27 10:09:42 +00002069 AddAccessor(templ, v8_str("age"),
2070 SimpleAccessorGetter, SimpleAccessorSetter);
2071 AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
2072 LocalContext env;
2073 env->Global()->Set(v8_str("Obj"), templ->GetFunction());
2074 CompileRun("var obj = new Obj;"
2075 "function setAge(i){ obj.age = i; };"
2076 "for(var i = 0; i <= 10000; i++) setAge(i);");
2077 // All i < 10000 go to the interceptor.
2078 ExpectInt32("obj.interceptor_age", 9999);
2079 // The last i goes to the accessor.
2080 ExpectInt32("obj.accessor_age", 10000);
2081}
2082
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002083
danno@chromium.orgbf0c8202011-12-27 10:09:42 +00002084THREADED_TEST(SwitchFromAccessorToInterceptor) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002085 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002086 Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
danno@chromium.orgbf0c8202011-12-27 10:09:42 +00002087 AddAccessor(templ, v8_str("age"),
2088 SimpleAccessorGetter, SimpleAccessorSetter);
2089 AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
2090 LocalContext env;
2091 env->Global()->Set(v8_str("Obj"), templ->GetFunction());
2092 CompileRun("var obj = new Obj;"
2093 "function setAge(i){ obj.age = i; };"
2094 "for(var i = 20000; i >= 9999; i--) setAge(i);");
2095 // All i >= 10000 go to the accessor.
2096 ExpectInt32("obj.accessor_age", 10000);
2097 // The last i goes to the interceptor.
2098 ExpectInt32("obj.interceptor_age", 9999);
2099}
2100
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002101
danno@chromium.orgbf0c8202011-12-27 10:09:42 +00002102THREADED_TEST(SwitchFromInterceptorToAccessorWithInheritance) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002103 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002104 Handle<FunctionTemplate> parent = FunctionTemplate::New(CcTest::isolate());
2105 Handle<FunctionTemplate> child = FunctionTemplate::New(CcTest::isolate());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002106 child->Inherit(parent);
2107 AddAccessor(parent, v8_str("age"),
2108 SimpleAccessorGetter, SimpleAccessorSetter);
2109 AddInterceptor(child, InterceptorGetter, InterceptorSetter);
2110 LocalContext env;
2111 env->Global()->Set(v8_str("Child"), child->GetFunction());
2112 CompileRun("var child = new Child;"
2113 "function setAge(i){ child.age = i; };"
2114 "for(var i = 0; i <= 10000; i++) setAge(i);");
2115 // All i < 10000 go to the interceptor.
2116 ExpectInt32("child.interceptor_age", 9999);
2117 // The last i goes to the accessor.
2118 ExpectInt32("child.accessor_age", 10000);
2119}
2120
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002121
danno@chromium.orgbf0c8202011-12-27 10:09:42 +00002122THREADED_TEST(SwitchFromAccessorToInterceptorWithInheritance) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002123 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002124 Handle<FunctionTemplate> parent = FunctionTemplate::New(CcTest::isolate());
2125 Handle<FunctionTemplate> child = FunctionTemplate::New(CcTest::isolate());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002126 child->Inherit(parent);
2127 AddAccessor(parent, v8_str("age"),
2128 SimpleAccessorGetter, SimpleAccessorSetter);
2129 AddInterceptor(child, InterceptorGetter, InterceptorSetter);
2130 LocalContext env;
2131 env->Global()->Set(v8_str("Child"), child->GetFunction());
2132 CompileRun("var child = new Child;"
2133 "function setAge(i){ child.age = i; };"
2134 "for(var i = 20000; i >= 9999; i--) setAge(i);");
2135 // All i >= 10000 go to the accessor.
2136 ExpectInt32("child.accessor_age", 10000);
2137 // The last i goes to the interceptor.
2138 ExpectInt32("child.interceptor_age", 9999);
2139}
2140
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002141
danno@chromium.orgbf0c8202011-12-27 10:09:42 +00002142THREADED_TEST(SwitchFromInterceptorToJSAccessor) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002143 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002144 Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
danno@chromium.orgbf0c8202011-12-27 10:09:42 +00002145 AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
2146 LocalContext env;
2147 env->Global()->Set(v8_str("Obj"), templ->GetFunction());
2148 CompileRun("var obj = new Obj;"
2149 "function setter(i) { this.accessor_age = i; };"
2150 "function getter() { return this.accessor_age; };"
2151 "function setAge(i) { obj.age = i; };"
2152 "Object.defineProperty(obj, 'age', { get:getter, set:setter });"
2153 "for(var i = 0; i <= 10000; i++) setAge(i);");
2154 // All i < 10000 go to the interceptor.
2155 ExpectInt32("obj.interceptor_age", 9999);
2156 // The last i goes to the JavaScript accessor.
2157 ExpectInt32("obj.accessor_age", 10000);
2158 // The installed JavaScript getter is still intact.
2159 // This last part is a regression test for issue 1651 and relies on the fact
2160 // that both interceptor and accessor are being installed on the same object.
2161 ExpectInt32("obj.age", 10000);
2162 ExpectBoolean("obj.hasOwnProperty('age')", true);
2163 ExpectUndefined("Object.getOwnPropertyDescriptor(obj, 'age').value");
2164}
2165
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002166
danno@chromium.orgbf0c8202011-12-27 10:09:42 +00002167THREADED_TEST(SwitchFromJSAccessorToInterceptor) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002168 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002169 Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
danno@chromium.orgbf0c8202011-12-27 10:09:42 +00002170 AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
2171 LocalContext env;
2172 env->Global()->Set(v8_str("Obj"), templ->GetFunction());
2173 CompileRun("var obj = new Obj;"
2174 "function setter(i) { this.accessor_age = i; };"
2175 "function getter() { return this.accessor_age; };"
2176 "function setAge(i) { obj.age = i; };"
2177 "Object.defineProperty(obj, 'age', { get:getter, set:setter });"
2178 "for(var i = 20000; i >= 9999; i--) setAge(i);");
2179 // All i >= 10000 go to the accessor.
2180 ExpectInt32("obj.accessor_age", 10000);
2181 // The last i goes to the interceptor.
2182 ExpectInt32("obj.interceptor_age", 9999);
2183 // The installed JavaScript getter is still intact.
2184 // This last part is a regression test for issue 1651 and relies on the fact
2185 // that both interceptor and accessor are being installed on the same object.
2186 ExpectInt32("obj.age", 10000);
2187 ExpectBoolean("obj.hasOwnProperty('age')", true);
2188 ExpectUndefined("Object.getOwnPropertyDescriptor(obj, 'age').value");
2189}
2190
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002191
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002192THREADED_TEST(SwitchFromInterceptorToProperty) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002193 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002194 Handle<FunctionTemplate> parent = FunctionTemplate::New(CcTest::isolate());
2195 Handle<FunctionTemplate> child = FunctionTemplate::New(CcTest::isolate());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002196 child->Inherit(parent);
2197 AddInterceptor(child, InterceptorGetter, InterceptorSetter);
2198 LocalContext env;
2199 env->Global()->Set(v8_str("Child"), child->GetFunction());
2200 CompileRun("var child = new Child;"
2201 "function setAge(i){ child.age = i; };"
2202 "for(var i = 0; i <= 10000; i++) setAge(i);");
2203 // All i < 10000 go to the interceptor.
2204 ExpectInt32("child.interceptor_age", 9999);
2205 // The last i goes to child's own property.
2206 ExpectInt32("child.age", 10000);
2207}
2208
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002209
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002210THREADED_TEST(SwitchFromPropertyToInterceptor) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002211 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002212 Handle<FunctionTemplate> parent = FunctionTemplate::New(CcTest::isolate());
2213 Handle<FunctionTemplate> child = FunctionTemplate::New(CcTest::isolate());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002214 child->Inherit(parent);
2215 AddInterceptor(child, InterceptorGetter, InterceptorSetter);
2216 LocalContext env;
2217 env->Global()->Set(v8_str("Child"), child->GetFunction());
2218 CompileRun("var child = new Child;"
2219 "function setAge(i){ child.age = i; };"
2220 "for(var i = 20000; i >= 9999; i--) setAge(i);");
2221 // All i >= 10000 go to child's own property.
2222 ExpectInt32("child.age", 10000);
2223 // The last i goes to the interceptor.
2224 ExpectInt32("child.interceptor_age", 9999);
2225}
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002226
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002227
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002228THREADED_TEST(NamedPropertyHandlerGetter) {
2229 echo_named_call_count = 0;
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002230 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002231 v8::Handle<v8::FunctionTemplate> templ =
2232 v8::FunctionTemplate::New(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002233 templ->InstanceTemplate()->SetNamedPropertyHandler(EchoNamedProperty,
2234 0, 0, 0, 0,
2235 v8_str("data"));
2236 LocalContext env;
2237 env->Global()->Set(v8_str("obj"),
2238 templ->GetFunction()->NewInstance());
2239 CHECK_EQ(echo_named_call_count, 0);
2240 v8_compile("obj.x")->Run();
2241 CHECK_EQ(echo_named_call_count, 1);
2242 const char* code = "var str = 'oddle'; obj[str] + obj.poddle;";
2243 v8::Handle<Value> str = CompileRun(code);
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00002244 String::Utf8Value value(str);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002245 CHECK_EQ(*value, "oddlepoddle");
2246 // Check default behavior
2247 CHECK_EQ(v8_compile("obj.flob = 10;")->Run()->Int32Value(), 10);
2248 CHECK(v8_compile("'myProperty' in obj")->Run()->BooleanValue());
2249 CHECK(v8_compile("delete obj.myProperty")->Run()->BooleanValue());
2250}
2251
2252
2253int echo_indexed_call_count = 0;
2254
2255
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002256static void EchoIndexedProperty(
2257 uint32_t index,
2258 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002259 ApiTestFuzzer::Fuzz();
2260 CHECK_EQ(v8_num(637), info.Data());
2261 echo_indexed_call_count++;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002262 info.GetReturnValue().Set(v8_num(index));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002263}
2264
2265
2266THREADED_TEST(IndexedPropertyHandlerGetter) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002267 v8::Isolate* isolate = CcTest::isolate();
2268 v8::HandleScope scope(isolate);
2269 v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002270 templ->InstanceTemplate()->SetIndexedPropertyHandler(EchoIndexedProperty,
2271 0, 0, 0, 0,
2272 v8_num(637));
2273 LocalContext env;
2274 env->Global()->Set(v8_str("obj"),
2275 templ->GetFunction()->NewInstance());
2276 Local<Script> script = v8_compile("obj[900]");
2277 CHECK_EQ(script->Run()->Int32Value(), 900);
2278}
2279
2280
2281v8::Handle<v8::Object> bottom;
2282
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002283static void CheckThisIndexedPropertyHandler(
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002284 uint32_t index,
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002285 const v8::PropertyCallbackInfo<v8::Value>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002286 CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyHandler));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002287 ApiTestFuzzer::Fuzz();
2288 CHECK(info.This()->Equals(bottom));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002289}
2290
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002291static void CheckThisNamedPropertyHandler(
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002292 Local<String> name,
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002293 const v8::PropertyCallbackInfo<v8::Value>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002294 CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyHandler));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002295 ApiTestFuzzer::Fuzz();
2296 CHECK(info.This()->Equals(bottom));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002297}
2298
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002299void CheckThisIndexedPropertySetter(
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002300 uint32_t index,
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002301 Local<Value> value,
2302 const v8::PropertyCallbackInfo<v8::Value>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002303 CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertySetter));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002304 ApiTestFuzzer::Fuzz();
2305 CHECK(info.This()->Equals(bottom));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002306}
2307
2308
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002309void CheckThisNamedPropertySetter(
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002310 Local<String> property,
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002311 Local<Value> value,
2312 const v8::PropertyCallbackInfo<v8::Value>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002313 CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertySetter));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002314 ApiTestFuzzer::Fuzz();
2315 CHECK(info.This()->Equals(bottom));
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002316}
2317
2318void CheckThisIndexedPropertyQuery(
2319 uint32_t index,
2320 const v8::PropertyCallbackInfo<v8::Integer>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002321 CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyQuery));
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002322 ApiTestFuzzer::Fuzz();
2323 CHECK(info.This()->Equals(bottom));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002324}
2325
2326
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002327void CheckThisNamedPropertyQuery(
2328 Local<String> property,
2329 const v8::PropertyCallbackInfo<v8::Integer>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002330 CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyQuery));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002331 ApiTestFuzzer::Fuzz();
2332 CHECK(info.This()->Equals(bottom));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002333}
2334
2335
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002336void CheckThisIndexedPropertyDeleter(
2337 uint32_t index,
2338 const v8::PropertyCallbackInfo<v8::Boolean>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002339 CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyDeleter));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002340 ApiTestFuzzer::Fuzz();
2341 CHECK(info.This()->Equals(bottom));
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002342}
2343
2344
2345void CheckThisNamedPropertyDeleter(
2346 Local<String> property,
2347 const v8::PropertyCallbackInfo<v8::Boolean>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002348 CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyDeleter));
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002349 ApiTestFuzzer::Fuzz();
2350 CHECK(info.This()->Equals(bottom));
2351}
2352
2353
2354void CheckThisIndexedPropertyEnumerator(
2355 const v8::PropertyCallbackInfo<v8::Array>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002356 CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyEnumerator));
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002357 ApiTestFuzzer::Fuzz();
2358 CHECK(info.This()->Equals(bottom));
2359}
2360
2361
2362void CheckThisNamedPropertyEnumerator(
2363 const v8::PropertyCallbackInfo<v8::Array>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002364 CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyEnumerator));
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002365 ApiTestFuzzer::Fuzz();
2366 CHECK(info.This()->Equals(bottom));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002367}
2368
2369
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002370THREADED_PROFILED_TEST(PropertyHandlerInPrototype) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002371 LocalContext env;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002372 v8::Isolate* isolate = env->GetIsolate();
2373 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002374
2375 // Set up a prototype chain with three interceptors.
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002376 v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002377 templ->InstanceTemplate()->SetIndexedPropertyHandler(
2378 CheckThisIndexedPropertyHandler,
2379 CheckThisIndexedPropertySetter,
2380 CheckThisIndexedPropertyQuery,
2381 CheckThisIndexedPropertyDeleter,
2382 CheckThisIndexedPropertyEnumerator);
2383
2384 templ->InstanceTemplate()->SetNamedPropertyHandler(
2385 CheckThisNamedPropertyHandler,
2386 CheckThisNamedPropertySetter,
2387 CheckThisNamedPropertyQuery,
2388 CheckThisNamedPropertyDeleter,
2389 CheckThisNamedPropertyEnumerator);
2390
2391 bottom = templ->GetFunction()->NewInstance();
2392 Local<v8::Object> top = templ->GetFunction()->NewInstance();
2393 Local<v8::Object> middle = templ->GetFunction()->NewInstance();
2394
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00002395 bottom->SetPrototype(middle);
2396 middle->SetPrototype(top);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002397 env->Global()->Set(v8_str("obj"), bottom);
2398
2399 // Indexed and named get.
2400 Script::Compile(v8_str("obj[0]"))->Run();
2401 Script::Compile(v8_str("obj.x"))->Run();
2402
2403 // Indexed and named set.
2404 Script::Compile(v8_str("obj[1] = 42"))->Run();
2405 Script::Compile(v8_str("obj.y = 42"))->Run();
2406
2407 // Indexed and named query.
2408 Script::Compile(v8_str("0 in obj"))->Run();
2409 Script::Compile(v8_str("'x' in obj"))->Run();
2410
2411 // Indexed and named deleter.
2412 Script::Compile(v8_str("delete obj[0]"))->Run();
2413 Script::Compile(v8_str("delete obj.x"))->Run();
2414
2415 // Enumerators.
2416 Script::Compile(v8_str("for (var p in obj) ;"))->Run();
2417}
2418
2419
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002420static void PrePropertyHandlerGet(
2421 Local<String> key,
2422 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002423 ApiTestFuzzer::Fuzz();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002424 if (v8_str("pre")->Equals(key)) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002425 info.GetReturnValue().Set(v8_str("PrePropertyHandler: pre"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002426 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002427}
2428
2429
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002430static void PrePropertyHandlerQuery(
2431 Local<String> key,
2432 const v8::PropertyCallbackInfo<v8::Integer>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002433 if (v8_str("pre")->Equals(key)) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002434 info.GetReturnValue().Set(static_cast<int32_t>(v8::None));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002435 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002436}
2437
2438
2439THREADED_TEST(PrePropertyHandler) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002440 v8::Isolate* isolate = CcTest::isolate();
2441 v8::HandleScope scope(isolate);
2442 v8::Handle<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002443 desc->InstanceTemplate()->SetNamedPropertyHandler(PrePropertyHandlerGet,
2444 0,
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00002445 PrePropertyHandlerQuery);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002446 LocalContext env(NULL, desc->InstanceTemplate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002447 Script::Compile(v8_str(
2448 "var pre = 'Object: pre'; var on = 'Object: on';"))->Run();
2449 v8::Handle<Value> result_pre = Script::Compile(v8_str("pre"))->Run();
2450 CHECK_EQ(v8_str("PrePropertyHandler: pre"), result_pre);
2451 v8::Handle<Value> result_on = Script::Compile(v8_str("on"))->Run();
2452 CHECK_EQ(v8_str("Object: on"), result_on);
2453 v8::Handle<Value> result_post = Script::Compile(v8_str("post"))->Run();
2454 CHECK(result_post.IsEmpty());
2455}
2456
2457
ager@chromium.org870a0b62008-11-04 11:43:05 +00002458THREADED_TEST(UndefinedIsNotEnumerable) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00002459 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00002460 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org870a0b62008-11-04 11:43:05 +00002461 v8::Handle<Value> result = Script::Compile(v8_str(
2462 "this.propertyIsEnumerable(undefined)"))->Run();
2463 CHECK(result->IsFalse());
2464}
2465
2466
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002467v8::Handle<Script> call_recursively_script;
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00002468static const int kTargetRecursionDepth = 200; // near maximum
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002469
2470
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002471static void CallScriptRecursivelyCall(
2472 const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002473 ApiTestFuzzer::Fuzz();
2474 int depth = args.This()->Get(v8_str("depth"))->Int32Value();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002475 if (depth == kTargetRecursionDepth) return;
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002476 args.This()->Set(v8_str("depth"),
2477 v8::Integer::New(args.GetIsolate(), depth + 1));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002478 args.GetReturnValue().Set(call_recursively_script->Run());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002479}
2480
2481
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002482static void CallFunctionRecursivelyCall(
2483 const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002484 ApiTestFuzzer::Fuzz();
2485 int depth = args.This()->Get(v8_str("depth"))->Int32Value();
2486 if (depth == kTargetRecursionDepth) {
2487 printf("[depth = %d]\n", depth);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002488 return;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002489 }
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002490 args.This()->Set(v8_str("depth"),
2491 v8::Integer::New(args.GetIsolate(), depth + 1));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002492 v8::Handle<Value> function =
2493 args.This()->Get(v8_str("callFunctionRecursively"));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002494 args.GetReturnValue().Set(
2495 function.As<Function>()->Call(args.This(), 0, NULL));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002496}
2497
2498
2499THREADED_TEST(DeepCrossLanguageRecursion) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002500 v8::Isolate* isolate = CcTest::isolate();
2501 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00002502 v8::Handle<v8::ObjectTemplate> global = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002503 global->Set(v8_str("callScriptRecursively"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002504 v8::FunctionTemplate::New(isolate, CallScriptRecursivelyCall));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002505 global->Set(v8_str("callFunctionRecursively"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002506 v8::FunctionTemplate::New(isolate, CallFunctionRecursivelyCall));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002507 LocalContext env(NULL, global);
2508
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002509 env->Global()->Set(v8_str("depth"), v8::Integer::New(isolate, 0));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002510 call_recursively_script = v8_compile("callScriptRecursively()");
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00002511 call_recursively_script->Run();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002512 call_recursively_script = v8::Handle<Script>();
2513
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002514 env->Global()->Set(v8_str("depth"), v8::Integer::New(isolate, 0));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002515 Script::Compile(v8_str("callFunctionRecursively()"))->Run();
2516}
2517
2518
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002519static void ThrowingPropertyHandlerGet(
2520 Local<String> key,
2521 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002522 ApiTestFuzzer::Fuzz();
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00002523 info.GetReturnValue().Set(info.GetIsolate()->ThrowException(key));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002524}
2525
2526
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002527static void ThrowingPropertyHandlerSet(
2528 Local<String> key,
2529 Local<Value>,
2530 const v8::PropertyCallbackInfo<v8::Value>& info) {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00002531 info.GetIsolate()->ThrowException(key);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002532 info.GetReturnValue().SetUndefined(); // not the same as empty handle
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002533}
2534
2535
2536THREADED_TEST(CallbackExceptionRegression) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00002537 v8::Isolate* isolate = CcTest::isolate();
2538 v8::HandleScope scope(isolate);
2539 v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002540 obj->SetNamedPropertyHandler(ThrowingPropertyHandlerGet,
2541 ThrowingPropertyHandlerSet);
2542 LocalContext env;
2543 env->Global()->Set(v8_str("obj"), obj->NewInstance());
2544 v8::Handle<Value> otto = Script::Compile(v8_str(
2545 "try { with (obj) { otto; } } catch (e) { e; }"))->Run();
2546 CHECK_EQ(v8_str("otto"), otto);
2547 v8::Handle<Value> netto = Script::Compile(v8_str(
2548 "try { with (obj) { netto = 4; } } catch (e) { e; }"))->Run();
2549 CHECK_EQ(v8_str("netto"), netto);
2550}
2551
2552
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002553THREADED_TEST(FunctionPrototype) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002554 v8::Isolate* isolate = CcTest::isolate();
2555 v8::HandleScope scope(isolate);
2556 Local<v8::FunctionTemplate> Foo = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002557 Foo->PrototypeTemplate()->Set(v8_str("plak"), v8_num(321));
2558 LocalContext env;
2559 env->Global()->Set(v8_str("Foo"), Foo->GetFunction());
2560 Local<Script> script = Script::Compile(v8_str("Foo.prototype.plak"));
2561 CHECK_EQ(script->Run()->Int32Value(), 321);
2562}
2563
2564
2565THREADED_TEST(InternalFields) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002566 LocalContext env;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002567 v8::Isolate* isolate = env->GetIsolate();
2568 v8::HandleScope scope(isolate);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002569
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002570 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002571 Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
2572 instance_templ->SetInternalFieldCount(1);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002573 Local<v8::Object> obj = templ->GetFunction()->NewInstance();
2574 CHECK_EQ(1, obj->InternalFieldCount());
2575 CHECK(obj->GetInternalField(0)->IsUndefined());
2576 obj->SetInternalField(0, v8_num(17));
2577 CHECK_EQ(17, obj->GetInternalField(0)->Int32Value());
2578}
2579
2580
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002581THREADED_TEST(GlobalObjectInternalFields) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00002582 v8::Isolate* isolate = CcTest::isolate();
2583 v8::HandleScope scope(isolate);
2584 Local<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New(isolate);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002585 global_template->SetInternalFieldCount(1);
2586 LocalContext env(NULL, global_template);
2587 v8::Handle<v8::Object> global_proxy = env->Global();
2588 v8::Handle<v8::Object> global = global_proxy->GetPrototype().As<v8::Object>();
2589 CHECK_EQ(1, global->InternalFieldCount());
2590 CHECK(global->GetInternalField(0)->IsUndefined());
2591 global->SetInternalField(0, v8_num(17));
2592 CHECK_EQ(17, global->GetInternalField(0)->Int32Value());
2593}
2594
2595
danno@chromium.org169691d2013-07-15 08:01:13 +00002596THREADED_TEST(GlobalObjectHasRealIndexedProperty) {
2597 LocalContext env;
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002598 v8::HandleScope scope(CcTest::isolate());
danno@chromium.org169691d2013-07-15 08:01:13 +00002599
2600 v8::Local<v8::Object> global = env->Global();
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00002601 global->Set(0, v8::String::NewFromUtf8(CcTest::isolate(), "value"));
danno@chromium.org169691d2013-07-15 08:01:13 +00002602 CHECK(global->HasRealIndexedProperty(0));
2603}
2604
2605
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002606static void CheckAlignedPointerInInternalField(Handle<v8::Object> obj,
2607 void* value) {
2608 CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(value) & 0x1));
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00002609 obj->SetAlignedPointerInInternalField(0, value);
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002610 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00002611 CHECK_EQ(value, obj->GetAlignedPointerFromInternalField(0));
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002612}
2613
2614
2615THREADED_TEST(InternalFieldsAlignedPointers) {
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002616 LocalContext env;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002617 v8::Isolate* isolate = env->GetIsolate();
2618 v8::HandleScope scope(isolate);
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002619
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002620 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002621 Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
2622 instance_templ->SetInternalFieldCount(1);
2623 Local<v8::Object> obj = templ->GetFunction()->NewInstance();
2624 CHECK_EQ(1, obj->InternalFieldCount());
2625
2626 CheckAlignedPointerInInternalField(obj, NULL);
2627
2628 int* heap_allocated = new int[100];
2629 CheckAlignedPointerInInternalField(obj, heap_allocated);
2630 delete[] heap_allocated;
2631
2632 int stack_allocated[100];
2633 CheckAlignedPointerInInternalField(obj, stack_allocated);
2634
2635 void* huge = reinterpret_cast<void*>(~static_cast<uintptr_t>(1));
2636 CheckAlignedPointerInInternalField(obj, huge);
2637}
2638
2639
2640static void CheckAlignedPointerInEmbedderData(LocalContext* env,
2641 int index,
2642 void* value) {
2643 CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(value) & 0x1));
2644 (*env)->SetAlignedPointerInEmbedderData(index, value);
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002645 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002646 CHECK_EQ(value, (*env)->GetAlignedPointerFromEmbedderData(index));
2647}
2648
2649
2650static void* AlignedTestPointer(int i) {
2651 return reinterpret_cast<void*>(i * 1234);
2652}
2653
2654
2655THREADED_TEST(EmbedderDataAlignedPointers) {
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002656 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00002657 v8::HandleScope scope(env->GetIsolate());
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002658
2659 CheckAlignedPointerInEmbedderData(&env, 0, NULL);
2660
2661 int* heap_allocated = new int[100];
2662 CheckAlignedPointerInEmbedderData(&env, 1, heap_allocated);
2663 delete[] heap_allocated;
2664
2665 int stack_allocated[100];
2666 CheckAlignedPointerInEmbedderData(&env, 2, stack_allocated);
2667
2668 void* huge = reinterpret_cast<void*>(~static_cast<uintptr_t>(1));
2669 CheckAlignedPointerInEmbedderData(&env, 3, huge);
2670
2671 // Test growing of the embedder data's backing store.
2672 for (int i = 0; i < 100; i++) {
2673 env->SetAlignedPointerInEmbedderData(i, AlignedTestPointer(i));
2674 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002675 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002676 for (int i = 0; i < 100; i++) {
2677 CHECK_EQ(AlignedTestPointer(i), env->GetAlignedPointerFromEmbedderData(i));
2678 }
2679}
2680
2681
2682static void CheckEmbedderData(LocalContext* env,
2683 int index,
2684 v8::Handle<Value> data) {
2685 (*env)->SetEmbedderData(index, data);
2686 CHECK((*env)->GetEmbedderData(index)->StrictEquals(data));
2687}
2688
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002689
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002690THREADED_TEST(EmbedderData) {
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002691 LocalContext env;
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002692 v8::Isolate* isolate = env->GetIsolate();
2693 v8::HandleScope scope(isolate);
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002694
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00002695 CheckEmbedderData(
2696 &env, 3,
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002697 v8::String::NewFromUtf8(isolate, "The quick brown fox jumps"));
2698 CheckEmbedderData(&env, 2, v8::String::NewFromUtf8(isolate,
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00002699 "over the lazy dog."));
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002700 CheckEmbedderData(&env, 1, v8::Number::New(isolate, 1.2345));
2701 CheckEmbedderData(&env, 0, v8::Boolean::New(isolate, true));
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002702}
2703
2704
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002705THREADED_TEST(IdentityHash) {
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002706 LocalContext env;
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002707 v8::Isolate* isolate = env->GetIsolate();
2708 v8::HandleScope scope(isolate);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002709
2710 // Ensure that the test starts with an fresh heap to test whether the hash
2711 // code is based on the address.
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002712 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002713 Local<v8::Object> obj = v8::Object::New(isolate);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002714 int hash = obj->GetIdentityHash();
2715 int hash1 = obj->GetIdentityHash();
2716 CHECK_EQ(hash, hash1);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002717 int hash2 = v8::Object::New(isolate)->GetIdentityHash();
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002718 // Since the identity hash is essentially a random number two consecutive
2719 // objects should not be assigned the same hash code. If the test below fails
2720 // the random number generator should be evaluated.
2721 CHECK_NE(hash, hash2);
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002722 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002723 int hash3 = v8::Object::New(isolate)->GetIdentityHash();
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002724 // Make sure that the identity hash is not based on the initial address of
2725 // the object alone. If the test below fails the random number generator
2726 // should be evaluated.
2727 CHECK_NE(hash, hash3);
2728 int hash4 = obj->GetIdentityHash();
2729 CHECK_EQ(hash, hash4);
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002730
2731 // Check identity hashes behaviour in the presence of JS accessors.
2732 // Put a getter for 'v8::IdentityHash' on the Object's prototype:
2733 {
2734 CompileRun("Object.prototype['v8::IdentityHash'] = 42;\n");
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002735 Local<v8::Object> o1 = v8::Object::New(isolate);
2736 Local<v8::Object> o2 = v8::Object::New(isolate);
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002737 CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash());
2738 }
2739 {
2740 CompileRun(
2741 "function cnst() { return 42; };\n"
2742 "Object.prototype.__defineGetter__('v8::IdentityHash', cnst);\n");
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002743 Local<v8::Object> o1 = v8::Object::New(isolate);
2744 Local<v8::Object> o2 = v8::Object::New(isolate);
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002745 CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash());
2746 }
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002747}
2748
2749
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002750THREADED_TEST(SymbolProperties) {
2751 i::FLAG_harmony_symbols = true;
2752
2753 LocalContext env;
2754 v8::Isolate* isolate = env->GetIsolate();
2755 v8::HandleScope scope(isolate);
2756
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002757 v8::Local<v8::Object> obj = v8::Object::New(isolate);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002758 v8::Local<v8::Symbol> sym1 = v8::Symbol::New(isolate);
2759 v8::Local<v8::Symbol> sym2 = v8::Symbol::New(isolate, "my-symbol");
2760
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002761 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002762
2763 // Check basic symbol functionality.
2764 CHECK(sym1->IsSymbol());
2765 CHECK(sym2->IsSymbol());
2766 CHECK(!obj->IsSymbol());
2767
2768 CHECK(sym1->Equals(sym1));
2769 CHECK(sym2->Equals(sym2));
2770 CHECK(!sym1->Equals(sym2));
2771 CHECK(!sym2->Equals(sym1));
2772 CHECK(sym1->StrictEquals(sym1));
2773 CHECK(sym2->StrictEquals(sym2));
2774 CHECK(!sym1->StrictEquals(sym2));
2775 CHECK(!sym2->StrictEquals(sym1));
2776
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00002777 CHECK(sym2->Name()->Equals(v8::String::NewFromUtf8(isolate, "my-symbol")));
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002778
2779 v8::Local<v8::Value> sym_val = sym2;
2780 CHECK(sym_val->IsSymbol());
2781 CHECK(sym_val->Equals(sym2));
2782 CHECK(sym_val->StrictEquals(sym2));
2783 CHECK(v8::Symbol::Cast(*sym_val)->Equals(sym2));
2784
2785 v8::Local<v8::Value> sym_obj = v8::SymbolObject::New(isolate, sym2);
2786 CHECK(sym_obj->IsSymbolObject());
2787 CHECK(!sym2->IsSymbolObject());
2788 CHECK(!obj->IsSymbolObject());
2789 CHECK(sym_obj->Equals(sym2));
2790 CHECK(!sym_obj->StrictEquals(sym2));
2791 CHECK(v8::SymbolObject::Cast(*sym_obj)->Equals(sym_obj));
danno@chromium.orgd3c42102013-08-01 16:58:23 +00002792 CHECK(v8::SymbolObject::Cast(*sym_obj)->ValueOf()->Equals(sym2));
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002793
2794 // Make sure delete of a non-existent symbol property works.
2795 CHECK(obj->Delete(sym1));
2796 CHECK(!obj->Has(sym1));
2797
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002798 CHECK(obj->Set(sym1, v8::Integer::New(isolate, 1503)));
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002799 CHECK(obj->Has(sym1));
2800 CHECK_EQ(1503, obj->Get(sym1)->Int32Value());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002801 CHECK(obj->Set(sym1, v8::Integer::New(isolate, 2002)));
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002802 CHECK(obj->Has(sym1));
2803 CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
2804 CHECK_EQ(v8::None, obj->GetPropertyAttributes(sym1));
2805
2806 CHECK_EQ(0, obj->GetOwnPropertyNames()->Length());
2807 int num_props = obj->GetPropertyNames()->Length();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002808 CHECK(obj->Set(v8::String::NewFromUtf8(isolate, "bla"),
2809 v8::Integer::New(isolate, 20)));
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002810 CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
2811 CHECK_EQ(num_props + 1, obj->GetPropertyNames()->Length());
2812
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002813 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002814
2815 // Add another property and delete it afterwards to force the object in
2816 // slow case.
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002817 CHECK(obj->Set(sym2, v8::Integer::New(isolate, 2008)));
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002818 CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
2819 CHECK_EQ(2008, obj->Get(sym2)->Int32Value());
2820 CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
2821 CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
2822
2823 CHECK(obj->Has(sym1));
2824 CHECK(obj->Has(sym2));
2825 CHECK(obj->Delete(sym2));
2826 CHECK(obj->Has(sym1));
2827 CHECK(!obj->Has(sym2));
2828 CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
2829 CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00002830
2831 // Symbol properties are inherited.
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002832 v8::Local<v8::Object> child = v8::Object::New(isolate);
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00002833 child->SetPrototype(obj);
2834 CHECK(child->Has(sym1));
2835 CHECK_EQ(2002, child->Get(sym1)->Int32Value());
2836 CHECK_EQ(0, child->GetOwnPropertyNames()->Length());
2837}
2838
2839
2840THREADED_TEST(PrivateProperties) {
2841 LocalContext env;
2842 v8::Isolate* isolate = env->GetIsolate();
2843 v8::HandleScope scope(isolate);
2844
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002845 v8::Local<v8::Object> obj = v8::Object::New(isolate);
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00002846 v8::Local<v8::Private> priv1 = v8::Private::New(isolate);
2847 v8::Local<v8::Private> priv2 = v8::Private::New(isolate, "my-private");
2848
2849 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
2850
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00002851 CHECK(priv2->Name()->Equals(v8::String::NewFromUtf8(isolate, "my-private")));
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00002852
2853 // Make sure delete of a non-existent private symbol property works.
2854 CHECK(obj->DeletePrivate(priv1));
2855 CHECK(!obj->HasPrivate(priv1));
2856
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002857 CHECK(obj->SetPrivate(priv1, v8::Integer::New(isolate, 1503)));
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00002858 CHECK(obj->HasPrivate(priv1));
2859 CHECK_EQ(1503, obj->GetPrivate(priv1)->Int32Value());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002860 CHECK(obj->SetPrivate(priv1, v8::Integer::New(isolate, 2002)));
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00002861 CHECK(obj->HasPrivate(priv1));
2862 CHECK_EQ(2002, obj->GetPrivate(priv1)->Int32Value());
2863
2864 CHECK_EQ(0, obj->GetOwnPropertyNames()->Length());
2865 int num_props = obj->GetPropertyNames()->Length();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002866 CHECK(obj->Set(v8::String::NewFromUtf8(isolate, "bla"),
2867 v8::Integer::New(isolate, 20)));
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00002868 CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
2869 CHECK_EQ(num_props + 1, obj->GetPropertyNames()->Length());
2870
2871 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
2872
2873 // Add another property and delete it afterwards to force the object in
2874 // slow case.
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002875 CHECK(obj->SetPrivate(priv2, v8::Integer::New(isolate, 2008)));
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00002876 CHECK_EQ(2002, obj->GetPrivate(priv1)->Int32Value());
2877 CHECK_EQ(2008, obj->GetPrivate(priv2)->Int32Value());
2878 CHECK_EQ(2002, obj->GetPrivate(priv1)->Int32Value());
2879 CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
2880
2881 CHECK(obj->HasPrivate(priv1));
2882 CHECK(obj->HasPrivate(priv2));
2883 CHECK(obj->DeletePrivate(priv2));
2884 CHECK(obj->HasPrivate(priv1));
2885 CHECK(!obj->HasPrivate(priv2));
2886 CHECK_EQ(2002, obj->GetPrivate(priv1)->Int32Value());
2887 CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
2888
2889 // Private properties are inherited (for the time being).
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002890 v8::Local<v8::Object> child = v8::Object::New(isolate);
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00002891 child->SetPrototype(obj);
2892 CHECK(child->HasPrivate(priv1));
2893 CHECK_EQ(2002, child->GetPrivate(priv1)->Int32Value());
2894 CHECK_EQ(0, child->GetOwnPropertyNames()->Length());
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002895}
2896
2897
ulan@chromium.org837a67e2013-06-11 15:39:48 +00002898class ScopedArrayBufferContents {
2899 public:
2900 explicit ScopedArrayBufferContents(
2901 const v8::ArrayBuffer::Contents& contents)
2902 : contents_(contents) {}
2903 ~ScopedArrayBufferContents() { free(contents_.Data()); }
2904 void* Data() const { return contents_.Data(); }
2905 size_t ByteLength() const { return contents_.ByteLength(); }
2906 private:
2907 const v8::ArrayBuffer::Contents contents_;
2908};
2909
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002910template <typename T>
2911static void CheckInternalFieldsAreZero(v8::Handle<T> value) {
2912 CHECK_EQ(T::kInternalFieldCount, value->InternalFieldCount());
2913 for (int i = 0; i < value->InternalFieldCount(); i++) {
2914 CHECK_EQ(0, value->GetInternalField(i)->Int32Value());
2915 }
2916}
2917
ulan@chromium.org837a67e2013-06-11 15:39:48 +00002918
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002919THREADED_TEST(ArrayBuffer_ApiInternalToExternal) {
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002920 LocalContext env;
2921 v8::Isolate* isolate = env->GetIsolate();
2922 v8::HandleScope handle_scope(isolate);
2923
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00002924 Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, 1024);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002925 CheckInternalFieldsAreZero(ab);
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002926 CHECK_EQ(1024, static_cast<int>(ab->ByteLength()));
2927 CHECK(!ab->IsExternal());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002928 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002929
ulan@chromium.org837a67e2013-06-11 15:39:48 +00002930 ScopedArrayBufferContents ab_contents(ab->Externalize());
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002931 CHECK(ab->IsExternal());
2932
2933 CHECK_EQ(1024, static_cast<int>(ab_contents.ByteLength()));
2934 uint8_t* data = static_cast<uint8_t*>(ab_contents.Data());
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002935 ASSERT(data != NULL);
2936 env->Global()->Set(v8_str("ab"), ab);
2937
2938 v8::Handle<v8::Value> result = CompileRun("ab.byteLength");
2939 CHECK_EQ(1024, result->Int32Value());
2940
danno@chromium.orgf005df62013-04-30 16:36:45 +00002941 result = CompileRun("var u8 = new Uint8Array(ab);"
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002942 "u8[0] = 0xFF;"
2943 "u8[1] = 0xAA;"
2944 "u8.length");
2945 CHECK_EQ(1024, result->Int32Value());
2946 CHECK_EQ(0xFF, data[0]);
2947 CHECK_EQ(0xAA, data[1]);
2948 data[0] = 0xCC;
2949 data[1] = 0x11;
2950 result = CompileRun("u8[0] + u8[1]");
2951 CHECK_EQ(0xDD, result->Int32Value());
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002952}
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002953
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002954
2955THREADED_TEST(ArrayBuffer_JSInternalToExternal) {
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002956 LocalContext env;
2957 v8::Isolate* isolate = env->GetIsolate();
2958 v8::HandleScope handle_scope(isolate);
2959
2960
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00002961 v8::Local<v8::Value> result =
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002962 CompileRun("var ab1 = new ArrayBuffer(2);"
2963 "var u8_a = new Uint8Array(ab1);"
2964 "u8_a[0] = 0xAA;"
2965 "u8_a[1] = 0xFF; u8_a.buffer");
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00002966 Local<v8::ArrayBuffer> ab1 = Local<v8::ArrayBuffer>::Cast(result);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002967 CheckInternalFieldsAreZero(ab1);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002968 CHECK_EQ(2, static_cast<int>(ab1->ByteLength()));
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002969 CHECK(!ab1->IsExternal());
ulan@chromium.org837a67e2013-06-11 15:39:48 +00002970 ScopedArrayBufferContents ab1_contents(ab1->Externalize());
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002971 CHECK(ab1->IsExternal());
2972
2973 result = CompileRun("ab1.byteLength");
2974 CHECK_EQ(2, result->Int32Value());
2975 result = CompileRun("u8_a[0]");
2976 CHECK_EQ(0xAA, result->Int32Value());
2977 result = CompileRun("u8_a[1]");
2978 CHECK_EQ(0xFF, result->Int32Value());
2979 result = CompileRun("var u8_b = new Uint8Array(ab1);"
2980 "u8_b[0] = 0xBB;"
2981 "u8_a[0]");
2982 CHECK_EQ(0xBB, result->Int32Value());
2983 result = CompileRun("u8_b[1]");
2984 CHECK_EQ(0xFF, result->Int32Value());
2985
2986 CHECK_EQ(2, static_cast<int>(ab1_contents.ByteLength()));
2987 uint8_t* ab1_data = static_cast<uint8_t*>(ab1_contents.Data());
2988 CHECK_EQ(0xBB, ab1_data[0]);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002989 CHECK_EQ(0xFF, ab1_data[1]);
2990 ab1_data[0] = 0xCC;
2991 ab1_data[1] = 0x11;
2992 result = CompileRun("u8_a[0] + u8_a[1]");
2993 CHECK_EQ(0xDD, result->Int32Value());
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002994}
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002995
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002996
2997THREADED_TEST(ArrayBuffer_External) {
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002998 LocalContext env;
2999 v8::Isolate* isolate = env->GetIsolate();
3000 v8::HandleScope handle_scope(isolate);
3001
3002 i::ScopedVector<uint8_t> my_data(100);
3003 memset(my_data.start(), 0, 100);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00003004 Local<v8::ArrayBuffer> ab3 =
3005 v8::ArrayBuffer::New(isolate, my_data.start(), 100);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00003006 CheckInternalFieldsAreZero(ab3);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003007 CHECK_EQ(100, static_cast<int>(ab3->ByteLength()));
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00003008 CHECK(ab3->IsExternal());
3009
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003010 env->Global()->Set(v8_str("ab3"), ab3);
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00003011
3012 v8::Handle<v8::Value> result = CompileRun("ab3.byteLength");
3013 CHECK_EQ(100, result->Int32Value());
3014
danno@chromium.orgf005df62013-04-30 16:36:45 +00003015 result = CompileRun("var u8_b = new Uint8Array(ab3);"
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003016 "u8_b[0] = 0xBB;"
3017 "u8_b[1] = 0xCC;"
3018 "u8_b.length");
3019 CHECK_EQ(100, result->Int32Value());
3020 CHECK_EQ(0xBB, my_data[0]);
3021 CHECK_EQ(0xCC, my_data[1]);
3022 my_data[0] = 0xCC;
3023 my_data[1] = 0x11;
3024 result = CompileRun("u8_b[0] + u8_b[1]");
3025 CHECK_EQ(0xDD, result->Int32Value());
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003026}
3027
3028
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003029static void CheckDataViewIsNeutered(v8::Handle<v8::DataView> dv) {
3030 CHECK_EQ(0, static_cast<int>(dv->ByteLength()));
3031 CHECK_EQ(0, static_cast<int>(dv->ByteOffset()));
3032}
3033
3034
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003035static void CheckIsNeutered(v8::Handle<v8::TypedArray> ta) {
3036 CHECK_EQ(0, static_cast<int>(ta->ByteLength()));
3037 CHECK_EQ(0, static_cast<int>(ta->Length()));
3038 CHECK_EQ(0, static_cast<int>(ta->ByteOffset()));
3039}
3040
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003041
3042static void CheckIsTypedArrayVarNeutered(const char* name) {
3043 i::ScopedVector<char> source(1024);
3044 i::OS::SNPrintF(source,
3045 "%s.byteLength == 0 && %s.byteOffset == 0 && %s.length == 0",
3046 name, name, name);
3047 CHECK(CompileRun(source.start())->IsTrue());
3048 v8::Handle<v8::TypedArray> ta =
3049 v8::Handle<v8::TypedArray>::Cast(CompileRun(name));
3050 CheckIsNeutered(ta);
3051}
3052
3053
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003054template <typename TypedArray, int kElementSize>
3055static Handle<TypedArray> CreateAndCheck(Handle<v8::ArrayBuffer> ab,
3056 int byteOffset,
3057 int length) {
3058 v8::Handle<TypedArray> ta = TypedArray::New(ab, byteOffset, length);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00003059 CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003060 CHECK_EQ(byteOffset, static_cast<int>(ta->ByteOffset()));
3061 CHECK_EQ(length, static_cast<int>(ta->Length()));
3062 CHECK_EQ(length * kElementSize, static_cast<int>(ta->ByteLength()));
3063 return ta;
3064}
3065
3066
3067THREADED_TEST(ArrayBuffer_NeuteringApi) {
3068 LocalContext env;
3069 v8::Isolate* isolate = env->GetIsolate();
3070 v8::HandleScope handle_scope(isolate);
3071
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00003072 v8::Handle<v8::ArrayBuffer> buffer = v8::ArrayBuffer::New(isolate, 1024);
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003073
3074 v8::Handle<v8::Uint8Array> u8a =
3075 CreateAndCheck<v8::Uint8Array, 1>(buffer, 1, 1023);
3076 v8::Handle<v8::Uint8ClampedArray> u8c =
3077 CreateAndCheck<v8::Uint8ClampedArray, 1>(buffer, 1, 1023);
3078 v8::Handle<v8::Int8Array> i8a =
3079 CreateAndCheck<v8::Int8Array, 1>(buffer, 1, 1023);
3080
3081 v8::Handle<v8::Uint16Array> u16a =
3082 CreateAndCheck<v8::Uint16Array, 2>(buffer, 2, 511);
3083 v8::Handle<v8::Int16Array> i16a =
3084 CreateAndCheck<v8::Int16Array, 2>(buffer, 2, 511);
3085
3086 v8::Handle<v8::Uint32Array> u32a =
3087 CreateAndCheck<v8::Uint32Array, 4>(buffer, 4, 255);
3088 v8::Handle<v8::Int32Array> i32a =
3089 CreateAndCheck<v8::Int32Array, 4>(buffer, 4, 255);
3090
3091 v8::Handle<v8::Float32Array> f32a =
3092 CreateAndCheck<v8::Float32Array, 4>(buffer, 4, 255);
3093 v8::Handle<v8::Float64Array> f64a =
3094 CreateAndCheck<v8::Float64Array, 8>(buffer, 8, 127);
3095
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003096 v8::Handle<v8::DataView> dv = v8::DataView::New(buffer, 1, 1023);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00003097 CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003098 CHECK_EQ(1, static_cast<int>(dv->ByteOffset()));
3099 CHECK_EQ(1023, static_cast<int>(dv->ByteLength()));
3100
ulan@chromium.org837a67e2013-06-11 15:39:48 +00003101 ScopedArrayBufferContents contents(buffer->Externalize());
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003102 buffer->Neuter();
3103 CHECK_EQ(0, static_cast<int>(buffer->ByteLength()));
3104 CheckIsNeutered(u8a);
3105 CheckIsNeutered(u8c);
3106 CheckIsNeutered(i8a);
3107 CheckIsNeutered(u16a);
3108 CheckIsNeutered(i16a);
3109 CheckIsNeutered(u32a);
3110 CheckIsNeutered(i32a);
3111 CheckIsNeutered(f32a);
3112 CheckIsNeutered(f64a);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003113 CheckDataViewIsNeutered(dv);
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003114}
3115
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00003116
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003117THREADED_TEST(ArrayBuffer_NeuteringScript) {
3118 LocalContext env;
3119 v8::Isolate* isolate = env->GetIsolate();
3120 v8::HandleScope handle_scope(isolate);
3121
3122 CompileRun(
3123 "var ab = new ArrayBuffer(1024);"
3124 "var u8a = new Uint8Array(ab, 1, 1023);"
3125 "var u8c = new Uint8ClampedArray(ab, 1, 1023);"
3126 "var i8a = new Int8Array(ab, 1, 1023);"
3127 "var u16a = new Uint16Array(ab, 2, 511);"
3128 "var i16a = new Int16Array(ab, 2, 511);"
3129 "var u32a = new Uint32Array(ab, 4, 255);"
3130 "var i32a = new Int32Array(ab, 4, 255);"
3131 "var f32a = new Float32Array(ab, 4, 255);"
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003132 "var f64a = new Float64Array(ab, 8, 127);"
3133 "var dv = new DataView(ab, 1, 1023);");
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003134
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00003135 v8::Handle<v8::ArrayBuffer> ab =
3136 Local<v8::ArrayBuffer>::Cast(CompileRun("ab"));
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003137
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003138 v8::Handle<v8::DataView> dv =
3139 v8::Handle<v8::DataView>::Cast(CompileRun("dv"));
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003140
ulan@chromium.org837a67e2013-06-11 15:39:48 +00003141 ScopedArrayBufferContents contents(ab->Externalize());
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003142 ab->Neuter();
3143 CHECK_EQ(0, static_cast<int>(ab->ByteLength()));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003144 CHECK_EQ(0, CompileRun("ab.byteLength")->Int32Value());
3145
3146 CheckIsTypedArrayVarNeutered("u8a");
3147 CheckIsTypedArrayVarNeutered("u8c");
3148 CheckIsTypedArrayVarNeutered("i8a");
3149 CheckIsTypedArrayVarNeutered("u16a");
3150 CheckIsTypedArrayVarNeutered("i16a");
3151 CheckIsTypedArrayVarNeutered("u32a");
3152 CheckIsTypedArrayVarNeutered("i32a");
3153 CheckIsTypedArrayVarNeutered("f32a");
3154 CheckIsTypedArrayVarNeutered("f64a");
3155
3156 CHECK(CompileRun("dv.byteLength == 0 && dv.byteOffset == 0")->IsTrue());
3157 CheckDataViewIsNeutered(dv);
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003158}
3159
3160
3161
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003162THREADED_TEST(HiddenProperties) {
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003163 LocalContext env;
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003164 v8::Isolate* isolate = env->GetIsolate();
3165 v8::HandleScope scope(isolate);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003166
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003167 v8::Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003168 v8::Local<v8::String> key = v8_str("api-test::hidden-key");
3169 v8::Local<v8::String> empty = v8_str("");
3170 v8::Local<v8::String> prop_name = v8_str("prop_name");
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
kasperl@chromium.orgacae3782009-04-11 09:17:08 +00003174 // Make sure delete of a non-existent hidden value works
3175 CHECK(obj->DeleteHiddenValue(key));
3176
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003177 CHECK(obj->SetHiddenValue(key, v8::Integer::New(isolate, 1503)));
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003178 CHECK_EQ(1503, obj->GetHiddenValue(key)->Int32Value());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003179 CHECK(obj->SetHiddenValue(key, v8::Integer::New(isolate, 2002)));
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003180 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
3181
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003182 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003183
3184 // Make sure we do not find the hidden property.
3185 CHECK(!obj->Has(empty));
3186 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
3187 CHECK(obj->Get(empty)->IsUndefined());
3188 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003189 CHECK(obj->Set(empty, v8::Integer::New(isolate, 2003)));
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003190 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
3191 CHECK_EQ(2003, obj->Get(empty)->Int32Value());
3192
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003193 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003194
3195 // Add another property and delete it afterwards to force the object in
3196 // slow case.
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003197 CHECK(obj->Set(prop_name, v8::Integer::New(isolate, 2008)));
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003198 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
3199 CHECK_EQ(2008, obj->Get(prop_name)->Int32Value());
3200 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
3201 CHECK(obj->Delete(prop_name));
3202 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
3203
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003204 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003205
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00003206 CHECK(obj->SetHiddenValue(key, Handle<Value>()));
3207 CHECK(obj->GetHiddenValue(key).IsEmpty());
3208
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003209 CHECK(obj->SetHiddenValue(key, v8::Integer::New(isolate, 2002)));
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003210 CHECK(obj->DeleteHiddenValue(key));
3211 CHECK(obj->GetHiddenValue(key).IsEmpty());
3212}
3213
3214
ricow@chromium.org9fe9cdf2011-09-27 08:04:16 +00003215THREADED_TEST(Regress97784) {
3216 // Regression test for crbug.com/97784
3217 // Messing with the Object.prototype should not have effect on
3218 // hidden properties.
ricow@chromium.org9fe9cdf2011-09-27 08:04:16 +00003219 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003220 v8::HandleScope scope(env->GetIsolate());
ricow@chromium.org9fe9cdf2011-09-27 08:04:16 +00003221
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003222 v8::Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
ricow@chromium.org9fe9cdf2011-09-27 08:04:16 +00003223 v8::Local<v8::String> key = v8_str("hidden");
3224
3225 CompileRun(
3226 "set_called = false;"
3227 "Object.defineProperty("
3228 " Object.prototype,"
3229 " 'hidden',"
3230 " {get: function() { return 45; },"
3231 " set: function() { set_called = true; }})");
3232
3233 CHECK(obj->GetHiddenValue(key).IsEmpty());
3234 // Make sure that the getter and setter from Object.prototype is not invoked.
3235 // If it did we would have full access to the hidden properties in
3236 // the accessor.
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003237 CHECK(obj->SetHiddenValue(key, v8::Integer::New(env->GetIsolate(), 42)));
ricow@chromium.org9fe9cdf2011-09-27 08:04:16 +00003238 ExpectFalse("set_called");
3239 CHECK_EQ(42, obj->GetHiddenValue(key)->Int32Value());
3240}
3241
3242
ager@chromium.orgc4c92722009-11-18 14:12:51 +00003243static bool interceptor_for_hidden_properties_called;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003244static void InterceptorForHiddenProperties(
3245 Local<String> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.orgc4c92722009-11-18 14:12:51 +00003246 interceptor_for_hidden_properties_called = true;
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00003247}
3248
3249
3250THREADED_TEST(HiddenPropertiesWithInterceptors) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00003251 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00003252 v8::Isolate* isolate = context->GetIsolate();
3253 v8::HandleScope scope(isolate);
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00003254
ager@chromium.orgc4c92722009-11-18 14:12:51 +00003255 interceptor_for_hidden_properties_called = false;
3256
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00003257 v8::Local<v8::String> key = v8_str("api-test::hidden-key");
3258
3259 // Associate an interceptor with an object and start setting hidden values.
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00003260 Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(isolate);
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00003261 Local<v8::ObjectTemplate> instance_templ = fun_templ->InstanceTemplate();
3262 instance_templ->SetNamedPropertyHandler(InterceptorForHiddenProperties);
3263 Local<v8::Function> function = fun_templ->GetFunction();
3264 Local<v8::Object> obj = function->NewInstance();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003265 CHECK(obj->SetHiddenValue(key, v8::Integer::New(isolate, 2302)));
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00003266 CHECK_EQ(2302, obj->GetHiddenValue(key)->Int32Value());
ager@chromium.orgc4c92722009-11-18 14:12:51 +00003267 CHECK(!interceptor_for_hidden_properties_called);
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00003268}
3269
3270
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003271THREADED_TEST(External) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003272 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003273 int x = 3;
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00003274 Local<v8::External> ext = v8::External::New(CcTest::isolate(), &x);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003275 LocalContext env;
3276 env->Global()->Set(v8_str("ext"), ext);
3277 Local<Value> reext_obj = Script::Compile(v8_str("this.ext"))->Run();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00003278 v8::Handle<v8::External> reext = reext_obj.As<v8::External>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003279 int* ptr = static_cast<int*>(reext->Value());
3280 CHECK_EQ(x, 3);
3281 *ptr = 10;
3282 CHECK_EQ(x, 10);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00003283
3284 // Make sure unaligned pointers are wrapped properly.
3285 char* data = i::StrDup("0123456789");
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00003286 Local<v8::Value> zero = v8::External::New(CcTest::isolate(), &data[0]);
3287 Local<v8::Value> one = v8::External::New(CcTest::isolate(), &data[1]);
3288 Local<v8::Value> two = v8::External::New(CcTest::isolate(), &data[2]);
3289 Local<v8::Value> three = v8::External::New(CcTest::isolate(), &data[3]);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00003290
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00003291 char* char_ptr = reinterpret_cast<char*>(v8::External::Cast(*zero)->Value());
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00003292 CHECK_EQ('0', *char_ptr);
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00003293 char_ptr = reinterpret_cast<char*>(v8::External::Cast(*one)->Value());
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00003294 CHECK_EQ('1', *char_ptr);
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00003295 char_ptr = reinterpret_cast<char*>(v8::External::Cast(*two)->Value());
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00003296 CHECK_EQ('2', *char_ptr);
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00003297 char_ptr = reinterpret_cast<char*>(v8::External::Cast(*three)->Value());
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00003298 CHECK_EQ('3', *char_ptr);
3299 i::DeleteArray(data);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003300}
3301
3302
3303THREADED_TEST(GlobalHandle) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003304 v8::Isolate* isolate = CcTest::isolate();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003305 v8::Persistent<String> global;
3306 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003307 v8::HandleScope scope(isolate);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003308 global.Reset(isolate, v8_str("str"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003309 }
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00003310 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003311 v8::HandleScope scope(isolate);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003312 CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00003313 }
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00003314 global.Reset();
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003315 {
3316 v8::HandleScope scope(isolate);
3317 global.Reset(isolate, v8_str("str"));
3318 }
3319 {
3320 v8::HandleScope scope(isolate);
3321 CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
3322 }
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00003323 global.Reset();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003324}
3325
3326
ulan@chromium.org57ff8812013-05-10 08:16:55 +00003327THREADED_TEST(ResettingGlobalHandle) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003328 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00003329 v8::Persistent<String> global;
3330 {
3331 v8::HandleScope scope(isolate);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003332 global.Reset(isolate, v8_str("str"));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00003333 }
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003334 v8::internal::GlobalHandles* global_handles =
3335 reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003336 int initial_handle_count = global_handles->global_handles_count();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00003337 {
3338 v8::HandleScope scope(isolate);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003339 CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00003340 }
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003341 {
3342 v8::HandleScope scope(isolate);
3343 global.Reset(isolate, v8_str("longer"));
3344 }
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003345 CHECK_EQ(global_handles->global_handles_count(), initial_handle_count);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003346 {
3347 v8::HandleScope scope(isolate);
3348 CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 6);
3349 }
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00003350 global.Reset();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003351 CHECK_EQ(global_handles->global_handles_count(), initial_handle_count - 1);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00003352}
3353
3354
3355THREADED_TEST(ResettingGlobalHandleToEmpty) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003356 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00003357 v8::Persistent<String> global;
3358 {
3359 v8::HandleScope scope(isolate);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003360 global.Reset(isolate, v8_str("str"));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00003361 }
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003362 v8::internal::GlobalHandles* global_handles =
3363 reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003364 int initial_handle_count = global_handles->global_handles_count();
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003365 {
3366 v8::HandleScope scope(isolate);
3367 CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
3368 }
ulan@chromium.org57ff8812013-05-10 08:16:55 +00003369 {
3370 v8::HandleScope scope(isolate);
3371 Local<String> empty;
3372 global.Reset(isolate, empty);
3373 }
3374 CHECK(global.IsEmpty());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003375 CHECK_EQ(global_handles->global_handles_count(), initial_handle_count - 1);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00003376}
3377
3378
machenbach@chromium.orgc86e8c22013-11-27 15:11:04 +00003379template<class T>
3380static v8::UniquePersistent<T> PassUnique(v8::UniquePersistent<T> unique) {
3381 return unique.Pass();
3382}
3383
3384
3385template<class T>
3386static v8::UniquePersistent<T> ReturnUnique(v8::Isolate* isolate,
3387 const v8::Persistent<T> & global) {
3388 v8::UniquePersistent<String> unique(isolate, global);
3389 return unique.Pass();
3390}
3391
3392
3393THREADED_TEST(UniquePersistent) {
3394 v8::Isolate* isolate = CcTest::isolate();
3395 v8::Persistent<String> global;
3396 {
3397 v8::HandleScope scope(isolate);
3398 global.Reset(isolate, v8_str("str"));
3399 }
3400 v8::internal::GlobalHandles* global_handles =
3401 reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
3402 int initial_handle_count = global_handles->global_handles_count();
3403 {
3404 v8::UniquePersistent<String> unique(isolate, global);
3405 CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
3406 // Test assignment via Pass
3407 {
3408 v8::UniquePersistent<String> copy = unique.Pass();
3409 CHECK(unique.IsEmpty());
3410 CHECK(copy == global);
3411 CHECK_EQ(initial_handle_count + 1,
3412 global_handles->global_handles_count());
3413 unique = copy.Pass();
3414 }
3415 // Test ctor via Pass
3416 {
3417 v8::UniquePersistent<String> copy(unique.Pass());
3418 CHECK(unique.IsEmpty());
3419 CHECK(copy == global);
3420 CHECK_EQ(initial_handle_count + 1,
3421 global_handles->global_handles_count());
3422 unique = copy.Pass();
3423 }
3424 // Test pass through function call
3425 {
3426 v8::UniquePersistent<String> copy = PassUnique(unique.Pass());
3427 CHECK(unique.IsEmpty());
3428 CHECK(copy == global);
3429 CHECK_EQ(initial_handle_count + 1,
3430 global_handles->global_handles_count());
3431 unique = copy.Pass();
3432 }
3433 CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
3434 }
3435 // Test pass from function call
3436 {
3437 v8::UniquePersistent<String> unique = ReturnUnique(isolate, global);
3438 CHECK(unique == global);
3439 CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
3440 }
3441 CHECK_EQ(initial_handle_count, global_handles->global_handles_count());
3442 global.Reset();
3443}
3444
3445
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003446THREADED_TEST(GlobalHandleUpcast) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003447 v8::Isolate* isolate = CcTest::isolate();
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003448 v8::HandleScope scope(isolate);
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00003449 v8::Local<String> local = v8::Local<String>::New(isolate, v8_str("str"));
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003450 v8::Persistent<String> global_string(isolate, local);
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003451 v8::Persistent<Value>& global_value =
3452 v8::Persistent<Value>::Cast(global_string);
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003453 CHECK(v8::Local<v8::Value>::New(isolate, global_value)->IsString());
3454 CHECK(global_string == v8::Persistent<String>::Cast(global_value));
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00003455 global_string.Reset();
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003456}
3457
3458
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +00003459THREADED_TEST(HandleEquality) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003460 v8::Isolate* isolate = CcTest::isolate();
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +00003461 v8::Persistent<String> global1;
3462 v8::Persistent<String> global2;
3463 {
3464 v8::HandleScope scope(isolate);
3465 global1.Reset(isolate, v8_str("str"));
3466 global2.Reset(isolate, v8_str("str2"));
3467 }
3468 CHECK_EQ(global1 == global1, true);
3469 CHECK_EQ(global1 != global1, false);
3470 {
3471 v8::HandleScope scope(isolate);
3472 Local<String> local1 = Local<String>::New(isolate, global1);
3473 Local<String> local2 = Local<String>::New(isolate, global2);
3474
3475 CHECK_EQ(global1 == local1, true);
3476 CHECK_EQ(global1 != local1, false);
3477 CHECK_EQ(local1 == global1, true);
3478 CHECK_EQ(local1 != global1, false);
3479
3480 CHECK_EQ(global1 == local2, false);
3481 CHECK_EQ(global1 != local2, true);
3482 CHECK_EQ(local2 == global1, false);
3483 CHECK_EQ(local2 != global1, true);
3484
3485 CHECK_EQ(local1 == local2, false);
3486 CHECK_EQ(local1 != local2, true);
3487
3488 Local<String> anotherLocal1 = Local<String>::New(isolate, global1);
3489 CHECK_EQ(local1 == anotherLocal1, true);
3490 CHECK_EQ(local1 != anotherLocal1, false);
3491 }
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00003492 global1.Reset();
3493 global2.Reset();
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +00003494}
3495
3496
mstarzinger@chromium.org32280cf2012-12-06 17:32:37 +00003497THREADED_TEST(LocalHandle) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003498 v8::HandleScope scope(CcTest::isolate());
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00003499 v8::Local<String> local =
3500 v8::Local<String>::New(CcTest::isolate(), v8_str("str"));
mstarzinger@chromium.org32280cf2012-12-06 17:32:37 +00003501 CHECK_EQ(local->Length(), 3);
3502}
3503
3504
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00003505class WeakCallCounter {
3506 public:
3507 explicit WeakCallCounter(int id) : id_(id), number_of_weak_calls_(0) { }
3508 int id() { return id_; }
3509 void increment() { number_of_weak_calls_++; }
3510 int NumberOfWeakCalls() { return number_of_weak_calls_; }
3511 private:
3512 int id_;
3513 int number_of_weak_calls_;
3514};
3515
3516
mstarzinger@chromium.org69008382013-10-18 10:34:25 +00003517template<typename T>
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003518struct WeakCallCounterAndPersistent {
3519 explicit WeakCallCounterAndPersistent(WeakCallCounter* counter)
3520 : counter(counter) {}
3521 WeakCallCounter* counter;
3522 v8::Persistent<T> handle;
3523};
3524
3525
3526template <typename T>
3527static void WeakPointerCallback(
3528 const v8::WeakCallbackData<T, WeakCallCounterAndPersistent<T> >& data) {
3529 CHECK_EQ(1234, data.GetParameter()->counter->id());
3530 data.GetParameter()->counter->increment();
3531 data.GetParameter()->handle.Reset();
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00003532}
3533
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00003534
mstarzinger@chromium.org69008382013-10-18 10:34:25 +00003535template<typename T>
3536static UniqueId MakeUniqueId(const Persistent<T>& p) {
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00003537 return UniqueId(reinterpret_cast<uintptr_t>(*v8::Utils::OpenPersistent(p)));
3538}
3539
3540
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003541THREADED_TEST(ApiObjectGroups) {
3542 LocalContext env;
3543 v8::Isolate* iso = env->GetIsolate();
3544 HandleScope scope(iso);
3545
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003546 WeakCallCounter counter(1234);
3547
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003548 WeakCallCounterAndPersistent<Value> g1s1(&counter);
3549 WeakCallCounterAndPersistent<Value> g1s2(&counter);
3550 WeakCallCounterAndPersistent<Value> g1c1(&counter);
3551 WeakCallCounterAndPersistent<Value> g2s1(&counter);
3552 WeakCallCounterAndPersistent<Value> g2s2(&counter);
3553 WeakCallCounterAndPersistent<Value> g2c1(&counter);
3554
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003555 {
3556 HandleScope scope(iso);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003557 g1s1.handle.Reset(iso, Object::New(iso));
3558 g1s2.handle.Reset(iso, Object::New(iso));
3559 g1c1.handle.Reset(iso, Object::New(iso));
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003560 g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback);
3561 g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback);
3562 g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003563
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003564 g2s1.handle.Reset(iso, Object::New(iso));
3565 g2s2.handle.Reset(iso, Object::New(iso));
3566 g2c1.handle.Reset(iso, Object::New(iso));
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003567 g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback);
3568 g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback);
3569 g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003570 }
3571
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003572 WeakCallCounterAndPersistent<Value> root(&counter);
3573 root.handle.Reset(iso, g1s1.handle); // make a root.
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003574
3575 // Connect group 1 and 2, make a cycle.
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003576 {
3577 HandleScope scope(iso);
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003578 CHECK(Local<Object>::New(iso, g1s2.handle.As<Object>())->
3579 Set(0, Local<Value>::New(iso, g2s2.handle)));
3580 CHECK(Local<Object>::New(iso, g2s1.handle.As<Object>())->
3581 Set(0, Local<Value>::New(iso, g1s1.handle)));
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003582 }
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003583
3584 {
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003585 UniqueId id1 = MakeUniqueId(g1s1.handle);
3586 UniqueId id2 = MakeUniqueId(g2s2.handle);
3587 iso->SetObjectGroupId(g1s1.handle, id1);
3588 iso->SetObjectGroupId(g1s2.handle, id1);
3589 iso->SetReferenceFromGroup(id1, g1c1.handle);
3590 iso->SetObjectGroupId(g2s1.handle, id2);
3591 iso->SetObjectGroupId(g2s2.handle, id2);
3592 iso->SetReferenceFromGroup(id2, g2c1.handle);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003593 }
3594 // Do a single full GC, ensure incremental marking is stopped.
3595 v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>(
3596 iso)->heap();
3597 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
3598
3599 // All object should be alive.
3600 CHECK_EQ(0, counter.NumberOfWeakCalls());
3601
3602 // Weaken the root.
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003603 root.handle.SetWeak(&root, &WeakPointerCallback);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003604 // But make children strong roots---all the objects (except for children)
3605 // should be collectable now.
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003606 g1c1.handle.ClearWeak();
3607 g2c1.handle.ClearWeak();
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003608
3609 // Groups are deleted, rebuild groups.
3610 {
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003611 UniqueId id1 = MakeUniqueId(g1s1.handle);
3612 UniqueId id2 = MakeUniqueId(g2s2.handle);
3613 iso->SetObjectGroupId(g1s1.handle, id1);
3614 iso->SetObjectGroupId(g1s2.handle, id1);
3615 iso->SetReferenceFromGroup(id1, g1c1.handle);
3616 iso->SetObjectGroupId(g2s1.handle, id2);
3617 iso->SetObjectGroupId(g2s2.handle, id2);
3618 iso->SetReferenceFromGroup(id2, g2c1.handle);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003619 }
3620
3621 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
3622
3623 // All objects should be gone. 5 global handles in total.
3624 CHECK_EQ(5, counter.NumberOfWeakCalls());
3625
3626 // And now make children weak again and collect them.
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003627 g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback);
3628 g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003629
3630 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
3631 CHECK_EQ(7, counter.NumberOfWeakCalls());
3632}
3633
3634
mstarzinger@chromium.org69008382013-10-18 10:34:25 +00003635THREADED_TEST(ApiObjectGroupsForSubtypes) {
3636 LocalContext env;
3637 v8::Isolate* iso = env->GetIsolate();
3638 HandleScope scope(iso);
3639
mstarzinger@chromium.org69008382013-10-18 10:34:25 +00003640 WeakCallCounter counter(1234);
3641
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003642 WeakCallCounterAndPersistent<Object> g1s1(&counter);
3643 WeakCallCounterAndPersistent<String> g1s2(&counter);
3644 WeakCallCounterAndPersistent<String> g1c1(&counter);
3645 WeakCallCounterAndPersistent<Object> g2s1(&counter);
3646 WeakCallCounterAndPersistent<String> g2s2(&counter);
3647 WeakCallCounterAndPersistent<String> g2c1(&counter);
3648
mstarzinger@chromium.org69008382013-10-18 10:34:25 +00003649 {
3650 HandleScope scope(iso);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003651 g1s1.handle.Reset(iso, Object::New(iso));
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003652 g1s2.handle.Reset(iso, String::NewFromUtf8(iso, "foo1"));
3653 g1c1.handle.Reset(iso, String::NewFromUtf8(iso, "foo2"));
3654 g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback);
3655 g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback);
3656 g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback);
mstarzinger@chromium.org69008382013-10-18 10:34:25 +00003657
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003658 g2s1.handle.Reset(iso, Object::New(iso));
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003659 g2s2.handle.Reset(iso, String::NewFromUtf8(iso, "foo3"));
3660 g2c1.handle.Reset(iso, String::NewFromUtf8(iso, "foo4"));
3661 g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback);
3662 g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback);
3663 g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback);
mstarzinger@chromium.org69008382013-10-18 10:34:25 +00003664 }
3665
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003666 WeakCallCounterAndPersistent<Value> root(&counter);
3667 root.handle.Reset(iso, g1s1.handle); // make a root.
mstarzinger@chromium.org69008382013-10-18 10:34:25 +00003668
3669 // Connect group 1 and 2, make a cycle.
3670 {
3671 HandleScope scope(iso);
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003672 CHECK(Local<Object>::New(iso, g1s1.handle)
3673 ->Set(0, Local<Object>::New(iso, g2s1.handle)));
3674 CHECK(Local<Object>::New(iso, g2s1.handle)
3675 ->Set(0, Local<Object>::New(iso, g1s1.handle)));
mstarzinger@chromium.org69008382013-10-18 10:34:25 +00003676 }
3677
3678 {
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003679 UniqueId id1 = MakeUniqueId(g1s1.handle);
3680 UniqueId id2 = MakeUniqueId(g2s2.handle);
3681 iso->SetObjectGroupId(g1s1.handle, id1);
3682 iso->SetObjectGroupId(g1s2.handle, id1);
3683 iso->SetReference(g1s1.handle, g1c1.handle);
3684 iso->SetObjectGroupId(g2s1.handle, id2);
3685 iso->SetObjectGroupId(g2s2.handle, id2);
3686 iso->SetReferenceFromGroup(id2, g2c1.handle);
mstarzinger@chromium.org69008382013-10-18 10:34:25 +00003687 }
3688 // Do a single full GC, ensure incremental marking is stopped.
3689 v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>(
3690 iso)->heap();
3691 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
3692
3693 // All object should be alive.
3694 CHECK_EQ(0, counter.NumberOfWeakCalls());
3695
3696 // Weaken the root.
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003697 root.handle.SetWeak(&root, &WeakPointerCallback);
mstarzinger@chromium.org69008382013-10-18 10:34:25 +00003698 // But make children strong roots---all the objects (except for children)
3699 // should be collectable now.
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003700 g1c1.handle.ClearWeak();
3701 g2c1.handle.ClearWeak();
mstarzinger@chromium.org69008382013-10-18 10:34:25 +00003702
3703 // Groups are deleted, rebuild groups.
3704 {
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003705 UniqueId id1 = MakeUniqueId(g1s1.handle);
3706 UniqueId id2 = MakeUniqueId(g2s2.handle);
3707 iso->SetObjectGroupId(g1s1.handle, id1);
3708 iso->SetObjectGroupId(g1s2.handle, id1);
3709 iso->SetReference(g1s1.handle, g1c1.handle);
3710 iso->SetObjectGroupId(g2s1.handle, id2);
3711 iso->SetObjectGroupId(g2s2.handle, id2);
3712 iso->SetReferenceFromGroup(id2, g2c1.handle);
mstarzinger@chromium.org69008382013-10-18 10:34:25 +00003713 }
3714
3715 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
3716
3717 // All objects should be gone. 5 global handles in total.
3718 CHECK_EQ(5, counter.NumberOfWeakCalls());
3719
3720 // And now make children weak again and collect them.
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003721 g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback);
3722 g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback);
mstarzinger@chromium.org69008382013-10-18 10:34:25 +00003723
3724 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
3725 CHECK_EQ(7, counter.NumberOfWeakCalls());
3726}
3727
3728
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003729THREADED_TEST(ApiObjectGroupsCycle) {
3730 LocalContext env;
3731 v8::Isolate* iso = env->GetIsolate();
3732 HandleScope scope(iso);
3733
3734 WeakCallCounter counter(1234);
3735
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003736 WeakCallCounterAndPersistent<Value> g1s1(&counter);
3737 WeakCallCounterAndPersistent<Value> g1s2(&counter);
3738 WeakCallCounterAndPersistent<Value> g2s1(&counter);
3739 WeakCallCounterAndPersistent<Value> g2s2(&counter);
3740 WeakCallCounterAndPersistent<Value> g3s1(&counter);
3741 WeakCallCounterAndPersistent<Value> g3s2(&counter);
3742 WeakCallCounterAndPersistent<Value> g4s1(&counter);
3743 WeakCallCounterAndPersistent<Value> g4s2(&counter);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003744
3745 {
3746 HandleScope scope(iso);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003747 g1s1.handle.Reset(iso, Object::New(iso));
3748 g1s2.handle.Reset(iso, Object::New(iso));
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003749 g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback);
3750 g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback);
3751 CHECK(g1s1.handle.IsWeak());
3752 CHECK(g1s2.handle.IsWeak());
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003753
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003754 g2s1.handle.Reset(iso, Object::New(iso));
3755 g2s2.handle.Reset(iso, Object::New(iso));
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003756 g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback);
3757 g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback);
3758 CHECK(g2s1.handle.IsWeak());
3759 CHECK(g2s2.handle.IsWeak());
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003760
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003761 g3s1.handle.Reset(iso, Object::New(iso));
3762 g3s2.handle.Reset(iso, Object::New(iso));
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003763 g3s1.handle.SetWeak(&g3s1, &WeakPointerCallback);
3764 g3s2.handle.SetWeak(&g3s2, &WeakPointerCallback);
3765 CHECK(g3s1.handle.IsWeak());
3766 CHECK(g3s2.handle.IsWeak());
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003767
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003768 g4s1.handle.Reset(iso, Object::New(iso));
3769 g4s2.handle.Reset(iso, Object::New(iso));
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003770 g4s1.handle.SetWeak(&g4s1, &WeakPointerCallback);
3771 g4s2.handle.SetWeak(&g4s2, &WeakPointerCallback);
3772 CHECK(g4s1.handle.IsWeak());
3773 CHECK(g4s2.handle.IsWeak());
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003774 }
3775
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003776 WeakCallCounterAndPersistent<Value> root(&counter);
3777 root.handle.Reset(iso, g1s1.handle); // make a root.
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003778
3779 // Connect groups. We're building the following cycle:
3780 // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other
3781 // groups.
3782 {
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003783 UniqueId id1 = MakeUniqueId(g1s1.handle);
3784 UniqueId id2 = MakeUniqueId(g2s1.handle);
3785 UniqueId id3 = MakeUniqueId(g3s1.handle);
3786 UniqueId id4 = MakeUniqueId(g4s1.handle);
3787 iso->SetObjectGroupId(g1s1.handle, id1);
3788 iso->SetObjectGroupId(g1s2.handle, id1);
3789 iso->SetReferenceFromGroup(id1, g2s1.handle);
3790 iso->SetObjectGroupId(g2s1.handle, id2);
3791 iso->SetObjectGroupId(g2s2.handle, id2);
3792 iso->SetReferenceFromGroup(id2, g3s1.handle);
3793 iso->SetObjectGroupId(g3s1.handle, id3);
3794 iso->SetObjectGroupId(g3s2.handle, id3);
3795 iso->SetReferenceFromGroup(id3, g4s1.handle);
3796 iso->SetObjectGroupId(g4s1.handle, id4);
3797 iso->SetObjectGroupId(g4s2.handle, id4);
3798 iso->SetReferenceFromGroup(id4, g1s1.handle);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003799 }
3800 // Do a single full GC
3801 v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>(
3802 iso)->heap();
3803 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
3804
3805 // All object should be alive.
3806 CHECK_EQ(0, counter.NumberOfWeakCalls());
3807
3808 // Weaken the root.
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003809 root.handle.SetWeak(&root, &WeakPointerCallback);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003810
3811 // Groups are deleted, rebuild groups.
3812 {
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003813 UniqueId id1 = MakeUniqueId(g1s1.handle);
3814 UniqueId id2 = MakeUniqueId(g2s1.handle);
3815 UniqueId id3 = MakeUniqueId(g3s1.handle);
3816 UniqueId id4 = MakeUniqueId(g4s1.handle);
3817 iso->SetObjectGroupId(g1s1.handle, id1);
3818 iso->SetObjectGroupId(g1s2.handle, id1);
3819 iso->SetReferenceFromGroup(id1, g2s1.handle);
3820 iso->SetObjectGroupId(g2s1.handle, id2);
3821 iso->SetObjectGroupId(g2s2.handle, id2);
3822 iso->SetReferenceFromGroup(id2, g3s1.handle);
3823 iso->SetObjectGroupId(g3s1.handle, id3);
3824 iso->SetObjectGroupId(g3s2.handle, id3);
3825 iso->SetReferenceFromGroup(id3, g4s1.handle);
3826 iso->SetObjectGroupId(g4s1.handle, id4);
3827 iso->SetObjectGroupId(g4s2.handle, id4);
3828 iso->SetReferenceFromGroup(id4, g1s1.handle);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003829 }
3830
3831 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
3832
3833 // All objects should be gone. 9 global handles in total.
3834 CHECK_EQ(9, counter.NumberOfWeakCalls());
3835}
3836
3837
mvstanton@chromium.orge4ac3ef2012-11-12 14:53:34 +00003838// TODO(mstarzinger): This should be a THREADED_TEST but causes failures
3839// on the buildbots, so was made non-threaded for the time being.
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003840TEST(ApiObjectGroupsCycleForScavenger) {
3841 i::FLAG_stress_compaction = false;
3842 i::FLAG_gc_global = false;
3843 LocalContext env;
3844 v8::Isolate* iso = env->GetIsolate();
3845 HandleScope scope(iso);
3846
3847 WeakCallCounter counter(1234);
3848
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003849 WeakCallCounterAndPersistent<Value> g1s1(&counter);
3850 WeakCallCounterAndPersistent<Value> g1s2(&counter);
3851 WeakCallCounterAndPersistent<Value> g2s1(&counter);
3852 WeakCallCounterAndPersistent<Value> g2s2(&counter);
3853 WeakCallCounterAndPersistent<Value> g3s1(&counter);
3854 WeakCallCounterAndPersistent<Value> g3s2(&counter);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003855
3856 {
3857 HandleScope scope(iso);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003858 g1s1.handle.Reset(iso, Object::New(iso));
3859 g1s2.handle.Reset(iso, Object::New(iso));
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003860 g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback);
3861 g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003862
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003863 g2s1.handle.Reset(iso, Object::New(iso));
3864 g2s2.handle.Reset(iso, Object::New(iso));
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003865 g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback);
3866 g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003867
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003868 g3s1.handle.Reset(iso, Object::New(iso));
3869 g3s2.handle.Reset(iso, Object::New(iso));
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003870 g3s1.handle.SetWeak(&g3s1, &WeakPointerCallback);
3871 g3s2.handle.SetWeak(&g3s2, &WeakPointerCallback);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003872 }
3873
3874 // Make a root.
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003875 WeakCallCounterAndPersistent<Value> root(&counter);
3876 root.handle.Reset(iso, g1s1.handle);
3877 root.handle.MarkPartiallyDependent();
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003878
3879 // Connect groups. We're building the following cycle:
3880 // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other
3881 // groups.
3882 {
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003883 HandleScope handle_scope(iso);
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003884 g1s1.handle.MarkPartiallyDependent();
3885 g1s2.handle.MarkPartiallyDependent();
3886 g2s1.handle.MarkPartiallyDependent();
3887 g2s2.handle.MarkPartiallyDependent();
3888 g3s1.handle.MarkPartiallyDependent();
3889 g3s2.handle.MarkPartiallyDependent();
3890 iso->SetObjectGroupId(g1s1.handle, UniqueId(1));
3891 iso->SetObjectGroupId(g1s2.handle, UniqueId(1));
3892 Local<Object>::New(iso, g1s1.handle.As<Object>())->Set(
3893 v8_str("x"), Local<Value>::New(iso, g2s1.handle));
3894 iso->SetObjectGroupId(g2s1.handle, UniqueId(2));
3895 iso->SetObjectGroupId(g2s2.handle, UniqueId(2));
3896 Local<Object>::New(iso, g2s1.handle.As<Object>())->Set(
3897 v8_str("x"), Local<Value>::New(iso, g3s1.handle));
3898 iso->SetObjectGroupId(g3s1.handle, UniqueId(3));
3899 iso->SetObjectGroupId(g3s2.handle, UniqueId(3));
3900 Local<Object>::New(iso, g3s1.handle.As<Object>())->Set(
3901 v8_str("x"), Local<Value>::New(iso, g1s1.handle));
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003902 }
3903
3904 v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>(
3905 iso)->heap();
3906 heap->CollectGarbage(i::NEW_SPACE);
3907
3908 // All objects should be alive.
3909 CHECK_EQ(0, counter.NumberOfWeakCalls());
3910
3911 // Weaken the root.
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003912 root.handle.SetWeak(&root, &WeakPointerCallback);
3913 root.handle.MarkPartiallyDependent();
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003914
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003915 // Groups are deleted, rebuild groups.
3916 {
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003917 HandleScope handle_scope(iso);
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003918 g1s1.handle.MarkPartiallyDependent();
3919 g1s2.handle.MarkPartiallyDependent();
3920 g2s1.handle.MarkPartiallyDependent();
3921 g2s2.handle.MarkPartiallyDependent();
3922 g3s1.handle.MarkPartiallyDependent();
3923 g3s2.handle.MarkPartiallyDependent();
3924 iso->SetObjectGroupId(g1s1.handle, UniqueId(1));
3925 iso->SetObjectGroupId(g1s2.handle, UniqueId(1));
3926 Local<Object>::New(iso, g1s1.handle.As<Object>())->Set(
3927 v8_str("x"), Local<Value>::New(iso, g2s1.handle));
3928 iso->SetObjectGroupId(g2s1.handle, UniqueId(2));
3929 iso->SetObjectGroupId(g2s2.handle, UniqueId(2));
3930 Local<Object>::New(iso, g2s1.handle.As<Object>())->Set(
3931 v8_str("x"), Local<Value>::New(iso, g3s1.handle));
3932 iso->SetObjectGroupId(g3s1.handle, UniqueId(3));
3933 iso->SetObjectGroupId(g3s2.handle, UniqueId(3));
3934 Local<Object>::New(iso, g3s1.handle.As<Object>())->Set(
3935 v8_str("x"), Local<Value>::New(iso, g1s1.handle));
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003936 }
3937
3938 heap->CollectGarbage(i::NEW_SPACE);
3939
3940 // All objects should be gone. 7 global handles in total.
3941 CHECK_EQ(7, counter.NumberOfWeakCalls());
3942}
3943
3944
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003945THREADED_TEST(ScriptException) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003946 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003947 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003948 Local<Script> script = Script::Compile(v8_str("throw 'panama!';"));
3949 v8::TryCatch try_catch;
3950 Local<Value> result = script->Run();
3951 CHECK(result.IsEmpty());
3952 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00003953 String::Utf8Value exception_value(try_catch.Exception());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003954 CHECK_EQ(*exception_value, "panama!");
3955}
3956
3957
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00003958TEST(TryCatchCustomException) {
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00003959 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003960 v8::HandleScope scope(env->GetIsolate());
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00003961 v8::TryCatch try_catch;
3962 CompileRun("function CustomError() { this.a = 'b'; }"
3963 "(function f() { throw new CustomError(); })();");
3964 CHECK(try_catch.HasCaught());
3965 CHECK(try_catch.Exception()->ToObject()->
3966 Get(v8_str("a"))->Equals(v8_str("b")));
3967}
3968
3969
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003970bool message_received;
3971
3972
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00003973static void check_message_0(v8::Handle<v8::Message> message,
3974 v8::Handle<Value> data) {
hpayer@chromium.org8432c912013-02-28 15:55:26 +00003975 CHECK_EQ(5.76, data->NumberValue());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003976 CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
ager@chromium.org65dad4b2009-04-23 08:48:43 +00003977 CHECK_EQ(7.56, message->GetScriptData()->NumberValue());
danno@chromium.orgd3c42102013-08-01 16:58:23 +00003978 CHECK(!message->IsSharedCrossOrigin());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003979 message_received = true;
3980}
3981
3982
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00003983THREADED_TEST(MessageHandler0) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003984 message_received = false;
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003985 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003986 CHECK(!message_received);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003987 LocalContext context;
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003988 v8::V8::AddMessageListener(check_message_0, v8_num(5.76));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003989 v8::ScriptOrigin origin =
3990 v8::ScriptOrigin(v8_str("6.75"));
ager@chromium.org65dad4b2009-04-23 08:48:43 +00003991 v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
3992 &origin);
3993 script->SetData(v8_str("7.56"));
3994 script->Run();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003995 CHECK(message_received);
3996 // clear out the message listener
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00003997 v8::V8::RemoveMessageListeners(check_message_0);
3998}
3999
4000
4001static void check_message_1(v8::Handle<v8::Message> message,
4002 v8::Handle<Value> data) {
4003 CHECK(data->IsNumber());
4004 CHECK_EQ(1337, data->Int32Value());
danno@chromium.orgd3c42102013-08-01 16:58:23 +00004005 CHECK(!message->IsSharedCrossOrigin());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00004006 message_received = true;
4007}
4008
4009
4010TEST(MessageHandler1) {
4011 message_received = false;
machenbach@chromium.org528ce022013-09-23 14:09:36 +00004012 v8::HandleScope scope(CcTest::isolate());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00004013 CHECK(!message_received);
4014 v8::V8::AddMessageListener(check_message_1);
4015 LocalContext context;
4016 CompileRun("throw 1337;");
4017 CHECK(message_received);
4018 // clear out the message listener
4019 v8::V8::RemoveMessageListeners(check_message_1);
4020}
4021
4022
4023static void check_message_2(v8::Handle<v8::Message> message,
4024 v8::Handle<Value> data) {
4025 LocalContext context;
4026 CHECK(data->IsObject());
4027 v8::Local<v8::Value> hidden_property =
4028 v8::Object::Cast(*data)->GetHiddenValue(v8_str("hidden key"));
4029 CHECK(v8_str("hidden value")->Equals(hidden_property));
danno@chromium.orgd3c42102013-08-01 16:58:23 +00004030 CHECK(!message->IsSharedCrossOrigin());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00004031 message_received = true;
4032}
4033
4034
4035TEST(MessageHandler2) {
4036 message_received = false;
machenbach@chromium.org528ce022013-09-23 14:09:36 +00004037 v8::HandleScope scope(CcTest::isolate());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00004038 CHECK(!message_received);
4039 v8::V8::AddMessageListener(check_message_2);
4040 LocalContext context;
4041 v8::Local<v8::Value> error = v8::Exception::Error(v8_str("custom error"));
4042 v8::Object::Cast(*error)->SetHiddenValue(v8_str("hidden key"),
4043 v8_str("hidden value"));
4044 context->Global()->Set(v8_str("error"), error);
4045 CompileRun("throw error;");
4046 CHECK(message_received);
4047 // clear out the message listener
4048 v8::V8::RemoveMessageListeners(check_message_2);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004049}
4050
4051
danno@chromium.orgd3c42102013-08-01 16:58:23 +00004052static void check_message_3(v8::Handle<v8::Message> message,
4053 v8::Handle<Value> data) {
4054 CHECK(message->IsSharedCrossOrigin());
4055 CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
4056 message_received = true;
4057}
4058
4059
4060TEST(MessageHandler3) {
4061 message_received = false;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00004062 v8::Isolate* isolate = CcTest::isolate();
4063 v8::HandleScope scope(isolate);
danno@chromium.orgd3c42102013-08-01 16:58:23 +00004064 CHECK(!message_received);
4065 v8::V8::AddMessageListener(check_message_3);
4066 LocalContext context;
4067 v8::ScriptOrigin origin =
4068 v8::ScriptOrigin(v8_str("6.75"),
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004069 v8::Integer::New(isolate, 1),
4070 v8::Integer::New(isolate, 2),
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00004071 v8::True(isolate));
danno@chromium.orgd3c42102013-08-01 16:58:23 +00004072 v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
4073 &origin);
4074 script->Run();
4075 CHECK(message_received);
4076 // clear out the message listener
4077 v8::V8::RemoveMessageListeners(check_message_3);
4078}
4079
4080
4081static void check_message_4(v8::Handle<v8::Message> message,
4082 v8::Handle<Value> data) {
4083 CHECK(!message->IsSharedCrossOrigin());
4084 CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
4085 message_received = true;
4086}
4087
4088
4089TEST(MessageHandler4) {
4090 message_received = false;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00004091 v8::Isolate* isolate = CcTest::isolate();
4092 v8::HandleScope scope(isolate);
danno@chromium.orgd3c42102013-08-01 16:58:23 +00004093 CHECK(!message_received);
4094 v8::V8::AddMessageListener(check_message_4);
4095 LocalContext context;
4096 v8::ScriptOrigin origin =
4097 v8::ScriptOrigin(v8_str("6.75"),
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004098 v8::Integer::New(isolate, 1),
4099 v8::Integer::New(isolate, 2),
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00004100 v8::False(isolate));
danno@chromium.orgd3c42102013-08-01 16:58:23 +00004101 v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
4102 &origin);
4103 script->Run();
4104 CHECK(message_received);
4105 // clear out the message listener
4106 v8::V8::RemoveMessageListeners(check_message_4);
4107}
4108
4109
4110static void check_message_5a(v8::Handle<v8::Message> message,
4111 v8::Handle<Value> data) {
4112 CHECK(message->IsSharedCrossOrigin());
4113 CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
4114 message_received = true;
4115}
4116
4117
4118static void check_message_5b(v8::Handle<v8::Message> message,
4119 v8::Handle<Value> data) {
4120 CHECK(!message->IsSharedCrossOrigin());
4121 CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
4122 message_received = true;
4123}
4124
4125
4126TEST(MessageHandler5) {
4127 message_received = false;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00004128 v8::Isolate* isolate = CcTest::isolate();
4129 v8::HandleScope scope(isolate);
danno@chromium.orgd3c42102013-08-01 16:58:23 +00004130 CHECK(!message_received);
4131 v8::V8::AddMessageListener(check_message_5a);
4132 LocalContext context;
4133 v8::ScriptOrigin origin =
4134 v8::ScriptOrigin(v8_str("6.75"),
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004135 v8::Integer::New(isolate, 1),
4136 v8::Integer::New(isolate, 2),
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00004137 v8::True(isolate));
danno@chromium.orgd3c42102013-08-01 16:58:23 +00004138 v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
4139 &origin);
4140 script->Run();
4141 CHECK(message_received);
4142 // clear out the message listener
4143 v8::V8::RemoveMessageListeners(check_message_5a);
4144
4145 message_received = false;
4146 v8::V8::AddMessageListener(check_message_5b);
4147 origin =
4148 v8::ScriptOrigin(v8_str("6.75"),
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004149 v8::Integer::New(isolate, 1),
4150 v8::Integer::New(isolate, 2),
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00004151 v8::False(isolate));
danno@chromium.orgd3c42102013-08-01 16:58:23 +00004152 script = Script::Compile(v8_str("throw 'error'"),
4153 &origin);
4154 script->Run();
4155 CHECK(message_received);
4156 // clear out the message listener
4157 v8::V8::RemoveMessageListeners(check_message_5b);
4158}
4159
4160
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004161THREADED_TEST(GetSetProperty) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004162 LocalContext context;
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004163 v8::Isolate* isolate = context->GetIsolate();
4164 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004165 context->Global()->Set(v8_str("foo"), v8_num(14));
4166 context->Global()->Set(v8_str("12"), v8_num(92));
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004167 context->Global()->Set(v8::Integer::New(isolate, 16), v8_num(32));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004168 context->Global()->Set(v8_num(13), v8_num(56));
4169 Local<Value> foo = Script::Compile(v8_str("this.foo"))->Run();
4170 CHECK_EQ(14, foo->Int32Value());
4171 Local<Value> twelve = Script::Compile(v8_str("this[12]"))->Run();
4172 CHECK_EQ(92, twelve->Int32Value());
4173 Local<Value> sixteen = Script::Compile(v8_str("this[16]"))->Run();
4174 CHECK_EQ(32, sixteen->Int32Value());
4175 Local<Value> thirteen = Script::Compile(v8_str("this[13]"))->Run();
4176 CHECK_EQ(56, thirteen->Int32Value());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004177 CHECK_EQ(92,
4178 context->Global()->Get(v8::Integer::New(isolate, 12))->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004179 CHECK_EQ(92, context->Global()->Get(v8_str("12"))->Int32Value());
4180 CHECK_EQ(92, context->Global()->Get(v8_num(12))->Int32Value());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004181 CHECK_EQ(32,
4182 context->Global()->Get(v8::Integer::New(isolate, 16))->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004183 CHECK_EQ(32, context->Global()->Get(v8_str("16"))->Int32Value());
4184 CHECK_EQ(32, context->Global()->Get(v8_num(16))->Int32Value());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004185 CHECK_EQ(56,
4186 context->Global()->Get(v8::Integer::New(isolate, 13))->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004187 CHECK_EQ(56, context->Global()->Get(v8_str("13"))->Int32Value());
4188 CHECK_EQ(56, context->Global()->Get(v8_num(13))->Int32Value());
4189}
4190
4191
4192THREADED_TEST(PropertyAttributes) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004193 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004194 v8::HandleScope scope(context->GetIsolate());
rossberg@chromium.org717967f2011-07-20 13:44:42 +00004195 // none
4196 Local<String> prop = v8_str("none");
4197 context->Global()->Set(prop, v8_num(7));
4198 CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(prop));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004199 // read-only
rossberg@chromium.org717967f2011-07-20 13:44:42 +00004200 prop = v8_str("read_only");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004201 context->Global()->Set(prop, v8_num(7), v8::ReadOnly);
4202 CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
rossberg@chromium.org717967f2011-07-20 13:44:42 +00004203 CHECK_EQ(v8::ReadOnly, context->Global()->GetPropertyAttributes(prop));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004204 Script::Compile(v8_str("read_only = 9"))->Run();
4205 CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
4206 context->Global()->Set(prop, v8_num(10));
4207 CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
4208 // dont-delete
4209 prop = v8_str("dont_delete");
4210 context->Global()->Set(prop, v8_num(13), v8::DontDelete);
4211 CHECK_EQ(13, context->Global()->Get(prop)->Int32Value());
4212 Script::Compile(v8_str("delete dont_delete"))->Run();
4213 CHECK_EQ(13, context->Global()->Get(prop)->Int32Value());
rossberg@chromium.org717967f2011-07-20 13:44:42 +00004214 CHECK_EQ(v8::DontDelete, context->Global()->GetPropertyAttributes(prop));
4215 // dont-enum
4216 prop = v8_str("dont_enum");
4217 context->Global()->Set(prop, v8_num(28), v8::DontEnum);
4218 CHECK_EQ(v8::DontEnum, context->Global()->GetPropertyAttributes(prop));
4219 // absent
4220 prop = v8_str("absent");
4221 CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(prop));
4222 Local<Value> fake_prop = v8_num(1);
4223 CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(fake_prop));
4224 // exception
4225 TryCatch try_catch;
4226 Local<Value> exception =
4227 CompileRun("({ toString: function() { throw 'exception';} })");
4228 CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(exception));
4229 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00004230 String::Utf8Value exception_value(try_catch.Exception());
rossberg@chromium.org717967f2011-07-20 13:44:42 +00004231 CHECK_EQ("exception", *exception_value);
4232 try_catch.Reset();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004233}
4234
4235
4236THREADED_TEST(Array) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004237 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004238 v8::HandleScope scope(context->GetIsolate());
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00004239 Local<v8::Array> array = v8::Array::New(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004240 CHECK_EQ(0, array->Length());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004241 CHECK(array->Get(0)->IsUndefined());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004242 CHECK(!array->Has(0));
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004243 CHECK(array->Get(100)->IsUndefined());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004244 CHECK(!array->Has(100));
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004245 array->Set(2, v8_num(7));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004246 CHECK_EQ(3, array->Length());
4247 CHECK(!array->Has(0));
4248 CHECK(!array->Has(1));
4249 CHECK(array->Has(2));
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004250 CHECK_EQ(7, array->Get(2)->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004251 Local<Value> obj = Script::Compile(v8_str("[1, 2, 3]"))->Run();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004252 Local<v8::Array> arr = obj.As<v8::Array>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004253 CHECK_EQ(3, arr->Length());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004254 CHECK_EQ(1, arr->Get(0)->Int32Value());
4255 CHECK_EQ(2, arr->Get(1)->Int32Value());
4256 CHECK_EQ(3, arr->Get(2)->Int32Value());
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00004257 array = v8::Array::New(context->GetIsolate(), 27);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00004258 CHECK_EQ(27, array->Length());
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00004259 array = v8::Array::New(context->GetIsolate(), -27);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00004260 CHECK_EQ(0, array->Length());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004261}
4262
4263
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00004264void HandleF(const v8::FunctionCallbackInfo<v8::Value>& args) {
machenbach@chromium.orgafbdadc2013-12-09 16:12:18 +00004265 v8::EscapableHandleScope scope(args.GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004266 ApiTestFuzzer::Fuzz();
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00004267 Local<v8::Array> result = v8::Array::New(args.GetIsolate(), args.Length());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004268 for (int i = 0; i < args.Length(); i++)
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004269 result->Set(i, args[i]);
machenbach@chromium.orgafbdadc2013-12-09 16:12:18 +00004270 args.GetReturnValue().Set(scope.Escape(result));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004271}
4272
4273
4274THREADED_TEST(Vector) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00004275 v8::Isolate* isolate = CcTest::isolate();
4276 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004277 Local<ObjectTemplate> global = ObjectTemplate::New(isolate);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00004278 global->Set(v8_str("f"), v8::FunctionTemplate::New(isolate, HandleF));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004279 LocalContext context(0, global);
4280
4281 const char* fun = "f()";
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004282 Local<v8::Array> a0 = CompileRun(fun).As<v8::Array>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004283 CHECK_EQ(0, a0->Length());
4284
4285 const char* fun2 = "f(11)";
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004286 Local<v8::Array> a1 = CompileRun(fun2).As<v8::Array>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004287 CHECK_EQ(1, a1->Length());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004288 CHECK_EQ(11, a1->Get(0)->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004289
4290 const char* fun3 = "f(12, 13)";
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004291 Local<v8::Array> a2 = CompileRun(fun3).As<v8::Array>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004292 CHECK_EQ(2, a2->Length());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004293 CHECK_EQ(12, a2->Get(0)->Int32Value());
4294 CHECK_EQ(13, a2->Get(1)->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004295
4296 const char* fun4 = "f(14, 15, 16)";
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004297 Local<v8::Array> a3 = CompileRun(fun4).As<v8::Array>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004298 CHECK_EQ(3, a3->Length());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004299 CHECK_EQ(14, a3->Get(0)->Int32Value());
4300 CHECK_EQ(15, a3->Get(1)->Int32Value());
4301 CHECK_EQ(16, a3->Get(2)->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004302
4303 const char* fun5 = "f(17, 18, 19, 20)";
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004304 Local<v8::Array> a4 = CompileRun(fun5).As<v8::Array>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004305 CHECK_EQ(4, a4->Length());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004306 CHECK_EQ(17, a4->Get(0)->Int32Value());
4307 CHECK_EQ(18, a4->Get(1)->Int32Value());
4308 CHECK_EQ(19, a4->Get(2)->Int32Value());
4309 CHECK_EQ(20, a4->Get(3)->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004310}
4311
4312
4313THREADED_TEST(FunctionCall) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004314 LocalContext context;
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +00004315 v8::Isolate* isolate = context->GetIsolate();
4316 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004317 CompileRun(
4318 "function Foo() {"
4319 " var result = [];"
4320 " for (var i = 0; i < arguments.length; i++) {"
4321 " result.push(arguments[i]);"
4322 " }"
4323 " return result;"
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +00004324 "}"
4325 "function ReturnThisSloppy() {"
4326 " return this;"
4327 "}"
4328 "function ReturnThisStrict() {"
4329 " 'use strict';"
4330 " return this;"
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004331 "}");
4332 Local<Function> Foo =
4333 Local<Function>::Cast(context->Global()->Get(v8_str("Foo")));
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +00004334 Local<Function> ReturnThisSloppy =
4335 Local<Function>::Cast(context->Global()->Get(v8_str("ReturnThisSloppy")));
4336 Local<Function> ReturnThisStrict =
4337 Local<Function>::Cast(context->Global()->Get(v8_str("ReturnThisStrict")));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004338
4339 v8::Handle<Value>* args0 = NULL;
4340 Local<v8::Array> a0 = Local<v8::Array>::Cast(Foo->Call(Foo, 0, args0));
4341 CHECK_EQ(0, a0->Length());
4342
4343 v8::Handle<Value> args1[] = { v8_num(1.1) };
4344 Local<v8::Array> a1 = Local<v8::Array>::Cast(Foo->Call(Foo, 1, args1));
4345 CHECK_EQ(1, a1->Length());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004346 CHECK_EQ(1.1, a1->Get(v8::Integer::New(isolate, 0))->NumberValue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004347
4348 v8::Handle<Value> args2[] = { v8_num(2.2),
4349 v8_num(3.3) };
4350 Local<v8::Array> a2 = Local<v8::Array>::Cast(Foo->Call(Foo, 2, args2));
4351 CHECK_EQ(2, a2->Length());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004352 CHECK_EQ(2.2, a2->Get(v8::Integer::New(isolate, 0))->NumberValue());
4353 CHECK_EQ(3.3, a2->Get(v8::Integer::New(isolate, 1))->NumberValue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004354
4355 v8::Handle<Value> args3[] = { v8_num(4.4),
4356 v8_num(5.5),
4357 v8_num(6.6) };
4358 Local<v8::Array> a3 = Local<v8::Array>::Cast(Foo->Call(Foo, 3, args3));
4359 CHECK_EQ(3, a3->Length());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004360 CHECK_EQ(4.4, a3->Get(v8::Integer::New(isolate, 0))->NumberValue());
4361 CHECK_EQ(5.5, a3->Get(v8::Integer::New(isolate, 1))->NumberValue());
4362 CHECK_EQ(6.6, a3->Get(v8::Integer::New(isolate, 2))->NumberValue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004363
4364 v8::Handle<Value> args4[] = { v8_num(7.7),
4365 v8_num(8.8),
4366 v8_num(9.9),
4367 v8_num(10.11) };
4368 Local<v8::Array> a4 = Local<v8::Array>::Cast(Foo->Call(Foo, 4, args4));
4369 CHECK_EQ(4, a4->Length());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004370 CHECK_EQ(7.7, a4->Get(v8::Integer::New(isolate, 0))->NumberValue());
4371 CHECK_EQ(8.8, a4->Get(v8::Integer::New(isolate, 1))->NumberValue());
4372 CHECK_EQ(9.9, a4->Get(v8::Integer::New(isolate, 2))->NumberValue());
4373 CHECK_EQ(10.11, a4->Get(v8::Integer::New(isolate, 3))->NumberValue());
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +00004374
4375 Local<v8::Value> r1 = ReturnThisSloppy->Call(v8::Undefined(isolate), 0, NULL);
4376 CHECK(r1->StrictEquals(context->Global()));
4377 Local<v8::Value> r2 = ReturnThisSloppy->Call(v8::Null(isolate), 0, NULL);
4378 CHECK(r2->StrictEquals(context->Global()));
4379 Local<v8::Value> r3 = ReturnThisSloppy->Call(v8_num(42), 0, NULL);
4380 CHECK(r3->IsNumberObject());
4381 CHECK_EQ(42.0, r3.As<v8::NumberObject>()->ValueOf());
4382 Local<v8::Value> r4 = ReturnThisSloppy->Call(v8_str("hello"), 0, NULL);
4383 CHECK(r4->IsStringObject());
4384 CHECK(r4.As<v8::StringObject>()->ValueOf()->StrictEquals(v8_str("hello")));
4385 Local<v8::Value> r5 = ReturnThisSloppy->Call(v8::True(isolate), 0, NULL);
4386 CHECK(r5->IsBooleanObject());
4387 CHECK(r5.As<v8::BooleanObject>()->ValueOf());
4388
4389 Local<v8::Value> r6 = ReturnThisStrict->Call(v8::Undefined(isolate), 0, NULL);
4390 CHECK(r6->IsUndefined());
4391 Local<v8::Value> r7 = ReturnThisStrict->Call(v8::Null(isolate), 0, NULL);
4392 CHECK(r7->IsNull());
4393 Local<v8::Value> r8 = ReturnThisStrict->Call(v8_num(42), 0, NULL);
4394 CHECK(r8->StrictEquals(v8_num(42)));
4395 Local<v8::Value> r9 = ReturnThisStrict->Call(v8_str("hello"), 0, NULL);
4396 CHECK(r9->StrictEquals(v8_str("hello")));
4397 Local<v8::Value> r10 = ReturnThisStrict->Call(v8::True(isolate), 0, NULL);
4398 CHECK(r10->StrictEquals(v8::True(isolate)));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004399}
4400
4401
4402static const char* js_code_causing_out_of_memory =
4403 "var a = new Array(); while(true) a.push(a);";
4404
4405
4406// These tests run for a long time and prevent us from running tests
4407// that come after them so they cannot run in parallel.
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00004408TEST(OutOfMemory) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004409 // It's not possible to read a snapshot into a heap with different dimensions.
lrn@chromium.org32d961d2010-06-30 09:09:34 +00004410 if (i::Snapshot::IsEnabled()) return;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004411 // Set heap limits.
4412 static const int K = 1024;
4413 v8::ResourceConstraints constraints;
4414 constraints.set_max_young_space_size(256 * K);
machenbach@chromium.orgc1789ee2013-07-05 07:09:57 +00004415 constraints.set_max_old_space_size(5 * K * K);
machenbach@chromium.org7ff76072013-11-21 09:47:43 +00004416 v8::SetResourceConstraints(CcTest::isolate(), &constraints);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004417
4418 // Execute a script that causes out of memory.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004419 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004420 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004421 v8::V8::IgnoreOutOfMemoryException();
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00004422 Local<Script> script = Script::Compile(String::NewFromUtf8(
4423 context->GetIsolate(), js_code_causing_out_of_memory));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004424 Local<Value> result = script->Run();
4425
4426 // Check for out of memory state.
4427 CHECK(result.IsEmpty());
4428 CHECK(context->HasOutOfMemoryException());
4429}
4430
4431
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00004432void ProvokeOutOfMemory(const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004433 ApiTestFuzzer::Fuzz();
4434
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004435 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004436 v8::HandleScope scope(context->GetIsolate());
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00004437 Local<Script> script = Script::Compile(String::NewFromUtf8(
4438 context->GetIsolate(), js_code_causing_out_of_memory));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004439 Local<Value> result = script->Run();
4440
4441 // Check for out of memory state.
4442 CHECK(result.IsEmpty());
4443 CHECK(context->HasOutOfMemoryException());
4444
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00004445 args.GetReturnValue().Set(result);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004446}
4447
4448
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00004449TEST(OutOfMemoryNested) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004450 // It's not possible to read a snapshot into a heap with different dimensions.
lrn@chromium.org32d961d2010-06-30 09:09:34 +00004451 if (i::Snapshot::IsEnabled()) return;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004452 // Set heap limits.
4453 static const int K = 1024;
4454 v8::ResourceConstraints constraints;
4455 constraints.set_max_young_space_size(256 * K);
machenbach@chromium.orgc1789ee2013-07-05 07:09:57 +00004456 constraints.set_max_old_space_size(5 * K * K);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004457 v8::Isolate* isolate = CcTest::isolate();
4458 v8::SetResourceConstraints(isolate, &constraints);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004459
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004460 v8::HandleScope scope(isolate);
4461 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004462 templ->Set(v8_str("ProvokeOutOfMemory"),
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004463 v8::FunctionTemplate::New(isolate, ProvokeOutOfMemory));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004464 LocalContext context(0, templ);
4465 v8::V8::IgnoreOutOfMemoryException();
4466 Local<Value> result = CompileRun(
4467 "var thrown = false;"
4468 "try {"
4469 " ProvokeOutOfMemory();"
4470 "} catch (e) {"
4471 " thrown = true;"
4472 "}");
4473 // Check for out of memory state.
4474 CHECK(result.IsEmpty());
4475 CHECK(context->HasOutOfMemoryException());
4476}
4477
4478
yangguo@chromium.org49546742013-12-23 16:17:49 +00004479void OOMCallback(const char* location, const char* message) {
4480 exit(0);
4481}
4482
4483
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004484TEST(HugeConsStringOutOfMemory) {
4485 // It's not possible to read a snapshot into a heap with different dimensions.
lrn@chromium.org32d961d2010-06-30 09:09:34 +00004486 if (i::Snapshot::IsEnabled()) return;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004487 // Set heap limits.
4488 static const int K = 1024;
4489 v8::ResourceConstraints constraints;
4490 constraints.set_max_young_space_size(256 * K);
machenbach@chromium.orgc1789ee2013-07-05 07:09:57 +00004491 constraints.set_max_old_space_size(4 * K * K);
machenbach@chromium.org7ff76072013-11-21 09:47:43 +00004492 v8::SetResourceConstraints(CcTest::isolate(), &constraints);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004493
4494 // Execute a script that causes out of memory.
yangguo@chromium.org49546742013-12-23 16:17:49 +00004495 v8::V8::SetFatalErrorHandler(OOMCallback);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004496
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00004497 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004498 v8::HandleScope scope(context->GetIsolate());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00004499
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004500 // Build huge string. This should fail with out of memory exception.
yangguo@chromium.org49546742013-12-23 16:17:49 +00004501 CompileRun(
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004502 "var str = Array.prototype.join.call({length: 513}, \"A\").toUpperCase();"
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00004503 "for (var i = 0; i < 22; i++) { str = str + str; }");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004504
yangguo@chromium.org49546742013-12-23 16:17:49 +00004505 CHECK(false); // Should not return.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004506}
4507
4508
4509THREADED_TEST(ConstructCall) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004510 LocalContext context;
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004511 v8::Isolate* isolate = context->GetIsolate();
4512 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004513 CompileRun(
4514 "function Foo() {"
4515 " var result = [];"
4516 " for (var i = 0; i < arguments.length; i++) {"
4517 " result.push(arguments[i]);"
4518 " }"
4519 " return result;"
4520 "}");
4521 Local<Function> Foo =
4522 Local<Function>::Cast(context->Global()->Get(v8_str("Foo")));
4523
4524 v8::Handle<Value>* args0 = NULL;
4525 Local<v8::Array> a0 = Local<v8::Array>::Cast(Foo->NewInstance(0, args0));
4526 CHECK_EQ(0, a0->Length());
4527
4528 v8::Handle<Value> args1[] = { v8_num(1.1) };
4529 Local<v8::Array> a1 = Local<v8::Array>::Cast(Foo->NewInstance(1, args1));
4530 CHECK_EQ(1, a1->Length());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004531 CHECK_EQ(1.1, a1->Get(v8::Integer::New(isolate, 0))->NumberValue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004532
4533 v8::Handle<Value> args2[] = { v8_num(2.2),
4534 v8_num(3.3) };
4535 Local<v8::Array> a2 = Local<v8::Array>::Cast(Foo->NewInstance(2, args2));
4536 CHECK_EQ(2, a2->Length());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004537 CHECK_EQ(2.2, a2->Get(v8::Integer::New(isolate, 0))->NumberValue());
4538 CHECK_EQ(3.3, a2->Get(v8::Integer::New(isolate, 1))->NumberValue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004539
4540 v8::Handle<Value> args3[] = { v8_num(4.4),
4541 v8_num(5.5),
4542 v8_num(6.6) };
4543 Local<v8::Array> a3 = Local<v8::Array>::Cast(Foo->NewInstance(3, args3));
4544 CHECK_EQ(3, a3->Length());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004545 CHECK_EQ(4.4, a3->Get(v8::Integer::New(isolate, 0))->NumberValue());
4546 CHECK_EQ(5.5, a3->Get(v8::Integer::New(isolate, 1))->NumberValue());
4547 CHECK_EQ(6.6, a3->Get(v8::Integer::New(isolate, 2))->NumberValue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004548
4549 v8::Handle<Value> args4[] = { v8_num(7.7),
4550 v8_num(8.8),
4551 v8_num(9.9),
4552 v8_num(10.11) };
4553 Local<v8::Array> a4 = Local<v8::Array>::Cast(Foo->NewInstance(4, args4));
4554 CHECK_EQ(4, a4->Length());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004555 CHECK_EQ(7.7, a4->Get(v8::Integer::New(isolate, 0))->NumberValue());
4556 CHECK_EQ(8.8, a4->Get(v8::Integer::New(isolate, 1))->NumberValue());
4557 CHECK_EQ(9.9, a4->Get(v8::Integer::New(isolate, 2))->NumberValue());
4558 CHECK_EQ(10.11, a4->Get(v8::Integer::New(isolate, 3))->NumberValue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004559}
4560
4561
4562static void CheckUncle(v8::TryCatch* try_catch) {
4563 CHECK(try_catch->HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00004564 String::Utf8Value str_value(try_catch->Exception());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004565 CHECK_EQ(*str_value, "uncle?");
4566 try_catch->Reset();
4567}
4568
4569
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004570THREADED_TEST(ConversionNumber) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004571 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004572 v8::HandleScope scope(env->GetIsolate());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004573 // Very large number.
4574 CompileRun("var obj = Math.pow(2,32) * 1237;");
4575 Local<Value> obj = env->Global()->Get(v8_str("obj"));
4576 CHECK_EQ(5312874545152.0, obj->ToNumber()->Value());
4577 CHECK_EQ(0, obj->ToInt32()->Value());
4578 CHECK(0u == obj->ToUint32()->Value()); // NOLINT - no CHECK_EQ for unsigned.
4579 // Large number.
4580 CompileRun("var obj = -1234567890123;");
4581 obj = env->Global()->Get(v8_str("obj"));
4582 CHECK_EQ(-1234567890123.0, obj->ToNumber()->Value());
4583 CHECK_EQ(-1912276171, obj->ToInt32()->Value());
4584 CHECK(2382691125u == obj->ToUint32()->Value()); // NOLINT
4585 // Small positive integer.
4586 CompileRun("var obj = 42;");
4587 obj = env->Global()->Get(v8_str("obj"));
4588 CHECK_EQ(42.0, obj->ToNumber()->Value());
4589 CHECK_EQ(42, obj->ToInt32()->Value());
4590 CHECK(42u == obj->ToUint32()->Value()); // NOLINT
4591 // Negative integer.
4592 CompileRun("var obj = -37;");
4593 obj = env->Global()->Get(v8_str("obj"));
4594 CHECK_EQ(-37.0, obj->ToNumber()->Value());
4595 CHECK_EQ(-37, obj->ToInt32()->Value());
4596 CHECK(4294967259u == obj->ToUint32()->Value()); // NOLINT
4597 // Positive non-int32 integer.
4598 CompileRun("var obj = 0x81234567;");
4599 obj = env->Global()->Get(v8_str("obj"));
4600 CHECK_EQ(2166572391.0, obj->ToNumber()->Value());
4601 CHECK_EQ(-2128394905, obj->ToInt32()->Value());
4602 CHECK(2166572391u == obj->ToUint32()->Value()); // NOLINT
4603 // Fraction.
4604 CompileRun("var obj = 42.3;");
4605 obj = env->Global()->Get(v8_str("obj"));
4606 CHECK_EQ(42.3, obj->ToNumber()->Value());
4607 CHECK_EQ(42, obj->ToInt32()->Value());
4608 CHECK(42u == obj->ToUint32()->Value()); // NOLINT
4609 // Large negative fraction.
4610 CompileRun("var obj = -5726623061.75;");
4611 obj = env->Global()->Get(v8_str("obj"));
4612 CHECK_EQ(-5726623061.75, obj->ToNumber()->Value());
4613 CHECK_EQ(-1431655765, obj->ToInt32()->Value());
4614 CHECK(2863311531u == obj->ToUint32()->Value()); // NOLINT
4615}
4616
4617
4618THREADED_TEST(isNumberType) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004619 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004620 v8::HandleScope scope(env->GetIsolate());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004621 // Very large number.
4622 CompileRun("var obj = Math.pow(2,32) * 1237;");
4623 Local<Value> obj = env->Global()->Get(v8_str("obj"));
4624 CHECK(!obj->IsInt32());
4625 CHECK(!obj->IsUint32());
4626 // Large negative number.
4627 CompileRun("var obj = -1234567890123;");
4628 obj = env->Global()->Get(v8_str("obj"));
4629 CHECK(!obj->IsInt32());
4630 CHECK(!obj->IsUint32());
4631 // Small positive integer.
4632 CompileRun("var obj = 42;");
4633 obj = env->Global()->Get(v8_str("obj"));
4634 CHECK(obj->IsInt32());
4635 CHECK(obj->IsUint32());
4636 // Negative integer.
4637 CompileRun("var obj = -37;");
4638 obj = env->Global()->Get(v8_str("obj"));
4639 CHECK(obj->IsInt32());
4640 CHECK(!obj->IsUint32());
4641 // Positive non-int32 integer.
4642 CompileRun("var obj = 0x81234567;");
4643 obj = env->Global()->Get(v8_str("obj"));
4644 CHECK(!obj->IsInt32());
4645 CHECK(obj->IsUint32());
4646 // Fraction.
4647 CompileRun("var obj = 42.3;");
4648 obj = env->Global()->Get(v8_str("obj"));
4649 CHECK(!obj->IsInt32());
4650 CHECK(!obj->IsUint32());
4651 // Large negative fraction.
4652 CompileRun("var obj = -5726623061.75;");
4653 obj = env->Global()->Get(v8_str("obj"));
4654 CHECK(!obj->IsInt32());
4655 CHECK(!obj->IsUint32());
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00004656 // Positive zero
4657 CompileRun("var obj = 0.0;");
4658 obj = env->Global()->Get(v8_str("obj"));
4659 CHECK(obj->IsInt32());
4660 CHECK(obj->IsUint32());
4661 // Positive zero
4662 CompileRun("var obj = -0.0;");
4663 obj = env->Global()->Get(v8_str("obj"));
4664 CHECK(!obj->IsInt32());
4665 CHECK(!obj->IsUint32());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004666}
4667
4668
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004669THREADED_TEST(ConversionException) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004670 LocalContext env;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00004671 v8::Isolate* isolate = env->GetIsolate();
4672 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004673 CompileRun(
4674 "function TestClass() { };"
4675 "TestClass.prototype.toString = function () { throw 'uncle?'; };"
4676 "var obj = new TestClass();");
4677 Local<Value> obj = env->Global()->Get(v8_str("obj"));
4678
4679 v8::TryCatch try_catch;
4680
4681 Local<Value> to_string_result = obj->ToString();
4682 CHECK(to_string_result.IsEmpty());
4683 CheckUncle(&try_catch);
4684
4685 Local<Value> to_number_result = obj->ToNumber();
4686 CHECK(to_number_result.IsEmpty());
4687 CheckUncle(&try_catch);
4688
4689 Local<Value> to_integer_result = obj->ToInteger();
4690 CHECK(to_integer_result.IsEmpty());
4691 CheckUncle(&try_catch);
4692
4693 Local<Value> to_uint32_result = obj->ToUint32();
4694 CHECK(to_uint32_result.IsEmpty());
4695 CheckUncle(&try_catch);
4696
4697 Local<Value> to_int32_result = obj->ToInt32();
4698 CHECK(to_int32_result.IsEmpty());
4699 CheckUncle(&try_catch);
4700
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00004701 Local<Value> to_object_result = v8::Undefined(isolate)->ToObject();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004702 CHECK(to_object_result.IsEmpty());
4703 CHECK(try_catch.HasCaught());
4704 try_catch.Reset();
4705
4706 int32_t int32_value = obj->Int32Value();
4707 CHECK_EQ(0, int32_value);
4708 CheckUncle(&try_catch);
4709
4710 uint32_t uint32_value = obj->Uint32Value();
4711 CHECK_EQ(0, uint32_value);
4712 CheckUncle(&try_catch);
4713
4714 double number_value = obj->NumberValue();
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00004715 CHECK_NE(0, std::isnan(number_value));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004716 CheckUncle(&try_catch);
4717
4718 int64_t integer_value = obj->IntegerValue();
4719 CHECK_EQ(0.0, static_cast<double>(integer_value));
4720 CheckUncle(&try_catch);
4721}
4722
4723
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00004724void ThrowFromC(const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004725 ApiTestFuzzer::Fuzz();
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00004726 args.GetIsolate()->ThrowException(v8_str("konto"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004727}
4728
4729
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00004730void CCatcher(const v8::FunctionCallbackInfo<v8::Value>& args) {
4731 if (args.Length() < 1) {
4732 args.GetReturnValue().Set(false);
4733 return;
4734 }
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004735 v8::HandleScope scope(args.GetIsolate());
ager@chromium.org8bb60582008-12-11 12:02:20 +00004736 v8::TryCatch try_catch;
ager@chromium.org71daaf62009-04-01 07:22:49 +00004737 Local<Value> result = v8::Script::Compile(args[0]->ToString())->Run();
4738 CHECK(!try_catch.HasCaught() || result.IsEmpty());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00004739 args.GetReturnValue().Set(try_catch.HasCaught());
ager@chromium.org8bb60582008-12-11 12:02:20 +00004740}
4741
4742
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004743THREADED_TEST(APICatch) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004744 v8::Isolate* isolate = CcTest::isolate();
4745 v8::HandleScope scope(isolate);
4746 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004747 templ->Set(v8_str("ThrowFromC"),
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004748 v8::FunctionTemplate::New(isolate, ThrowFromC));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004749 LocalContext context(0, templ);
4750 CompileRun(
4751 "var thrown = false;"
4752 "try {"
4753 " ThrowFromC();"
4754 "} catch (e) {"
4755 " thrown = true;"
4756 "}");
4757 Local<Value> thrown = context->Global()->Get(v8_str("thrown"));
4758 CHECK(thrown->BooleanValue());
4759}
4760
4761
ager@chromium.org8bb60582008-12-11 12:02:20 +00004762THREADED_TEST(APIThrowTryCatch) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004763 v8::Isolate* isolate = CcTest::isolate();
4764 v8::HandleScope scope(isolate);
4765 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org8bb60582008-12-11 12:02:20 +00004766 templ->Set(v8_str("ThrowFromC"),
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004767 v8::FunctionTemplate::New(isolate, ThrowFromC));
ager@chromium.org8bb60582008-12-11 12:02:20 +00004768 LocalContext context(0, templ);
4769 v8::TryCatch try_catch;
4770 CompileRun("ThrowFromC();");
4771 CHECK(try_catch.HasCaught());
4772}
4773
4774
4775// Test that a try-finally block doesn't shadow a try-catch block
4776// when setting up an external handler.
ager@chromium.org71daaf62009-04-01 07:22:49 +00004777//
4778// BUG(271): Some of the exception propagation does not work on the
4779// ARM simulator because the simulator separates the C++ stack and the
4780// JS stack. This test therefore fails on the simulator. The test is
4781// not threaded to allow the threading tests to run on the simulator.
4782TEST(TryCatchInTryFinally) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004783 v8::Isolate* isolate = CcTest::isolate();
4784 v8::HandleScope scope(isolate);
4785 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org8bb60582008-12-11 12:02:20 +00004786 templ->Set(v8_str("CCatcher"),
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004787 v8::FunctionTemplate::New(isolate, CCatcher));
ager@chromium.org8bb60582008-12-11 12:02:20 +00004788 LocalContext context(0, templ);
4789 Local<Value> result = CompileRun("try {"
4790 " try {"
4791 " CCatcher('throw 7;');"
4792 " } finally {"
4793 " }"
4794 "} catch (e) {"
4795 "}");
4796 CHECK(result->IsTrue());
4797}
4798
4799
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00004800static void check_reference_error_message(
4801 v8::Handle<v8::Message> message,
4802 v8::Handle<v8::Value> data) {
4803 const char* reference_error = "Uncaught ReferenceError: asdf is not defined";
4804 CHECK(message->Get()->Equals(v8_str(reference_error)));
4805}
4806
4807
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00004808static void Fail(const v8::FunctionCallbackInfo<v8::Value>& args) {
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00004809 ApiTestFuzzer::Fuzz();
4810 CHECK(false);
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00004811}
4812
4813
4814// Test that overwritten methods are not invoked on uncaught exception
4815// formatting. However, they are invoked when performing normal error
4816// string conversions.
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00004817TEST(APIThrowMessageOverwrittenToString) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00004818 v8::Isolate* isolate = CcTest::isolate();
4819 v8::HandleScope scope(isolate);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00004820 v8::V8::AddMessageListener(check_reference_error_message);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004821 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00004822 templ->Set(v8_str("fail"), v8::FunctionTemplate::New(isolate, Fail));
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00004823 LocalContext context(NULL, templ);
4824 CompileRun("asdf;");
4825 CompileRun("var limit = {};"
4826 "limit.valueOf = fail;"
4827 "Error.stackTraceLimit = limit;");
4828 CompileRun("asdf");
4829 CompileRun("Array.prototype.pop = fail;");
4830 CompileRun("Object.prototype.hasOwnProperty = fail;");
4831 CompileRun("Object.prototype.toString = function f() { return 'Yikes'; }");
whesse@chromium.org7a392b32011-01-31 11:30:36 +00004832 CompileRun("Number.prototype.toString = function f() { return 'Yikes'; }");
4833 CompileRun("String.prototype.toString = function f() { return 'Yikes'; }");
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00004834 CompileRun("ReferenceError.prototype.toString ="
4835 " function() { return 'Whoops' }");
4836 CompileRun("asdf;");
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00004837 CompileRun("ReferenceError.prototype.constructor.name = void 0;");
4838 CompileRun("asdf;");
4839 CompileRun("ReferenceError.prototype.constructor = void 0;");
4840 CompileRun("asdf;");
ager@chromium.org0ee099b2011-01-25 14:06:47 +00004841 CompileRun("ReferenceError.prototype.__proto__ = new Object();");
4842 CompileRun("asdf;");
4843 CompileRun("ReferenceError.prototype = new Object();");
4844 CompileRun("asdf;");
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00004845 v8::Handle<Value> string = CompileRun("try { asdf; } catch(e) { e + ''; }");
4846 CHECK(string->Equals(v8_str("Whoops")));
ager@chromium.org378b34e2011-01-28 08:04:38 +00004847 CompileRun("ReferenceError.prototype.constructor = new Object();"
4848 "ReferenceError.prototype.constructor.name = 1;"
4849 "Number.prototype.toString = function() { return 'Whoops'; };"
4850 "ReferenceError.prototype.toString = Object.prototype.toString;");
4851 CompileRun("asdf;");
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00004852 v8::V8::RemoveMessageListeners(check_reference_error_message);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00004853}
4854
4855
danno@chromium.org59400602013-08-13 17:09:37 +00004856static void check_custom_error_tostring(
yangguo@chromium.org304cc332012-07-24 07:59:48 +00004857 v8::Handle<v8::Message> message,
4858 v8::Handle<v8::Value> data) {
4859 const char* uncaught_error = "Uncaught MyError toString";
4860 CHECK(message->Get()->Equals(v8_str(uncaught_error)));
4861}
4862
4863
4864TEST(CustomErrorToString) {
yangguo@chromium.org304cc332012-07-24 07:59:48 +00004865 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004866 v8::HandleScope scope(context->GetIsolate());
danno@chromium.org59400602013-08-13 17:09:37 +00004867 v8::V8::AddMessageListener(check_custom_error_tostring);
yangguo@chromium.org304cc332012-07-24 07:59:48 +00004868 CompileRun(
4869 "function MyError(name, message) { "
4870 " this.name = name; "
4871 " this.message = message; "
4872 "} "
4873 "MyError.prototype = Object.create(Error.prototype); "
4874 "MyError.prototype.toString = function() { "
4875 " return 'MyError toString'; "
4876 "}; "
4877 "throw new MyError('my name', 'my message'); ");
danno@chromium.org59400602013-08-13 17:09:37 +00004878 v8::V8::RemoveMessageListeners(check_custom_error_tostring);
4879}
4880
4881
4882static void check_custom_error_message(
4883 v8::Handle<v8::Message> message,
4884 v8::Handle<v8::Value> data) {
4885 const char* uncaught_error = "Uncaught MyError: my message";
4886 printf("%s\n", *v8::String::Utf8Value(message->Get()));
4887 CHECK(message->Get()->Equals(v8_str(uncaught_error)));
4888}
4889
4890
4891TEST(CustomErrorMessage) {
4892 LocalContext context;
4893 v8::HandleScope scope(context->GetIsolate());
4894 v8::V8::AddMessageListener(check_custom_error_message);
4895
4896 // Handlebars.
4897 CompileRun(
4898 "function MyError(msg) { "
4899 " this.name = 'MyError'; "
4900 " this.message = msg; "
4901 "} "
4902 "MyError.prototype = new Error(); "
4903 "throw new MyError('my message'); ");
4904
4905 // Closure.
4906 CompileRun(
4907 "function MyError(msg) { "
4908 " this.name = 'MyError'; "
4909 " this.message = msg; "
4910 "} "
4911 "inherits = function(childCtor, parentCtor) { "
4912 " function tempCtor() {}; "
4913 " tempCtor.prototype = parentCtor.prototype; "
4914 " childCtor.superClass_ = parentCtor.prototype; "
4915 " childCtor.prototype = new tempCtor(); "
4916 " childCtor.prototype.constructor = childCtor; "
4917 "}; "
4918 "inherits(MyError, Error); "
4919 "throw new MyError('my message'); ");
4920
4921 // Object.create.
4922 CompileRun(
4923 "function MyError(msg) { "
4924 " this.name = 'MyError'; "
4925 " this.message = msg; "
4926 "} "
4927 "MyError.prototype = Object.create(Error.prototype); "
4928 "throw new MyError('my message'); ");
4929
yangguo@chromium.org304cc332012-07-24 07:59:48 +00004930 v8::V8::RemoveMessageListeners(check_custom_error_message);
4931}
4932
4933
ager@chromium.org8bb60582008-12-11 12:02:20 +00004934static void receive_message(v8::Handle<v8::Message> message,
4935 v8::Handle<v8::Value> data) {
ager@chromium.org71daaf62009-04-01 07:22:49 +00004936 message->Get();
ager@chromium.org8bb60582008-12-11 12:02:20 +00004937 message_received = true;
4938}
4939
4940
4941TEST(APIThrowMessage) {
4942 message_received = false;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004943 v8::Isolate* isolate = CcTest::isolate();
4944 v8::HandleScope scope(isolate);
ager@chromium.org8bb60582008-12-11 12:02:20 +00004945 v8::V8::AddMessageListener(receive_message);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004946 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org8bb60582008-12-11 12:02:20 +00004947 templ->Set(v8_str("ThrowFromC"),
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004948 v8::FunctionTemplate::New(isolate, ThrowFromC));
ager@chromium.org8bb60582008-12-11 12:02:20 +00004949 LocalContext context(0, templ);
4950 CompileRun("ThrowFromC();");
4951 CHECK(message_received);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00004952 v8::V8::RemoveMessageListeners(receive_message);
ager@chromium.org8bb60582008-12-11 12:02:20 +00004953}
4954
4955
4956TEST(APIThrowMessageAndVerboseTryCatch) {
4957 message_received = false;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004958 v8::Isolate* isolate = CcTest::isolate();
4959 v8::HandleScope scope(isolate);
ager@chromium.org8bb60582008-12-11 12:02:20 +00004960 v8::V8::AddMessageListener(receive_message);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004961 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org8bb60582008-12-11 12:02:20 +00004962 templ->Set(v8_str("ThrowFromC"),
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004963 v8::FunctionTemplate::New(isolate, ThrowFromC));
ager@chromium.org8bb60582008-12-11 12:02:20 +00004964 LocalContext context(0, templ);
4965 v8::TryCatch try_catch;
4966 try_catch.SetVerbose(true);
ager@chromium.org71daaf62009-04-01 07:22:49 +00004967 Local<Value> result = CompileRun("ThrowFromC();");
ager@chromium.org8bb60582008-12-11 12:02:20 +00004968 CHECK(try_catch.HasCaught());
ager@chromium.org71daaf62009-04-01 07:22:49 +00004969 CHECK(result.IsEmpty());
ager@chromium.org8bb60582008-12-11 12:02:20 +00004970 CHECK(message_received);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00004971 v8::V8::RemoveMessageListeners(receive_message);
ager@chromium.org8bb60582008-12-11 12:02:20 +00004972}
4973
4974
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00004975TEST(APIStackOverflowAndVerboseTryCatch) {
4976 message_received = false;
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00004977 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004978 v8::HandleScope scope(context->GetIsolate());
4979 v8::V8::AddMessageListener(receive_message);
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00004980 v8::TryCatch try_catch;
4981 try_catch.SetVerbose(true);
4982 Local<Value> result = CompileRun("function foo() { foo(); } foo();");
4983 CHECK(try_catch.HasCaught());
4984 CHECK(result.IsEmpty());
4985 CHECK(message_received);
4986 v8::V8::RemoveMessageListeners(receive_message);
4987}
4988
4989
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004990THREADED_TEST(ExternalScriptException) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004991 v8::Isolate* isolate = CcTest::isolate();
4992 v8::HandleScope scope(isolate);
4993 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004994 templ->Set(v8_str("ThrowFromC"),
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004995 v8::FunctionTemplate::New(isolate, ThrowFromC));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004996 LocalContext context(0, templ);
4997
4998 v8::TryCatch try_catch;
4999 Local<Script> script
5000 = Script::Compile(v8_str("ThrowFromC(); throw 'panama';"));
5001 Local<Value> result = script->Run();
5002 CHECK(result.IsEmpty());
5003 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00005004 String::Utf8Value exception_value(try_catch.Exception());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005005 CHECK_EQ("konto", *exception_value);
5006}
5007
5008
5009
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005010void CThrowCountDown(const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005011 ApiTestFuzzer::Fuzz();
5012 CHECK_EQ(4, args.Length());
5013 int count = args[0]->Int32Value();
5014 int cInterval = args[2]->Int32Value();
5015 if (count == 0) {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00005016 args.GetIsolate()->ThrowException(v8_str("FromC"));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005017 return;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005018 } else {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00005019 Local<v8::Object> global =
5020 args.GetIsolate()->GetCurrentContext()->Global();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005021 Local<Value> fun = global->Get(v8_str("JSThrowCountDown"));
5022 v8::Handle<Value> argv[] = { v8_num(count - 1),
5023 args[1],
5024 args[2],
5025 args[3] };
5026 if (count % cInterval == 0) {
5027 v8::TryCatch try_catch;
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00005028 Local<Value> result = fun.As<Function>()->Call(global, 4, argv);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005029 int expected = args[3]->Int32Value();
5030 if (try_catch.HasCaught()) {
5031 CHECK_EQ(expected, count);
ager@chromium.org71daaf62009-04-01 07:22:49 +00005032 CHECK(result.IsEmpty());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00005033 CHECK(!CcTest::i_isolate()->has_scheduled_exception());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005034 } else {
5035 CHECK_NE(expected, count);
5036 }
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005037 args.GetReturnValue().Set(result);
5038 return;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005039 } else {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005040 args.GetReturnValue().Set(fun.As<Function>()->Call(global, 4, argv));
5041 return;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005042 }
5043 }
5044}
5045
5046
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005047void JSCheck(const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005048 ApiTestFuzzer::Fuzz();
5049 CHECK_EQ(3, args.Length());
5050 bool equality = args[0]->BooleanValue();
5051 int count = args[1]->Int32Value();
5052 int expected = args[2]->Int32Value();
5053 if (equality) {
5054 CHECK_EQ(count, expected);
5055 } else {
5056 CHECK_NE(count, expected);
5057 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005058}
5059
5060
ager@chromium.org8bb60582008-12-11 12:02:20 +00005061THREADED_TEST(EvalInTryFinally) {
ager@chromium.org8bb60582008-12-11 12:02:20 +00005062 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005063 v8::HandleScope scope(context->GetIsolate());
ager@chromium.org8bb60582008-12-11 12:02:20 +00005064 v8::TryCatch try_catch;
5065 CompileRun("(function() {"
5066 " try {"
5067 " eval('asldkf (*&^&*^');"
5068 " } finally {"
5069 " return;"
5070 " }"
5071 "})()");
5072 CHECK(!try_catch.HasCaught());
5073}
5074
5075
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005076// This test works by making a stack of alternating JavaScript and C
5077// activations. These activations set up exception handlers with regular
5078// intervals, one interval for C activations and another for JavaScript
5079// activations. When enough activations have been created an exception is
5080// thrown and we check that the right activation catches the exception and that
5081// no other activations do. The right activation is always the topmost one with
5082// a handler, regardless of whether it is in JavaScript or C.
5083//
5084// The notation used to describe a test case looks like this:
5085//
5086// *JS[4] *C[3] @JS[2] C[1] JS[0]
5087//
5088// Each entry is an activation, either JS or C. The index is the count at that
5089// level. Stars identify activations with exception handlers, the @ identifies
5090// the exception handler that should catch the exception.
ager@chromium.org71daaf62009-04-01 07:22:49 +00005091//
5092// BUG(271): Some of the exception propagation does not work on the
5093// ARM simulator because the simulator separates the C++ stack and the
5094// JS stack. This test therefore fails on the simulator. The test is
5095// not threaded to allow the threading tests to run on the simulator.
5096TEST(ExceptionOrder) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00005097 v8::Isolate* isolate = CcTest::isolate();
5098 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005099 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00005100 templ->Set(v8_str("check"), v8::FunctionTemplate::New(isolate, JSCheck));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005101 templ->Set(v8_str("CThrowCountDown"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00005102 v8::FunctionTemplate::New(isolate, CThrowCountDown));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005103 LocalContext context(0, templ);
5104 CompileRun(
5105 "function JSThrowCountDown(count, jsInterval, cInterval, expected) {"
5106 " if (count == 0) throw 'FromJS';"
5107 " if (count % jsInterval == 0) {"
5108 " try {"
5109 " var value = CThrowCountDown(count - 1,"
5110 " jsInterval,"
5111 " cInterval,"
5112 " expected);"
5113 " check(false, count, expected);"
5114 " return value;"
5115 " } catch (e) {"
5116 " check(true, count, expected);"
5117 " }"
5118 " } else {"
5119 " return CThrowCountDown(count - 1, jsInterval, cInterval, expected);"
5120 " }"
5121 "}");
5122 Local<Function> fun =
5123 Local<Function>::Cast(context->Global()->Get(v8_str("JSThrowCountDown")));
5124
5125 const int argc = 4;
5126 // count jsInterval cInterval expected
5127
5128 // *JS[4] *C[3] @JS[2] C[1] JS[0]
5129 v8::Handle<Value> a0[argc] = { v8_num(4), v8_num(2), v8_num(3), v8_num(2) };
5130 fun->Call(fun, argc, a0);
5131
5132 // JS[5] *C[4] JS[3] @C[2] JS[1] C[0]
5133 v8::Handle<Value> a1[argc] = { v8_num(5), v8_num(6), v8_num(1), v8_num(2) };
5134 fun->Call(fun, argc, a1);
5135
5136 // JS[6] @C[5] JS[4] C[3] JS[2] C[1] JS[0]
5137 v8::Handle<Value> a2[argc] = { v8_num(6), v8_num(7), v8_num(5), v8_num(5) };
5138 fun->Call(fun, argc, a2);
5139
5140 // @JS[6] C[5] JS[4] C[3] JS[2] C[1] JS[0]
5141 v8::Handle<Value> a3[argc] = { v8_num(6), v8_num(6), v8_num(7), v8_num(6) };
5142 fun->Call(fun, argc, a3);
5143
5144 // JS[6] *C[5] @JS[4] C[3] JS[2] C[1] JS[0]
5145 v8::Handle<Value> a4[argc] = { v8_num(6), v8_num(4), v8_num(5), v8_num(4) };
5146 fun->Call(fun, argc, a4);
5147
5148 // JS[6] C[5] *JS[4] @C[3] JS[2] C[1] JS[0]
5149 v8::Handle<Value> a5[argc] = { v8_num(6), v8_num(4), v8_num(3), v8_num(3) };
5150 fun->Call(fun, argc, a5);
5151}
5152
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00005153
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005154void ThrowValue(const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005155 ApiTestFuzzer::Fuzz();
5156 CHECK_EQ(1, args.Length());
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00005157 args.GetIsolate()->ThrowException(args[0]);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005158}
5159
5160
5161THREADED_TEST(ThrowValues) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00005162 v8::Isolate* isolate = CcTest::isolate();
5163 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005164 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00005165 templ->Set(v8_str("Throw"), v8::FunctionTemplate::New(isolate, ThrowValue));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005166 LocalContext context(0, templ);
5167 v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
5168 "function Run(obj) {"
5169 " try {"
5170 " Throw(obj);"
5171 " } catch (e) {"
5172 " return e;"
5173 " }"
5174 " return 'no exception';"
5175 "}"
5176 "[Run('str'), Run(1), Run(0), Run(null), Run(void 0)];"));
5177 CHECK_EQ(5, result->Length());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00005178 CHECK(result->Get(v8::Integer::New(isolate, 0))->IsString());
5179 CHECK(result->Get(v8::Integer::New(isolate, 1))->IsNumber());
5180 CHECK_EQ(1, result->Get(v8::Integer::New(isolate, 1))->Int32Value());
5181 CHECK(result->Get(v8::Integer::New(isolate, 2))->IsNumber());
5182 CHECK_EQ(0, result->Get(v8::Integer::New(isolate, 2))->Int32Value());
5183 CHECK(result->Get(v8::Integer::New(isolate, 3))->IsNull());
5184 CHECK(result->Get(v8::Integer::New(isolate, 4))->IsUndefined());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005185}
5186
5187
5188THREADED_TEST(CatchZero) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005189 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005190 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005191 v8::TryCatch try_catch;
5192 CHECK(!try_catch.HasCaught());
5193 Script::Compile(v8_str("throw 10"))->Run();
5194 CHECK(try_catch.HasCaught());
5195 CHECK_EQ(10, try_catch.Exception()->Int32Value());
5196 try_catch.Reset();
5197 CHECK(!try_catch.HasCaught());
5198 Script::Compile(v8_str("throw 0"))->Run();
5199 CHECK(try_catch.HasCaught());
5200 CHECK_EQ(0, try_catch.Exception()->Int32Value());
5201}
5202
5203
5204THREADED_TEST(CatchExceptionFromWith) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005205 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005206 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005207 v8::TryCatch try_catch;
5208 CHECK(!try_catch.HasCaught());
5209 Script::Compile(v8_str("var o = {}; with (o) { throw 42; }"))->Run();
5210 CHECK(try_catch.HasCaught());
5211}
5212
5213
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00005214THREADED_TEST(TryCatchAndFinallyHidingException) {
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00005215 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005216 v8::HandleScope scope(context->GetIsolate());
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00005217 v8::TryCatch try_catch;
5218 CHECK(!try_catch.HasCaught());
5219 CompileRun("function f(k) { try { this[k]; } finally { return 0; } };");
5220 CompileRun("f({toString: function() { throw 42; }});");
5221 CHECK(!try_catch.HasCaught());
5222}
5223
5224
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005225void WithTryCatch(const v8::FunctionCallbackInfo<v8::Value>& args) {
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00005226 v8::TryCatch try_catch;
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00005227}
5228
5229
5230THREADED_TEST(TryCatchAndFinally) {
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00005231 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00005232 v8::Isolate* isolate = context->GetIsolate();
5233 v8::HandleScope scope(isolate);
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00005234 context->Global()->Set(
5235 v8_str("native_with_try_catch"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00005236 v8::FunctionTemplate::New(isolate, WithTryCatch)->GetFunction());
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00005237 v8::TryCatch try_catch;
5238 CHECK(!try_catch.HasCaught());
5239 CompileRun(
5240 "try {\n"
5241 " throw new Error('a');\n"
5242 "} finally {\n"
5243 " native_with_try_catch();\n"
5244 "}\n");
5245 CHECK(try_catch.HasCaught());
5246}
5247
5248
mmassi@chromium.org49a44672012-12-04 13:52:03 +00005249static void TryCatchNestedHelper(int depth) {
5250 if (depth > 0) {
5251 v8::TryCatch try_catch;
5252 try_catch.SetVerbose(true);
5253 TryCatchNestedHelper(depth - 1);
5254 CHECK(try_catch.HasCaught());
5255 try_catch.ReThrow();
5256 } else {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00005257 CcTest::isolate()->ThrowException(v8_str("back"));
mmassi@chromium.org49a44672012-12-04 13:52:03 +00005258 }
5259}
5260
5261
5262TEST(TryCatchNested) {
5263 v8::V8::Initialize();
mmassi@chromium.org49a44672012-12-04 13:52:03 +00005264 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005265 v8::HandleScope scope(context->GetIsolate());
mmassi@chromium.org49a44672012-12-04 13:52:03 +00005266 v8::TryCatch try_catch;
5267 TryCatchNestedHelper(5);
5268 CHECK(try_catch.HasCaught());
5269 CHECK_EQ(0, strcmp(*v8::String::Utf8Value(try_catch.Exception()), "back"));
5270}
5271
5272
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +00005273void TryCatchMixedNestingCheck(v8::TryCatch* try_catch) {
5274 CHECK(try_catch->HasCaught());
5275 Handle<Message> message = try_catch->Message();
5276 Handle<Value> resource = message->GetScriptResourceName();
5277 CHECK_EQ(0, strcmp(*v8::String::Utf8Value(resource), "inner"));
5278 CHECK_EQ(0, strcmp(*v8::String::Utf8Value(message->Get()),
5279 "Uncaught Error: a"));
5280 CHECK_EQ(1, message->GetLineNumber());
5281 CHECK_EQ(6, message->GetStartColumn());
5282}
5283
5284
5285void TryCatchMixedNestingHelper(
5286 const v8::FunctionCallbackInfo<v8::Value>& args) {
5287 ApiTestFuzzer::Fuzz();
5288 v8::TryCatch try_catch;
5289 CompileRunWithOrigin("throw new Error('a');\n", "inner", 0, 0);
5290 CHECK(try_catch.HasCaught());
5291 TryCatchMixedNestingCheck(&try_catch);
5292 try_catch.ReThrow();
5293}
5294
5295
5296// This test ensures that an outer TryCatch in the following situation:
5297// C++/TryCatch -> JS -> C++/TryCatch -> JS w/ SyntaxError
5298// does not clobber the Message object generated for the inner TryCatch.
5299// This exercises the ability of TryCatch.ReThrow() to restore the
5300// inner pending Message before throwing the exception again.
5301TEST(TryCatchMixedNesting) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00005302 v8::Isolate* isolate = CcTest::isolate();
5303 v8::HandleScope scope(isolate);
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +00005304 v8::V8::Initialize();
5305 v8::TryCatch try_catch;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005306 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +00005307 templ->Set(v8_str("TryCatchMixedNestingHelper"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00005308 v8::FunctionTemplate::New(isolate, TryCatchMixedNestingHelper));
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +00005309 LocalContext context(0, templ);
5310 CompileRunWithOrigin("TryCatchMixedNestingHelper();\n", "outer", 1, 1);
5311 TryCatchMixedNestingCheck(&try_catch);
5312}
5313
5314
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005315THREADED_TEST(Equality) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005316 LocalContext context;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00005317 v8::Isolate* isolate = context->GetIsolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005318 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005319 // Check that equality works at all before relying on CHECK_EQ
5320 CHECK(v8_str("a")->Equals(v8_str("a")));
5321 CHECK(!v8_str("a")->Equals(v8_str("b")));
5322
5323 CHECK_EQ(v8_str("a"), v8_str("a"));
5324 CHECK_NE(v8_str("a"), v8_str("b"));
5325 CHECK_EQ(v8_num(1), v8_num(1));
5326 CHECK_EQ(v8_num(1.00), v8_num(1));
5327 CHECK_NE(v8_num(1), v8_num(2));
5328
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00005329 // Assume String is not internalized.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005330 CHECK(v8_str("a")->StrictEquals(v8_str("a")));
5331 CHECK(!v8_str("a")->StrictEquals(v8_str("b")));
5332 CHECK(!v8_str("5")->StrictEquals(v8_num(5)));
5333 CHECK(v8_num(1)->StrictEquals(v8_num(1)));
5334 CHECK(!v8_num(1)->StrictEquals(v8_num(2)));
machenbach@chromium.org3d079fe2013-09-25 08:19:55 +00005335 CHECK(v8_num(0.0)->StrictEquals(v8_num(-0.0)));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005336 Local<Value> not_a_number = v8_num(i::OS::nan_value());
5337 CHECK(!not_a_number->StrictEquals(not_a_number));
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00005338 CHECK(v8::False(isolate)->StrictEquals(v8::False(isolate)));
5339 CHECK(!v8::False(isolate)->StrictEquals(v8::Undefined(isolate)));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005340
ulan@chromium.org0f13e742014-01-03 15:51:11 +00005341 v8::Handle<v8::Object> obj = v8::Object::New(isolate);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00005342 v8::Persistent<v8::Object> alias(isolate, obj);
rossberg@chromium.org79e79022013-06-03 15:43:46 +00005343 CHECK(v8::Local<v8::Object>::New(isolate, alias)->StrictEquals(obj));
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00005344 alias.Reset();
machenbach@chromium.org3d079fe2013-09-25 08:19:55 +00005345
5346 CHECK(v8_str("a")->SameValue(v8_str("a")));
5347 CHECK(!v8_str("a")->SameValue(v8_str("b")));
5348 CHECK(!v8_str("5")->SameValue(v8_num(5)));
5349 CHECK(v8_num(1)->SameValue(v8_num(1)));
5350 CHECK(!v8_num(1)->SameValue(v8_num(2)));
5351 CHECK(!v8_num(0.0)->SameValue(v8_num(-0.0)));
5352 CHECK(not_a_number->SameValue(not_a_number));
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00005353 CHECK(v8::False(isolate)->SameValue(v8::False(isolate)));
5354 CHECK(!v8::False(isolate)->SameValue(v8::Undefined(isolate)));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005355}
5356
5357
5358THREADED_TEST(MultiRun) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005359 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005360 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005361 Local<Script> script = Script::Compile(v8_str("x"));
5362 for (int i = 0; i < 10; i++)
5363 script->Run();
5364}
5365
5366
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005367static void GetXValue(Local<String> name,
5368 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005369 ApiTestFuzzer::Fuzz();
5370 CHECK_EQ(info.Data(), v8_str("donut"));
5371 CHECK_EQ(name, v8_str("x"));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005372 info.GetReturnValue().Set(name);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005373}
5374
5375
5376THREADED_TEST(SimplePropertyRead) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005377 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005378 v8::Isolate* isolate = context->GetIsolate();
5379 v8::HandleScope scope(isolate);
5380 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005381 templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005382 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5383 Local<Script> script = Script::Compile(v8_str("obj.x"));
5384 for (int i = 0; i < 10; i++) {
5385 Local<Value> result = script->Run();
5386 CHECK_EQ(result, v8_str("x"));
5387 }
5388}
5389
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00005390
ager@chromium.org5c838252010-02-19 08:53:10 +00005391THREADED_TEST(DefinePropertyOnAPIAccessor) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005392 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005393 v8::Isolate* isolate = context->GetIsolate();
5394 v8::HandleScope scope(isolate);
5395 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +00005396 templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
ager@chromium.org5c838252010-02-19 08:53:10 +00005397 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5398
5399 // Uses getOwnPropertyDescriptor to check the configurable status
5400 Local<Script> script_desc
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00005401 = Script::Compile(v8_str("var prop = Object.getOwnPropertyDescriptor( "
ager@chromium.org5c838252010-02-19 08:53:10 +00005402 "obj, 'x');"
5403 "prop.configurable;"));
5404 Local<Value> result = script_desc->Run();
5405 CHECK_EQ(result->BooleanValue(), true);
5406
5407 // Redefine get - but still configurable
5408 Local<Script> script_define
5409 = Script::Compile(v8_str("var desc = { get: function(){return 42; },"
5410 " configurable: true };"
5411 "Object.defineProperty(obj, 'x', desc);"
5412 "obj.x"));
5413 result = script_define->Run();
5414 CHECK_EQ(result, v8_num(42));
5415
5416 // Check that the accessor is still configurable
5417 result = script_desc->Run();
5418 CHECK_EQ(result->BooleanValue(), true);
5419
5420 // Redefine to a non-configurable
5421 script_define
5422 = Script::Compile(v8_str("var desc = { get: function(){return 43; },"
5423 " configurable: false };"
5424 "Object.defineProperty(obj, 'x', desc);"
5425 "obj.x"));
5426 result = script_define->Run();
5427 CHECK_EQ(result, v8_num(43));
5428 result = script_desc->Run();
5429 CHECK_EQ(result->BooleanValue(), false);
5430
5431 // Make sure that it is not possible to redefine again
5432 v8::TryCatch try_catch;
5433 result = script_define->Run();
5434 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00005435 String::Utf8Value exception_value(try_catch.Exception());
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00005436 CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
ager@chromium.org5c838252010-02-19 08:53:10 +00005437}
5438
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00005439
ager@chromium.org5c838252010-02-19 08:53:10 +00005440THREADED_TEST(DefinePropertyOnDefineGetterSetter) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005441 v8::Isolate* isolate = CcTest::isolate();
5442 v8::HandleScope scope(isolate);
5443 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +00005444 templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
5445 LocalContext context;
5446 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5447
5448 Local<Script> script_desc = Script::Compile(v8_str("var prop ="
5449 "Object.getOwnPropertyDescriptor( "
5450 "obj, 'x');"
5451 "prop.configurable;"));
5452 Local<Value> result = script_desc->Run();
5453 CHECK_EQ(result->BooleanValue(), true);
5454
5455 Local<Script> script_define =
5456 Script::Compile(v8_str("var desc = {get: function(){return 42; },"
5457 " configurable: true };"
5458 "Object.defineProperty(obj, 'x', desc);"
5459 "obj.x"));
5460 result = script_define->Run();
5461 CHECK_EQ(result, v8_num(42));
5462
5463
5464 result = script_desc->Run();
5465 CHECK_EQ(result->BooleanValue(), true);
5466
5467
5468 script_define =
5469 Script::Compile(v8_str("var desc = {get: function(){return 43; },"
5470 " configurable: false };"
5471 "Object.defineProperty(obj, 'x', desc);"
5472 "obj.x"));
5473 result = script_define->Run();
5474 CHECK_EQ(result, v8_num(43));
5475 result = script_desc->Run();
5476
5477 CHECK_EQ(result->BooleanValue(), false);
5478
5479 v8::TryCatch try_catch;
5480 result = script_define->Run();
5481 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00005482 String::Utf8Value exception_value(try_catch.Exception());
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00005483 CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
ager@chromium.org5c838252010-02-19 08:53:10 +00005484}
5485
5486
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00005487static v8::Handle<v8::Object> GetGlobalProperty(LocalContext* context,
5488 char const* name) {
5489 return v8::Handle<v8::Object>::Cast((*context)->Global()->Get(v8_str(name)));
5490}
ager@chromium.org5c838252010-02-19 08:53:10 +00005491
5492
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00005493THREADED_TEST(DefineAPIAccessorOnObject) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005494 v8::Isolate* isolate = CcTest::isolate();
5495 v8::HandleScope scope(isolate);
5496 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00005497 LocalContext context;
5498
5499 context->Global()->Set(v8_str("obj1"), templ->NewInstance());
5500 CompileRun("var obj2 = {};");
5501
5502 CHECK(CompileRun("obj1.x")->IsUndefined());
5503 CHECK(CompileRun("obj2.x")->IsUndefined());
5504
5505 CHECK(GetGlobalProperty(&context, "obj1")->
5506 SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5507
5508 ExpectString("obj1.x", "x");
5509 CHECK(CompileRun("obj2.x")->IsUndefined());
5510
5511 CHECK(GetGlobalProperty(&context, "obj2")->
5512 SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5513
5514 ExpectString("obj1.x", "x");
5515 ExpectString("obj2.x", "x");
5516
5517 ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5518 ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5519
5520 CompileRun("Object.defineProperty(obj1, 'x',"
5521 "{ get: function() { return 'y'; }, configurable: true })");
5522
5523 ExpectString("obj1.x", "y");
5524 ExpectString("obj2.x", "x");
5525
5526 CompileRun("Object.defineProperty(obj2, 'x',"
5527 "{ get: function() { return 'y'; }, configurable: true })");
5528
5529 ExpectString("obj1.x", "y");
5530 ExpectString("obj2.x", "y");
5531
5532 ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5533 ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5534
5535 CHECK(GetGlobalProperty(&context, "obj1")->
5536 SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5537 CHECK(GetGlobalProperty(&context, "obj2")->
5538 SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5539
5540 ExpectString("obj1.x", "x");
5541 ExpectString("obj2.x", "x");
5542
5543 ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5544 ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5545
5546 // Define getters/setters, but now make them not configurable.
5547 CompileRun("Object.defineProperty(obj1, 'x',"
5548 "{ get: function() { return 'z'; }, configurable: false })");
5549 CompileRun("Object.defineProperty(obj2, 'x',"
5550 "{ get: function() { return 'z'; }, configurable: false })");
5551
5552 ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5553 ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5554
5555 ExpectString("obj1.x", "z");
5556 ExpectString("obj2.x", "z");
5557
5558 CHECK(!GetGlobalProperty(&context, "obj1")->
5559 SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5560 CHECK(!GetGlobalProperty(&context, "obj2")->
5561 SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5562
5563 ExpectString("obj1.x", "z");
5564 ExpectString("obj2.x", "z");
5565}
5566
5567
5568THREADED_TEST(DontDeleteAPIAccessorsCannotBeOverriden) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005569 v8::Isolate* isolate = CcTest::isolate();
5570 v8::HandleScope scope(isolate);
5571 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00005572 LocalContext context;
5573
5574 context->Global()->Set(v8_str("obj1"), templ->NewInstance());
5575 CompileRun("var obj2 = {};");
5576
5577 CHECK(GetGlobalProperty(&context, "obj1")->SetAccessor(
5578 v8_str("x"),
5579 GetXValue, NULL,
5580 v8_str("donut"), v8::DEFAULT, v8::DontDelete));
5581 CHECK(GetGlobalProperty(&context, "obj2")->SetAccessor(
5582 v8_str("x"),
5583 GetXValue, NULL,
5584 v8_str("donut"), v8::DEFAULT, v8::DontDelete));
5585
5586 ExpectString("obj1.x", "x");
5587 ExpectString("obj2.x", "x");
5588
5589 ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5590 ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5591
5592 CHECK(!GetGlobalProperty(&context, "obj1")->
5593 SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5594 CHECK(!GetGlobalProperty(&context, "obj2")->
5595 SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5596
5597 {
5598 v8::TryCatch try_catch;
5599 CompileRun("Object.defineProperty(obj1, 'x',"
5600 "{get: function() { return 'func'; }})");
5601 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00005602 String::Utf8Value exception_value(try_catch.Exception());
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00005603 CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00005604 }
5605 {
5606 v8::TryCatch try_catch;
5607 CompileRun("Object.defineProperty(obj2, 'x',"
5608 "{get: function() { return 'func'; }})");
5609 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00005610 String::Utf8Value exception_value(try_catch.Exception());
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00005611 CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00005612 }
5613}
5614
5615
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005616static void Get239Value(Local<String> name,
5617 const v8::PropertyCallbackInfo<v8::Value>& info) {
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00005618 ApiTestFuzzer::Fuzz();
5619 CHECK_EQ(info.Data(), v8_str("donut"));
5620 CHECK_EQ(name, v8_str("239"));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005621 info.GetReturnValue().Set(name);
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00005622}
5623
5624
5625THREADED_TEST(ElementAPIAccessor) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005626 v8::Isolate* isolate = CcTest::isolate();
5627 v8::HandleScope scope(isolate);
5628 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00005629 LocalContext context;
5630
5631 context->Global()->Set(v8_str("obj1"), templ->NewInstance());
5632 CompileRun("var obj2 = {};");
5633
5634 CHECK(GetGlobalProperty(&context, "obj1")->SetAccessor(
5635 v8_str("239"),
5636 Get239Value, NULL,
5637 v8_str("donut")));
5638 CHECK(GetGlobalProperty(&context, "obj2")->SetAccessor(
5639 v8_str("239"),
5640 Get239Value, NULL,
5641 v8_str("donut")));
5642
5643 ExpectString("obj1[239]", "239");
5644 ExpectString("obj2[239]", "239");
5645 ExpectString("obj1['239']", "239");
5646 ExpectString("obj2['239']", "239");
5647}
5648
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005649
5650v8::Persistent<Value> xValue;
5651
5652
5653static void SetXValue(Local<String> name,
5654 Local<Value> value,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005655 const v8::PropertyCallbackInfo<void>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005656 CHECK_EQ(value, v8_num(4));
5657 CHECK_EQ(info.Data(), v8_str("donut"));
5658 CHECK_EQ(name, v8_str("x"));
5659 CHECK(xValue.IsEmpty());
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00005660 xValue.Reset(info.GetIsolate(), value);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005661}
5662
5663
5664THREADED_TEST(SimplePropertyWrite) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005665 v8::Isolate* isolate = CcTest::isolate();
5666 v8::HandleScope scope(isolate);
5667 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005668 templ->SetAccessor(v8_str("x"), GetXValue, SetXValue, v8_str("donut"));
5669 LocalContext context;
5670 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5671 Local<Script> script = Script::Compile(v8_str("obj.x = 4"));
5672 for (int i = 0; i < 10; i++) {
5673 CHECK(xValue.IsEmpty());
5674 script->Run();
machenbach@chromium.org528ce022013-09-23 14:09:36 +00005675 CHECK_EQ(v8_num(4), Local<Value>::New(CcTest::isolate(), xValue));
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00005676 xValue.Reset();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005677 }
5678}
5679
5680
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00005681THREADED_TEST(SetterOnly) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005682 v8::Isolate* isolate = CcTest::isolate();
5683 v8::HandleScope scope(isolate);
5684 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00005685 templ->SetAccessor(v8_str("x"), NULL, SetXValue, v8_str("donut"));
5686 LocalContext context;
5687 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5688 Local<Script> script = Script::Compile(v8_str("obj.x = 4; obj.x"));
5689 for (int i = 0; i < 10; i++) {
5690 CHECK(xValue.IsEmpty());
5691 script->Run();
machenbach@chromium.org528ce022013-09-23 14:09:36 +00005692 CHECK_EQ(v8_num(4), Local<Value>::New(CcTest::isolate(), xValue));
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00005693 xValue.Reset();
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00005694 }
5695}
5696
5697
5698THREADED_TEST(NoAccessors) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005699 v8::Isolate* isolate = CcTest::isolate();
5700 v8::HandleScope scope(isolate);
5701 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00005702 templ->SetAccessor(v8_str("x"),
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005703 static_cast<v8::AccessorGetterCallback>(NULL),
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00005704 NULL,
5705 v8_str("donut"));
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00005706 LocalContext context;
5707 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5708 Local<Script> script = Script::Compile(v8_str("obj.x = 4; obj.x"));
5709 for (int i = 0; i < 10; i++) {
5710 script->Run();
5711 }
5712}
5713
5714
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005715static void XPropertyGetter(Local<String> property,
5716 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005717 ApiTestFuzzer::Fuzz();
5718 CHECK(info.Data()->IsUndefined());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005719 info.GetReturnValue().Set(property);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005720}
5721
5722
ager@chromium.orgeadaf222009-06-16 09:43:10 +00005723THREADED_TEST(NamedInterceptorPropertyRead) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005724 v8::Isolate* isolate = CcTest::isolate();
5725 v8::HandleScope scope(isolate);
5726 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005727 templ->SetNamedPropertyHandler(XPropertyGetter);
5728 LocalContext context;
5729 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5730 Local<Script> script = Script::Compile(v8_str("obj.x"));
5731 for (int i = 0; i < 10; i++) {
5732 Local<Value> result = script->Run();
5733 CHECK_EQ(result, v8_str("x"));
5734 }
5735}
5736
ager@chromium.orgeadaf222009-06-16 09:43:10 +00005737
ager@chromium.orgb26c50a2010-03-26 09:27:16 +00005738THREADED_TEST(NamedInterceptorDictionaryIC) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005739 v8::Isolate* isolate = CcTest::isolate();
5740 v8::HandleScope scope(isolate);
5741 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.orgb26c50a2010-03-26 09:27:16 +00005742 templ->SetNamedPropertyHandler(XPropertyGetter);
5743 LocalContext context;
5744 // Create an object with a named interceptor.
5745 context->Global()->Set(v8_str("interceptor_obj"), templ->NewInstance());
5746 Local<Script> script = Script::Compile(v8_str("interceptor_obj.x"));
5747 for (int i = 0; i < 10; i++) {
5748 Local<Value> result = script->Run();
5749 CHECK_EQ(result, v8_str("x"));
5750 }
5751 // Create a slow case object and a function accessing a property in
5752 // that slow case object (with dictionary probing in generated
5753 // code). Then force object with a named interceptor into slow-case,
5754 // pass it to the function, and check that the interceptor is called
5755 // instead of accessing the local property.
5756 Local<Value> result =
5757 CompileRun("function get_x(o) { return o.x; };"
5758 "var obj = { x : 42, y : 0 };"
5759 "delete obj.y;"
5760 "for (var i = 0; i < 10; i++) get_x(obj);"
5761 "interceptor_obj.x = 42;"
5762 "interceptor_obj.y = 10;"
5763 "delete interceptor_obj.y;"
5764 "get_x(interceptor_obj)");
5765 CHECK_EQ(result, v8_str("x"));
5766}
5767
5768
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00005769THREADED_TEST(NamedInterceptorDictionaryICMultipleContext) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00005770 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00005771 v8::HandleScope scope(isolate);
5772 v8::Local<Context> context1 = Context::New(isolate);
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00005773
5774 context1->Enter();
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005775 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00005776 templ->SetNamedPropertyHandler(XPropertyGetter);
5777 // Create an object with a named interceptor.
5778 v8::Local<v8::Object> object = templ->NewInstance();
5779 context1->Global()->Set(v8_str("interceptor_obj"), object);
5780
5781 // Force the object into the slow case.
5782 CompileRun("interceptor_obj.y = 0;"
5783 "delete interceptor_obj.y;");
5784 context1->Exit();
5785
5786 {
5787 // Introduce the object into a different context.
5788 // Repeat named loads to exercise ICs.
5789 LocalContext context2;
5790 context2->Global()->Set(v8_str("interceptor_obj"), object);
5791 Local<Value> result =
5792 CompileRun("function get_x(o) { return o.x; }"
5793 "interceptor_obj.x = 42;"
5794 "for (var i=0; i != 10; i++) {"
5795 " get_x(interceptor_obj);"
5796 "}"
5797 "get_x(interceptor_obj)");
5798 // Check that the interceptor was actually invoked.
5799 CHECK_EQ(result, v8_str("x"));
5800 }
5801
5802 // Return to the original context and force some object to the slow case
5803 // to cause the NormalizedMapCache to verify.
5804 context1->Enter();
5805 CompileRun("var obj = { x : 0 }; delete obj.x;");
5806 context1->Exit();
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00005807}
5808
5809
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005810static void SetXOnPrototypeGetter(
5811 Local<String> property,
5812 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.org5c838252010-02-19 08:53:10 +00005813 // Set x on the prototype object and do not handle the get request.
5814 v8::Handle<v8::Value> proto = info.Holder()->GetPrototype();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00005815 proto.As<v8::Object>()->Set(v8_str("x"),
5816 v8::Integer::New(info.GetIsolate(), 23));
ager@chromium.org5c838252010-02-19 08:53:10 +00005817}
5818
5819
5820// This is a regression test for http://crbug.com/20104. Map
5821// transitions should not interfere with post interceptor lookup.
5822THREADED_TEST(NamedInterceptorMapTransitionRead) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00005823 v8::Isolate* isolate = CcTest::isolate();
5824 v8::HandleScope scope(isolate);
5825 Local<v8::FunctionTemplate> function_template =
5826 v8::FunctionTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +00005827 Local<v8::ObjectTemplate> instance_template
5828 = function_template->InstanceTemplate();
5829 instance_template->SetNamedPropertyHandler(SetXOnPrototypeGetter);
5830 LocalContext context;
5831 context->Global()->Set(v8_str("F"), function_template->GetFunction());
5832 // Create an instance of F and introduce a map transition for x.
5833 CompileRun("var o = new F(); o.x = 23;");
5834 // Create an instance of F and invoke the getter. The result should be 23.
5835 Local<Value> result = CompileRun("o = new F(); o.x");
5836 CHECK_EQ(result->Int32Value(), 23);
5837}
5838
5839
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005840static void IndexedPropertyGetter(
5841 uint32_t index,
5842 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.orgeadaf222009-06-16 09:43:10 +00005843 ApiTestFuzzer::Fuzz();
5844 if (index == 37) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005845 info.GetReturnValue().Set(v8_num(625));
ager@chromium.orgeadaf222009-06-16 09:43:10 +00005846 }
ager@chromium.orgeadaf222009-06-16 09:43:10 +00005847}
5848
5849
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005850static void IndexedPropertySetter(
5851 uint32_t index,
5852 Local<Value> value,
5853 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.orgeadaf222009-06-16 09:43:10 +00005854 ApiTestFuzzer::Fuzz();
5855 if (index == 39) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005856 info.GetReturnValue().Set(value);
ager@chromium.orgeadaf222009-06-16 09:43:10 +00005857 }
ager@chromium.orgeadaf222009-06-16 09:43:10 +00005858}
5859
5860
5861THREADED_TEST(IndexedInterceptorWithIndexedAccessor) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005862 v8::Isolate* isolate = CcTest::isolate();
5863 v8::HandleScope scope(isolate);
5864 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.orgeadaf222009-06-16 09:43:10 +00005865 templ->SetIndexedPropertyHandler(IndexedPropertyGetter,
5866 IndexedPropertySetter);
5867 LocalContext context;
5868 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5869 Local<Script> getter_script = Script::Compile(v8_str(
5870 "obj.__defineGetter__(\"3\", function(){return 5;});obj[3];"));
5871 Local<Script> setter_script = Script::Compile(v8_str(
5872 "obj.__defineSetter__(\"17\", function(val){this.foo = val;});"
5873 "obj[17] = 23;"
5874 "obj.foo;"));
5875 Local<Script> interceptor_setter_script = Script::Compile(v8_str(
5876 "obj.__defineSetter__(\"39\", function(val){this.foo = \"hit\";});"
5877 "obj[39] = 47;"
5878 "obj.foo;")); // This setter should not run, due to the interceptor.
5879 Local<Script> interceptor_getter_script = Script::Compile(v8_str(
5880 "obj[37];"));
5881 Local<Value> result = getter_script->Run();
5882 CHECK_EQ(v8_num(5), result);
5883 result = setter_script->Run();
5884 CHECK_EQ(v8_num(23), result);
5885 result = interceptor_setter_script->Run();
5886 CHECK_EQ(v8_num(23), result);
5887 result = interceptor_getter_script->Run();
5888 CHECK_EQ(v8_num(625), result);
5889}
5890
5891
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005892static void UnboxedDoubleIndexedPropertyGetter(
ricow@chromium.org9fa09672011-07-25 11:05:35 +00005893 uint32_t index,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005894 const v8::PropertyCallbackInfo<v8::Value>& info) {
ricow@chromium.org9fa09672011-07-25 11:05:35 +00005895 ApiTestFuzzer::Fuzz();
5896 if (index < 25) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005897 info.GetReturnValue().Set(v8_num(index));
ricow@chromium.org9fa09672011-07-25 11:05:35 +00005898 }
ricow@chromium.org9fa09672011-07-25 11:05:35 +00005899}
5900
5901
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005902static void UnboxedDoubleIndexedPropertySetter(
ricow@chromium.org9fa09672011-07-25 11:05:35 +00005903 uint32_t index,
5904 Local<Value> value,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005905 const v8::PropertyCallbackInfo<v8::Value>& info) {
ricow@chromium.org9fa09672011-07-25 11:05:35 +00005906 ApiTestFuzzer::Fuzz();
5907 if (index < 25) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005908 info.GetReturnValue().Set(v8_num(index));
ricow@chromium.org9fa09672011-07-25 11:05:35 +00005909 }
ricow@chromium.org9fa09672011-07-25 11:05:35 +00005910}
5911
5912
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005913void UnboxedDoubleIndexedPropertyEnumerator(
5914 const v8::PropertyCallbackInfo<v8::Array>& info) {
ricow@chromium.org9fa09672011-07-25 11:05:35 +00005915 // Force the list of returned keys to be stored in a FastDoubleArray.
5916 Local<Script> indexed_property_names_script = Script::Compile(v8_str(
5917 "keys = new Array(); keys[125000] = 1;"
5918 "for(i = 0; i < 80000; i++) { keys[i] = i; };"
5919 "keys.length = 25; keys;"));
5920 Local<Value> result = indexed_property_names_script->Run();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005921 info.GetReturnValue().Set(Local<v8::Array>::Cast(result));
ricow@chromium.org9fa09672011-07-25 11:05:35 +00005922}
5923
5924
5925// Make sure that the the interceptor code in the runtime properly handles
5926// merging property name lists for double-array-backed arrays.
5927THREADED_TEST(IndexedInterceptorUnboxedDoubleWithIndexedAccessor) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005928 v8::Isolate* isolate = CcTest::isolate();
5929 v8::HandleScope scope(isolate);
5930 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ricow@chromium.org9fa09672011-07-25 11:05:35 +00005931 templ->SetIndexedPropertyHandler(UnboxedDoubleIndexedPropertyGetter,
5932 UnboxedDoubleIndexedPropertySetter,
5933 0,
5934 0,
5935 UnboxedDoubleIndexedPropertyEnumerator);
5936 LocalContext context;
5937 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5938 // When obj is created, force it to be Stored in a FastDoubleArray.
5939 Local<Script> create_unboxed_double_script = Script::Compile(v8_str(
5940 "obj[125000] = 1; for(i = 0; i < 80000; i+=2) { obj[i] = i; } "
5941 "key_count = 0; "
5942 "for (x in obj) {key_count++;};"
5943 "obj;"));
5944 Local<Value> result = create_unboxed_double_script->Run();
5945 CHECK(result->ToObject()->HasRealIndexedProperty(2000));
5946 Local<Script> key_count_check = Script::Compile(v8_str(
5947 "key_count;"));
5948 result = key_count_check->Run();
5949 CHECK_EQ(v8_num(40013), result);
5950}
5951
5952
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005953void NonStrictArgsIndexedPropertyEnumerator(
5954 const v8::PropertyCallbackInfo<v8::Array>& info) {
rossberg@chromium.org28a37082011-08-22 11:03:23 +00005955 // Force the list of returned keys to be stored in a Arguments object.
5956 Local<Script> indexed_property_names_script = Script::Compile(v8_str(
5957 "function f(w,x) {"
5958 " return arguments;"
5959 "}"
5960 "keys = f(0, 1, 2, 3);"
5961 "keys;"));
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00005962 Local<Object> result =
5963 Local<Object>::Cast(indexed_property_names_script->Run());
5964 // Have to populate the handle manually, as it's not Cast-able.
5965 i::Handle<i::JSObject> o =
5966 v8::Utils::OpenHandle<Object, i::JSObject>(result);
5967 i::Handle<i::JSArray> array(reinterpret_cast<i::JSArray*>(*o));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005968 info.GetReturnValue().Set(v8::Utils::ToLocal(array));
rossberg@chromium.org28a37082011-08-22 11:03:23 +00005969}
5970
5971
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005972static void NonStrictIndexedPropertyGetter(
rossberg@chromium.org28a37082011-08-22 11:03:23 +00005973 uint32_t index,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005974 const v8::PropertyCallbackInfo<v8::Value>& info) {
rossberg@chromium.org28a37082011-08-22 11:03:23 +00005975 ApiTestFuzzer::Fuzz();
5976 if (index < 4) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005977 info.GetReturnValue().Set(v8_num(index));
rossberg@chromium.org28a37082011-08-22 11:03:23 +00005978 }
rossberg@chromium.org28a37082011-08-22 11:03:23 +00005979}
5980
5981
5982// Make sure that the the interceptor code in the runtime properly handles
5983// merging property name lists for non-string arguments arrays.
5984THREADED_TEST(IndexedInterceptorNonStrictArgsWithIndexedAccessor) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005985 v8::Isolate* isolate = CcTest::isolate();
5986 v8::HandleScope scope(isolate);
5987 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
rossberg@chromium.org28a37082011-08-22 11:03:23 +00005988 templ->SetIndexedPropertyHandler(NonStrictIndexedPropertyGetter,
5989 0,
5990 0,
5991 0,
5992 NonStrictArgsIndexedPropertyEnumerator);
5993 LocalContext context;
5994 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5995 Local<Script> create_args_script =
5996 Script::Compile(v8_str(
5997 "var key_count = 0;"
5998 "for (x in obj) {key_count++;} key_count;"));
5999 Local<Value> result = create_args_script->Run();
6000 CHECK_EQ(v8_num(4), result);
6001}
6002
6003
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00006004static void IdentityIndexedPropertyGetter(
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +00006005 uint32_t index,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00006006 const v8::PropertyCallbackInfo<v8::Value>& info) {
6007 info.GetReturnValue().Set(index);
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +00006008}
6009
6010
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00006011THREADED_TEST(IndexedInterceptorWithGetOwnPropertyDescriptor) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00006012 v8::Isolate* isolate = CcTest::isolate();
6013 v8::HandleScope scope(isolate);
6014 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00006015 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
6016
6017 LocalContext context;
6018 context->Global()->Set(v8_str("obj"), templ->NewInstance());
6019
6020 // Check fast object case.
6021 const char* fast_case_code =
6022 "Object.getOwnPropertyDescriptor(obj, 0).value.toString()";
6023 ExpectString(fast_case_code, "0");
6024
6025 // Check slow case.
6026 const char* slow_case_code =
6027 "obj.x = 1; delete obj.x;"
6028 "Object.getOwnPropertyDescriptor(obj, 1).value.toString()";
6029 ExpectString(slow_case_code, "1");
6030}
6031
6032
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +00006033THREADED_TEST(IndexedInterceptorWithNoSetter) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00006034 v8::Isolate* isolate = CcTest::isolate();
6035 v8::HandleScope scope(isolate);
6036 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +00006037 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
6038
6039 LocalContext context;
6040 context->Global()->Set(v8_str("obj"), templ->NewInstance());
6041
6042 const char* code =
6043 "try {"
6044 " obj[0] = 239;"
6045 " for (var i = 0; i < 100; i++) {"
6046 " var v = obj[0];"
6047 " if (v != 0) throw 'Wrong value ' + v + ' at iteration ' + i;"
6048 " }"
6049 " 'PASSED'"
6050 "} catch(e) {"
6051 " e"
6052 "}";
6053 ExpectString(code, "PASSED");
6054}
6055
6056
ager@chromium.org5c838252010-02-19 08:53:10 +00006057THREADED_TEST(IndexedInterceptorWithAccessorCheck) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00006058 v8::Isolate* isolate = CcTest::isolate();
6059 v8::HandleScope scope(isolate);
6060 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +00006061 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
6062
6063 LocalContext context;
6064 Local<v8::Object> obj = templ->NewInstance();
6065 obj->TurnOnAccessCheck();
6066 context->Global()->Set(v8_str("obj"), obj);
6067
6068 const char* code =
6069 "try {"
6070 " for (var i = 0; i < 100; i++) {"
6071 " var v = obj[0];"
6072 " if (v != undefined) throw 'Wrong value ' + v + ' at iteration ' + i;"
6073 " }"
6074 " 'PASSED'"
6075 "} catch(e) {"
6076 " e"
6077 "}";
6078 ExpectString(code, "PASSED");
6079}
6080
6081
6082THREADED_TEST(IndexedInterceptorWithAccessorCheckSwitchedOn) {
6083 i::FLAG_allow_natives_syntax = true;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00006084 v8::Isolate* isolate = CcTest::isolate();
6085 v8::HandleScope scope(isolate);
6086 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +00006087 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
6088
6089 LocalContext context;
6090 Local<v8::Object> obj = templ->NewInstance();
6091 context->Global()->Set(v8_str("obj"), obj);
6092
6093 const char* code =
6094 "try {"
6095 " for (var i = 0; i < 100; i++) {"
6096 " var expected = i;"
6097 " if (i == 5) {"
6098 " %EnableAccessChecks(obj);"
6099 " expected = undefined;"
6100 " }"
6101 " var v = obj[i];"
6102 " if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
6103 " if (i == 5) %DisableAccessChecks(obj);"
6104 " }"
6105 " 'PASSED'"
6106 "} catch(e) {"
6107 " e"
6108 "}";
6109 ExpectString(code, "PASSED");
6110}
6111
6112
6113THREADED_TEST(IndexedInterceptorWithDifferentIndices) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00006114 v8::Isolate* isolate = CcTest::isolate();
6115 v8::HandleScope scope(isolate);
6116 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +00006117 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
6118
6119 LocalContext context;
6120 Local<v8::Object> obj = templ->NewInstance();
6121 context->Global()->Set(v8_str("obj"), obj);
6122
6123 const char* code =
6124 "try {"
6125 " for (var i = 0; i < 100; i++) {"
6126 " var v = obj[i];"
6127 " if (v != i) throw 'Wrong value ' + v + ' at iteration ' + i;"
6128 " }"
6129 " 'PASSED'"
6130 "} catch(e) {"
6131 " e"
6132 "}";
6133 ExpectString(code, "PASSED");
6134}
6135
6136
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +00006137THREADED_TEST(IndexedInterceptorWithNegativeIndices) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00006138 v8::Isolate* isolate = CcTest::isolate();
6139 v8::HandleScope scope(isolate);
6140 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +00006141 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
6142
6143 LocalContext context;
6144 Local<v8::Object> obj = templ->NewInstance();
6145 context->Global()->Set(v8_str("obj"), obj);
6146
6147 const char* code =
6148 "try {"
6149 " for (var i = 0; i < 100; i++) {"
6150 " var expected = i;"
6151 " var key = i;"
6152 " if (i == 25) {"
6153 " key = -1;"
6154 " expected = undefined;"
6155 " }"
6156 " if (i == 50) {"
6157 " /* probe minimal Smi number on 32-bit platforms */"
6158 " key = -(1 << 30);"
6159 " expected = undefined;"
6160 " }"
6161 " if (i == 75) {"
6162 " /* probe minimal Smi number on 64-bit platforms */"
6163 " key = 1 << 31;"
6164 " expected = undefined;"
6165 " }"
6166 " var v = obj[key];"
6167 " if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
6168 " }"
6169 " 'PASSED'"
6170 "} catch(e) {"
6171 " e"
6172 "}";
6173 ExpectString(code, "PASSED");
6174}
6175
6176
ager@chromium.org5c838252010-02-19 08:53:10 +00006177THREADED_TEST(IndexedInterceptorWithNotSmiLookup) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00006178 v8::Isolate* isolate = CcTest::isolate();
6179 v8::HandleScope scope(isolate);
6180 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +00006181 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
6182
6183 LocalContext context;
6184 Local<v8::Object> obj = templ->NewInstance();
6185 context->Global()->Set(v8_str("obj"), obj);
6186
6187 const char* code =
6188 "try {"
6189 " for (var i = 0; i < 100; i++) {"
6190 " var expected = i;"
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +00006191 " var key = i;"
ager@chromium.org5c838252010-02-19 08:53:10 +00006192 " if (i == 50) {"
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +00006193 " key = 'foobar';"
ager@chromium.org5c838252010-02-19 08:53:10 +00006194 " expected = undefined;"
6195 " }"
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +00006196 " var v = obj[key];"
ager@chromium.org5c838252010-02-19 08:53:10 +00006197 " if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
6198 " }"
6199 " 'PASSED'"
6200 "} catch(e) {"
6201 " e"
6202 "}";
6203 ExpectString(code, "PASSED");
6204}
6205
6206
6207THREADED_TEST(IndexedInterceptorGoingMegamorphic) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00006208 v8::Isolate* isolate = CcTest::isolate();
6209 v8::HandleScope scope(isolate);
6210 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +00006211 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
6212
6213 LocalContext context;
6214 Local<v8::Object> obj = templ->NewInstance();
6215 context->Global()->Set(v8_str("obj"), obj);
6216
6217 const char* code =
6218 "var original = obj;"
6219 "try {"
6220 " for (var i = 0; i < 100; i++) {"
6221 " var expected = i;"
6222 " if (i == 50) {"
6223 " obj = {50: 'foobar'};"
6224 " expected = 'foobar';"
6225 " }"
6226 " var v = obj[i];"
6227 " if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
6228 " if (i == 50) obj = original;"
6229 " }"
6230 " 'PASSED'"
6231 "} catch(e) {"
6232 " e"
6233 "}";
6234 ExpectString(code, "PASSED");
6235}
6236
6237
6238THREADED_TEST(IndexedInterceptorReceiverTurningSmi) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00006239 v8::Isolate* isolate = CcTest::isolate();
6240 v8::HandleScope scope(isolate);
6241 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +00006242 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
6243
6244 LocalContext context;
6245 Local<v8::Object> obj = templ->NewInstance();
6246 context->Global()->Set(v8_str("obj"), obj);
6247
6248 const char* code =
6249 "var original = obj;"
6250 "try {"
6251 " for (var i = 0; i < 100; i++) {"
6252 " var expected = i;"
6253 " if (i == 5) {"
6254 " obj = 239;"
6255 " expected = undefined;"
6256 " }"
6257 " var v = obj[i];"
6258 " if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
6259 " if (i == 5) obj = original;"
6260 " }"
6261 " 'PASSED'"
6262 "} catch(e) {"
6263 " e"
6264 "}";
6265 ExpectString(code, "PASSED");
6266}
6267
6268
6269THREADED_TEST(IndexedInterceptorOnProto) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00006270 v8::Isolate* isolate = CcTest::isolate();
6271 v8::HandleScope scope(isolate);
6272 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +00006273 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
6274
6275 LocalContext context;
6276 Local<v8::Object> obj = templ->NewInstance();
6277 context->Global()->Set(v8_str("obj"), obj);
6278
6279 const char* code =
6280 "var o = {__proto__: obj};"
6281 "try {"
6282 " for (var i = 0; i < 100; i++) {"
6283 " var v = o[i];"
6284 " if (v != i) throw 'Wrong value ' + v + ' at iteration ' + i;"
6285 " }"
6286 " 'PASSED'"
6287 "} catch(e) {"
6288 " e"
6289 "}";
6290 ExpectString(code, "PASSED");
6291}
6292
6293
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006294THREADED_TEST(MultiContexts) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00006295 v8::Isolate* isolate = CcTest::isolate();
6296 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00006297 v8::Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00006298 templ->Set(v8_str("dummy"), v8::FunctionTemplate::New(isolate,
6299 DummyCallHandler));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006300
6301 Local<String> password = v8_str("Password");
6302
6303 // Create an environment
6304 LocalContext context0(0, templ);
6305 context0->SetSecurityToken(password);
6306 v8::Handle<v8::Object> global0 = context0->Global();
6307 global0->Set(v8_str("custom"), v8_num(1234));
6308 CHECK_EQ(1234, global0->Get(v8_str("custom"))->Int32Value());
6309
6310 // Create an independent environment
6311 LocalContext context1(0, templ);
6312 context1->SetSecurityToken(password);
6313 v8::Handle<v8::Object> global1 = context1->Global();
6314 global1->Set(v8_str("custom"), v8_num(1234));
6315 CHECK_NE(global0, global1);
6316 CHECK_EQ(1234, global0->Get(v8_str("custom"))->Int32Value());
6317 CHECK_EQ(1234, global1->Get(v8_str("custom"))->Int32Value());
6318
6319 // Now create a new context with the old global
6320 LocalContext context2(0, templ, global1);
6321 context2->SetSecurityToken(password);
6322 v8::Handle<v8::Object> global2 = context2->Global();
6323 CHECK_EQ(global1, global2);
6324 CHECK_EQ(0, global1->Get(v8_str("custom"))->Int32Value());
6325 CHECK_EQ(0, global2->Get(v8_str("custom"))->Int32Value());
6326}
6327
6328
6329THREADED_TEST(FunctionPrototypeAcrossContexts) {
6330 // Make sure that functions created by cloning boilerplates cannot
6331 // communicate through their __proto__ field.
6332
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006333 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006334
6335 LocalContext env0;
6336 v8::Handle<v8::Object> global0 =
6337 env0->Global();
6338 v8::Handle<v8::Object> object0 =
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00006339 global0->Get(v8_str("Object")).As<v8::Object>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006340 v8::Handle<v8::Object> tostring0 =
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00006341 object0->Get(v8_str("toString")).As<v8::Object>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006342 v8::Handle<v8::Object> proto0 =
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00006343 tostring0->Get(v8_str("__proto__")).As<v8::Object>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006344 proto0->Set(v8_str("custom"), v8_num(1234));
6345
6346 LocalContext env1;
6347 v8::Handle<v8::Object> global1 =
6348 env1->Global();
6349 v8::Handle<v8::Object> object1 =
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00006350 global1->Get(v8_str("Object")).As<v8::Object>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006351 v8::Handle<v8::Object> tostring1 =
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00006352 object1->Get(v8_str("toString")).As<v8::Object>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006353 v8::Handle<v8::Object> proto1 =
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00006354 tostring1->Get(v8_str("__proto__")).As<v8::Object>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006355 CHECK(!proto1->Has(v8_str("custom")));
6356}
6357
6358
6359THREADED_TEST(Regress892105) {
6360 // Make sure that object and array literals created by cloning
6361 // boilerplates cannot communicate through their __proto__
6362 // field. This is rather difficult to check, but we try to add stuff
6363 // to Object.prototype and Array.prototype and create a new
6364 // environment. This should succeed.
6365
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006366 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006367
6368 Local<String> source = v8_str("Object.prototype.obj = 1234;"
6369 "Array.prototype.arr = 4567;"
6370 "8901");
6371
6372 LocalContext env0;
6373 Local<Script> script0 = Script::Compile(source);
6374 CHECK_EQ(8901.0, script0->Run()->NumberValue());
6375
6376 LocalContext env1;
6377 Local<Script> script1 = Script::Compile(source);
6378 CHECK_EQ(8901.0, script1->Run()->NumberValue());
6379}
6380
6381
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006382THREADED_TEST(UndetectableObject) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006383 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00006384 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006385
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00006386 Local<v8::FunctionTemplate> desc =
6387 v8::FunctionTemplate::New(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006388 desc->InstanceTemplate()->MarkAsUndetectable(); // undetectable
6389
6390 Local<v8::Object> obj = desc->GetFunction()->NewInstance();
6391 env->Global()->Set(v8_str("undetectable"), obj);
6392
6393 ExpectString("undetectable.toString()", "[object Object]");
6394 ExpectString("typeof undetectable", "undefined");
6395 ExpectString("typeof(undetectable)", "undefined");
6396 ExpectBoolean("typeof undetectable == 'undefined'", true);
6397 ExpectBoolean("typeof undetectable == 'object'", false);
6398 ExpectBoolean("if (undetectable) { true; } else { false; }", false);
6399 ExpectBoolean("!undetectable", true);
6400
6401 ExpectObject("true&&undetectable", obj);
6402 ExpectBoolean("false&&undetectable", false);
6403 ExpectBoolean("true||undetectable", true);
6404 ExpectObject("false||undetectable", obj);
6405
6406 ExpectObject("undetectable&&true", obj);
6407 ExpectObject("undetectable&&false", obj);
6408 ExpectBoolean("undetectable||true", true);
6409 ExpectBoolean("undetectable||false", false);
6410
6411 ExpectBoolean("undetectable==null", true);
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00006412 ExpectBoolean("null==undetectable", true);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006413 ExpectBoolean("undetectable==undefined", true);
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00006414 ExpectBoolean("undefined==undetectable", true);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006415 ExpectBoolean("undetectable==undetectable", true);
6416
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00006417
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006418 ExpectBoolean("undetectable===null", false);
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00006419 ExpectBoolean("null===undetectable", false);
6420 ExpectBoolean("undetectable===undefined", false);
6421 ExpectBoolean("undefined===undetectable", false);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006422 ExpectBoolean("undetectable===undetectable", true);
6423}
6424
6425
ager@chromium.org04921a82011-06-27 13:21:41 +00006426THREADED_TEST(VoidLiteral) {
ager@chromium.org04921a82011-06-27 13:21:41 +00006427 LocalContext env;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00006428 v8::Isolate* isolate = env->GetIsolate();
6429 v8::HandleScope scope(isolate);
ager@chromium.org04921a82011-06-27 13:21:41 +00006430
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00006431 Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
ager@chromium.org04921a82011-06-27 13:21:41 +00006432 desc->InstanceTemplate()->MarkAsUndetectable(); // undetectable
6433
6434 Local<v8::Object> obj = desc->GetFunction()->NewInstance();
6435 env->Global()->Set(v8_str("undetectable"), obj);
6436
6437 ExpectBoolean("undefined == void 0", true);
6438 ExpectBoolean("undetectable == void 0", true);
6439 ExpectBoolean("null == void 0", true);
6440 ExpectBoolean("undefined === void 0", true);
6441 ExpectBoolean("undetectable === void 0", false);
6442 ExpectBoolean("null === void 0", false);
6443
6444 ExpectBoolean("void 0 == undefined", true);
6445 ExpectBoolean("void 0 == undetectable", true);
6446 ExpectBoolean("void 0 == null", true);
6447 ExpectBoolean("void 0 === undefined", true);
6448 ExpectBoolean("void 0 === undetectable", false);
6449 ExpectBoolean("void 0 === null", false);
6450
6451 ExpectString("(function() {"
6452 " try {"
6453 " return x === void 0;"
6454 " } catch(e) {"
6455 " return e.toString();"
6456 " }"
6457 "})()",
6458 "ReferenceError: x is not defined");
6459 ExpectString("(function() {"
6460 " try {"
6461 " return void 0 === x;"
6462 " } catch(e) {"
6463 " return e.toString();"
6464 " }"
6465 "})()",
6466 "ReferenceError: x is not defined");
6467}
6468
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00006469
6470THREADED_TEST(ExtensibleOnUndetectable) {
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00006471 LocalContext env;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00006472 v8::Isolate* isolate = env->GetIsolate();
6473 v8::HandleScope scope(isolate);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00006474
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00006475 Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00006476 desc->InstanceTemplate()->MarkAsUndetectable(); // undetectable
6477
6478 Local<v8::Object> obj = desc->GetFunction()->NewInstance();
6479 env->Global()->Set(v8_str("undetectable"), obj);
6480
6481 Local<String> source = v8_str("undetectable.x = 42;"
6482 "undetectable.x");
6483
6484 Local<Script> script = Script::Compile(source);
6485
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006486 CHECK_EQ(v8::Integer::New(isolate, 42), script->Run());
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00006487
6488 ExpectBoolean("Object.isExtensible(undetectable)", true);
6489
6490 source = v8_str("Object.preventExtensions(undetectable);");
6491 script = Script::Compile(source);
6492 script->Run();
6493 ExpectBoolean("Object.isExtensible(undetectable)", false);
6494
6495 source = v8_str("undetectable.y = 2000;");
6496 script = Script::Compile(source);
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00006497 script->Run();
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00006498 ExpectBoolean("undetectable.y == undefined", true);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00006499}
6500
6501
6502
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006503THREADED_TEST(UndetectableString) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006504 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00006505 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006506
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00006507 Local<String> obj = String::NewFromUtf8(env->GetIsolate(), "foo",
6508 String::kUndetectableString);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006509 env->Global()->Set(v8_str("undetectable"), obj);
6510
6511 ExpectString("undetectable", "foo");
6512 ExpectString("typeof undetectable", "undefined");
6513 ExpectString("typeof(undetectable)", "undefined");
6514 ExpectBoolean("typeof undetectable == 'undefined'", true);
6515 ExpectBoolean("typeof undetectable == 'string'", false);
6516 ExpectBoolean("if (undetectable) { true; } else { false; }", false);
6517 ExpectBoolean("!undetectable", true);
6518
6519 ExpectObject("true&&undetectable", obj);
6520 ExpectBoolean("false&&undetectable", false);
6521 ExpectBoolean("true||undetectable", true);
6522 ExpectObject("false||undetectable", obj);
6523
6524 ExpectObject("undetectable&&true", obj);
6525 ExpectObject("undetectable&&false", obj);
6526 ExpectBoolean("undetectable||true", true);
6527 ExpectBoolean("undetectable||false", false);
6528
6529 ExpectBoolean("undetectable==null", true);
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00006530 ExpectBoolean("null==undetectable", true);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006531 ExpectBoolean("undetectable==undefined", true);
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00006532 ExpectBoolean("undefined==undetectable", true);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006533 ExpectBoolean("undetectable==undetectable", true);
6534
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00006535
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006536 ExpectBoolean("undetectable===null", false);
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00006537 ExpectBoolean("null===undetectable", false);
6538 ExpectBoolean("undetectable===undefined", false);
6539 ExpectBoolean("undefined===undetectable", false);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006540 ExpectBoolean("undetectable===undetectable", true);
6541}
6542
6543
vegorov@chromium.org7304bca2011-05-16 12:14:13 +00006544TEST(UndetectableOptimized) {
6545 i::FLAG_allow_natives_syntax = true;
vegorov@chromium.org7304bca2011-05-16 12:14:13 +00006546 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00006547 v8::HandleScope scope(env->GetIsolate());
vegorov@chromium.org7304bca2011-05-16 12:14:13 +00006548
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00006549 Local<String> obj = String::NewFromUtf8(env->GetIsolate(), "foo",
6550 String::kUndetectableString);
vegorov@chromium.org7304bca2011-05-16 12:14:13 +00006551 env->Global()->Set(v8_str("undetectable"), obj);
6552 env->Global()->Set(v8_str("detectable"), v8_str("bar"));
6553
6554 ExpectString(
6555 "function testBranch() {"
6556 " if (!%_IsUndetectableObject(undetectable)) throw 1;"
6557 " if (%_IsUndetectableObject(detectable)) throw 2;"
6558 "}\n"
6559 "function testBool() {"
6560 " var b1 = !%_IsUndetectableObject(undetectable);"
6561 " var b2 = %_IsUndetectableObject(detectable);"
6562 " if (b1) throw 3;"
6563 " if (b2) throw 4;"
6564 " return b1 == b2;"
6565 "}\n"
6566 "%OptimizeFunctionOnNextCall(testBranch);"
6567 "%OptimizeFunctionOnNextCall(testBool);"
6568 "for (var i = 0; i < 10; i++) {"
6569 " testBranch();"
6570 " testBool();"
6571 "}\n"
6572 "\"PASS\"",
6573 "PASS");
6574}
6575
6576
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006577template <typename T> static void USE(T) { }
6578
6579
machenbach@chromium.orgafbdadc2013-12-09 16:12:18 +00006580// The point of this test is type checking. We run it only so compilers
6581// don't complain about an unused function.
6582TEST(PersistentHandles) {
6583 LocalContext env;
6584 v8::Isolate* isolate = CcTest::isolate();
6585 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006586 Local<String> str = v8_str("foo");
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00006587 v8::Persistent<String> p_str(isolate, str);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00006588 p_str.Reset();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006589 Local<Script> scr = Script::Compile(v8_str(""));
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00006590 v8::Persistent<Script> p_scr(isolate, scr);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00006591 p_scr.Reset();
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00006592 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00006593 v8::Persistent<ObjectTemplate> p_templ(isolate, templ);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00006594 p_templ.Reset();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006595}
6596
6597
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00006598static void HandleLogDelegator(
6599 const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006600 ApiTestFuzzer::Fuzz();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006601}
6602
6603
6604THREADED_TEST(GlobalObjectTemplate) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006605 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006606 v8::HandleScope handle_scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00006607 Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006608 global_template->Set(v8_str("JSNI_Log"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00006609 v8::FunctionTemplate::New(isolate, HandleLogDelegator));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006610 v8::Local<Context> context = Context::New(isolate, 0, global_template);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006611 Context::Scope context_scope(context);
6612 Script::Compile(v8_str("JSNI_Log('LOG')"))->Run();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006613}
6614
6615
6616static const char* kSimpleExtensionSource =
6617 "function Foo() {"
6618 " return 4;"
6619 "}";
6620
6621
machenbach@chromium.org09cae8d2014-01-30 01:05:27 +00006622TEST(SimpleExtensions) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006623 v8::HandleScope handle_scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006624 v8::RegisterExtension(new Extension("simpletest", kSimpleExtensionSource));
6625 const char* extension_names[] = { "simpletest" };
6626 v8::ExtensionConfiguration extensions(1, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006627 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006628 Context::New(CcTest::isolate(), &extensions);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006629 Context::Scope lock(context);
6630 v8::Handle<Value> result = Script::Compile(v8_str("Foo()"))->Run();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006631 CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 4));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006632}
6633
6634
machenbach@chromium.org09cae8d2014-01-30 01:05:27 +00006635TEST(NullExtensions) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006636 v8::HandleScope handle_scope(CcTest::isolate());
danno@chromium.org412fa512012-09-14 13:28:26 +00006637 v8::RegisterExtension(new Extension("nulltest", NULL));
6638 const char* extension_names[] = { "nulltest" };
6639 v8::ExtensionConfiguration extensions(1, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006640 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006641 Context::New(CcTest::isolate(), &extensions);
danno@chromium.org412fa512012-09-14 13:28:26 +00006642 Context::Scope lock(context);
6643 v8::Handle<Value> result = Script::Compile(v8_str("1+3"))->Run();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006644 CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 4));
danno@chromium.org412fa512012-09-14 13:28:26 +00006645}
6646
6647
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00006648static const char* kEmbeddedExtensionSource =
6649 "function Ret54321(){return 54321;}~~@@$"
6650 "$%% THIS IS A SERIES OF NON-NULL-TERMINATED STRINGS.";
6651static const int kEmbeddedExtensionSourceValidLen = 34;
6652
6653
machenbach@chromium.org09cae8d2014-01-30 01:05:27 +00006654TEST(ExtensionMissingSourceLength) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006655 v8::HandleScope handle_scope(CcTest::isolate());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00006656 v8::RegisterExtension(new Extension("srclentest_fail",
6657 kEmbeddedExtensionSource));
6658 const char* extension_names[] = { "srclentest_fail" };
6659 v8::ExtensionConfiguration extensions(1, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006660 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006661 Context::New(CcTest::isolate(), &extensions);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00006662 CHECK_EQ(0, *context);
6663}
6664
6665
machenbach@chromium.org09cae8d2014-01-30 01:05:27 +00006666TEST(ExtensionWithSourceLength) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00006667 for (int source_len = kEmbeddedExtensionSourceValidLen - 1;
6668 source_len <= kEmbeddedExtensionSourceValidLen + 1; ++source_len) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006669 v8::HandleScope handle_scope(CcTest::isolate());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00006670 i::ScopedVector<char> extension_name(32);
6671 i::OS::SNPrintF(extension_name, "ext #%d", source_len);
6672 v8::RegisterExtension(new Extension(extension_name.start(),
6673 kEmbeddedExtensionSource, 0, 0,
6674 source_len));
6675 const char* extension_names[1] = { extension_name.start() };
6676 v8::ExtensionConfiguration extensions(1, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006677 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006678 Context::New(CcTest::isolate(), &extensions);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00006679 if (source_len == kEmbeddedExtensionSourceValidLen) {
6680 Context::Scope lock(context);
6681 v8::Handle<Value> result = Script::Compile(v8_str("Ret54321()"))->Run();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006682 CHECK_EQ(v8::Integer::New(CcTest::isolate(), 54321), result);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00006683 } else {
6684 // Anything but exactly the right length should fail to compile.
6685 CHECK_EQ(0, *context);
6686 }
6687 }
6688}
6689
6690
ager@chromium.org18ad94b2009-09-02 08:22:29 +00006691static const char* kEvalExtensionSource1 =
6692 "function UseEval1() {"
kasperl@chromium.org2d18d102009-04-15 13:27:32 +00006693 " var x = 42;"
6694 " return eval('x');"
6695 "}";
6696
6697
ager@chromium.org18ad94b2009-09-02 08:22:29 +00006698static const char* kEvalExtensionSource2 =
6699 "(function() {"
6700 " var x = 42;"
6701 " function e() {"
6702 " return eval('x');"
6703 " }"
6704 " this.UseEval2 = e;"
6705 "})()";
6706
6707
machenbach@chromium.org09cae8d2014-01-30 01:05:27 +00006708TEST(UseEvalFromExtension) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006709 v8::HandleScope handle_scope(CcTest::isolate());
ager@chromium.org18ad94b2009-09-02 08:22:29 +00006710 v8::RegisterExtension(new Extension("evaltest1", kEvalExtensionSource1));
6711 v8::RegisterExtension(new Extension("evaltest2", kEvalExtensionSource2));
6712 const char* extension_names[] = { "evaltest1", "evaltest2" };
6713 v8::ExtensionConfiguration extensions(2, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006714 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006715 Context::New(CcTest::isolate(), &extensions);
kasperl@chromium.org2d18d102009-04-15 13:27:32 +00006716 Context::Scope lock(context);
ager@chromium.org18ad94b2009-09-02 08:22:29 +00006717 v8::Handle<Value> result = Script::Compile(v8_str("UseEval1()"))->Run();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006718 CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 42));
ager@chromium.org18ad94b2009-09-02 08:22:29 +00006719 result = Script::Compile(v8_str("UseEval2()"))->Run();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006720 CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 42));
kasperl@chromium.org2d18d102009-04-15 13:27:32 +00006721}
6722
6723
ager@chromium.org18ad94b2009-09-02 08:22:29 +00006724static const char* kWithExtensionSource1 =
6725 "function UseWith1() {"
kasperl@chromium.org2d18d102009-04-15 13:27:32 +00006726 " var x = 42;"
6727 " with({x:87}) { return x; }"
6728 "}";
6729
6730
ager@chromium.org18ad94b2009-09-02 08:22:29 +00006731
6732static const char* kWithExtensionSource2 =
6733 "(function() {"
6734 " var x = 42;"
6735 " function e() {"
6736 " with ({x:87}) { return x; }"
6737 " }"
6738 " this.UseWith2 = e;"
6739 "})()";
6740
6741
machenbach@chromium.org09cae8d2014-01-30 01:05:27 +00006742TEST(UseWithFromExtension) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006743 v8::HandleScope handle_scope(CcTest::isolate());
ager@chromium.org18ad94b2009-09-02 08:22:29 +00006744 v8::RegisterExtension(new Extension("withtest1", kWithExtensionSource1));
6745 v8::RegisterExtension(new Extension("withtest2", kWithExtensionSource2));
6746 const char* extension_names[] = { "withtest1", "withtest2" };
6747 v8::ExtensionConfiguration extensions(2, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006748 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006749 Context::New(CcTest::isolate(), &extensions);
kasperl@chromium.org2d18d102009-04-15 13:27:32 +00006750 Context::Scope lock(context);
ager@chromium.org18ad94b2009-09-02 08:22:29 +00006751 v8::Handle<Value> result = Script::Compile(v8_str("UseWith1()"))->Run();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006752 CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 87));
ager@chromium.org18ad94b2009-09-02 08:22:29 +00006753 result = Script::Compile(v8_str("UseWith2()"))->Run();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006754 CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 87));
kasperl@chromium.org2d18d102009-04-15 13:27:32 +00006755}
6756
6757
machenbach@chromium.org09cae8d2014-01-30 01:05:27 +00006758TEST(AutoExtensions) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006759 v8::HandleScope handle_scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006760 Extension* extension = new Extension("autotest", kSimpleExtensionSource);
6761 extension->set_auto_enable(true);
6762 v8::RegisterExtension(extension);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006763 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006764 Context::New(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006765 Context::Scope lock(context);
6766 v8::Handle<Value> result = Script::Compile(v8_str("Foo()"))->Run();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006767 CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 4));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006768}
6769
6770
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00006771static const char* kSyntaxErrorInExtensionSource =
6772 "[";
6773
6774
6775// Test that a syntax error in an extension does not cause a fatal
6776// error but results in an empty context.
machenbach@chromium.org09cae8d2014-01-30 01:05:27 +00006777TEST(SyntaxErrorExtensions) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006778 v8::HandleScope handle_scope(CcTest::isolate());
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00006779 v8::RegisterExtension(new Extension("syntaxerror",
6780 kSyntaxErrorInExtensionSource));
6781 const char* extension_names[] = { "syntaxerror" };
6782 v8::ExtensionConfiguration extensions(1, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006783 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006784 Context::New(CcTest::isolate(), &extensions);
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00006785 CHECK(context.IsEmpty());
6786}
6787
6788
6789static const char* kExceptionInExtensionSource =
6790 "throw 42";
6791
6792
6793// Test that an exception when installing an extension does not cause
6794// a fatal error but results in an empty context.
machenbach@chromium.org09cae8d2014-01-30 01:05:27 +00006795TEST(ExceptionExtensions) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006796 v8::HandleScope handle_scope(CcTest::isolate());
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00006797 v8::RegisterExtension(new Extension("exception",
6798 kExceptionInExtensionSource));
6799 const char* extension_names[] = { "exception" };
6800 v8::ExtensionConfiguration extensions(1, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006801 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006802 Context::New(CcTest::isolate(), &extensions);
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00006803 CHECK(context.IsEmpty());
6804}
6805
6806
ager@chromium.org5b2fbee2010-09-08 06:38:15 +00006807static const char* kNativeCallInExtensionSource =
6808 "function call_runtime_last_index_of(x) {"
6809 " return %StringLastIndexOf(x, 'bob', 10);"
6810 "}";
6811
6812
6813static const char* kNativeCallTest =
6814 "call_runtime_last_index_of('bobbobboellebobboellebobbob');";
6815
6816// Test that a native runtime calls are supported in extensions.
machenbach@chromium.org09cae8d2014-01-30 01:05:27 +00006817TEST(NativeCallInExtensions) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006818 v8::HandleScope handle_scope(CcTest::isolate());
ager@chromium.org5b2fbee2010-09-08 06:38:15 +00006819 v8::RegisterExtension(new Extension("nativecall",
6820 kNativeCallInExtensionSource));
6821 const char* extension_names[] = { "nativecall" };
6822 v8::ExtensionConfiguration extensions(1, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006823 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006824 Context::New(CcTest::isolate(), &extensions);
ager@chromium.org5b2fbee2010-09-08 06:38:15 +00006825 Context::Scope lock(context);
6826 v8::Handle<Value> result = Script::Compile(v8_str(kNativeCallTest))->Run();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006827 CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 3));
ager@chromium.org5b2fbee2010-09-08 06:38:15 +00006828}
6829
6830
whesse@chromium.org7b260152011-06-20 15:33:18 +00006831class NativeFunctionExtension : public Extension {
6832 public:
6833 NativeFunctionExtension(const char* name,
6834 const char* source,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00006835 v8::FunctionCallback fun = &Echo)
whesse@chromium.org7b260152011-06-20 15:33:18 +00006836 : Extension(name, source),
6837 function_(fun) { }
6838
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00006839 virtual v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate(
6840 v8::Isolate* isolate,
whesse@chromium.org7b260152011-06-20 15:33:18 +00006841 v8::Handle<v8::String> name) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00006842 return v8::FunctionTemplate::New(isolate, function_);
whesse@chromium.org7b260152011-06-20 15:33:18 +00006843 }
6844
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00006845 static void Echo(const v8::FunctionCallbackInfo<v8::Value>& args) {
6846 if (args.Length() >= 1) args.GetReturnValue().Set(args[0]);
whesse@chromium.org7b260152011-06-20 15:33:18 +00006847 }
6848 private:
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00006849 v8::FunctionCallback function_;
whesse@chromium.org7b260152011-06-20 15:33:18 +00006850};
6851
6852
machenbach@chromium.org09cae8d2014-01-30 01:05:27 +00006853TEST(NativeFunctionDeclaration) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006854 v8::HandleScope handle_scope(CcTest::isolate());
whesse@chromium.org7b260152011-06-20 15:33:18 +00006855 const char* name = "nativedecl";
6856 v8::RegisterExtension(new NativeFunctionExtension(name,
6857 "native function foo();"));
6858 const char* extension_names[] = { name };
6859 v8::ExtensionConfiguration extensions(1, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006860 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006861 Context::New(CcTest::isolate(), &extensions);
whesse@chromium.org7b260152011-06-20 15:33:18 +00006862 Context::Scope lock(context);
6863 v8::Handle<Value> result = Script::Compile(v8_str("foo(42);"))->Run();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006864 CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 42));
whesse@chromium.org7b260152011-06-20 15:33:18 +00006865}
6866
6867
machenbach@chromium.org09cae8d2014-01-30 01:05:27 +00006868TEST(NativeFunctionDeclarationError) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006869 v8::HandleScope handle_scope(CcTest::isolate());
lrn@chromium.org67e236d2011-06-23 10:18:16 +00006870 const char* name = "nativedeclerr";
whesse@chromium.org7b260152011-06-20 15:33:18 +00006871 // Syntax error in extension code.
6872 v8::RegisterExtension(new NativeFunctionExtension(name,
6873 "native\nfunction foo();"));
6874 const char* extension_names[] = { name };
6875 v8::ExtensionConfiguration extensions(1, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006876 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006877 Context::New(CcTest::isolate(), &extensions);
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00006878 CHECK(context.IsEmpty());
whesse@chromium.org7b260152011-06-20 15:33:18 +00006879}
6880
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00006881
machenbach@chromium.org09cae8d2014-01-30 01:05:27 +00006882TEST(NativeFunctionDeclarationErrorEscape) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006883 v8::HandleScope handle_scope(CcTest::isolate());
lrn@chromium.org67e236d2011-06-23 10:18:16 +00006884 const char* name = "nativedeclerresc";
whesse@chromium.org7b260152011-06-20 15:33:18 +00006885 // Syntax error in extension code - escape code in "native" means that
6886 // it's not treated as a keyword.
6887 v8::RegisterExtension(new NativeFunctionExtension(
6888 name,
6889 "nativ\\u0065 function foo();"));
6890 const char* extension_names[] = { name };
6891 v8::ExtensionConfiguration extensions(1, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006892 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006893 Context::New(CcTest::isolate(), &extensions);
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00006894 CHECK(context.IsEmpty());
whesse@chromium.org7b260152011-06-20 15:33:18 +00006895}
6896
6897
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006898static void CheckDependencies(const char* name, const char* expected) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006899 v8::HandleScope handle_scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006900 v8::ExtensionConfiguration config(1, &name);
6901 LocalContext context(&config);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00006902 CHECK_EQ(String::NewFromUtf8(CcTest::isolate(), expected),
6903 context->Global()->Get(v8_str("loaded")));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006904}
6905
6906
6907/*
6908 * Configuration:
6909 *
6910 * /-- B <--\
6911 * A <- -- D <-- E
6912 * \-- C <--/
6913 */
6914THREADED_TEST(ExtensionDependency) {
6915 static const char* kEDeps[] = { "D" };
6916 v8::RegisterExtension(new Extension("E", "this.loaded += 'E';", 1, kEDeps));
6917 static const char* kDDeps[] = { "B", "C" };
6918 v8::RegisterExtension(new Extension("D", "this.loaded += 'D';", 2, kDDeps));
6919 static const char* kBCDeps[] = { "A" };
6920 v8::RegisterExtension(new Extension("B", "this.loaded += 'B';", 1, kBCDeps));
6921 v8::RegisterExtension(new Extension("C", "this.loaded += 'C';", 1, kBCDeps));
6922 v8::RegisterExtension(new Extension("A", "this.loaded += 'A';"));
6923 CheckDependencies("A", "undefinedA");
6924 CheckDependencies("B", "undefinedAB");
6925 CheckDependencies("C", "undefinedAC");
6926 CheckDependencies("D", "undefinedABCD");
6927 CheckDependencies("E", "undefinedABCDE");
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006928 v8::HandleScope handle_scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006929 static const char* exts[2] = { "C", "E" };
6930 v8::ExtensionConfiguration config(2, exts);
6931 LocalContext context(&config);
6932 CHECK_EQ(v8_str("undefinedACBDE"), context->Global()->Get(v8_str("loaded")));
6933}
6934
6935
6936static const char* kExtensionTestScript =
6937 "native function A();"
6938 "native function B();"
6939 "native function C();"
6940 "function Foo(i) {"
6941 " if (i == 0) return A();"
6942 " if (i == 1) return B();"
6943 " if (i == 2) return C();"
6944 "}";
6945
6946
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00006947static void CallFun(const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006948 ApiTestFuzzer::Fuzz();
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00006949 if (args.IsConstructCall()) {
6950 args.This()->Set(v8_str("data"), args.Data());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00006951 args.GetReturnValue().SetNull();
6952 return;
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00006953 }
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00006954 args.GetReturnValue().Set(args.Data());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006955}
6956
6957
6958class FunctionExtension : public Extension {
6959 public:
6960 FunctionExtension() : Extension("functiontest", kExtensionTestScript) { }
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00006961 virtual v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate(
6962 v8::Isolate* isolate,
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006963 v8::Handle<String> name);
6964};
6965
6966
6967static int lookup_count = 0;
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00006968v8::Handle<v8::FunctionTemplate> FunctionExtension::GetNativeFunctionTemplate(
6969 v8::Isolate* isolate, v8::Handle<String> name) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006970 lookup_count++;
6971 if (name->Equals(v8_str("A"))) {
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006972 return v8::FunctionTemplate::New(
6973 isolate, CallFun, v8::Integer::New(isolate, 8));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006974 } else if (name->Equals(v8_str("B"))) {
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006975 return v8::FunctionTemplate::New(
6976 isolate, CallFun, v8::Integer::New(isolate, 7));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006977 } else if (name->Equals(v8_str("C"))) {
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006978 return v8::FunctionTemplate::New(
6979 isolate, CallFun, v8::Integer::New(isolate, 6));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006980 } else {
6981 return v8::Handle<v8::FunctionTemplate>();
6982 }
6983}
6984
6985
6986THREADED_TEST(FunctionLookup) {
6987 v8::RegisterExtension(new FunctionExtension());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006988 v8::HandleScope handle_scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006989 static const char* exts[1] = { "functiontest" };
6990 v8::ExtensionConfiguration config(1, exts);
6991 LocalContext context(&config);
6992 CHECK_EQ(3, lookup_count);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006993 CHECK_EQ(v8::Integer::New(CcTest::isolate(), 8),
6994 Script::Compile(v8_str("Foo(0)"))->Run());
6995 CHECK_EQ(v8::Integer::New(CcTest::isolate(), 7),
6996 Script::Compile(v8_str("Foo(1)"))->Run());
6997 CHECK_EQ(v8::Integer::New(CcTest::isolate(), 6),
6998 Script::Compile(v8_str("Foo(2)"))->Run());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006999}
7000
7001
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00007002THREADED_TEST(NativeFunctionConstructCall) {
7003 v8::RegisterExtension(new FunctionExtension());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007004 v8::HandleScope handle_scope(CcTest::isolate());
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00007005 static const char* exts[1] = { "functiontest" };
7006 v8::ExtensionConfiguration config(1, exts);
7007 LocalContext context(&config);
7008 for (int i = 0; i < 10; i++) {
7009 // Run a few times to ensure that allocation of objects doesn't
7010 // change behavior of a constructor function.
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007011 CHECK_EQ(v8::Integer::New(CcTest::isolate(), 8),
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00007012 Script::Compile(v8_str("(new A()).data"))->Run());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007013 CHECK_EQ(v8::Integer::New(CcTest::isolate(), 7),
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00007014 Script::Compile(v8_str("(new B()).data"))->Run());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007015 CHECK_EQ(v8::Integer::New(CcTest::isolate(), 6),
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00007016 Script::Compile(v8_str("(new C()).data"))->Run());
7017 }
7018}
7019
7020
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007021static const char* last_location;
7022static const char* last_message;
7023void StoringErrorCallback(const char* location, const char* message) {
7024 if (last_location == NULL) {
7025 last_location = location;
7026 last_message = message;
7027 }
7028}
7029
7030
7031// ErrorReporting creates a circular extensions configuration and
7032// tests that the fatal error handler gets called. This renders V8
7033// unusable and therefore this test cannot be run in parallel.
7034TEST(ErrorReporting) {
7035 v8::V8::SetFatalErrorHandler(StoringErrorCallback);
7036 static const char* aDeps[] = { "B" };
7037 v8::RegisterExtension(new Extension("A", "", 1, aDeps));
7038 static const char* bDeps[] = { "A" };
7039 v8::RegisterExtension(new Extension("B", "", 1, bDeps));
7040 last_location = NULL;
7041 v8::ExtensionConfiguration config(1, bDeps);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007042 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007043 Context::New(CcTest::isolate(), &config);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007044 CHECK(context.IsEmpty());
7045 CHECK_NE(last_location, NULL);
7046}
7047
7048
7049static void MissingScriptInfoMessageListener(v8::Handle<v8::Message> message,
7050 v8::Handle<Value> data) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00007051 CHECK(message->GetScriptResourceName()->IsUndefined());
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00007052 CHECK_EQ(v8::Undefined(CcTest::isolate()), message->GetScriptResourceName());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007053 message->GetLineNumber();
7054 message->GetSourceLine();
7055}
7056
7057
7058THREADED_TEST(ErrorWithMissingScriptInfo) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007059 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00007060 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007061 v8::V8::AddMessageListener(MissingScriptInfoMessageListener);
7062 Script::Compile(v8_str("throw Error()"))->Run();
7063 v8::V8::RemoveMessageListeners(MissingScriptInfoMessageListener);
7064}
7065
7066
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007067struct FlagAndPersistent {
7068 bool flag;
7069 v8::Persistent<v8::Object> handle;
7070};
7071
7072
7073static void DisposeAndSetFlag(
7074 const v8::WeakCallbackData<v8::Object, FlagAndPersistent>& data) {
7075 data.GetParameter()->handle.Reset();
7076 data.GetParameter()->flag = true;
ager@chromium.orgc4c92722009-11-18 14:12:51 +00007077}
7078
ager@chromium.orgc4c92722009-11-18 14:12:51 +00007079
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007080THREADED_TEST(IndependentWeakHandle) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007081 v8::Isolate* iso = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007082 v8::HandleScope scope(iso);
7083 v8::Handle<Context> context = Context::New(iso);
ager@chromium.orgc4c92722009-11-18 14:12:51 +00007084 Context::Scope context_scope(context);
7085
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007086 FlagAndPersistent object_a, object_b;
ager@chromium.orgc4c92722009-11-18 14:12:51 +00007087
7088 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00007089 v8::HandleScope handle_scope(iso);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007090 object_a.handle.Reset(iso, v8::Object::New(iso));
7091 object_b.handle.Reset(iso, v8::Object::New(iso));
ager@chromium.orgc4c92722009-11-18 14:12:51 +00007092 }
7093
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007094 object_a.flag = false;
7095 object_b.flag = false;
7096 object_a.handle.SetWeak(&object_a, &DisposeAndSetFlag);
7097 object_b.handle.SetWeak(&object_b, &DisposeAndSetFlag);
7098 CHECK(!object_b.handle.IsIndependent());
7099 object_a.handle.MarkIndependent();
7100 object_b.handle.MarkIndependent();
7101 CHECK(object_b.handle.IsIndependent());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007102 CcTest::heap()->PerformScavenge();
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007103 CHECK(object_a.flag);
7104 CHECK(object_b.flag);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007105}
ager@chromium.orgc4c92722009-11-18 14:12:51 +00007106
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007107
7108static void InvokeScavenge() {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007109 CcTest::heap()->PerformScavenge();
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007110}
7111
7112
7113static void InvokeMarkSweep() {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007114 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007115}
7116
7117
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007118static void ForceScavenge(
7119 const v8::WeakCallbackData<v8::Object, FlagAndPersistent>& data) {
7120 data.GetParameter()->handle.Reset();
7121 data.GetParameter()->flag = true;
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007122 InvokeScavenge();
7123}
7124
7125
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007126static void ForceMarkSweep(
7127 const v8::WeakCallbackData<v8::Object, FlagAndPersistent>& data) {
7128 data.GetParameter()->handle.Reset();
7129 data.GetParameter()->flag = true;
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007130 InvokeMarkSweep();
7131}
7132
7133
7134THREADED_TEST(GCFromWeakCallbacks) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007135 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007136 v8::HandleScope scope(isolate);
7137 v8::Handle<Context> context = Context::New(isolate);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007138 Context::Scope context_scope(context);
7139
7140 static const int kNumberOfGCTypes = 2;
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007141 typedef v8::WeakCallbackData<v8::Object, FlagAndPersistent>::Callback
7142 Callback;
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007143 Callback gc_forcing_callback[kNumberOfGCTypes] =
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007144 {&ForceScavenge, &ForceMarkSweep};
7145
7146 typedef void (*GCInvoker)();
7147 GCInvoker invoke_gc[kNumberOfGCTypes] = {&InvokeScavenge, &InvokeMarkSweep};
7148
7149 for (int outer_gc = 0; outer_gc < kNumberOfGCTypes; outer_gc++) {
7150 for (int inner_gc = 0; inner_gc < kNumberOfGCTypes; inner_gc++) {
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007151 FlagAndPersistent object;
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007152 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00007153 v8::HandleScope handle_scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007154 object.handle.Reset(isolate, v8::Object::New(isolate));
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007155 }
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007156 object.flag = false;
7157 object.handle.SetWeak(&object, gc_forcing_callback[inner_gc]);
7158 object.handle.MarkIndependent();
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007159 invoke_gc[outer_gc]();
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007160 CHECK(object.flag);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007161 }
ager@chromium.orgc4c92722009-11-18 14:12:51 +00007162 }
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007163}
7164
7165
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007166static void RevivingCallback(
7167 const v8::WeakCallbackData<v8::Object, FlagAndPersistent>& data) {
7168 data.GetParameter()->handle.ClearWeak();
7169 data.GetParameter()->flag = true;
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007170}
7171
7172
7173THREADED_TEST(IndependentHandleRevival) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007174 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007175 v8::HandleScope scope(isolate);
7176 v8::Handle<Context> context = Context::New(isolate);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007177 Context::Scope context_scope(context);
7178
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007179 FlagAndPersistent object;
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007180 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00007181 v8::HandleScope handle_scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007182 v8::Local<v8::Object> o = v8::Object::New(isolate);
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007183 object.handle.Reset(isolate, o);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007184 o->Set(v8_str("x"), v8::Integer::New(isolate, 1));
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007185 v8::Local<String> y_str = v8_str("y");
rossberg@chromium.org79e79022013-06-03 15:43:46 +00007186 o->Set(y_str, y_str);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007187 }
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007188 object.flag = false;
7189 object.handle.SetWeak(&object, &RevivingCallback);
7190 object.handle.MarkIndependent();
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007191 CcTest::heap()->PerformScavenge();
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007192 CHECK(object.flag);
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007193 CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007194 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00007195 v8::HandleScope handle_scope(isolate);
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007196 v8::Local<v8::Object> o =
7197 v8::Local<v8::Object>::New(isolate, object.handle);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007198 v8::Local<String> y_str = v8_str("y");
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007199 CHECK_EQ(v8::Integer::New(isolate, 1), o->Get(v8_str("x")));
rossberg@chromium.org79e79022013-06-03 15:43:46 +00007200 CHECK(o->Get(y_str)->Equals(y_str));
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007201 }
ager@chromium.orgc4c92722009-11-18 14:12:51 +00007202}
7203
7204
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007205v8::Handle<Function> args_fun;
7206
7207
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007208static void ArgumentsTestCallback(
7209 const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007210 ApiTestFuzzer::Fuzz();
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00007211 v8::Isolate* isolate = args.GetIsolate();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007212 CHECK_EQ(args_fun, args.Callee());
7213 CHECK_EQ(3, args.Length());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007214 CHECK_EQ(v8::Integer::New(isolate, 1), args[0]);
7215 CHECK_EQ(v8::Integer::New(isolate, 2), args[1]);
7216 CHECK_EQ(v8::Integer::New(isolate, 3), args[2]);
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00007217 CHECK_EQ(v8::Undefined(isolate), args[3]);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00007218 v8::HandleScope scope(args.GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007219 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007220}
7221
7222
7223THREADED_TEST(Arguments) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00007224 v8::Isolate* isolate = CcTest::isolate();
7225 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00007226 v8::Handle<v8::ObjectTemplate> global = ObjectTemplate::New(isolate);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00007227 global->Set(v8_str("f"),
7228 v8::FunctionTemplate::New(isolate, ArgumentsTestCallback));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007229 LocalContext context(NULL, global);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00007230 args_fun = context->Global()->Get(v8_str("f")).As<Function>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007231 v8_compile("f(1, 2, 3)")->Run();
7232}
7233
7234
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007235static void NoBlockGetterX(Local<String> name,
7236 const v8::PropertyCallbackInfo<v8::Value>&) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007237}
7238
7239
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007240static void NoBlockGetterI(uint32_t index,
7241 const v8::PropertyCallbackInfo<v8::Value>&) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007242}
7243
7244
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007245static void PDeleter(Local<String> name,
7246 const v8::PropertyCallbackInfo<v8::Boolean>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007247 if (!name->Equals(v8_str("foo"))) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007248 return; // not intercepted
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007249 }
7250
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007251 info.GetReturnValue().Set(false); // intercepted, don't delete the property
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007252}
7253
7254
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007255static void IDeleter(uint32_t index,
7256 const v8::PropertyCallbackInfo<v8::Boolean>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007257 if (index != 2) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007258 return; // not intercepted
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007259 }
7260
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007261 info.GetReturnValue().Set(false); // intercepted, don't delete the property
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007262}
7263
7264
7265THREADED_TEST(Deleter) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00007266 v8::Isolate* isolate = CcTest::isolate();
7267 v8::HandleScope scope(isolate);
7268 v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007269 obj->SetNamedPropertyHandler(NoBlockGetterX, NULL, NULL, PDeleter, NULL);
7270 obj->SetIndexedPropertyHandler(NoBlockGetterI, NULL, NULL, IDeleter, NULL);
7271 LocalContext context;
7272 context->Global()->Set(v8_str("k"), obj->NewInstance());
7273 CompileRun(
7274 "k.foo = 'foo';"
7275 "k.bar = 'bar';"
7276 "k[2] = 2;"
7277 "k[4] = 4;");
7278 CHECK(v8_compile("delete k.foo")->Run()->IsFalse());
7279 CHECK(v8_compile("delete k.bar")->Run()->IsTrue());
7280
7281 CHECK_EQ(v8_compile("k.foo")->Run(), v8_str("foo"));
7282 CHECK(v8_compile("k.bar")->Run()->IsUndefined());
7283
7284 CHECK(v8_compile("delete k[2]")->Run()->IsFalse());
7285 CHECK(v8_compile("delete k[4]")->Run()->IsTrue());
7286
7287 CHECK_EQ(v8_compile("k[2]")->Run(), v8_num(2));
7288 CHECK(v8_compile("k[4]")->Run()->IsUndefined());
7289}
7290
7291
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007292static void GetK(Local<String> name,
7293 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007294 ApiTestFuzzer::Fuzz();
ager@chromium.org65dad4b2009-04-23 08:48:43 +00007295 if (name->Equals(v8_str("foo")) ||
7296 name->Equals(v8_str("bar")) ||
7297 name->Equals(v8_str("baz"))) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007298 info.GetReturnValue().SetUndefined();
ager@chromium.org65dad4b2009-04-23 08:48:43 +00007299 }
ager@chromium.org65dad4b2009-04-23 08:48:43 +00007300}
7301
7302
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007303static void IndexedGetK(uint32_t index,
7304 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.org65dad4b2009-04-23 08:48:43 +00007305 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007306 if (index == 0 || index == 1) info.GetReturnValue().SetUndefined();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007307}
7308
7309
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007310static void NamedEnum(const v8::PropertyCallbackInfo<v8::Array>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007311 ApiTestFuzzer::Fuzz();
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00007312 v8::Handle<v8::Array> result = v8::Array::New(info.GetIsolate(), 3);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007313 result->Set(v8::Integer::New(info.GetIsolate(), 0), v8_str("foo"));
7314 result->Set(v8::Integer::New(info.GetIsolate(), 1), v8_str("bar"));
7315 result->Set(v8::Integer::New(info.GetIsolate(), 2), v8_str("baz"));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007316 info.GetReturnValue().Set(result);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007317}
7318
7319
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007320static void IndexedEnum(const v8::PropertyCallbackInfo<v8::Array>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007321 ApiTestFuzzer::Fuzz();
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00007322 v8::Handle<v8::Array> result = v8::Array::New(info.GetIsolate(), 2);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007323 result->Set(v8::Integer::New(info.GetIsolate(), 0), v8_str("0"));
7324 result->Set(v8::Integer::New(info.GetIsolate(), 1), v8_str("1"));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007325 info.GetReturnValue().Set(result);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007326}
7327
7328
7329THREADED_TEST(Enumerators) {
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007330 v8::Isolate* isolate = CcTest::isolate();
7331 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00007332 v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007333 obj->SetNamedPropertyHandler(GetK, NULL, NULL, NULL, NamedEnum);
ager@chromium.org65dad4b2009-04-23 08:48:43 +00007334 obj->SetIndexedPropertyHandler(IndexedGetK, NULL, NULL, NULL, IndexedEnum);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007335 LocalContext context;
7336 context->Global()->Set(v8_str("k"), obj->NewInstance());
7337 v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
ager@chromium.org65dad4b2009-04-23 08:48:43 +00007338 "k[10] = 0;"
7339 "k.a = 0;"
7340 "k[5] = 0;"
7341 "k.b = 0;"
7342 "k[4294967295] = 0;"
7343 "k.c = 0;"
7344 "k[4294967296] = 0;"
7345 "k.d = 0;"
7346 "k[140000] = 0;"
7347 "k.e = 0;"
7348 "k[30000000000] = 0;"
7349 "k.f = 0;"
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007350 "var result = [];"
7351 "for (var prop in k) {"
7352 " result.push(prop);"
7353 "}"
7354 "result"));
ager@chromium.org65dad4b2009-04-23 08:48:43 +00007355 // Check that we get all the property names returned including the
7356 // ones from the enumerators in the right order: indexed properties
7357 // in numerical order, indexed interceptor properties, named
7358 // properties in insertion order, named interceptor properties.
7359 // This order is not mandated by the spec, so this test is just
7360 // documenting our behavior.
7361 CHECK_EQ(17, result->Length());
7362 // Indexed properties in numerical order.
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007363 CHECK_EQ(v8_str("5"), result->Get(v8::Integer::New(isolate, 0)));
7364 CHECK_EQ(v8_str("10"), result->Get(v8::Integer::New(isolate, 1)));
7365 CHECK_EQ(v8_str("140000"), result->Get(v8::Integer::New(isolate, 2)));
7366 CHECK_EQ(v8_str("4294967295"), result->Get(v8::Integer::New(isolate, 3)));
ager@chromium.org65dad4b2009-04-23 08:48:43 +00007367 // Indexed interceptor properties in the order they are returned
7368 // from the enumerator interceptor.
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007369 CHECK_EQ(v8_str("0"), result->Get(v8::Integer::New(isolate, 4)));
7370 CHECK_EQ(v8_str("1"), result->Get(v8::Integer::New(isolate, 5)));
ager@chromium.org65dad4b2009-04-23 08:48:43 +00007371 // Named properties in insertion order.
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007372 CHECK_EQ(v8_str("a"), result->Get(v8::Integer::New(isolate, 6)));
7373 CHECK_EQ(v8_str("b"), result->Get(v8::Integer::New(isolate, 7)));
7374 CHECK_EQ(v8_str("c"), result->Get(v8::Integer::New(isolate, 8)));
7375 CHECK_EQ(v8_str("4294967296"), result->Get(v8::Integer::New(isolate, 9)));
7376 CHECK_EQ(v8_str("d"), result->Get(v8::Integer::New(isolate, 10)));
7377 CHECK_EQ(v8_str("e"), result->Get(v8::Integer::New(isolate, 11)));
7378 CHECK_EQ(v8_str("30000000000"), result->Get(v8::Integer::New(isolate, 12)));
7379 CHECK_EQ(v8_str("f"), result->Get(v8::Integer::New(isolate, 13)));
ager@chromium.org65dad4b2009-04-23 08:48:43 +00007380 // Named interceptor properties.
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007381 CHECK_EQ(v8_str("foo"), result->Get(v8::Integer::New(isolate, 14)));
7382 CHECK_EQ(v8_str("bar"), result->Get(v8::Integer::New(isolate, 15)));
7383 CHECK_EQ(v8_str("baz"), result->Get(v8::Integer::New(isolate, 16)));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007384}
7385
7386
7387int p_getter_count;
7388int p_getter_count2;
7389
7390
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007391static void PGetter(Local<String> name,
7392 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007393 ApiTestFuzzer::Fuzz();
7394 p_getter_count++;
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007395 v8::Handle<v8::Object> global =
7396 info.GetIsolate()->GetCurrentContext()->Global();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007397 CHECK_EQ(info.Holder(), global->Get(v8_str("o1")));
7398 if (name->Equals(v8_str("p1"))) {
7399 CHECK_EQ(info.This(), global->Get(v8_str("o1")));
7400 } else if (name->Equals(v8_str("p2"))) {
7401 CHECK_EQ(info.This(), global->Get(v8_str("o2")));
7402 } else if (name->Equals(v8_str("p3"))) {
7403 CHECK_EQ(info.This(), global->Get(v8_str("o3")));
7404 } else if (name->Equals(v8_str("p4"))) {
7405 CHECK_EQ(info.This(), global->Get(v8_str("o4")));
7406 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007407}
7408
7409
7410static void RunHolderTest(v8::Handle<v8::ObjectTemplate> obj) {
7411 ApiTestFuzzer::Fuzz();
7412 LocalContext context;
7413 context->Global()->Set(v8_str("o1"), obj->NewInstance());
7414 CompileRun(
7415 "o1.__proto__ = { };"
7416 "var o2 = { __proto__: o1 };"
7417 "var o3 = { __proto__: o2 };"
7418 "var o4 = { __proto__: o3 };"
7419 "for (var i = 0; i < 10; i++) o4.p4;"
7420 "for (var i = 0; i < 10; i++) o3.p3;"
7421 "for (var i = 0; i < 10; i++) o2.p2;"
7422 "for (var i = 0; i < 10; i++) o1.p1;");
7423}
7424
7425
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007426static void PGetter2(Local<String> name,
7427 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007428 ApiTestFuzzer::Fuzz();
7429 p_getter_count2++;
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007430 v8::Handle<v8::Object> global =
7431 info.GetIsolate()->GetCurrentContext()->Global();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007432 CHECK_EQ(info.Holder(), global->Get(v8_str("o1")));
7433 if (name->Equals(v8_str("p1"))) {
7434 CHECK_EQ(info.This(), global->Get(v8_str("o1")));
7435 } else if (name->Equals(v8_str("p2"))) {
7436 CHECK_EQ(info.This(), global->Get(v8_str("o2")));
7437 } else if (name->Equals(v8_str("p3"))) {
7438 CHECK_EQ(info.This(), global->Get(v8_str("o3")));
7439 } else if (name->Equals(v8_str("p4"))) {
7440 CHECK_EQ(info.This(), global->Get(v8_str("o4")));
7441 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007442}
7443
7444
7445THREADED_TEST(GetterHolders) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00007446 v8::Isolate* isolate = CcTest::isolate();
7447 v8::HandleScope scope(isolate);
7448 v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007449 obj->SetAccessor(v8_str("p1"), PGetter);
7450 obj->SetAccessor(v8_str("p2"), PGetter);
7451 obj->SetAccessor(v8_str("p3"), PGetter);
7452 obj->SetAccessor(v8_str("p4"), PGetter);
7453 p_getter_count = 0;
7454 RunHolderTest(obj);
7455 CHECK_EQ(40, p_getter_count);
7456}
7457
7458
7459THREADED_TEST(PreInterceptorHolders) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00007460 v8::Isolate* isolate = CcTest::isolate();
7461 v8::HandleScope scope(isolate);
7462 v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007463 obj->SetNamedPropertyHandler(PGetter2);
7464 p_getter_count2 = 0;
7465 RunHolderTest(obj);
7466 CHECK_EQ(40, p_getter_count2);
7467}
7468
7469
7470THREADED_TEST(ObjectInstantiation) {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00007471 v8::Isolate* isolate = CcTest::isolate();
7472 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00007473 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007474 templ->SetAccessor(v8_str("t"), PGetter2);
7475 LocalContext context;
7476 context->Global()->Set(v8_str("o"), templ->NewInstance());
7477 for (int i = 0; i < 100; i++) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007478 v8::HandleScope inner_scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007479 v8::Handle<v8::Object> obj = templ->NewInstance();
7480 CHECK_NE(obj, context->Global()->Get(v8_str("o")));
7481 context->Global()->Set(v8_str("o2"), obj);
7482 v8::Handle<Value> value =
7483 Script::Compile(v8_str("o.__proto__ === o2.__proto__"))->Run();
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00007484 CHECK_EQ(v8::True(isolate), value);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007485 context->Global()->Set(v8_str("o"), obj);
7486 }
7487}
7488
7489
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007490static int StrCmp16(uint16_t* a, uint16_t* b) {
7491 while (true) {
7492 if (*a == 0 && *b == 0) return 0;
7493 if (*a != *b) return 0 + *a - *b;
7494 a++;
7495 b++;
7496 }
7497}
7498
7499
7500static int StrNCmp16(uint16_t* a, uint16_t* b, int n) {
7501 while (true) {
7502 if (n-- == 0) return 0;
7503 if (*a == 0 && *b == 0) return 0;
7504 if (*a != *b) return 0 + *a - *b;
7505 a++;
7506 b++;
7507 }
7508}
7509
7510
yangguo@chromium.org154ff992012-03-13 08:09:54 +00007511int GetUtf8Length(Handle<String> str) {
7512 int len = str->Utf8Length();
7513 if (len < 0) {
7514 i::Handle<i::String> istr(v8::Utils::OpenHandle(*str));
7515 i::FlattenString(istr);
7516 len = str->Utf8Length();
7517 }
7518 return len;
7519}
7520
7521
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007522THREADED_TEST(StringWrite) {
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007523 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00007524 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007525 v8::Handle<String> str = v8_str("abcde");
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007526 // abc<Icelandic eth><Unicode snowman>.
7527 v8::Handle<String> str2 = v8_str("abc\303\260\342\230\203");
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00007528 v8::Handle<String> str3 = v8::String::NewFromUtf8(
7529 context->GetIsolate(), "abc\0def", v8::String::kNormalString, 7);
machenbach@chromium.orgc8cbc432014-01-21 09:01:57 +00007530 // "ab" + lead surrogate + "cd" + trail surrogate + "ef"
7531 uint16_t orphans[8] = { 0x61, 0x62, 0xd800, 0x63, 0x64, 0xdc00, 0x65, 0x66 };
7532 v8::Handle<String> orphans_str = v8::String::NewFromTwoByte(
7533 context->GetIsolate(), orphans, v8::String::kNormalString, 8);
7534 // single lead surrogate
7535 uint16_t lead[1] = { 0xd800 };
7536 v8::Handle<String> lead_str = v8::String::NewFromTwoByte(
7537 context->GetIsolate(), lead, v8::String::kNormalString, 1);
7538 // single trail surrogate
7539 uint16_t trail[1] = { 0xdc00 };
7540 v8::Handle<String> trail_str = v8::String::NewFromTwoByte(
7541 context->GetIsolate(), trail, v8::String::kNormalString, 1);
7542 // surrogate pair
7543 uint16_t pair[2] = { 0xd800, 0xdc00 };
7544 v8::Handle<String> pair_str = v8::String::NewFromTwoByte(
7545 context->GetIsolate(), pair, v8::String::kNormalString, 2);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007546 const int kStride = 4; // Must match stride in for loops in JS below.
7547 CompileRun(
7548 "var left = '';"
7549 "for (var i = 0; i < 0xd800; i += 4) {"
7550 " left = left + String.fromCharCode(i);"
7551 "}");
7552 CompileRun(
7553 "var right = '';"
7554 "for (var i = 0; i < 0xd800; i += 4) {"
7555 " right = String.fromCharCode(i) + right;"
7556 "}");
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007557 v8::Handle<v8::Object> global = context->Global();
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007558 Handle<String> left_tree = global->Get(v8_str("left")).As<String>();
7559 Handle<String> right_tree = global->Get(v8_str("right")).As<String>();
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007560
7561 CHECK_EQ(5, str2->Length());
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007562 CHECK_EQ(0xd800 / kStride, left_tree->Length());
7563 CHECK_EQ(0xd800 / kStride, right_tree->Length());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007564
7565 char buf[100];
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007566 char utf8buf[0xd800 * 3];
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007567 uint16_t wbuf[100];
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007568 int len;
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007569 int charlen;
7570
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007571 memset(utf8buf, 0x1, 1000);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007572 len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007573 CHECK_EQ(9, len);
7574 CHECK_EQ(5, charlen);
7575 CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007576
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007577 memset(utf8buf, 0x1, 1000);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007578 len = str2->WriteUtf8(utf8buf, 8, &charlen);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007579 CHECK_EQ(8, len);
7580 CHECK_EQ(5, charlen);
7581 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203\1", 9));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007582
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007583 memset(utf8buf, 0x1, 1000);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007584 len = str2->WriteUtf8(utf8buf, 7, &charlen);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007585 CHECK_EQ(5, len);
7586 CHECK_EQ(4, charlen);
7587 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007588
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007589 memset(utf8buf, 0x1, 1000);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007590 len = str2->WriteUtf8(utf8buf, 6, &charlen);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007591 CHECK_EQ(5, len);
7592 CHECK_EQ(4, charlen);
7593 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007594
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007595 memset(utf8buf, 0x1, 1000);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007596 len = str2->WriteUtf8(utf8buf, 5, &charlen);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007597 CHECK_EQ(5, len);
7598 CHECK_EQ(4, charlen);
7599 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007600
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007601 memset(utf8buf, 0x1, 1000);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007602 len = str2->WriteUtf8(utf8buf, 4, &charlen);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007603 CHECK_EQ(3, len);
7604 CHECK_EQ(3, charlen);
7605 CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007606
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007607 memset(utf8buf, 0x1, 1000);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007608 len = str2->WriteUtf8(utf8buf, 3, &charlen);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007609 CHECK_EQ(3, len);
7610 CHECK_EQ(3, charlen);
7611 CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007612
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007613 memset(utf8buf, 0x1, 1000);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007614 len = str2->WriteUtf8(utf8buf, 2, &charlen);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007615 CHECK_EQ(2, len);
7616 CHECK_EQ(2, charlen);
7617 CHECK_EQ(0, strncmp(utf8buf, "ab\1", 3));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007618
machenbach@chromium.orgc8cbc432014-01-21 09:01:57 +00007619 // allow orphan surrogates by default
7620 memset(utf8buf, 0x1, 1000);
7621 len = orphans_str->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen);
7622 CHECK_EQ(13, len);
7623 CHECK_EQ(8, charlen);
7624 CHECK_EQ(0, strcmp(utf8buf, "ab\355\240\200cd\355\260\200ef"));
7625
7626 // replace orphan surrogates with unicode replacement character
7627 memset(utf8buf, 0x1, 1000);
7628 len = orphans_str->WriteUtf8(utf8buf,
7629 sizeof(utf8buf),
7630 &charlen,
7631 String::REPLACE_INVALID_UTF8);
7632 CHECK_EQ(13, len);
7633 CHECK_EQ(8, charlen);
7634 CHECK_EQ(0, strcmp(utf8buf, "ab\357\277\275cd\357\277\275ef"));
7635
7636 // replace single lead surrogate with unicode replacement character
7637 memset(utf8buf, 0x1, 1000);
7638 len = lead_str->WriteUtf8(utf8buf,
7639 sizeof(utf8buf),
7640 &charlen,
7641 String::REPLACE_INVALID_UTF8);
7642 CHECK_EQ(4, len);
7643 CHECK_EQ(1, charlen);
7644 CHECK_EQ(0, strcmp(utf8buf, "\357\277\275"));
7645
7646 // replace single trail surrogate with unicode replacement character
7647 memset(utf8buf, 0x1, 1000);
7648 len = trail_str->WriteUtf8(utf8buf,
7649 sizeof(utf8buf),
7650 &charlen,
7651 String::REPLACE_INVALID_UTF8);
7652 CHECK_EQ(4, len);
7653 CHECK_EQ(1, charlen);
7654 CHECK_EQ(0, strcmp(utf8buf, "\357\277\275"));
7655
7656 // do not replace / write anything if surrogate pair does not fit the buffer
7657 // space
7658 memset(utf8buf, 0x1, 1000);
7659 len = pair_str->WriteUtf8(utf8buf,
7660 3,
7661 &charlen,
7662 String::REPLACE_INVALID_UTF8);
7663 CHECK_EQ(0, len);
7664 CHECK_EQ(0, charlen);
7665
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007666 memset(utf8buf, 0x1, sizeof(utf8buf));
yangguo@chromium.org154ff992012-03-13 08:09:54 +00007667 len = GetUtf8Length(left_tree);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007668 int utf8_expected =
7669 (0x80 + (0x800 - 0x80) * 2 + (0xd800 - 0x800) * 3) / kStride;
7670 CHECK_EQ(utf8_expected, len);
7671 len = left_tree->WriteUtf8(utf8buf, utf8_expected, &charlen);
7672 CHECK_EQ(utf8_expected, len);
7673 CHECK_EQ(0xd800 / kStride, charlen);
7674 CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[utf8_expected - 3]));
7675 CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[utf8_expected - 2]));
7676 CHECK_EQ(0xc0 - kStride,
7677 static_cast<unsigned char>(utf8buf[utf8_expected - 1]));
7678 CHECK_EQ(1, utf8buf[utf8_expected]);
7679
7680 memset(utf8buf, 0x1, sizeof(utf8buf));
yangguo@chromium.org154ff992012-03-13 08:09:54 +00007681 len = GetUtf8Length(right_tree);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007682 CHECK_EQ(utf8_expected, len);
7683 len = right_tree->WriteUtf8(utf8buf, utf8_expected, &charlen);
7684 CHECK_EQ(utf8_expected, len);
7685 CHECK_EQ(0xd800 / kStride, charlen);
7686 CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[0]));
7687 CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[1]));
7688 CHECK_EQ(0xc0 - kStride, static_cast<unsigned char>(utf8buf[2]));
7689 CHECK_EQ(1, utf8buf[utf8_expected]);
7690
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007691 memset(buf, 0x1, sizeof(buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007692 memset(wbuf, 0x1, sizeof(wbuf));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007693 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007694 CHECK_EQ(5, len);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007695 len = str->Write(wbuf);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007696 CHECK_EQ(5, len);
7697 CHECK_EQ(0, strcmp("abcde", buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007698 uint16_t answer1[] = {'a', 'b', 'c', 'd', 'e', '\0'};
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007699 CHECK_EQ(0, StrCmp16(answer1, wbuf));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007700
7701 memset(buf, 0x1, sizeof(buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007702 memset(wbuf, 0x1, sizeof(wbuf));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007703 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 4);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007704 CHECK_EQ(4, len);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007705 len = str->Write(wbuf, 0, 4);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007706 CHECK_EQ(4, len);
7707 CHECK_EQ(0, strncmp("abcd\1", buf, 5));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007708 uint16_t answer2[] = {'a', 'b', 'c', 'd', 0x101};
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007709 CHECK_EQ(0, StrNCmp16(answer2, wbuf, 5));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007710
7711 memset(buf, 0x1, sizeof(buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007712 memset(wbuf, 0x1, sizeof(wbuf));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007713 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 5);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007714 CHECK_EQ(5, len);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007715 len = str->Write(wbuf, 0, 5);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007716 CHECK_EQ(5, len);
7717 CHECK_EQ(0, strncmp("abcde\1", buf, 6));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007718 uint16_t answer3[] = {'a', 'b', 'c', 'd', 'e', 0x101};
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007719 CHECK_EQ(0, StrNCmp16(answer3, wbuf, 6));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007720
7721 memset(buf, 0x1, sizeof(buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007722 memset(wbuf, 0x1, sizeof(wbuf));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007723 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 6);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007724 CHECK_EQ(5, len);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007725 len = str->Write(wbuf, 0, 6);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007726 CHECK_EQ(5, len);
7727 CHECK_EQ(0, strcmp("abcde", buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007728 uint16_t answer4[] = {'a', 'b', 'c', 'd', 'e', '\0'};
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007729 CHECK_EQ(0, StrCmp16(answer4, wbuf));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007730
7731 memset(buf, 0x1, sizeof(buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007732 memset(wbuf, 0x1, sizeof(wbuf));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007733 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, -1);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007734 CHECK_EQ(1, len);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007735 len = str->Write(wbuf, 4, -1);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007736 CHECK_EQ(1, len);
7737 CHECK_EQ(0, strcmp("e", buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007738 uint16_t answer5[] = {'e', '\0'};
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007739 CHECK_EQ(0, StrCmp16(answer5, wbuf));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007740
7741 memset(buf, 0x1, sizeof(buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007742 memset(wbuf, 0x1, sizeof(wbuf));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007743 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, 6);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007744 CHECK_EQ(1, len);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007745 len = str->Write(wbuf, 4, 6);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007746 CHECK_EQ(1, len);
7747 CHECK_EQ(0, strcmp("e", buf));
7748 CHECK_EQ(0, StrCmp16(answer5, wbuf));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007749
7750 memset(buf, 0x1, sizeof(buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007751 memset(wbuf, 0x1, sizeof(wbuf));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007752 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, 1);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007753 CHECK_EQ(1, len);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007754 len = str->Write(wbuf, 4, 1);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007755 CHECK_EQ(1, len);
7756 CHECK_EQ(0, strncmp("e\1", buf, 2));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007757 uint16_t answer6[] = {'e', 0x101};
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007758 CHECK_EQ(0, StrNCmp16(answer6, wbuf, 2));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007759
7760 memset(buf, 0x1, sizeof(buf));
7761 memset(wbuf, 0x1, sizeof(wbuf));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007762 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 3, 1);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007763 CHECK_EQ(1, len);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007764 len = str->Write(wbuf, 3, 1);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007765 CHECK_EQ(1, len);
7766 CHECK_EQ(0, strncmp("d\1", buf, 2));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007767 uint16_t answer7[] = {'d', 0x101};
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007768 CHECK_EQ(0, StrNCmp16(answer7, wbuf, 2));
ricow@chromium.orgddd545c2011-08-24 12:02:41 +00007769
7770 memset(wbuf, 0x1, sizeof(wbuf));
7771 wbuf[5] = 'X';
7772 len = str->Write(wbuf, 0, 6, String::NO_NULL_TERMINATION);
7773 CHECK_EQ(5, len);
7774 CHECK_EQ('X', wbuf[5]);
7775 uint16_t answer8a[] = {'a', 'b', 'c', 'd', 'e'};
7776 uint16_t answer8b[] = {'a', 'b', 'c', 'd', 'e', '\0'};
7777 CHECK_EQ(0, StrNCmp16(answer8a, wbuf, 5));
7778 CHECK_NE(0, StrCmp16(answer8b, wbuf));
7779 wbuf[5] = '\0';
7780 CHECK_EQ(0, StrCmp16(answer8b, wbuf));
7781
7782 memset(buf, 0x1, sizeof(buf));
7783 buf[5] = 'X';
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007784 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf),
7785 0,
7786 6,
7787 String::NO_NULL_TERMINATION);
ricow@chromium.orgddd545c2011-08-24 12:02:41 +00007788 CHECK_EQ(5, len);
7789 CHECK_EQ('X', buf[5]);
7790 CHECK_EQ(0, strncmp("abcde", buf, 5));
7791 CHECK_NE(0, strcmp("abcde", buf));
7792 buf[5] = '\0';
7793 CHECK_EQ(0, strcmp("abcde", buf));
7794
7795 memset(utf8buf, 0x1, sizeof(utf8buf));
7796 utf8buf[8] = 'X';
7797 len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen,
7798 String::NO_NULL_TERMINATION);
7799 CHECK_EQ(8, len);
7800 CHECK_EQ('X', utf8buf[8]);
7801 CHECK_EQ(5, charlen);
7802 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203", 8));
7803 CHECK_NE(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
7804 utf8buf[8] = '\0';
7805 CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
yangguo@chromium.org304cc332012-07-24 07:59:48 +00007806
7807 memset(utf8buf, 0x1, sizeof(utf8buf));
7808 utf8buf[5] = 'X';
7809 len = str->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen,
7810 String::NO_NULL_TERMINATION);
7811 CHECK_EQ(5, len);
7812 CHECK_EQ('X', utf8buf[5]); // Test that the sixth character is untouched.
7813 CHECK_EQ(5, charlen);
7814 utf8buf[5] = '\0';
7815 CHECK_EQ(0, strcmp(utf8buf, "abcde"));
7816
7817 memset(buf, 0x1, sizeof(buf));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007818 len = str3->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
yangguo@chromium.org304cc332012-07-24 07:59:48 +00007819 CHECK_EQ(7, len);
7820 CHECK_EQ(0, strcmp("abc", buf));
7821 CHECK_EQ(0, buf[3]);
7822 CHECK_EQ(0, strcmp("def", buf + 4));
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00007823
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007824 CHECK_EQ(0, str->WriteOneByte(NULL, 0, 0, String::NO_NULL_TERMINATION));
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00007825 CHECK_EQ(0, str->WriteUtf8(NULL, 0, 0, String::NO_NULL_TERMINATION));
7826 CHECK_EQ(0, str->Write(NULL, 0, 0, String::NO_NULL_TERMINATION));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007827}
7828
7829
yangguo@chromium.org154ff992012-03-13 08:09:54 +00007830static void Utf16Helper(
7831 LocalContext& context,
7832 const char* name,
7833 const char* lengths_name,
7834 int len) {
7835 Local<v8::Array> a =
7836 Local<v8::Array>::Cast(context->Global()->Get(v8_str(name)));
7837 Local<v8::Array> alens =
7838 Local<v8::Array>::Cast(context->Global()->Get(v8_str(lengths_name)));
7839 for (int i = 0; i < len; i++) {
7840 Local<v8::String> string =
7841 Local<v8::String>::Cast(a->Get(i));
7842 Local<v8::Number> expected_len =
7843 Local<v8::Number>::Cast(alens->Get(i));
7844 int length = GetUtf8Length(string);
7845 CHECK_EQ(static_cast<int>(expected_len->Value()), length);
7846 }
7847}
7848
7849
7850static uint16_t StringGet(Handle<String> str, int index) {
7851 i::Handle<i::String> istring =
7852 v8::Utils::OpenHandle(String::Cast(*str));
7853 return istring->Get(index);
7854}
7855
7856
7857static void WriteUtf8Helper(
7858 LocalContext& context,
7859 const char* name,
7860 const char* lengths_name,
7861 int len) {
7862 Local<v8::Array> b =
7863 Local<v8::Array>::Cast(context->Global()->Get(v8_str(name)));
7864 Local<v8::Array> alens =
7865 Local<v8::Array>::Cast(context->Global()->Get(v8_str(lengths_name)));
7866 char buffer[1000];
7867 char buffer2[1000];
7868 for (int i = 0; i < len; i++) {
7869 Local<v8::String> string =
7870 Local<v8::String>::Cast(b->Get(i));
7871 Local<v8::Number> expected_len =
7872 Local<v8::Number>::Cast(alens->Get(i));
7873 int utf8_length = static_cast<int>(expected_len->Value());
7874 for (int j = utf8_length + 1; j >= 0; j--) {
7875 memset(reinterpret_cast<void*>(&buffer), 42, sizeof(buffer));
7876 memset(reinterpret_cast<void*>(&buffer2), 42, sizeof(buffer2));
7877 int nchars;
7878 int utf8_written =
7879 string->WriteUtf8(buffer, j, &nchars, String::NO_OPTIONS);
7880 int utf8_written2 =
7881 string->WriteUtf8(buffer2, j, &nchars, String::NO_NULL_TERMINATION);
7882 CHECK_GE(utf8_length + 1, utf8_written);
7883 CHECK_GE(utf8_length, utf8_written2);
7884 for (int k = 0; k < utf8_written2; k++) {
7885 CHECK_EQ(buffer[k], buffer2[k]);
7886 }
7887 CHECK(nchars * 3 >= utf8_written - 1);
7888 CHECK(nchars <= utf8_written);
7889 if (j == utf8_length + 1) {
7890 CHECK_EQ(utf8_written2, utf8_length);
7891 CHECK_EQ(utf8_written2 + 1, utf8_written);
7892 }
7893 CHECK_EQ(buffer[utf8_written], 42);
7894 if (j > utf8_length) {
7895 if (utf8_written != 0) CHECK_EQ(buffer[utf8_written - 1], 0);
7896 if (utf8_written > 1) CHECK_NE(buffer[utf8_written - 2], 42);
7897 Handle<String> roundtrip = v8_str(buffer);
7898 CHECK(roundtrip->Equals(string));
7899 } else {
7900 if (utf8_written != 0) CHECK_NE(buffer[utf8_written - 1], 42);
7901 }
7902 if (utf8_written2 != 0) CHECK_NE(buffer[utf8_written - 1], 42);
7903 if (nchars >= 2) {
7904 uint16_t trail = StringGet(string, nchars - 1);
7905 uint16_t lead = StringGet(string, nchars - 2);
7906 if (((lead & 0xfc00) == 0xd800) &&
7907 ((trail & 0xfc00) == 0xdc00)) {
7908 unsigned char u1 = buffer2[utf8_written2 - 4];
7909 unsigned char u2 = buffer2[utf8_written2 - 3];
7910 unsigned char u3 = buffer2[utf8_written2 - 2];
7911 unsigned char u4 = buffer2[utf8_written2 - 1];
7912 CHECK_EQ((u1 & 0xf8), 0xf0);
7913 CHECK_EQ((u2 & 0xc0), 0x80);
7914 CHECK_EQ((u3 & 0xc0), 0x80);
7915 CHECK_EQ((u4 & 0xc0), 0x80);
7916 uint32_t c = 0x10000 + ((lead & 0x3ff) << 10) + (trail & 0x3ff);
7917 CHECK_EQ((u4 & 0x3f), (c & 0x3f));
7918 CHECK_EQ((u3 & 0x3f), ((c >> 6) & 0x3f));
7919 CHECK_EQ((u2 & 0x3f), ((c >> 12) & 0x3f));
7920 CHECK_EQ((u1 & 0x3), c >> 18);
7921 }
7922 }
7923 }
7924 }
7925}
7926
7927
7928THREADED_TEST(Utf16) {
7929 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00007930 v8::HandleScope scope(context->GetIsolate());
yangguo@chromium.org154ff992012-03-13 08:09:54 +00007931 CompileRun(
7932 "var pad = '01234567890123456789';"
7933 "var p = [];"
7934 "var plens = [20, 3, 3];"
7935 "p.push('01234567890123456789');"
7936 "var lead = 0xd800;"
7937 "var trail = 0xdc00;"
7938 "p.push(String.fromCharCode(0xd800));"
7939 "p.push(String.fromCharCode(0xdc00));"
7940 "var a = [];"
7941 "var b = [];"
danno@chromium.org88aa0582012-03-23 15:11:57 +00007942 "var c = [];"
yangguo@chromium.org154ff992012-03-13 08:09:54 +00007943 "var alens = [];"
7944 "for (var i = 0; i < 3; i++) {"
7945 " p[1] = String.fromCharCode(lead++);"
7946 " for (var j = 0; j < 3; j++) {"
7947 " p[2] = String.fromCharCode(trail++);"
7948 " a.push(p[i] + p[j]);"
7949 " b.push(p[i] + p[j]);"
danno@chromium.org88aa0582012-03-23 15:11:57 +00007950 " c.push(p[i] + p[j]);"
yangguo@chromium.org154ff992012-03-13 08:09:54 +00007951 " alens.push(plens[i] + plens[j]);"
7952 " }"
7953 "}"
7954 "alens[5] -= 2;" // Here the surrogate pairs match up.
7955 "var a2 = [];"
7956 "var b2 = [];"
danno@chromium.org88aa0582012-03-23 15:11:57 +00007957 "var c2 = [];"
yangguo@chromium.org154ff992012-03-13 08:09:54 +00007958 "var a2lens = [];"
7959 "for (var m = 0; m < 9; m++) {"
7960 " for (var n = 0; n < 9; n++) {"
7961 " a2.push(a[m] + a[n]);"
7962 " b2.push(b[m] + b[n]);"
danno@chromium.org88aa0582012-03-23 15:11:57 +00007963 " var newc = 'x' + c[m] + c[n] + 'y';"
7964 " c2.push(newc.substring(1, newc.length - 1));"
yangguo@chromium.org154ff992012-03-13 08:09:54 +00007965 " var utf = alens[m] + alens[n];" // And here.
7966 // The 'n's that start with 0xdc.. are 6-8
7967 // The 'm's that end with 0xd8.. are 1, 4 and 7
7968 " if ((m % 3) == 1 && n >= 6) utf -= 2;"
7969 " a2lens.push(utf);"
7970 " }"
7971 "}");
7972 Utf16Helper(context, "a", "alens", 9);
7973 Utf16Helper(context, "a2", "a2lens", 81);
7974 WriteUtf8Helper(context, "b", "alens", 9);
7975 WriteUtf8Helper(context, "b2", "a2lens", 81);
danno@chromium.org88aa0582012-03-23 15:11:57 +00007976 WriteUtf8Helper(context, "c2", "a2lens", 81);
yangguo@chromium.org154ff992012-03-13 08:09:54 +00007977}
7978
7979
7980static bool SameSymbol(Handle<String> s1, Handle<String> s2) {
7981 i::Handle<i::String> is1(v8::Utils::OpenHandle(*s1));
7982 i::Handle<i::String> is2(v8::Utils::OpenHandle(*s2));
7983 return *is1 == *is2;
7984}
7985
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00007986static void SameSymbolHelper(v8::Isolate* isolate, const char* a,
7987 const char* b) {
7988 Handle<String> symbol1 =
7989 v8::String::NewFromUtf8(isolate, a, v8::String::kInternalizedString);
7990 Handle<String> symbol2 =
7991 v8::String::NewFromUtf8(isolate, b, v8::String::kInternalizedString);
yangguo@chromium.org154ff992012-03-13 08:09:54 +00007992 CHECK(SameSymbol(symbol1, symbol2));
7993}
7994
7995
7996THREADED_TEST(Utf16Symbol) {
7997 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00007998 v8::HandleScope scope(context->GetIsolate());
yangguo@chromium.org154ff992012-03-13 08:09:54 +00007999
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00008000 Handle<String> symbol1 = v8::String::NewFromUtf8(
8001 context->GetIsolate(), "abc", v8::String::kInternalizedString);
8002 Handle<String> symbol2 = v8::String::NewFromUtf8(
8003 context->GetIsolate(), "abc", v8::String::kInternalizedString);
yangguo@chromium.org154ff992012-03-13 08:09:54 +00008004 CHECK(SameSymbol(symbol1, symbol2));
8005
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00008006 SameSymbolHelper(context->GetIsolate(),
8007 "\360\220\220\205", // 4 byte encoding.
yangguo@chromium.org154ff992012-03-13 08:09:54 +00008008 "\355\240\201\355\260\205"); // 2 3-byte surrogates.
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00008009 SameSymbolHelper(context->GetIsolate(),
8010 "\355\240\201\355\260\206", // 2 3-byte surrogates.
yangguo@chromium.org154ff992012-03-13 08:09:54 +00008011 "\360\220\220\206"); // 4 byte encoding.
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00008012 SameSymbolHelper(context->GetIsolate(),
8013 "x\360\220\220\205", // 4 byte encoding.
yangguo@chromium.org154ff992012-03-13 08:09:54 +00008014 "x\355\240\201\355\260\205"); // 2 3-byte surrogates.
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00008015 SameSymbolHelper(context->GetIsolate(),
8016 "x\355\240\201\355\260\206", // 2 3-byte surrogates.
yangguo@chromium.org154ff992012-03-13 08:09:54 +00008017 "x\360\220\220\206"); // 4 byte encoding.
8018 CompileRun(
8019 "var sym0 = 'benedictus';"
8020 "var sym0b = 'S\303\270ren';"
8021 "var sym1 = '\355\240\201\355\260\207';"
8022 "var sym2 = '\360\220\220\210';"
8023 "var sym3 = 'x\355\240\201\355\260\207';"
8024 "var sym4 = 'x\360\220\220\210';"
8025 "if (sym1.length != 2) throw sym1;"
8026 "if (sym1.charCodeAt(1) != 0xdc07) throw sym1.charCodeAt(1);"
8027 "if (sym2.length != 2) throw sym2;"
8028 "if (sym2.charCodeAt(1) != 0xdc08) throw sym2.charCodeAt(2);"
8029 "if (sym3.length != 3) throw sym3;"
8030 "if (sym3.charCodeAt(2) != 0xdc07) throw sym1.charCodeAt(2);"
8031 "if (sym4.length != 3) throw sym4;"
8032 "if (sym4.charCodeAt(2) != 0xdc08) throw sym2.charCodeAt(2);");
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00008033 Handle<String> sym0 = v8::String::NewFromUtf8(
8034 context->GetIsolate(), "benedictus", v8::String::kInternalizedString);
8035 Handle<String> sym0b = v8::String::NewFromUtf8(
8036 context->GetIsolate(), "S\303\270ren", v8::String::kInternalizedString);
8037 Handle<String> sym1 =
8038 v8::String::NewFromUtf8(context->GetIsolate(), "\355\240\201\355\260\207",
8039 v8::String::kInternalizedString);
8040 Handle<String> sym2 =
8041 v8::String::NewFromUtf8(context->GetIsolate(), "\360\220\220\210",
8042 v8::String::kInternalizedString);
8043 Handle<String> sym3 = v8::String::NewFromUtf8(
8044 context->GetIsolate(), "x\355\240\201\355\260\207",
8045 v8::String::kInternalizedString);
8046 Handle<String> sym4 =
8047 v8::String::NewFromUtf8(context->GetIsolate(), "x\360\220\220\210",
8048 v8::String::kInternalizedString);
yangguo@chromium.org154ff992012-03-13 08:09:54 +00008049 v8::Local<v8::Object> global = context->Global();
8050 Local<Value> s0 = global->Get(v8_str("sym0"));
8051 Local<Value> s0b = global->Get(v8_str("sym0b"));
8052 Local<Value> s1 = global->Get(v8_str("sym1"));
8053 Local<Value> s2 = global->Get(v8_str("sym2"));
8054 Local<Value> s3 = global->Get(v8_str("sym3"));
8055 Local<Value> s4 = global->Get(v8_str("sym4"));
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00008056 CHECK(SameSymbol(sym0, Handle<String>::Cast(s0)));
8057 CHECK(SameSymbol(sym0b, Handle<String>::Cast(s0b)));
8058 CHECK(SameSymbol(sym1, Handle<String>::Cast(s1)));
8059 CHECK(SameSymbol(sym2, Handle<String>::Cast(s2)));
8060 CHECK(SameSymbol(sym3, Handle<String>::Cast(s3)));
8061 CHECK(SameSymbol(sym4, Handle<String>::Cast(s4)));
yangguo@chromium.org154ff992012-03-13 08:09:54 +00008062}
8063
8064
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008065THREADED_TEST(ToArrayIndex) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008066 LocalContext context;
ulan@chromium.org0f13e742014-01-03 15:51:11 +00008067 v8::Isolate* isolate = context->GetIsolate();
8068 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008069
8070 v8::Handle<String> str = v8_str("42");
8071 v8::Handle<v8::Uint32> index = str->ToArrayIndex();
8072 CHECK(!index.IsEmpty());
8073 CHECK_EQ(42.0, index->Uint32Value());
8074 str = v8_str("42asdf");
8075 index = str->ToArrayIndex();
8076 CHECK(index.IsEmpty());
8077 str = v8_str("-42");
8078 index = str->ToArrayIndex();
8079 CHECK(index.IsEmpty());
8080 str = v8_str("4294967295");
8081 index = str->ToArrayIndex();
8082 CHECK(!index.IsEmpty());
8083 CHECK_EQ(4294967295.0, index->Uint32Value());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00008084 v8::Handle<v8::Number> num = v8::Number::New(isolate, 1);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008085 index = num->ToArrayIndex();
8086 CHECK(!index.IsEmpty());
8087 CHECK_EQ(1.0, index->Uint32Value());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00008088 num = v8::Number::New(isolate, -1);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008089 index = num->ToArrayIndex();
8090 CHECK(index.IsEmpty());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00008091 v8::Handle<v8::Object> obj = v8::Object::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008092 index = obj->ToArrayIndex();
8093 CHECK(index.IsEmpty());
8094}
8095
8096
8097THREADED_TEST(ErrorConstruction) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008098 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008099 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008100
8101 v8::Handle<String> foo = v8_str("foo");
8102 v8::Handle<String> message = v8_str("message");
8103 v8::Handle<Value> range_error = v8::Exception::RangeError(foo);
8104 CHECK(range_error->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00008105 CHECK(range_error.As<v8::Object>()->Get(message)->Equals(foo));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008106 v8::Handle<Value> reference_error = v8::Exception::ReferenceError(foo);
8107 CHECK(reference_error->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00008108 CHECK(reference_error.As<v8::Object>()->Get(message)->Equals(foo));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008109 v8::Handle<Value> syntax_error = v8::Exception::SyntaxError(foo);
8110 CHECK(syntax_error->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00008111 CHECK(syntax_error.As<v8::Object>()->Get(message)->Equals(foo));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008112 v8::Handle<Value> type_error = v8::Exception::TypeError(foo);
8113 CHECK(type_error->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00008114 CHECK(type_error.As<v8::Object>()->Get(message)->Equals(foo));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008115 v8::Handle<Value> error = v8::Exception::Error(foo);
8116 CHECK(error->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00008117 CHECK(error.As<v8::Object>()->Get(message)->Equals(foo));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008118}
8119
8120
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00008121static void YGetter(Local<String> name,
8122 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008123 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00008124 info.GetReturnValue().Set(v8_num(10));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008125}
8126
8127
8128static void YSetter(Local<String> name,
8129 Local<Value> value,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00008130 const v8::PropertyCallbackInfo<void>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008131 if (info.This()->Has(name)) {
8132 info.This()->Delete(name);
8133 }
8134 info.This()->Set(name, value);
8135}
8136
8137
8138THREADED_TEST(DeleteAccessor) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00008139 v8::Isolate* isolate = CcTest::isolate();
8140 v8::HandleScope scope(isolate);
8141 v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008142 obj->SetAccessor(v8_str("y"), YGetter, YSetter);
8143 LocalContext context;
8144 v8::Handle<v8::Object> holder = obj->NewInstance();
8145 context->Global()->Set(v8_str("holder"), holder);
8146 v8::Handle<Value> result = CompileRun(
8147 "holder.y = 11; holder.y = 12; holder.y");
8148 CHECK_EQ(12, result->Uint32Value());
8149}
8150
8151
8152THREADED_TEST(TypeSwitch) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00008153 v8::Isolate* isolate = CcTest::isolate();
8154 v8::HandleScope scope(isolate);
8155 v8::Handle<v8::FunctionTemplate> templ1 = v8::FunctionTemplate::New(isolate);
8156 v8::Handle<v8::FunctionTemplate> templ2 = v8::FunctionTemplate::New(isolate);
8157 v8::Handle<v8::FunctionTemplate> templ3 = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008158 v8::Handle<v8::FunctionTemplate> templs[3] = { templ1, templ2, templ3 };
8159 v8::Handle<v8::TypeSwitch> type_switch = v8::TypeSwitch::New(3, templs);
8160 LocalContext context;
ulan@chromium.org0f13e742014-01-03 15:51:11 +00008161 v8::Handle<v8::Object> obj0 = v8::Object::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008162 v8::Handle<v8::Object> obj1 = templ1->GetFunction()->NewInstance();
8163 v8::Handle<v8::Object> obj2 = templ2->GetFunction()->NewInstance();
8164 v8::Handle<v8::Object> obj3 = templ3->GetFunction()->NewInstance();
8165 for (int i = 0; i < 10; i++) {
8166 CHECK_EQ(0, type_switch->match(obj0));
8167 CHECK_EQ(1, type_switch->match(obj1));
8168 CHECK_EQ(2, type_switch->match(obj2));
8169 CHECK_EQ(3, type_switch->match(obj3));
8170 CHECK_EQ(3, type_switch->match(obj3));
8171 CHECK_EQ(2, type_switch->match(obj2));
8172 CHECK_EQ(1, type_switch->match(obj1));
8173 CHECK_EQ(0, type_switch->match(obj0));
8174 }
8175}
8176
8177
8178// For use within the TestSecurityHandler() test.
8179static bool g_security_callback_result = false;
8180static bool NamedSecurityTestCallback(Local<v8::Object> global,
8181 Local<Value> name,
8182 v8::AccessType type,
8183 Local<Value> data) {
8184 // Always allow read access.
8185 if (type == v8::ACCESS_GET)
8186 return true;
8187
8188 // Sometimes allow other access.
8189 return g_security_callback_result;
8190}
8191
8192
8193static bool IndexedSecurityTestCallback(Local<v8::Object> global,
8194 uint32_t key,
8195 v8::AccessType type,
8196 Local<Value> data) {
8197 // Always allow read access.
8198 if (type == v8::ACCESS_GET)
8199 return true;
8200
8201 // Sometimes allow other access.
8202 return g_security_callback_result;
8203}
8204
8205
8206static int trouble_nesting = 0;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00008207static void TroubleCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008208 ApiTestFuzzer::Fuzz();
8209 trouble_nesting++;
8210
8211 // Call a JS function that throws an uncaught exception.
machenbach@chromium.org528ce022013-09-23 14:09:36 +00008212 Local<v8::Object> arg_this =
8213 args.GetIsolate()->GetCurrentContext()->Global();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008214 Local<Value> trouble_callee = (trouble_nesting == 3) ?
8215 arg_this->Get(v8_str("trouble_callee")) :
8216 arg_this->Get(v8_str("trouble_caller"));
8217 CHECK(trouble_callee->IsFunction());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00008218 args.GetReturnValue().Set(
8219 Function::Cast(*trouble_callee)->Call(arg_this, 0, NULL));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008220}
8221
8222
8223static int report_count = 0;
8224static void ApiUncaughtExceptionTestListener(v8::Handle<v8::Message>,
8225 v8::Handle<Value>) {
8226 report_count++;
8227}
8228
8229
8230// Counts uncaught exceptions, but other tests running in parallel
8231// also have uncaught exceptions.
8232TEST(ApiUncaughtException) {
ager@chromium.org8bb60582008-12-11 12:02:20 +00008233 report_count = 0;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008234 LocalContext env;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00008235 v8::Isolate* isolate = env->GetIsolate();
8236 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008237 v8::V8::AddMessageListener(ApiUncaughtExceptionTestListener);
8238
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00008239 Local<v8::FunctionTemplate> fun =
8240 v8::FunctionTemplate::New(isolate, TroubleCallback);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008241 v8::Local<v8::Object> global = env->Global();
8242 global->Set(v8_str("trouble"), fun->GetFunction());
8243
8244 Script::Compile(v8_str("function trouble_callee() {"
8245 " var x = null;"
8246 " return x.foo;"
8247 "};"
8248 "function trouble_caller() {"
8249 " trouble();"
8250 "};"))->Run();
8251 Local<Value> trouble = global->Get(v8_str("trouble"));
8252 CHECK(trouble->IsFunction());
8253 Local<Value> trouble_callee = global->Get(v8_str("trouble_callee"));
8254 CHECK(trouble_callee->IsFunction());
8255 Local<Value> trouble_caller = global->Get(v8_str("trouble_caller"));
8256 CHECK(trouble_caller->IsFunction());
8257 Function::Cast(*trouble_caller)->Call(global, 0, NULL);
8258 CHECK_EQ(1, report_count);
ager@chromium.org8bb60582008-12-11 12:02:20 +00008259 v8::V8::RemoveMessageListeners(ApiUncaughtExceptionTestListener);
8260}
8261
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00008262static const char* script_resource_name = "ExceptionInNativeScript.js";
8263static void ExceptionInNativeScriptTestListener(v8::Handle<v8::Message> message,
8264 v8::Handle<Value>) {
8265 v8::Handle<v8::Value> name_val = message->GetScriptResourceName();
8266 CHECK(!name_val.IsEmpty() && name_val->IsString());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00008267 v8::String::Utf8Value name(message->GetScriptResourceName());
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00008268 CHECK_EQ(script_resource_name, *name);
8269 CHECK_EQ(3, message->GetLineNumber());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00008270 v8::String::Utf8Value source_line(message->GetSourceLine());
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00008271 CHECK_EQ(" new o.foo();", *source_line);
8272}
8273
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00008274
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00008275TEST(ExceptionInNativeScript) {
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00008276 LocalContext env;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00008277 v8::Isolate* isolate = env->GetIsolate();
8278 v8::HandleScope scope(isolate);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00008279 v8::V8::AddMessageListener(ExceptionInNativeScriptTestListener);
8280
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00008281 Local<v8::FunctionTemplate> fun =
8282 v8::FunctionTemplate::New(isolate, TroubleCallback);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00008283 v8::Local<v8::Object> global = env->Global();
8284 global->Set(v8_str("trouble"), fun->GetFunction());
8285
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00008286 Script::Compile(
8287 v8_str(
8288 "function trouble() {\n"
8289 " var o = {};\n"
8290 " new o.foo();\n"
8291 "};"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00008292 v8::String::NewFromUtf8(isolate, script_resource_name))->Run();
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00008293 Local<Value> trouble = global->Get(v8_str("trouble"));
8294 CHECK(trouble->IsFunction());
8295 Function::Cast(*trouble)->Call(global, 0, NULL);
8296 v8::V8::RemoveMessageListeners(ExceptionInNativeScriptTestListener);
8297}
8298
ager@chromium.org8bb60582008-12-11 12:02:20 +00008299
8300TEST(CompilationErrorUsingTryCatchHandler) {
ager@chromium.org8bb60582008-12-11 12:02:20 +00008301 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008302 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org8bb60582008-12-11 12:02:20 +00008303 v8::TryCatch try_catch;
8304 Script::Compile(v8_str("This doesn't &*&@#$&*^ compile."));
8305 CHECK_NE(NULL, *try_catch.Exception());
8306 CHECK(try_catch.HasCaught());
8307}
8308
8309
8310TEST(TryCatchFinallyUsingTryCatchHandler) {
ager@chromium.org8bb60582008-12-11 12:02:20 +00008311 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008312 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org8bb60582008-12-11 12:02:20 +00008313 v8::TryCatch try_catch;
8314 Script::Compile(v8_str("try { throw ''; } catch (e) {}"))->Run();
8315 CHECK(!try_catch.HasCaught());
8316 Script::Compile(v8_str("try { throw ''; } finally {}"))->Run();
8317 CHECK(try_catch.HasCaught());
8318 try_catch.Reset();
8319 Script::Compile(v8_str("(function() {"
8320 "try { throw ''; } finally { return; }"
8321 "})()"))->Run();
8322 CHECK(!try_catch.HasCaught());
8323 Script::Compile(v8_str("(function()"
8324 " { try { throw ''; } finally { throw 0; }"
8325 "})()"))->Run();
8326 CHECK(try_catch.HasCaught());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008327}
8328
8329
8330// SecurityHandler can't be run twice
8331TEST(SecurityHandler) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00008332 v8::Isolate* isolate = CcTest::isolate();
8333 v8::HandleScope scope0(isolate);
8334 v8::Handle<v8::ObjectTemplate> global_template =
8335 v8::ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008336 global_template->SetAccessCheckCallbacks(NamedSecurityTestCallback,
8337 IndexedSecurityTestCallback);
8338 // Create an environment
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00008339 v8::Handle<Context> context0 = Context::New(isolate, NULL, global_template);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008340 context0->Enter();
8341
8342 v8::Handle<v8::Object> global0 = context0->Global();
8343 v8::Handle<Script> script0 = v8_compile("foo = 111");
8344 script0->Run();
8345 global0->Set(v8_str("0"), v8_num(999));
8346 v8::Handle<Value> foo0 = global0->Get(v8_str("foo"));
8347 CHECK_EQ(111, foo0->Int32Value());
8348 v8::Handle<Value> z0 = global0->Get(v8_str("0"));
8349 CHECK_EQ(999, z0->Int32Value());
8350
8351 // Create another environment, should fail security checks.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00008352 v8::HandleScope scope1(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008353
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008354 v8::Handle<Context> context1 =
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00008355 Context::New(isolate, NULL, global_template);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008356 context1->Enter();
8357
8358 v8::Handle<v8::Object> global1 = context1->Global();
8359 global1->Set(v8_str("othercontext"), global0);
8360 // This set will fail the security check.
8361 v8::Handle<Script> script1 =
8362 v8_compile("othercontext.foo = 222; othercontext[0] = 888;");
8363 script1->Run();
8364 // This read will pass the security check.
8365 v8::Handle<Value> foo1 = global0->Get(v8_str("foo"));
8366 CHECK_EQ(111, foo1->Int32Value());
8367 // This read will pass the security check.
8368 v8::Handle<Value> z1 = global0->Get(v8_str("0"));
8369 CHECK_EQ(999, z1->Int32Value());
8370
8371 // Create another environment, should pass security checks.
8372 { g_security_callback_result = true; // allow security handler to pass.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00008373 v8::HandleScope scope2(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008374 LocalContext context2;
8375 v8::Handle<v8::Object> global2 = context2->Global();
8376 global2->Set(v8_str("othercontext"), global0);
8377 v8::Handle<Script> script2 =
8378 v8_compile("othercontext.foo = 333; othercontext[0] = 888;");
8379 script2->Run();
8380 v8::Handle<Value> foo2 = global0->Get(v8_str("foo"));
8381 CHECK_EQ(333, foo2->Int32Value());
8382 v8::Handle<Value> z2 = global0->Get(v8_str("0"));
8383 CHECK_EQ(888, z2->Int32Value());
8384 }
8385
8386 context1->Exit();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008387 context0->Exit();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008388}
8389
8390
8391THREADED_TEST(SecurityChecks) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008392 LocalContext env1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008393 v8::HandleScope handle_scope(env1->GetIsolate());
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008394 v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008395
8396 Local<Value> foo = v8_str("foo");
8397 Local<Value> bar = v8_str("bar");
8398
8399 // Set to the same domain.
8400 env1->SetSecurityToken(foo);
8401
8402 // Create a function in env1.
8403 Script::Compile(v8_str("spy=function(){return spy;}"))->Run();
8404 Local<Value> spy = env1->Global()->Get(v8_str("spy"));
8405 CHECK(spy->IsFunction());
8406
8407 // Create another function accessing global objects.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00008408 Script::Compile(v8_str("spy2=function(){return new this.Array();}"))->Run();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008409 Local<Value> spy2 = env1->Global()->Get(v8_str("spy2"));
8410 CHECK(spy2->IsFunction());
8411
8412 // Switch to env2 in the same domain and invoke spy on env2.
8413 {
8414 env2->SetSecurityToken(foo);
8415 // Enter env2
8416 Context::Scope scope_env2(env2);
8417 Local<Value> result = Function::Cast(*spy)->Call(env2->Global(), 0, NULL);
8418 CHECK(result->IsFunction());
8419 }
8420
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008421 {
8422 env2->SetSecurityToken(bar);
8423 Context::Scope scope_env2(env2);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008424
8425 // Call cross_domain_call, it should throw an exception
8426 v8::TryCatch try_catch;
8427 Function::Cast(*spy2)->Call(env2->Global(), 0, NULL);
8428 CHECK(try_catch.HasCaught());
8429 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008430}
8431
8432
8433// Regression test case for issue 1183439.
8434THREADED_TEST(SecurityChecksForPrototypeChain) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008435 LocalContext current;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008436 v8::HandleScope scope(current->GetIsolate());
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008437 v8::Handle<Context> other = Context::New(current->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008438
8439 // Change context to be able to get to the Object function in the
8440 // other context without hitting the security checks.
8441 v8::Local<Value> other_object;
8442 { Context::Scope scope(other);
8443 other_object = other->Global()->Get(v8_str("Object"));
8444 other->Global()->Set(v8_num(42), v8_num(87));
8445 }
8446
8447 current->Global()->Set(v8_str("other"), other->Global());
8448 CHECK(v8_compile("other")->Run()->Equals(other->Global()));
8449
8450 // Make sure the security check fails here and we get an undefined
8451 // result instead of getting the Object function. Repeat in a loop
8452 // to make sure to exercise the IC code.
8453 v8::Local<Script> access_other0 = v8_compile("other.Object");
8454 v8::Local<Script> access_other1 = v8_compile("other[42]");
8455 for (int i = 0; i < 5; i++) {
8456 CHECK(!access_other0->Run()->Equals(other_object));
8457 CHECK(access_other0->Run()->IsUndefined());
8458 CHECK(!access_other1->Run()->Equals(v8_num(87)));
8459 CHECK(access_other1->Run()->IsUndefined());
8460 }
8461
8462 // Create an object that has 'other' in its prototype chain and make
8463 // sure we cannot access the Object function indirectly through
8464 // that. Repeat in a loop to make sure to exercise the IC code.
8465 v8_compile("function F() { };"
8466 "F.prototype = other;"
8467 "var f = new F();")->Run();
8468 v8::Local<Script> access_f0 = v8_compile("f.Object");
8469 v8::Local<Script> access_f1 = v8_compile("f[42]");
8470 for (int j = 0; j < 5; j++) {
8471 CHECK(!access_f0->Run()->Equals(other_object));
8472 CHECK(access_f0->Run()->IsUndefined());
8473 CHECK(!access_f1->Run()->Equals(v8_num(87)));
8474 CHECK(access_f1->Run()->IsUndefined());
8475 }
8476
8477 // Now it gets hairy: Set the prototype for the other global object
8478 // to be the current global object. The prototype chain for 'f' now
8479 // goes through 'other' but ends up in the current global object.
8480 { Context::Scope scope(other);
8481 other->Global()->Set(v8_str("__proto__"), current->Global());
8482 }
8483 // Set a named and an index property on the current global
8484 // object. To force the lookup to go through the other global object,
8485 // the properties must not exist in the other global object.
8486 current->Global()->Set(v8_str("foo"), v8_num(100));
8487 current->Global()->Set(v8_num(99), v8_num(101));
8488 // Try to read the properties from f and make sure that the access
8489 // gets stopped by the security checks on the other global object.
8490 Local<Script> access_f2 = v8_compile("f.foo");
8491 Local<Script> access_f3 = v8_compile("f[99]");
8492 for (int k = 0; k < 5; k++) {
8493 CHECK(!access_f2->Run()->Equals(v8_num(100)));
8494 CHECK(access_f2->Run()->IsUndefined());
8495 CHECK(!access_f3->Run()->Equals(v8_num(101)));
8496 CHECK(access_f3->Run()->IsUndefined());
8497 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008498}
8499
8500
8501THREADED_TEST(CrossDomainDelete) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008502 LocalContext env1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008503 v8::HandleScope handle_scope(env1->GetIsolate());
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008504 v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008505
8506 Local<Value> foo = v8_str("foo");
8507 Local<Value> bar = v8_str("bar");
8508
8509 // Set to the same domain.
8510 env1->SetSecurityToken(foo);
8511 env2->SetSecurityToken(foo);
8512
8513 env1->Global()->Set(v8_str("prop"), v8_num(3));
8514 env2->Global()->Set(v8_str("env1"), env1->Global());
8515
8516 // Change env2 to a different domain and delete env1.prop.
8517 env2->SetSecurityToken(bar);
8518 {
8519 Context::Scope scope_env2(env2);
8520 Local<Value> result =
8521 Script::Compile(v8_str("delete env1.prop"))->Run();
8522 CHECK(result->IsFalse());
8523 }
8524
8525 // Check that env1.prop still exists.
8526 Local<Value> v = env1->Global()->Get(v8_str("prop"));
8527 CHECK(v->IsNumber());
8528 CHECK_EQ(3, v->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008529}
8530
8531
ager@chromium.org870a0b62008-11-04 11:43:05 +00008532THREADED_TEST(CrossDomainIsPropertyEnumerable) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00008533 LocalContext env1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008534 v8::HandleScope handle_scope(env1->GetIsolate());
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008535 v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
ager@chromium.org870a0b62008-11-04 11:43:05 +00008536
8537 Local<Value> foo = v8_str("foo");
8538 Local<Value> bar = v8_str("bar");
8539
8540 // Set to the same domain.
8541 env1->SetSecurityToken(foo);
8542 env2->SetSecurityToken(foo);
8543
8544 env1->Global()->Set(v8_str("prop"), v8_num(3));
8545 env2->Global()->Set(v8_str("env1"), env1->Global());
8546
8547 // env1.prop is enumerable in env2.
8548 Local<String> test = v8_str("propertyIsEnumerable.call(env1, 'prop')");
8549 {
8550 Context::Scope scope_env2(env2);
8551 Local<Value> result = Script::Compile(test)->Run();
8552 CHECK(result->IsTrue());
8553 }
8554
8555 // Change env2 to a different domain and test again.
8556 env2->SetSecurityToken(bar);
8557 {
8558 Context::Scope scope_env2(env2);
8559 Local<Value> result = Script::Compile(test)->Run();
8560 CHECK(result->IsFalse());
8561 }
ager@chromium.org870a0b62008-11-04 11:43:05 +00008562}
8563
8564
ager@chromium.org236ad962008-09-25 09:45:57 +00008565THREADED_TEST(CrossDomainForIn) {
ager@chromium.org236ad962008-09-25 09:45:57 +00008566 LocalContext env1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008567 v8::HandleScope handle_scope(env1->GetIsolate());
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008568 v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
ager@chromium.org236ad962008-09-25 09:45:57 +00008569
8570 Local<Value> foo = v8_str("foo");
8571 Local<Value> bar = v8_str("bar");
8572
8573 // Set to the same domain.
8574 env1->SetSecurityToken(foo);
8575 env2->SetSecurityToken(foo);
8576
8577 env1->Global()->Set(v8_str("prop"), v8_num(3));
8578 env2->Global()->Set(v8_str("env1"), env1->Global());
8579
8580 // Change env2 to a different domain and set env1's global object
8581 // as the __proto__ of an object in env2 and enumerate properties
8582 // in for-in. It shouldn't enumerate properties on env1's global
8583 // object.
8584 env2->SetSecurityToken(bar);
8585 {
8586 Context::Scope scope_env2(env2);
8587 Local<Value> result =
8588 CompileRun("(function(){var obj = {'__proto__':env1};"
8589 "for (var p in obj)"
8590 " if (p == 'prop') return false;"
8591 "return true;})()");
8592 CHECK(result->IsTrue());
8593 }
ager@chromium.org236ad962008-09-25 09:45:57 +00008594}
8595
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008596
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00008597TEST(ContextDetachGlobal) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00008598 LocalContext env1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008599 v8::HandleScope handle_scope(env1->GetIsolate());
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008600 v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00008601
8602 Local<v8::Object> global1 = env1->Global();
8603
8604 Local<Value> foo = v8_str("foo");
8605
8606 // Set to the same domain.
8607 env1->SetSecurityToken(foo);
8608 env2->SetSecurityToken(foo);
8609
8610 // Enter env2
8611 env2->Enter();
8612
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00008613 // Create a function in env2 and add a reference to it in env1.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00008614 Local<v8::Object> global2 = env2->Global();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00008615 global2->Set(v8_str("prop"), v8::Integer::New(env2->GetIsolate(), 1));
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00008616 CompileRun("function getProp() {return prop;}");
8617
8618 env1->Global()->Set(v8_str("getProp"),
8619 global2->Get(v8_str("getProp")));
8620
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00008621 // Detach env2's global, and reuse the global object of env2
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00008622 env2->Exit();
8623 env2->DetachGlobal();
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00008624
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008625 v8::Handle<Context> env3 = Context::New(env1->GetIsolate(),
8626 0,
8627 v8::Handle<v8::ObjectTemplate>(),
8628 global2);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00008629 env3->SetSecurityToken(v8_str("bar"));
8630 env3->Enter();
8631
8632 Local<v8::Object> global3 = env3->Global();
8633 CHECK_EQ(global2, global3);
8634 CHECK(global3->Get(v8_str("prop"))->IsUndefined());
8635 CHECK(global3->Get(v8_str("getProp"))->IsUndefined());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00008636 global3->Set(v8_str("prop"), v8::Integer::New(env3->GetIsolate(), -1));
8637 global3->Set(v8_str("prop2"), v8::Integer::New(env3->GetIsolate(), 2));
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00008638 env3->Exit();
8639
8640 // Call getProp in env1, and it should return the value 1
8641 {
8642 Local<Value> get_prop = global1->Get(v8_str("getProp"));
8643 CHECK(get_prop->IsFunction());
8644 v8::TryCatch try_catch;
8645 Local<Value> r = Function::Cast(*get_prop)->Call(global1, 0, NULL);
8646 CHECK(!try_catch.HasCaught());
8647 CHECK_EQ(1, r->Int32Value());
8648 }
8649
8650 // Check that env3 is not accessible from env1
8651 {
8652 Local<Value> r = global3->Get(v8_str("prop2"));
8653 CHECK(r->IsUndefined());
8654 }
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00008655}
8656
8657
jkummerow@chromium.org113035e2013-12-13 15:13:40 +00008658TEST(DetachGlobal) {
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00008659 LocalContext env1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008660 v8::HandleScope scope(env1->GetIsolate());
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00008661
8662 // Create second environment.
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008663 v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00008664
8665 Local<Value> foo = v8_str("foo");
8666
8667 // Set same security token for env1 and env2.
8668 env1->SetSecurityToken(foo);
8669 env2->SetSecurityToken(foo);
8670
8671 // Create a property on the global object in env2.
8672 {
8673 v8::Context::Scope scope(env2);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00008674 env2->Global()->Set(v8_str("p"), v8::Integer::New(env2->GetIsolate(), 42));
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00008675 }
8676
8677 // Create a reference to env2 global from env1 global.
8678 env1->Global()->Set(v8_str("other"), env2->Global());
8679
8680 // Check that we have access to other.p in env2 from env1.
8681 Local<Value> result = CompileRun("other.p");
8682 CHECK(result->IsInt32());
8683 CHECK_EQ(42, result->Int32Value());
8684
8685 // Hold on to global from env2 and detach global from env2.
8686 Local<v8::Object> global2 = env2->Global();
8687 env2->DetachGlobal();
8688
8689 // Check that the global has been detached. No other.p property can
8690 // be found.
8691 result = CompileRun("other.p");
8692 CHECK(result->IsUndefined());
8693
8694 // Reuse global2 for env3.
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008695 v8::Handle<Context> env3 = Context::New(env1->GetIsolate(),
8696 0,
8697 v8::Handle<v8::ObjectTemplate>(),
8698 global2);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00008699 CHECK_EQ(global2, env3->Global());
8700
8701 // Start by using the same security token for env3 as for env1 and env2.
8702 env3->SetSecurityToken(foo);
8703
8704 // Create a property on the global object in env3.
8705 {
8706 v8::Context::Scope scope(env3);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00008707 env3->Global()->Set(v8_str("p"), v8::Integer::New(env3->GetIsolate(), 24));
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00008708 }
8709
8710 // Check that other.p is now the property in env3 and that we have access.
8711 result = CompileRun("other.p");
8712 CHECK(result->IsInt32());
8713 CHECK_EQ(24, result->Int32Value());
8714
8715 // Change security token for env3 to something different from env1 and env2.
8716 env3->SetSecurityToken(v8_str("bar"));
8717
8718 // Check that we do not have access to other.p in env1. |other| is now
8719 // the global object for env3 which has a different security token,
8720 // so access should be blocked.
8721 result = CompileRun("other.p");
8722 CHECK(result->IsUndefined());
jkummerow@chromium.org113035e2013-12-13 15:13:40 +00008723}
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00008724
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00008725
rossberg@chromium.org9ed27462014-01-07 14:16:41 +00008726void GetThisX(const v8::FunctionCallbackInfo<v8::Value>& info) {
8727 info.GetReturnValue().Set(
8728 info.GetIsolate()->GetCurrentContext()->Global()->Get(v8_str("x")));
8729}
8730
8731
jkummerow@chromium.org113035e2013-12-13 15:13:40 +00008732TEST(DetachedAccesses) {
8733 LocalContext env1;
8734 v8::HandleScope scope(env1->GetIsolate());
8735
8736 // Create second environment.
rossberg@chromium.org9ed27462014-01-07 14:16:41 +00008737 Local<ObjectTemplate> inner_global_template =
8738 FunctionTemplate::New(env1->GetIsolate())->InstanceTemplate();
8739 inner_global_template ->SetAccessorProperty(
8740 v8_str("this_x"), FunctionTemplate::New(env1->GetIsolate(), GetThisX));
8741 v8::Local<Context> env2 =
8742 Context::New(env1->GetIsolate(), NULL, inner_global_template);
jkummerow@chromium.org113035e2013-12-13 15:13:40 +00008743
8744 Local<Value> foo = v8_str("foo");
8745
8746 // Set same security token for env1 and env2.
8747 env1->SetSecurityToken(foo);
8748 env2->SetSecurityToken(foo);
8749
rossberg@chromium.org9ed27462014-01-07 14:16:41 +00008750 env1->Global()->Set(v8_str("x"), v8_str("env1_x"));
8751
jkummerow@chromium.org113035e2013-12-13 15:13:40 +00008752 {
8753 v8::Context::Scope scope(env2);
rossberg@chromium.org9ed27462014-01-07 14:16:41 +00008754 env2->Global()->Set(v8_str("x"), v8_str("env2_x"));
jkummerow@chromium.org113035e2013-12-13 15:13:40 +00008755 CompileRun(
rossberg@chromium.org9ed27462014-01-07 14:16:41 +00008756 "function bound_x() { return x; }"
8757 "function get_x() { return this.x; }"
8758 "function get_x_w() { return (function() {return this.x;})(); }");
8759 env1->Global()->Set(v8_str("bound_x"), CompileRun("bound_x"));
jkummerow@chromium.org113035e2013-12-13 15:13:40 +00008760 env1->Global()->Set(v8_str("get_x"), CompileRun("get_x"));
8761 env1->Global()->Set(v8_str("get_x_w"), CompileRun("get_x_w"));
rossberg@chromium.org9ed27462014-01-07 14:16:41 +00008762 env1->Global()->Set(
8763 v8_str("this_x"),
8764 CompileRun("Object.getOwnPropertyDescriptor(this, 'this_x').get"));
jkummerow@chromium.org113035e2013-12-13 15:13:40 +00008765 }
8766
8767 Local<Object> env2_global = env2->Global();
8768 env2_global->TurnOnAccessCheck();
8769 env2->DetachGlobal();
8770
8771 Local<Value> result;
rossberg@chromium.org9ed27462014-01-07 14:16:41 +00008772 result = CompileRun("bound_x()");
8773 CHECK_EQ(v8_str("env2_x"), result);
jkummerow@chromium.org113035e2013-12-13 15:13:40 +00008774 result = CompileRun("get_x()");
8775 CHECK(result->IsUndefined());
8776 result = CompileRun("get_x_w()");
8777 CHECK(result->IsUndefined());
rossberg@chromium.org9ed27462014-01-07 14:16:41 +00008778 result = CompileRun("this_x()");
8779 CHECK_EQ(v8_str("env2_x"), result);
jkummerow@chromium.org113035e2013-12-13 15:13:40 +00008780
8781 // Reattach env2's proxy
8782 env2 = Context::New(env1->GetIsolate(),
8783 0,
8784 v8::Handle<v8::ObjectTemplate>(),
8785 env2_global);
8786 env2->SetSecurityToken(foo);
8787 {
8788 v8::Context::Scope scope(env2);
rossberg@chromium.org9ed27462014-01-07 14:16:41 +00008789 env2->Global()->Set(v8_str("x"), v8_str("env3_x"));
8790 env2->Global()->Set(v8_str("env1"), env1->Global());
8791 result = CompileRun(
8792 "results = [];"
8793 "for (var i = 0; i < 4; i++ ) {"
8794 " results.push(env1.bound_x());"
8795 " results.push(env1.get_x());"
8796 " results.push(env1.get_x_w());"
8797 " results.push(env1.this_x());"
8798 "}"
8799 "results");
8800 Local<v8::Array> results = Local<v8::Array>::Cast(result);
8801 CHECK_EQ(16, results->Length());
8802 for (int i = 0; i < 16; i += 4) {
8803 CHECK_EQ(v8_str("env2_x"), results->Get(i + 0));
8804 CHECK_EQ(v8_str("env1_x"), results->Get(i + 1));
8805 CHECK_EQ(v8_str("env3_x"), results->Get(i + 2));
8806 CHECK_EQ(v8_str("env2_x"), results->Get(i + 3));
8807 }
jkummerow@chromium.org113035e2013-12-13 15:13:40 +00008808 }
8809
rossberg@chromium.org9ed27462014-01-07 14:16:41 +00008810 result = CompileRun(
8811 "results = [];"
8812 "for (var i = 0; i < 4; i++ ) {"
8813 " results.push(bound_x());"
8814 " results.push(get_x());"
8815 " results.push(get_x_w());"
8816 " results.push(this_x());"
8817 "}"
8818 "results");
8819 Local<v8::Array> results = Local<v8::Array>::Cast(result);
8820 CHECK_EQ(16, results->Length());
8821 for (int i = 0; i < 16; i += 4) {
8822 CHECK_EQ(v8_str("env2_x"), results->Get(i + 0));
8823 CHECK_EQ(v8_str("env3_x"), results->Get(i + 1));
8824 CHECK_EQ(v8_str("env3_x"), results->Get(i + 2));
8825 CHECK_EQ(v8_str("env2_x"), results->Get(i + 3));
8826 }
8827
8828 result = CompileRun(
8829 "results = [];"
8830 "for (var i = 0; i < 4; i++ ) {"
8831 " results.push(this.bound_x());"
8832 " results.push(this.get_x());"
8833 " results.push(this.get_x_w());"
8834 " results.push(this.this_x());"
8835 "}"
8836 "results");
8837 results = Local<v8::Array>::Cast(result);
8838 CHECK_EQ(16, results->Length());
8839 for (int i = 0; i < 16; i += 4) {
8840 CHECK_EQ(v8_str("env2_x"), results->Get(i + 0));
8841 CHECK_EQ(v8_str("env1_x"), results->Get(i + 1));
8842 CHECK_EQ(v8_str("env3_x"), results->Get(i + 2));
8843 CHECK_EQ(v8_str("env2_x"), results->Get(i + 3));
8844 }
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00008845}
8846
8847
ricow@chromium.org83aa5492011-02-07 12:42:56 +00008848static bool allowed_access_type[v8::ACCESS_KEYS + 1] = { false };
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008849static bool NamedAccessBlocker(Local<v8::Object> global,
8850 Local<Value> name,
8851 v8::AccessType type,
8852 Local<Value> data) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00008853 return CcTest::isolate()->GetCurrentContext()->Global()->Equals(global) ||
ricow@chromium.org83aa5492011-02-07 12:42:56 +00008854 allowed_access_type[type];
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008855}
8856
8857
8858static bool IndexedAccessBlocker(Local<v8::Object> global,
8859 uint32_t key,
8860 v8::AccessType type,
8861 Local<Value> data) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00008862 return CcTest::isolate()->GetCurrentContext()->Global()->Equals(global) ||
ricow@chromium.org83aa5492011-02-07 12:42:56 +00008863 allowed_access_type[type];
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008864}
8865
8866
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00008867static int g_echo_value_1 = -1;
8868static int g_echo_value_2 = -1;
8869
8870
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00008871static void EchoGetter(
8872 Local<String> name,
8873 const v8::PropertyCallbackInfo<v8::Value>& info) {
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00008874 info.GetReturnValue().Set(v8_num(g_echo_value_1));
8875}
8876
8877
8878static void EchoGetter(const v8::FunctionCallbackInfo<v8::Value>& info) {
8879 info.GetReturnValue().Set(v8_num(g_echo_value_2));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008880}
8881
8882
8883static void EchoSetter(Local<String> name,
8884 Local<Value> value,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00008885 const v8::PropertyCallbackInfo<void>&) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008886 if (value->IsNumber())
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00008887 g_echo_value_1 = value->Int32Value();
8888}
8889
8890
8891static void EchoSetter(const v8::FunctionCallbackInfo<v8::Value>& info) {
8892 v8::Handle<v8::Value> value = info[0];
8893 if (value->IsNumber())
8894 g_echo_value_2 = value->Int32Value();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008895}
8896
8897
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00008898static void UnreachableGetter(
8899 Local<String> name,
8900 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008901 CHECK(false); // This function should not be called..
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008902}
8903
8904
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00008905static void UnreachableSetter(Local<String>,
8906 Local<Value>,
8907 const v8::PropertyCallbackInfo<void>&) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008908 CHECK(false); // This function should nto be called.
8909}
8910
8911
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00008912static void UnreachableFunction(
8913 const v8::FunctionCallbackInfo<v8::Value>& info) {
8914 CHECK(false); // This function should not be called..
8915}
8916
8917
ricow@chromium.org83aa5492011-02-07 12:42:56 +00008918TEST(AccessControl) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00008919 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008920 v8::HandleScope handle_scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00008921 v8::Handle<v8::ObjectTemplate> global_template =
8922 v8::ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008923
8924 global_template->SetAccessCheckCallbacks(NamedAccessBlocker,
8925 IndexedAccessBlocker);
8926
8927 // Add an accessor accessible by cross-domain JS code.
8928 global_template->SetAccessor(
8929 v8_str("accessible_prop"),
8930 EchoGetter, EchoSetter,
8931 v8::Handle<Value>(),
8932 v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
8933
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00008934
8935 global_template->SetAccessorProperty(
8936 v8_str("accessible_js_prop"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00008937 v8::FunctionTemplate::New(isolate, EchoGetter),
8938 v8::FunctionTemplate::New(isolate, EchoSetter),
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00008939 v8::None,
8940 v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
8941
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008942 // Add an accessor that is not accessible by cross-domain JS code.
ager@chromium.org870a0b62008-11-04 11:43:05 +00008943 global_template->SetAccessor(v8_str("blocked_prop"),
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008944 UnreachableGetter, UnreachableSetter,
8945 v8::Handle<Value>(),
8946 v8::DEFAULT);
8947
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00008948 global_template->SetAccessorProperty(
8949 v8_str("blocked_js_prop"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00008950 v8::FunctionTemplate::New(isolate, UnreachableFunction),
8951 v8::FunctionTemplate::New(isolate, UnreachableFunction),
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00008952 v8::None,
8953 v8::DEFAULT);
8954
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008955 // Create an environment
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008956 v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008957 context0->Enter();
8958
8959 v8::Handle<v8::Object> global0 = context0->Global();
8960
ricow@chromium.org83aa5492011-02-07 12:42:56 +00008961 // Define a property with JS getter and setter.
8962 CompileRun(
8963 "function getter() { return 'getter'; };\n"
8964 "function setter() { return 'setter'; }\n"
8965 "Object.defineProperty(this, 'js_accessor_p', {get:getter, set:setter})");
8966
8967 Local<Value> getter = global0->Get(v8_str("getter"));
8968 Local<Value> setter = global0->Get(v8_str("setter"));
8969
8970 // And define normal element.
8971 global0->Set(239, v8_str("239"));
8972
8973 // Define an element with JS getter and setter.
8974 CompileRun(
8975 "function el_getter() { return 'el_getter'; };\n"
8976 "function el_setter() { return 'el_setter'; };\n"
8977 "Object.defineProperty(this, '42', {get: el_getter, set: el_setter});");
8978
8979 Local<Value> el_getter = global0->Get(v8_str("el_getter"));
8980 Local<Value> el_setter = global0->Get(v8_str("el_setter"));
8981
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008982 v8::HandleScope scope1(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008983
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008984 v8::Local<Context> context1 = Context::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008985 context1->Enter();
8986
8987 v8::Handle<v8::Object> global1 = context1->Global();
8988 global1->Set(v8_str("other"), global0);
8989
ricow@chromium.org83aa5492011-02-07 12:42:56 +00008990 // Access blocked property.
8991 CompileRun("other.blocked_prop = 1");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008992
ricow@chromium.org83aa5492011-02-07 12:42:56 +00008993 ExpectUndefined("other.blocked_prop");
8994 ExpectUndefined(
8995 "Object.getOwnPropertyDescriptor(other, 'blocked_prop')");
8996 ExpectFalse("propertyIsEnumerable.call(other, 'blocked_prop')");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008997
ricow@chromium.org83aa5492011-02-07 12:42:56 +00008998 // Enable ACCESS_HAS
8999 allowed_access_type[v8::ACCESS_HAS] = true;
9000 ExpectUndefined("other.blocked_prop");
9001 // ... and now we can get the descriptor...
9002 ExpectUndefined(
antonm@chromium.orgdca01352011-01-31 17:15:05 +00009003 "Object.getOwnPropertyDescriptor(other, 'blocked_prop').value");
ricow@chromium.org83aa5492011-02-07 12:42:56 +00009004 // ... and enumerate the property.
9005 ExpectTrue("propertyIsEnumerable.call(other, 'blocked_prop')");
9006 allowed_access_type[v8::ACCESS_HAS] = false;
antonm@chromium.orgdca01352011-01-31 17:15:05 +00009007
ricow@chromium.org83aa5492011-02-07 12:42:56 +00009008 // Access blocked element.
9009 CompileRun("other[239] = 1");
9010
9011 ExpectUndefined("other[239]");
9012 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '239')");
9013 ExpectFalse("propertyIsEnumerable.call(other, '239')");
9014
9015 // Enable ACCESS_HAS
9016 allowed_access_type[v8::ACCESS_HAS] = true;
9017 ExpectUndefined("other[239]");
9018 // ... and now we can get the descriptor...
9019 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '239').value");
9020 // ... and enumerate the property.
9021 ExpectTrue("propertyIsEnumerable.call(other, '239')");
9022 allowed_access_type[v8::ACCESS_HAS] = false;
9023
9024 // Access a property with JS accessor.
9025 CompileRun("other.js_accessor_p = 2");
9026
9027 ExpectUndefined("other.js_accessor_p");
9028 ExpectUndefined(
9029 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p')");
9030
9031 // Enable ACCESS_HAS.
9032 allowed_access_type[v8::ACCESS_HAS] = true;
9033 ExpectUndefined("other.js_accessor_p");
9034 ExpectUndefined(
9035 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get");
9036 ExpectUndefined(
9037 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set");
9038 ExpectUndefined(
9039 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
9040 allowed_access_type[v8::ACCESS_HAS] = false;
9041
9042 // Enable both ACCESS_HAS and ACCESS_GET.
9043 allowed_access_type[v8::ACCESS_HAS] = true;
9044 allowed_access_type[v8::ACCESS_GET] = true;
9045
9046 ExpectString("other.js_accessor_p", "getter");
9047 ExpectObject(
9048 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get", getter);
9049 ExpectUndefined(
9050 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set");
9051 ExpectUndefined(
9052 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
9053
9054 allowed_access_type[v8::ACCESS_GET] = false;
9055 allowed_access_type[v8::ACCESS_HAS] = false;
9056
9057 // Enable both ACCESS_HAS and ACCESS_SET.
9058 allowed_access_type[v8::ACCESS_HAS] = true;
9059 allowed_access_type[v8::ACCESS_SET] = true;
9060
9061 ExpectUndefined("other.js_accessor_p");
9062 ExpectUndefined(
9063 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get");
9064 ExpectObject(
9065 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set", setter);
9066 ExpectUndefined(
9067 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
9068
9069 allowed_access_type[v8::ACCESS_SET] = false;
9070 allowed_access_type[v8::ACCESS_HAS] = false;
9071
9072 // Enable both ACCESS_HAS, ACCESS_GET and ACCESS_SET.
9073 allowed_access_type[v8::ACCESS_HAS] = true;
9074 allowed_access_type[v8::ACCESS_GET] = true;
9075 allowed_access_type[v8::ACCESS_SET] = true;
9076
9077 ExpectString("other.js_accessor_p", "getter");
9078 ExpectObject(
9079 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get", getter);
9080 ExpectObject(
9081 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set", setter);
9082 ExpectUndefined(
9083 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
9084
9085 allowed_access_type[v8::ACCESS_SET] = false;
9086 allowed_access_type[v8::ACCESS_GET] = false;
9087 allowed_access_type[v8::ACCESS_HAS] = false;
9088
9089 // Access an element with JS accessor.
9090 CompileRun("other[42] = 2");
9091
9092 ExpectUndefined("other[42]");
9093 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42')");
9094
9095 // Enable ACCESS_HAS.
9096 allowed_access_type[v8::ACCESS_HAS] = true;
9097 ExpectUndefined("other[42]");
9098 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').get");
9099 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').set");
9100 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
9101 allowed_access_type[v8::ACCESS_HAS] = false;
9102
9103 // Enable both ACCESS_HAS and ACCESS_GET.
9104 allowed_access_type[v8::ACCESS_HAS] = true;
9105 allowed_access_type[v8::ACCESS_GET] = true;
9106
9107 ExpectString("other[42]", "el_getter");
9108 ExpectObject("Object.getOwnPropertyDescriptor(other, '42').get", el_getter);
9109 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').set");
9110 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
9111
9112 allowed_access_type[v8::ACCESS_GET] = false;
9113 allowed_access_type[v8::ACCESS_HAS] = false;
9114
9115 // Enable both ACCESS_HAS and ACCESS_SET.
9116 allowed_access_type[v8::ACCESS_HAS] = true;
9117 allowed_access_type[v8::ACCESS_SET] = true;
9118
9119 ExpectUndefined("other[42]");
9120 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').get");
9121 ExpectObject("Object.getOwnPropertyDescriptor(other, '42').set", el_setter);
9122 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
9123
9124 allowed_access_type[v8::ACCESS_SET] = false;
9125 allowed_access_type[v8::ACCESS_HAS] = false;
9126
9127 // Enable both ACCESS_HAS, ACCESS_GET and ACCESS_SET.
9128 allowed_access_type[v8::ACCESS_HAS] = true;
9129 allowed_access_type[v8::ACCESS_GET] = true;
9130 allowed_access_type[v8::ACCESS_SET] = true;
9131
9132 ExpectString("other[42]", "el_getter");
9133 ExpectObject("Object.getOwnPropertyDescriptor(other, '42').get", el_getter);
9134 ExpectObject("Object.getOwnPropertyDescriptor(other, '42').set", el_setter);
9135 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
9136
9137 allowed_access_type[v8::ACCESS_SET] = false;
9138 allowed_access_type[v8::ACCESS_GET] = false;
9139 allowed_access_type[v8::ACCESS_HAS] = false;
9140
9141 v8::Handle<Value> value;
ager@chromium.org870a0b62008-11-04 11:43:05 +00009142
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009143 // Access accessible property
antonm@chromium.orgdca01352011-01-31 17:15:05 +00009144 value = CompileRun("other.accessible_prop = 3");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009145 CHECK(value->IsNumber());
9146 CHECK_EQ(3, value->Int32Value());
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00009147 CHECK_EQ(3, g_echo_value_1);
9148
9149 // Access accessible js property
9150 value = CompileRun("other.accessible_js_prop = 3");
9151 CHECK(value->IsNumber());
9152 CHECK_EQ(3, value->Int32Value());
9153 CHECK_EQ(3, g_echo_value_2);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009154
antonm@chromium.orgdca01352011-01-31 17:15:05 +00009155 value = CompileRun("other.accessible_prop");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009156 CHECK(value->IsNumber());
9157 CHECK_EQ(3, value->Int32Value());
9158
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00009159 value = CompileRun("other.accessible_js_prop");
9160 CHECK(value->IsNumber());
9161 CHECK_EQ(3, value->Int32Value());
9162
antonm@chromium.orgdca01352011-01-31 17:15:05 +00009163 value = CompileRun(
9164 "Object.getOwnPropertyDescriptor(other, 'accessible_prop').value");
9165 CHECK(value->IsNumber());
9166 CHECK_EQ(3, value->Int32Value());
9167
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00009168 value = CompileRun(
9169 "Object.getOwnPropertyDescriptor(other, 'accessible_js_prop').get()");
9170 CHECK(value->IsNumber());
9171 CHECK_EQ(3, value->Int32Value());
9172
antonm@chromium.orgdca01352011-01-31 17:15:05 +00009173 value = CompileRun("propertyIsEnumerable.call(other, 'accessible_prop')");
ager@chromium.org870a0b62008-11-04 11:43:05 +00009174 CHECK(value->IsTrue());
9175
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00009176 value = CompileRun("propertyIsEnumerable.call(other, 'accessible_js_prop')");
9177 CHECK(value->IsTrue());
9178
ager@chromium.org870a0b62008-11-04 11:43:05 +00009179 // Enumeration doesn't enumerate accessors from inaccessible objects in
9180 // the prototype chain even if the accessors are in themselves accessible.
antonm@chromium.orgdca01352011-01-31 17:15:05 +00009181 value =
ager@chromium.org870a0b62008-11-04 11:43:05 +00009182 CompileRun("(function(){var obj = {'__proto__':other};"
9183 "for (var p in obj)"
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00009184 " if (p == 'accessible_prop' ||"
9185 " p == 'accessible_js_prop' ||"
9186 " p == 'blocked_js_prop' ||"
9187 " p == 'blocked_js_prop') {"
ager@chromium.org870a0b62008-11-04 11:43:05 +00009188 " return false;"
9189 " }"
9190 "return true;})()");
antonm@chromium.orgdca01352011-01-31 17:15:05 +00009191 CHECK(value->IsTrue());
ager@chromium.org870a0b62008-11-04 11:43:05 +00009192
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009193 context1->Exit();
9194 context0->Exit();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009195}
9196
9197
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00009198TEST(AccessControlES5) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00009199 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009200 v8::HandleScope handle_scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00009201 v8::Handle<v8::ObjectTemplate> global_template =
9202 v8::ObjectTemplate::New(isolate);
ricow@chromium.org65001782011-02-15 13:36:41 +00009203
9204 global_template->SetAccessCheckCallbacks(NamedAccessBlocker,
9205 IndexedAccessBlocker);
9206
ricow@chromium.orgf5a18a22011-03-15 10:00:20 +00009207 // Add accessible accessor.
9208 global_template->SetAccessor(
9209 v8_str("accessible_prop"),
9210 EchoGetter, EchoSetter,
9211 v8::Handle<Value>(),
9212 v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
9213
9214
ricow@chromium.org65001782011-02-15 13:36:41 +00009215 // Add an accessor that is not accessible by cross-domain JS code.
9216 global_template->SetAccessor(v8_str("blocked_prop"),
9217 UnreachableGetter, UnreachableSetter,
9218 v8::Handle<Value>(),
9219 v8::DEFAULT);
9220
9221 // Create an environment
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009222 v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
ricow@chromium.org65001782011-02-15 13:36:41 +00009223 context0->Enter();
9224
9225 v8::Handle<v8::Object> global0 = context0->Global();
9226
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009227 v8::Local<Context> context1 = Context::New(isolate);
ricow@chromium.org65001782011-02-15 13:36:41 +00009228 context1->Enter();
9229 v8::Handle<v8::Object> global1 = context1->Global();
9230 global1->Set(v8_str("other"), global0);
9231
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00009232 // Regression test for issue 1154.
ricow@chromium.org65001782011-02-15 13:36:41 +00009233 ExpectTrue("Object.keys(other).indexOf('blocked_prop') == -1");
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00009234
9235 ExpectUndefined("other.blocked_prop");
9236
9237 // Regression test for issue 1027.
9238 CompileRun("Object.defineProperty(\n"
9239 " other, 'blocked_prop', {configurable: false})");
9240 ExpectUndefined("other.blocked_prop");
9241 ExpectUndefined(
9242 "Object.getOwnPropertyDescriptor(other, 'blocked_prop')");
9243
9244 // Regression test for issue 1171.
9245 ExpectTrue("Object.isExtensible(other)");
9246 CompileRun("Object.preventExtensions(other)");
9247 ExpectTrue("Object.isExtensible(other)");
9248
9249 // Object.seal and Object.freeze.
9250 CompileRun("Object.freeze(other)");
9251 ExpectTrue("Object.isExtensible(other)");
9252
9253 CompileRun("Object.seal(other)");
9254 ExpectTrue("Object.isExtensible(other)");
ricow@chromium.orgf5a18a22011-03-15 10:00:20 +00009255
9256 // Regression test for issue 1250.
9257 // Make sure that we can set the accessible accessors value using normal
9258 // assignment.
9259 CompileRun("other.accessible_prop = 42");
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00009260 CHECK_EQ(42, g_echo_value_1);
ricow@chromium.orgf5a18a22011-03-15 10:00:20 +00009261
9262 v8::Handle<Value> value;
9263 // We follow Safari in ignoring assignments to host object accessors.
9264 CompileRun("Object.defineProperty(other, 'accessible_prop', {value: -1})");
9265 value = CompileRun("other.accessible_prop == 42");
9266 CHECK(value->IsTrue());
ricow@chromium.org65001782011-02-15 13:36:41 +00009267}
9268
9269
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00009270static bool GetOwnPropertyNamesNamedBlocker(Local<v8::Object> global,
9271 Local<Value> name,
9272 v8::AccessType type,
9273 Local<Value> data) {
9274 return false;
9275}
9276
9277
9278static bool GetOwnPropertyNamesIndexedBlocker(Local<v8::Object> global,
9279 uint32_t key,
9280 v8::AccessType type,
9281 Local<Value> data) {
9282 return false;
9283}
9284
9285
9286THREADED_TEST(AccessControlGetOwnPropertyNames) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00009287 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009288 v8::HandleScope handle_scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00009289 v8::Handle<v8::ObjectTemplate> obj_template =
9290 v8::ObjectTemplate::New(isolate);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00009291
ulan@chromium.org0f13e742014-01-03 15:51:11 +00009292 obj_template->Set(v8_str("x"), v8::Integer::New(isolate, 42));
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00009293 obj_template->SetAccessCheckCallbacks(GetOwnPropertyNamesNamedBlocker,
9294 GetOwnPropertyNamesIndexedBlocker);
9295
9296 // Create an environment
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009297 v8::Local<Context> context0 = Context::New(isolate, NULL, obj_template);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00009298 context0->Enter();
9299
9300 v8::Handle<v8::Object> global0 = context0->Global();
9301
machenbach@chromium.org528ce022013-09-23 14:09:36 +00009302 v8::HandleScope scope1(CcTest::isolate());
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00009303
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009304 v8::Local<Context> context1 = Context::New(isolate);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00009305 context1->Enter();
9306
9307 v8::Handle<v8::Object> global1 = context1->Global();
9308 global1->Set(v8_str("other"), global0);
9309 global1->Set(v8_str("object"), obj_template->NewInstance());
9310
9311 v8::Handle<Value> value;
9312
9313 // Attempt to get the property names of the other global object and
9314 // of an object that requires access checks. Accessing the other
9315 // global object should be blocked by access checks on the global
9316 // proxy object. Accessing the object that requires access checks
9317 // is blocked by the access checks on the object itself.
9318 value = CompileRun("Object.getOwnPropertyNames(other).length == 0");
9319 CHECK(value->IsTrue());
9320
9321 value = CompileRun("Object.getOwnPropertyNames(object).length == 0");
9322 CHECK(value->IsTrue());
9323
9324 context1->Exit();
9325 context0->Exit();
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00009326}
9327
9328
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009329static void IndexedPropertyEnumerator(
9330 const v8::PropertyCallbackInfo<v8::Array>& info) {
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00009331 v8::Handle<v8::Array> result = v8::Array::New(info.GetIsolate(), 2);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00009332 result->Set(0, v8::Integer::New(info.GetIsolate(), 7));
9333 result->Set(1, v8::Object::New(info.GetIsolate()));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009334 info.GetReturnValue().Set(result);
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00009335}
9336
9337
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009338static void NamedPropertyEnumerator(
9339 const v8::PropertyCallbackInfo<v8::Array>& info) {
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00009340 v8::Handle<v8::Array> result = v8::Array::New(info.GetIsolate(), 2);
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00009341 result->Set(0, v8_str("x"));
ulan@chromium.org0f13e742014-01-03 15:51:11 +00009342 result->Set(1, v8::Object::New(info.GetIsolate()));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009343 info.GetReturnValue().Set(result);
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00009344}
9345
9346
9347THREADED_TEST(GetOwnPropertyNamesWithInterceptor) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00009348 v8::Isolate* isolate = CcTest::isolate();
9349 v8::HandleScope handle_scope(isolate);
9350 v8::Handle<v8::ObjectTemplate> obj_template =
9351 v8::ObjectTemplate::New(isolate);
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00009352
ulan@chromium.org0f13e742014-01-03 15:51:11 +00009353 obj_template->Set(v8_str("7"), v8::Integer::New(CcTest::isolate(), 7));
9354 obj_template->Set(v8_str("x"), v8::Integer::New(CcTest::isolate(), 42));
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00009355 obj_template->SetIndexedPropertyHandler(NULL, NULL, NULL, NULL,
9356 IndexedPropertyEnumerator);
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00009357 obj_template->SetNamedPropertyHandler(NULL, NULL, NULL, NULL,
9358 NamedPropertyEnumerator);
9359
9360 LocalContext context;
9361 v8::Handle<v8::Object> global = context->Global();
9362 global->Set(v8_str("object"), obj_template->NewInstance());
9363
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00009364 v8::Handle<v8::Value> result =
9365 CompileRun("Object.getOwnPropertyNames(object)");
9366 CHECK(result->IsArray());
9367 v8::Handle<v8::Array> result_array = v8::Handle<v8::Array>::Cast(result);
9368 CHECK_EQ(3, result_array->Length());
9369 CHECK(result_array->Get(0)->IsString());
9370 CHECK(result_array->Get(1)->IsString());
9371 CHECK(result_array->Get(2)->IsString());
9372 CHECK_EQ(v8_str("7"), result_array->Get(0));
9373 CHECK_EQ(v8_str("[object Object]"), result_array->Get(1));
9374 CHECK_EQ(v8_str("x"), result_array->Get(2));
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00009375}
9376
9377
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009378static void ConstTenGetter(Local<String> name,
9379 const v8::PropertyCallbackInfo<v8::Value>& info) {
9380 info.GetReturnValue().Set(v8_num(10));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009381}
9382
9383
9384THREADED_TEST(CrossDomainAccessors) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00009385 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009386 v8::HandleScope handle_scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009387
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00009388 v8::Handle<v8::FunctionTemplate> func_template =
9389 v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009390
9391 v8::Handle<v8::ObjectTemplate> global_template =
9392 func_template->InstanceTemplate();
9393
9394 v8::Handle<v8::ObjectTemplate> proto_template =
9395 func_template->PrototypeTemplate();
9396
9397 // Add an accessor to proto that's accessible by cross-domain JS code.
9398 proto_template->SetAccessor(v8_str("accessible"),
9399 ConstTenGetter, 0,
9400 v8::Handle<Value>(),
9401 v8::ALL_CAN_READ);
9402
9403 // Add an accessor that is not accessible by cross-domain JS code.
9404 global_template->SetAccessor(v8_str("unreachable"),
9405 UnreachableGetter, 0,
9406 v8::Handle<Value>(),
9407 v8::DEFAULT);
9408
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009409 v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009410 context0->Enter();
9411
9412 Local<v8::Object> global = context0->Global();
9413 // Add a normal property that shadows 'accessible'
9414 global->Set(v8_str("accessible"), v8_num(11));
9415
9416 // Enter a new context.
machenbach@chromium.org528ce022013-09-23 14:09:36 +00009417 v8::HandleScope scope1(CcTest::isolate());
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009418 v8::Local<Context> context1 = Context::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009419 context1->Enter();
9420
9421 v8::Handle<v8::Object> global1 = context1->Global();
9422 global1->Set(v8_str("other"), global);
9423
9424 // Should return 10, instead of 11
9425 v8::Handle<Value> value = v8_compile("other.accessible")->Run();
9426 CHECK(value->IsNumber());
9427 CHECK_EQ(10, value->Int32Value());
9428
9429 value = v8_compile("other.unreachable")->Run();
9430 CHECK(value->IsUndefined());
9431
9432 context1->Exit();
9433 context0->Exit();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009434}
9435
9436
9437static int named_access_count = 0;
9438static int indexed_access_count = 0;
9439
9440static bool NamedAccessCounter(Local<v8::Object> global,
9441 Local<Value> name,
9442 v8::AccessType type,
9443 Local<Value> data) {
9444 named_access_count++;
9445 return true;
9446}
9447
9448
9449static bool IndexedAccessCounter(Local<v8::Object> global,
9450 uint32_t key,
9451 v8::AccessType type,
9452 Local<Value> data) {
9453 indexed_access_count++;
9454 return true;
9455}
9456
9457
9458// This one is too easily disturbed by other tests.
9459TEST(AccessControlIC) {
9460 named_access_count = 0;
9461 indexed_access_count = 0;
9462
machenbach@chromium.org528ce022013-09-23 14:09:36 +00009463 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009464 v8::HandleScope handle_scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009465
9466 // Create an environment.
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009467 v8::Local<Context> context0 = Context::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009468 context0->Enter();
9469
9470 // Create an object that requires access-check functions to be
9471 // called for cross-domain access.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00009472 v8::Handle<v8::ObjectTemplate> object_template =
9473 v8::ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009474 object_template->SetAccessCheckCallbacks(NamedAccessCounter,
9475 IndexedAccessCounter);
9476 Local<v8::Object> object = object_template->NewInstance();
9477
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009478 v8::HandleScope scope1(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009479
9480 // Create another environment.
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009481 v8::Local<Context> context1 = Context::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009482 context1->Enter();
9483
9484 // Make easy access to the object from the other environment.
9485 v8::Handle<v8::Object> global1 = context1->Global();
9486 global1->Set(v8_str("obj"), object);
9487
9488 v8::Handle<Value> value;
9489
9490 // Check that the named access-control function is called every time.
ager@chromium.org8bb60582008-12-11 12:02:20 +00009491 CompileRun("function testProp(obj) {"
9492 " for (var i = 0; i < 10; i++) obj.prop = 1;"
9493 " for (var j = 0; j < 10; j++) obj.prop;"
9494 " return obj.prop"
9495 "}");
9496 value = CompileRun("testProp(obj)");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009497 CHECK(value->IsNumber());
9498 CHECK_EQ(1, value->Int32Value());
9499 CHECK_EQ(21, named_access_count);
9500
9501 // Check that the named access-control function is called every time.
ager@chromium.org8bb60582008-12-11 12:02:20 +00009502 CompileRun("var p = 'prop';"
9503 "function testKeyed(obj) {"
9504 " for (var i = 0; i < 10; i++) obj[p] = 1;"
9505 " for (var j = 0; j < 10; j++) obj[p];"
9506 " return obj[p];"
9507 "}");
9508 // Use obj which requires access checks. No inline caching is used
9509 // in that case.
9510 value = CompileRun("testKeyed(obj)");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009511 CHECK(value->IsNumber());
9512 CHECK_EQ(1, value->Int32Value());
9513 CHECK_EQ(42, named_access_count);
ager@chromium.org8bb60582008-12-11 12:02:20 +00009514 // Force the inline caches into generic state and try again.
9515 CompileRun("testKeyed({ a: 0 })");
9516 CompileRun("testKeyed({ b: 0 })");
9517 value = CompileRun("testKeyed(obj)");
9518 CHECK(value->IsNumber());
9519 CHECK_EQ(1, value->Int32Value());
9520 CHECK_EQ(63, named_access_count);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009521
9522 // Check that the indexed access-control function is called every time.
ager@chromium.org8bb60582008-12-11 12:02:20 +00009523 CompileRun("function testIndexed(obj) {"
9524 " for (var i = 0; i < 10; i++) obj[0] = 1;"
9525 " for (var j = 0; j < 10; j++) obj[0];"
9526 " return obj[0]"
9527 "}");
9528 value = CompileRun("testIndexed(obj)");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009529 CHECK(value->IsNumber());
9530 CHECK_EQ(1, value->Int32Value());
9531 CHECK_EQ(21, indexed_access_count);
ager@chromium.org8bb60582008-12-11 12:02:20 +00009532 // Force the inline caches into generic state.
9533 CompileRun("testIndexed(new Array(1))");
9534 // Test that the indexed access check is called.
9535 value = CompileRun("testIndexed(obj)");
9536 CHECK(value->IsNumber());
9537 CHECK_EQ(1, value->Int32Value());
9538 CHECK_EQ(42, indexed_access_count);
9539
9540 // Check that the named access check is called when invoking
9541 // functions on an object that requires access checks.
9542 CompileRun("obj.f = function() {}");
9543 CompileRun("function testCallNormal(obj) {"
9544 " for (var i = 0; i < 10; i++) obj.f();"
9545 "}");
9546 CompileRun("testCallNormal(obj)");
9547 CHECK_EQ(74, named_access_count);
9548
9549 // Force obj into slow case.
9550 value = CompileRun("delete obj.prop");
9551 CHECK(value->BooleanValue());
9552 // Force inline caches into dictionary probing mode.
9553 CompileRun("var o = { x: 0 }; delete o.x; testProp(o);");
9554 // Test that the named access check is called.
9555 value = CompileRun("testProp(obj);");
9556 CHECK(value->IsNumber());
9557 CHECK_EQ(1, value->Int32Value());
9558 CHECK_EQ(96, named_access_count);
9559
9560 // Force the call inline cache into dictionary probing mode.
9561 CompileRun("o.f = function() {}; testCallNormal(o)");
9562 // Test that the named access check is still called for each
9563 // invocation of the function.
9564 value = CompileRun("testCallNormal(obj)");
9565 CHECK_EQ(106, named_access_count);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009566
9567 context1->Exit();
9568 context0->Exit();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009569}
9570
9571
9572static bool NamedAccessFlatten(Local<v8::Object> global,
9573 Local<Value> name,
9574 v8::AccessType type,
9575 Local<Value> data) {
9576 char buf[100];
9577 int len;
9578
9579 CHECK(name->IsString());
9580
9581 memset(buf, 0x1, sizeof(buf));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009582 len = name.As<String>()->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009583 CHECK_EQ(4, len);
9584
9585 uint16_t buf2[100];
9586
9587 memset(buf, 0x1, sizeof(buf));
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00009588 len = name.As<String>()->Write(buf2);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009589 CHECK_EQ(4, len);
9590
9591 return true;
9592}
9593
9594
9595static bool IndexedAccessFlatten(Local<v8::Object> global,
9596 uint32_t key,
9597 v8::AccessType type,
9598 Local<Value> data) {
9599 return true;
9600}
9601
9602
9603// Regression test. In access checks, operations that may cause
9604// garbage collection are not allowed. It used to be the case that
9605// using the Write operation on a string could cause a garbage
9606// collection due to flattening of the string. This is no longer the
9607// case.
9608THREADED_TEST(AccessControlFlatten) {
9609 named_access_count = 0;
9610 indexed_access_count = 0;
9611
machenbach@chromium.org528ce022013-09-23 14:09:36 +00009612 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009613 v8::HandleScope handle_scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009614
9615 // Create an environment.
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009616 v8::Local<Context> context0 = Context::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009617 context0->Enter();
9618
9619 // Create an object that requires access-check functions to be
9620 // called for cross-domain access.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00009621 v8::Handle<v8::ObjectTemplate> object_template =
9622 v8::ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009623 object_template->SetAccessCheckCallbacks(NamedAccessFlatten,
9624 IndexedAccessFlatten);
9625 Local<v8::Object> object = object_template->NewInstance();
9626
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009627 v8::HandleScope scope1(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009628
9629 // Create another environment.
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009630 v8::Local<Context> context1 = Context::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009631 context1->Enter();
9632
9633 // Make easy access to the object from the other environment.
9634 v8::Handle<v8::Object> global1 = context1->Global();
9635 global1->Set(v8_str("obj"), object);
9636
9637 v8::Handle<Value> value;
9638
9639 value = v8_compile("var p = 'as' + 'df';")->Run();
9640 value = v8_compile("obj[p];")->Run();
9641
9642 context1->Exit();
9643 context0->Exit();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009644}
9645
9646
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009647static void AccessControlNamedGetter(
9648 Local<String>,
9649 const v8::PropertyCallbackInfo<v8::Value>& info) {
9650 info.GetReturnValue().Set(42);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009651}
9652
9653
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009654static void AccessControlNamedSetter(
9655 Local<String>,
9656 Local<Value> value,
9657 const v8::PropertyCallbackInfo<v8::Value>& info) {
9658 info.GetReturnValue().Set(value);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009659}
9660
9661
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009662static void AccessControlIndexedGetter(
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009663 uint32_t index,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009664 const v8::PropertyCallbackInfo<v8::Value>& info) {
9665 info.GetReturnValue().Set(v8_num(42));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009666}
9667
9668
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009669static void AccessControlIndexedSetter(
9670 uint32_t,
9671 Local<Value> value,
9672 const v8::PropertyCallbackInfo<v8::Value>& info) {
9673 info.GetReturnValue().Set(value);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009674}
9675
9676
9677THREADED_TEST(AccessControlInterceptorIC) {
9678 named_access_count = 0;
9679 indexed_access_count = 0;
9680
machenbach@chromium.org528ce022013-09-23 14:09:36 +00009681 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009682 v8::HandleScope handle_scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009683
9684 // Create an environment.
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009685 v8::Local<Context> context0 = Context::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009686 context0->Enter();
9687
9688 // Create an object that requires access-check functions to be
9689 // called for cross-domain access. The object also has interceptors
9690 // interceptor.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00009691 v8::Handle<v8::ObjectTemplate> object_template =
9692 v8::ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009693 object_template->SetAccessCheckCallbacks(NamedAccessCounter,
9694 IndexedAccessCounter);
9695 object_template->SetNamedPropertyHandler(AccessControlNamedGetter,
9696 AccessControlNamedSetter);
9697 object_template->SetIndexedPropertyHandler(AccessControlIndexedGetter,
9698 AccessControlIndexedSetter);
9699 Local<v8::Object> object = object_template->NewInstance();
9700
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009701 v8::HandleScope scope1(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009702
9703 // Create another environment.
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009704 v8::Local<Context> context1 = Context::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009705 context1->Enter();
9706
9707 // Make easy access to the object from the other environment.
9708 v8::Handle<v8::Object> global1 = context1->Global();
9709 global1->Set(v8_str("obj"), object);
9710
9711 v8::Handle<Value> value;
9712
9713 // Check that the named access-control function is called every time
9714 // eventhough there is an interceptor on the object.
9715 value = v8_compile("for (var i = 0; i < 10; i++) obj.x = 1;")->Run();
9716 value = v8_compile("for (var i = 0; i < 10; i++) obj.x;"
9717 "obj.x")->Run();
9718 CHECK(value->IsNumber());
9719 CHECK_EQ(42, value->Int32Value());
9720 CHECK_EQ(21, named_access_count);
9721
9722 value = v8_compile("var p = 'x';")->Run();
9723 value = v8_compile("for (var i = 0; i < 10; i++) obj[p] = 1;")->Run();
9724 value = v8_compile("for (var i = 0; i < 10; i++) obj[p];"
9725 "obj[p]")->Run();
9726 CHECK(value->IsNumber());
9727 CHECK_EQ(42, value->Int32Value());
9728 CHECK_EQ(42, named_access_count);
9729
9730 // Check that the indexed access-control function is called every
9731 // time eventhough there is an interceptor on the object.
9732 value = v8_compile("for (var i = 0; i < 10; i++) obj[0] = 1;")->Run();
9733 value = v8_compile("for (var i = 0; i < 10; i++) obj[0];"
9734 "obj[0]")->Run();
9735 CHECK(value->IsNumber());
9736 CHECK_EQ(42, value->Int32Value());
9737 CHECK_EQ(21, indexed_access_count);
9738
9739 context1->Exit();
9740 context0->Exit();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009741}
9742
9743
9744THREADED_TEST(Version) {
9745 v8::V8::GetVersion();
9746}
9747
9748
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009749static void InstanceFunctionCallback(
9750 const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009751 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009752 args.GetReturnValue().Set(v8_num(12));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009753}
9754
9755
9756THREADED_TEST(InstanceProperties) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009757 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00009758 v8::Isolate* isolate = context->GetIsolate();
9759 v8::HandleScope handle_scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009760
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00009761 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009762 Local<ObjectTemplate> instance = t->InstanceTemplate();
9763
9764 instance->Set(v8_str("x"), v8_num(42));
9765 instance->Set(v8_str("f"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00009766 v8::FunctionTemplate::New(isolate, InstanceFunctionCallback));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009767
9768 Local<Value> o = t->GetFunction()->NewInstance();
9769
9770 context->Global()->Set(v8_str("i"), o);
9771 Local<Value> value = Script::Compile(v8_str("i.x"))->Run();
9772 CHECK_EQ(42, value->Int32Value());
9773
9774 value = Script::Compile(v8_str("i.f()"))->Run();
9775 CHECK_EQ(12, value->Int32Value());
9776}
9777
9778
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009779static void GlobalObjectInstancePropertiesGet(
9780 Local<String> key,
9781 const v8::PropertyCallbackInfo<v8::Value>&) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009782 ApiTestFuzzer::Fuzz();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009783}
9784
9785
9786THREADED_TEST(GlobalObjectInstanceProperties) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00009787 v8::Isolate* isolate = CcTest::isolate();
9788 v8::HandleScope handle_scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009789
9790 Local<Value> global_object;
9791
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00009792 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009793 t->InstanceTemplate()->SetNamedPropertyHandler(
9794 GlobalObjectInstancePropertiesGet);
9795 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
9796 instance_template->Set(v8_str("x"), v8_num(42));
9797 instance_template->Set(v8_str("f"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00009798 v8::FunctionTemplate::New(isolate,
9799 InstanceFunctionCallback));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009800
kasperl@chromium.orga5551262010-12-07 12:49:48 +00009801 // The script to check how Crankshaft compiles missing global function
9802 // invocations. function g is not defined and should throw on call.
9803 const char* script =
9804 "function wrapper(call) {"
9805 " var x = 0, y = 1;"
9806 " for (var i = 0; i < 1000; i++) {"
9807 " x += i * 100;"
9808 " y += i * 100;"
9809 " }"
9810 " if (call) g();"
9811 "}"
9812 "for (var i = 0; i < 17; i++) wrapper(false);"
9813 "var thrown = 0;"
9814 "try { wrapper(true); } catch (e) { thrown = 1; };"
9815 "thrown";
9816
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009817 {
9818 LocalContext env(NULL, instance_template);
9819 // Hold on to the global object so it can be used again in another
9820 // environment initialization.
9821 global_object = env->Global();
9822
9823 Local<Value> value = Script::Compile(v8_str("x"))->Run();
9824 CHECK_EQ(42, value->Int32Value());
9825 value = Script::Compile(v8_str("f()"))->Run();
9826 CHECK_EQ(12, value->Int32Value());
kasperl@chromium.orga5551262010-12-07 12:49:48 +00009827 value = Script::Compile(v8_str(script))->Run();
9828 CHECK_EQ(1, value->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009829 }
9830
9831 {
9832 // Create new environment reusing the global object.
9833 LocalContext env(NULL, instance_template, global_object);
9834 Local<Value> value = Script::Compile(v8_str("x"))->Run();
9835 CHECK_EQ(42, value->Int32Value());
9836 value = Script::Compile(v8_str("f()"))->Run();
9837 CHECK_EQ(12, value->Int32Value());
kasperl@chromium.orga5551262010-12-07 12:49:48 +00009838 value = Script::Compile(v8_str(script))->Run();
9839 CHECK_EQ(1, value->Int32Value());
9840 }
9841}
9842
9843
9844THREADED_TEST(CallKnownGlobalReceiver) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00009845 v8::Isolate* isolate = CcTest::isolate();
9846 v8::HandleScope handle_scope(isolate);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00009847
9848 Local<Value> global_object;
9849
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00009850 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00009851 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
9852
9853 // The script to check that we leave global object not
9854 // global object proxy on stack when we deoptimize from inside
9855 // arguments evaluation.
9856 // To provoke error we need to both force deoptimization
9857 // from arguments evaluation and to force CallIC to take
9858 // CallIC_Miss code path that can't cope with global proxy.
9859 const char* script =
9860 "function bar(x, y) { try { } finally { } }"
9861 "function baz(x) { try { } finally { } }"
9862 "function bom(x) { try { } finally { } }"
9863 "function foo(x) { bar([x], bom(2)); }"
9864 "for (var i = 0; i < 10000; i++) foo(1);"
9865 "foo";
9866
9867 Local<Value> foo;
9868 {
9869 LocalContext env(NULL, instance_template);
9870 // Hold on to the global object so it can be used again in another
9871 // environment initialization.
9872 global_object = env->Global();
9873 foo = Script::Compile(v8_str(script))->Run();
9874 }
9875
9876 {
9877 // Create new environment reusing the global object.
9878 LocalContext env(NULL, instance_template, global_object);
9879 env->Global()->Set(v8_str("foo"), foo);
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00009880 Script::Compile(v8_str("foo()"))->Run();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009881 }
9882}
9883
9884
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009885static void ShadowFunctionCallback(
9886 const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009887 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009888 args.GetReturnValue().Set(v8_num(42));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009889}
9890
9891
9892static int shadow_y;
9893static int shadow_y_setter_call_count;
9894static int shadow_y_getter_call_count;
9895
9896
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009897static void ShadowYSetter(Local<String>,
9898 Local<Value>,
9899 const v8::PropertyCallbackInfo<void>&) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009900 shadow_y_setter_call_count++;
9901 shadow_y = 42;
9902}
9903
9904
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009905static void ShadowYGetter(Local<String> name,
9906 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009907 ApiTestFuzzer::Fuzz();
9908 shadow_y_getter_call_count++;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009909 info.GetReturnValue().Set(v8_num(shadow_y));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009910}
9911
9912
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009913static void ShadowIndexedGet(uint32_t index,
9914 const v8::PropertyCallbackInfo<v8::Value>&) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009915}
9916
9917
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009918static void ShadowNamedGet(Local<String> key,
9919 const v8::PropertyCallbackInfo<v8::Value>&) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009920}
9921
9922
9923THREADED_TEST(ShadowObject) {
9924 shadow_y = shadow_y_setter_call_count = shadow_y_getter_call_count = 0;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00009925 v8::Isolate* isolate = CcTest::isolate();
9926 v8::HandleScope handle_scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009927
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00009928 Local<ObjectTemplate> global_template = v8::ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009929 LocalContext context(NULL, global_template);
9930
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00009931 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009932 t->InstanceTemplate()->SetNamedPropertyHandler(ShadowNamedGet);
9933 t->InstanceTemplate()->SetIndexedPropertyHandler(ShadowIndexedGet);
9934 Local<ObjectTemplate> proto = t->PrototypeTemplate();
9935 Local<ObjectTemplate> instance = t->InstanceTemplate();
9936
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009937 proto->Set(v8_str("f"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00009938 v8::FunctionTemplate::New(isolate,
9939 ShadowFunctionCallback,
9940 Local<Value>()));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009941 proto->Set(v8_str("x"), v8_num(12));
9942
9943 instance->SetAccessor(v8_str("y"), ShadowYGetter, ShadowYSetter);
9944
9945 Local<Value> o = t->GetFunction()->NewInstance();
9946 context->Global()->Set(v8_str("__proto__"), o);
9947
9948 Local<Value> value =
ricow@chromium.orgd2be9012011-06-01 06:00:58 +00009949 Script::Compile(v8_str("this.propertyIsEnumerable(0)"))->Run();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009950 CHECK(value->IsBoolean());
9951 CHECK(!value->BooleanValue());
9952
9953 value = Script::Compile(v8_str("x"))->Run();
9954 CHECK_EQ(12, value->Int32Value());
9955
9956 value = Script::Compile(v8_str("f()"))->Run();
9957 CHECK_EQ(42, value->Int32Value());
9958
mmassi@chromium.org7028c052012-06-13 11:51:58 +00009959 Script::Compile(v8_str("y = 43"))->Run();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009960 CHECK_EQ(1, shadow_y_setter_call_count);
9961 value = Script::Compile(v8_str("y"))->Run();
9962 CHECK_EQ(1, shadow_y_getter_call_count);
9963 CHECK_EQ(42, value->Int32Value());
9964}
9965
9966
9967THREADED_TEST(HiddenPrototype) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009968 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00009969 v8::Isolate* isolate = context->GetIsolate();
9970 v8::HandleScope handle_scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009971
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00009972 Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009973 t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00009974 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009975 t1->SetHiddenPrototype(true);
9976 t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00009977 Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009978 t2->SetHiddenPrototype(true);
9979 t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00009980 Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009981 t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
9982
9983 Local<v8::Object> o0 = t0->GetFunction()->NewInstance();
9984 Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
9985 Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
9986 Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
9987
9988 // Setting the prototype on an object skips hidden prototypes.
9989 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
9990 o0->Set(v8_str("__proto__"), o1);
9991 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
9992 CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
9993 o0->Set(v8_str("__proto__"), o2);
9994 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
9995 CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
9996 CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
9997 o0->Set(v8_str("__proto__"), o3);
9998 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
9999 CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
10000 CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
10001 CHECK_EQ(3, o0->Get(v8_str("u"))->Int32Value());
10002
10003 // Getting the prototype of o0 should get the first visible one
10004 // which is o3. Therefore, z should not be defined on the prototype
10005 // object.
10006 Local<Value> proto = o0->Get(v8_str("__proto__"));
10007 CHECK(proto->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000010008 CHECK(proto.As<v8::Object>()->Get(v8_str("z"))->IsUndefined());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010009}
10010
10011
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000010012THREADED_TEST(HiddenPrototypeSet) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000010013 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010014 v8::Isolate* isolate = context->GetIsolate();
10015 v8::HandleScope handle_scope(isolate);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000010016
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010017 Local<v8::FunctionTemplate> ot = v8::FunctionTemplate::New(isolate);
10018 Local<v8::FunctionTemplate> ht = v8::FunctionTemplate::New(isolate);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000010019 ht->SetHiddenPrototype(true);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010020 Local<v8::FunctionTemplate> pt = v8::FunctionTemplate::New(isolate);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000010021 ht->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
10022
10023 Local<v8::Object> o = ot->GetFunction()->NewInstance();
10024 Local<v8::Object> h = ht->GetFunction()->NewInstance();
10025 Local<v8::Object> p = pt->GetFunction()->NewInstance();
10026 o->Set(v8_str("__proto__"), h);
10027 h->Set(v8_str("__proto__"), p);
10028
10029 // Setting a property that exists on the hidden prototype goes there.
10030 o->Set(v8_str("x"), v8_num(7));
10031 CHECK_EQ(7, o->Get(v8_str("x"))->Int32Value());
10032 CHECK_EQ(7, h->Get(v8_str("x"))->Int32Value());
10033 CHECK(p->Get(v8_str("x"))->IsUndefined());
10034
10035 // Setting a new property should not be forwarded to the hidden prototype.
10036 o->Set(v8_str("y"), v8_num(6));
10037 CHECK_EQ(6, o->Get(v8_str("y"))->Int32Value());
10038 CHECK(h->Get(v8_str("y"))->IsUndefined());
10039 CHECK(p->Get(v8_str("y"))->IsUndefined());
10040
10041 // Setting a property that only exists on a prototype of the hidden prototype
10042 // is treated normally again.
10043 p->Set(v8_str("z"), v8_num(8));
10044 CHECK_EQ(8, o->Get(v8_str("z"))->Int32Value());
10045 CHECK_EQ(8, h->Get(v8_str("z"))->Int32Value());
10046 CHECK_EQ(8, p->Get(v8_str("z"))->Int32Value());
10047 o->Set(v8_str("z"), v8_num(9));
10048 CHECK_EQ(9, o->Get(v8_str("z"))->Int32Value());
10049 CHECK_EQ(8, h->Get(v8_str("z"))->Int32Value());
10050 CHECK_EQ(8, p->Get(v8_str("z"))->Int32Value());
10051}
10052
10053
10054// Regression test for issue 2457.
10055THREADED_TEST(HiddenPrototypeIdentityHash) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000010056 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000010057 v8::HandleScope handle_scope(context->GetIsolate());
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000010058
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010059 Handle<FunctionTemplate> t = FunctionTemplate::New(context->GetIsolate());
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000010060 t->SetHiddenPrototype(true);
10061 t->InstanceTemplate()->Set(v8_str("foo"), v8_num(75));
10062 Handle<Object> p = t->GetFunction()->NewInstance();
ulan@chromium.org0f13e742014-01-03 15:51:11 +000010063 Handle<Object> o = Object::New(context->GetIsolate());
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000010064 o->SetPrototype(p);
10065
10066 int hash = o->GetIdentityHash();
10067 USE(hash);
10068 o->Set(v8_str("foo"), v8_num(42));
10069 ASSERT_EQ(hash, o->GetIdentityHash());
10070}
10071
10072
ager@chromium.org5c838252010-02-19 08:53:10 +000010073THREADED_TEST(SetPrototype) {
ager@chromium.org5c838252010-02-19 08:53:10 +000010074 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010075 v8::Isolate* isolate = context->GetIsolate();
10076 v8::HandleScope handle_scope(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +000010077
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010078 Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +000010079 t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010080 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +000010081 t1->SetHiddenPrototype(true);
10082 t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010083 Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +000010084 t2->SetHiddenPrototype(true);
10085 t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010086 Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +000010087 t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
10088
10089 Local<v8::Object> o0 = t0->GetFunction()->NewInstance();
10090 Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
10091 Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
10092 Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
10093
10094 // Setting the prototype on an object does not skip hidden prototypes.
10095 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
10096 CHECK(o0->SetPrototype(o1));
10097 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
10098 CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
10099 CHECK(o1->SetPrototype(o2));
10100 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
10101 CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
10102 CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
10103 CHECK(o2->SetPrototype(o3));
10104 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
10105 CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
10106 CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
10107 CHECK_EQ(3, o0->Get(v8_str("u"))->Int32Value());
10108
10109 // Getting the prototype of o0 should get the first visible one
10110 // which is o3. Therefore, z should not be defined on the prototype
10111 // object.
10112 Local<Value> proto = o0->Get(v8_str("__proto__"));
10113 CHECK(proto->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000010114 CHECK_EQ(proto.As<v8::Object>(), o3);
ager@chromium.org5c838252010-02-19 08:53:10 +000010115
10116 // However, Object::GetPrototype ignores hidden prototype.
10117 Local<Value> proto0 = o0->GetPrototype();
10118 CHECK(proto0->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000010119 CHECK_EQ(proto0.As<v8::Object>(), o1);
ager@chromium.org5c838252010-02-19 08:53:10 +000010120
10121 Local<Value> proto1 = o1->GetPrototype();
10122 CHECK(proto1->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000010123 CHECK_EQ(proto1.As<v8::Object>(), o2);
ager@chromium.org5c838252010-02-19 08:53:10 +000010124
10125 Local<Value> proto2 = o2->GetPrototype();
10126 CHECK(proto2->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000010127 CHECK_EQ(proto2.As<v8::Object>(), o3);
ager@chromium.org5c838252010-02-19 08:53:10 +000010128}
10129
10130
ricow@chromium.org27bf2882011-11-17 08:34:43 +000010131// Getting property names of an object with a prototype chain that
10132// triggers dictionary elements in GetLocalPropertyNames() shouldn't
10133// crash the runtime.
10134THREADED_TEST(Regress91517) {
10135 i::FLAG_allow_natives_syntax = true;
ricow@chromium.org27bf2882011-11-17 08:34:43 +000010136 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010137 v8::Isolate* isolate = context->GetIsolate();
10138 v8::HandleScope handle_scope(isolate);
ricow@chromium.org27bf2882011-11-17 08:34:43 +000010139
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010140 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
ricow@chromium.org27bf2882011-11-17 08:34:43 +000010141 t1->SetHiddenPrototype(true);
10142 t1->InstanceTemplate()->Set(v8_str("foo"), v8_num(1));
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010143 Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
ricow@chromium.org27bf2882011-11-17 08:34:43 +000010144 t2->SetHiddenPrototype(true);
10145 t2->InstanceTemplate()->Set(v8_str("fuz1"), v8_num(2));
ulan@chromium.org0f13e742014-01-03 15:51:11 +000010146 t2->InstanceTemplate()->Set(v8_str("objects"), v8::Object::New(isolate));
ricow@chromium.org27bf2882011-11-17 08:34:43 +000010147 t2->InstanceTemplate()->Set(v8_str("fuz2"), v8_num(2));
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010148 Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
ricow@chromium.org27bf2882011-11-17 08:34:43 +000010149 t3->SetHiddenPrototype(true);
10150 t3->InstanceTemplate()->Set(v8_str("boo"), v8_num(3));
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010151 Local<v8::FunctionTemplate> t4 = v8::FunctionTemplate::New(isolate);
ricow@chromium.org27bf2882011-11-17 08:34:43 +000010152 t4->InstanceTemplate()->Set(v8_str("baz"), v8_num(4));
10153
10154 // Force dictionary-based properties.
10155 i::ScopedVector<char> name_buf(1024);
10156 for (int i = 1; i <= 1000; i++) {
10157 i::OS::SNPrintF(name_buf, "sdf%d", i);
10158 t2->InstanceTemplate()->Set(v8_str(name_buf.start()), v8_num(2));
10159 }
10160
10161 Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
10162 Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
10163 Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
10164 Local<v8::Object> o4 = t4->GetFunction()->NewInstance();
10165
10166 // Create prototype chain of hidden prototypes.
10167 CHECK(o4->SetPrototype(o3));
10168 CHECK(o3->SetPrototype(o2));
10169 CHECK(o2->SetPrototype(o1));
10170
10171 // Call the runtime version of GetLocalPropertyNames() on the natively
10172 // created object through JavaScript.
10173 context->Global()->Set(v8_str("obj"), o4);
machenbach@chromium.org03453962014-01-10 14:16:31 +000010174 // PROPERTY_ATTRIBUTES_NONE = 0
10175 CompileRun("var names = %GetLocalPropertyNames(obj, 0);");
ricow@chromium.org27bf2882011-11-17 08:34:43 +000010176
10177 ExpectInt32("names.length", 1006);
10178 ExpectTrue("names.indexOf(\"baz\") >= 0");
10179 ExpectTrue("names.indexOf(\"boo\") >= 0");
10180 ExpectTrue("names.indexOf(\"foo\") >= 0");
10181 ExpectTrue("names.indexOf(\"fuz1\") >= 0");
10182 ExpectTrue("names.indexOf(\"fuz2\") >= 0");
10183 ExpectFalse("names[1005] == undefined");
10184}
10185
10186
ulan@chromium.org0f13e742014-01-03 15:51:11 +000010187// Getting property names of an object with a hidden and inherited
10188// prototype should not duplicate the accessor properties inherited.
10189THREADED_TEST(Regress269562) {
10190 i::FLAG_allow_natives_syntax = true;
10191 LocalContext context;
10192 v8::HandleScope handle_scope(context->GetIsolate());
10193
10194 Local<v8::FunctionTemplate> t1 =
10195 v8::FunctionTemplate::New(context->GetIsolate());
10196 t1->SetHiddenPrototype(true);
10197
10198 Local<v8::ObjectTemplate> i1 = t1->InstanceTemplate();
10199 i1->SetAccessor(v8_str("foo"),
10200 SimpleAccessorGetter, SimpleAccessorSetter);
10201 i1->SetAccessor(v8_str("bar"),
10202 SimpleAccessorGetter, SimpleAccessorSetter);
10203 i1->SetAccessor(v8_str("baz"),
10204 SimpleAccessorGetter, SimpleAccessorSetter);
10205 i1->Set(v8_str("n1"), v8_num(1));
10206 i1->Set(v8_str("n2"), v8_num(2));
10207
10208 Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
10209 Local<v8::FunctionTemplate> t2 =
10210 v8::FunctionTemplate::New(context->GetIsolate());
10211 t2->SetHiddenPrototype(true);
10212
10213 // Inherit from t1 and mark prototype as hidden.
10214 t2->Inherit(t1);
10215 t2->InstanceTemplate()->Set(v8_str("mine"), v8_num(4));
10216
10217 Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
10218 CHECK(o2->SetPrototype(o1));
10219
10220 v8::Local<v8::Symbol> sym = v8::Symbol::New(context->GetIsolate(), "s1");
10221 o1->Set(sym, v8_num(3));
10222 o1->SetHiddenValue(v8_str("h1"),
10223 v8::Integer::New(context->GetIsolate(), 2013));
10224
10225 // Call the runtime version of GetLocalPropertyNames() on
10226 // the natively created object through JavaScript.
10227 context->Global()->Set(v8_str("obj"), o2);
10228 context->Global()->Set(v8_str("sym"), sym);
machenbach@chromium.org03453962014-01-10 14:16:31 +000010229 // PROPERTY_ATTRIBUTES_NONE = 0
10230 CompileRun("var names = %GetLocalPropertyNames(obj, 0);");
ulan@chromium.org0f13e742014-01-03 15:51:11 +000010231
10232 ExpectInt32("names.length", 7);
10233 ExpectTrue("names.indexOf(\"foo\") >= 0");
10234 ExpectTrue("names.indexOf(\"bar\") >= 0");
10235 ExpectTrue("names.indexOf(\"baz\") >= 0");
10236 ExpectTrue("names.indexOf(\"n1\") >= 0");
10237 ExpectTrue("names.indexOf(\"n2\") >= 0");
10238 ExpectTrue("names.indexOf(sym) >= 0");
10239 ExpectTrue("names.indexOf(\"mine\") >= 0");
10240}
10241
10242
ricow@chromium.org2c99e282011-07-28 09:15:17 +000010243THREADED_TEST(FunctionReadOnlyPrototype) {
ager@chromium.org04921a82011-06-27 13:21:41 +000010244 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010245 v8::Isolate* isolate = context->GetIsolate();
10246 v8::HandleScope handle_scope(isolate);
ager@chromium.org04921a82011-06-27 13:21:41 +000010247
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010248 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000010249 t1->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(isolate, 42));
ricow@chromium.org2c99e282011-07-28 09:15:17 +000010250 t1->ReadOnlyPrototype();
ager@chromium.org04921a82011-06-27 13:21:41 +000010251 context->Global()->Set(v8_str("func1"), t1->GetFunction());
ricow@chromium.org2c99e282011-07-28 09:15:17 +000010252 // Configured value of ReadOnly flag.
ager@chromium.org04921a82011-06-27 13:21:41 +000010253 CHECK(CompileRun(
10254 "(function() {"
10255 " descriptor = Object.getOwnPropertyDescriptor(func1, 'prototype');"
ricow@chromium.org2c99e282011-07-28 09:15:17 +000010256 " return (descriptor['writable'] == false);"
ager@chromium.org04921a82011-06-27 13:21:41 +000010257 "})()")->BooleanValue());
ricow@chromium.org2c99e282011-07-28 09:15:17 +000010258 CHECK_EQ(42, CompileRun("func1.prototype.x")->Int32Value());
10259 CHECK_EQ(42,
10260 CompileRun("func1.prototype = {}; func1.prototype.x")->Int32Value());
ager@chromium.org04921a82011-06-27 13:21:41 +000010261
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010262 Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000010263 t2->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(isolate, 42));
ager@chromium.org04921a82011-06-27 13:21:41 +000010264 context->Global()->Set(v8_str("func2"), t2->GetFunction());
ricow@chromium.org2c99e282011-07-28 09:15:17 +000010265 // Default value of ReadOnly flag.
ager@chromium.org04921a82011-06-27 13:21:41 +000010266 CHECK(CompileRun(
10267 "(function() {"
10268 " descriptor = Object.getOwnPropertyDescriptor(func2, 'prototype');"
ricow@chromium.org2c99e282011-07-28 09:15:17 +000010269 " return (descriptor['writable'] == true);"
ager@chromium.org04921a82011-06-27 13:21:41 +000010270 "})()")->BooleanValue());
ricow@chromium.org2c99e282011-07-28 09:15:17 +000010271 CHECK_EQ(42, CompileRun("func2.prototype.x")->Int32Value());
ager@chromium.org04921a82011-06-27 13:21:41 +000010272}
10273
10274
ager@chromium.org5c838252010-02-19 08:53:10 +000010275THREADED_TEST(SetPrototypeThrows) {
ager@chromium.org5c838252010-02-19 08:53:10 +000010276 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010277 v8::Isolate* isolate = context->GetIsolate();
10278 v8::HandleScope handle_scope(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +000010279
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010280 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +000010281
10282 Local<v8::Object> o0 = t->GetFunction()->NewInstance();
10283 Local<v8::Object> o1 = t->GetFunction()->NewInstance();
10284
10285 CHECK(o0->SetPrototype(o1));
10286 // If setting the prototype leads to the cycle, SetPrototype should
10287 // return false and keep VM in sane state.
10288 v8::TryCatch try_catch;
10289 CHECK(!o1->SetPrototype(o0));
10290 CHECK(!try_catch.HasCaught());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000010291 ASSERT(!CcTest::i_isolate()->has_pending_exception());
ager@chromium.org5c838252010-02-19 08:53:10 +000010292
10293 CHECK_EQ(42, CompileRun("function f() { return 42; }; f()")->Int32Value());
10294}
10295
10296
verwaest@chromium.org662436e2013-08-28 08:41:27 +000010297THREADED_TEST(FunctionRemovePrototype) {
10298 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010299 v8::Isolate* isolate = context->GetIsolate();
10300 v8::HandleScope handle_scope(isolate);
verwaest@chromium.org662436e2013-08-28 08:41:27 +000010301
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010302 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
verwaest@chromium.org662436e2013-08-28 08:41:27 +000010303 t1->RemovePrototype();
10304 Local<v8::Function> fun = t1->GetFunction();
10305 context->Global()->Set(v8_str("fun"), fun);
10306 CHECK(!CompileRun("'prototype' in fun")->BooleanValue());
10307
10308 v8::TryCatch try_catch;
10309 CompileRun("new fun()");
10310 CHECK(try_catch.HasCaught());
10311
10312 try_catch.Reset();
10313 fun->NewInstance();
10314 CHECK(try_catch.HasCaught());
10315}
10316
10317
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010318THREADED_TEST(GetterSetterExceptions) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010319 LocalContext context;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000010320 v8::Isolate* isolate = context->GetIsolate();
10321 v8::HandleScope handle_scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010322 CompileRun(
10323 "function Foo() { };"
10324 "function Throw() { throw 5; };"
10325 "var x = { };"
10326 "x.__defineSetter__('set', Throw);"
10327 "x.__defineGetter__('get', Throw);");
10328 Local<v8::Object> x =
10329 Local<v8::Object>::Cast(context->Global()->Get(v8_str("x")));
10330 v8::TryCatch try_catch;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000010331 x->Set(v8_str("set"), v8::Integer::New(isolate, 8));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010332 x->Get(v8_str("get"));
ulan@chromium.org0f13e742014-01-03 15:51:11 +000010333 x->Set(v8_str("set"), v8::Integer::New(isolate, 8));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010334 x->Get(v8_str("get"));
ulan@chromium.org0f13e742014-01-03 15:51:11 +000010335 x->Set(v8_str("set"), v8::Integer::New(isolate, 8));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010336 x->Get(v8_str("get"));
ulan@chromium.org0f13e742014-01-03 15:51:11 +000010337 x->Set(v8_str("set"), v8::Integer::New(isolate, 8));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010338 x->Get(v8_str("get"));
10339}
10340
10341
10342THREADED_TEST(Constructor) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010343 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010344 v8::Isolate* isolate = context->GetIsolate();
10345 v8::HandleScope handle_scope(isolate);
10346 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010347 templ->SetClassName(v8_str("Fun"));
10348 Local<Function> cons = templ->GetFunction();
10349 context->Global()->Set(v8_str("Fun"), cons);
10350 Local<v8::Object> inst = cons->NewInstance();
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000010351 i::Handle<i::JSObject> obj(v8::Utils::OpenHandle(*inst));
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000010352 CHECK(obj->IsJSObject());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010353 Local<Value> value = CompileRun("(new Fun()).constructor === Fun");
10354 CHECK(value->BooleanValue());
10355}
10356
lrn@chromium.org1c092762011-05-09 09:42:16 +000010357
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010358static void ConstructorCallback(
10359 const v8::FunctionCallbackInfo<v8::Value>& args) {
lrn@chromium.org1c092762011-05-09 09:42:16 +000010360 ApiTestFuzzer::Fuzz();
10361 Local<Object> This;
10362
10363 if (args.IsConstructCall()) {
10364 Local<Object> Holder = args.Holder();
ulan@chromium.org0f13e742014-01-03 15:51:11 +000010365 This = Object::New(args.GetIsolate());
lrn@chromium.org1c092762011-05-09 09:42:16 +000010366 Local<Value> proto = Holder->GetPrototype();
10367 if (proto->IsObject()) {
10368 This->SetPrototype(proto);
10369 }
10370 } else {
10371 This = args.This();
10372 }
10373
10374 This->Set(v8_str("a"), args[0]);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010375 args.GetReturnValue().Set(This);
lrn@chromium.org1c092762011-05-09 09:42:16 +000010376}
10377
10378
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010379static void FakeConstructorCallback(
10380 const v8::FunctionCallbackInfo<v8::Value>& args) {
lrn@chromium.org1c092762011-05-09 09:42:16 +000010381 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010382 args.GetReturnValue().Set(args[0]);
lrn@chromium.org1c092762011-05-09 09:42:16 +000010383}
10384
10385
10386THREADED_TEST(ConstructorForObject) {
lrn@chromium.org1c092762011-05-09 09:42:16 +000010387 LocalContext context;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000010388 v8::Isolate* isolate = context->GetIsolate();
10389 v8::HandleScope handle_scope(isolate);
lrn@chromium.org1c092762011-05-09 09:42:16 +000010390
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000010391 { Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
lrn@chromium.org1c092762011-05-09 09:42:16 +000010392 instance_template->SetCallAsFunctionHandler(ConstructorCallback);
10393 Local<Object> instance = instance_template->NewInstance();
10394 context->Global()->Set(v8_str("obj"), instance);
10395 v8::TryCatch try_catch;
10396 Local<Value> value;
10397 CHECK(!try_catch.HasCaught());
10398
10399 // Call the Object's constructor with a 32-bit signed integer.
10400 value = CompileRun("(function() { var o = new obj(28); return o.a; })()");
10401 CHECK(!try_catch.HasCaught());
10402 CHECK(value->IsInt32());
10403 CHECK_EQ(28, value->Int32Value());
10404
10405 Local<Value> args1[] = { v8_num(28) };
10406 Local<Value> value_obj1 = instance->CallAsConstructor(1, args1);
10407 CHECK(value_obj1->IsObject());
10408 Local<Object> object1 = Local<Object>::Cast(value_obj1);
10409 value = object1->Get(v8_str("a"));
10410 CHECK(value->IsInt32());
10411 CHECK(!try_catch.HasCaught());
10412 CHECK_EQ(28, value->Int32Value());
10413
10414 // Call the Object's constructor with a String.
10415 value = CompileRun(
10416 "(function() { var o = new obj('tipli'); return o.a; })()");
10417 CHECK(!try_catch.HasCaught());
10418 CHECK(value->IsString());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000010419 String::Utf8Value string_value1(value->ToString());
lrn@chromium.org1c092762011-05-09 09:42:16 +000010420 CHECK_EQ("tipli", *string_value1);
10421
10422 Local<Value> args2[] = { v8_str("tipli") };
10423 Local<Value> value_obj2 = instance->CallAsConstructor(1, args2);
10424 CHECK(value_obj2->IsObject());
10425 Local<Object> object2 = Local<Object>::Cast(value_obj2);
10426 value = object2->Get(v8_str("a"));
10427 CHECK(!try_catch.HasCaught());
10428 CHECK(value->IsString());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000010429 String::Utf8Value string_value2(value->ToString());
lrn@chromium.org1c092762011-05-09 09:42:16 +000010430 CHECK_EQ("tipli", *string_value2);
10431
10432 // Call the Object's constructor with a Boolean.
10433 value = CompileRun("(function() { var o = new obj(true); return o.a; })()");
10434 CHECK(!try_catch.HasCaught());
10435 CHECK(value->IsBoolean());
10436 CHECK_EQ(true, value->BooleanValue());
10437
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000010438 Handle<Value> args3[] = { v8::True(isolate) };
lrn@chromium.org1c092762011-05-09 09:42:16 +000010439 Local<Value> value_obj3 = instance->CallAsConstructor(1, args3);
10440 CHECK(value_obj3->IsObject());
10441 Local<Object> object3 = Local<Object>::Cast(value_obj3);
10442 value = object3->Get(v8_str("a"));
10443 CHECK(!try_catch.HasCaught());
10444 CHECK(value->IsBoolean());
10445 CHECK_EQ(true, value->BooleanValue());
10446
10447 // Call the Object's constructor with undefined.
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000010448 Handle<Value> args4[] = { v8::Undefined(isolate) };
lrn@chromium.org1c092762011-05-09 09:42:16 +000010449 Local<Value> value_obj4 = instance->CallAsConstructor(1, args4);
10450 CHECK(value_obj4->IsObject());
10451 Local<Object> object4 = Local<Object>::Cast(value_obj4);
10452 value = object4->Get(v8_str("a"));
10453 CHECK(!try_catch.HasCaught());
10454 CHECK(value->IsUndefined());
10455
10456 // Call the Object's constructor with null.
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000010457 Handle<Value> args5[] = { v8::Null(isolate) };
lrn@chromium.org1c092762011-05-09 09:42:16 +000010458 Local<Value> value_obj5 = instance->CallAsConstructor(1, args5);
10459 CHECK(value_obj5->IsObject());
10460 Local<Object> object5 = Local<Object>::Cast(value_obj5);
10461 value = object5->Get(v8_str("a"));
10462 CHECK(!try_catch.HasCaught());
10463 CHECK(value->IsNull());
10464 }
10465
10466 // Check exception handling when there is no constructor set for the Object.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000010467 { Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
lrn@chromium.org1c092762011-05-09 09:42:16 +000010468 Local<Object> instance = instance_template->NewInstance();
10469 context->Global()->Set(v8_str("obj2"), instance);
10470 v8::TryCatch try_catch;
10471 Local<Value> value;
10472 CHECK(!try_catch.HasCaught());
10473
10474 value = CompileRun("new obj2(28)");
10475 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000010476 String::Utf8Value exception_value1(try_catch.Exception());
lrn@chromium.org1c092762011-05-09 09:42:16 +000010477 CHECK_EQ("TypeError: object is not a function", *exception_value1);
10478 try_catch.Reset();
10479
10480 Local<Value> args[] = { v8_num(29) };
10481 value = instance->CallAsConstructor(1, args);
10482 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000010483 String::Utf8Value exception_value2(try_catch.Exception());
lrn@chromium.org1c092762011-05-09 09:42:16 +000010484 CHECK_EQ("TypeError: #<Object> is not a function", *exception_value2);
10485 try_catch.Reset();
10486 }
10487
10488 // Check the case when constructor throws exception.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000010489 { Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
lrn@chromium.org1c092762011-05-09 09:42:16 +000010490 instance_template->SetCallAsFunctionHandler(ThrowValue);
10491 Local<Object> instance = instance_template->NewInstance();
10492 context->Global()->Set(v8_str("obj3"), instance);
10493 v8::TryCatch try_catch;
10494 Local<Value> value;
10495 CHECK(!try_catch.HasCaught());
10496
10497 value = CompileRun("new obj3(22)");
10498 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000010499 String::Utf8Value exception_value1(try_catch.Exception());
lrn@chromium.org1c092762011-05-09 09:42:16 +000010500 CHECK_EQ("22", *exception_value1);
10501 try_catch.Reset();
10502
10503 Local<Value> args[] = { v8_num(23) };
10504 value = instance->CallAsConstructor(1, args);
10505 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000010506 String::Utf8Value exception_value2(try_catch.Exception());
lrn@chromium.org1c092762011-05-09 09:42:16 +000010507 CHECK_EQ("23", *exception_value2);
10508 try_catch.Reset();
10509 }
10510
10511 // Check whether constructor returns with an object or non-object.
10512 { Local<FunctionTemplate> function_template =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010513 FunctionTemplate::New(isolate, FakeConstructorCallback);
lrn@chromium.org1c092762011-05-09 09:42:16 +000010514 Local<Function> function = function_template->GetFunction();
10515 Local<Object> instance1 = function;
10516 context->Global()->Set(v8_str("obj4"), instance1);
10517 v8::TryCatch try_catch;
10518 Local<Value> value;
10519 CHECK(!try_catch.HasCaught());
10520
10521 CHECK(instance1->IsObject());
10522 CHECK(instance1->IsFunction());
10523
10524 value = CompileRun("new obj4(28)");
10525 CHECK(!try_catch.HasCaught());
10526 CHECK(value->IsObject());
10527
10528 Local<Value> args1[] = { v8_num(28) };
10529 value = instance1->CallAsConstructor(1, args1);
10530 CHECK(!try_catch.HasCaught());
10531 CHECK(value->IsObject());
10532
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000010533 Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
lrn@chromium.org1c092762011-05-09 09:42:16 +000010534 instance_template->SetCallAsFunctionHandler(FakeConstructorCallback);
10535 Local<Object> instance2 = instance_template->NewInstance();
10536 context->Global()->Set(v8_str("obj5"), instance2);
10537 CHECK(!try_catch.HasCaught());
10538
10539 CHECK(instance2->IsObject());
10540 CHECK(!instance2->IsFunction());
10541
10542 value = CompileRun("new obj5(28)");
10543 CHECK(!try_catch.HasCaught());
10544 CHECK(!value->IsObject());
10545
10546 Local<Value> args2[] = { v8_num(28) };
10547 value = instance2->CallAsConstructor(1, args2);
10548 CHECK(!try_catch.HasCaught());
10549 CHECK(!value->IsObject());
10550 }
10551}
10552
10553
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010554THREADED_TEST(FunctionDescriptorException) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010555 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010556 v8::Isolate* isolate = context->GetIsolate();
10557 v8::HandleScope handle_scope(isolate);
10558 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010559 templ->SetClassName(v8_str("Fun"));
10560 Local<Function> cons = templ->GetFunction();
10561 context->Global()->Set(v8_str("Fun"), cons);
10562 Local<Value> value = CompileRun(
10563 "function test() {"
10564 " try {"
10565 " (new Fun()).blah()"
10566 " } catch (e) {"
10567 " var str = String(e);"
machenbach@chromium.orga03ba1e2014-02-01 08:54:43 +000010568 // " if (str.indexOf('TypeError') == -1) return 1;"
10569 // " if (str.indexOf('[object Fun]') != -1) return 2;"
10570 // " if (str.indexOf('#<Fun>') == -1) return 3;"
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010571 " return 0;"
10572 " }"
10573 " return 4;"
10574 "}"
10575 "test();");
10576 CHECK_EQ(0, value->Int32Value());
10577}
10578
10579
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010580THREADED_TEST(EvalAliasedDynamic) {
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010581 LocalContext current;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000010582 v8::HandleScope scope(current->GetIsolate());
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010583
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010584 // Tests where aliased eval can only be resolved dynamically.
10585 Local<Script> script =
10586 Script::Compile(v8_str("function f(x) { "
10587 " var foo = 2;"
10588 " with (x) { return eval('foo'); }"
10589 "}"
10590 "foo = 0;"
10591 "result1 = f(new Object());"
ager@chromium.orge2902be2009-06-08 12:21:35 +000010592 "result2 = f(this);"
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010593 "var x = new Object();"
10594 "x.eval = function(x) { return 1; };"
10595 "result3 = f(x);"));
10596 script->Run();
10597 CHECK_EQ(2, current->Global()->Get(v8_str("result1"))->Int32Value());
10598 CHECK_EQ(0, current->Global()->Get(v8_str("result2"))->Int32Value());
10599 CHECK_EQ(1, current->Global()->Get(v8_str("result3"))->Int32Value());
10600
10601 v8::TryCatch try_catch;
10602 script =
10603 Script::Compile(v8_str("function f(x) { "
10604 " var bar = 2;"
10605 " with (x) { return eval('bar'); }"
10606 "}"
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000010607 "result4 = f(this)"));
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010608 script->Run();
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000010609 CHECK(!try_catch.HasCaught());
10610 CHECK_EQ(2, current->Global()->Get(v8_str("result4"))->Int32Value());
10611
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010612 try_catch.Reset();
10613}
10614
10615
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010616THREADED_TEST(CrossEval) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000010617 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010618 LocalContext other;
10619 LocalContext current;
10620
10621 Local<String> token = v8_str("<security token>");
10622 other->SetSecurityToken(token);
10623 current->SetSecurityToken(token);
10624
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000010625 // Set up reference from current to other.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010626 current->Global()->Set(v8_str("other"), other->Global());
10627
10628 // Check that new variables are introduced in other context.
10629 Local<Script> script =
10630 Script::Compile(v8_str("other.eval('var foo = 1234')"));
10631 script->Run();
10632 Local<Value> foo = other->Global()->Get(v8_str("foo"));
10633 CHECK_EQ(1234, foo->Int32Value());
10634 CHECK(!current->Global()->Has(v8_str("foo")));
10635
10636 // Check that writing to non-existing properties introduces them in
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010637 // the other context.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010638 script =
10639 Script::Compile(v8_str("other.eval('na = 1234')"));
10640 script->Run();
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010641 CHECK_EQ(1234, other->Global()->Get(v8_str("na"))->Int32Value());
10642 CHECK(!current->Global()->Has(v8_str("na")));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010643
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010644 // Check that global variables in current context are not visible in other
10645 // context.
10646 v8::TryCatch try_catch;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010647 script =
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010648 Script::Compile(v8_str("var bar = 42; other.eval('bar');"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010649 Local<Value> result = script->Run();
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010650 CHECK(try_catch.HasCaught());
10651 try_catch.Reset();
10652
10653 // Check that local variables in current context are not visible in other
10654 // context.
10655 script =
10656 Script::Compile(v8_str("(function() { "
10657 " var baz = 87;"
10658 " return other.eval('baz');"
10659 "})();"));
10660 result = script->Run();
10661 CHECK(try_catch.HasCaught());
10662 try_catch.Reset();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010663
10664 // Check that global variables in the other environment are visible
10665 // when evaluting code.
10666 other->Global()->Set(v8_str("bis"), v8_num(1234));
10667 script = Script::Compile(v8_str("other.eval('bis')"));
10668 CHECK_EQ(1234, script->Run()->Int32Value());
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010669 CHECK(!try_catch.HasCaught());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010670
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010671 // Check that the 'this' pointer points to the global object evaluating
10672 // code.
10673 other->Global()->Set(v8_str("t"), other->Global());
10674 script = Script::Compile(v8_str("other.eval('this == t')"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010675 result = script->Run();
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010676 CHECK(result->IsTrue());
10677 CHECK(!try_catch.HasCaught());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010678
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010679 // Check that variables introduced in with-statement are not visible in
10680 // other context.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010681 script =
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010682 Script::Compile(v8_str("with({x:2}){other.eval('x')}"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010683 result = script->Run();
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010684 CHECK(try_catch.HasCaught());
10685 try_catch.Reset();
ager@chromium.org3bf7b912008-11-17 09:09:45 +000010686
10687 // Check that you cannot use 'eval.call' with another object than the
10688 // current global object.
ager@chromium.org3bf7b912008-11-17 09:09:45 +000010689 script =
10690 Script::Compile(v8_str("other.y = 1; eval.call(other, 'y')"));
10691 result = script->Run();
10692 CHECK(try_catch.HasCaught());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010693}
10694
10695
ager@chromium.orge2902be2009-06-08 12:21:35 +000010696// Test that calling eval in a context which has been detached from
10697// its global throws an exception. This behavior is consistent with
10698// other JavaScript implementations.
10699THREADED_TEST(EvalInDetachedGlobal) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000010700 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000010701 v8::HandleScope scope(isolate);
ager@chromium.orge2902be2009-06-08 12:21:35 +000010702
ulan@chromium.org57ff8812013-05-10 08:16:55 +000010703 v8::Local<Context> context0 = Context::New(isolate);
10704 v8::Local<Context> context1 = Context::New(isolate);
ager@chromium.orge2902be2009-06-08 12:21:35 +000010705
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000010706 // Set up function in context0 that uses eval from context0.
ager@chromium.orge2902be2009-06-08 12:21:35 +000010707 context0->Enter();
10708 v8::Handle<v8::Value> fun =
10709 CompileRun("var x = 42;"
10710 "(function() {"
10711 " var e = eval;"
10712 " return function(s) { return e(s); }"
10713 "})()");
10714 context0->Exit();
10715
10716 // Put the function into context1 and call it before and after
10717 // detaching the global. Before detaching, the call succeeds and
10718 // after detaching and exception is thrown.
10719 context1->Enter();
10720 context1->Global()->Set(v8_str("fun"), fun);
10721 v8::Handle<v8::Value> x_value = CompileRun("fun('x')");
10722 CHECK_EQ(42, x_value->Int32Value());
10723 context0->DetachGlobal();
10724 v8::TryCatch catcher;
10725 x_value = CompileRun("fun('x')");
10726 CHECK(x_value.IsEmpty());
10727 CHECK(catcher.HasCaught());
10728 context1->Exit();
ager@chromium.orge2902be2009-06-08 12:21:35 +000010729}
10730
10731
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010732THREADED_TEST(CrossLazyLoad) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000010733 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010734 LocalContext other;
10735 LocalContext current;
10736
10737 Local<String> token = v8_str("<security token>");
10738 other->SetSecurityToken(token);
10739 current->SetSecurityToken(token);
10740
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000010741 // Set up reference from current to other.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010742 current->Global()->Set(v8_str("other"), other->Global());
10743
10744 // Trigger lazy loading in other context.
10745 Local<Script> script =
10746 Script::Compile(v8_str("other.eval('new Date(42)')"));
10747 Local<Value> value = script->Run();
10748 CHECK_EQ(42.0, value->NumberValue());
10749}
10750
10751
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010752static void call_as_function(const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010753 ApiTestFuzzer::Fuzz();
sgjesse@chromium.org05521fc2009-05-21 07:37:44 +000010754 if (args.IsConstructCall()) {
10755 if (args[0]->IsInt32()) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010756 args.GetReturnValue().Set(v8_num(-args[0]->Int32Value()));
10757 return;
sgjesse@chromium.org05521fc2009-05-21 07:37:44 +000010758 }
10759 }
10760
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010761 args.GetReturnValue().Set(args[0]);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010762}
10763
10764
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +000010765static void ReturnThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
10766 args.GetReturnValue().Set(args.This());
10767}
10768
10769
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010770// Test that a call handler can be set for objects which will allow
10771// non-function objects created through the API to be called as
10772// functions.
10773THREADED_TEST(CallAsFunction) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010774 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010775 v8::Isolate* isolate = context->GetIsolate();
10776 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010777
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010778 { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
lrn@chromium.org1c092762011-05-09 09:42:16 +000010779 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
10780 instance_template->SetCallAsFunctionHandler(call_as_function);
10781 Local<v8::Object> instance = t->GetFunction()->NewInstance();
10782 context->Global()->Set(v8_str("obj"), instance);
10783 v8::TryCatch try_catch;
10784 Local<Value> value;
10785 CHECK(!try_catch.HasCaught());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010786
lrn@chromium.org1c092762011-05-09 09:42:16 +000010787 value = CompileRun("obj(42)");
10788 CHECK(!try_catch.HasCaught());
10789 CHECK_EQ(42, value->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010790
lrn@chromium.org1c092762011-05-09 09:42:16 +000010791 value = CompileRun("(function(o){return o(49)})(obj)");
10792 CHECK(!try_catch.HasCaught());
10793 CHECK_EQ(49, value->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010794
lrn@chromium.org1c092762011-05-09 09:42:16 +000010795 // test special case of call as function
10796 value = CompileRun("[obj]['0'](45)");
10797 CHECK(!try_catch.HasCaught());
10798 CHECK_EQ(45, value->Int32Value());
ager@chromium.org9258b6b2008-09-11 09:11:10 +000010799
lrn@chromium.org1c092762011-05-09 09:42:16 +000010800 value = CompileRun("obj.call = Function.prototype.call;"
10801 "obj.call(null, 87)");
10802 CHECK(!try_catch.HasCaught());
10803 CHECK_EQ(87, value->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010804
lrn@chromium.org1c092762011-05-09 09:42:16 +000010805 // Regression tests for bug #1116356: Calling call through call/apply
10806 // must work for non-function receivers.
10807 const char* apply_99 = "Function.prototype.call.apply(obj, [this, 99])";
10808 value = CompileRun(apply_99);
10809 CHECK(!try_catch.HasCaught());
10810 CHECK_EQ(99, value->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010811
lrn@chromium.org1c092762011-05-09 09:42:16 +000010812 const char* call_17 = "Function.prototype.call.call(obj, this, 17)";
10813 value = CompileRun(call_17);
10814 CHECK(!try_catch.HasCaught());
10815 CHECK_EQ(17, value->Int32Value());
ager@chromium.org9085a012009-05-11 19:22:57 +000010816
lrn@chromium.org1c092762011-05-09 09:42:16 +000010817 // Check that the call-as-function handler can be called through
10818 // new.
10819 value = CompileRun("new obj(43)");
10820 CHECK(!try_catch.HasCaught());
10821 CHECK_EQ(-43, value->Int32Value());
10822
10823 // Check that the call-as-function handler can be called through
10824 // the API.
10825 v8::Handle<Value> args[] = { v8_num(28) };
10826 value = instance->CallAsFunction(instance, 1, args);
10827 CHECK(!try_catch.HasCaught());
10828 CHECK_EQ(28, value->Int32Value());
10829 }
10830
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010831 { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000010832 Local<ObjectTemplate> instance_template(t->InstanceTemplate());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000010833 USE(instance_template);
lrn@chromium.org1c092762011-05-09 09:42:16 +000010834 Local<v8::Object> instance = t->GetFunction()->NewInstance();
10835 context->Global()->Set(v8_str("obj2"), instance);
10836 v8::TryCatch try_catch;
10837 Local<Value> value;
10838 CHECK(!try_catch.HasCaught());
10839
10840 // Call an object without call-as-function handler through the JS
10841 value = CompileRun("obj2(28)");
10842 CHECK(value.IsEmpty());
10843 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000010844 String::Utf8Value exception_value1(try_catch.Exception());
machenbach@chromium.orga03ba1e2014-02-01 08:54:43 +000010845 // TODO(verwaest): Better message
10846 CHECK_EQ("TypeError: object is not a function",
lrn@chromium.org1c092762011-05-09 09:42:16 +000010847 *exception_value1);
10848 try_catch.Reset();
10849
10850 // Call an object without call-as-function handler through the API
10851 value = CompileRun("obj2(28)");
10852 v8::Handle<Value> args[] = { v8_num(28) };
10853 value = instance->CallAsFunction(instance, 1, args);
10854 CHECK(value.IsEmpty());
10855 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000010856 String::Utf8Value exception_value2(try_catch.Exception());
lrn@chromium.org1c092762011-05-09 09:42:16 +000010857 CHECK_EQ("TypeError: [object Object] is not a function", *exception_value2);
10858 try_catch.Reset();
10859 }
10860
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010861 { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
lrn@chromium.org1c092762011-05-09 09:42:16 +000010862 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
10863 instance_template->SetCallAsFunctionHandler(ThrowValue);
10864 Local<v8::Object> instance = t->GetFunction()->NewInstance();
10865 context->Global()->Set(v8_str("obj3"), instance);
10866 v8::TryCatch try_catch;
10867 Local<Value> value;
10868 CHECK(!try_catch.HasCaught());
10869
10870 // Catch the exception which is thrown by call-as-function handler
10871 value = CompileRun("obj3(22)");
10872 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000010873 String::Utf8Value exception_value1(try_catch.Exception());
lrn@chromium.org1c092762011-05-09 09:42:16 +000010874 CHECK_EQ("22", *exception_value1);
10875 try_catch.Reset();
10876
10877 v8::Handle<Value> args[] = { v8_num(23) };
10878 value = instance->CallAsFunction(instance, 1, args);
10879 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000010880 String::Utf8Value exception_value2(try_catch.Exception());
lrn@chromium.org1c092762011-05-09 09:42:16 +000010881 CHECK_EQ("23", *exception_value2);
10882 try_catch.Reset();
10883 }
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +000010884
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010885 { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +000010886 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
10887 instance_template->SetCallAsFunctionHandler(ReturnThis);
10888 Local<v8::Object> instance = t->GetFunction()->NewInstance();
10889
10890 Local<v8::Value> a1 =
10891 instance->CallAsFunction(v8::Undefined(isolate), 0, NULL);
10892 CHECK(a1->StrictEquals(instance));
10893 Local<v8::Value> a2 =
10894 instance->CallAsFunction(v8::Null(isolate), 0, NULL);
10895 CHECK(a2->StrictEquals(instance));
10896 Local<v8::Value> a3 =
10897 instance->CallAsFunction(v8_num(42), 0, NULL);
10898 CHECK(a3->StrictEquals(instance));
10899 Local<v8::Value> a4 =
10900 instance->CallAsFunction(v8_str("hello"), 0, NULL);
10901 CHECK(a4->StrictEquals(instance));
10902 Local<v8::Value> a5 =
10903 instance->CallAsFunction(v8::True(isolate), 0, NULL);
10904 CHECK(a5->StrictEquals(instance));
10905 }
10906
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010907 { CompileRun(
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +000010908 "function ReturnThisSloppy() {"
10909 " return this;"
10910 "}"
10911 "function ReturnThisStrict() {"
10912 " 'use strict';"
10913 " return this;"
10914 "}");
10915 Local<Function> ReturnThisSloppy =
10916 Local<Function>::Cast(
10917 context->Global()->Get(v8_str("ReturnThisSloppy")));
10918 Local<Function> ReturnThisStrict =
10919 Local<Function>::Cast(
10920 context->Global()->Get(v8_str("ReturnThisStrict")));
10921
10922 Local<v8::Value> a1 =
10923 ReturnThisSloppy->CallAsFunction(v8::Undefined(isolate), 0, NULL);
10924 CHECK(a1->StrictEquals(context->Global()));
10925 Local<v8::Value> a2 =
10926 ReturnThisSloppy->CallAsFunction(v8::Null(isolate), 0, NULL);
10927 CHECK(a2->StrictEquals(context->Global()));
10928 Local<v8::Value> a3 =
10929 ReturnThisSloppy->CallAsFunction(v8_num(42), 0, NULL);
10930 CHECK(a3->IsNumberObject());
10931 CHECK_EQ(42.0, a3.As<v8::NumberObject>()->ValueOf());
10932 Local<v8::Value> a4 =
10933 ReturnThisSloppy->CallAsFunction(v8_str("hello"), 0, NULL);
10934 CHECK(a4->IsStringObject());
10935 CHECK(a4.As<v8::StringObject>()->ValueOf()->StrictEquals(v8_str("hello")));
10936 Local<v8::Value> a5 =
10937 ReturnThisSloppy->CallAsFunction(v8::True(isolate), 0, NULL);
10938 CHECK(a5->IsBooleanObject());
10939 CHECK(a5.As<v8::BooleanObject>()->ValueOf());
10940
10941 Local<v8::Value> a6 =
10942 ReturnThisStrict->CallAsFunction(v8::Undefined(isolate), 0, NULL);
10943 CHECK(a6->IsUndefined());
10944 Local<v8::Value> a7 =
10945 ReturnThisStrict->CallAsFunction(v8::Null(isolate), 0, NULL);
10946 CHECK(a7->IsNull());
10947 Local<v8::Value> a8 =
10948 ReturnThisStrict->CallAsFunction(v8_num(42), 0, NULL);
10949 CHECK(a8->StrictEquals(v8_num(42)));
10950 Local<v8::Value> a9 =
10951 ReturnThisStrict->CallAsFunction(v8_str("hello"), 0, NULL);
10952 CHECK(a9->StrictEquals(v8_str("hello")));
10953 Local<v8::Value> a10 =
10954 ReturnThisStrict->CallAsFunction(v8::True(isolate), 0, NULL);
10955 CHECK(a10->StrictEquals(v8::True(isolate)));
10956 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010957}
10958
10959
karlklose@chromium.org83a47282011-05-11 11:54:09 +000010960// Check whether a non-function object is callable.
10961THREADED_TEST(CallableObject) {
karlklose@chromium.org83a47282011-05-11 11:54:09 +000010962 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010963 v8::Isolate* isolate = context->GetIsolate();
10964 v8::HandleScope scope(isolate);
karlklose@chromium.org83a47282011-05-11 11:54:09 +000010965
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000010966 { Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
karlklose@chromium.org83a47282011-05-11 11:54:09 +000010967 instance_template->SetCallAsFunctionHandler(call_as_function);
10968 Local<Object> instance = instance_template->NewInstance();
10969 v8::TryCatch try_catch;
10970
10971 CHECK(instance->IsCallable());
10972 CHECK(!try_catch.HasCaught());
10973 }
10974
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000010975 { Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
karlklose@chromium.org83a47282011-05-11 11:54:09 +000010976 Local<Object> instance = instance_template->NewInstance();
10977 v8::TryCatch try_catch;
10978
10979 CHECK(!instance->IsCallable());
10980 CHECK(!try_catch.HasCaught());
10981 }
10982
10983 { Local<FunctionTemplate> function_template =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010984 FunctionTemplate::New(isolate, call_as_function);
karlklose@chromium.org83a47282011-05-11 11:54:09 +000010985 Local<Function> function = function_template->GetFunction();
10986 Local<Object> instance = function;
10987 v8::TryCatch try_catch;
10988
10989 CHECK(instance->IsCallable());
10990 CHECK(!try_catch.HasCaught());
10991 }
10992
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010993 { Local<FunctionTemplate> function_template = FunctionTemplate::New(isolate);
karlklose@chromium.org83a47282011-05-11 11:54:09 +000010994 Local<Function> function = function_template->GetFunction();
10995 Local<Object> instance = function;
10996 v8::TryCatch try_catch;
10997
10998 CHECK(instance->IsCallable());
10999 CHECK(!try_catch.HasCaught());
11000 }
11001}
11002
11003
machenbach@chromium.org4610c282014-01-09 10:39:51 +000011004static int Recurse(v8::Isolate* isolate, int depth, int iterations) {
11005 v8::HandleScope scope(isolate);
11006 if (depth == 0) return v8::HandleScope::NumberOfHandles(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011007 for (int i = 0; i < iterations; i++) {
machenbach@chromium.org4610c282014-01-09 10:39:51 +000011008 Local<v8::Number> n(v8::Integer::New(isolate, 42));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011009 }
machenbach@chromium.org4610c282014-01-09 10:39:51 +000011010 return Recurse(isolate, depth - 1, iterations);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011011}
11012
11013
11014THREADED_TEST(HandleIteration) {
11015 static const int kIterations = 500;
11016 static const int kNesting = 200;
machenbach@chromium.org4610c282014-01-09 10:39:51 +000011017 LocalContext context;
11018 v8::Isolate* isolate = context->GetIsolate();
11019 v8::HandleScope scope0(isolate);
11020 CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011021 {
machenbach@chromium.org4610c282014-01-09 10:39:51 +000011022 v8::HandleScope scope1(isolate);
11023 CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011024 for (int i = 0; i < kIterations; i++) {
ulan@chromium.org0f13e742014-01-03 15:51:11 +000011025 Local<v8::Number> n(v8::Integer::New(CcTest::isolate(), 42));
machenbach@chromium.org4610c282014-01-09 10:39:51 +000011026 CHECK_EQ(i + 1, v8::HandleScope::NumberOfHandles(isolate));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011027 }
11028
machenbach@chromium.org4610c282014-01-09 10:39:51 +000011029 CHECK_EQ(kIterations, v8::HandleScope::NumberOfHandles(isolate));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011030 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011031 v8::HandleScope scope2(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011032 for (int j = 0; j < kIterations; j++) {
ulan@chromium.org0f13e742014-01-03 15:51:11 +000011033 Local<v8::Number> n(v8::Integer::New(CcTest::isolate(), 42));
machenbach@chromium.org4610c282014-01-09 10:39:51 +000011034 CHECK_EQ(j + 1 + kIterations,
11035 v8::HandleScope::NumberOfHandles(isolate));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011036 }
11037 }
machenbach@chromium.org4610c282014-01-09 10:39:51 +000011038 CHECK_EQ(kIterations, v8::HandleScope::NumberOfHandles(isolate));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011039 }
machenbach@chromium.org4610c282014-01-09 10:39:51 +000011040 CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
11041 CHECK_EQ(kNesting * kIterations, Recurse(isolate, kNesting, kIterations));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011042}
11043
11044
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011045static void InterceptorHasOwnPropertyGetter(
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011046 Local<String> name,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011047 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011048 ApiTestFuzzer::Fuzz();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011049}
11050
11051
11052THREADED_TEST(InterceptorHasOwnProperty) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011053 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000011054 v8::Isolate* isolate = context->GetIsolate();
11055 v8::HandleScope scope(isolate);
11056 Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011057 Local<v8::ObjectTemplate> instance_templ = fun_templ->InstanceTemplate();
11058 instance_templ->SetNamedPropertyHandler(InterceptorHasOwnPropertyGetter);
11059 Local<Function> function = fun_templ->GetFunction();
11060 context->Global()->Set(v8_str("constructor"), function);
11061 v8::Handle<Value> value = CompileRun(
11062 "var o = new constructor();"
11063 "o.hasOwnProperty('ostehaps');");
11064 CHECK_EQ(false, value->BooleanValue());
11065 value = CompileRun(
11066 "o.ostehaps = 42;"
11067 "o.hasOwnProperty('ostehaps');");
11068 CHECK_EQ(true, value->BooleanValue());
11069 value = CompileRun(
11070 "var p = new constructor();"
11071 "p.hasOwnProperty('ostehaps');");
11072 CHECK_EQ(false, value->BooleanValue());
11073}
11074
11075
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011076static void InterceptorHasOwnPropertyGetterGC(
ager@chromium.org9085a012009-05-11 19:22:57 +000011077 Local<String> name,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011078 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.org9085a012009-05-11 19:22:57 +000011079 ApiTestFuzzer::Fuzz();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011080 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org9085a012009-05-11 19:22:57 +000011081}
11082
11083
11084THREADED_TEST(InterceptorHasOwnPropertyCausingGC) {
ager@chromium.org9085a012009-05-11 19:22:57 +000011085 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000011086 v8::Isolate* isolate = context->GetIsolate();
11087 v8::HandleScope scope(isolate);
11088 Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(isolate);
ager@chromium.org9085a012009-05-11 19:22:57 +000011089 Local<v8::ObjectTemplate> instance_templ = fun_templ->InstanceTemplate();
11090 instance_templ->SetNamedPropertyHandler(InterceptorHasOwnPropertyGetterGC);
11091 Local<Function> function = fun_templ->GetFunction();
11092 context->Global()->Set(v8_str("constructor"), function);
11093 // Let's first make some stuff so we can be sure to get a good GC.
11094 CompileRun(
11095 "function makestr(size) {"
11096 " switch (size) {"
11097 " case 1: return 'f';"
11098 " case 2: return 'fo';"
11099 " case 3: return 'foo';"
11100 " }"
11101 " return makestr(size >> 1) + makestr((size + 1) >> 1);"
11102 "}"
11103 "var x = makestr(12345);"
11104 "x = makestr(31415);"
11105 "x = makestr(23456);");
11106 v8::Handle<Value> value = CompileRun(
11107 "var o = new constructor();"
11108 "o.__proto__ = new String(x);"
11109 "o.hasOwnProperty('ostehaps');");
11110 CHECK_EQ(false, value->BooleanValue());
11111}
11112
11113
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011114typedef void (*NamedPropertyGetter)(
11115 Local<String> property,
11116 const v8::PropertyCallbackInfo<v8::Value>& info);
ager@chromium.orge2902be2009-06-08 12:21:35 +000011117
11118
11119static void CheckInterceptorLoadIC(NamedPropertyGetter getter,
11120 const char* source,
11121 int expected) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011122 v8::Isolate* isolate = CcTest::isolate();
11123 v8::HandleScope scope(isolate);
11124 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
vegorov@chromium.org21b5e952010-11-23 10:24:40 +000011125 templ->SetNamedPropertyHandler(getter, 0, 0, 0, 0, v8_str("data"));
ager@chromium.orge2902be2009-06-08 12:21:35 +000011126 LocalContext context;
11127 context->Global()->Set(v8_str("o"), templ->NewInstance());
11128 v8::Handle<Value> value = CompileRun(source);
11129 CHECK_EQ(expected, value->Int32Value());
11130}
11131
11132
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011133static void InterceptorLoadICGetter(
11134 Local<String> name,
11135 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011136 ApiTestFuzzer::Fuzz();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011137 v8::Isolate* isolate = CcTest::isolate();
jkummerow@chromium.org28faa982012-04-13 09:58:30 +000011138 CHECK_EQ(isolate, info.GetIsolate());
vegorov@chromium.org21b5e952010-11-23 10:24:40 +000011139 CHECK_EQ(v8_str("data"), info.Data());
11140 CHECK_EQ(v8_str("x"), name);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000011141 info.GetReturnValue().Set(v8::Integer::New(isolate, 42));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011142}
11143
11144
11145// This test should hit the load IC for the interceptor case.
11146THREADED_TEST(InterceptorLoadIC) {
ager@chromium.orge2902be2009-06-08 12:21:35 +000011147 CheckInterceptorLoadIC(InterceptorLoadICGetter,
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011148 "var result = 0;"
11149 "for (var i = 0; i < 1000; i++) {"
11150 " result = o.x;"
ager@chromium.orge2902be2009-06-08 12:21:35 +000011151 "}",
11152 42);
11153}
11154
11155
11156// Below go several tests which verify that JITing for various
11157// configurations of interceptor and explicit fields works fine
11158// (those cases are special cased to get better performance).
11159
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011160static void InterceptorLoadXICGetter(
11161 Local<String> name,
11162 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.orge2902be2009-06-08 12:21:35 +000011163 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011164 info.GetReturnValue().Set(
11165 v8_str("x")->Equals(name) ?
ulan@chromium.org0f13e742014-01-03 15:51:11 +000011166 v8::Handle<v8::Value>(v8::Integer::New(info.GetIsolate(), 42)) :
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011167 v8::Handle<v8::Value>());
ager@chromium.orge2902be2009-06-08 12:21:35 +000011168}
11169
11170
11171THREADED_TEST(InterceptorLoadICWithFieldOnHolder) {
11172 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
11173 "var result = 0;"
11174 "o.y = 239;"
11175 "for (var i = 0; i < 1000; i++) {"
11176 " result = o.y;"
11177 "}",
11178 239);
11179}
11180
11181
11182THREADED_TEST(InterceptorLoadICWithSubstitutedProto) {
11183 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
11184 "var result = 0;"
11185 "o.__proto__ = { 'y': 239 };"
11186 "for (var i = 0; i < 1000; i++) {"
11187 " result = o.y + o.x;"
11188 "}",
11189 239 + 42);
11190}
11191
11192
11193THREADED_TEST(InterceptorLoadICWithPropertyOnProto) {
11194 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
11195 "var result = 0;"
11196 "o.__proto__.y = 239;"
11197 "for (var i = 0; i < 1000; i++) {"
11198 " result = o.y + o.x;"
11199 "}",
11200 239 + 42);
11201}
11202
11203
11204THREADED_TEST(InterceptorLoadICUndefined) {
11205 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
11206 "var result = 0;"
11207 "for (var i = 0; i < 1000; i++) {"
11208 " result = (o.y == undefined) ? 239 : 42;"
11209 "}",
11210 239);
11211}
11212
11213
11214THREADED_TEST(InterceptorLoadICWithOverride) {
11215 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
11216 "fst = new Object(); fst.__proto__ = o;"
11217 "snd = new Object(); snd.__proto__ = fst;"
11218 "var result1 = 0;"
11219 "for (var i = 0; i < 1000; i++) {"
11220 " result1 = snd.x;"
11221 "}"
11222 "fst.x = 239;"
11223 "var result = 0;"
11224 "for (var i = 0; i < 1000; i++) {"
11225 " result = snd.x;"
11226 "}"
11227 "result + result1",
11228 239 + 42);
11229}
11230
11231
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011232// Test the case when we stored field into
11233// a stub, but interceptor produced value on its own.
11234THREADED_TEST(InterceptorLoadICFieldNotNeeded) {
11235 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
11236 "proto = new Object();"
11237 "o.__proto__ = proto;"
11238 "proto.x = 239;"
11239 "for (var i = 0; i < 1000; i++) {"
11240 " o.x;"
11241 // Now it should be ICed and keep a reference to x defined on proto
11242 "}"
11243 "var result = 0;"
11244 "for (var i = 0; i < 1000; i++) {"
11245 " result += o.x;"
11246 "}"
11247 "result;",
11248 42 * 1000);
11249}
11250
11251
11252// Test the case when we stored field into
11253// a stub, but it got invalidated later on.
11254THREADED_TEST(InterceptorLoadICInvalidatedField) {
11255 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
11256 "proto1 = new Object();"
11257 "proto2 = new Object();"
11258 "o.__proto__ = proto1;"
11259 "proto1.__proto__ = proto2;"
11260 "proto2.y = 239;"
11261 "for (var i = 0; i < 1000; i++) {"
11262 " o.y;"
11263 // Now it should be ICed and keep a reference to y defined on proto2
11264 "}"
11265 "proto1.y = 42;"
11266 "var result = 0;"
11267 "for (var i = 0; i < 1000; i++) {"
11268 " result += o.y;"
11269 "}"
11270 "result;",
11271 42 * 1000);
11272}
11273
11274
ager@chromium.orgb26c50a2010-03-26 09:27:16 +000011275static int interceptor_load_not_handled_calls = 0;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011276static void InterceptorLoadNotHandled(
11277 Local<String> name,
11278 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.orgb26c50a2010-03-26 09:27:16 +000011279 ++interceptor_load_not_handled_calls;
ager@chromium.orgb26c50a2010-03-26 09:27:16 +000011280}
11281
11282
11283// Test how post-interceptor lookups are done in the non-cacheable
11284// case: the interceptor should not be invoked during this lookup.
11285THREADED_TEST(InterceptorLoadICPostInterceptor) {
11286 interceptor_load_not_handled_calls = 0;
11287 CheckInterceptorLoadIC(InterceptorLoadNotHandled,
11288 "receiver = new Object();"
11289 "receiver.__proto__ = o;"
11290 "proto = new Object();"
11291 "/* Make proto a slow-case object. */"
11292 "for (var i = 0; i < 1000; i++) {"
11293 " proto[\"xxxxxxxx\" + i] = [];"
11294 "}"
11295 "proto.x = 17;"
11296 "o.__proto__ = proto;"
11297 "var result = 0;"
11298 "for (var i = 0; i < 1000; i++) {"
11299 " result += receiver.x;"
11300 "}"
11301 "result;",
11302 17 * 1000);
11303 CHECK_EQ(1000, interceptor_load_not_handled_calls);
11304}
11305
11306
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011307// Test the case when we stored field into
11308// a stub, but it got invalidated later on due to override on
11309// global object which is between interceptor and fields' holders.
11310THREADED_TEST(InterceptorLoadICInvalidatedFieldViaGlobal) {
11311 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
11312 "o.__proto__ = this;" // set a global to be a proto of o.
11313 "this.__proto__.y = 239;"
11314 "for (var i = 0; i < 10; i++) {"
11315 " if (o.y != 239) throw 'oops: ' + o.y;"
11316 // Now it should be ICed and keep a reference to y defined on field_holder.
11317 "}"
11318 "this.y = 42;" // Assign on a global.
11319 "var result = 0;"
11320 "for (var i = 0; i < 10; i++) {"
11321 " result += o.y;"
11322 "}"
11323 "result;",
11324 42 * 10);
11325}
11326
11327
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011328static void SetOnThis(Local<String> name,
11329 Local<Value> value,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011330 const v8::PropertyCallbackInfo<void>& info) {
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011331 info.This()->ForceSet(name, value);
11332}
11333
11334
11335THREADED_TEST(InterceptorLoadICWithCallbackOnHolder) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011336 v8::Isolate* isolate = CcTest::isolate();
11337 v8::HandleScope scope(isolate);
11338 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011339 templ->SetNamedPropertyHandler(InterceptorLoadXICGetter);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011340 templ->SetAccessor(v8_str("y"), Return239Callback);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011341 LocalContext context;
11342 context->Global()->Set(v8_str("o"), templ->NewInstance());
ricow@chromium.org30ce4112010-05-31 10:38:25 +000011343
11344 // Check the case when receiver and interceptor's holder
11345 // are the same objects.
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011346 v8::Handle<Value> value = CompileRun(
11347 "var result = 0;"
11348 "for (var i = 0; i < 7; i++) {"
11349 " result = o.y;"
11350 "}");
11351 CHECK_EQ(239, value->Int32Value());
ricow@chromium.org30ce4112010-05-31 10:38:25 +000011352
11353 // Check the case when interceptor's holder is in proto chain
11354 // of receiver.
11355 value = CompileRun(
11356 "r = { __proto__: o };"
11357 "var result = 0;"
11358 "for (var i = 0; i < 7; i++) {"
11359 " result = r.y;"
11360 "}");
11361 CHECK_EQ(239, value->Int32Value());
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011362}
11363
11364
11365THREADED_TEST(InterceptorLoadICWithCallbackOnProto) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011366 v8::Isolate* isolate = CcTest::isolate();
11367 v8::HandleScope scope(isolate);
11368 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011369 templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011370 v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New(isolate);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011371 templ_p->SetAccessor(v8_str("y"), Return239Callback);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011372
11373 LocalContext context;
11374 context->Global()->Set(v8_str("o"), templ_o->NewInstance());
11375 context->Global()->Set(v8_str("p"), templ_p->NewInstance());
11376
ricow@chromium.org30ce4112010-05-31 10:38:25 +000011377 // Check the case when receiver and interceptor's holder
11378 // are the same objects.
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011379 v8::Handle<Value> value = CompileRun(
11380 "o.__proto__ = p;"
11381 "var result = 0;"
11382 "for (var i = 0; i < 7; i++) {"
11383 " result = o.x + o.y;"
11384 "}");
11385 CHECK_EQ(239 + 42, value->Int32Value());
ricow@chromium.org30ce4112010-05-31 10:38:25 +000011386
11387 // Check the case when interceptor's holder is in proto chain
11388 // of receiver.
11389 value = CompileRun(
11390 "r = { __proto__: o };"
11391 "var result = 0;"
11392 "for (var i = 0; i < 7; i++) {"
11393 " result = r.x + r.y;"
11394 "}");
11395 CHECK_EQ(239 + 42, value->Int32Value());
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011396}
11397
11398
11399THREADED_TEST(InterceptorLoadICForCallbackWithOverride) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011400 v8::Isolate* isolate = CcTest::isolate();
11401 v8::HandleScope scope(isolate);
11402 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011403 templ->SetNamedPropertyHandler(InterceptorLoadXICGetter);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011404 templ->SetAccessor(v8_str("y"), Return239Callback);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011405
11406 LocalContext context;
11407 context->Global()->Set(v8_str("o"), templ->NewInstance());
11408
11409 v8::Handle<Value> value = CompileRun(
11410 "fst = new Object(); fst.__proto__ = o;"
11411 "snd = new Object(); snd.__proto__ = fst;"
11412 "var result1 = 0;"
11413 "for (var i = 0; i < 7; i++) {"
11414 " result1 = snd.x;"
11415 "}"
11416 "fst.x = 239;"
11417 "var result = 0;"
11418 "for (var i = 0; i < 7; i++) {"
11419 " result = snd.x;"
11420 "}"
11421 "result + result1");
11422 CHECK_EQ(239 + 42, value->Int32Value());
11423}
11424
11425
11426// Test the case when we stored callback into
11427// a stub, but interceptor produced value on its own.
11428THREADED_TEST(InterceptorLoadICCallbackNotNeeded) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011429 v8::Isolate* isolate = CcTest::isolate();
11430 v8::HandleScope scope(isolate);
11431 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011432 templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011433 v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New(isolate);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011434 templ_p->SetAccessor(v8_str("y"), Return239Callback);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011435
11436 LocalContext context;
11437 context->Global()->Set(v8_str("o"), templ_o->NewInstance());
11438 context->Global()->Set(v8_str("p"), templ_p->NewInstance());
11439
11440 v8::Handle<Value> value = CompileRun(
11441 "o.__proto__ = p;"
11442 "for (var i = 0; i < 7; i++) {"
11443 " o.x;"
11444 // Now it should be ICed and keep a reference to x defined on p
11445 "}"
11446 "var result = 0;"
11447 "for (var i = 0; i < 7; i++) {"
11448 " result += o.x;"
11449 "}"
11450 "result");
11451 CHECK_EQ(42 * 7, value->Int32Value());
11452}
11453
11454
11455// Test the case when we stored callback into
11456// a stub, but it got invalidated later on.
11457THREADED_TEST(InterceptorLoadICInvalidatedCallback) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011458 v8::Isolate* isolate = CcTest::isolate();
11459 v8::HandleScope scope(isolate);
11460 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011461 templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011462 v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New(isolate);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011463 templ_p->SetAccessor(v8_str("y"), Return239Callback, SetOnThis);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011464
11465 LocalContext context;
11466 context->Global()->Set(v8_str("o"), templ_o->NewInstance());
11467 context->Global()->Set(v8_str("p"), templ_p->NewInstance());
11468
11469 v8::Handle<Value> value = CompileRun(
11470 "inbetween = new Object();"
11471 "o.__proto__ = inbetween;"
11472 "inbetween.__proto__ = p;"
11473 "for (var i = 0; i < 10; i++) {"
11474 " o.y;"
11475 // Now it should be ICed and keep a reference to y defined on p
11476 "}"
11477 "inbetween.y = 42;"
11478 "var result = 0;"
11479 "for (var i = 0; i < 10; i++) {"
11480 " result += o.y;"
11481 "}"
11482 "result");
11483 CHECK_EQ(42 * 10, value->Int32Value());
11484}
11485
11486
11487// Test the case when we stored callback into
11488// a stub, but it got invalidated later on due to override on
11489// global object which is between interceptor and callbacks' holders.
11490THREADED_TEST(InterceptorLoadICInvalidatedCallbackViaGlobal) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011491 v8::Isolate* isolate = CcTest::isolate();
11492 v8::HandleScope scope(isolate);
11493 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011494 templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011495 v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New(isolate);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011496 templ_p->SetAccessor(v8_str("y"), Return239Callback, SetOnThis);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011497
11498 LocalContext context;
11499 context->Global()->Set(v8_str("o"), templ_o->NewInstance());
11500 context->Global()->Set(v8_str("p"), templ_p->NewInstance());
11501
11502 v8::Handle<Value> value = CompileRun(
11503 "o.__proto__ = this;"
11504 "this.__proto__ = p;"
11505 "for (var i = 0; i < 10; i++) {"
11506 " if (o.y != 239) throw 'oops: ' + o.y;"
11507 // Now it should be ICed and keep a reference to y defined on p
11508 "}"
11509 "this.y = 42;"
11510 "var result = 0;"
11511 "for (var i = 0; i < 10; i++) {"
11512 " result += o.y;"
11513 "}"
11514 "result");
11515 CHECK_EQ(42 * 10, value->Int32Value());
11516}
11517
11518
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011519static void InterceptorLoadICGetter0(
11520 Local<String> name,
11521 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.orge2902be2009-06-08 12:21:35 +000011522 ApiTestFuzzer::Fuzz();
11523 CHECK(v8_str("x")->Equals(name));
ulan@chromium.org0f13e742014-01-03 15:51:11 +000011524 info.GetReturnValue().Set(v8::Integer::New(info.GetIsolate(), 0));
ager@chromium.orge2902be2009-06-08 12:21:35 +000011525}
11526
11527
11528THREADED_TEST(InterceptorReturningZero) {
11529 CheckInterceptorLoadIC(InterceptorLoadICGetter0,
11530 "o.x == undefined ? 1 : 0",
11531 0);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011532}
11533
11534
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011535static void InterceptorStoreICSetter(
11536 Local<String> key,
11537 Local<Value> value,
11538 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011539 CHECK(v8_str("x")->Equals(key));
11540 CHECK_EQ(42, value->Int32Value());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011541 info.GetReturnValue().Set(value);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011542}
11543
11544
11545// This test should hit the store IC for the interceptor case.
11546THREADED_TEST(InterceptorStoreIC) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011547 v8::Isolate* isolate = CcTest::isolate();
11548 v8::HandleScope scope(isolate);
11549 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011550 templ->SetNamedPropertyHandler(InterceptorLoadICGetter,
vegorov@chromium.org21b5e952010-11-23 10:24:40 +000011551 InterceptorStoreICSetter,
11552 0, 0, 0, v8_str("data"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011553 LocalContext context;
11554 context->Global()->Set(v8_str("o"), templ->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000011555 CompileRun(
11556 "for (var i = 0; i < 1000; i++) {"
11557 " o.x = 42;"
11558 "}");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011559}
11560
11561
ager@chromium.orgeadaf222009-06-16 09:43:10 +000011562THREADED_TEST(InterceptorStoreICWithNoSetter) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011563 v8::Isolate* isolate = CcTest::isolate();
11564 v8::HandleScope scope(isolate);
11565 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.orgeadaf222009-06-16 09:43:10 +000011566 templ->SetNamedPropertyHandler(InterceptorLoadXICGetter);
11567 LocalContext context;
11568 context->Global()->Set(v8_str("o"), templ->NewInstance());
11569 v8::Handle<Value> value = CompileRun(
11570 "for (var i = 0; i < 1000; i++) {"
11571 " o.y = 239;"
11572 "}"
11573 "42 + o.y");
11574 CHECK_EQ(239 + 42, value->Int32Value());
11575}
11576
11577
11578
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011579
11580v8::Handle<Value> call_ic_function;
11581v8::Handle<Value> call_ic_function2;
11582v8::Handle<Value> call_ic_function3;
11583
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011584static void InterceptorCallICGetter(
11585 Local<String> name,
11586 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011587 ApiTestFuzzer::Fuzz();
11588 CHECK(v8_str("x")->Equals(name));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011589 info.GetReturnValue().Set(call_ic_function);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011590}
11591
11592
11593// This test should hit the call IC for the interceptor case.
11594THREADED_TEST(InterceptorCallIC) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011595 v8::Isolate* isolate = CcTest::isolate();
11596 v8::HandleScope scope(isolate);
11597 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011598 templ->SetNamedPropertyHandler(InterceptorCallICGetter);
11599 LocalContext context;
11600 context->Global()->Set(v8_str("o"), templ->NewInstance());
11601 call_ic_function =
11602 v8_compile("function f(x) { return x + 1; }; f")->Run();
11603 v8::Handle<Value> value = CompileRun(
11604 "var result = 0;"
11605 "for (var i = 0; i < 1000; i++) {"
11606 " result = o.x(41);"
11607 "}");
11608 CHECK_EQ(42, value->Int32Value());
11609}
11610
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011611
11612// This test checks that if interceptor doesn't provide
11613// a value, we can fetch regular value.
11614THREADED_TEST(InterceptorCallICSeesOthers) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011615 v8::Isolate* isolate = CcTest::isolate();
11616 v8::HandleScope scope(isolate);
11617 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011618 templ->SetNamedPropertyHandler(NoBlockGetterX);
11619 LocalContext context;
11620 context->Global()->Set(v8_str("o"), templ->NewInstance());
11621 v8::Handle<Value> value = CompileRun(
11622 "o.x = function f(x) { return x + 1; };"
11623 "var result = 0;"
11624 "for (var i = 0; i < 7; i++) {"
11625 " result = o.x(41);"
11626 "}");
11627 CHECK_EQ(42, value->Int32Value());
11628}
11629
11630
11631static v8::Handle<Value> call_ic_function4;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011632static void InterceptorCallICGetter4(
11633 Local<String> name,
11634 const v8::PropertyCallbackInfo<v8::Value>& info) {
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011635 ApiTestFuzzer::Fuzz();
11636 CHECK(v8_str("x")->Equals(name));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011637 info.GetReturnValue().Set(call_ic_function4);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011638}
11639
11640
11641// This test checks that if interceptor provides a function,
11642// even if we cached shadowed variant, interceptor's function
11643// is invoked
11644THREADED_TEST(InterceptorCallICCacheableNotNeeded) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011645 v8::Isolate* isolate = CcTest::isolate();
11646 v8::HandleScope scope(isolate);
11647 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011648 templ->SetNamedPropertyHandler(InterceptorCallICGetter4);
11649 LocalContext context;
11650 context->Global()->Set(v8_str("o"), templ->NewInstance());
11651 call_ic_function4 =
11652 v8_compile("function f(x) { return x - 1; }; f")->Run();
11653 v8::Handle<Value> value = CompileRun(
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +000011654 "Object.getPrototypeOf(o).x = function(x) { return x + 1; };"
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011655 "var result = 0;"
11656 "for (var i = 0; i < 1000; i++) {"
11657 " result = o.x(42);"
11658 "}");
11659 CHECK_EQ(41, value->Int32Value());
11660}
11661
11662
11663// Test the case when we stored cacheable lookup into
11664// a stub, but it got invalidated later on
11665THREADED_TEST(InterceptorCallICInvalidatedCacheable) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011666 v8::Isolate* isolate = CcTest::isolate();
11667 v8::HandleScope scope(isolate);
11668 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011669 templ->SetNamedPropertyHandler(NoBlockGetterX);
11670 LocalContext context;
11671 context->Global()->Set(v8_str("o"), templ->NewInstance());
11672 v8::Handle<Value> value = CompileRun(
11673 "proto1 = new Object();"
11674 "proto2 = new Object();"
11675 "o.__proto__ = proto1;"
11676 "proto1.__proto__ = proto2;"
11677 "proto2.y = function(x) { return x + 1; };"
11678 // Invoke it many times to compile a stub
11679 "for (var i = 0; i < 7; i++) {"
11680 " o.y(42);"
11681 "}"
11682 "proto1.y = function(x) { return x - 1; };"
11683 "var result = 0;"
11684 "for (var i = 0; i < 7; i++) {"
11685 " result += o.y(42);"
11686 "}");
11687 CHECK_EQ(41 * 7, value->Int32Value());
11688}
11689
11690
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011691// This test checks that if interceptor doesn't provide a function,
11692// cached constant function is used
11693THREADED_TEST(InterceptorCallICConstantFunctionUsed) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011694 v8::Isolate* isolate = CcTest::isolate();
11695 v8::HandleScope scope(isolate);
11696 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011697 templ->SetNamedPropertyHandler(NoBlockGetterX);
11698 LocalContext context;
11699 context->Global()->Set(v8_str("o"), templ->NewInstance());
11700 v8::Handle<Value> value = CompileRun(
11701 "function inc(x) { return x + 1; };"
11702 "inc(1);"
11703 "o.x = inc;"
11704 "var result = 0;"
11705 "for (var i = 0; i < 1000; i++) {"
11706 " result = o.x(42);"
11707 "}");
11708 CHECK_EQ(43, value->Int32Value());
11709}
11710
11711
ulan@chromium.org2efb9002012-01-19 15:36:35 +000011712static v8::Handle<Value> call_ic_function5;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011713static void InterceptorCallICGetter5(
11714 Local<String> name,
11715 const v8::PropertyCallbackInfo<v8::Value>& info) {
ulan@chromium.org2efb9002012-01-19 15:36:35 +000011716 ApiTestFuzzer::Fuzz();
11717 if (v8_str("x")->Equals(name))
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011718 info.GetReturnValue().Set(call_ic_function5);
ulan@chromium.org2efb9002012-01-19 15:36:35 +000011719}
11720
11721
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011722// This test checks that if interceptor provides a function,
11723// even if we cached constant function, interceptor's function
11724// is invoked
11725THREADED_TEST(InterceptorCallICConstantFunctionNotNeeded) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011726 v8::Isolate* isolate = CcTest::isolate();
11727 v8::HandleScope scope(isolate);
11728 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011729 templ->SetNamedPropertyHandler(InterceptorCallICGetter5);
11730 LocalContext context;
11731 context->Global()->Set(v8_str("o"), templ->NewInstance());
11732 call_ic_function5 =
11733 v8_compile("function f(x) { return x - 1; }; f")->Run();
11734 v8::Handle<Value> value = CompileRun(
11735 "function inc(x) { return x + 1; };"
11736 "inc(1);"
11737 "o.x = inc;"
11738 "var result = 0;"
11739 "for (var i = 0; i < 1000; i++) {"
11740 " result = o.x(42);"
11741 "}");
11742 CHECK_EQ(41, value->Int32Value());
11743}
11744
11745
ulan@chromium.org2efb9002012-01-19 15:36:35 +000011746static v8::Handle<Value> call_ic_function6;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011747static void InterceptorCallICGetter6(
11748 Local<String> name,
11749 const v8::PropertyCallbackInfo<v8::Value>& info) {
ulan@chromium.org2efb9002012-01-19 15:36:35 +000011750 ApiTestFuzzer::Fuzz();
11751 if (v8_str("x")->Equals(name))
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011752 info.GetReturnValue().Set(call_ic_function6);
ulan@chromium.org2efb9002012-01-19 15:36:35 +000011753}
11754
11755
11756// Same test as above, except the code is wrapped in a function
11757// to test the optimized compiler.
11758THREADED_TEST(InterceptorCallICConstantFunctionNotNeededWrapped) {
11759 i::FLAG_allow_natives_syntax = true;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011760 v8::Isolate* isolate = CcTest::isolate();
11761 v8::HandleScope scope(isolate);
11762 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
ulan@chromium.org2efb9002012-01-19 15:36:35 +000011763 templ->SetNamedPropertyHandler(InterceptorCallICGetter6);
11764 LocalContext context;
11765 context->Global()->Set(v8_str("o"), templ->NewInstance());
11766 call_ic_function6 =
11767 v8_compile("function f(x) { return x - 1; }; f")->Run();
11768 v8::Handle<Value> value = CompileRun(
11769 "function inc(x) { return x + 1; };"
11770 "inc(1);"
11771 "o.x = inc;"
11772 "function test() {"
11773 " var result = 0;"
11774 " for (var i = 0; i < 1000; i++) {"
11775 " result = o.x(42);"
11776 " }"
11777 " return result;"
11778 "};"
11779 "test();"
11780 "test();"
11781 "test();"
11782 "%OptimizeFunctionOnNextCall(test);"
11783 "test()");
11784 CHECK_EQ(41, value->Int32Value());
11785}
11786
11787
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011788// Test the case when we stored constant function into
11789// a stub, but it got invalidated later on
11790THREADED_TEST(InterceptorCallICInvalidatedConstantFunction) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011791 v8::Isolate* isolate = CcTest::isolate();
11792 v8::HandleScope scope(isolate);
11793 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011794 templ->SetNamedPropertyHandler(NoBlockGetterX);
11795 LocalContext context;
11796 context->Global()->Set(v8_str("o"), templ->NewInstance());
11797 v8::Handle<Value> value = CompileRun(
11798 "function inc(x) { return x + 1; };"
11799 "inc(1);"
11800 "proto1 = new Object();"
11801 "proto2 = new Object();"
11802 "o.__proto__ = proto1;"
11803 "proto1.__proto__ = proto2;"
11804 "proto2.y = inc;"
11805 // Invoke it many times to compile a stub
11806 "for (var i = 0; i < 7; i++) {"
11807 " o.y(42);"
11808 "}"
11809 "proto1.y = function(x) { return x - 1; };"
11810 "var result = 0;"
11811 "for (var i = 0; i < 7; i++) {"
11812 " result += o.y(42);"
11813 "}");
11814 CHECK_EQ(41 * 7, value->Int32Value());
11815}
11816
11817
11818// Test the case when we stored constant function into
11819// a stub, but it got invalidated later on due to override on
11820// global object which is between interceptor and constant function' holders.
11821THREADED_TEST(InterceptorCallICInvalidatedConstantFunctionViaGlobal) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011822 v8::Isolate* isolate = CcTest::isolate();
11823 v8::HandleScope scope(isolate);
11824 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011825 templ->SetNamedPropertyHandler(NoBlockGetterX);
11826 LocalContext context;
11827 context->Global()->Set(v8_str("o"), templ->NewInstance());
11828 v8::Handle<Value> value = CompileRun(
11829 "function inc(x) { return x + 1; };"
11830 "inc(1);"
11831 "o.__proto__ = this;"
11832 "this.__proto__.y = inc;"
11833 // Invoke it many times to compile a stub
11834 "for (var i = 0; i < 7; i++) {"
11835 " if (o.y(42) != 43) throw 'oops: ' + o.y(42);"
11836 "}"
11837 "this.y = function(x) { return x - 1; };"
11838 "var result = 0;"
11839 "for (var i = 0; i < 7; i++) {"
11840 " result += o.y(42);"
11841 "}");
11842 CHECK_EQ(41 * 7, value->Int32Value());
11843}
11844
11845
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000011846// Test the case when actual function to call sits on global object.
11847THREADED_TEST(InterceptorCallICCachedFromGlobal) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011848 v8::Isolate* isolate = CcTest::isolate();
11849 v8::HandleScope scope(isolate);
11850 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000011851 templ_o->SetNamedPropertyHandler(NoBlockGetterX);
11852
11853 LocalContext context;
11854 context->Global()->Set(v8_str("o"), templ_o->NewInstance());
11855
11856 v8::Handle<Value> value = CompileRun(
11857 "try {"
11858 " o.__proto__ = this;"
11859 " for (var i = 0; i < 10; i++) {"
11860 " var v = o.parseFloat('239');"
11861 " if (v != 239) throw v;"
11862 // Now it should be ICed and keep a reference to parseFloat.
11863 " }"
11864 " var result = 0;"
11865 " for (var i = 0; i < 10; i++) {"
11866 " result += o.parseFloat('239');"
11867 " }"
11868 " result"
11869 "} catch(e) {"
11870 " e"
11871 "};");
11872 CHECK_EQ(239 * 10, value->Int32Value());
11873}
11874
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011875static void InterceptorCallICFastApi(
11876 Local<String> name,
11877 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.org5c838252010-02-19 08:53:10 +000011878 ApiTestFuzzer::Fuzz();
dslomov@chromium.orgb752d402013-06-18 11:54:54 +000011879 CheckReturnValue(info, FUNCTION_ADDR(InterceptorCallICFastApi));
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000011880 int* call_count =
11881 reinterpret_cast<int*>(v8::External::Cast(*info.Data())->Value());
ager@chromium.org5c838252010-02-19 08:53:10 +000011882 ++(*call_count);
11883 if ((*call_count) % 20 == 0) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011884 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org5c838252010-02-19 08:53:10 +000011885 }
ager@chromium.org5c838252010-02-19 08:53:10 +000011886}
11887
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011888static void FastApiCallback_TrivialSignature(
11889 const v8::FunctionCallbackInfo<v8::Value>& args) {
ager@chromium.org5c838252010-02-19 08:53:10 +000011890 ApiTestFuzzer::Fuzz();
dslomov@chromium.orgb752d402013-06-18 11:54:54 +000011891 CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_TrivialSignature));
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011892 v8::Isolate* isolate = CcTest::isolate();
jkummerow@chromium.org28faa982012-04-13 09:58:30 +000011893 CHECK_EQ(isolate, args.GetIsolate());
ager@chromium.org5c838252010-02-19 08:53:10 +000011894 CHECK_EQ(args.This(), args.Holder());
11895 CHECK(args.Data()->Equals(v8_str("method_data")));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011896 args.GetReturnValue().Set(args[0]->Int32Value() + 1);
ager@chromium.org5c838252010-02-19 08:53:10 +000011897}
11898
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011899static void FastApiCallback_SimpleSignature(
11900 const v8::FunctionCallbackInfo<v8::Value>& args) {
ager@chromium.org5c838252010-02-19 08:53:10 +000011901 ApiTestFuzzer::Fuzz();
dslomov@chromium.orgb752d402013-06-18 11:54:54 +000011902 CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_SimpleSignature));
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011903 v8::Isolate* isolate = CcTest::isolate();
jkummerow@chromium.org28faa982012-04-13 09:58:30 +000011904 CHECK_EQ(isolate, args.GetIsolate());
ager@chromium.org5c838252010-02-19 08:53:10 +000011905 CHECK_EQ(args.This()->GetPrototype(), args.Holder());
11906 CHECK(args.Data()->Equals(v8_str("method_data")));
11907 // Note, we're using HasRealNamedProperty instead of Has to avoid
11908 // invoking the interceptor again.
11909 CHECK(args.Holder()->HasRealNamedProperty(v8_str("foo")));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011910 args.GetReturnValue().Set(args[0]->Int32Value() + 1);
ager@chromium.org5c838252010-02-19 08:53:10 +000011911}
11912
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000011913
ager@chromium.org5c838252010-02-19 08:53:10 +000011914// Helper to maximize the odds of object moving.
11915static void GenerateSomeGarbage() {
11916 CompileRun(
11917 "var garbage;"
11918 "for (var i = 0; i < 1000; i++) {"
11919 " garbage = [1/i, \"garbage\" + i, garbage, {foo: garbage}];"
11920 "}"
11921 "garbage = undefined;");
11922}
11923
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000011924
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011925void DirectApiCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +000011926 static int count = 0;
11927 if (count++ % 3 == 0) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011928 CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
yangguo@chromium.orgd2899aa2012-06-21 11:16:20 +000011929 // This should move the stub
ricow@chromium.org83aa5492011-02-07 12:42:56 +000011930 GenerateSomeGarbage(); // This should ensure the old stub memory is flushed
11931 }
ricow@chromium.org83aa5492011-02-07 12:42:56 +000011932}
11933
11934
11935THREADED_TEST(CallICFastApi_DirectCall_GCMoveStub) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +000011936 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000011937 v8::Isolate* isolate = context->GetIsolate();
11938 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011939 v8::Handle<v8::ObjectTemplate> nativeobject_templ =
11940 v8::ObjectTemplate::New(isolate);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000011941 nativeobject_templ->Set(isolate, "callback",
11942 v8::FunctionTemplate::New(isolate,
11943 DirectApiCallback));
ricow@chromium.org83aa5492011-02-07 12:42:56 +000011944 v8::Local<v8::Object> nativeobject_obj = nativeobject_templ->NewInstance();
11945 context->Global()->Set(v8_str("nativeobject"), nativeobject_obj);
11946 // call the api function multiple times to ensure direct call stub creation.
11947 CompileRun(
11948 "function f() {"
11949 " for (var i = 1; i <= 30; i++) {"
11950 " nativeobject.callback();"
11951 " }"
11952 "}"
11953 "f();");
11954}
11955
11956
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011957void ThrowingDirectApiCallback(
11958 const v8::FunctionCallbackInfo<v8::Value>& args) {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000011959 args.GetIsolate()->ThrowException(v8_str("g"));
ricow@chromium.org83aa5492011-02-07 12:42:56 +000011960}
11961
11962
11963THREADED_TEST(CallICFastApi_DirectCall_Throw) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +000011964 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000011965 v8::Isolate* isolate = context->GetIsolate();
11966 v8::HandleScope scope(isolate);
11967 v8::Handle<v8::ObjectTemplate> nativeobject_templ =
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011968 v8::ObjectTemplate::New(isolate);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000011969 nativeobject_templ->Set(isolate, "callback",
11970 v8::FunctionTemplate::New(isolate,
11971 ThrowingDirectApiCallback));
ricow@chromium.org83aa5492011-02-07 12:42:56 +000011972 v8::Local<v8::Object> nativeobject_obj = nativeobject_templ->NewInstance();
11973 context->Global()->Set(v8_str("nativeobject"), nativeobject_obj);
11974 // call the api function multiple times to ensure direct call stub creation.
11975 v8::Handle<Value> result = CompileRun(
11976 "var result = '';"
11977 "function f() {"
11978 " for (var i = 1; i <= 5; i++) {"
11979 " try { nativeobject.callback(); } catch (e) { result += e; }"
11980 " }"
11981 "}"
11982 "f(); result;");
11983 CHECK_EQ(v8_str("ggggg"), result);
11984}
11985
11986
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000011987static Handle<Value> DoDirectGetter() {
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000011988 if (++p_getter_count % 3 == 0) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011989 CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000011990 GenerateSomeGarbage();
11991 }
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000011992 return v8_str("Direct Getter Result");
11993}
11994
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000011995static void DirectGetterCallback(
11996 Local<String> name,
11997 const v8::PropertyCallbackInfo<v8::Value>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +000011998 CheckReturnValue(info, FUNCTION_ADDR(DirectGetterCallback));
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000011999 info.GetReturnValue().Set(DoDirectGetter());
12000}
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000012001
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000012002
12003template<typename Accessor>
12004static void LoadICFastApi_DirectCall_GCMoveStub(Accessor accessor) {
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000012005 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012006 v8::Isolate* isolate = context->GetIsolate();
12007 v8::HandleScope scope(isolate);
12008 v8::Handle<v8::ObjectTemplate> obj = v8::ObjectTemplate::New(isolate);
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000012009 obj->SetAccessor(v8_str("p1"), accessor);
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000012010 context->Global()->Set(v8_str("o1"), obj->NewInstance());
12011 p_getter_count = 0;
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000012012 v8::Handle<v8::Value> result = CompileRun(
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000012013 "function f() {"
12014 " for (var i = 0; i < 30; i++) o1.p1;"
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000012015 " return o1.p1"
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000012016 "}"
12017 "f();");
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000012018 CHECK_EQ(v8_str("Direct Getter Result"), result);
12019 CHECK_EQ(31, p_getter_count);
12020}
12021
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012022
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012023THREADED_PROFILED_TEST(LoadICFastApi_DirectCall_GCMoveStub) {
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000012024 LoadICFastApi_DirectCall_GCMoveStub(DirectGetterCallback);
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000012025}
12026
12027
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012028void ThrowingDirectGetterCallback(
12029 Local<String> name,
12030 const v8::PropertyCallbackInfo<v8::Value>& info) {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000012031 info.GetIsolate()->ThrowException(v8_str("g"));
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000012032}
12033
12034
12035THREADED_TEST(LoadICFastApi_DirectCall_Throw) {
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000012036 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012037 v8::Isolate* isolate = context->GetIsolate();
12038 v8::HandleScope scope(isolate);
12039 v8::Handle<v8::ObjectTemplate> obj = v8::ObjectTemplate::New(isolate);
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000012040 obj->SetAccessor(v8_str("p1"), ThrowingDirectGetterCallback);
12041 context->Global()->Set(v8_str("o1"), obj->NewInstance());
12042 v8::Handle<Value> result = CompileRun(
12043 "var result = '';"
12044 "for (var i = 0; i < 5; i++) {"
12045 " try { o1.p1; } catch (e) { result += e; }"
12046 "}"
12047 "result;");
12048 CHECK_EQ(v8_str("ggggg"), result);
12049}
12050
12051
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012052THREADED_PROFILED_TEST(InterceptorCallICFastApi_TrivialSignature) {
ager@chromium.org5c838252010-02-19 08:53:10 +000012053 int interceptor_call_count = 0;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012054 v8::Isolate* isolate = CcTest::isolate();
12055 v8::HandleScope scope(isolate);
12056 v8::Handle<v8::FunctionTemplate> fun_templ =
12057 v8::FunctionTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +000012058 v8::Handle<v8::FunctionTemplate> method_templ =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012059 v8::FunctionTemplate::New(isolate,
12060 FastApiCallback_TrivialSignature,
ager@chromium.org5c838252010-02-19 08:53:10 +000012061 v8_str("method_data"),
12062 v8::Handle<v8::Signature>());
12063 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12064 proto_templ->Set(v8_str("method"), method_templ);
12065 v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
machenbach@chromium.org0cc09502013-11-13 12:20:55 +000012066 templ->SetNamedPropertyHandler(
12067 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012068 v8::External::New(isolate, &interceptor_call_count));
ager@chromium.org5c838252010-02-19 08:53:10 +000012069 LocalContext context;
12070 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12071 GenerateSomeGarbage();
12072 context->Global()->Set(v8_str("o"), fun->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012073 CompileRun(
ager@chromium.org5c838252010-02-19 08:53:10 +000012074 "var result = 0;"
12075 "for (var i = 0; i < 100; i++) {"
12076 " result = o.method(41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012077 "}");
ager@chromium.org5c838252010-02-19 08:53:10 +000012078 CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
12079 CHECK_EQ(100, interceptor_call_count);
12080}
12081
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012082
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012083THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature) {
ager@chromium.org5c838252010-02-19 08:53:10 +000012084 int interceptor_call_count = 0;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012085 v8::Isolate* isolate = CcTest::isolate();
12086 v8::HandleScope scope(isolate);
12087 v8::Handle<v8::FunctionTemplate> fun_templ =
12088 v8::FunctionTemplate::New(isolate);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000012089 v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012090 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12091 v8::Signature::New(isolate, fun_templ));
ager@chromium.org5c838252010-02-19 08:53:10 +000012092 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12093 proto_templ->Set(v8_str("method"), method_templ);
mmassi@chromium.org49a44672012-12-04 13:52:03 +000012094 fun_templ->SetHiddenPrototype(true);
ager@chromium.org5c838252010-02-19 08:53:10 +000012095 v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
machenbach@chromium.org0cc09502013-11-13 12:20:55 +000012096 templ->SetNamedPropertyHandler(
12097 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012098 v8::External::New(isolate, &interceptor_call_count));
ager@chromium.org5c838252010-02-19 08:53:10 +000012099 LocalContext context;
12100 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12101 GenerateSomeGarbage();
12102 context->Global()->Set(v8_str("o"), fun->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012103 CompileRun(
ager@chromium.org5c838252010-02-19 08:53:10 +000012104 "o.foo = 17;"
12105 "var receiver = {};"
12106 "receiver.__proto__ = o;"
12107 "var result = 0;"
12108 "for (var i = 0; i < 100; i++) {"
12109 " result = receiver.method(41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012110 "}");
ager@chromium.org5c838252010-02-19 08:53:10 +000012111 CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
12112 CHECK_EQ(100, interceptor_call_count);
12113}
12114
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012115
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012116THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss1) {
ager@chromium.org5c838252010-02-19 08:53:10 +000012117 int interceptor_call_count = 0;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012118 v8::Isolate* isolate = CcTest::isolate();
12119 v8::HandleScope scope(isolate);
12120 v8::Handle<v8::FunctionTemplate> fun_templ =
12121 v8::FunctionTemplate::New(isolate);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000012122 v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012123 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12124 v8::Signature::New(isolate, fun_templ));
ager@chromium.org5c838252010-02-19 08:53:10 +000012125 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12126 proto_templ->Set(v8_str("method"), method_templ);
mmassi@chromium.org49a44672012-12-04 13:52:03 +000012127 fun_templ->SetHiddenPrototype(true);
ager@chromium.org5c838252010-02-19 08:53:10 +000012128 v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
machenbach@chromium.org0cc09502013-11-13 12:20:55 +000012129 templ->SetNamedPropertyHandler(
12130 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012131 v8::External::New(isolate, &interceptor_call_count));
ager@chromium.org5c838252010-02-19 08:53:10 +000012132 LocalContext context;
12133 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12134 GenerateSomeGarbage();
12135 context->Global()->Set(v8_str("o"), fun->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012136 CompileRun(
ager@chromium.org5c838252010-02-19 08:53:10 +000012137 "o.foo = 17;"
12138 "var receiver = {};"
12139 "receiver.__proto__ = o;"
12140 "var result = 0;"
12141 "var saved_result = 0;"
12142 "for (var i = 0; i < 100; i++) {"
12143 " result = receiver.method(41);"
12144 " if (i == 50) {"
12145 " saved_result = result;"
12146 " receiver = {method: function(x) { return x - 1 }};"
12147 " }"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012148 "}");
ager@chromium.org5c838252010-02-19 08:53:10 +000012149 CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
12150 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
12151 CHECK_GE(interceptor_call_count, 50);
12152}
12153
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012154
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012155THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss2) {
ager@chromium.org5c838252010-02-19 08:53:10 +000012156 int interceptor_call_count = 0;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012157 v8::Isolate* isolate = CcTest::isolate();
12158 v8::HandleScope scope(isolate);
12159 v8::Handle<v8::FunctionTemplate> fun_templ =
12160 v8::FunctionTemplate::New(isolate);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000012161 v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012162 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12163 v8::Signature::New(isolate, fun_templ));
ager@chromium.org5c838252010-02-19 08:53:10 +000012164 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12165 proto_templ->Set(v8_str("method"), method_templ);
mmassi@chromium.org49a44672012-12-04 13:52:03 +000012166 fun_templ->SetHiddenPrototype(true);
ager@chromium.org5c838252010-02-19 08:53:10 +000012167 v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
machenbach@chromium.org0cc09502013-11-13 12:20:55 +000012168 templ->SetNamedPropertyHandler(
12169 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012170 v8::External::New(isolate, &interceptor_call_count));
ager@chromium.org5c838252010-02-19 08:53:10 +000012171 LocalContext context;
12172 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12173 GenerateSomeGarbage();
12174 context->Global()->Set(v8_str("o"), fun->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012175 CompileRun(
ager@chromium.org5c838252010-02-19 08:53:10 +000012176 "o.foo = 17;"
12177 "var receiver = {};"
12178 "receiver.__proto__ = o;"
12179 "var result = 0;"
12180 "var saved_result = 0;"
12181 "for (var i = 0; i < 100; i++) {"
12182 " result = receiver.method(41);"
12183 " if (i == 50) {"
12184 " saved_result = result;"
12185 " o.method = function(x) { return x - 1 };"
12186 " }"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012187 "}");
ager@chromium.org5c838252010-02-19 08:53:10 +000012188 CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
12189 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
12190 CHECK_GE(interceptor_call_count, 50);
12191}
12192
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012193
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012194THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss3) {
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000012195 int interceptor_call_count = 0;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012196 v8::Isolate* isolate = CcTest::isolate();
12197 v8::HandleScope scope(isolate);
12198 v8::Handle<v8::FunctionTemplate> fun_templ =
12199 v8::FunctionTemplate::New(isolate);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000012200 v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012201 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12202 v8::Signature::New(isolate, fun_templ));
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000012203 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12204 proto_templ->Set(v8_str("method"), method_templ);
mmassi@chromium.org49a44672012-12-04 13:52:03 +000012205 fun_templ->SetHiddenPrototype(true);
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000012206 v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
machenbach@chromium.org0cc09502013-11-13 12:20:55 +000012207 templ->SetNamedPropertyHandler(
12208 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012209 v8::External::New(isolate, &interceptor_call_count));
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000012210 LocalContext context;
12211 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12212 GenerateSomeGarbage();
12213 context->Global()->Set(v8_str("o"), fun->NewInstance());
12214 v8::TryCatch try_catch;
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012215 CompileRun(
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000012216 "o.foo = 17;"
12217 "var receiver = {};"
12218 "receiver.__proto__ = o;"
12219 "var result = 0;"
12220 "var saved_result = 0;"
12221 "for (var i = 0; i < 100; i++) {"
12222 " result = receiver.method(41);"
12223 " if (i == 50) {"
12224 " saved_result = result;"
12225 " receiver = 333;"
12226 " }"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012227 "}");
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000012228 CHECK(try_catch.HasCaught());
machenbach@chromium.orga03ba1e2014-02-01 08:54:43 +000012229 // TODO(verwaest): Adjust message.
12230 CHECK_EQ(v8_str("TypeError: undefined is not a function"),
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000012231 try_catch.Exception()->ToString());
12232 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
12233 CHECK_GE(interceptor_call_count, 50);
12234}
12235
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012236
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012237THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_TypeError) {
ager@chromium.org5c838252010-02-19 08:53:10 +000012238 int interceptor_call_count = 0;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012239 v8::Isolate* isolate = CcTest::isolate();
12240 v8::HandleScope scope(isolate);
12241 v8::Handle<v8::FunctionTemplate> fun_templ =
12242 v8::FunctionTemplate::New(isolate);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000012243 v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012244 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12245 v8::Signature::New(isolate, fun_templ));
ager@chromium.org5c838252010-02-19 08:53:10 +000012246 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12247 proto_templ->Set(v8_str("method"), method_templ);
mmassi@chromium.org49a44672012-12-04 13:52:03 +000012248 fun_templ->SetHiddenPrototype(true);
ager@chromium.org5c838252010-02-19 08:53:10 +000012249 v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
machenbach@chromium.org0cc09502013-11-13 12:20:55 +000012250 templ->SetNamedPropertyHandler(
12251 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012252 v8::External::New(isolate, &interceptor_call_count));
ager@chromium.org5c838252010-02-19 08:53:10 +000012253 LocalContext context;
12254 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12255 GenerateSomeGarbage();
12256 context->Global()->Set(v8_str("o"), fun->NewInstance());
12257 v8::TryCatch try_catch;
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012258 CompileRun(
ager@chromium.org5c838252010-02-19 08:53:10 +000012259 "o.foo = 17;"
12260 "var receiver = {};"
12261 "receiver.__proto__ = o;"
12262 "var result = 0;"
12263 "var saved_result = 0;"
12264 "for (var i = 0; i < 100; i++) {"
12265 " result = receiver.method(41);"
12266 " if (i == 50) {"
12267 " saved_result = result;"
12268 " receiver = {method: receiver.method};"
12269 " }"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012270 "}");
ager@chromium.org5c838252010-02-19 08:53:10 +000012271 CHECK(try_catch.HasCaught());
12272 CHECK_EQ(v8_str("TypeError: Illegal invocation"),
12273 try_catch.Exception()->ToString());
12274 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
12275 CHECK_GE(interceptor_call_count, 50);
12276}
12277
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012278
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012279THREADED_PROFILED_TEST(CallICFastApi_TrivialSignature) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012280 v8::Isolate* isolate = CcTest::isolate();
12281 v8::HandleScope scope(isolate);
12282 v8::Handle<v8::FunctionTemplate> fun_templ =
12283 v8::FunctionTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +000012284 v8::Handle<v8::FunctionTemplate> method_templ =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012285 v8::FunctionTemplate::New(isolate,
12286 FastApiCallback_TrivialSignature,
ager@chromium.org5c838252010-02-19 08:53:10 +000012287 v8_str("method_data"),
12288 v8::Handle<v8::Signature>());
12289 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12290 proto_templ->Set(v8_str("method"), method_templ);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000012291 v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012292 USE(templ);
ager@chromium.org5c838252010-02-19 08:53:10 +000012293 LocalContext context;
12294 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12295 GenerateSomeGarbage();
12296 context->Global()->Set(v8_str("o"), fun->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012297 CompileRun(
ager@chromium.org5c838252010-02-19 08:53:10 +000012298 "var result = 0;"
12299 "for (var i = 0; i < 100; i++) {"
12300 " result = o.method(41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012301 "}");
ager@chromium.org5c838252010-02-19 08:53:10 +000012302
12303 CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
12304}
12305
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012306
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012307THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012308 v8::Isolate* isolate = CcTest::isolate();
12309 v8::HandleScope scope(isolate);
12310 v8::Handle<v8::FunctionTemplate> fun_templ =
12311 v8::FunctionTemplate::New(isolate);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000012312 v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012313 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12314 v8::Signature::New(isolate, fun_templ));
ager@chromium.org5c838252010-02-19 08:53:10 +000012315 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12316 proto_templ->Set(v8_str("method"), method_templ);
mmassi@chromium.org49a44672012-12-04 13:52:03 +000012317 fun_templ->SetHiddenPrototype(true);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000012318 v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012319 CHECK(!templ.IsEmpty());
ager@chromium.org5c838252010-02-19 08:53:10 +000012320 LocalContext context;
12321 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12322 GenerateSomeGarbage();
12323 context->Global()->Set(v8_str("o"), fun->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012324 CompileRun(
ager@chromium.org5c838252010-02-19 08:53:10 +000012325 "o.foo = 17;"
12326 "var receiver = {};"
12327 "receiver.__proto__ = o;"
12328 "var result = 0;"
12329 "for (var i = 0; i < 100; i++) {"
12330 " result = receiver.method(41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012331 "}");
ager@chromium.org5c838252010-02-19 08:53:10 +000012332
12333 CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
12334}
12335
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012336
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012337THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss1) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012338 v8::Isolate* isolate = CcTest::isolate();
12339 v8::HandleScope scope(isolate);
12340 v8::Handle<v8::FunctionTemplate> fun_templ =
12341 v8::FunctionTemplate::New(isolate);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000012342 v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012343 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12344 v8::Signature::New(isolate, fun_templ));
ager@chromium.org5c838252010-02-19 08:53:10 +000012345 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12346 proto_templ->Set(v8_str("method"), method_templ);
mmassi@chromium.org49a44672012-12-04 13:52:03 +000012347 fun_templ->SetHiddenPrototype(true);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000012348 v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012349 CHECK(!templ.IsEmpty());
ager@chromium.org5c838252010-02-19 08:53:10 +000012350 LocalContext context;
12351 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12352 GenerateSomeGarbage();
12353 context->Global()->Set(v8_str("o"), fun->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012354 CompileRun(
ager@chromium.org5c838252010-02-19 08:53:10 +000012355 "o.foo = 17;"
12356 "var receiver = {};"
12357 "receiver.__proto__ = o;"
12358 "var result = 0;"
12359 "var saved_result = 0;"
12360 "for (var i = 0; i < 100; i++) {"
12361 " result = receiver.method(41);"
12362 " if (i == 50) {"
12363 " saved_result = result;"
12364 " receiver = {method: function(x) { return x - 1 }};"
12365 " }"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012366 "}");
ager@chromium.org5c838252010-02-19 08:53:10 +000012367 CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
12368 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
12369}
12370
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012371
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012372THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss2) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012373 v8::Isolate* isolate = CcTest::isolate();
12374 v8::HandleScope scope(isolate);
12375 v8::Handle<v8::FunctionTemplate> fun_templ =
12376 v8::FunctionTemplate::New(isolate);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000012377 v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012378 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12379 v8::Signature::New(isolate, fun_templ));
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000012380 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12381 proto_templ->Set(v8_str("method"), method_templ);
mmassi@chromium.org49a44672012-12-04 13:52:03 +000012382 fun_templ->SetHiddenPrototype(true);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000012383 v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012384 CHECK(!templ.IsEmpty());
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000012385 LocalContext context;
12386 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12387 GenerateSomeGarbage();
12388 context->Global()->Set(v8_str("o"), fun->NewInstance());
12389 v8::TryCatch try_catch;
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012390 CompileRun(
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000012391 "o.foo = 17;"
12392 "var receiver = {};"
12393 "receiver.__proto__ = o;"
12394 "var result = 0;"
12395 "var saved_result = 0;"
12396 "for (var i = 0; i < 100; i++) {"
12397 " result = receiver.method(41);"
12398 " if (i == 50) {"
12399 " saved_result = result;"
12400 " receiver = 333;"
12401 " }"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012402 "}");
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000012403 CHECK(try_catch.HasCaught());
machenbach@chromium.orga03ba1e2014-02-01 08:54:43 +000012404 // TODO(verwaest): Adjust message.
12405 CHECK_EQ(v8_str("TypeError: undefined is not a function"),
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000012406 try_catch.Exception()->ToString());
12407 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
12408}
12409
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012410
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012411THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_TypeError) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012412 v8::Isolate* isolate = CcTest::isolate();
12413 v8::HandleScope scope(isolate);
12414 v8::Handle<v8::FunctionTemplate> fun_templ =
12415 v8::FunctionTemplate::New(isolate);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000012416 v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012417 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12418 v8::Signature::New(isolate, fun_templ));
mmassi@chromium.org49a44672012-12-04 13:52:03 +000012419 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12420 proto_templ->Set(v8_str("method"), method_templ);
12421 fun_templ->SetHiddenPrototype(true);
12422 v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
12423 CHECK(!templ.IsEmpty());
12424 LocalContext context;
12425 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12426 GenerateSomeGarbage();
12427 context->Global()->Set(v8_str("o"), fun->NewInstance());
12428 v8::TryCatch try_catch;
12429 CompileRun(
12430 "o.foo = 17;"
12431 "var receiver = {};"
12432 "receiver.__proto__ = o;"
12433 "var result = 0;"
12434 "var saved_result = 0;"
12435 "for (var i = 0; i < 100; i++) {"
12436 " result = receiver.method(41);"
12437 " if (i == 50) {"
12438 " saved_result = result;"
12439 " receiver = Object.create(receiver);"
12440 " }"
12441 "}");
12442 CHECK(try_catch.HasCaught());
12443 CHECK_EQ(v8_str("TypeError: Illegal invocation"),
12444 try_catch.Exception()->ToString());
12445 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
12446}
12447
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000012448
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012449v8::Handle<Value> keyed_call_ic_function;
12450
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012451static void InterceptorKeyedCallICGetter(
12452 Local<String> name,
12453 const v8::PropertyCallbackInfo<v8::Value>& info) {
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012454 ApiTestFuzzer::Fuzz();
12455 if (v8_str("x")->Equals(name)) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012456 info.GetReturnValue().Set(keyed_call_ic_function);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012457 }
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012458}
12459
12460
12461// Test the case when we stored cacheable lookup into
12462// a stub, but the function name changed (to another cacheable function).
12463THREADED_TEST(InterceptorKeyedCallICKeyChange1) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012464 v8::Isolate* isolate = CcTest::isolate();
12465 v8::HandleScope scope(isolate);
12466 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012467 templ->SetNamedPropertyHandler(NoBlockGetterX);
12468 LocalContext context;
12469 context->Global()->Set(v8_str("o"), templ->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012470 CompileRun(
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012471 "proto = new Object();"
12472 "proto.y = function(x) { return x + 1; };"
12473 "proto.z = function(x) { return x - 1; };"
12474 "o.__proto__ = proto;"
12475 "var result = 0;"
12476 "var method = 'y';"
12477 "for (var i = 0; i < 10; i++) {"
12478 " if (i == 5) { method = 'z'; };"
12479 " result += o[method](41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012480 "}");
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012481 CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
12482}
12483
12484
12485// Test the case when we stored cacheable lookup into
12486// a stub, but the function name changed (and the new function is present
12487// both before and after the interceptor in the prototype chain).
12488THREADED_TEST(InterceptorKeyedCallICKeyChange2) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012489 v8::Isolate* isolate = CcTest::isolate();
12490 v8::HandleScope scope(isolate);
12491 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012492 templ->SetNamedPropertyHandler(InterceptorKeyedCallICGetter);
12493 LocalContext context;
12494 context->Global()->Set(v8_str("proto1"), templ->NewInstance());
12495 keyed_call_ic_function =
12496 v8_compile("function f(x) { return x - 1; }; f")->Run();
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012497 CompileRun(
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012498 "o = new Object();"
12499 "proto2 = new Object();"
12500 "o.y = function(x) { return x + 1; };"
12501 "proto2.y = function(x) { return x + 2; };"
12502 "o.__proto__ = proto1;"
12503 "proto1.__proto__ = proto2;"
12504 "var result = 0;"
12505 "var method = 'x';"
12506 "for (var i = 0; i < 10; i++) {"
12507 " if (i == 5) { method = 'y'; };"
12508 " result += o[method](41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012509 "}");
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012510 CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
12511}
12512
12513
12514// Same as InterceptorKeyedCallICKeyChange1 only the cacheable function sit
12515// on the global object.
12516THREADED_TEST(InterceptorKeyedCallICKeyChangeOnGlobal) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012517 v8::Isolate* isolate = CcTest::isolate();
12518 v8::HandleScope scope(isolate);
12519 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012520 templ->SetNamedPropertyHandler(NoBlockGetterX);
12521 LocalContext context;
12522 context->Global()->Set(v8_str("o"), templ->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012523 CompileRun(
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012524 "function inc(x) { return x + 1; };"
12525 "inc(1);"
12526 "function dec(x) { return x - 1; };"
12527 "dec(1);"
12528 "o.__proto__ = this;"
12529 "this.__proto__.x = inc;"
12530 "this.__proto__.y = dec;"
12531 "var result = 0;"
12532 "var method = 'x';"
12533 "for (var i = 0; i < 10; i++) {"
12534 " if (i == 5) { method = 'y'; };"
12535 " result += o[method](41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012536 "}");
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012537 CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
12538}
12539
12540
12541// Test the case when actual function to call sits on global object.
12542THREADED_TEST(InterceptorKeyedCallICFromGlobal) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012543 v8::Isolate* isolate = CcTest::isolate();
12544 v8::HandleScope scope(isolate);
12545 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012546 templ_o->SetNamedPropertyHandler(NoBlockGetterX);
12547 LocalContext context;
12548 context->Global()->Set(v8_str("o"), templ_o->NewInstance());
12549
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012550 CompileRun(
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012551 "function len(x) { return x.length; };"
12552 "o.__proto__ = this;"
12553 "var m = 'parseFloat';"
12554 "var result = 0;"
12555 "for (var i = 0; i < 10; i++) {"
12556 " if (i == 5) {"
12557 " m = 'len';"
12558 " saved_result = result;"
12559 " };"
12560 " result = o[m]('239');"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012561 "}");
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012562 CHECK_EQ(3, context->Global()->Get(v8_str("result"))->Int32Value());
12563 CHECK_EQ(239, context->Global()->Get(v8_str("saved_result"))->Int32Value());
12564}
12565
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012566
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012567// Test the map transition before the interceptor.
12568THREADED_TEST(InterceptorKeyedCallICMapChangeBefore) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012569 v8::Isolate* isolate = CcTest::isolate();
12570 v8::HandleScope scope(isolate);
12571 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012572 templ_o->SetNamedPropertyHandler(NoBlockGetterX);
12573 LocalContext context;
12574 context->Global()->Set(v8_str("proto"), templ_o->NewInstance());
12575
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012576 CompileRun(
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012577 "var o = new Object();"
12578 "o.__proto__ = proto;"
12579 "o.method = function(x) { return x + 1; };"
12580 "var m = 'method';"
12581 "var result = 0;"
12582 "for (var i = 0; i < 10; i++) {"
12583 " if (i == 5) { o.method = function(x) { return x - 1; }; };"
12584 " result += o[m](41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012585 "}");
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012586 CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
12587}
12588
12589
12590// Test the map transition after the interceptor.
12591THREADED_TEST(InterceptorKeyedCallICMapChangeAfter) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012592 v8::Isolate* isolate = CcTest::isolate();
12593 v8::HandleScope scope(isolate);
12594 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012595 templ_o->SetNamedPropertyHandler(NoBlockGetterX);
12596 LocalContext context;
12597 context->Global()->Set(v8_str("o"), templ_o->NewInstance());
12598
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012599 CompileRun(
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012600 "var proto = new Object();"
12601 "o.__proto__ = proto;"
12602 "proto.method = function(x) { return x + 1; };"
12603 "var m = 'method';"
12604 "var result = 0;"
12605 "for (var i = 0; i < 10; i++) {"
12606 " if (i == 5) { proto.method = function(x) { return x - 1; }; };"
12607 " result += o[m](41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012608 "}");
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012609 CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
12610}
12611
12612
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012613static int interceptor_call_count = 0;
12614
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012615static void InterceptorICRefErrorGetter(
12616 Local<String> name,
12617 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012618 ApiTestFuzzer::Fuzz();
12619 if (v8_str("x")->Equals(name) && interceptor_call_count++ < 20) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012620 info.GetReturnValue().Set(call_ic_function2);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012621 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012622}
12623
12624
12625// This test should hit load and call ICs for the interceptor case.
12626// Once in a while, the interceptor will reply that a property was not
12627// found in which case we should get a reference error.
12628THREADED_TEST(InterceptorICReferenceErrors) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012629 v8::Isolate* isolate = CcTest::isolate();
12630 v8::HandleScope scope(isolate);
12631 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012632 templ->SetNamedPropertyHandler(InterceptorICRefErrorGetter);
12633 LocalContext context(0, templ, v8::Handle<Value>());
12634 call_ic_function2 = v8_compile("function h(x) { return x; }; h")->Run();
12635 v8::Handle<Value> value = CompileRun(
12636 "function f() {"
12637 " for (var i = 0; i < 1000; i++) {"
12638 " try { x; } catch(e) { return true; }"
12639 " }"
12640 " return false;"
12641 "};"
12642 "f();");
12643 CHECK_EQ(true, value->BooleanValue());
12644 interceptor_call_count = 0;
12645 value = CompileRun(
12646 "function g() {"
12647 " for (var i = 0; i < 1000; i++) {"
12648 " try { x(42); } catch(e) { return true; }"
12649 " }"
12650 " return false;"
12651 "};"
12652 "g();");
12653 CHECK_EQ(true, value->BooleanValue());
12654}
12655
12656
12657static int interceptor_ic_exception_get_count = 0;
12658
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012659static void InterceptorICExceptionGetter(
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012660 Local<String> name,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012661 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012662 ApiTestFuzzer::Fuzz();
12663 if (v8_str("x")->Equals(name) && ++interceptor_ic_exception_get_count < 20) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012664 info.GetReturnValue().Set(call_ic_function3);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012665 }
12666 if (interceptor_ic_exception_get_count == 20) {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000012667 info.GetIsolate()->ThrowException(v8_num(42));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012668 return;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012669 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012670}
12671
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012672
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012673// Test interceptor load/call IC where the interceptor throws an
12674// exception once in a while.
12675THREADED_TEST(InterceptorICGetterExceptions) {
12676 interceptor_ic_exception_get_count = 0;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012677 v8::Isolate* isolate = CcTest::isolate();
12678 v8::HandleScope scope(isolate);
12679 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012680 templ->SetNamedPropertyHandler(InterceptorICExceptionGetter);
12681 LocalContext context(0, templ, v8::Handle<Value>());
12682 call_ic_function3 = v8_compile("function h(x) { return x; }; h")->Run();
12683 v8::Handle<Value> value = CompileRun(
12684 "function f() {"
12685 " for (var i = 0; i < 100; i++) {"
12686 " try { x; } catch(e) { return true; }"
12687 " }"
12688 " return false;"
12689 "};"
12690 "f();");
12691 CHECK_EQ(true, value->BooleanValue());
12692 interceptor_ic_exception_get_count = 0;
12693 value = CompileRun(
12694 "function f() {"
12695 " for (var i = 0; i < 100; i++) {"
12696 " try { x(42); } catch(e) { return true; }"
12697 " }"
12698 " return false;"
12699 "};"
12700 "f();");
12701 CHECK_EQ(true, value->BooleanValue());
12702}
12703
12704
12705static int interceptor_ic_exception_set_count = 0;
12706
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012707static void InterceptorICExceptionSetter(
12708 Local<String> key,
12709 Local<Value> value,
12710 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012711 ApiTestFuzzer::Fuzz();
12712 if (++interceptor_ic_exception_set_count > 20) {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000012713 info.GetIsolate()->ThrowException(v8_num(42));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012714 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012715}
12716
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012717
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012718// Test interceptor store IC where the interceptor throws an exception
12719// once in a while.
12720THREADED_TEST(InterceptorICSetterExceptions) {
12721 interceptor_ic_exception_set_count = 0;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012722 v8::Isolate* isolate = CcTest::isolate();
12723 v8::HandleScope scope(isolate);
12724 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012725 templ->SetNamedPropertyHandler(0, InterceptorICExceptionSetter);
12726 LocalContext context(0, templ, v8::Handle<Value>());
12727 v8::Handle<Value> value = CompileRun(
12728 "function f() {"
12729 " for (var i = 0; i < 100; i++) {"
12730 " try { x = 42; } catch(e) { return true; }"
12731 " }"
12732 " return false;"
12733 "};"
12734 "f();");
12735 CHECK_EQ(true, value->BooleanValue());
12736}
12737
12738
12739// Test that we ignore null interceptors.
12740THREADED_TEST(NullNamedInterceptor) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012741 v8::Isolate* isolate = CcTest::isolate();
12742 v8::HandleScope scope(isolate);
12743 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012744 templ->SetNamedPropertyHandler(
12745 static_cast<v8::NamedPropertyGetterCallback>(0));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012746 LocalContext context;
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000012747 templ->Set(CcTest::isolate(), "x", v8_num(42));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012748 v8::Handle<v8::Object> obj = templ->NewInstance();
12749 context->Global()->Set(v8_str("obj"), obj);
12750 v8::Handle<Value> value = CompileRun("obj.x");
12751 CHECK(value->IsInt32());
12752 CHECK_EQ(42, value->Int32Value());
12753}
12754
12755
12756// Test that we ignore null interceptors.
12757THREADED_TEST(NullIndexedInterceptor) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012758 v8::Isolate* isolate = CcTest::isolate();
12759 v8::HandleScope scope(isolate);
12760 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012761 templ->SetIndexedPropertyHandler(
12762 static_cast<v8::IndexedPropertyGetterCallback>(0));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012763 LocalContext context;
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000012764 templ->Set(CcTest::isolate(), "42", v8_num(42));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012765 v8::Handle<v8::Object> obj = templ->NewInstance();
12766 context->Global()->Set(v8_str("obj"), obj);
12767 v8::Handle<Value> value = CompileRun("obj[42]");
12768 CHECK(value->IsInt32());
12769 CHECK_EQ(42, value->Int32Value());
12770}
12771
12772
ricow@chromium.org30ce4112010-05-31 10:38:25 +000012773THREADED_TEST(NamedPropertyHandlerGetterAttributes) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012774 v8::Isolate* isolate = CcTest::isolate();
12775 v8::HandleScope scope(isolate);
12776 v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
ricow@chromium.org30ce4112010-05-31 10:38:25 +000012777 templ->InstanceTemplate()->SetNamedPropertyHandler(InterceptorLoadXICGetter);
12778 LocalContext env;
12779 env->Global()->Set(v8_str("obj"),
12780 templ->GetFunction()->NewInstance());
12781 ExpectTrue("obj.x === 42");
12782 ExpectTrue("!obj.propertyIsEnumerable('x')");
12783}
12784
12785
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012786static void ThrowingGetter(Local<String> name,
12787 const v8::PropertyCallbackInfo<v8::Value>& info) {
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012788 ApiTestFuzzer::Fuzz();
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000012789 info.GetIsolate()->ThrowException(Handle<Value>());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012790 info.GetReturnValue().SetUndefined();
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012791}
12792
12793
12794THREADED_TEST(VariousGetPropertiesAndThrowingCallbacks) {
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012795 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000012796 HandleScope scope(context->GetIsolate());
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012797
ulan@chromium.org0f13e742014-01-03 15:51:11 +000012798 Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012799 Local<ObjectTemplate> instance_templ = templ->InstanceTemplate();
12800 instance_templ->SetAccessor(v8_str("f"), ThrowingGetter);
12801
12802 Local<Object> instance = templ->GetFunction()->NewInstance();
12803
ulan@chromium.org0f13e742014-01-03 15:51:11 +000012804 Local<Object> another = Object::New(context->GetIsolate());
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012805 another->SetPrototype(instance);
12806
12807 Local<Object> with_js_getter = CompileRun(
12808 "o = {};\n"
12809 "o.__defineGetter__('f', function() { throw undefined; });\n"
12810 "o\n").As<Object>();
12811 CHECK(!with_js_getter.IsEmpty());
12812
12813 TryCatch try_catch;
12814
12815 Local<Value> result = instance->GetRealNamedProperty(v8_str("f"));
12816 CHECK(try_catch.HasCaught());
12817 try_catch.Reset();
12818 CHECK(result.IsEmpty());
12819
12820 result = another->GetRealNamedProperty(v8_str("f"));
12821 CHECK(try_catch.HasCaught());
12822 try_catch.Reset();
12823 CHECK(result.IsEmpty());
12824
12825 result = another->GetRealNamedPropertyInPrototypeChain(v8_str("f"));
12826 CHECK(try_catch.HasCaught());
12827 try_catch.Reset();
12828 CHECK(result.IsEmpty());
12829
12830 result = another->Get(v8_str("f"));
12831 CHECK(try_catch.HasCaught());
12832 try_catch.Reset();
12833 CHECK(result.IsEmpty());
12834
12835 result = with_js_getter->GetRealNamedProperty(v8_str("f"));
12836 CHECK(try_catch.HasCaught());
12837 try_catch.Reset();
12838 CHECK(result.IsEmpty());
12839
12840 result = with_js_getter->Get(v8_str("f"));
12841 CHECK(try_catch.HasCaught());
12842 try_catch.Reset();
12843 CHECK(result.IsEmpty());
12844}
12845
12846
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012847static void ThrowingCallbackWithTryCatch(
12848 const v8::FunctionCallbackInfo<v8::Value>& args) {
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012849 TryCatch try_catch;
12850 // Verboseness is important: it triggers message delivery which can call into
12851 // external code.
12852 try_catch.SetVerbose(true);
12853 CompileRun("throw 'from JS';");
12854 CHECK(try_catch.HasCaught());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000012855 CHECK(!CcTest::i_isolate()->has_pending_exception());
12856 CHECK(!CcTest::i_isolate()->has_scheduled_exception());
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012857}
12858
12859
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +000012860static int call_depth;
12861
12862
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012863static void WithTryCatch(Handle<Message> message, Handle<Value> data) {
12864 TryCatch try_catch;
12865}
12866
12867
12868static void ThrowFromJS(Handle<Message> message, Handle<Value> data) {
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +000012869 if (--call_depth) CompileRun("throw 'ThrowInJS';");
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012870}
12871
12872
12873static void ThrowViaApi(Handle<Message> message, Handle<Value> data) {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000012874 if (--call_depth) CcTest::isolate()->ThrowException(v8_str("ThrowViaApi"));
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012875}
12876
12877
12878static void WebKitLike(Handle<Message> message, Handle<Value> data) {
12879 Handle<String> errorMessageString = message->Get();
12880 CHECK(!errorMessageString.IsEmpty());
12881 message->GetStackTrace();
12882 message->GetScriptResourceName();
12883}
12884
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012885
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012886THREADED_TEST(ExceptionsDoNotPropagatePastTryCatch) {
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012887 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012888 v8::Isolate* isolate = context->GetIsolate();
12889 HandleScope scope(isolate);
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012890
12891 Local<Function> func =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012892 FunctionTemplate::New(isolate,
12893 ThrowingCallbackWithTryCatch)->GetFunction();
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012894 context->Global()->Set(v8_str("func"), func);
12895
12896 MessageCallback callbacks[] =
12897 { NULL, WebKitLike, ThrowViaApi, ThrowFromJS, WithTryCatch };
12898 for (unsigned i = 0; i < sizeof(callbacks)/sizeof(callbacks[0]); i++) {
12899 MessageCallback callback = callbacks[i];
12900 if (callback != NULL) {
12901 V8::AddMessageListener(callback);
12902 }
ricow@chromium.orgdcebac02011-04-20 09:44:50 +000012903 // Some small number to control number of times message handler should
12904 // throw an exception.
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +000012905 call_depth = 5;
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012906 ExpectFalse(
12907 "var thrown = false;\n"
12908 "try { func(); } catch(e) { thrown = true; }\n"
12909 "thrown\n");
12910 if (callback != NULL) {
12911 V8::RemoveMessageListeners(callback);
12912 }
12913 }
12914}
12915
12916
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012917static void ParentGetter(Local<String> name,
12918 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012919 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012920 info.GetReturnValue().Set(v8_num(1));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012921}
12922
12923
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012924static void ChildGetter(Local<String> name,
12925 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012926 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012927 info.GetReturnValue().Set(v8_num(42));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012928}
12929
12930
12931THREADED_TEST(Overriding) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +000012932 i::FLAG_es5_readonly = true;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012933 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012934 v8::Isolate* isolate = context->GetIsolate();
12935 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012936
12937 // Parent template.
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012938 Local<v8::FunctionTemplate> parent_templ = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012939 Local<ObjectTemplate> parent_instance_templ =
12940 parent_templ->InstanceTemplate();
12941 parent_instance_templ->SetAccessor(v8_str("f"), ParentGetter);
12942
12943 // Template that inherits from the parent template.
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012944 Local<v8::FunctionTemplate> child_templ = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012945 Local<ObjectTemplate> child_instance_templ =
12946 child_templ->InstanceTemplate();
12947 child_templ->Inherit(parent_templ);
12948 // Override 'f'. The child version of 'f' should get called for child
12949 // instances.
12950 child_instance_templ->SetAccessor(v8_str("f"), ChildGetter);
12951 // Add 'g' twice. The 'g' added last should get called for instances.
12952 child_instance_templ->SetAccessor(v8_str("g"), ParentGetter);
12953 child_instance_templ->SetAccessor(v8_str("g"), ChildGetter);
12954
12955 // Add 'h' as an accessor to the proto template with ReadOnly attributes
12956 // so 'h' can be shadowed on the instance object.
12957 Local<ObjectTemplate> child_proto_templ = child_templ->PrototypeTemplate();
12958 child_proto_templ->SetAccessor(v8_str("h"), ParentGetter, 0,
12959 v8::Handle<Value>(), v8::DEFAULT, v8::ReadOnly);
12960
12961 // Add 'i' as an accessor to the instance template with ReadOnly attributes
12962 // but the attribute does not have effect because it is duplicated with
12963 // NULL setter.
12964 child_instance_templ->SetAccessor(v8_str("i"), ChildGetter, 0,
12965 v8::Handle<Value>(), v8::DEFAULT, v8::ReadOnly);
12966
12967
12968
12969 // Instantiate the child template.
12970 Local<v8::Object> instance = child_templ->GetFunction()->NewInstance();
12971
12972 // Check that the child function overrides the parent one.
12973 context->Global()->Set(v8_str("o"), instance);
12974 Local<Value> value = v8_compile("o.f")->Run();
12975 // Check that the 'g' that was added last is hit.
12976 CHECK_EQ(42, value->Int32Value());
12977 value = v8_compile("o.g")->Run();
12978 CHECK_EQ(42, value->Int32Value());
12979
mmassi@chromium.org7028c052012-06-13 11:51:58 +000012980 // Check that 'h' cannot be shadowed.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012981 value = v8_compile("o.h = 3; o.h")->Run();
mmassi@chromium.org7028c052012-06-13 11:51:58 +000012982 CHECK_EQ(1, value->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012983
mmassi@chromium.org7028c052012-06-13 11:51:58 +000012984 // Check that 'i' cannot be shadowed or changed.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012985 value = v8_compile("o.i = 3; o.i")->Run();
12986 CHECK_EQ(42, value->Int32Value());
12987}
12988
12989
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012990static void IsConstructHandler(
12991 const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012992 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012993 args.GetReturnValue().Set(args.IsConstructCall());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012994}
12995
12996
12997THREADED_TEST(IsConstructCall) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012998 v8::Isolate* isolate = CcTest::isolate();
12999 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013000
13001 // Function template with call handler.
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000013002 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013003 templ->SetCallHandler(IsConstructHandler);
13004
13005 LocalContext context;
13006
13007 context->Global()->Set(v8_str("f"), templ->GetFunction());
13008 Local<Value> value = v8_compile("f()")->Run();
13009 CHECK(!value->BooleanValue());
13010 value = v8_compile("new f()")->Run();
13011 CHECK(value->BooleanValue());
13012}
13013
13014
13015THREADED_TEST(ObjectProtoToString) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000013016 v8::Isolate* isolate = CcTest::isolate();
13017 v8::HandleScope scope(isolate);
13018 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013019 templ->SetClassName(v8_str("MyClass"));
13020
13021 LocalContext context;
13022
13023 Local<String> customized_tostring = v8_str("customized toString");
13024
13025 // Replace Object.prototype.toString
13026 v8_compile("Object.prototype.toString = function() {"
13027 " return 'customized toString';"
13028 "}")->Run();
13029
13030 // Normal ToString call should call replaced Object.prototype.toString
13031 Local<v8::Object> instance = templ->GetFunction()->NewInstance();
13032 Local<String> value = instance->ToString();
13033 CHECK(value->IsString() && value->Equals(customized_tostring));
13034
13035 // ObjectProtoToString should not call replace toString function.
13036 value = instance->ObjectProtoToString();
13037 CHECK(value->IsString() && value->Equals(v8_str("[object MyClass]")));
13038
13039 // Check global
13040 value = context->Global()->ObjectProtoToString();
13041 CHECK(value->IsString() && value->Equals(v8_str("[object global]")));
13042
13043 // Check ordinary object
13044 Local<Value> object = v8_compile("new Object()")->Run();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000013045 value = object.As<v8::Object>()->ObjectProtoToString();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013046 CHECK(value->IsString() && value->Equals(v8_str("[object Object]")));
13047}
13048
13049
ager@chromium.orgbeb25712010-11-29 08:02:25 +000013050THREADED_TEST(ObjectGetConstructorName) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +000013051 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013052 v8::HandleScope scope(context->GetIsolate());
ager@chromium.orgbeb25712010-11-29 08:02:25 +000013053 v8_compile("function Parent() {};"
13054 "function Child() {};"
13055 "Child.prototype = new Parent();"
13056 "var outer = { inner: function() { } };"
13057 "var p = new Parent();"
13058 "var c = new Child();"
13059 "var x = new outer.inner();")->Run();
13060
13061 Local<v8::Value> p = context->Global()->Get(v8_str("p"));
13062 CHECK(p->IsObject() && p->ToObject()->GetConstructorName()->Equals(
13063 v8_str("Parent")));
13064
13065 Local<v8::Value> c = context->Global()->Get(v8_str("c"));
13066 CHECK(c->IsObject() && c->ToObject()->GetConstructorName()->Equals(
13067 v8_str("Child")));
13068
13069 Local<v8::Value> x = context->Global()->Get(v8_str("x"));
13070 CHECK(x->IsObject() && x->ToObject()->GetConstructorName()->Equals(
13071 v8_str("outer.inner")));
13072}
13073
13074
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013075bool ApiTestFuzzer::fuzzing_ = false;
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000013076i::Semaphore ApiTestFuzzer::all_tests_done_(0);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013077int ApiTestFuzzer::active_tests_;
13078int ApiTestFuzzer::tests_being_run_;
13079int ApiTestFuzzer::current_;
13080
13081
13082// We are in a callback and want to switch to another thread (if we
13083// are currently running the thread fuzzing test).
13084void ApiTestFuzzer::Fuzz() {
13085 if (!fuzzing_) return;
13086 ApiTestFuzzer* test = RegisterThreadedTest::nth(current_)->fuzzer_;
13087 test->ContextSwitch();
13088}
13089
13090
13091// Let the next thread go. Since it is also waiting on the V8 lock it may
13092// not start immediately.
13093bool ApiTestFuzzer::NextThread() {
13094 int test_position = GetNextTestNumber();
ager@chromium.orgc4c92722009-11-18 14:12:51 +000013095 const char* test_name = RegisterThreadedTest::nth(current_)->name();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013096 if (test_position == current_) {
ager@chromium.orgc4c92722009-11-18 14:12:51 +000013097 if (kLogThreading)
13098 printf("Stay with %s\n", test_name);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013099 return false;
13100 }
ager@chromium.orgc4c92722009-11-18 14:12:51 +000013101 if (kLogThreading) {
13102 printf("Switch from %s to %s\n",
13103 test_name,
13104 RegisterThreadedTest::nth(test_position)->name());
13105 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013106 current_ = test_position;
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000013107 RegisterThreadedTest::nth(current_)->fuzzer_->gate_.Signal();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013108 return true;
13109}
13110
13111
13112void ApiTestFuzzer::Run() {
13113 // When it is our turn...
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000013114 gate_.Wait();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013115 {
13116 // ... get the V8 lock and start running the test.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013117 v8::Locker locker(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013118 CallTest();
13119 }
13120 // This test finished.
13121 active_ = false;
13122 active_tests_--;
13123 // If it was the last then signal that fact.
13124 if (active_tests_ == 0) {
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000013125 all_tests_done_.Signal();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013126 } else {
13127 // Otherwise select a new test and start that.
13128 NextThread();
13129 }
13130}
13131
13132
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013133static unsigned linear_congruential_generator;
13134
13135
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000013136void ApiTestFuzzer::SetUp(PartOfTest part) {
kasperl@chromium.orgb9123622008-09-17 14:05:56 +000013137 linear_congruential_generator = i::FLAG_testing_prng_seed;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013138 fuzzing_ = true;
lrn@chromium.org1c092762011-05-09 09:42:16 +000013139 int count = RegisterThreadedTest::count();
13140 int start = count * part / (LAST_PART + 1);
13141 int end = (count * (part + 1) / (LAST_PART + 1)) - 1;
13142 active_tests_ = tests_being_run_ = end - start + 1;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013143 for (int i = 0; i < tests_being_run_; i++) {
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000013144 RegisterThreadedTest::nth(i)->fuzzer_ = new ApiTestFuzzer(i + start);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013145 }
13146 for (int i = 0; i < active_tests_; i++) {
13147 RegisterThreadedTest::nth(i)->fuzzer_->Start();
13148 }
13149}
13150
13151
13152static void CallTestNumber(int test_number) {
13153 (RegisterThreadedTest::nth(test_number)->callback())();
13154}
13155
13156
13157void ApiTestFuzzer::RunAllTests() {
13158 // Set off the first test.
13159 current_ = -1;
13160 NextThread();
13161 // Wait till they are all done.
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000013162 all_tests_done_.Wait();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013163}
13164
13165
13166int ApiTestFuzzer::GetNextTestNumber() {
13167 int next_test;
13168 do {
13169 next_test = (linear_congruential_generator >> 16) % tests_being_run_;
13170 linear_congruential_generator *= 1664525u;
13171 linear_congruential_generator += 1013904223u;
13172 } while (!RegisterThreadedTest::nth(next_test)->fuzzer_->active_);
13173 return next_test;
13174}
13175
13176
13177void ApiTestFuzzer::ContextSwitch() {
13178 // If the new thread is the same as the current thread there is nothing to do.
13179 if (NextThread()) {
13180 // Now it can start.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013181 v8::Unlocker unlocker(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013182 // Wait till someone starts us again.
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000013183 gate_.Wait();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013184 // And we're off.
13185 }
13186}
13187
13188
13189void ApiTestFuzzer::TearDown() {
13190 fuzzing_ = false;
ager@chromium.org41826e72009-03-30 13:30:57 +000013191 for (int i = 0; i < RegisterThreadedTest::count(); i++) {
13192 ApiTestFuzzer *fuzzer = RegisterThreadedTest::nth(i)->fuzzer_;
13193 if (fuzzer != NULL) fuzzer->Join();
13194 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013195}
13196
13197
13198// Lets not be needlessly self-referential.
mmassi@chromium.org2f0efde2013-02-06 14:12:58 +000013199TEST(Threading1) {
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000013200 ApiTestFuzzer::SetUp(ApiTestFuzzer::FIRST_PART);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013201 ApiTestFuzzer::RunAllTests();
13202 ApiTestFuzzer::TearDown();
13203}
13204
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000013205
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013206TEST(Threading2) {
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000013207 ApiTestFuzzer::SetUp(ApiTestFuzzer::SECOND_PART);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013208 ApiTestFuzzer::RunAllTests();
13209 ApiTestFuzzer::TearDown();
13210}
13211
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000013212
lrn@chromium.org1c092762011-05-09 09:42:16 +000013213TEST(Threading3) {
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000013214 ApiTestFuzzer::SetUp(ApiTestFuzzer::THIRD_PART);
lrn@chromium.org1c092762011-05-09 09:42:16 +000013215 ApiTestFuzzer::RunAllTests();
13216 ApiTestFuzzer::TearDown();
13217}
13218
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000013219
lrn@chromium.org1c092762011-05-09 09:42:16 +000013220TEST(Threading4) {
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000013221 ApiTestFuzzer::SetUp(ApiTestFuzzer::FOURTH_PART);
lrn@chromium.org1c092762011-05-09 09:42:16 +000013222 ApiTestFuzzer::RunAllTests();
13223 ApiTestFuzzer::TearDown();
13224}
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013225
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000013226
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013227void ApiTestFuzzer::CallTest() {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013228 v8::Isolate::Scope scope(CcTest::isolate());
ager@chromium.orgc4c92722009-11-18 14:12:51 +000013229 if (kLogThreading)
13230 printf("Start test %d\n", test_number_);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013231 CallTestNumber(test_number_);
ager@chromium.orgc4c92722009-11-18 14:12:51 +000013232 if (kLogThreading)
13233 printf("End test %d\n", test_number_);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013234}
13235
13236
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013237static void ThrowInJS(const v8::FunctionCallbackInfo<v8::Value>& args) {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000013238 v8::Isolate* isolate = args.GetIsolate();
13239 CHECK(v8::Locker::IsLocked(isolate));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013240 ApiTestFuzzer::Fuzz();
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000013241 v8::Unlocker unlocker(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013242 const char* code = "throw 7;";
13243 {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000013244 v8::Locker nested_locker(isolate);
13245 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013246 v8::Handle<Value> exception;
13247 { v8::TryCatch try_catch;
13248 v8::Handle<Value> value = CompileRun(code);
13249 CHECK(value.IsEmpty());
13250 CHECK(try_catch.HasCaught());
13251 // Make sure to wrap the exception in a new handle because
13252 // the handle returned from the TryCatch is destroyed
13253 // when the TryCatch is destroyed.
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000013254 exception = Local<Value>::New(isolate, try_catch.Exception());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013255 }
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000013256 args.GetIsolate()->ThrowException(exception);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013257 }
13258}
13259
13260
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013261static void ThrowInJSNoCatch(const v8::FunctionCallbackInfo<v8::Value>& args) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013262 CHECK(v8::Locker::IsLocked(CcTest::isolate()));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013263 ApiTestFuzzer::Fuzz();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013264 v8::Unlocker unlocker(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013265 const char* code = "throw 7;";
13266 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013267 v8::Locker nested_locker(CcTest::isolate());
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013268 v8::HandleScope scope(args.GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013269 v8::Handle<Value> value = CompileRun(code);
13270 CHECK(value.IsEmpty());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013271 args.GetReturnValue().Set(v8_str("foo"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013272 }
13273}
13274
13275
13276// These are locking tests that don't need to be run again
13277// as part of the locking aggregation tests.
13278TEST(NestedLockers) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000013279 v8::Isolate* isolate = CcTest::isolate();
13280 v8::Locker locker(isolate);
13281 CHECK(v8::Locker::IsLocked(isolate));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013282 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013283 v8::HandleScope scope(env->GetIsolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000013284 Local<v8::FunctionTemplate> fun_templ =
13285 v8::FunctionTemplate::New(isolate, ThrowInJS);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013286 Local<Function> fun = fun_templ->GetFunction();
13287 env->Global()->Set(v8_str("throw_in_js"), fun);
13288 Local<Script> script = v8_compile("(function () {"
13289 " try {"
13290 " throw_in_js();"
13291 " return 42;"
13292 " } catch (e) {"
13293 " return e * 13;"
13294 " }"
13295 "})();");
13296 CHECK_EQ(91, script->Run()->Int32Value());
13297}
13298
13299
13300// These are locking tests that don't need to be run again
13301// as part of the locking aggregation tests.
13302TEST(NestedLockersNoTryCatch) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013303 v8::Locker locker(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013304 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013305 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013306 Local<v8::FunctionTemplate> fun_templ =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000013307 v8::FunctionTemplate::New(env->GetIsolate(), ThrowInJSNoCatch);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013308 Local<Function> fun = fun_templ->GetFunction();
13309 env->Global()->Set(v8_str("throw_in_js"), fun);
13310 Local<Script> script = v8_compile("(function () {"
13311 " try {"
13312 " throw_in_js();"
13313 " return 42;"
13314 " } catch (e) {"
13315 " return e * 13;"
13316 " }"
13317 "})();");
13318 CHECK_EQ(91, script->Run()->Int32Value());
13319}
13320
13321
13322THREADED_TEST(RecursiveLocking) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013323 v8::Locker locker(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013324 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013325 v8::Locker locker2(CcTest::isolate());
13326 CHECK(v8::Locker::IsLocked(CcTest::isolate()));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013327 }
13328}
13329
13330
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013331static void UnlockForAMoment(const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013332 ApiTestFuzzer::Fuzz();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013333 v8::Unlocker unlocker(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013334}
13335
13336
13337THREADED_TEST(LockUnlockLock) {
13338 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013339 v8::Locker locker(CcTest::isolate());
13340 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013341 LocalContext env;
13342 Local<v8::FunctionTemplate> fun_templ =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000013343 v8::FunctionTemplate::New(CcTest::isolate(), UnlockForAMoment);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013344 Local<Function> fun = fun_templ->GetFunction();
13345 env->Global()->Set(v8_str("unlock_for_a_moment"), fun);
13346 Local<Script> script = v8_compile("(function () {"
13347 " unlock_for_a_moment();"
13348 " return 42;"
13349 "})();");
13350 CHECK_EQ(42, script->Run()->Int32Value());
13351 }
13352 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013353 v8::Locker locker(CcTest::isolate());
13354 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013355 LocalContext env;
13356 Local<v8::FunctionTemplate> fun_templ =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000013357 v8::FunctionTemplate::New(CcTest::isolate(), UnlockForAMoment);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013358 Local<Function> fun = fun_templ->GetFunction();
13359 env->Global()->Set(v8_str("unlock_for_a_moment"), fun);
13360 Local<Script> script = v8_compile("(function () {"
13361 " unlock_for_a_moment();"
13362 " return 42;"
13363 "})();");
13364 CHECK_EQ(42, script->Run()->Int32Value());
13365 }
13366}
13367
13368
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000013369static int GetGlobalObjectsCount() {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013370 CcTest::heap()->EnsureHeapIsIterable();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013371 int count = 0;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013372 i::HeapIterator it(CcTest::heap());
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000013373 for (i::HeapObject* object = it.next(); object != NULL; object = it.next())
13374 if (object->IsJSGlobalObject()) count++;
13375 return count;
13376}
13377
13378
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000013379static void CheckSurvivingGlobalObjectsCount(int expected) {
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +000013380 // We need to collect all garbage twice to be sure that everything
13381 // has been collected. This is because inline caches are cleared in
13382 // the first garbage collection but some of the maps have already
13383 // been marked at that point. Therefore some of the maps are not
13384 // collected until the second garbage collection.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013385 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
13386 CcTest::heap()->CollectAllGarbage(i::Heap::kMakeHeapIterableMask);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000013387 int count = GetGlobalObjectsCount();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013388#ifdef DEBUG
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013389 if (count != expected) CcTest::heap()->TracePathToGlobal();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013390#endif
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000013391 CHECK_EQ(expected, count);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013392}
13393
13394
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013395TEST(DontLeakGlobalObjects) {
13396 // Regression test for issues 1139850 and 1174891.
13397
machenbach@chromium.orgc8cbc432014-01-21 09:01:57 +000013398 i::FLAG_expose_gc = true;
kasperl@chromium.orgb9123622008-09-17 14:05:56 +000013399 v8::V8::Initialize();
ager@chromium.org9258b6b2008-09-11 09:11:10 +000013400
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013401 for (int i = 0; i < 5; i++) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013402 { v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013403 LocalContext context;
13404 }
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +000013405 v8::V8::ContextDisposedNotification();
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000013406 CheckSurvivingGlobalObjectsCount(0);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013407
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013408 { v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013409 LocalContext context;
13410 v8_compile("Date")->Run();
13411 }
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +000013412 v8::V8::ContextDisposedNotification();
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000013413 CheckSurvivingGlobalObjectsCount(0);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013414
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013415 { v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013416 LocalContext context;
13417 v8_compile("/aaa/")->Run();
13418 }
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +000013419 v8::V8::ContextDisposedNotification();
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000013420 CheckSurvivingGlobalObjectsCount(0);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013421
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 const char* extension_list[] = { "v8/gc" };
13424 v8::ExtensionConfiguration extensions(1, extension_list);
13425 LocalContext context(&extensions);
13426 v8_compile("gc();")->Run();
13427 }
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +000013428 v8::V8::ContextDisposedNotification();
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000013429 CheckSurvivingGlobalObjectsCount(0);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013430 }
13431}
13432
dslomov@chromium.org639bac02013-09-09 11:58:54 +000013433
13434TEST(CopyablePersistent) {
13435 LocalContext context;
13436 v8::Isolate* isolate = context->GetIsolate();
13437 i::GlobalHandles* globals =
13438 reinterpret_cast<i::Isolate*>(isolate)->global_handles();
13439 int initial_handles = globals->global_handles_count();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013440 typedef v8::Persistent<v8::Object, v8::CopyablePersistentTraits<v8::Object> >
13441 CopyableObject;
dslomov@chromium.org639bac02013-09-09 11:58:54 +000013442 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013443 CopyableObject handle1;
dslomov@chromium.org639bac02013-09-09 11:58:54 +000013444 {
13445 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000013446 handle1.Reset(isolate, v8::Object::New(isolate));
dslomov@chromium.org639bac02013-09-09 11:58:54 +000013447 }
13448 CHECK_EQ(initial_handles + 1, globals->global_handles_count());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013449 CopyableObject handle2;
dslomov@chromium.org639bac02013-09-09 11:58:54 +000013450 handle2 = handle1;
13451 CHECK(handle1 == handle2);
13452 CHECK_EQ(initial_handles + 2, globals->global_handles_count());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013453 CopyableObject handle3(handle2);
dslomov@chromium.org639bac02013-09-09 11:58:54 +000013454 CHECK(handle1 == handle3);
13455 CHECK_EQ(initial_handles + 3, globals->global_handles_count());
13456 }
13457 // Verify autodispose
hpayer@chromium.orgc5d49712013-09-11 08:25:48 +000013458 CHECK_EQ(initial_handles, globals->global_handles_count());
dslomov@chromium.org639bac02013-09-09 11:58:54 +000013459}
13460
13461
13462static void WeakApiCallback(
13463 const v8::WeakCallbackData<v8::Object, Persistent<v8::Object> >& data) {
13464 Local<Value> value = data.GetValue()->Get(v8_str("key"));
13465 CHECK_EQ(231, static_cast<int32_t>(Local<v8::Integer>::Cast(value)->Value()));
13466 data.GetParameter()->Reset();
13467 delete data.GetParameter();
13468}
13469
13470
13471TEST(WeakCallbackApi) {
13472 LocalContext context;
13473 v8::Isolate* isolate = context->GetIsolate();
13474 i::GlobalHandles* globals =
13475 reinterpret_cast<i::Isolate*>(isolate)->global_handles();
13476 int initial_handles = globals->global_handles_count();
13477 {
13478 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000013479 v8::Local<v8::Object> obj = v8::Object::New(isolate);
13480 obj->Set(v8_str("key"), v8::Integer::New(isolate, 231));
dslomov@chromium.org639bac02013-09-09 11:58:54 +000013481 v8::Persistent<v8::Object>* handle =
13482 new v8::Persistent<v8::Object>(isolate, obj);
13483 handle->SetWeak<v8::Object, v8::Persistent<v8::Object> >(handle,
13484 WeakApiCallback);
13485 }
13486 reinterpret_cast<i::Isolate*>(isolate)->heap()->
13487 CollectAllGarbage(i::Heap::kNoGCFlags);
13488 // Verify disposed.
13489 CHECK_EQ(initial_handles, globals->global_handles_count());
13490}
13491
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013492
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000013493v8::Persistent<v8::Object> some_object;
13494v8::Persistent<v8::Object> bad_handle;
13495
machenbach@chromium.orgddf38112013-12-04 09:42:52 +000013496void NewPersistentHandleCallback(
13497 const v8::WeakCallbackData<v8::Object, v8::Persistent<v8::Object> >& data) {
13498 v8::HandleScope scope(data.GetIsolate());
13499 bad_handle.Reset(data.GetIsolate(), some_object);
13500 data.GetParameter()->Reset();
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000013501}
13502
13503
13504THREADED_TEST(NewPersistentHandleFromWeakCallback) {
13505 LocalContext context;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000013506 v8::Isolate* isolate = context->GetIsolate();
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000013507
13508 v8::Persistent<v8::Object> handle1, handle2;
13509 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013510 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000013511 some_object.Reset(isolate, v8::Object::New(isolate));
13512 handle1.Reset(isolate, v8::Object::New(isolate));
13513 handle2.Reset(isolate, v8::Object::New(isolate));
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000013514 }
13515 // Note: order is implementation dependent alas: currently
13516 // global handle nodes are processed by PostGarbageCollectionProcessing
13517 // in reverse allocation order, so if second allocated handle is deleted,
13518 // weak callback of the first handle would be able to 'reallocate' it.
machenbach@chromium.orgddf38112013-12-04 09:42:52 +000013519 handle1.SetWeak(&handle1, NewPersistentHandleCallback);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000013520 handle2.Reset();
machenbach@chromium.orgddf38112013-12-04 09:42:52 +000013521 CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000013522}
13523
13524
13525v8::Persistent<v8::Object> to_be_disposed;
13526
machenbach@chromium.orgddf38112013-12-04 09:42:52 +000013527void DisposeAndForceGcCallback(
13528 const v8::WeakCallbackData<v8::Object, v8::Persistent<v8::Object> >& data) {
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000013529 to_be_disposed.Reset();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013530 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
machenbach@chromium.orgddf38112013-12-04 09:42:52 +000013531 data.GetParameter()->Reset();
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000013532}
13533
13534
13535THREADED_TEST(DoNotUseDeletedNodesInSecondLevelGc) {
13536 LocalContext context;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000013537 v8::Isolate* isolate = context->GetIsolate();
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000013538
13539 v8::Persistent<v8::Object> handle1, handle2;
13540 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013541 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000013542 handle1.Reset(isolate, v8::Object::New(isolate));
13543 handle2.Reset(isolate, v8::Object::New(isolate));
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000013544 }
machenbach@chromium.orgddf38112013-12-04 09:42:52 +000013545 handle1.SetWeak(&handle1, DisposeAndForceGcCallback);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000013546 to_be_disposed.Reset(isolate, handle2);
machenbach@chromium.orgddf38112013-12-04 09:42:52 +000013547 CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000013548}
13549
machenbach@chromium.orgddf38112013-12-04 09:42:52 +000013550void DisposingCallback(
13551 const v8::WeakCallbackData<v8::Object, v8::Persistent<v8::Object> >& data) {
13552 data.GetParameter()->Reset();
ager@chromium.orgc4c92722009-11-18 14:12:51 +000013553}
13554
machenbach@chromium.orgddf38112013-12-04 09:42:52 +000013555void HandleCreatingCallback(
13556 const v8::WeakCallbackData<v8::Object, v8::Persistent<v8::Object> >& data) {
13557 v8::HandleScope scope(data.GetIsolate());
ulan@chromium.org0f13e742014-01-03 15:51:11 +000013558 v8::Persistent<v8::Object>(data.GetIsolate(),
13559 v8::Object::New(data.GetIsolate()));
machenbach@chromium.orgddf38112013-12-04 09:42:52 +000013560 data.GetParameter()->Reset();
ager@chromium.orgc4c92722009-11-18 14:12:51 +000013561}
13562
13563
13564THREADED_TEST(NoGlobalHandlesOrphaningDueToWeakCallback) {
13565 LocalContext context;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000013566 v8::Isolate* isolate = context->GetIsolate();
ager@chromium.orgc4c92722009-11-18 14:12:51 +000013567
13568 v8::Persistent<v8::Object> handle1, handle2, handle3;
13569 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013570 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000013571 handle3.Reset(isolate, v8::Object::New(isolate));
13572 handle2.Reset(isolate, v8::Object::New(isolate));
13573 handle1.Reset(isolate, v8::Object::New(isolate));
ager@chromium.orgc4c92722009-11-18 14:12:51 +000013574 }
machenbach@chromium.orgddf38112013-12-04 09:42:52 +000013575 handle2.SetWeak(&handle2, DisposingCallback);
13576 handle3.SetWeak(&handle3, HandleCreatingCallback);
13577 CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
ager@chromium.orgc4c92722009-11-18 14:12:51 +000013578}
13579
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000013580
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013581THREADED_TEST(CheckForCrossContextObjectLiterals) {
kasperl@chromium.orgb9123622008-09-17 14:05:56 +000013582 v8::V8::Initialize();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013583
13584 const int nof = 2;
13585 const char* sources[nof] = {
13586 "try { [ 2, 3, 4 ].forEach(5); } catch(e) { e.toString(); }",
13587 "Object()"
13588 };
13589
13590 for (int i = 0; i < nof; i++) {
13591 const char* source = sources[i];
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013592 { v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013593 LocalContext context;
13594 CompileRun(source);
13595 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013596 { v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013597 LocalContext context;
13598 CompileRun(source);
13599 }
13600 }
13601}
13602
13603
ulan@chromium.org57ff8812013-05-10 08:16:55 +000013604static v8::Handle<Value> NestedScope(v8::Local<Context> env) {
machenbach@chromium.orgafbdadc2013-12-09 16:12:18 +000013605 v8::EscapableHandleScope inner(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013606 env->Enter();
machenbach@chromium.orgafbdadc2013-12-09 16:12:18 +000013607 v8::Local<Value> three = v8_num(3);
13608 v8::Local<Value> value = inner.Escape(three);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013609 env->Exit();
13610 return value;
13611}
13612
13613
13614THREADED_TEST(NestedHandleScopeAndContexts) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013615 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000013616 v8::HandleScope outer(isolate);
13617 v8::Local<Context> env = Context::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013618 env->Enter();
13619 v8::Handle<Value> value = NestedScope(env);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000013620 v8::Handle<String> str(value->ToString());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000013621 CHECK(!str.IsEmpty());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013622 env->Exit();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013623}
13624
13625
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013626static bool MatchPointers(void* key1, void* key2) {
13627 return key1 == key2;
13628}
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013629
13630
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013631struct SymbolInfo {
13632 size_t id;
13633 size_t size;
13634 std::string name;
13635};
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013636
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013637
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013638class SetFunctionEntryHookTest {
13639 public:
13640 SetFunctionEntryHookTest() {
13641 CHECK(instance_ == NULL);
13642 instance_ = this;
13643 }
13644 ~SetFunctionEntryHookTest() {
13645 CHECK(instance_ == this);
13646 instance_ = NULL;
13647 }
13648 void Reset() {
13649 symbols_.clear();
13650 symbol_locations_.clear();
13651 invocations_.clear();
13652 }
13653 void RunTest();
13654 void OnJitEvent(const v8::JitCodeEvent* event);
13655 static void JitEvent(const v8::JitCodeEvent* event) {
13656 CHECK(instance_ != NULL);
13657 instance_->OnJitEvent(event);
13658 }
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013659
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013660 void OnEntryHook(uintptr_t function,
13661 uintptr_t return_addr_location);
13662 static void EntryHook(uintptr_t function,
13663 uintptr_t return_addr_location) {
13664 CHECK(instance_ != NULL);
13665 instance_->OnEntryHook(function, return_addr_location);
13666 }
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000013667
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013668 static void RuntimeCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
13669 CHECK(instance_ != NULL);
13670 args.GetReturnValue().Set(v8_num(42));
13671 }
13672 void RunLoopInNewEnv(v8::Isolate* isolate);
13673
13674 // Records addr as location of symbol.
13675 void InsertSymbolAt(i::Address addr, SymbolInfo* symbol);
13676
13677 // Finds the symbol containing addr
13678 SymbolInfo* FindSymbolForAddr(i::Address addr);
13679 // Returns the number of invocations where the caller name contains
13680 // \p caller_name and the function name contains \p function_name.
13681 int CountInvocations(const char* caller_name,
13682 const char* function_name);
13683
13684 i::Handle<i::JSFunction> foo_func_;
13685 i::Handle<i::JSFunction> bar_func_;
13686
13687 typedef std::map<size_t, SymbolInfo> SymbolMap;
13688 typedef std::map<i::Address, SymbolInfo*> SymbolLocationMap;
13689 typedef std::map<std::pair<SymbolInfo*, SymbolInfo*>, int> InvocationMap;
13690 SymbolMap symbols_;
13691 SymbolLocationMap symbol_locations_;
13692 InvocationMap invocations_;
13693
13694 static SetFunctionEntryHookTest* instance_;
13695};
13696SetFunctionEntryHookTest* SetFunctionEntryHookTest::instance_ = NULL;
13697
13698
13699// Returns true if addr is in the range [start, start+len).
13700static bool Overlaps(i::Address start, size_t len, i::Address addr) {
13701 if (start <= addr && start + len > addr)
13702 return true;
13703
13704 return false;
13705}
13706
13707void SetFunctionEntryHookTest::InsertSymbolAt(i::Address addr,
13708 SymbolInfo* symbol) {
13709 // Insert the symbol at the new location.
13710 SymbolLocationMap::iterator it =
13711 symbol_locations_.insert(std::make_pair(addr, symbol)).first;
13712 // Now erase symbols to the left and right that overlap this one.
13713 while (it != symbol_locations_.begin()) {
13714 SymbolLocationMap::iterator left = it;
13715 --left;
13716 if (!Overlaps(left->first, left->second->size, addr))
13717 break;
13718 symbol_locations_.erase(left);
13719 }
13720
13721 // Now erase symbols to the left and right that overlap this one.
13722 while (true) {
13723 SymbolLocationMap::iterator right = it;
13724 ++right;
13725 if (right == symbol_locations_.end())
13726 break;
13727 if (!Overlaps(addr, symbol->size, right->first))
13728 break;
13729 symbol_locations_.erase(right);
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000013730 }
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013731}
13732
13733
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013734void SetFunctionEntryHookTest::OnJitEvent(const v8::JitCodeEvent* event) {
13735 switch (event->type) {
13736 case v8::JitCodeEvent::CODE_ADDED: {
13737 CHECK(event->code_start != NULL);
13738 CHECK_NE(0, static_cast<int>(event->code_len));
13739 CHECK(event->name.str != NULL);
13740 size_t symbol_id = symbols_.size();
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013741
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013742 // Record the new symbol.
13743 SymbolInfo& info = symbols_[symbol_id];
13744 info.id = symbol_id;
13745 info.size = event->code_len;
13746 info.name.assign(event->name.str, event->name.str + event->name.len);
13747
13748 // And record it's location.
13749 InsertSymbolAt(reinterpret_cast<i::Address>(event->code_start), &info);
13750 }
13751 break;
13752
13753 case v8::JitCodeEvent::CODE_MOVED: {
13754 // We would like to never see code move that we haven't seen before,
13755 // but the code creation event does not happen until the line endings
13756 // have been calculated (this is so that we can report the line in the
13757 // script at which the function source is found, see
13758 // Compiler::RecordFunctionCompilation) and the line endings
13759 // calculations can cause a GC, which can move the newly created code
13760 // before its existence can be logged.
13761 SymbolLocationMap::iterator it(
13762 symbol_locations_.find(
13763 reinterpret_cast<i::Address>(event->code_start)));
13764 if (it != symbol_locations_.end()) {
13765 // Found a symbol at this location, move it.
13766 SymbolInfo* info = it->second;
13767 symbol_locations_.erase(it);
13768 InsertSymbolAt(reinterpret_cast<i::Address>(event->new_code_start),
13769 info);
13770 }
13771 }
13772 default:
13773 break;
13774 }
13775}
13776
13777void SetFunctionEntryHookTest::OnEntryHook(
13778 uintptr_t function, uintptr_t return_addr_location) {
13779 // Get the function's code object.
13780 i::Code* function_code = i::Code::GetCodeFromTargetAddress(
13781 reinterpret_cast<i::Address>(function));
13782 CHECK(function_code != NULL);
13783
13784 // Then try and look up the caller's code object.
13785 i::Address caller = *reinterpret_cast<i::Address*>(return_addr_location);
13786
13787 // Count the invocation.
13788 SymbolInfo* caller_symbol = FindSymbolForAddr(caller);
13789 SymbolInfo* function_symbol =
13790 FindSymbolForAddr(reinterpret_cast<i::Address>(function));
13791 ++invocations_[std::make_pair(caller_symbol, function_symbol)];
13792
13793 if (!bar_func_.is_null() && function_code == bar_func_->code()) {
13794 // Check that we have a symbol for the "bar" function at the right location.
13795 SymbolLocationMap::iterator it(
13796 symbol_locations_.find(function_code->instruction_start()));
13797 CHECK(it != symbol_locations_.end());
13798 }
13799
13800 if (!foo_func_.is_null() && function_code == foo_func_->code()) {
13801 // Check that we have a symbol for "foo" at the right location.
13802 SymbolLocationMap::iterator it(
13803 symbol_locations_.find(function_code->instruction_start()));
13804 CHECK(it != symbol_locations_.end());
13805 }
13806}
13807
13808
13809SymbolInfo* SetFunctionEntryHookTest::FindSymbolForAddr(i::Address addr) {
13810 SymbolLocationMap::iterator it(symbol_locations_.lower_bound(addr));
13811 // Do we have a direct hit on a symbol?
13812 if (it != symbol_locations_.end()) {
13813 if (it->first == addr)
13814 return it->second;
13815 }
13816
13817 // If not a direct hit, it'll have to be the previous symbol.
13818 if (it == symbol_locations_.begin())
13819 return NULL;
13820
13821 --it;
13822 size_t offs = addr - it->first;
13823 if (offs < it->second->size)
13824 return it->second;
13825
13826 return NULL;
13827}
13828
13829
13830int SetFunctionEntryHookTest::CountInvocations(
13831 const char* caller_name, const char* function_name) {
13832 InvocationMap::iterator it(invocations_.begin());
13833 int invocations = 0;
13834 for (; it != invocations_.end(); ++it) {
13835 SymbolInfo* caller = it->first.first;
13836 SymbolInfo* function = it->first.second;
13837
13838 // Filter out non-matching functions.
13839 if (function_name != NULL) {
13840 if (function->name.find(function_name) == std::string::npos)
13841 continue;
13842 }
13843
13844 // Filter out non-matching callers.
13845 if (caller_name != NULL) {
13846 if (caller == NULL)
13847 continue;
13848 if (caller->name.find(caller_name) == std::string::npos)
13849 continue;
13850 }
13851
13852 // It matches add the invocation count to the tally.
13853 invocations += it->second;
13854 }
13855
13856 return invocations;
13857}
13858
13859
13860void SetFunctionEntryHookTest::RunLoopInNewEnv(v8::Isolate* isolate) {
ulan@chromium.org57ff8812013-05-10 08:16:55 +000013861 v8::HandleScope outer(isolate);
13862 v8::Local<Context> env = Context::New(isolate);
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013863 env->Enter();
13864
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000013865 Local<ObjectTemplate> t = ObjectTemplate::New(isolate);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000013866 t->Set(v8_str("asdf"), v8::FunctionTemplate::New(isolate, RuntimeCallback));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013867 env->Global()->Set(v8_str("obj"), t->NewInstance());
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013868
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013869 const char* script =
13870 "function bar() {\n"
13871 " var sum = 0;\n"
13872 " for (i = 0; i < 100; ++i)\n"
13873 " sum = foo(i);\n"
13874 " return sum;\n"
13875 "}\n"
13876 "function foo(i) { return i * i; }\n"
13877 "// Invoke on the runtime function.\n"
13878 "obj.asdf()";
13879 CompileRun(script);
13880 bar_func_ = i::Handle<i::JSFunction>::cast(
13881 v8::Utils::OpenHandle(*env->Global()->Get(v8_str("bar"))));
13882 ASSERT(!bar_func_.is_null());
13883
13884 foo_func_ =
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013885 i::Handle<i::JSFunction>::cast(
13886 v8::Utils::OpenHandle(*env->Global()->Get(v8_str("foo"))));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013887 ASSERT(!foo_func_.is_null());
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013888
13889 v8::Handle<v8::Value> value = CompileRun("bar();");
13890 CHECK(value->IsNumber());
13891 CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value());
13892
13893 // Test the optimized codegen path.
13894 value = CompileRun("%OptimizeFunctionOnNextCall(foo);"
13895 "bar();");
13896 CHECK(value->IsNumber());
13897 CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value());
13898
13899 env->Exit();
13900}
13901
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000013902
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013903void SetFunctionEntryHookTest::RunTest() {
13904 // Work in a new isolate throughout.
13905 v8::Isolate* isolate = v8::Isolate::New();
13906
13907 // Test setting the entry hook on the new isolate.
13908 CHECK(v8::V8::SetFunctionEntryHook(isolate, EntryHook));
13909
13910 // Replacing the hook, once set should fail.
13911 CHECK_EQ(false, v8::V8::SetFunctionEntryHook(isolate, EntryHook));
13912
13913 {
13914 v8::Isolate::Scope scope(isolate);
13915
13916 v8::V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, JitEvent);
13917
13918 RunLoopInNewEnv(isolate);
13919
13920 // Check the exepected invocation counts.
13921 CHECK_EQ(2, CountInvocations(NULL, "bar"));
13922 CHECK_EQ(200, CountInvocations("bar", "foo"));
13923 CHECK_EQ(200, CountInvocations(NULL, "foo"));
13924
13925 // Verify that we have an entry hook on some specific stubs.
13926 CHECK_NE(0, CountInvocations(NULL, "CEntryStub"));
13927 CHECK_NE(0, CountInvocations(NULL, "JSEntryStub"));
13928 CHECK_NE(0, CountInvocations(NULL, "JSEntryTrampoline"));
13929 }
13930 isolate->Dispose();
13931
13932 Reset();
13933
13934 // Make sure a second isolate is unaffected by the previous entry hook.
13935 isolate = v8::Isolate::New();
13936 {
13937 v8::Isolate::Scope scope(isolate);
13938
13939 // Reset the entry count to zero and set the entry hook.
13940 RunLoopInNewEnv(isolate);
13941
13942 // We should record no invocations in this isolate.
13943 CHECK_EQ(0, static_cast<int>(invocations_.size()));
13944 }
13945 // Since the isolate has been used, we shouldn't be able to set an entry
13946 // hook anymore.
13947 CHECK_EQ(false, v8::V8::SetFunctionEntryHook(isolate, EntryHook));
13948
13949 isolate->Dispose();
13950}
13951
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013952
13953TEST(SetFunctionEntryHook) {
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000013954 // FunctionEntryHook does not work well with experimental natives.
13955 // Experimental natives are compiled during snapshot deserialization.
13956 // This test breaks because InstallGetter (function from snapshot that
13957 // only gets called from experimental natives) is compiled with entry hooks.
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013958 i::FLAG_allow_natives_syntax = true;
yangguo@chromium.orgfb377212012-11-16 14:43:43 +000013959 i::FLAG_use_inlining = false;
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013960
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013961 SetFunctionEntryHookTest test;
13962 test.RunTest();
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013963}
13964
13965
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000013966static i::HashMap* code_map = NULL;
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +000013967static i::HashMap* jitcode_line_info = NULL;
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000013968static int saw_bar = 0;
13969static int move_events = 0;
13970
13971
13972static bool FunctionNameIs(const char* expected,
13973 const v8::JitCodeEvent* event) {
13974 // Log lines for functions are of the general form:
13975 // "LazyCompile:<type><function_name>", where the type is one of
13976 // "*", "~" or "".
13977 static const char kPreamble[] = "LazyCompile:";
13978 static size_t kPreambleLen = sizeof(kPreamble) - 1;
13979
13980 if (event->name.len < sizeof(kPreamble) - 1 ||
13981 strncmp(kPreamble, event->name.str, kPreambleLen) != 0) {
13982 return false;
13983 }
13984
13985 const char* tail = event->name.str + kPreambleLen;
13986 size_t tail_len = event->name.len - kPreambleLen;
13987 size_t expected_len = strlen(expected);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000013988 if (tail_len > 1 && (*tail == '*' || *tail == '~')) {
13989 --tail_len;
13990 ++tail;
13991 }
13992
13993 // Check for tails like 'bar :1'.
13994 if (tail_len > expected_len + 2 &&
13995 tail[expected_len] == ' ' &&
13996 tail[expected_len + 1] == ':' &&
13997 tail[expected_len + 2] &&
13998 !strncmp(tail, expected, expected_len)) {
13999 return true;
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014000 }
14001
14002 if (tail_len != expected_len)
14003 return false;
14004
14005 return strncmp(tail, expected, expected_len) == 0;
14006}
14007
14008
14009static void event_handler(const v8::JitCodeEvent* event) {
14010 CHECK(event != NULL);
14011 CHECK(code_map != NULL);
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +000014012 CHECK(jitcode_line_info != NULL);
14013
14014 class DummyJitCodeLineInfo {
14015 };
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014016
14017 switch (event->type) {
14018 case v8::JitCodeEvent::CODE_ADDED: {
14019 CHECK(event->code_start != NULL);
14020 CHECK_NE(0, static_cast<int>(event->code_len));
14021 CHECK(event->name.str != NULL);
14022 i::HashMap::Entry* entry =
14023 code_map->Lookup(event->code_start,
14024 i::ComputePointerHash(event->code_start),
14025 true);
14026 entry->value = reinterpret_cast<void*>(event->code_len);
14027
14028 if (FunctionNameIs("bar", event)) {
14029 ++saw_bar;
14030 }
14031 }
14032 break;
14033
14034 case v8::JitCodeEvent::CODE_MOVED: {
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014035 uint32_t hash = i::ComputePointerHash(event->code_start);
jkummerow@chromium.org78502a92012-09-06 13:50:42 +000014036 // We would like to never see code move that we haven't seen before,
14037 // but the code creation event does not happen until the line endings
14038 // have been calculated (this is so that we can report the line in the
14039 // script at which the function source is found, see
14040 // Compiler::RecordFunctionCompilation) and the line endings
14041 // calculations can cause a GC, which can move the newly created code
14042 // before its existence can be logged.
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014043 i::HashMap::Entry* entry =
14044 code_map->Lookup(event->code_start, hash, false);
jkummerow@chromium.org78502a92012-09-06 13:50:42 +000014045 if (entry != NULL) {
14046 ++move_events;
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014047
jkummerow@chromium.org78502a92012-09-06 13:50:42 +000014048 CHECK_EQ(reinterpret_cast<void*>(event->code_len), entry->value);
14049 code_map->Remove(event->code_start, hash);
14050
14051 entry = code_map->Lookup(event->new_code_start,
14052 i::ComputePointerHash(event->new_code_start),
14053 true);
14054 CHECK(entry != NULL);
14055 entry->value = reinterpret_cast<void*>(event->code_len);
14056 }
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014057 }
14058 break;
14059
14060 case v8::JitCodeEvent::CODE_REMOVED:
14061 // Object/code removal events are currently not dispatched from the GC.
14062 CHECK(false);
14063 break;
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +000014064
14065 // For CODE_START_LINE_INFO_RECORDING event, we will create one
14066 // DummyJitCodeLineInfo data structure pointed by event->user_dat. We
14067 // record it in jitcode_line_info.
14068 case v8::JitCodeEvent::CODE_START_LINE_INFO_RECORDING: {
14069 DummyJitCodeLineInfo* line_info = new DummyJitCodeLineInfo();
14070 v8::JitCodeEvent* temp_event = const_cast<v8::JitCodeEvent*>(event);
14071 temp_event->user_data = line_info;
14072 i::HashMap::Entry* entry =
14073 jitcode_line_info->Lookup(line_info,
14074 i::ComputePointerHash(line_info),
14075 true);
14076 entry->value = reinterpret_cast<void*>(line_info);
14077 }
14078 break;
14079 // For these two events, we will check whether the event->user_data
14080 // data structure is created before during CODE_START_LINE_INFO_RECORDING
14081 // event. And delete it in CODE_END_LINE_INFO_RECORDING event handling.
14082 case v8::JitCodeEvent::CODE_END_LINE_INFO_RECORDING: {
14083 CHECK(event->user_data != NULL);
14084 uint32_t hash = i::ComputePointerHash(event->user_data);
14085 i::HashMap::Entry* entry =
14086 jitcode_line_info->Lookup(event->user_data, hash, false);
14087 CHECK(entry != NULL);
14088 delete reinterpret_cast<DummyJitCodeLineInfo*>(event->user_data);
14089 }
14090 break;
14091
14092 case v8::JitCodeEvent::CODE_ADD_LINE_POS_INFO: {
14093 CHECK(event->user_data != NULL);
14094 uint32_t hash = i::ComputePointerHash(event->user_data);
14095 i::HashMap::Entry* entry =
14096 jitcode_line_info->Lookup(event->user_data, hash, false);
14097 CHECK(entry != NULL);
14098 }
14099 break;
14100
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014101 default:
14102 // Impossible event.
14103 CHECK(false);
14104 break;
14105 }
14106}
14107
14108
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014109UNINITIALIZED_TEST(SetJitCodeEventHandler) {
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +000014110 i::FLAG_stress_compaction = true;
danno@chromium.orgf005df62013-04-30 16:36:45 +000014111 i::FLAG_incremental_marking = false;
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014112 const char* script =
14113 "function bar() {"
14114 " var sum = 0;"
14115 " for (i = 0; i < 100; ++i)"
14116 " sum = foo(i);"
14117 " return sum;"
14118 "}"
14119 "function foo(i) { return i * i; };"
14120 "bar();";
14121
14122 // Run this test in a new isolate to make sure we don't
14123 // have remnants of state from other code.
14124 v8::Isolate* isolate = v8::Isolate::New();
14125 isolate->Enter();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014126 i::Heap* heap = reinterpret_cast<i::Isolate*>(isolate)->heap();
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014127
14128 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014129 v8::HandleScope scope(isolate);
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014130 i::HashMap code(MatchPointers);
14131 code_map = &code;
14132
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +000014133 i::HashMap lineinfo(MatchPointers);
14134 jitcode_line_info = &lineinfo;
14135
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014136 saw_bar = 0;
14137 move_events = 0;
14138
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014139 V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, event_handler);
14140
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014141 // Generate new code objects sparsely distributed across several
14142 // different fragmented code-space pages.
14143 const int kIterations = 10;
14144 for (int i = 0; i < kIterations; ++i) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014145 LocalContext env(isolate);
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +000014146 i::AlwaysAllocateScope always_allocate;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014147 SimulateFullSpace(heap->code_space());
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +000014148 CompileRun(script);
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014149
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +000014150 // Keep a strong reference to the code object in the handle scope.
14151 i::Handle<i::Code> bar_code(i::Handle<i::JSFunction>::cast(
14152 v8::Utils::OpenHandle(*env->Global()->Get(v8_str("bar"))))->code());
14153 i::Handle<i::Code> foo_code(i::Handle<i::JSFunction>::cast(
14154 v8::Utils::OpenHandle(*env->Global()->Get(v8_str("foo"))))->code());
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014155
14156 // Clear the compilation cache to get more wastage.
hpayer@chromium.orgc5d49712013-09-11 08:25:48 +000014157 reinterpret_cast<i::Isolate*>(isolate)->compilation_cache()->Clear();
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014158 }
14159
14160 // Force code movement.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014161 heap->CollectAllAvailableGarbage("TestSetJitCodeEventHandler");
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014162
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +000014163 V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
14164
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014165 CHECK_LE(kIterations, saw_bar);
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +000014166 CHECK_LT(0, move_events);
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014167
14168 code_map = NULL;
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +000014169 jitcode_line_info = NULL;
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014170 }
14171
14172 isolate->Exit();
14173 isolate->Dispose();
14174
14175 // Do this in a new isolate.
14176 isolate = v8::Isolate::New();
14177 isolate->Enter();
14178
14179 // Verify that we get callbacks for existing code objects when we
14180 // request enumeration of existing code.
14181 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014182 v8::HandleScope scope(isolate);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014183 LocalContext env(isolate);
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014184 CompileRun(script);
14185
14186 // Now get code through initial iteration.
14187 i::HashMap code(MatchPointers);
14188 code_map = &code;
14189
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +000014190 i::HashMap lineinfo(MatchPointers);
14191 jitcode_line_info = &lineinfo;
14192
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014193 V8::SetJitCodeEventHandler(v8::kJitCodeEventEnumExisting, event_handler);
14194 V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
14195
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +000014196 jitcode_line_info = NULL;
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014197 // We expect that we got some events. Note that if we could get code removal
14198 // notifications, we could compare two collections, one created by listening
14199 // from the time of creation of an isolate, and the other by subscribing
14200 // with EnumExisting.
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +000014201 CHECK_LT(0, code.occupancy());
14202
14203 code_map = NULL;
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014204 }
14205
14206 isolate->Exit();
14207 isolate->Dispose();
14208}
14209
14210
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000014211THREADED_TEST(ExternalAllocatedMemory) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014212 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000014213 v8::HandleScope outer(isolate);
14214 v8::Local<Context> env(Context::New(isolate));
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000014215 CHECK(!env.IsEmpty());
machenbach@chromium.org7ff76072013-11-21 09:47:43 +000014216 const int64_t kSize = 1024*1024;
14217 int64_t baseline = isolate->AdjustAmountOfExternalAllocatedMemory(0);
14218 CHECK_EQ(baseline + kSize,
14219 isolate->AdjustAmountOfExternalAllocatedMemory(kSize));
danno@chromium.orgf005df62013-04-30 16:36:45 +000014220 CHECK_EQ(baseline,
machenbach@chromium.org7ff76072013-11-21 09:47:43 +000014221 isolate->AdjustAmountOfExternalAllocatedMemory(-kSize));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000014222}
14223
14224
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014225// Regression test for issue 54, object templates with internal fields
14226// but no accessors or interceptors did not get their internal field
14227// count set on instances.
14228THREADED_TEST(Regress54) {
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014229 LocalContext context;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000014230 v8::Isolate* isolate = context->GetIsolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014231 v8::HandleScope outer(isolate);
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014232 static v8::Persistent<v8::ObjectTemplate> templ;
14233 if (templ.IsEmpty()) {
machenbach@chromium.orgafbdadc2013-12-09 16:12:18 +000014234 v8::EscapableHandleScope inner(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000014235 v8::Local<v8::ObjectTemplate> local = v8::ObjectTemplate::New(isolate);
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014236 local->SetInternalFieldCount(1);
machenbach@chromium.orgafbdadc2013-12-09 16:12:18 +000014237 templ.Reset(isolate, inner.Escape(local));
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014238 }
rossberg@chromium.org79e79022013-06-03 15:43:46 +000014239 v8::Handle<v8::Object> result =
14240 v8::Local<v8::ObjectTemplate>::New(isolate, templ)->NewInstance();
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014241 CHECK_EQ(1, result->InternalFieldCount());
14242}
14243
14244
14245// If part of the threaded tests, this test makes ThreadingTest fail
14246// on mac.
14247TEST(CatchStackOverflow) {
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014248 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014249 v8::HandleScope scope(context->GetIsolate());
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014250 v8::TryCatch try_catch;
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000014251 v8::Handle<v8::Script> script = v8::Script::Compile(v8::String::NewFromUtf8(
14252 context->GetIsolate(),
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014253 "function f() {"
14254 " return f();"
14255 "}"
14256 ""
14257 "f();"));
14258 v8::Handle<v8::Value> result = script->Run();
14259 CHECK(result.IsEmpty());
14260}
14261
14262
kasperl@chromium.org7be3c992009-03-12 07:19:55 +000014263static void CheckTryCatchSourceInfo(v8::Handle<v8::Script> script,
14264 const char* resource_name,
14265 int line_offset) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014266 v8::HandleScope scope(CcTest::isolate());
kasperl@chromium.org7be3c992009-03-12 07:19:55 +000014267 v8::TryCatch try_catch;
14268 v8::Handle<v8::Value> result = script->Run();
14269 CHECK(result.IsEmpty());
14270 CHECK(try_catch.HasCaught());
14271 v8::Handle<v8::Message> message = try_catch.Message();
14272 CHECK(!message.IsEmpty());
14273 CHECK_EQ(10 + line_offset, message->GetLineNumber());
14274 CHECK_EQ(91, message->GetStartPosition());
14275 CHECK_EQ(92, message->GetEndPosition());
14276 CHECK_EQ(2, message->GetStartColumn());
14277 CHECK_EQ(3, message->GetEndColumn());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000014278 v8::String::Utf8Value line(message->GetSourceLine());
kasperl@chromium.org7be3c992009-03-12 07:19:55 +000014279 CHECK_EQ(" throw 'nirk';", *line);
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000014280 v8::String::Utf8Value name(message->GetScriptResourceName());
kasperl@chromium.org7be3c992009-03-12 07:19:55 +000014281 CHECK_EQ(resource_name, *name);
14282}
14283
14284
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014285THREADED_TEST(TryCatchSourceInfo) {
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014286 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014287 v8::HandleScope scope(context->GetIsolate());
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000014288 v8::Handle<v8::String> source = v8::String::NewFromUtf8(
14289 context->GetIsolate(),
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014290 "function Foo() {\n"
14291 " return Bar();\n"
14292 "}\n"
14293 "\n"
14294 "function Bar() {\n"
14295 " return Baz();\n"
14296 "}\n"
14297 "\n"
14298 "function Baz() {\n"
14299 " throw 'nirk';\n"
14300 "}\n"
14301 "\n"
14302 "Foo();\n");
kasperl@chromium.org7be3c992009-03-12 07:19:55 +000014303
14304 const char* resource_name;
14305 v8::Handle<v8::Script> script;
14306 resource_name = "test.js";
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000014307 script = v8::Script::Compile(
14308 source, v8::String::NewFromUtf8(context->GetIsolate(), resource_name));
kasperl@chromium.org7be3c992009-03-12 07:19:55 +000014309 CheckTryCatchSourceInfo(script, resource_name, 0);
14310
14311 resource_name = "test1.js";
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000014312 v8::ScriptOrigin origin1(
14313 v8::String::NewFromUtf8(context->GetIsolate(), resource_name));
kasperl@chromium.org7be3c992009-03-12 07:19:55 +000014314 script = v8::Script::Compile(source, &origin1);
14315 CheckTryCatchSourceInfo(script, resource_name, 0);
14316
14317 resource_name = "test2.js";
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000014318 v8::ScriptOrigin origin2(
14319 v8::String::NewFromUtf8(context->GetIsolate(), resource_name),
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014320 v8::Integer::New(context->GetIsolate(), 7));
kasperl@chromium.org7be3c992009-03-12 07:19:55 +000014321 script = v8::Script::Compile(source, &origin2);
14322 CheckTryCatchSourceInfo(script, resource_name, 7);
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014323}
kasperl@chromium.orgb9123622008-09-17 14:05:56 +000014324
14325
14326THREADED_TEST(CompilationCache) {
kasperl@chromium.orgb9123622008-09-17 14:05:56 +000014327 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014328 v8::HandleScope scope(context->GetIsolate());
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000014329 v8::Handle<v8::String> source0 =
14330 v8::String::NewFromUtf8(context->GetIsolate(), "1234");
14331 v8::Handle<v8::String> source1 =
14332 v8::String::NewFromUtf8(context->GetIsolate(), "1234");
14333 v8::Handle<v8::Script> script0 = v8::Script::Compile(
14334 source0, v8::String::NewFromUtf8(context->GetIsolate(), "test.js"));
14335 v8::Handle<v8::Script> script1 = v8::Script::Compile(
14336 source1, v8::String::NewFromUtf8(context->GetIsolate(), "test.js"));
kasperl@chromium.orgb9123622008-09-17 14:05:56 +000014337 v8::Handle<v8::Script> script2 =
14338 v8::Script::Compile(source0); // different origin
14339 CHECK_EQ(1234, script0->Run()->Int32Value());
14340 CHECK_EQ(1234, script1->Run()->Int32Value());
14341 CHECK_EQ(1234, script2->Run()->Int32Value());
14342}
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000014343
14344
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000014345static void FunctionNameCallback(
14346 const v8::FunctionCallbackInfo<v8::Value>& args) {
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000014347 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000014348 args.GetReturnValue().Set(v8_num(42));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000014349}
14350
14351
14352THREADED_TEST(CallbackFunctionName) {
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000014353 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000014354 v8::Isolate* isolate = context->GetIsolate();
14355 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000014356 Local<ObjectTemplate> t = ObjectTemplate::New(isolate);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000014357 t->Set(v8_str("asdf"),
14358 v8::FunctionTemplate::New(isolate, FunctionNameCallback));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000014359 context->Global()->Set(v8_str("obj"), t->NewInstance());
14360 v8::Handle<v8::Value> value = CompileRun("obj.asdf.name");
14361 CHECK(value->IsString());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000014362 v8::String::Utf8Value name(value);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000014363 CHECK_EQ("asdf", *name);
14364}
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014365
14366
14367THREADED_TEST(DateAccess) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014368 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014369 v8::HandleScope scope(context->GetIsolate());
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000014370 v8::Handle<v8::Value> date =
14371 v8::Date::New(context->GetIsolate(), 1224744689038.0);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014372 CHECK(date->IsDate());
danno@chromium.orgd3c42102013-08-01 16:58:23 +000014373 CHECK_EQ(1224744689038.0, date.As<v8::Date>()->ValueOf());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014374}
14375
14376
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014377void CheckProperties(v8::Isolate* isolate,
14378 v8::Handle<v8::Value> val,
14379 int elmc,
14380 const char* elmv[]) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000014381 v8::Handle<v8::Object> obj = val.As<v8::Object>();
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014382 v8::Handle<v8::Array> props = obj->GetPropertyNames();
14383 CHECK_EQ(elmc, props->Length());
14384 for (int i = 0; i < elmc; i++) {
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014385 v8::String::Utf8Value elm(props->Get(v8::Integer::New(isolate, i)));
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014386 CHECK_EQ(elmv[i], *elm);
14387 }
14388}
14389
14390
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014391void CheckOwnProperties(v8::Isolate* isolate,
14392 v8::Handle<v8::Value> val,
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000014393 int elmc,
14394 const char* elmv[]) {
14395 v8::Handle<v8::Object> obj = val.As<v8::Object>();
14396 v8::Handle<v8::Array> props = obj->GetOwnPropertyNames();
14397 CHECK_EQ(elmc, props->Length());
14398 for (int i = 0; i < elmc; i++) {
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014399 v8::String::Utf8Value elm(props->Get(v8::Integer::New(isolate, i)));
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000014400 CHECK_EQ(elmv[i], *elm);
14401 }
14402}
14403
14404
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014405THREADED_TEST(PropertyEnumeration) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014406 LocalContext context;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014407 v8::Isolate* isolate = context->GetIsolate();
14408 v8::HandleScope scope(isolate);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000014409 v8::Handle<v8::Value> obj = v8::Script::Compile(v8::String::NewFromUtf8(
14410 context->GetIsolate(),
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014411 "var result = [];"
14412 "result[0] = {};"
14413 "result[1] = {a: 1, b: 2};"
14414 "result[2] = [1, 2, 3];"
14415 "var proto = {x: 1, y: 2, z: 3};"
14416 "var x = { __proto__: proto, w: 0, z: 1 };"
14417 "result[3] = x;"
14418 "result;"))->Run();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000014419 v8::Handle<v8::Array> elms = obj.As<v8::Array>();
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014420 CHECK_EQ(4, elms->Length());
14421 int elmc0 = 0;
14422 const char** elmv0 = NULL;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014423 CheckProperties(
14424 isolate, elms->Get(v8::Integer::New(isolate, 0)), elmc0, elmv0);
14425 CheckOwnProperties(
14426 isolate, elms->Get(v8::Integer::New(isolate, 0)), elmc0, elmv0);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014427 int elmc1 = 2;
14428 const char* elmv1[] = {"a", "b"};
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014429 CheckProperties(
14430 isolate, elms->Get(v8::Integer::New(isolate, 1)), elmc1, elmv1);
14431 CheckOwnProperties(
14432 isolate, elms->Get(v8::Integer::New(isolate, 1)), elmc1, elmv1);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014433 int elmc2 = 3;
14434 const char* elmv2[] = {"0", "1", "2"};
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014435 CheckProperties(
14436 isolate, elms->Get(v8::Integer::New(isolate, 2)), elmc2, elmv2);
14437 CheckOwnProperties(
14438 isolate, elms->Get(v8::Integer::New(isolate, 2)), elmc2, elmv2);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014439 int elmc3 = 4;
14440 const char* elmv3[] = {"w", "z", "x", "y"};
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014441 CheckProperties(
14442 isolate, elms->Get(v8::Integer::New(isolate, 3)), elmc3, elmv3);
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000014443 int elmc4 = 2;
14444 const char* elmv4[] = {"w", "z"};
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014445 CheckOwnProperties(
14446 isolate, elms->Get(v8::Integer::New(isolate, 3)), elmc4, elmv4);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014447}
ager@chromium.org870a0b62008-11-04 11:43:05 +000014448
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000014449
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000014450THREADED_TEST(PropertyEnumeration2) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000014451 LocalContext context;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014452 v8::Isolate* isolate = context->GetIsolate();
14453 v8::HandleScope scope(isolate);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000014454 v8::Handle<v8::Value> obj = v8::Script::Compile(v8::String::NewFromUtf8(
14455 context->GetIsolate(),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000014456 "var result = [];"
14457 "result[0] = {};"
14458 "result[1] = {a: 1, b: 2};"
14459 "result[2] = [1, 2, 3];"
14460 "var proto = {x: 1, y: 2, z: 3};"
14461 "var x = { __proto__: proto, w: 0, z: 1 };"
14462 "result[3] = x;"
14463 "result;"))->Run();
14464 v8::Handle<v8::Array> elms = obj.As<v8::Array>();
14465 CHECK_EQ(4, elms->Length());
14466 int elmc0 = 0;
14467 const char** elmv0 = NULL;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014468 CheckProperties(isolate,
14469 elms->Get(v8::Integer::New(isolate, 0)), elmc0, elmv0);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000014470
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014471 v8::Handle<v8::Value> val = elms->Get(v8::Integer::New(isolate, 0));
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000014472 v8::Handle<v8::Array> props = val.As<v8::Object>()->GetPropertyNames();
14473 CHECK_EQ(0, props->Length());
14474 for (uint32_t i = 0; i < props->Length(); i++) {
14475 printf("p[%d]\n", i);
14476 }
14477}
ager@chromium.org870a0b62008-11-04 11:43:05 +000014478
ager@chromium.org870a0b62008-11-04 11:43:05 +000014479static bool NamedSetAccessBlocker(Local<v8::Object> obj,
14480 Local<Value> name,
14481 v8::AccessType type,
14482 Local<Value> data) {
14483 return type != v8::ACCESS_SET;
14484}
14485
14486
14487static bool IndexedSetAccessBlocker(Local<v8::Object> obj,
14488 uint32_t key,
14489 v8::AccessType type,
14490 Local<Value> data) {
14491 return type != v8::ACCESS_SET;
14492}
14493
14494
14495THREADED_TEST(DisableAccessChecksWhileConfiguring) {
ager@chromium.org870a0b62008-11-04 11:43:05 +000014496 LocalContext context;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000014497 v8::Isolate* isolate = context->GetIsolate();
14498 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000014499 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org870a0b62008-11-04 11:43:05 +000014500 templ->SetAccessCheckCallbacks(NamedSetAccessBlocker,
14501 IndexedSetAccessBlocker);
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000014502 templ->Set(v8_str("x"), v8::True(isolate));
ager@chromium.org870a0b62008-11-04 11:43:05 +000014503 Local<v8::Object> instance = templ->NewInstance();
14504 context->Global()->Set(v8_str("obj"), instance);
14505 Local<Value> value = CompileRun("obj.x");
14506 CHECK(value->BooleanValue());
14507}
ager@chromium.orga74f0da2008-12-03 16:05:52 +000014508
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000014509
ager@chromium.org32912102009-01-16 10:38:43 +000014510static bool NamedGetAccessBlocker(Local<v8::Object> obj,
14511 Local<Value> name,
14512 v8::AccessType type,
14513 Local<Value> data) {
14514 return false;
14515}
14516
14517
14518static bool IndexedGetAccessBlocker(Local<v8::Object> obj,
14519 uint32_t key,
14520 v8::AccessType type,
14521 Local<Value> data) {
14522 return false;
14523}
14524
14525
14526
14527THREADED_TEST(AccessChecksReenabledCorrectly) {
ager@chromium.org32912102009-01-16 10:38:43 +000014528 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000014529 v8::Isolate* isolate = context->GetIsolate();
14530 v8::HandleScope scope(isolate);
14531 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org32912102009-01-16 10:38:43 +000014532 templ->SetAccessCheckCallbacks(NamedGetAccessBlocker,
14533 IndexedGetAccessBlocker);
14534 templ->Set(v8_str("a"), v8_str("a"));
14535 // Add more than 8 (see kMaxFastProperties) properties
14536 // so that the constructor will force copying map.
14537 // Cannot sprintf, gcc complains unsafety.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000014538 char buf[4];
ager@chromium.org32912102009-01-16 10:38:43 +000014539 for (char i = '0'; i <= '9' ; i++) {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000014540 buf[0] = i;
ager@chromium.org32912102009-01-16 10:38:43 +000014541 for (char j = '0'; j <= '9'; j++) {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000014542 buf[1] = j;
ager@chromium.org32912102009-01-16 10:38:43 +000014543 for (char k = '0'; k <= '9'; k++) {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000014544 buf[2] = k;
14545 buf[3] = 0;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000014546 templ->Set(v8_str(buf), v8::Number::New(isolate, k));
ager@chromium.org32912102009-01-16 10:38:43 +000014547 }
14548 }
14549 }
14550
14551 Local<v8::Object> instance_1 = templ->NewInstance();
14552 context->Global()->Set(v8_str("obj_1"), instance_1);
14553
14554 Local<Value> value_1 = CompileRun("obj_1.a");
14555 CHECK(value_1->IsUndefined());
14556
14557 Local<v8::Object> instance_2 = templ->NewInstance();
14558 context->Global()->Set(v8_str("obj_2"), instance_2);
14559
14560 Local<Value> value_2 = CompileRun("obj_2.a");
14561 CHECK(value_2->IsUndefined());
14562}
ager@chromium.orga74f0da2008-12-03 16:05:52 +000014563
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000014564
ager@chromium.org8bb60582008-12-11 12:02:20 +000014565// This tests that access check information remains on the global
14566// object template when creating contexts.
14567THREADED_TEST(AccessControlRepeatedContextCreation) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014568 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000014569 v8::HandleScope handle_scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000014570 v8::Handle<v8::ObjectTemplate> global_template =
14571 v8::ObjectTemplate::New(isolate);
ager@chromium.org8bb60582008-12-11 12:02:20 +000014572 global_template->SetAccessCheckCallbacks(NamedSetAccessBlocker,
14573 IndexedSetAccessBlocker);
14574 i::Handle<i::ObjectTemplateInfo> internal_template =
14575 v8::Utils::OpenHandle(*global_template);
14576 CHECK(!internal_template->constructor()->IsUndefined());
14577 i::Handle<i::FunctionTemplateInfo> constructor(
14578 i::FunctionTemplateInfo::cast(internal_template->constructor()));
14579 CHECK(!constructor->access_check_info()->IsUndefined());
ulan@chromium.org57ff8812013-05-10 08:16:55 +000014580 v8::Local<Context> context0(Context::New(isolate, NULL, global_template));
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000014581 CHECK(!context0.IsEmpty());
ager@chromium.org8bb60582008-12-11 12:02:20 +000014582 CHECK(!constructor->access_check_info()->IsUndefined());
14583}
14584
14585
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000014586THREADED_TEST(TurnOnAccessCheck) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014587 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000014588 v8::HandleScope handle_scope(isolate);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000014589
14590 // Create an environment with access check to the global object disabled by
14591 // default.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000014592 v8::Handle<v8::ObjectTemplate> global_template =
14593 v8::ObjectTemplate::New(isolate);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000014594 global_template->SetAccessCheckCallbacks(NamedGetAccessBlocker,
14595 IndexedGetAccessBlocker,
14596 v8::Handle<v8::Value>(),
14597 false);
ulan@chromium.org57ff8812013-05-10 08:16:55 +000014598 v8::Local<Context> context = Context::New(isolate, NULL, global_template);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000014599 Context::Scope context_scope(context);
14600
14601 // Set up a property and a number of functions.
14602 context->Global()->Set(v8_str("a"), v8_num(1));
14603 CompileRun("function f1() {return a;}"
14604 "function f2() {return a;}"
14605 "function g1() {return h();}"
14606 "function g2() {return h();}"
14607 "function h() {return 1;}");
14608 Local<Function> f1 =
14609 Local<Function>::Cast(context->Global()->Get(v8_str("f1")));
14610 Local<Function> f2 =
14611 Local<Function>::Cast(context->Global()->Get(v8_str("f2")));
14612 Local<Function> g1 =
14613 Local<Function>::Cast(context->Global()->Get(v8_str("g1")));
14614 Local<Function> g2 =
14615 Local<Function>::Cast(context->Global()->Get(v8_str("g2")));
14616 Local<Function> h =
14617 Local<Function>::Cast(context->Global()->Get(v8_str("h")));
14618
14619 // Get the global object.
14620 v8::Handle<v8::Object> global = context->Global();
14621
14622 // Call f1 one time and f2 a number of times. This will ensure that f1 still
14623 // uses the runtime system to retreive property a whereas f2 uses global load
14624 // inline cache.
14625 CHECK(f1->Call(global, 0, NULL)->Equals(v8_num(1)));
14626 for (int i = 0; i < 4; i++) {
14627 CHECK(f2->Call(global, 0, NULL)->Equals(v8_num(1)));
14628 }
14629
14630 // Same for g1 and g2.
14631 CHECK(g1->Call(global, 0, NULL)->Equals(v8_num(1)));
14632 for (int i = 0; i < 4; i++) {
14633 CHECK(g2->Call(global, 0, NULL)->Equals(v8_num(1)));
14634 }
14635
14636 // Detach the global and turn on access check.
jkummerow@chromium.org113035e2013-12-13 15:13:40 +000014637 Local<Object> hidden_global = Local<Object>::Cast(
14638 context->Global()->GetPrototype());
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000014639 context->DetachGlobal();
jkummerow@chromium.org113035e2013-12-13 15:13:40 +000014640 hidden_global->TurnOnAccessCheck();
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000014641
14642 // Failing access check to property get results in undefined.
14643 CHECK(f1->Call(global, 0, NULL)->IsUndefined());
14644 CHECK(f2->Call(global, 0, NULL)->IsUndefined());
14645
14646 // Failing access check to function call results in exception.
14647 CHECK(g1->Call(global, 0, NULL).IsEmpty());
14648 CHECK(g2->Call(global, 0, NULL).IsEmpty());
14649
14650 // No failing access check when just returning a constant.
14651 CHECK(h->Call(global, 0, NULL)->Equals(v8_num(1)));
14652}
14653
14654
jkummerow@chromium.orgf7a58842012-02-21 10:08:21 +000014655static const char* kPropertyA = "a";
14656static const char* kPropertyH = "h";
kasperl@chromium.orga5551262010-12-07 12:49:48 +000014657
14658static bool NamedGetAccessBlockAandH(Local<v8::Object> obj,
14659 Local<Value> name,
14660 v8::AccessType type,
14661 Local<Value> data) {
jkummerow@chromium.orgf7a58842012-02-21 10:08:21 +000014662 if (!name->IsString()) return false;
14663 i::Handle<i::String> name_handle =
14664 v8::Utils::OpenHandle(String::Cast(*name));
jkummerow@chromium.org59297c72013-01-09 16:32:23 +000014665 return !name_handle->IsUtf8EqualTo(i::CStrVector(kPropertyA))
14666 && !name_handle->IsUtf8EqualTo(i::CStrVector(kPropertyH));
kasperl@chromium.orga5551262010-12-07 12:49:48 +000014667}
14668
14669
jkummerow@chromium.orgf7a58842012-02-21 10:08:21 +000014670THREADED_TEST(TurnOnAccessCheckAndRecompile) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014671 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000014672 v8::HandleScope handle_scope(isolate);
kasperl@chromium.orga5551262010-12-07 12:49:48 +000014673
14674 // Create an environment with access check to the global object disabled by
14675 // default. When the registered access checker will block access to properties
jkummerow@chromium.orgf7a58842012-02-21 10:08:21 +000014676 // a and h.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000014677 v8::Handle<v8::ObjectTemplate> global_template =
14678 v8::ObjectTemplate::New(isolate);
kasperl@chromium.orga5551262010-12-07 12:49:48 +000014679 global_template->SetAccessCheckCallbacks(NamedGetAccessBlockAandH,
14680 IndexedGetAccessBlocker,
14681 v8::Handle<v8::Value>(),
14682 false);
ulan@chromium.org57ff8812013-05-10 08:16:55 +000014683 v8::Local<Context> context = Context::New(isolate, NULL, global_template);
kasperl@chromium.orga5551262010-12-07 12:49:48 +000014684 Context::Scope context_scope(context);
14685
14686 // Set up a property and a number of functions.
14687 context->Global()->Set(v8_str("a"), v8_num(1));
14688 static const char* source = "function f1() {return a;}"
14689 "function f2() {return a;}"
14690 "function g1() {return h();}"
14691 "function g2() {return h();}"
14692 "function h() {return 1;}";
14693
14694 CompileRun(source);
14695 Local<Function> f1;
14696 Local<Function> f2;
14697 Local<Function> g1;
14698 Local<Function> g2;
14699 Local<Function> h;
14700 f1 = Local<Function>::Cast(context->Global()->Get(v8_str("f1")));
14701 f2 = Local<Function>::Cast(context->Global()->Get(v8_str("f2")));
14702 g1 = Local<Function>::Cast(context->Global()->Get(v8_str("g1")));
14703 g2 = Local<Function>::Cast(context->Global()->Get(v8_str("g2")));
14704 h = Local<Function>::Cast(context->Global()->Get(v8_str("h")));
14705
14706 // Get the global object.
14707 v8::Handle<v8::Object> global = context->Global();
14708
14709 // Call f1 one time and f2 a number of times. This will ensure that f1 still
14710 // uses the runtime system to retreive property a whereas f2 uses global load
14711 // inline cache.
14712 CHECK(f1->Call(global, 0, NULL)->Equals(v8_num(1)));
14713 for (int i = 0; i < 4; i++) {
14714 CHECK(f2->Call(global, 0, NULL)->Equals(v8_num(1)));
14715 }
14716
14717 // Same for g1 and g2.
14718 CHECK(g1->Call(global, 0, NULL)->Equals(v8_num(1)));
14719 for (int i = 0; i < 4; i++) {
14720 CHECK(g2->Call(global, 0, NULL)->Equals(v8_num(1)));
14721 }
14722
14723 // Detach the global and turn on access check now blocking access to property
14724 // a and function h.
jkummerow@chromium.org113035e2013-12-13 15:13:40 +000014725 Local<Object> hidden_global = Local<Object>::Cast(
14726 context->Global()->GetPrototype());
kasperl@chromium.orga5551262010-12-07 12:49:48 +000014727 context->DetachGlobal();
jkummerow@chromium.org113035e2013-12-13 15:13:40 +000014728 hidden_global->TurnOnAccessCheck();
kasperl@chromium.orga5551262010-12-07 12:49:48 +000014729
14730 // Failing access check to property get results in undefined.
14731 CHECK(f1->Call(global, 0, NULL)->IsUndefined());
14732 CHECK(f2->Call(global, 0, NULL)->IsUndefined());
14733
14734 // Failing access check to function call results in exception.
14735 CHECK(g1->Call(global, 0, NULL).IsEmpty());
14736 CHECK(g2->Call(global, 0, NULL).IsEmpty());
14737
14738 // No failing access check when just returning a constant.
14739 CHECK(h->Call(global, 0, NULL)->Equals(v8_num(1)));
14740
14741 // Now compile the source again. And get the newly compiled functions, except
14742 // for h for which access is blocked.
14743 CompileRun(source);
jkummerow@chromium.org113035e2013-12-13 15:13:40 +000014744 f1 = Local<Function>::Cast(hidden_global->Get(v8_str("f1")));
14745 f2 = Local<Function>::Cast(hidden_global->Get(v8_str("f2")));
14746 g1 = Local<Function>::Cast(hidden_global->Get(v8_str("g1")));
14747 g2 = Local<Function>::Cast(hidden_global->Get(v8_str("g2")));
14748 CHECK(hidden_global->Get(v8_str("h"))->IsUndefined());
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
14759
ager@chromium.orga74f0da2008-12-03 16:05:52 +000014760// This test verifies that pre-compilation (aka preparsing) can be called
14761// without initializing the whole VM. Thus we cannot run this test in a
14762// multi-threaded setup.
14763TEST(PreCompile) {
14764 // TODO(155): This test would break without the initialization of V8. This is
14765 // a workaround for now to make this test not fail.
14766 v8::V8::Initialize();
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +000014767 v8::Isolate* isolate = CcTest::isolate();
machenbach@chromium.org4ddd2f12014-01-14 08:13:44 +000014768 HandleScope handle_scope(isolate);
kmillikin@chromium.org9155e252010-05-26 13:27:57 +000014769 const char* script = "function foo(a) { return a+1; }";
machenbach@chromium.org4ddd2f12014-01-14 08:13:44 +000014770 v8::ScriptData* sd = v8::ScriptData::PreCompile(v8::String::NewFromUtf8(
14771 isolate, script, v8::String::kNormalString, i::StrLength(script)));
ager@chromium.orga74f0da2008-12-03 16:05:52 +000014772 CHECK_NE(sd->Length(), 0);
14773 CHECK_NE(sd->Data(), NULL);
fschneider@chromium.org0c20e672010-01-14 15:28:53 +000014774 CHECK(!sd->HasError());
14775 delete sd;
14776}
14777
14778
14779TEST(PreCompileWithError) {
14780 v8::V8::Initialize();
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +000014781 v8::Isolate* isolate = CcTest::isolate();
machenbach@chromium.org4ddd2f12014-01-14 08:13:44 +000014782 HandleScope handle_scope(isolate);
kmillikin@chromium.org9155e252010-05-26 13:27:57 +000014783 const char* script = "function foo(a) { return 1 * * 2; }";
machenbach@chromium.org4ddd2f12014-01-14 08:13:44 +000014784 v8::ScriptData* sd = v8::ScriptData::PreCompile(v8::String::NewFromUtf8(
14785 isolate, script, v8::String::kNormalString, i::StrLength(script)));
fschneider@chromium.org0c20e672010-01-14 15:28:53 +000014786 CHECK(sd->HasError());
14787 delete sd;
14788}
14789
14790
14791TEST(Regress31661) {
14792 v8::V8::Initialize();
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +000014793 v8::Isolate* isolate = CcTest::isolate();
machenbach@chromium.org4ddd2f12014-01-14 08:13:44 +000014794 HandleScope handle_scope(isolate);
kmillikin@chromium.org9155e252010-05-26 13:27:57 +000014795 const char* script = " The Definintive Guide";
machenbach@chromium.org4ddd2f12014-01-14 08:13:44 +000014796 v8::ScriptData* sd = v8::ScriptData::PreCompile(v8::String::NewFromUtf8(
14797 isolate, script, v8::String::kNormalString, i::StrLength(script)));
fschneider@chromium.org0c20e672010-01-14 15:28:53 +000014798 CHECK(sd->HasError());
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000014799 delete sd;
ager@chromium.orga74f0da2008-12-03 16:05:52 +000014800}
14801
14802
kmillikin@chromium.org9155e252010-05-26 13:27:57 +000014803// Tests that ScriptData can be serialized and deserialized.
14804TEST(PreCompileSerialization) {
14805 v8::V8::Initialize();
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +000014806 v8::Isolate* isolate = CcTest::isolate();
machenbach@chromium.org4ddd2f12014-01-14 08:13:44 +000014807 HandleScope handle_scope(isolate);
kmillikin@chromium.org9155e252010-05-26 13:27:57 +000014808 const char* script = "function foo(a) { return a+1; }";
machenbach@chromium.org4ddd2f12014-01-14 08:13:44 +000014809 v8::ScriptData* sd = v8::ScriptData::PreCompile(v8::String::NewFromUtf8(
14810 isolate, script, v8::String::kNormalString, i::StrLength(script)));
kmillikin@chromium.org9155e252010-05-26 13:27:57 +000014811
14812 // Serialize.
14813 int serialized_data_length = sd->Length();
14814 char* serialized_data = i::NewArray<char>(serialized_data_length);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +000014815 i::OS::MemCopy(serialized_data, sd->Data(), serialized_data_length);
kmillikin@chromium.org9155e252010-05-26 13:27:57 +000014816
14817 // Deserialize.
14818 v8::ScriptData* deserialized_sd =
14819 v8::ScriptData::New(serialized_data, serialized_data_length);
14820
14821 // Verify that the original is the same as the deserialized.
14822 CHECK_EQ(sd->Length(), deserialized_sd->Length());
14823 CHECK_EQ(0, memcmp(sd->Data(), deserialized_sd->Data(), sd->Length()));
14824 CHECK_EQ(sd->HasError(), deserialized_sd->HasError());
14825
14826 delete sd;
14827 delete deserialized_sd;
machenbach@chromium.orgbb8234d2014-02-10 09:01:23 +000014828 i::DeleteArray(serialized_data);
kmillikin@chromium.org9155e252010-05-26 13:27:57 +000014829}
14830
14831
14832// Attempts to deserialize bad data.
14833TEST(PreCompileDeserializationError) {
14834 v8::V8::Initialize();
14835 const char* data = "DONT CARE";
14836 int invalid_size = 3;
14837 v8::ScriptData* sd = v8::ScriptData::New(data, invalid_size);
14838
14839 CHECK_EQ(0, sd->Length());
14840
14841 delete sd;
14842}
14843
14844
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014845// Attempts to deserialize bad data.
14846TEST(PreCompileInvalidPreparseDataError) {
14847 v8::V8::Initialize();
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +000014848 v8::Isolate* isolate = CcTest::isolate();
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014849 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014850 v8::HandleScope scope(context->GetIsolate());
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014851
14852 const char* script = "function foo(){ return 5;}\n"
14853 "function bar(){ return 6 + 7;} foo();";
machenbach@chromium.org4ddd2f12014-01-14 08:13:44 +000014854 v8::ScriptData* sd = v8::ScriptData::PreCompile(v8::String::NewFromUtf8(
14855 isolate, script, v8::String::kNormalString, i::StrLength(script)));
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014856 CHECK(!sd->HasError());
14857 // ScriptDataImpl private implementation details
ager@chromium.orgbeb25712010-11-29 08:02:25 +000014858 const int kHeaderSize = i::PreparseDataConstants::kHeaderSize;
ager@chromium.org5b2fbee2010-09-08 06:38:15 +000014859 const int kFunctionEntrySize = i::FunctionEntry::kSize;
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014860 const int kFunctionEntryStartOffset = 0;
14861 const int kFunctionEntryEndOffset = 1;
14862 unsigned* sd_data =
14863 reinterpret_cast<unsigned*>(const_cast<char*>(sd->Data()));
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014864
14865 // Overwrite function bar's end position with 0.
14866 sd_data[kHeaderSize + 1 * kFunctionEntrySize + kFunctionEntryEndOffset] = 0;
14867 v8::TryCatch try_catch;
14868
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000014869 Local<String> source = String::NewFromUtf8(isolate, script);
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014870 Local<Script> compiled_script = Script::New(source, NULL, sd);
14871 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000014872 String::Utf8Value exception_value(try_catch.Message()->Get());
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014873 CHECK_EQ("Uncaught SyntaxError: Invalid preparser data for function bar",
14874 *exception_value);
14875
14876 try_catch.Reset();
machenbach@chromium.orgbb8234d2014-02-10 09:01:23 +000014877 delete sd;
lrn@chromium.orgd4e9e222011-08-03 12:01:58 +000014878
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014879 // Overwrite function bar's start position with 200. The function entry
lrn@chromium.orgd4e9e222011-08-03 12:01:58 +000014880 // will not be found when searching for it by position and we should fall
14881 // back on eager compilation.
machenbach@chromium.org4ddd2f12014-01-14 08:13:44 +000014882 sd = v8::ScriptData::PreCompile(v8::String::NewFromUtf8(
14883 isolate, script, v8::String::kNormalString, i::StrLength(script)));
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +000014884 sd_data = reinterpret_cast<unsigned*>(const_cast<char*>(sd->Data()));
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014885 sd_data[kHeaderSize + 1 * kFunctionEntrySize + kFunctionEntryStartOffset] =
14886 200;
14887 compiled_script = Script::New(source, NULL, sd);
lrn@chromium.orgd4e9e222011-08-03 12:01:58 +000014888 CHECK(!try_catch.HasCaught());
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014889
14890 delete sd;
14891}
14892
14893
ager@chromium.orga74f0da2008-12-03 16:05:52 +000014894// This tests that we do not allow dictionary load/call inline caches
14895// to use functions that have not yet been compiled. The potential
14896// problem of loading a function that has not yet been compiled can
14897// arise because we share code between contexts via the compilation
14898// cache.
14899THREADED_TEST(DictionaryICLoadedFunction) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014900 v8::HandleScope scope(CcTest::isolate());
ager@chromium.orga74f0da2008-12-03 16:05:52 +000014901 // Test LoadIC.
14902 for (int i = 0; i < 2; i++) {
14903 LocalContext context;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000014904 context->Global()->Set(v8_str("tmp"), v8::True(CcTest::isolate()));
ager@chromium.orga74f0da2008-12-03 16:05:52 +000014905 context->Global()->Delete(v8_str("tmp"));
14906 CompileRun("for (var j = 0; j < 10; j++) new RegExp('');");
14907 }
14908 // Test CallIC.
14909 for (int i = 0; i < 2; i++) {
14910 LocalContext context;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000014911 context->Global()->Set(v8_str("tmp"), v8::True(CcTest::isolate()));
ager@chromium.orga74f0da2008-12-03 16:05:52 +000014912 context->Global()->Delete(v8_str("tmp"));
14913 CompileRun("for (var j = 0; j < 10; j++) RegExp('')");
14914 }
14915}
ager@chromium.orgddb913d2009-01-27 10:01:48 +000014916
14917
14918// Test that cross-context new calls use the context of the callee to
14919// create the new JavaScript object.
14920THREADED_TEST(CrossContextNew) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014921 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000014922 v8::HandleScope scope(isolate);
14923 v8::Local<Context> context0 = Context::New(isolate);
14924 v8::Local<Context> context1 = Context::New(isolate);
ager@chromium.orgddb913d2009-01-27 10:01:48 +000014925
14926 // Allow cross-domain access.
14927 Local<String> token = v8_str("<security token>");
14928 context0->SetSecurityToken(token);
14929 context1->SetSecurityToken(token);
14930
14931 // Set an 'x' property on the Object prototype and define a
14932 // constructor function in context0.
14933 context0->Enter();
14934 CompileRun("Object.prototype.x = 42; function C() {};");
14935 context0->Exit();
14936
14937 // Call the constructor function from context0 and check that the
14938 // result has the 'x' property.
14939 context1->Enter();
14940 context1->Global()->Set(v8_str("other"), context0->Global());
14941 Local<Value> value = CompileRun("var instance = new other.C(); instance.x");
14942 CHECK(value->IsInt32());
14943 CHECK_EQ(42, value->Int32Value());
14944 context1->Exit();
ager@chromium.orgddb913d2009-01-27 10:01:48 +000014945}
ager@chromium.org381abbb2009-02-25 13:23:22 +000014946
14947
ager@chromium.org3b45ab52009-03-19 22:21:34 +000014948// Verify that we can clone an object
14949TEST(ObjectClone) {
ager@chromium.org3b45ab52009-03-19 22:21:34 +000014950 LocalContext env;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014951 v8::Isolate* isolate = env->GetIsolate();
14952 v8::HandleScope scope(isolate);
ager@chromium.org3b45ab52009-03-19 22:21:34 +000014953
14954 const char* sample =
14955 "var rv = {};" \
14956 "rv.alpha = 'hello';" \
14957 "rv.beta = 123;" \
14958 "rv;";
14959
14960 // Create an object, verify basics.
14961 Local<Value> val = CompileRun(sample);
14962 CHECK(val->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000014963 Local<v8::Object> obj = val.As<v8::Object>();
ager@chromium.org3b45ab52009-03-19 22:21:34 +000014964 obj->Set(v8_str("gamma"), v8_str("cloneme"));
14965
14966 CHECK_EQ(v8_str("hello"), obj->Get(v8_str("alpha")));
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014967 CHECK_EQ(v8::Integer::New(isolate, 123), obj->Get(v8_str("beta")));
ager@chromium.org3b45ab52009-03-19 22:21:34 +000014968 CHECK_EQ(v8_str("cloneme"), obj->Get(v8_str("gamma")));
14969
14970 // Clone it.
14971 Local<v8::Object> clone = obj->Clone();
14972 CHECK_EQ(v8_str("hello"), clone->Get(v8_str("alpha")));
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014973 CHECK_EQ(v8::Integer::New(isolate, 123), clone->Get(v8_str("beta")));
ager@chromium.org3b45ab52009-03-19 22:21:34 +000014974 CHECK_EQ(v8_str("cloneme"), clone->Get(v8_str("gamma")));
14975
14976 // Set a property on the clone, verify each object.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014977 clone->Set(v8_str("beta"), v8::Integer::New(isolate, 456));
14978 CHECK_EQ(v8::Integer::New(isolate, 123), obj->Get(v8_str("beta")));
14979 CHECK_EQ(v8::Integer::New(isolate, 456), clone->Get(v8_str("beta")));
ager@chromium.org3b45ab52009-03-19 22:21:34 +000014980}
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000014981
14982
ager@chromium.org5ec48922009-05-05 07:25:34 +000014983class AsciiVectorResource : public v8::String::ExternalAsciiStringResource {
14984 public:
14985 explicit AsciiVectorResource(i::Vector<const char> vector)
14986 : data_(vector) {}
14987 virtual ~AsciiVectorResource() {}
14988 virtual size_t length() const { return data_.length(); }
14989 virtual const char* data() const { return data_.start(); }
14990 private:
14991 i::Vector<const char> data_;
14992};
14993
14994
14995class UC16VectorResource : public v8::String::ExternalStringResource {
14996 public:
14997 explicit UC16VectorResource(i::Vector<const i::uc16> vector)
14998 : data_(vector) {}
14999 virtual ~UC16VectorResource() {}
15000 virtual size_t length() const { return data_.length(); }
15001 virtual const i::uc16* data() const { return data_.start(); }
15002 private:
15003 i::Vector<const i::uc16> data_;
15004};
15005
15006
15007static void MorphAString(i::String* string,
15008 AsciiVectorResource* ascii_resource,
15009 UC16VectorResource* uc16_resource) {
15010 CHECK(i::StringShape(string).IsExternal());
ulan@chromium.org8e8d8822012-11-23 14:36:46 +000015011 if (string->IsOneByteRepresentation()) {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +000015012 // Check old map is not internalized or long.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015013 CHECK(string->map() == CcTest::heap()->external_ascii_string_map());
ager@chromium.org5ec48922009-05-05 07:25:34 +000015014 // Morph external string to be TwoByte string.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015015 string->set_map(CcTest::heap()->external_string_map());
ager@chromium.org5ec48922009-05-05 07:25:34 +000015016 i::ExternalTwoByteString* morphed =
15017 i::ExternalTwoByteString::cast(string);
15018 morphed->set_resource(uc16_resource);
15019 } else {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +000015020 // Check old map is not internalized or long.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015021 CHECK(string->map() == CcTest::heap()->external_string_map());
ager@chromium.org5ec48922009-05-05 07:25:34 +000015022 // Morph external string to be ASCII string.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015023 string->set_map(CcTest::heap()->external_ascii_string_map());
ager@chromium.org5ec48922009-05-05 07:25:34 +000015024 i::ExternalAsciiString* morphed =
15025 i::ExternalAsciiString::cast(string);
15026 morphed->set_resource(ascii_resource);
15027 }
15028}
15029
15030
15031// Test that we can still flatten a string if the components it is built up
15032// from have been turned into 16 bit strings in the mean time.
15033THREADED_TEST(MorphCompositeStringTest) {
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +000015034 char utf_buffer[129];
ager@chromium.org5ec48922009-05-05 07:25:34 +000015035 const char* c_string = "Now is the time for all good men"
15036 " to come to the aid of the party";
15037 uint16_t* two_byte_string = AsciiToTwoByteString(c_string);
15038 {
ager@chromium.org5ec48922009-05-05 07:25:34 +000015039 LocalContext env;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015040 i::Factory* factory = CcTest::i_isolate()->factory();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015041 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org5ec48922009-05-05 07:25:34 +000015042 AsciiVectorResource ascii_resource(
ager@chromium.orgc4c92722009-11-18 14:12:51 +000015043 i::Vector<const char>(c_string, i::StrLength(c_string)));
ager@chromium.org5ec48922009-05-05 07:25:34 +000015044 UC16VectorResource uc16_resource(
ager@chromium.orgc4c92722009-11-18 14:12:51 +000015045 i::Vector<const uint16_t>(two_byte_string,
15046 i::StrLength(c_string)));
ager@chromium.org5ec48922009-05-05 07:25:34 +000015047
15048 Local<String> lhs(v8::Utils::ToLocal(
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000015049 factory->NewExternalStringFromAscii(&ascii_resource)));
ager@chromium.org5ec48922009-05-05 07:25:34 +000015050 Local<String> rhs(v8::Utils::ToLocal(
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000015051 factory->NewExternalStringFromAscii(&ascii_resource)));
ager@chromium.org5ec48922009-05-05 07:25:34 +000015052
15053 env->Global()->Set(v8_str("lhs"), lhs);
15054 env->Global()->Set(v8_str("rhs"), rhs);
15055
15056 CompileRun(
15057 "var cons = lhs + rhs;"
15058 "var slice = lhs.substring(1, lhs.length - 1);"
15059 "var slice_on_cons = (lhs + rhs).substring(1, lhs.length *2 - 1);");
15060
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015061 CHECK(lhs->IsOneByte());
15062 CHECK(rhs->IsOneByte());
rossberg@chromium.org2c067b12012-03-19 11:01:52 +000015063
ager@chromium.org5ec48922009-05-05 07:25:34 +000015064 MorphAString(*v8::Utils::OpenHandle(*lhs), &ascii_resource, &uc16_resource);
15065 MorphAString(*v8::Utils::OpenHandle(*rhs), &ascii_resource, &uc16_resource);
15066
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +000015067 // This should UTF-8 without flattening, since everything is ASCII.
15068 Handle<String> cons = v8_compile("cons")->Run().As<String>();
15069 CHECK_EQ(128, cons->Utf8Length());
15070 int nchars = -1;
15071 CHECK_EQ(129, cons->WriteUtf8(utf_buffer, -1, &nchars));
15072 CHECK_EQ(128, nchars);
15073 CHECK_EQ(0, strcmp(
15074 utf_buffer,
15075 "Now is the time for all good men to come to the aid of the party"
15076 "Now is the time for all good men to come to the aid of the party"));
15077
ager@chromium.org5ec48922009-05-05 07:25:34 +000015078 // Now do some stuff to make sure the strings are flattened, etc.
15079 CompileRun(
15080 "/[^a-z]/.test(cons);"
15081 "/[^a-z]/.test(slice);"
15082 "/[^a-z]/.test(slice_on_cons);");
15083 const char* expected_cons =
15084 "Now is the time for all good men to come to the aid of the party"
15085 "Now is the time for all good men to come to the aid of the party";
15086 const char* expected_slice =
15087 "ow is the time for all good men to come to the aid of the part";
15088 const char* expected_slice_on_cons =
15089 "ow is the time for all good men to come to the aid of the party"
15090 "Now is the time for all good men to come to the aid of the part";
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015091 CHECK_EQ(String::NewFromUtf8(env->GetIsolate(), expected_cons),
ager@chromium.org5ec48922009-05-05 07:25:34 +000015092 env->Global()->Get(v8_str("cons")));
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015093 CHECK_EQ(String::NewFromUtf8(env->GetIsolate(), expected_slice),
ager@chromium.org5ec48922009-05-05 07:25:34 +000015094 env->Global()->Get(v8_str("slice")));
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015095 CHECK_EQ(String::NewFromUtf8(env->GetIsolate(), expected_slice_on_cons),
ager@chromium.org5ec48922009-05-05 07:25:34 +000015096 env->Global()->Get(v8_str("slice_on_cons")));
15097 }
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000015098 i::DeleteArray(two_byte_string);
ager@chromium.org5ec48922009-05-05 07:25:34 +000015099}
15100
15101
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000015102TEST(CompileExternalTwoByteSource) {
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000015103 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015104 v8::HandleScope scope(context->GetIsolate());
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000015105
15106 // This is a very short list of sources, which currently is to check for a
15107 // regression caused by r2703.
15108 const char* ascii_sources[] = {
15109 "0.5",
15110 "-0.5", // This mainly testes PushBack in the Scanner.
15111 "--0.5", // This mainly testes PushBack in the Scanner.
15112 NULL
15113 };
15114
15115 // Compile the sources as external two byte strings.
15116 for (int i = 0; ascii_sources[i] != NULL; i++) {
15117 uint16_t* two_byte_string = AsciiToTwoByteString(ascii_sources[i]);
machenbach@chromium.org57a54ac2014-01-31 14:01:53 +000015118 TestResource* uc16_resource = new TestResource(two_byte_string);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000015119 v8::Local<v8::String> source =
machenbach@chromium.org57a54ac2014-01-31 14:01:53 +000015120 v8::String::NewExternal(context->GetIsolate(), uc16_resource);
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000015121 v8::Script::Compile(source);
15122 }
15123}
15124
15125
mstarzinger@chromium.orgb4968be2013-10-16 09:00:56 +000015126#ifndef V8_INTERPRETED_REGEXP
15127
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +000015128struct RegExpInterruptionData {
15129 int loop_count;
15130 UC16VectorResource* string_resource;
15131 v8::Persistent<v8::String> string;
15132} regexp_interruption_data;
15133
15134
15135class RegExpInterruptionThread : public i::Thread {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015136 public:
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +000015137 explicit RegExpInterruptionThread(v8::Isolate* isolate)
15138 : Thread("TimeoutThread"), isolate_(isolate) {}
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000015139
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +000015140 virtual void Run() {
15141 for (regexp_interruption_data.loop_count = 0;
15142 regexp_interruption_data.loop_count < 7;
15143 regexp_interruption_data.loop_count++) {
15144 i::OS::Sleep(50); // Wait a bit before requesting GC.
15145 reinterpret_cast<i::Isolate*>(isolate_)->stack_guard()->RequestGC();
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015146 }
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +000015147 i::OS::Sleep(50); // Wait a bit before terminating.
15148 v8::V8::TerminateExecution(isolate_);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015149 }
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015150
jkummerow@chromium.orge297f592011-06-08 10:05:15 +000015151 private:
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +000015152 v8::Isolate* isolate_;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015153};
15154
15155
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +000015156void RunBeforeGC(v8::GCType type, v8::GCCallbackFlags flags) {
15157 if (regexp_interruption_data.loop_count != 2) return;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015158 v8::HandleScope scope(CcTest::isolate());
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +000015159 v8::Local<v8::String> string = v8::Local<v8::String>::New(
15160 CcTest::isolate(), regexp_interruption_data.string);
15161 string->MakeExternal(regexp_interruption_data.string_resource);
15162}
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015163
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015164
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +000015165// Test that RegExp execution can be interrupted. Specifically, we test
15166// * interrupting with GC
15167// * turn the subject string from one-byte internal to two-byte external string
15168// * force termination
15169TEST(RegExpInterruption) {
15170 v8::HandleScope scope(CcTest::isolate());
15171 LocalContext env;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015172
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +000015173 RegExpInterruptionThread timeout_thread(CcTest::isolate());
15174
15175 v8::V8::AddGCPrologueCallback(RunBeforeGC);
15176 static const char* ascii_content = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
15177 i::uc16* uc16_content = AsciiToTwoByteString(ascii_content);
15178 v8::Local<v8::String> string = v8_str(ascii_content);
15179
15180 CcTest::global()->Set(v8_str("a"), string);
15181 regexp_interruption_data.string.Reset(CcTest::isolate(), string);
15182 regexp_interruption_data.string_resource = new UC16VectorResource(
15183 i::Vector<const i::uc16>(uc16_content, i::StrLength(ascii_content)));
15184
15185 v8::TryCatch try_catch;
15186 timeout_thread.Start();
15187
15188 CompileRun("/((a*)*)*b/.exec(a)");
15189 CHECK(try_catch.HasTerminated());
15190
15191 timeout_thread.Join();
15192
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015193 regexp_interruption_data.string.Reset();
machenbach@chromium.orgbb8234d2014-02-10 09:01:23 +000015194 i::DeleteArray(uc16_content);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015195}
15196
mstarzinger@chromium.orgb4968be2013-10-16 09:00:56 +000015197#endif // V8_INTERPRETED_REGEXP
15198
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015199
mmassi@chromium.org7028c052012-06-13 11:51:58 +000015200// Test that we cannot set a property on the global object if there
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015201// is a read-only property in the prototype chain.
15202TEST(ReadOnlyPropertyInGlobalProto) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +000015203 i::FLAG_es5_readonly = true;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015204 v8::Isolate* isolate = CcTest::isolate();
15205 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000015206 v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015207 LocalContext context(0, templ);
15208 v8::Handle<v8::Object> global = context->Global();
15209 v8::Handle<v8::Object> global_proto =
15210 v8::Handle<v8::Object>::Cast(global->Get(v8_str("__proto__")));
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015211 global_proto->Set(v8_str("x"), v8::Integer::New(isolate, 0), v8::ReadOnly);
15212 global_proto->Set(v8_str("y"), v8::Integer::New(isolate, 0), v8::ReadOnly);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015213 // Check without 'eval' or 'with'.
15214 v8::Handle<v8::Value> res =
15215 CompileRun("function f() { x = 42; return x; }; f()");
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015216 CHECK_EQ(v8::Integer::New(isolate, 0), res);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015217 // Check with 'eval'.
mmassi@chromium.org7028c052012-06-13 11:51:58 +000015218 res = CompileRun("function f() { eval('1'); y = 43; return y; }; f()");
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015219 CHECK_EQ(v8::Integer::New(isolate, 0), res);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015220 // Check with 'with'.
mmassi@chromium.org7028c052012-06-13 11:51:58 +000015221 res = CompileRun("function f() { with (this) { y = 44 }; return y; }; f()");
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015222 CHECK_EQ(v8::Integer::New(isolate, 0), res);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015223}
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015224
15225static int force_set_set_count = 0;
15226static int force_set_get_count = 0;
15227bool pass_on_get = false;
15228
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015229static void ForceSetGetter(v8::Local<v8::String> name,
15230 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015231 force_set_get_count++;
15232 if (pass_on_get) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015233 return;
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015234 }
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015235 info.GetReturnValue().Set(3);
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015236}
15237
15238static void ForceSetSetter(v8::Local<v8::String> name,
15239 v8::Local<v8::Value> value,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015240 const v8::PropertyCallbackInfo<void>& info) {
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015241 force_set_set_count++;
15242}
15243
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015244static void ForceSetInterceptSetter(
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015245 v8::Local<v8::String> name,
15246 v8::Local<v8::Value> value,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015247 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015248 force_set_set_count++;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015249 info.GetReturnValue().SetUndefined();
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015250}
15251
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000015252
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015253TEST(ForceSet) {
15254 force_set_get_count = 0;
15255 force_set_set_count = 0;
15256 pass_on_get = false;
15257
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015258 v8::Isolate* isolate = CcTest::isolate();
15259 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000015260 v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015261 v8::Handle<v8::String> access_property =
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015262 v8::String::NewFromUtf8(isolate, "a");
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015263 templ->SetAccessor(access_property, ForceSetGetter, ForceSetSetter);
15264 LocalContext context(NULL, templ);
15265 v8::Handle<v8::Object> global = context->Global();
15266
15267 // Ordinary properties
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015268 v8::Handle<v8::String> simple_property =
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015269 v8::String::NewFromUtf8(isolate, "p");
15270 global->Set(simple_property, v8::Int32::New(isolate, 4), v8::ReadOnly);
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015271 CHECK_EQ(4, global->Get(simple_property)->Int32Value());
15272 // This should fail because the property is read-only
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015273 global->Set(simple_property, v8::Int32::New(isolate, 5));
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015274 CHECK_EQ(4, global->Get(simple_property)->Int32Value());
15275 // This should succeed even though the property is read-only
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015276 global->ForceSet(simple_property, v8::Int32::New(isolate, 6));
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015277 CHECK_EQ(6, global->Get(simple_property)->Int32Value());
15278
15279 // Accessors
15280 CHECK_EQ(0, force_set_set_count);
15281 CHECK_EQ(0, force_set_get_count);
15282 CHECK_EQ(3, global->Get(access_property)->Int32Value());
15283 // CHECK_EQ the property shouldn't override it, just call the setter
15284 // which in this case does nothing.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015285 global->Set(access_property, v8::Int32::New(isolate, 7));
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015286 CHECK_EQ(3, global->Get(access_property)->Int32Value());
15287 CHECK_EQ(1, force_set_set_count);
15288 CHECK_EQ(2, force_set_get_count);
15289 // Forcing the property to be set should override the accessor without
15290 // calling it
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015291 global->ForceSet(access_property, v8::Int32::New(isolate, 8));
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015292 CHECK_EQ(8, global->Get(access_property)->Int32Value());
15293 CHECK_EQ(1, force_set_set_count);
15294 CHECK_EQ(2, force_set_get_count);
15295}
15296
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000015297
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015298TEST(ForceSetWithInterceptor) {
15299 force_set_get_count = 0;
15300 force_set_set_count = 0;
15301 pass_on_get = false;
15302
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015303 v8::Isolate* isolate = CcTest::isolate();
15304 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000015305 v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015306 templ->SetNamedPropertyHandler(ForceSetGetter, ForceSetInterceptSetter);
15307 LocalContext context(NULL, templ);
15308 v8::Handle<v8::Object> global = context->Global();
15309
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015310 v8::Handle<v8::String> some_property =
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015311 v8::String::NewFromUtf8(isolate, "a");
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015312 CHECK_EQ(0, force_set_set_count);
15313 CHECK_EQ(0, force_set_get_count);
15314 CHECK_EQ(3, global->Get(some_property)->Int32Value());
15315 // Setting the property shouldn't override it, just call the setter
15316 // which in this case does nothing.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015317 global->Set(some_property, v8::Int32::New(isolate, 7));
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015318 CHECK_EQ(3, global->Get(some_property)->Int32Value());
15319 CHECK_EQ(1, force_set_set_count);
15320 CHECK_EQ(2, force_set_get_count);
15321 // Getting the property when the interceptor returns an empty handle
15322 // should yield undefined, since the property isn't present on the
15323 // object itself yet.
15324 pass_on_get = true;
15325 CHECK(global->Get(some_property)->IsUndefined());
15326 CHECK_EQ(1, force_set_set_count);
15327 CHECK_EQ(3, force_set_get_count);
15328 // Forcing the property to be set should cause the value to be
15329 // set locally without calling the interceptor.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015330 global->ForceSet(some_property, v8::Int32::New(isolate, 8));
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015331 CHECK_EQ(8, global->Get(some_property)->Int32Value());
15332 CHECK_EQ(1, force_set_set_count);
15333 CHECK_EQ(4, force_set_get_count);
15334 // Reenabling the interceptor should cause it to take precedence over
15335 // the property
15336 pass_on_get = false;
15337 CHECK_EQ(3, global->Get(some_property)->Int32Value());
15338 CHECK_EQ(1, force_set_set_count);
15339 CHECK_EQ(5, force_set_get_count);
15340 // The interceptor should also work for other properties
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015341 CHECK_EQ(3, global->Get(v8::String::NewFromUtf8(isolate, "b"))
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015342 ->Int32Value());
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015343 CHECK_EQ(1, force_set_set_count);
15344 CHECK_EQ(6, force_set_get_count);
15345}
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000015346
15347
ager@chromium.orge2902be2009-06-08 12:21:35 +000015348THREADED_TEST(ForceDelete) {
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015349 v8::Isolate* isolate = CcTest::isolate();
15350 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000015351 v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
ager@chromium.orge2902be2009-06-08 12:21:35 +000015352 LocalContext context(NULL, templ);
15353 v8::Handle<v8::Object> global = context->Global();
15354
15355 // Ordinary properties
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015356 v8::Handle<v8::String> simple_property =
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015357 v8::String::NewFromUtf8(isolate, "p");
15358 global->Set(simple_property, v8::Int32::New(isolate, 4), v8::DontDelete);
ager@chromium.orge2902be2009-06-08 12:21:35 +000015359 CHECK_EQ(4, global->Get(simple_property)->Int32Value());
15360 // This should fail because the property is dont-delete.
15361 CHECK(!global->Delete(simple_property));
15362 CHECK_EQ(4, global->Get(simple_property)->Int32Value());
15363 // This should succeed even though the property is dont-delete.
15364 CHECK(global->ForceDelete(simple_property));
15365 CHECK(global->Get(simple_property)->IsUndefined());
15366}
15367
15368
15369static int force_delete_interceptor_count = 0;
15370static bool pass_on_delete = false;
15371
15372
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015373static void ForceDeleteDeleter(
ager@chromium.orge2902be2009-06-08 12:21:35 +000015374 v8::Local<v8::String> name,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015375 const v8::PropertyCallbackInfo<v8::Boolean>& info) {
ager@chromium.orge2902be2009-06-08 12:21:35 +000015376 force_delete_interceptor_count++;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015377 if (pass_on_delete) return;
15378 info.GetReturnValue().Set(true);
ager@chromium.orge2902be2009-06-08 12:21:35 +000015379}
15380
15381
15382THREADED_TEST(ForceDeleteWithInterceptor) {
15383 force_delete_interceptor_count = 0;
15384 pass_on_delete = false;
15385
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015386 v8::Isolate* isolate = CcTest::isolate();
15387 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000015388 v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
ager@chromium.orge2902be2009-06-08 12:21:35 +000015389 templ->SetNamedPropertyHandler(0, 0, 0, ForceDeleteDeleter);
15390 LocalContext context(NULL, templ);
15391 v8::Handle<v8::Object> global = context->Global();
15392
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015393 v8::Handle<v8::String> some_property =
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015394 v8::String::NewFromUtf8(isolate, "a");
15395 global->Set(some_property, v8::Integer::New(isolate, 42), v8::DontDelete);
ager@chromium.orge2902be2009-06-08 12:21:35 +000015396
15397 // Deleting a property should get intercepted and nothing should
15398 // happen.
15399 CHECK_EQ(0, force_delete_interceptor_count);
15400 CHECK(global->Delete(some_property));
15401 CHECK_EQ(1, force_delete_interceptor_count);
15402 CHECK_EQ(42, global->Get(some_property)->Int32Value());
15403 // Deleting the property when the interceptor returns an empty
15404 // handle should not delete the property since it is DontDelete.
15405 pass_on_delete = true;
15406 CHECK(!global->Delete(some_property));
15407 CHECK_EQ(2, force_delete_interceptor_count);
15408 CHECK_EQ(42, global->Get(some_property)->Int32Value());
15409 // Forcing the property to be deleted should delete the value
15410 // without calling the interceptor.
15411 CHECK(global->ForceDelete(some_property));
15412 CHECK(global->Get(some_property)->IsUndefined());
15413 CHECK_EQ(2, force_delete_interceptor_count);
15414}
15415
15416
kasperl@chromium.org68ac0092009-07-09 06:00:35 +000015417// Make sure that forcing a delete invalidates any IC stubs, so we
15418// don't read the hole value.
15419THREADED_TEST(ForceDeleteIC) {
kasperl@chromium.org68ac0092009-07-09 06:00:35 +000015420 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015421 v8::HandleScope scope(context->GetIsolate());
kasperl@chromium.org68ac0092009-07-09 06:00:35 +000015422 // Create a DontDelete variable on the global object.
15423 CompileRun("this.__proto__ = { foo: 'horse' };"
15424 "var foo = 'fish';"
15425 "function f() { return foo.length; }");
15426 // Initialize the IC for foo in f.
15427 CompileRun("for (var i = 0; i < 4; i++) f();");
15428 // Make sure the value of foo is correct before the deletion.
15429 CHECK_EQ(4, CompileRun("f()")->Int32Value());
15430 // Force the deletion of foo.
15431 CHECK(context->Global()->ForceDelete(v8_str("foo")));
15432 // Make sure the value for foo is read from the prototype, and that
15433 // we don't get in trouble with reading the deleted cell value
15434 // sentinel.
15435 CHECK_EQ(5, CompileRun("f()")->Int32Value());
15436}
15437
15438
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +000015439TEST(InlinedFunctionAcrossContexts) {
15440 i::FLAG_allow_natives_syntax = true;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015441 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000015442 v8::HandleScope outer_scope(isolate);
15443 v8::Local<v8::Context> ctx1 = v8::Context::New(isolate);
15444 v8::Local<v8::Context> ctx2 = v8::Context::New(isolate);
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +000015445 ctx1->Enter();
15446
15447 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015448 v8::HandleScope inner_scope(CcTest::isolate());
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +000015449 CompileRun("var G = 42; function foo() { return G; }");
15450 v8::Local<v8::Value> foo = ctx1->Global()->Get(v8_str("foo"));
15451 ctx2->Enter();
15452 ctx2->Global()->Set(v8_str("o"), foo);
15453 v8::Local<v8::Value> res = CompileRun(
15454 "function f() { return o(); }"
15455 "for (var i = 0; i < 10; ++i) f();"
15456 "%OptimizeFunctionOnNextCall(f);"
15457 "f();");
15458 CHECK_EQ(42, res->Int32Value());
15459 ctx2->Exit();
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015460 v8::Handle<v8::String> G_property =
15461 v8::String::NewFromUtf8(CcTest::isolate(), "G");
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +000015462 CHECK(ctx1->Global()->ForceDelete(G_property));
15463 ctx2->Enter();
15464 ExpectString(
15465 "(function() {"
15466 " try {"
15467 " return f();"
15468 " } catch(e) {"
15469 " return e.toString();"
15470 " }"
15471 " })()",
15472 "ReferenceError: G is not defined");
15473 ctx2->Exit();
15474 ctx1->Exit();
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +000015475 }
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +000015476}
15477
15478
ulan@chromium.org57ff8812013-05-10 08:16:55 +000015479static v8::Local<Context> calling_context0;
15480static v8::Local<Context> calling_context1;
15481static v8::Local<Context> calling_context2;
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000015482
15483
15484// Check that the call to the callback is initiated in
15485// calling_context2, the directly calling context is calling_context1
15486// and the callback itself is in calling_context0.
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015487static void GetCallingContextCallback(
15488 const v8::FunctionCallbackInfo<v8::Value>& args) {
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000015489 ApiTestFuzzer::Fuzz();
mvstanton@chromium.org40ce96b2013-04-09 09:52:22 +000015490 CHECK(args.GetIsolate()->GetCurrentContext() == calling_context0);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015491 CHECK(args.GetIsolate()->GetCallingContext() == calling_context1);
15492 CHECK(args.GetIsolate()->GetEnteredContext() == calling_context2);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015493 args.GetReturnValue().Set(42);
15494}
15495
15496
15497THREADED_TEST(GetCurrentContextWhenNotInContext) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015498 i::Isolate* isolate = CcTest::i_isolate();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015499 CHECK(isolate != NULL);
15500 CHECK(isolate->context() == NULL);
15501 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
15502 v8::HandleScope scope(v8_isolate);
15503 // The following should not crash, but return an empty handle.
15504 v8::Local<v8::Context> current = v8_isolate->GetCurrentContext();
15505 CHECK(current.IsEmpty());
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000015506}
15507
15508
15509THREADED_TEST(GetCallingContext) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015510 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000015511 v8::HandleScope scope(isolate);
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000015512
ulan@chromium.org57ff8812013-05-10 08:16:55 +000015513 Local<Context> calling_context0(Context::New(isolate));
15514 Local<Context> calling_context1(Context::New(isolate));
15515 Local<Context> calling_context2(Context::New(isolate));
15516 ::calling_context0 = calling_context0;
15517 ::calling_context1 = calling_context1;
15518 ::calling_context2 = calling_context2;
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000015519
15520 // Allow cross-domain access.
15521 Local<String> token = v8_str("<security token>");
15522 calling_context0->SetSecurityToken(token);
15523 calling_context1->SetSecurityToken(token);
15524 calling_context2->SetSecurityToken(token);
15525
15526 // Create an object with a C++ callback in context0.
15527 calling_context0->Enter();
15528 Local<v8::FunctionTemplate> callback_templ =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000015529 v8::FunctionTemplate::New(isolate, GetCallingContextCallback);
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000015530 calling_context0->Global()->Set(v8_str("callback"),
15531 callback_templ->GetFunction());
15532 calling_context0->Exit();
15533
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000015534 // Expose context0 in context1 and set up a function that calls the
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000015535 // callback function.
15536 calling_context1->Enter();
15537 calling_context1->Global()->Set(v8_str("context0"),
15538 calling_context0->Global());
15539 CompileRun("function f() { context0.callback() }");
15540 calling_context1->Exit();
15541
15542 // Expose context1 in context2 and call the callback function in
15543 // context0 indirectly through f in context1.
15544 calling_context2->Enter();
15545 calling_context2->Global()->Set(v8_str("context1"),
15546 calling_context1->Global());
15547 CompileRun("context1.f()");
15548 calling_context2->Exit();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000015549 ::calling_context0.Clear();
15550 ::calling_context1.Clear();
15551 ::calling_context2.Clear();
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000015552}
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000015553
15554
15555// Check that a variable declaration with no explicit initialization
erik.corry@gmail.comed49e962012-04-17 11:57:53 +000015556// value does shadow an existing property in the prototype chain.
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000015557THREADED_TEST(InitGlobalVarInProtoChain) {
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +000015558 i::FLAG_es52_globals = true;
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000015559 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015560 v8::HandleScope scope(context->GetIsolate());
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000015561 // Introduce a variable in the prototype chain.
15562 CompileRun("__proto__.x = 42");
erik.corry@gmail.comed49e962012-04-17 11:57:53 +000015563 v8::Handle<v8::Value> result = CompileRun("var x = 43; x");
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000015564 CHECK(!result->IsUndefined());
erik.corry@gmail.comed49e962012-04-17 11:57:53 +000015565 CHECK_EQ(43, result->Int32Value());
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000015566}
kasperl@chromium.org68ac0092009-07-09 06:00:35 +000015567
15568
15569// Regression test for issue 398.
15570// If a function is added to an object, creating a constant function
15571// field, and the result is cloned, replacing the constant function on the
15572// original should not affect the clone.
15573// See http://code.google.com/p/v8/issues/detail?id=398
15574THREADED_TEST(ReplaceConstantFunction) {
kasperl@chromium.org68ac0092009-07-09 06:00:35 +000015575 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000015576 v8::Isolate* isolate = context->GetIsolate();
15577 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015578 v8::Handle<v8::Object> obj = v8::Object::New(isolate);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000015579 v8::Handle<v8::FunctionTemplate> func_templ =
15580 v8::FunctionTemplate::New(isolate);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015581 v8::Handle<v8::String> foo_string =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000015582 v8::String::NewFromUtf8(isolate, "foo");
kasperl@chromium.org68ac0092009-07-09 06:00:35 +000015583 obj->Set(foo_string, func_templ->GetFunction());
15584 v8::Handle<v8::Object> obj_clone = obj->Clone();
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015585 obj_clone->Set(foo_string,
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000015586 v8::String::NewFromUtf8(isolate, "Hello"));
kasperl@chromium.org68ac0092009-07-09 06:00:35 +000015587 CHECK(!obj->Get(foo_string)->IsUndefined());
15588}
kasperl@chromium.orge959c182009-07-27 08:59:04 +000015589
15590
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015591static void CheckElementValue(i::Isolate* isolate,
15592 int expected,
15593 i::Handle<i::Object> obj,
15594 int offset) {
15595 i::Object* element = obj->GetElement(isolate, offset)->ToObjectChecked();
15596 CHECK_EQ(expected, i::Smi::cast(element)->value());
15597}
15598
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015599
15600THREADED_TEST(PixelArray) {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015601 LocalContext context;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015602 i::Isolate* isolate = CcTest::i_isolate();
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015603 i::Factory* factory = isolate->factory();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015604 v8::HandleScope scope(context->GetIsolate());
ager@chromium.orgc4c92722009-11-18 14:12:51 +000015605 const int kElementCount = 260;
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015606 uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(kElementCount));
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000015607 i::Handle<i::ExternalUint8ClampedArray> pixels =
15608 i::Handle<i::ExternalUint8ClampedArray>::cast(
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000015609 factory->NewExternalArray(kElementCount,
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000015610 v8::kExternalUint8ClampedArray,
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000015611 pixel_data));
15612 // Force GC to trigger verification.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015613 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015614 for (int i = 0; i < kElementCount; i++) {
ager@chromium.orgc4c92722009-11-18 14:12:51 +000015615 pixels->set(i, i % 256);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015616 }
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000015617 // Force GC to trigger verification.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015618 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015619 for (int i = 0; i < kElementCount; i++) {
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +000015620 CHECK_EQ(i % 256, pixels->get_scalar(i));
ager@chromium.orgc4c92722009-11-18 14:12:51 +000015621 CHECK_EQ(i % 256, pixel_data[i]);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015622 }
15623
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015624 v8::Handle<v8::Object> obj = v8::Object::New(context->GetIsolate());
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015625 i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
15626 // Set the elements to be the pixels.
15627 // jsobj->set_elements(*pixels);
15628 obj->SetIndexedPropertiesToPixelData(pixel_data, kElementCount);
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015629 CheckElementValue(isolate, 1, jsobj, 1);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015630 obj->Set(v8_str("field"), v8::Int32::New(CcTest::isolate(), 1503));
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015631 context->Global()->Set(v8_str("pixels"), obj);
15632 v8::Handle<v8::Value> result = CompileRun("pixels.field");
15633 CHECK_EQ(1503, result->Int32Value());
15634 result = CompileRun("pixels[1]");
15635 CHECK_EQ(1, result->Int32Value());
sgjesse@chromium.org9eceac12009-09-30 07:18:41 +000015636
15637 result = CompileRun("var sum = 0;"
15638 "for (var i = 0; i < 8; i++) {"
15639 " sum += pixels[i] = pixels[i] = -i;"
15640 "}"
15641 "sum;");
15642 CHECK_EQ(-28, result->Int32Value());
15643
15644 result = CompileRun("var sum = 0;"
15645 "for (var i = 0; i < 8; i++) {"
15646 " sum += pixels[i] = pixels[i] = 0;"
15647 "}"
15648 "sum;");
15649 CHECK_EQ(0, result->Int32Value());
15650
15651 result = CompileRun("var sum = 0;"
15652 "for (var i = 0; i < 8; i++) {"
15653 " sum += pixels[i] = pixels[i] = 255;"
15654 "}"
15655 "sum;");
15656 CHECK_EQ(8 * 255, result->Int32Value());
15657
15658 result = CompileRun("var sum = 0;"
15659 "for (var i = 0; i < 8; i++) {"
15660 " sum += pixels[i] = pixels[i] = 256 + i;"
15661 "}"
15662 "sum;");
15663 CHECK_EQ(2076, result->Int32Value());
15664
15665 result = CompileRun("var sum = 0;"
15666 "for (var i = 0; i < 8; i++) {"
15667 " sum += pixels[i] = pixels[i] = i;"
15668 "}"
15669 "sum;");
15670 CHECK_EQ(28, result->Int32Value());
15671
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015672 result = CompileRun("var sum = 0;"
15673 "for (var i = 0; i < 8; i++) {"
15674 " sum += pixels[i];"
15675 "}"
15676 "sum;");
15677 CHECK_EQ(28, result->Int32Value());
15678
ulan@chromium.org09d7ab52013-02-25 15:50:35 +000015679 i::Handle<i::Smi> value(i::Smi::FromInt(2),
15680 reinterpret_cast<i::Isolate*>(context->GetIsolate()));
jkummerow@chromium.org486075a2011-09-07 12:44:28 +000015681 i::Handle<i::Object> no_failure;
yangguo@chromium.orgab30bb82012-02-24 14:41:46 +000015682 no_failure =
15683 i::JSObject::SetElement(jsobj, 1, value, NONE, i::kNonStrictMode);
jkummerow@chromium.org486075a2011-09-07 12:44:28 +000015684 ASSERT(!no_failure.is_null());
15685 i::USE(no_failure);
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015686 CheckElementValue(isolate, 2, jsobj, 1);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015687 *value.location() = i::Smi::FromInt(256);
yangguo@chromium.orgab30bb82012-02-24 14:41:46 +000015688 no_failure =
15689 i::JSObject::SetElement(jsobj, 1, value, NONE, i::kNonStrictMode);
jkummerow@chromium.org486075a2011-09-07 12:44:28 +000015690 ASSERT(!no_failure.is_null());
15691 i::USE(no_failure);
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015692 CheckElementValue(isolate, 255, jsobj, 1);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015693 *value.location() = i::Smi::FromInt(-1);
yangguo@chromium.orgab30bb82012-02-24 14:41:46 +000015694 no_failure =
15695 i::JSObject::SetElement(jsobj, 1, value, NONE, i::kNonStrictMode);
jkummerow@chromium.org486075a2011-09-07 12:44:28 +000015696 ASSERT(!no_failure.is_null());
15697 i::USE(no_failure);
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015698 CheckElementValue(isolate, 0, jsobj, 1);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015699
15700 result = CompileRun("for (var i = 0; i < 8; i++) {"
15701 " pixels[i] = (i * 65) - 109;"
15702 "}"
15703 "pixels[1] + pixels[6];");
15704 CHECK_EQ(255, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015705 CheckElementValue(isolate, 0, jsobj, 0);
15706 CheckElementValue(isolate, 0, jsobj, 1);
15707 CheckElementValue(isolate, 21, jsobj, 2);
15708 CheckElementValue(isolate, 86, jsobj, 3);
15709 CheckElementValue(isolate, 151, jsobj, 4);
15710 CheckElementValue(isolate, 216, jsobj, 5);
15711 CheckElementValue(isolate, 255, jsobj, 6);
15712 CheckElementValue(isolate, 255, jsobj, 7);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015713 result = CompileRun("var sum = 0;"
15714 "for (var i = 0; i < 8; i++) {"
15715 " sum += pixels[i];"
15716 "}"
15717 "sum;");
15718 CHECK_EQ(984, result->Int32Value());
15719
15720 result = CompileRun("for (var i = 0; i < 8; i++) {"
15721 " pixels[i] = (i * 1.1);"
15722 "}"
15723 "pixels[1] + pixels[6];");
15724 CHECK_EQ(8, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015725 CheckElementValue(isolate, 0, jsobj, 0);
15726 CheckElementValue(isolate, 1, jsobj, 1);
15727 CheckElementValue(isolate, 2, jsobj, 2);
15728 CheckElementValue(isolate, 3, jsobj, 3);
15729 CheckElementValue(isolate, 4, jsobj, 4);
15730 CheckElementValue(isolate, 6, jsobj, 5);
15731 CheckElementValue(isolate, 7, jsobj, 6);
15732 CheckElementValue(isolate, 8, jsobj, 7);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015733
15734 result = CompileRun("for (var i = 0; i < 8; i++) {"
15735 " pixels[7] = undefined;"
15736 "}"
15737 "pixels[7];");
15738 CHECK_EQ(0, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015739 CheckElementValue(isolate, 0, jsobj, 7);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015740
15741 result = CompileRun("for (var i = 0; i < 8; i++) {"
15742 " pixels[6] = '2.3';"
15743 "}"
15744 "pixels[6];");
15745 CHECK_EQ(2, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015746 CheckElementValue(isolate, 2, jsobj, 6);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015747
15748 result = CompileRun("for (var i = 0; i < 8; i++) {"
15749 " pixels[5] = NaN;"
15750 "}"
15751 "pixels[5];");
15752 CHECK_EQ(0, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015753 CheckElementValue(isolate, 0, jsobj, 5);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015754
15755 result = CompileRun("for (var i = 0; i < 8; i++) {"
15756 " pixels[8] = Infinity;"
15757 "}"
15758 "pixels[8];");
15759 CHECK_EQ(255, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015760 CheckElementValue(isolate, 255, jsobj, 8);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015761
15762 result = CompileRun("for (var i = 0; i < 8; i++) {"
15763 " pixels[9] = -Infinity;"
15764 "}"
15765 "pixels[9];");
15766 CHECK_EQ(0, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015767 CheckElementValue(isolate, 0, jsobj, 9);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015768
15769 result = CompileRun("pixels[3] = 33;"
15770 "delete pixels[3];"
15771 "pixels[3];");
15772 CHECK_EQ(33, result->Int32Value());
15773
15774 result = CompileRun("pixels[0] = 10; pixels[1] = 11;"
15775 "pixels[2] = 12; pixels[3] = 13;"
15776 "pixels.__defineGetter__('2',"
15777 "function() { return 120; });"
15778 "pixels[2];");
15779 CHECK_EQ(12, result->Int32Value());
15780
15781 result = CompileRun("var js_array = new Array(40);"
15782 "js_array[0] = 77;"
15783 "js_array;");
15784 CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
15785
15786 result = CompileRun("pixels[1] = 23;"
15787 "pixels.__proto__ = [];"
15788 "js_array.__proto__ = pixels;"
15789 "js_array.concat(pixels);");
15790 CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
15791 CHECK_EQ(23, v8::Object::Cast(*result)->Get(v8_str("1"))->Int32Value());
15792
sgjesse@chromium.org9eceac12009-09-30 07:18:41 +000015793 result = CompileRun("pixels[1] = 23;");
15794 CHECK_EQ(23, result->Int32Value());
15795
ager@chromium.orgc4c92722009-11-18 14:12:51 +000015796 // Test for index greater than 255. Regression test for:
15797 // http://code.google.com/p/chromium/issues/detail?id=26337.
15798 result = CompileRun("pixels[256] = 255;");
15799 CHECK_EQ(255, result->Int32Value());
15800 result = CompileRun("var i = 0;"
15801 "for (var j = 0; j < 8; j++) { i = pixels[256]; }"
15802 "i");
15803 CHECK_EQ(255, result->Int32Value());
15804
ricow@chromium.org83aa5492011-02-07 12:42:56 +000015805 // Make sure that pixel array ICs recognize when a non-pixel array
15806 // is passed to it.
15807 result = CompileRun("function pa_load(p) {"
15808 " var sum = 0;"
15809 " for (var j = 0; j < 256; j++) { sum += p[j]; }"
15810 " return sum;"
15811 "}"
15812 "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
15813 "for (var i = 0; i < 10; ++i) { pa_load(pixels); }"
15814 "just_ints = new Object();"
15815 "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
15816 "for (var i = 0; i < 10; ++i) {"
15817 " result = pa_load(just_ints);"
15818 "}"
15819 "result");
15820 CHECK_EQ(32640, result->Int32Value());
15821
15822 // Make sure that pixel array ICs recognize out-of-bound accesses.
15823 result = CompileRun("function pa_load(p, start) {"
15824 " var sum = 0;"
15825 " for (var j = start; j < 256; j++) { sum += p[j]; }"
15826 " return sum;"
15827 "}"
15828 "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
15829 "for (var i = 0; i < 10; ++i) { pa_load(pixels,0); }"
15830 "for (var i = 0; i < 10; ++i) {"
15831 " result = pa_load(pixels,-10);"
15832 "}"
15833 "result");
15834 CHECK_EQ(0, result->Int32Value());
15835
15836 // Make sure that generic ICs properly handles a pixel array.
15837 result = CompileRun("function pa_load(p) {"
15838 " var sum = 0;"
15839 " for (var j = 0; j < 256; j++) { sum += p[j]; }"
15840 " return sum;"
15841 "}"
15842 "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
15843 "just_ints = new Object();"
15844 "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
15845 "for (var i = 0; i < 10; ++i) { pa_load(just_ints); }"
15846 "for (var i = 0; i < 10; ++i) {"
15847 " result = pa_load(pixels);"
15848 "}"
15849 "result");
15850 CHECK_EQ(32640, result->Int32Value());
15851
15852 // Make sure that generic load ICs recognize out-of-bound accesses in
15853 // pixel arrays.
15854 result = CompileRun("function pa_load(p, start) {"
15855 " var sum = 0;"
15856 " for (var j = start; j < 256; j++) { sum += p[j]; }"
15857 " return sum;"
15858 "}"
15859 "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
15860 "just_ints = new Object();"
15861 "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
15862 "for (var i = 0; i < 10; ++i) { pa_load(just_ints,0); }"
15863 "for (var i = 0; i < 10; ++i) { pa_load(pixels,0); }"
15864 "for (var i = 0; i < 10; ++i) {"
15865 " result = pa_load(pixels,-10);"
15866 "}"
15867 "result");
15868 CHECK_EQ(0, result->Int32Value());
15869
15870 // Make sure that generic ICs properly handles other types than pixel
15871 // arrays (that the inlined fast pixel array test leaves the right information
15872 // in the right registers).
15873 result = CompileRun("function pa_load(p) {"
15874 " var sum = 0;"
15875 " for (var j = 0; j < 256; j++) { sum += p[j]; }"
15876 " return sum;"
15877 "}"
15878 "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
15879 "just_ints = new Object();"
15880 "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
15881 "for (var i = 0; i < 10; ++i) { pa_load(just_ints); }"
15882 "for (var i = 0; i < 10; ++i) { pa_load(pixels); }"
15883 "sparse_array = new Object();"
15884 "for (var i = 0; i < 256; ++i) { sparse_array[i] = i; }"
15885 "sparse_array[1000000] = 3;"
15886 "for (var i = 0; i < 10; ++i) {"
15887 " result = pa_load(sparse_array);"
15888 "}"
15889 "result");
15890 CHECK_EQ(32640, result->Int32Value());
15891
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +000015892 // Make sure that pixel array store ICs clamp values correctly.
15893 result = CompileRun("function pa_store(p) {"
15894 " for (var j = 0; j < 256; j++) { p[j] = j * 2; }"
15895 "}"
15896 "pa_store(pixels);"
15897 "var sum = 0;"
15898 "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
15899 "sum");
15900 CHECK_EQ(48896, result->Int32Value());
15901
15902 // Make sure that pixel array stores correctly handle accesses outside
15903 // of the pixel array..
15904 result = CompileRun("function pa_store(p,start) {"
15905 " for (var j = 0; j < 256; j++) {"
15906 " p[j+start] = j * 2;"
15907 " }"
15908 "}"
15909 "pa_store(pixels,0);"
15910 "pa_store(pixels,-128);"
15911 "var sum = 0;"
15912 "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
15913 "sum");
15914 CHECK_EQ(65280, result->Int32Value());
15915
15916 // Make sure that the generic store stub correctly handle accesses outside
15917 // of the pixel array..
15918 result = CompileRun("function pa_store(p,start) {"
15919 " for (var j = 0; j < 256; j++) {"
15920 " p[j+start] = j * 2;"
15921 " }"
15922 "}"
15923 "pa_store(pixels,0);"
15924 "just_ints = new Object();"
15925 "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
15926 "pa_store(just_ints, 0);"
15927 "pa_store(pixels,-128);"
15928 "var sum = 0;"
15929 "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
15930 "sum");
15931 CHECK_EQ(65280, result->Int32Value());
15932
15933 // Make sure that the generic keyed store stub clamps pixel array values
15934 // correctly.
15935 result = CompileRun("function pa_store(p) {"
15936 " for (var j = 0; j < 256; j++) { p[j] = j * 2; }"
15937 "}"
15938 "pa_store(pixels);"
15939 "just_ints = new Object();"
15940 "pa_store(just_ints);"
15941 "pa_store(pixels);"
15942 "var sum = 0;"
15943 "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
15944 "sum");
15945 CHECK_EQ(48896, result->Int32Value());
15946
15947 // Make sure that pixel array loads are optimized by crankshaft.
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000015948 result = CompileRun("function pa_load(p) {"
15949 " var sum = 0;"
15950 " for (var i=0; i<256; ++i) {"
15951 " sum += p[i];"
15952 " }"
15953 " return sum; "
15954 "}"
15955 "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000015956 "for (var i = 0; i < 5000; ++i) {"
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000015957 " result = pa_load(pixels);"
15958 "}"
15959 "result");
15960 CHECK_EQ(32640, result->Int32Value());
15961
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000015962 // Make sure that pixel array stores are optimized by crankshaft.
15963 result = CompileRun("function pa_init(p) {"
15964 "for (var i = 0; i < 256; ++i) { p[i] = i; }"
15965 "}"
15966 "function pa_load(p) {"
15967 " var sum = 0;"
15968 " for (var i=0; i<256; ++i) {"
15969 " sum += p[i];"
15970 " }"
15971 " return sum; "
15972 "}"
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000015973 "for (var i = 0; i < 5000; ++i) {"
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000015974 " pa_init(pixels);"
15975 "}"
15976 "result = pa_load(pixels);"
15977 "result");
15978 CHECK_EQ(32640, result->Int32Value());
15979
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015980 free(pixel_data);
15981}
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000015982
ager@chromium.org96c75b52009-08-26 09:13:16 +000015983
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000015984THREADED_TEST(PixelArrayInfo) {
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000015985 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015986 v8::HandleScope scope(context->GetIsolate());
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000015987 for (int size = 0; size < 100; size += 10) {
15988 uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(size));
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015989 v8::Handle<v8::Object> obj = v8::Object::New(context->GetIsolate());
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000015990 obj->SetIndexedPropertiesToPixelData(pixel_data, size);
15991 CHECK(obj->HasIndexedPropertiesInPixelData());
15992 CHECK_EQ(pixel_data, obj->GetIndexedPropertiesPixelData());
15993 CHECK_EQ(size, obj->GetIndexedPropertiesPixelDataLength());
15994 free(pixel_data);
15995 }
15996}
15997
15998
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015999static void NotHandledIndexedPropertyGetter(
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000016000 uint32_t index,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000016001 const v8::PropertyCallbackInfo<v8::Value>& info) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000016002 ApiTestFuzzer::Fuzz();
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000016003}
16004
16005
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000016006static void NotHandledIndexedPropertySetter(
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000016007 uint32_t index,
16008 Local<Value> value,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000016009 const v8::PropertyCallbackInfo<v8::Value>& info) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000016010 ApiTestFuzzer::Fuzz();
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000016011}
16012
16013
16014THREADED_TEST(PixelArrayWithInterceptor) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000016015 LocalContext context;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000016016 i::Factory* factory = CcTest::i_isolate()->factory();
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000016017 v8::Isolate* isolate = context->GetIsolate();
16018 v8::HandleScope scope(isolate);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000016019 const int kElementCount = 260;
16020 uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(kElementCount));
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016021 i::Handle<i::ExternalUint8ClampedArray> pixels =
16022 i::Handle<i::ExternalUint8ClampedArray>::cast(
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000016023 factory->NewExternalArray(kElementCount,
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016024 v8::kExternalUint8ClampedArray,
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000016025 pixel_data));
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000016026 for (int i = 0; i < kElementCount; i++) {
16027 pixels->set(i, i % 256);
16028 }
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000016029 v8::Handle<v8::ObjectTemplate> templ =
16030 v8::ObjectTemplate::New(context->GetIsolate());
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000016031 templ->SetIndexedPropertyHandler(NotHandledIndexedPropertyGetter,
16032 NotHandledIndexedPropertySetter);
16033 v8::Handle<v8::Object> obj = templ->NewInstance();
16034 obj->SetIndexedPropertiesToPixelData(pixel_data, kElementCount);
16035 context->Global()->Set(v8_str("pixels"), obj);
16036 v8::Handle<v8::Value> result = CompileRun("pixels[1]");
16037 CHECK_EQ(1, result->Int32Value());
16038 result = CompileRun("var sum = 0;"
16039 "for (var i = 0; i < 8; i++) {"
16040 " sum += pixels[i] = pixels[i] = -i;"
16041 "}"
16042 "sum;");
16043 CHECK_EQ(-28, result->Int32Value());
16044 result = CompileRun("pixels.hasOwnProperty('1')");
16045 CHECK(result->BooleanValue());
16046 free(pixel_data);
16047}
16048
16049
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016050static int ExternalArrayElementSize(v8::ExternalArrayType array_type) {
16051 switch (array_type) {
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016052 case v8::kExternalInt8Array:
16053 case v8::kExternalUint8Array:
16054 case v8::kExternalUint8ClampedArray:
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016055 return 1;
16056 break;
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016057 case v8::kExternalInt16Array:
16058 case v8::kExternalUint16Array:
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016059 return 2;
16060 break;
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016061 case v8::kExternalInt32Array:
16062 case v8::kExternalUint32Array:
16063 case v8::kExternalFloat32Array:
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016064 return 4;
16065 break;
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016066 case v8::kExternalFloat64Array:
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +000016067 return 8;
16068 break;
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016069 default:
16070 UNREACHABLE();
16071 return -1;
16072 }
16073 UNREACHABLE();
16074 return -1;
16075}
16076
16077
ager@chromium.org3811b432009-10-28 14:53:37 +000016078template <class ExternalArrayClass, class ElementType>
danno@chromium.orgf005df62013-04-30 16:36:45 +000016079static void ObjectWithExternalArrayTestHelper(
16080 Handle<Context> context,
16081 v8::Handle<Object> obj,
16082 int element_count,
16083 v8::ExternalArrayType array_type,
16084 int64_t low, int64_t high) {
ager@chromium.org3811b432009-10-28 14:53:37 +000016085 i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000016086 i::Isolate* isolate = jsobj->GetIsolate();
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016087 obj->Set(v8_str("field"),
16088 v8::Int32::New(reinterpret_cast<v8::Isolate*>(isolate), 1503));
ager@chromium.org3811b432009-10-28 14:53:37 +000016089 context->Global()->Set(v8_str("ext_array"), obj);
16090 v8::Handle<v8::Value> result = CompileRun("ext_array.field");
16091 CHECK_EQ(1503, result->Int32Value());
16092 result = CompileRun("ext_array[1]");
16093 CHECK_EQ(1, result->Int32Value());
16094
ager@chromium.org3811b432009-10-28 14:53:37 +000016095 // Check assigned smis
16096 result = CompileRun("for (var i = 0; i < 8; i++) {"
16097 " ext_array[i] = i;"
16098 "}"
16099 "var sum = 0;"
16100 "for (var i = 0; i < 8; i++) {"
16101 " sum += ext_array[i];"
16102 "}"
16103 "sum;");
machenbach@chromium.org5c88bc32014-01-17 08:10:36 +000016104
ager@chromium.org3811b432009-10-28 14:53:37 +000016105 CHECK_EQ(28, result->Int32Value());
machenbach@chromium.org5c88bc32014-01-17 08:10:36 +000016106 // Check pass through of assigned smis
16107 result = CompileRun("var sum = 0;"
16108 "for (var i = 0; i < 8; i++) {"
16109 " sum += ext_array[i] = ext_array[i] = -i;"
16110 "}"
16111 "sum;");
16112 CHECK_EQ(-28, result->Int32Value());
16113
ager@chromium.org3811b432009-10-28 14:53:37 +000016114
16115 // Check assigned smis in reverse order
16116 result = CompileRun("for (var i = 8; --i >= 0; ) {"
16117 " ext_array[i] = i;"
16118 "}"
16119 "var sum = 0;"
16120 "for (var i = 0; i < 8; i++) {"
16121 " sum += ext_array[i];"
16122 "}"
16123 "sum;");
16124 CHECK_EQ(28, result->Int32Value());
16125
16126 // Check pass through of assigned HeapNumbers
16127 result = CompileRun("var sum = 0;"
16128 "for (var i = 0; i < 16; i+=2) {"
16129 " sum += ext_array[i] = ext_array[i] = (-i * 0.5);"
16130 "}"
16131 "sum;");
16132 CHECK_EQ(-28, result->Int32Value());
16133
16134 // Check assigned HeapNumbers
16135 result = CompileRun("for (var i = 0; i < 16; i+=2) {"
16136 " ext_array[i] = (i * 0.5);"
16137 "}"
16138 "var sum = 0;"
16139 "for (var i = 0; i < 16; i+=2) {"
16140 " sum += ext_array[i];"
16141 "}"
16142 "sum;");
16143 CHECK_EQ(28, result->Int32Value());
16144
16145 // Check assigned HeapNumbers in reverse order
16146 result = CompileRun("for (var i = 14; i >= 0; i-=2) {"
16147 " ext_array[i] = (i * 0.5);"
16148 "}"
16149 "var sum = 0;"
16150 "for (var i = 0; i < 16; i+=2) {"
16151 " sum += ext_array[i];"
16152 "}"
16153 "sum;");
16154 CHECK_EQ(28, result->Int32Value());
16155
16156 i::ScopedVector<char> test_buf(1024);
16157
16158 // Check legal boundary conditions.
16159 // The repeated loads and stores ensure the ICs are exercised.
16160 const char* boundary_program =
16161 "var res = 0;"
16162 "for (var i = 0; i < 16; i++) {"
16163 " ext_array[i] = %lld;"
16164 " if (i > 8) {"
16165 " res = ext_array[i];"
16166 " }"
16167 "}"
16168 "res;";
16169 i::OS::SNPrintF(test_buf,
16170 boundary_program,
16171 low);
16172 result = CompileRun(test_buf.start());
16173 CHECK_EQ(low, result->IntegerValue());
16174
16175 i::OS::SNPrintF(test_buf,
16176 boundary_program,
16177 high);
16178 result = CompileRun(test_buf.start());
16179 CHECK_EQ(high, result->IntegerValue());
16180
16181 // Check misprediction of type in IC.
16182 result = CompileRun("var tmp_array = ext_array;"
16183 "var sum = 0;"
16184 "for (var i = 0; i < 8; i++) {"
16185 " tmp_array[i] = i;"
16186 " sum += tmp_array[i];"
16187 " if (i == 4) {"
16188 " tmp_array = {};"
16189 " }"
16190 "}"
16191 "sum;");
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000016192 // Force GC to trigger verification.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000016193 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org3811b432009-10-28 14:53:37 +000016194 CHECK_EQ(28, result->Int32Value());
16195
16196 // Make sure out-of-range loads do not throw.
16197 i::OS::SNPrintF(test_buf,
16198 "var caught_exception = false;"
16199 "try {"
16200 " ext_array[%d];"
16201 "} catch (e) {"
16202 " caught_exception = true;"
16203 "}"
16204 "caught_exception;",
danno@chromium.orgf005df62013-04-30 16:36:45 +000016205 element_count);
ager@chromium.org3811b432009-10-28 14:53:37 +000016206 result = CompileRun(test_buf.start());
16207 CHECK_EQ(false, result->BooleanValue());
16208
16209 // Make sure out-of-range stores do not throw.
16210 i::OS::SNPrintF(test_buf,
16211 "var caught_exception = false;"
16212 "try {"
16213 " ext_array[%d] = 1;"
16214 "} catch (e) {"
16215 " caught_exception = true;"
16216 "}"
16217 "caught_exception;",
danno@chromium.orgf005df62013-04-30 16:36:45 +000016218 element_count);
ager@chromium.org3811b432009-10-28 14:53:37 +000016219 result = CompileRun(test_buf.start());
16220 CHECK_EQ(false, result->BooleanValue());
16221
16222 // Check other boundary conditions, values and operations.
16223 result = CompileRun("for (var i = 0; i < 8; i++) {"
16224 " ext_array[7] = undefined;"
16225 "}"
16226 "ext_array[7];");
16227 CHECK_EQ(0, result->Int32Value());
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016228 if (array_type == v8::kExternalFloat64Array ||
16229 array_type == v8::kExternalFloat32Array) {
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000016230 CHECK_EQ(static_cast<int>(i::OS::nan_value()),
16231 static_cast<int>(
16232 jsobj->GetElement(isolate, 7)->ToObjectChecked()->Number()));
yangguo@chromium.org56454712012-02-16 15:33:53 +000016233 } else {
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000016234 CheckElementValue(isolate, 0, jsobj, 7);
yangguo@chromium.org56454712012-02-16 15:33:53 +000016235 }
ager@chromium.org3811b432009-10-28 14:53:37 +000016236
16237 result = CompileRun("for (var i = 0; i < 8; i++) {"
16238 " ext_array[6] = '2.3';"
16239 "}"
16240 "ext_array[6];");
16241 CHECK_EQ(2, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000016242 CHECK_EQ(2,
16243 static_cast<int>(
16244 jsobj->GetElement(isolate, 6)->ToObjectChecked()->Number()));
ager@chromium.org3811b432009-10-28 14:53:37 +000016245
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016246 if (array_type != v8::kExternalFloat32Array &&
16247 array_type != v8::kExternalFloat64Array) {
ager@chromium.org3811b432009-10-28 14:53:37 +000016248 // Though the specification doesn't state it, be explicit about
16249 // converting NaNs and +/-Infinity to zero.
16250 result = CompileRun("for (var i = 0; i < 8; i++) {"
16251 " ext_array[i] = 5;"
16252 "}"
16253 "for (var i = 0; i < 8; i++) {"
16254 " ext_array[i] = NaN;"
16255 "}"
16256 "ext_array[5];");
16257 CHECK_EQ(0, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000016258 CheckElementValue(isolate, 0, jsobj, 5);
ager@chromium.org3811b432009-10-28 14:53:37 +000016259
16260 result = CompileRun("for (var i = 0; i < 8; i++) {"
16261 " ext_array[i] = 5;"
16262 "}"
16263 "for (var i = 0; i < 8; i++) {"
16264 " ext_array[i] = Infinity;"
16265 "}"
16266 "ext_array[5];");
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000016267 int expected_value =
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016268 (array_type == v8::kExternalUint8ClampedArray) ? 255 : 0;
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000016269 CHECK_EQ(expected_value, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000016270 CheckElementValue(isolate, expected_value, jsobj, 5);
ager@chromium.org3811b432009-10-28 14:53:37 +000016271
16272 result = CompileRun("for (var i = 0; i < 8; i++) {"
16273 " ext_array[i] = 5;"
16274 "}"
16275 "for (var i = 0; i < 8; i++) {"
16276 " ext_array[i] = -Infinity;"
16277 "}"
16278 "ext_array[5];");
16279 CHECK_EQ(0, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000016280 CheckElementValue(isolate, 0, jsobj, 5);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +000016281
16282 // Check truncation behavior of integral arrays.
16283 const char* unsigned_data =
16284 "var source_data = [0.6, 10.6];"
16285 "var expected_results = [0, 10];";
16286 const char* signed_data =
16287 "var source_data = [0.6, 10.6, -0.6, -10.6];"
16288 "var expected_results = [0, 10, 0, -10];";
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000016289 const char* pixel_data =
16290 "var source_data = [0.6, 10.6];"
16291 "var expected_results = [1, 11];";
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +000016292 bool is_unsigned =
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016293 (array_type == v8::kExternalUint8Array ||
16294 array_type == v8::kExternalUint16Array ||
16295 array_type == v8::kExternalUint32Array);
16296 bool is_pixel_data = array_type == v8::kExternalUint8ClampedArray;
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +000016297
16298 i::OS::SNPrintF(test_buf,
16299 "%s"
16300 "var all_passed = true;"
16301 "for (var i = 0; i < source_data.length; i++) {"
16302 " for (var j = 0; j < 8; j++) {"
16303 " ext_array[j] = source_data[i];"
16304 " }"
16305 " all_passed = all_passed &&"
16306 " (ext_array[5] == expected_results[i]);"
16307 "}"
16308 "all_passed;",
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000016309 (is_unsigned ?
16310 unsigned_data :
16311 (is_pixel_data ? pixel_data : signed_data)));
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +000016312 result = CompileRun(test_buf.start());
16313 CHECK_EQ(true, result->BooleanValue());
ager@chromium.org3811b432009-10-28 14:53:37 +000016314 }
16315
danno@chromium.orgf005df62013-04-30 16:36:45 +000016316 i::Handle<ExternalArrayClass> array(
16317 ExternalArrayClass::cast(jsobj->elements()));
16318 for (int i = 0; i < element_count; i++) {
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000016319 array->set(i, static_cast<ElementType>(i));
16320 }
danno@chromium.orgf005df62013-04-30 16:36:45 +000016321
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000016322 // Test complex assignments
16323 result = CompileRun("function ee_op_test_complex_func(sum) {"
16324 " for (var i = 0; i < 40; ++i) {"
16325 " sum += (ext_array[i] += 1);"
16326 " sum += (ext_array[i] -= 1);"
16327 " } "
16328 " return sum;"
16329 "}"
16330 "sum=0;"
16331 "for (var i=0;i<10000;++i) {"
16332 " sum=ee_op_test_complex_func(sum);"
16333 "}"
16334 "sum;");
16335 CHECK_EQ(16000000, result->Int32Value());
16336
16337 // Test count operations
16338 result = CompileRun("function ee_op_test_count_func(sum) {"
16339 " for (var i = 0; i < 40; ++i) {"
16340 " sum += (++ext_array[i]);"
16341 " sum += (--ext_array[i]);"
16342 " } "
16343 " return sum;"
16344 "}"
16345 "sum=0;"
16346 "for (var i=0;i<10000;++i) {"
16347 " sum=ee_op_test_count_func(sum);"
16348 "}"
16349 "sum;");
16350 CHECK_EQ(16000000, result->Int32Value());
16351
ager@chromium.org3811b432009-10-28 14:53:37 +000016352 result = CompileRun("ext_array[3] = 33;"
16353 "delete ext_array[3];"
16354 "ext_array[3];");
16355 CHECK_EQ(33, result->Int32Value());
16356
16357 result = CompileRun("ext_array[0] = 10; ext_array[1] = 11;"
16358 "ext_array[2] = 12; ext_array[3] = 13;"
16359 "ext_array.__defineGetter__('2',"
16360 "function() { return 120; });"
16361 "ext_array[2];");
16362 CHECK_EQ(12, result->Int32Value());
16363
16364 result = CompileRun("var js_array = new Array(40);"
16365 "js_array[0] = 77;"
16366 "js_array;");
16367 CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
16368
16369 result = CompileRun("ext_array[1] = 23;"
16370 "ext_array.__proto__ = [];"
16371 "js_array.__proto__ = ext_array;"
16372 "js_array.concat(ext_array);");
16373 CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
16374 CHECK_EQ(23, v8::Object::Cast(*result)->Get(v8_str("1"))->Int32Value());
16375
16376 result = CompileRun("ext_array[1] = 23;");
16377 CHECK_EQ(23, result->Int32Value());
danno@chromium.orgf005df62013-04-30 16:36:45 +000016378}
16379
16380
machenbach@chromium.org5c88bc32014-01-17 08:10:36 +000016381template <class FixedTypedArrayClass,
16382 i::ElementsKind elements_kind,
16383 class ElementType>
16384static void FixedTypedArrayTestHelper(
16385 v8::ExternalArrayType array_type,
16386 ElementType low,
16387 ElementType high) {
16388 i::FLAG_allow_natives_syntax = true;
16389 LocalContext context;
16390 i::Isolate* isolate = CcTest::i_isolate();
16391 i::Factory* factory = isolate->factory();
16392 v8::HandleScope scope(context->GetIsolate());
16393 const int kElementCount = 260;
16394 i::Handle<FixedTypedArrayClass> fixed_array =
16395 i::Handle<FixedTypedArrayClass>::cast(
16396 factory->NewFixedTypedArray(kElementCount, array_type));
16397 CHECK_EQ(FixedTypedArrayClass::kInstanceType,
16398 fixed_array->map()->instance_type());
16399 CHECK_EQ(kElementCount, fixed_array->length());
16400 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
16401 for (int i = 0; i < kElementCount; i++) {
16402 fixed_array->set(i, static_cast<ElementType>(i));
16403 }
16404 // Force GC to trigger verification.
16405 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
16406 for (int i = 0; i < kElementCount; i++) {
16407 CHECK_EQ(static_cast<int64_t>(static_cast<ElementType>(i)),
16408 static_cast<int64_t>(fixed_array->get_scalar(i)));
16409 }
16410 v8::Handle<v8::Object> obj = v8::Object::New(CcTest::isolate());
16411 i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
16412 i::Handle<i::Map> fixed_array_map =
16413 isolate->factory()->GetElementsTransitionMap(jsobj, elements_kind);
16414 jsobj->set_map(*fixed_array_map);
16415 jsobj->set_elements(*fixed_array);
16416
16417 ObjectWithExternalArrayTestHelper<FixedTypedArrayClass, ElementType>(
16418 context.local(), obj, kElementCount, array_type,
16419 static_cast<int64_t>(low),
16420 static_cast<int64_t>(high));
16421}
16422
16423
16424THREADED_TEST(FixedUint8Array) {
16425 FixedTypedArrayTestHelper<i::FixedUint8Array, i::UINT8_ELEMENTS, uint8_t>(
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016426 v8::kExternalUint8Array,
machenbach@chromium.org5c88bc32014-01-17 08:10:36 +000016427 0x0, 0xFF);
16428}
16429
16430
16431THREADED_TEST(FixedUint8ClampedArray) {
16432 FixedTypedArrayTestHelper<i::FixedUint8ClampedArray,
16433 i::UINT8_CLAMPED_ELEMENTS, uint8_t>(
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016434 v8::kExternalUint8ClampedArray,
machenbach@chromium.org5c88bc32014-01-17 08:10:36 +000016435 0x0, 0xFF);
16436}
16437
16438
16439THREADED_TEST(FixedInt8Array) {
16440 FixedTypedArrayTestHelper<i::FixedInt8Array, i::INT8_ELEMENTS, int8_t>(
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016441 v8::kExternalInt8Array,
machenbach@chromium.org5c88bc32014-01-17 08:10:36 +000016442 -0x80, 0x7F);
16443}
16444
16445
16446THREADED_TEST(FixedUint16Array) {
16447 FixedTypedArrayTestHelper<i::FixedUint16Array, i::UINT16_ELEMENTS, uint16_t>(
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016448 v8::kExternalUint16Array,
machenbach@chromium.org5c88bc32014-01-17 08:10:36 +000016449 0x0, 0xFFFF);
16450}
16451
16452
16453THREADED_TEST(FixedInt16Array) {
16454 FixedTypedArrayTestHelper<i::FixedInt16Array, i::INT16_ELEMENTS, int16_t>(
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016455 v8::kExternalInt16Array,
machenbach@chromium.org5c88bc32014-01-17 08:10:36 +000016456 -0x8000, 0x7FFF);
16457}
16458
16459
16460THREADED_TEST(FixedUint32Array) {
16461 FixedTypedArrayTestHelper<i::FixedUint32Array, i::UINT32_ELEMENTS, uint32_t>(
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016462 v8::kExternalUint32Array,
machenbach@chromium.org5c88bc32014-01-17 08:10:36 +000016463 0x0, UINT_MAX);
16464}
16465
16466
16467THREADED_TEST(FixedInt32Array) {
16468 FixedTypedArrayTestHelper<i::FixedInt32Array, i::INT32_ELEMENTS, int32_t>(
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016469 v8::kExternalInt32Array,
machenbach@chromium.org5c88bc32014-01-17 08:10:36 +000016470 INT_MIN, INT_MAX);
16471}
16472
16473
16474THREADED_TEST(FixedFloat32Array) {
16475 FixedTypedArrayTestHelper<i::FixedFloat32Array, i::FLOAT32_ELEMENTS, float>(
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016476 v8::kExternalFloat32Array,
machenbach@chromium.org5c88bc32014-01-17 08:10:36 +000016477 -500, 500);
16478}
16479
16480
16481THREADED_TEST(FixedFloat64Array) {
16482 FixedTypedArrayTestHelper<i::FixedFloat64Array, i::FLOAT64_ELEMENTS, float>(
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016483 v8::kExternalFloat64Array,
machenbach@chromium.org5c88bc32014-01-17 08:10:36 +000016484 -500, 500);
16485}
16486
16487
danno@chromium.orgf005df62013-04-30 16:36:45 +000016488template <class ExternalArrayClass, class ElementType>
16489static void ExternalArrayTestHelper(v8::ExternalArrayType array_type,
16490 int64_t low,
16491 int64_t high) {
16492 LocalContext context;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000016493 i::Isolate* isolate = CcTest::i_isolate();
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000016494 i::Factory* factory = isolate->factory();
danno@chromium.orgf005df62013-04-30 16:36:45 +000016495 v8::HandleScope scope(context->GetIsolate());
16496 const int kElementCount = 40;
16497 int element_size = ExternalArrayElementSize(array_type);
16498 ElementType* array_data =
16499 static_cast<ElementType*>(malloc(kElementCount * element_size));
16500 i::Handle<ExternalArrayClass> array =
16501 i::Handle<ExternalArrayClass>::cast(
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000016502 factory->NewExternalArray(kElementCount, array_type, array_data));
danno@chromium.orgf005df62013-04-30 16:36:45 +000016503 // Force GC to trigger verification.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000016504 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
danno@chromium.orgf005df62013-04-30 16:36:45 +000016505 for (int i = 0; i < kElementCount; i++) {
16506 array->set(i, static_cast<ElementType>(i));
16507 }
16508 // Force GC to trigger verification.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000016509 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
danno@chromium.orgf005df62013-04-30 16:36:45 +000016510 for (int i = 0; i < kElementCount; i++) {
16511 CHECK_EQ(static_cast<int64_t>(i),
16512 static_cast<int64_t>(array->get_scalar(i)));
16513 CHECK_EQ(static_cast<int64_t>(i), static_cast<int64_t>(array_data[i]));
16514 }
16515
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016516 v8::Handle<v8::Object> obj = v8::Object::New(context->GetIsolate());
danno@chromium.orgf005df62013-04-30 16:36:45 +000016517 i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
16518 // Set the elements to be the external array.
16519 obj->SetIndexedPropertiesToExternalArrayData(array_data,
16520 array_type,
16521 kElementCount);
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000016522 CHECK_EQ(1,
16523 static_cast<int>(
16524 jsobj->GetElement(isolate, 1)->ToObjectChecked()->Number()));
danno@chromium.orgf005df62013-04-30 16:36:45 +000016525
16526 ObjectWithExternalArrayTestHelper<ExternalArrayClass, ElementType>(
16527 context.local(), obj, kElementCount, array_type, low, high);
16528
16529 v8::Handle<v8::Value> result;
ager@chromium.org3811b432009-10-28 14:53:37 +000016530
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +000016531 // Test more complex manipulations which cause eax to contain values
16532 // that won't be completely overwritten by loads from the arrays.
16533 // This catches bugs in the instructions used for the KeyedLoadIC
16534 // for byte and word types.
16535 {
16536 const int kXSize = 300;
16537 const int kYSize = 300;
16538 const int kLargeElementCount = kXSize * kYSize * 4;
16539 ElementType* large_array_data =
16540 static_cast<ElementType*>(malloc(kLargeElementCount * element_size));
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016541 v8::Handle<v8::Object> large_obj = v8::Object::New(context->GetIsolate());
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +000016542 // Set the elements to be the external array.
16543 large_obj->SetIndexedPropertiesToExternalArrayData(large_array_data,
16544 array_type,
16545 kLargeElementCount);
16546 context->Global()->Set(v8_str("large_array"), large_obj);
16547 // Initialize contents of a few rows.
16548 for (int x = 0; x < 300; x++) {
16549 int row = 0;
16550 int offset = row * 300 * 4;
16551 large_array_data[offset + 4 * x + 0] = (ElementType) 127;
16552 large_array_data[offset + 4 * x + 1] = (ElementType) 0;
16553 large_array_data[offset + 4 * x + 2] = (ElementType) 0;
16554 large_array_data[offset + 4 * x + 3] = (ElementType) 127;
16555 row = 150;
16556 offset = row * 300 * 4;
16557 large_array_data[offset + 4 * x + 0] = (ElementType) 127;
16558 large_array_data[offset + 4 * x + 1] = (ElementType) 0;
16559 large_array_data[offset + 4 * x + 2] = (ElementType) 0;
16560 large_array_data[offset + 4 * x + 3] = (ElementType) 127;
16561 row = 298;
16562 offset = row * 300 * 4;
16563 large_array_data[offset + 4 * x + 0] = (ElementType) 127;
16564 large_array_data[offset + 4 * x + 1] = (ElementType) 0;
16565 large_array_data[offset + 4 * x + 2] = (ElementType) 0;
16566 large_array_data[offset + 4 * x + 3] = (ElementType) 127;
16567 }
16568 // The goal of the code below is to make "offset" large enough
16569 // that the computation of the index (which goes into eax) has
16570 // high bits set which will not be overwritten by a byte or short
16571 // load.
16572 result = CompileRun("var failed = false;"
16573 "var offset = 0;"
16574 "for (var i = 0; i < 300; i++) {"
16575 " if (large_array[4 * i] != 127 ||"
16576 " large_array[4 * i + 1] != 0 ||"
16577 " large_array[4 * i + 2] != 0 ||"
16578 " large_array[4 * i + 3] != 127) {"
16579 " failed = true;"
16580 " }"
16581 "}"
16582 "offset = 150 * 300 * 4;"
16583 "for (var i = 0; i < 300; i++) {"
16584 " if (large_array[offset + 4 * i] != 127 ||"
16585 " large_array[offset + 4 * i + 1] != 0 ||"
16586 " large_array[offset + 4 * i + 2] != 0 ||"
16587 " large_array[offset + 4 * i + 3] != 127) {"
16588 " failed = true;"
16589 " }"
16590 "}"
16591 "offset = 298 * 300 * 4;"
16592 "for (var i = 0; i < 300; i++) {"
16593 " if (large_array[offset + 4 * i] != 127 ||"
16594 " large_array[offset + 4 * i + 1] != 0 ||"
16595 " large_array[offset + 4 * i + 2] != 0 ||"
16596 " large_array[offset + 4 * i + 3] != 127) {"
16597 " failed = true;"
16598 " }"
16599 "}"
16600 "!failed;");
16601 CHECK_EQ(true, result->BooleanValue());
16602 free(large_array_data);
16603 }
16604
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016605 // The "" property descriptor is overloaded to store information about
16606 // the external array. Ensure that setting and accessing the "" property
16607 // works (it should overwrite the information cached about the external
16608 // array in the DescriptorArray) in various situations.
16609 result = CompileRun("ext_array[''] = 23; ext_array['']");
16610 CHECK_EQ(23, result->Int32Value());
16611
16612 // Property "" set after the external array is associated with the object.
16613 {
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016614 v8::Handle<v8::Object> obj2 = v8::Object::New(context->GetIsolate());
16615 obj2->Set(v8_str("ee_test_field"),
16616 v8::Int32::New(context->GetIsolate(), 256));
16617 obj2->Set(v8_str(""), v8::Int32::New(context->GetIsolate(), 1503));
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016618 // Set the elements to be the external array.
16619 obj2->SetIndexedPropertiesToExternalArrayData(array_data,
16620 array_type,
16621 kElementCount);
16622 context->Global()->Set(v8_str("ext_array"), obj2);
16623 result = CompileRun("ext_array['']");
16624 CHECK_EQ(1503, result->Int32Value());
16625 }
16626
16627 // Property "" set after the external array is associated with the object.
16628 {
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016629 v8::Handle<v8::Object> obj2 = v8::Object::New(context->GetIsolate());
16630 obj2->Set(v8_str("ee_test_field_2"),
16631 v8::Int32::New(context->GetIsolate(), 256));
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016632 // Set the elements to be the external array.
16633 obj2->SetIndexedPropertiesToExternalArrayData(array_data,
16634 array_type,
16635 kElementCount);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016636 obj2->Set(v8_str(""), v8::Int32::New(context->GetIsolate(), 1503));
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016637 context->Global()->Set(v8_str("ext_array"), obj2);
16638 result = CompileRun("ext_array['']");
16639 CHECK_EQ(1503, result->Int32Value());
16640 }
16641
16642 // Should reuse the map from previous test.
16643 {
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016644 v8::Handle<v8::Object> obj2 = v8::Object::New(context->GetIsolate());
16645 obj2->Set(v8_str("ee_test_field_2"),
16646 v8::Int32::New(context->GetIsolate(), 256));
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016647 // Set the elements to be the external array. Should re-use the map
16648 // from previous test.
16649 obj2->SetIndexedPropertiesToExternalArrayData(array_data,
16650 array_type,
16651 kElementCount);
16652 context->Global()->Set(v8_str("ext_array"), obj2);
16653 result = CompileRun("ext_array['']");
16654 }
16655
16656 // Property "" is a constant function that shouldn't not be interfered with
16657 // when an external array is set.
16658 {
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016659 v8::Handle<v8::Object> obj2 = v8::Object::New(context->GetIsolate());
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016660 // Start
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016661 obj2->Set(v8_str("ee_test_field3"),
16662 v8::Int32::New(context->GetIsolate(), 256));
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016663
16664 // Add a constant function to an object.
16665 context->Global()->Set(v8_str("ext_array"), obj2);
16666 result = CompileRun("ext_array[''] = function() {return 1503;};"
16667 "ext_array['']();");
16668
16669 // Add an external array transition to the same map that
16670 // has the constant transition.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016671 v8::Handle<v8::Object> obj3 = v8::Object::New(context->GetIsolate());
16672 obj3->Set(v8_str("ee_test_field3"),
16673 v8::Int32::New(context->GetIsolate(), 256));
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016674 obj3->SetIndexedPropertiesToExternalArrayData(array_data,
16675 array_type,
16676 kElementCount);
16677 context->Global()->Set(v8_str("ext_array"), obj3);
16678 }
16679
16680 // If a external array transition is in the map, it should get clobbered
16681 // by a constant function.
16682 {
16683 // Add an external array transition.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016684 v8::Handle<v8::Object> obj3 = v8::Object::New(context->GetIsolate());
16685 obj3->Set(v8_str("ee_test_field4"),
16686 v8::Int32::New(context->GetIsolate(), 256));
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016687 obj3->SetIndexedPropertiesToExternalArrayData(array_data,
16688 array_type,
16689 kElementCount);
16690
16691 // Add a constant function to the same map that just got an external array
16692 // transition.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016693 v8::Handle<v8::Object> obj2 = v8::Object::New(context->GetIsolate());
16694 obj2->Set(v8_str("ee_test_field4"),
16695 v8::Int32::New(context->GetIsolate(), 256));
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016696 context->Global()->Set(v8_str("ext_array"), obj2);
16697 result = CompileRun("ext_array[''] = function() {return 1503;};"
16698 "ext_array['']();");
16699 }
16700
ager@chromium.org3811b432009-10-28 14:53:37 +000016701 free(array_data);
16702}
16703
16704
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016705THREADED_TEST(ExternalInt8Array) {
16706 ExternalArrayTestHelper<i::ExternalInt8Array, int8_t>(
16707 v8::kExternalInt8Array,
ager@chromium.org3811b432009-10-28 14:53:37 +000016708 -128,
16709 127);
16710}
16711
16712
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016713THREADED_TEST(ExternalUint8Array) {
16714 ExternalArrayTestHelper<i::ExternalUint8Array, uint8_t>(
16715 v8::kExternalUint8Array,
ager@chromium.org3811b432009-10-28 14:53:37 +000016716 0,
16717 255);
16718}
16719
16720
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016721THREADED_TEST(ExternalUint8ClampedArray) {
16722 ExternalArrayTestHelper<i::ExternalUint8ClampedArray, uint8_t>(
16723 v8::kExternalUint8ClampedArray,
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000016724 0,
16725 255);
16726}
16727
16728
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016729THREADED_TEST(ExternalInt16Array) {
16730 ExternalArrayTestHelper<i::ExternalInt16Array, int16_t>(
16731 v8::kExternalInt16Array,
ager@chromium.org3811b432009-10-28 14:53:37 +000016732 -32768,
16733 32767);
16734}
16735
16736
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016737THREADED_TEST(ExternalUint16Array) {
16738 ExternalArrayTestHelper<i::ExternalUint16Array, uint16_t>(
16739 v8::kExternalUint16Array,
ager@chromium.org3811b432009-10-28 14:53:37 +000016740 0,
16741 65535);
16742}
16743
16744
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016745THREADED_TEST(ExternalInt32Array) {
16746 ExternalArrayTestHelper<i::ExternalInt32Array, int32_t>(
16747 v8::kExternalInt32Array,
ager@chromium.org3811b432009-10-28 14:53:37 +000016748 INT_MIN, // -2147483648
16749 INT_MAX); // 2147483647
16750}
16751
16752
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016753THREADED_TEST(ExternalUint32Array) {
16754 ExternalArrayTestHelper<i::ExternalUint32Array, uint32_t>(
16755 v8::kExternalUint32Array,
ager@chromium.org3811b432009-10-28 14:53:37 +000016756 0,
16757 UINT_MAX); // 4294967295
16758}
16759
16760
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016761THREADED_TEST(ExternalFloat32Array) {
16762 ExternalArrayTestHelper<i::ExternalFloat32Array, float>(
16763 v8::kExternalFloat32Array,
ager@chromium.org3811b432009-10-28 14:53:37 +000016764 -500,
16765 500);
16766}
16767
16768
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016769THREADED_TEST(ExternalFloat64Array) {
16770 ExternalArrayTestHelper<i::ExternalFloat64Array, double>(
16771 v8::kExternalFloat64Array,
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +000016772 -500,
16773 500);
16774}
16775
16776
ager@chromium.org3811b432009-10-28 14:53:37 +000016777THREADED_TEST(ExternalArrays) {
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016778 TestExternalInt8Array();
16779 TestExternalUint8Array();
16780 TestExternalInt16Array();
16781 TestExternalUint16Array();
16782 TestExternalInt32Array();
16783 TestExternalUint32Array();
16784 TestExternalFloat32Array();
ager@chromium.org3811b432009-10-28 14:53:37 +000016785}
16786
16787
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016788void ExternalArrayInfoTestHelper(v8::ExternalArrayType array_type) {
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016789 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016790 v8::HandleScope scope(context->GetIsolate());
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016791 for (int size = 0; size < 100; size += 10) {
16792 int element_size = ExternalArrayElementSize(array_type);
16793 void* external_data = malloc(size * element_size);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016794 v8::Handle<v8::Object> obj = v8::Object::New(context->GetIsolate());
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016795 obj->SetIndexedPropertiesToExternalArrayData(
16796 external_data, array_type, size);
16797 CHECK(obj->HasIndexedPropertiesInExternalArrayData());
16798 CHECK_EQ(external_data, obj->GetIndexedPropertiesExternalArrayData());
16799 CHECK_EQ(array_type, obj->GetIndexedPropertiesExternalArrayDataType());
16800 CHECK_EQ(size, obj->GetIndexedPropertiesExternalArrayDataLength());
16801 free(external_data);
16802 }
16803}
16804
16805
16806THREADED_TEST(ExternalArrayInfo) {
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016807 ExternalArrayInfoTestHelper(v8::kExternalInt8Array);
16808 ExternalArrayInfoTestHelper(v8::kExternalUint8Array);
16809 ExternalArrayInfoTestHelper(v8::kExternalInt16Array);
16810 ExternalArrayInfoTestHelper(v8::kExternalUint16Array);
16811 ExternalArrayInfoTestHelper(v8::kExternalInt32Array);
16812 ExternalArrayInfoTestHelper(v8::kExternalUint32Array);
16813 ExternalArrayInfoTestHelper(v8::kExternalFloat32Array);
16814 ExternalArrayInfoTestHelper(v8::kExternalFloat64Array);
16815 ExternalArrayInfoTestHelper(v8::kExternalUint8ClampedArray);
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016816}
16817
16818
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016819void ExtArrayLimitsHelper(v8::Isolate* isolate,
16820 v8::ExternalArrayType array_type,
16821 int size) {
16822 v8::Handle<v8::Object> obj = v8::Object::New(isolate);
danno@chromium.org412fa512012-09-14 13:28:26 +000016823 v8::V8::SetFatalErrorHandler(StoringErrorCallback);
16824 last_location = last_message = NULL;
16825 obj->SetIndexedPropertiesToExternalArrayData(NULL, array_type, size);
16826 CHECK(!obj->HasIndexedPropertiesInExternalArrayData());
16827 CHECK_NE(NULL, last_location);
16828 CHECK_NE(NULL, last_message);
16829}
16830
16831
16832TEST(ExternalArrayLimits) {
danno@chromium.org412fa512012-09-14 13:28:26 +000016833 LocalContext context;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016834 v8::Isolate* isolate = context->GetIsolate();
16835 v8::HandleScope scope(isolate);
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016836 ExtArrayLimitsHelper(isolate, v8::kExternalInt8Array, 0x40000000);
16837 ExtArrayLimitsHelper(isolate, v8::kExternalInt8Array, 0xffffffff);
16838 ExtArrayLimitsHelper(isolate, v8::kExternalUint8Array, 0x40000000);
16839 ExtArrayLimitsHelper(isolate, v8::kExternalUint8Array, 0xffffffff);
16840 ExtArrayLimitsHelper(isolate, v8::kExternalInt16Array, 0x40000000);
16841 ExtArrayLimitsHelper(isolate, v8::kExternalInt16Array, 0xffffffff);
16842 ExtArrayLimitsHelper(isolate, v8::kExternalUint16Array, 0x40000000);
16843 ExtArrayLimitsHelper(isolate, v8::kExternalUint16Array, 0xffffffff);
16844 ExtArrayLimitsHelper(isolate, v8::kExternalInt32Array, 0x40000000);
16845 ExtArrayLimitsHelper(isolate, v8::kExternalInt32Array, 0xffffffff);
16846 ExtArrayLimitsHelper(isolate, v8::kExternalUint32Array, 0x40000000);
16847 ExtArrayLimitsHelper(isolate, v8::kExternalUint32Array, 0xffffffff);
16848 ExtArrayLimitsHelper(isolate, v8::kExternalFloat32Array, 0x40000000);
16849 ExtArrayLimitsHelper(isolate, v8::kExternalFloat32Array, 0xffffffff);
16850 ExtArrayLimitsHelper(isolate, v8::kExternalFloat64Array, 0x40000000);
16851 ExtArrayLimitsHelper(isolate, v8::kExternalFloat64Array, 0xffffffff);
16852 ExtArrayLimitsHelper(isolate, v8::kExternalUint8ClampedArray, 0x40000000);
16853 ExtArrayLimitsHelper(isolate, v8::kExternalUint8ClampedArray, 0xffffffff);
danno@chromium.org412fa512012-09-14 13:28:26 +000016854}
16855
16856
danno@chromium.orgf005df62013-04-30 16:36:45 +000016857template <typename ElementType, typename TypedArray,
16858 class ExternalArrayClass>
16859void TypedArrayTestHelper(v8::ExternalArrayType array_type,
16860 int64_t low, int64_t high) {
16861 const int kElementCount = 50;
danno@chromium.orgf005df62013-04-30 16:36:45 +000016862
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +000016863 i::ScopedVector<ElementType> backing_store(kElementCount+2);
16864
danno@chromium.orgf005df62013-04-30 16:36:45 +000016865 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(),
16871 (kElementCount + 2) * sizeof(ElementType));
danno@chromium.orgf005df62013-04-30 16:36:45 +000016872 Local<TypedArray> ta =
16873 TypedArray::New(ab, 2*sizeof(ElementType), kElementCount);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000016874 CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
danno@chromium.orgf005df62013-04-30 16:36:45 +000016875 CHECK_EQ(kElementCount, static_cast<int>(ta->Length()));
16876 CHECK_EQ(2*sizeof(ElementType), static_cast<int>(ta->ByteOffset()));
16877 CHECK_EQ(kElementCount*sizeof(ElementType),
16878 static_cast<int>(ta->ByteLength()));
16879 CHECK_EQ(ab, ta->Buffer());
16880
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +000016881 ElementType* data = backing_store.start() + 2;
danno@chromium.orgf005df62013-04-30 16:36:45 +000016882 for (int i = 0; i < kElementCount; i++) {
16883 data[i] = static_cast<ElementType>(i);
16884 }
16885
16886 ObjectWithExternalArrayTestHelper<ExternalArrayClass, ElementType>(
16887 env.local(), ta, kElementCount, array_type, low, high);
16888}
16889
16890
16891THREADED_TEST(Uint8Array) {
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016892 TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::ExternalUint8Array>(
16893 v8::kExternalUint8Array, 0, 0xFF);
danno@chromium.orgf005df62013-04-30 16:36:45 +000016894}
16895
16896
16897THREADED_TEST(Int8Array) {
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016898 TypedArrayTestHelper<int8_t, v8::Int8Array, i::ExternalInt8Array>(
16899 v8::kExternalInt8Array, -0x80, 0x7F);
danno@chromium.orgf005df62013-04-30 16:36:45 +000016900}
16901
16902
16903THREADED_TEST(Uint16Array) {
16904 TypedArrayTestHelper<uint16_t,
16905 v8::Uint16Array,
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016906 i::ExternalUint16Array>(
16907 v8::kExternalUint16Array, 0, 0xFFFF);
danno@chromium.orgf005df62013-04-30 16:36:45 +000016908}
16909
16910
16911THREADED_TEST(Int16Array) {
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016912 TypedArrayTestHelper<int16_t, v8::Int16Array, i::ExternalInt16Array>(
16913 v8::kExternalInt16Array, -0x8000, 0x7FFF);
danno@chromium.orgf005df62013-04-30 16:36:45 +000016914}
16915
16916
16917THREADED_TEST(Uint32Array) {
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016918 TypedArrayTestHelper<uint32_t, v8::Uint32Array, i::ExternalUint32Array>(
16919 v8::kExternalUint32Array, 0, UINT_MAX);
danno@chromium.orgf005df62013-04-30 16:36:45 +000016920}
16921
16922
16923THREADED_TEST(Int32Array) {
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016924 TypedArrayTestHelper<int32_t, v8::Int32Array, i::ExternalInt32Array>(
16925 v8::kExternalInt32Array, INT_MIN, INT_MAX);
danno@chromium.orgf005df62013-04-30 16:36:45 +000016926}
16927
16928
16929THREADED_TEST(Float32Array) {
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016930 TypedArrayTestHelper<float, v8::Float32Array, i::ExternalFloat32Array>(
16931 v8::kExternalFloat32Array, -500, 500);
danno@chromium.orgf005df62013-04-30 16:36:45 +000016932}
16933
16934
16935THREADED_TEST(Float64Array) {
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016936 TypedArrayTestHelper<double, v8::Float64Array, i::ExternalFloat64Array>(
16937 v8::kExternalFloat64Array, -500, 500);
danno@chromium.orgf005df62013-04-30 16:36:45 +000016938}
16939
16940
ulan@chromium.org57ff8812013-05-10 08:16:55 +000016941THREADED_TEST(Uint8ClampedArray) {
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016942 TypedArrayTestHelper<uint8_t,
16943 v8::Uint8ClampedArray, i::ExternalUint8ClampedArray>(
16944 v8::kExternalUint8ClampedArray, 0, 0xFF);
ulan@chromium.org57ff8812013-05-10 08:16:55 +000016945}
16946
16947
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000016948THREADED_TEST(DataView) {
16949 const int kSize = 50;
16950
16951 i::ScopedVector<uint8_t> backing_store(kSize+2);
16952
16953 LocalContext env;
16954 v8::Isolate* isolate = env->GetIsolate();
16955 v8::HandleScope handle_scope(isolate);
16956
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000016957 Local<v8::ArrayBuffer> ab =
16958 v8::ArrayBuffer::New(isolate, backing_store.start(), 2 + kSize);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000016959 Local<v8::DataView> dv =
16960 v8::DataView::New(ab, 2, kSize);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000016961 CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000016962 CHECK_EQ(2, static_cast<int>(dv->ByteOffset()));
16963 CHECK_EQ(kSize, static_cast<int>(dv->ByteLength()));
16964 CHECK_EQ(ab, dv->Buffer());
16965}
16966
16967
16968#define IS_ARRAY_BUFFER_VIEW_TEST(View) \
16969 THREADED_TEST(Is##View) { \
ulan@chromium.org57ff8812013-05-10 08:16:55 +000016970 LocalContext env; \
16971 v8::Isolate* isolate = env->GetIsolate(); \
16972 v8::HandleScope handle_scope(isolate); \
16973 \
16974 Handle<Value> result = CompileRun( \
16975 "var ab = new ArrayBuffer(128);" \
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000016976 "new " #View "(ab)"); \
16977 CHECK(result->IsArrayBufferView()); \
16978 CHECK(result->Is##View()); \
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000016979 CheckInternalFieldsAreZero<v8::ArrayBufferView>(result.As<v8::View>()); \
ulan@chromium.org57ff8812013-05-10 08:16:55 +000016980 }
16981
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000016982IS_ARRAY_BUFFER_VIEW_TEST(Uint8Array)
16983IS_ARRAY_BUFFER_VIEW_TEST(Int8Array)
16984IS_ARRAY_BUFFER_VIEW_TEST(Uint16Array)
16985IS_ARRAY_BUFFER_VIEW_TEST(Int16Array)
16986IS_ARRAY_BUFFER_VIEW_TEST(Uint32Array)
16987IS_ARRAY_BUFFER_VIEW_TEST(Int32Array)
16988IS_ARRAY_BUFFER_VIEW_TEST(Float32Array)
16989IS_ARRAY_BUFFER_VIEW_TEST(Float64Array)
16990IS_ARRAY_BUFFER_VIEW_TEST(Uint8ClampedArray)
16991IS_ARRAY_BUFFER_VIEW_TEST(DataView)
ulan@chromium.org57ff8812013-05-10 08:16:55 +000016992
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000016993#undef IS_ARRAY_BUFFER_VIEW_TEST
ulan@chromium.org57ff8812013-05-10 08:16:55 +000016994
16995
16996
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000016997THREADED_TEST(ScriptContextDependence) {
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000016998 LocalContext c1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016999 v8::HandleScope scope(c1->GetIsolate());
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000017000 const char *source = "foo";
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017001 v8::Handle<v8::Script> dep =
17002 v8::Script::Compile(v8::String::NewFromUtf8(c1->GetIsolate(), source));
17003 v8::Handle<v8::Script> indep =
17004 v8::Script::New(v8::String::NewFromUtf8(c1->GetIsolate(), source));
17005 c1->Global()->Set(v8::String::NewFromUtf8(c1->GetIsolate(), "foo"),
ulan@chromium.org0f13e742014-01-03 15:51:11 +000017006 v8::Integer::New(c1->GetIsolate(), 100));
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000017007 CHECK_EQ(dep->Run()->Int32Value(), 100);
17008 CHECK_EQ(indep->Run()->Int32Value(), 100);
17009 LocalContext c2;
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017010 c2->Global()->Set(v8::String::NewFromUtf8(c2->GetIsolate(), "foo"),
ulan@chromium.org0f13e742014-01-03 15:51:11 +000017011 v8::Integer::New(c2->GetIsolate(), 101));
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000017012 CHECK_EQ(dep->Run()->Int32Value(), 100);
17013 CHECK_EQ(indep->Run()->Int32Value(), 101);
17014}
17015
ager@chromium.org96c75b52009-08-26 09:13:16 +000017016
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000017017THREADED_TEST(StackTrace) {
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000017018 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017019 v8::HandleScope scope(context->GetIsolate());
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000017020 v8::TryCatch try_catch;
17021 const char *source = "function foo() { FAIL.FAIL; }; foo();";
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017022 v8::Handle<v8::String> src =
17023 v8::String::NewFromUtf8(context->GetIsolate(), source);
17024 v8::Handle<v8::String> origin =
17025 v8::String::NewFromUtf8(context->GetIsolate(), "stack-trace-test");
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000017026 v8::Script::New(src, origin)->Run();
17027 CHECK(try_catch.HasCaught());
17028 v8::String::Utf8Value stack(try_catch.StackTrace());
17029 CHECK(strstr(*stack, "at foo (stack-trace-test") != NULL);
17030}
ager@chromium.org96c75b52009-08-26 09:13:16 +000017031
17032
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017033// Checks that a StackFrame has certain expected values.
17034void checkStackFrame(const char* expected_script_name,
17035 const char* expected_func_name, int expected_line_number,
17036 int expected_column, bool is_eval, bool is_constructor,
17037 v8::Handle<v8::StackFrame> frame) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017038 v8::HandleScope scope(CcTest::isolate());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017039 v8::String::Utf8Value func_name(frame->GetFunctionName());
17040 v8::String::Utf8Value script_name(frame->GetScriptName());
17041 if (*script_name == NULL) {
17042 // The situation where there is no associated script, like for evals.
17043 CHECK(expected_script_name == NULL);
17044 } else {
17045 CHECK(strstr(*script_name, expected_script_name) != NULL);
17046 }
17047 CHECK(strstr(*func_name, expected_func_name) != NULL);
17048 CHECK_EQ(expected_line_number, frame->GetLineNumber());
17049 CHECK_EQ(expected_column, frame->GetColumn());
17050 CHECK_EQ(is_eval, frame->IsEval());
17051 CHECK_EQ(is_constructor, frame->IsConstructor());
17052}
17053
17054
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017055void AnalyzeStackInNativeCode(const v8::FunctionCallbackInfo<v8::Value>& args) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017056 v8::HandleScope scope(args.GetIsolate());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017057 const char* origin = "capture-stack-trace-test";
17058 const int kOverviewTest = 1;
17059 const int kDetailedTest = 2;
17060
17061 ASSERT(args.Length() == 1);
17062
17063 int testGroup = args[0]->Int32Value();
17064 if (testGroup == kOverviewTest) {
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017065 v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
17066 args.GetIsolate(), 10, v8::StackTrace::kOverview);
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017067 CHECK_EQ(4, stackTrace->GetFrameCount());
17068 checkStackFrame(origin, "bar", 2, 10, false, false,
17069 stackTrace->GetFrame(0));
17070 checkStackFrame(origin, "foo", 6, 3, false, false,
17071 stackTrace->GetFrame(1));
whesse@chromium.org030d38e2011-07-13 13:23:34 +000017072 // This is the source string inside the eval which has the call to foo.
17073 checkStackFrame(NULL, "", 1, 5, false, false,
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017074 stackTrace->GetFrame(2));
whesse@chromium.org030d38e2011-07-13 13:23:34 +000017075 // The last frame is an anonymous function which has the initial eval call.
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017076 checkStackFrame(origin, "", 8, 7, false, false,
17077 stackTrace->GetFrame(3));
17078
17079 CHECK(stackTrace->AsArray()->IsArray());
17080 } else if (testGroup == kDetailedTest) {
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017081 v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
17082 args.GetIsolate(), 10, v8::StackTrace::kDetailed);
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017083 CHECK_EQ(4, stackTrace->GetFrameCount());
17084 checkStackFrame(origin, "bat", 4, 22, false, false,
17085 stackTrace->GetFrame(0));
17086 checkStackFrame(origin, "baz", 8, 3, false, true,
17087 stackTrace->GetFrame(1));
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +000017088#ifdef ENABLE_DEBUGGER_SUPPORT
17089 bool is_eval = true;
17090#else // ENABLE_DEBUGGER_SUPPORT
17091 bool is_eval = false;
17092#endif // ENABLE_DEBUGGER_SUPPORT
17093
whesse@chromium.org030d38e2011-07-13 13:23:34 +000017094 // This is the source string inside the eval which has the call to baz.
17095 checkStackFrame(NULL, "", 1, 5, is_eval, false,
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017096 stackTrace->GetFrame(2));
whesse@chromium.org030d38e2011-07-13 13:23:34 +000017097 // The last frame is an anonymous function which has the initial eval call.
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017098 checkStackFrame(origin, "", 10, 1, false, false,
17099 stackTrace->GetFrame(3));
17100
17101 CHECK(stackTrace->AsArray()->IsArray());
17102 }
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017103}
17104
17105
17106// Tests the C++ StackTrace API.
kasperl@chromium.orga5551262010-12-07 12:49:48 +000017107// TODO(3074796): Reenable this as a THREADED_TEST once it passes.
17108// THREADED_TEST(CaptureStackTrace) {
17109TEST(CaptureStackTrace) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017110 v8::Isolate* isolate = CcTest::isolate();
17111 v8::HandleScope scope(isolate);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017112 v8::Handle<v8::String> origin =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017113 v8::String::NewFromUtf8(isolate, "capture-stack-trace-test");
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000017114 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017115 templ->Set(v8_str("AnalyzeStackInNativeCode"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017116 v8::FunctionTemplate::New(isolate, AnalyzeStackInNativeCode));
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017117 LocalContext context(0, templ);
17118
17119 // Test getting OVERVIEW information. Should ignore information that is not
17120 // script name, function name, line number, and column offset.
17121 const char *overview_source =
17122 "function bar() {\n"
17123 " var y; AnalyzeStackInNativeCode(1);\n"
17124 "}\n"
17125 "function foo() {\n"
17126 "\n"
17127 " bar();\n"
17128 "}\n"
17129 "var x;eval('new foo();');";
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017130 v8::Handle<v8::String> overview_src =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017131 v8::String::NewFromUtf8(isolate, overview_source);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000017132 v8::Handle<Value> overview_result(
17133 v8::Script::New(overview_src, origin)->Run());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000017134 CHECK(!overview_result.IsEmpty());
17135 CHECK(overview_result->IsObject());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017136
17137 // Test getting DETAILED information.
17138 const char *detailed_source =
17139 "function bat() {AnalyzeStackInNativeCode(2);\n"
17140 "}\n"
17141 "\n"
17142 "function baz() {\n"
17143 " bat();\n"
17144 "}\n"
17145 "eval('new baz();');";
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017146 v8::Handle<v8::String> detailed_src =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017147 v8::String::NewFromUtf8(isolate, detailed_source);
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017148 // Make the script using a non-zero line and column offset.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000017149 v8::Handle<v8::Integer> line_offset = v8::Integer::New(isolate, 3);
17150 v8::Handle<v8::Integer> column_offset = v8::Integer::New(isolate, 5);
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017151 v8::ScriptOrigin detailed_origin(origin, line_offset, column_offset);
17152 v8::Handle<v8::Script> detailed_script(
17153 v8::Script::New(detailed_src, &detailed_origin));
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000017154 v8::Handle<Value> detailed_result(detailed_script->Run());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000017155 CHECK(!detailed_result.IsEmpty());
17156 CHECK(detailed_result->IsObject());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017157}
17158
17159
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000017160static void StackTraceForUncaughtExceptionListener(
17161 v8::Handle<v8::Message> message,
17162 v8::Handle<Value>) {
17163 v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
17164 CHECK_EQ(2, stack_trace->GetFrameCount());
17165 checkStackFrame("origin", "foo", 2, 3, false, false,
17166 stack_trace->GetFrame(0));
17167 checkStackFrame("origin", "bar", 5, 3, false, false,
17168 stack_trace->GetFrame(1));
17169}
17170
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000017171
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000017172TEST(CaptureStackTraceForUncaughtException) {
17173 report_count = 0;
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000017174 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017175 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000017176 v8::V8::AddMessageListener(StackTraceForUncaughtExceptionListener);
17177 v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
17178
17179 Script::Compile(v8_str("function foo() {\n"
17180 " throw 1;\n"
17181 "};\n"
17182 "function bar() {\n"
17183 " foo();\n"
17184 "};"),
17185 v8_str("origin"))->Run();
17186 v8::Local<v8::Object> global = env->Global();
17187 Local<Value> trouble = global->Get(v8_str("bar"));
17188 CHECK(trouble->IsFunction());
17189 Function::Cast(*trouble)->Call(global, 0, NULL);
17190 v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
17191 v8::V8::RemoveMessageListeners(StackTraceForUncaughtExceptionListener);
17192}
17193
17194
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000017195TEST(CaptureStackTraceForUncaughtExceptionAndSetters) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000017196 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017197 v8::HandleScope scope(env->GetIsolate());
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000017198 v8::V8::SetCaptureStackTraceForUncaughtExceptions(true,
17199 1024,
17200 v8::StackTrace::kDetailed);
17201
17202 CompileRun(
17203 "var setters = ['column', 'lineNumber', 'scriptName',\n"
17204 " 'scriptNameOrSourceURL', 'functionName', 'isEval',\n"
17205 " 'isConstructor'];\n"
17206 "for (var i = 0; i < setters.length; i++) {\n"
17207 " var prop = setters[i];\n"
17208 " Object.prototype.__defineSetter__(prop, function() { throw prop; });\n"
17209 "}\n");
17210 CompileRun("throw 'exception';");
17211 v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
17212}
17213
17214
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000017215static void RethrowStackTraceHandler(v8::Handle<v8::Message> message,
17216 v8::Handle<v8::Value> data) {
17217 // Use the frame where JavaScript is called from.
17218 v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
17219 CHECK(!stack_trace.IsEmpty());
17220 int frame_count = stack_trace->GetFrameCount();
17221 CHECK_EQ(3, frame_count);
17222 int line_number[] = {1, 2, 5};
17223 for (int i = 0; i < frame_count; i++) {
17224 CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
17225 }
17226}
17227
17228
17229// Test that we only return the stack trace at the site where the exception
17230// is first thrown (not where it is rethrown).
17231TEST(RethrowStackTrace) {
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000017232 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017233 v8::HandleScope scope(env->GetIsolate());
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000017234 // We make sure that
17235 // - the stack trace of the ReferenceError in g() is reported.
17236 // - the stack trace is not overwritten when e1 is rethrown by t().
17237 // - the stack trace of e2 does not overwrite that of e1.
17238 const char* source =
17239 "function g() { error; } \n"
17240 "function f() { g(); } \n"
17241 "function t(e) { throw e; } \n"
17242 "try { \n"
17243 " f(); \n"
17244 "} catch (e1) { \n"
17245 " try { \n"
17246 " error; \n"
17247 " } catch (e2) { \n"
17248 " t(e1); \n"
17249 " } \n"
17250 "} \n";
17251 v8::V8::AddMessageListener(RethrowStackTraceHandler);
17252 v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
17253 CompileRun(source);
17254 v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
17255 v8::V8::RemoveMessageListeners(RethrowStackTraceHandler);
17256}
17257
17258
17259static void RethrowPrimitiveStackTraceHandler(v8::Handle<v8::Message> message,
17260 v8::Handle<v8::Value> data) {
17261 v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
17262 CHECK(!stack_trace.IsEmpty());
17263 int frame_count = stack_trace->GetFrameCount();
17264 CHECK_EQ(2, frame_count);
17265 int line_number[] = {3, 7};
17266 for (int i = 0; i < frame_count; i++) {
17267 CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
17268 }
17269}
17270
17271
17272// Test that we do not recognize identity for primitive exceptions.
17273TEST(RethrowPrimitiveStackTrace) {
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000017274 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017275 v8::HandleScope scope(env->GetIsolate());
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000017276 // We do not capture stack trace for non Error objects on creation time.
17277 // Instead, we capture the stack trace on last throw.
17278 const char* source =
17279 "function g() { throw 404; } \n"
17280 "function f() { g(); } \n"
17281 "function t(e) { throw e; } \n"
17282 "try { \n"
17283 " f(); \n"
17284 "} catch (e1) { \n"
17285 " t(e1) \n"
17286 "} \n";
17287 v8::V8::AddMessageListener(RethrowPrimitiveStackTraceHandler);
17288 v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
17289 CompileRun(source);
17290 v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
17291 v8::V8::RemoveMessageListeners(RethrowPrimitiveStackTraceHandler);
17292}
17293
17294
17295static void RethrowExistingStackTraceHandler(v8::Handle<v8::Message> message,
17296 v8::Handle<v8::Value> data) {
17297 // Use the frame where JavaScript is called from.
17298 v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
17299 CHECK(!stack_trace.IsEmpty());
17300 CHECK_EQ(1, stack_trace->GetFrameCount());
17301 CHECK_EQ(1, stack_trace->GetFrame(0)->GetLineNumber());
17302}
17303
17304
17305// Test that the stack trace is captured when the error object is created and
17306// not where it is thrown.
17307TEST(RethrowExistingStackTrace) {
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000017308 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017309 v8::HandleScope scope(env->GetIsolate());
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000017310 const char* source =
17311 "var e = new Error(); \n"
17312 "throw e; \n";
17313 v8::V8::AddMessageListener(RethrowExistingStackTraceHandler);
17314 v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
17315 CompileRun(source);
17316 v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
17317 v8::V8::RemoveMessageListeners(RethrowExistingStackTraceHandler);
17318}
17319
17320
17321static void RethrowBogusErrorStackTraceHandler(v8::Handle<v8::Message> message,
17322 v8::Handle<v8::Value> data) {
17323 // Use the frame where JavaScript is called from.
17324 v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
17325 CHECK(!stack_trace.IsEmpty());
17326 CHECK_EQ(1, stack_trace->GetFrameCount());
17327 CHECK_EQ(2, stack_trace->GetFrame(0)->GetLineNumber());
17328}
17329
17330
17331// Test that the stack trace is captured where the bogus Error object is thrown.
17332TEST(RethrowBogusErrorStackTrace) {
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000017333 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017334 v8::HandleScope scope(env->GetIsolate());
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000017335 const char* source =
17336 "var e = {__proto__: new Error()} \n"
17337 "throw e; \n";
17338 v8::V8::AddMessageListener(RethrowBogusErrorStackTraceHandler);
17339 v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
17340 CompileRun(source);
17341 v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
17342 v8::V8::RemoveMessageListeners(RethrowBogusErrorStackTraceHandler);
17343}
17344
17345
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017346void AnalyzeStackOfEvalWithSourceURL(
17347 const v8::FunctionCallbackInfo<v8::Value>& args) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017348 v8::HandleScope scope(args.GetIsolate());
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017349 v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
17350 args.GetIsolate(), 10, v8::StackTrace::kDetailed);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000017351 CHECK_EQ(5, stackTrace->GetFrameCount());
17352 v8::Handle<v8::String> url = v8_str("eval_url");
17353 for (int i = 0; i < 3; i++) {
17354 v8::Handle<v8::String> name =
17355 stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
17356 CHECK(!name.IsEmpty());
17357 CHECK_EQ(url, name);
17358 }
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000017359}
17360
17361
17362TEST(SourceURLInStackTrace) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017363 v8::Isolate* isolate = CcTest::isolate();
17364 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000017365 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000017366 templ->Set(v8_str("AnalyzeStackOfEvalWithSourceURL"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017367 v8::FunctionTemplate::New(isolate,
17368 AnalyzeStackOfEvalWithSourceURL));
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000017369 LocalContext context(0, templ);
17370
17371 const char *source =
17372 "function outer() {\n"
17373 "function bar() {\n"
17374 " AnalyzeStackOfEvalWithSourceURL();\n"
17375 "}\n"
17376 "function foo() {\n"
17377 "\n"
17378 " bar();\n"
17379 "}\n"
17380 "foo();\n"
17381 "}\n"
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000017382 "eval('(' + outer +')()%s');";
17383
17384 i::ScopedVector<char> code(1024);
17385 i::OS::SNPrintF(code, source, "//# sourceURL=eval_url");
17386 CHECK(CompileRun(code.start())->IsUndefined());
17387 i::OS::SNPrintF(code, source, "//@ sourceURL=eval_url");
17388 CHECK(CompileRun(code.start())->IsUndefined());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000017389}
17390
17391
jkummerow@chromium.org8fa5bd92013-09-02 11:45:09 +000017392static int scriptIdInStack[2];
17393
17394void AnalyzeScriptIdInStack(
17395 const v8::FunctionCallbackInfo<v8::Value>& args) {
17396 v8::HandleScope scope(args.GetIsolate());
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017397 v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
17398 args.GetIsolate(), 10, v8::StackTrace::kScriptId);
jkummerow@chromium.org8fa5bd92013-09-02 11:45:09 +000017399 CHECK_EQ(2, stackTrace->GetFrameCount());
17400 for (int i = 0; i < 2; i++) {
17401 scriptIdInStack[i] = stackTrace->GetFrame(i)->GetScriptId();
17402 }
17403}
17404
17405
17406TEST(ScriptIdInStackTrace) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017407 v8::Isolate* isolate = CcTest::isolate();
17408 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000017409 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
jkummerow@chromium.org8fa5bd92013-09-02 11:45:09 +000017410 templ->Set(v8_str("AnalyzeScriptIdInStack"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017411 v8::FunctionTemplate::New(isolate, AnalyzeScriptIdInStack));
jkummerow@chromium.org8fa5bd92013-09-02 11:45:09 +000017412 LocalContext context(0, templ);
17413
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017414 v8::Handle<v8::String> scriptSource = v8::String::NewFromUtf8(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017415 isolate,
jkummerow@chromium.org8fa5bd92013-09-02 11:45:09 +000017416 "function foo() {\n"
17417 " AnalyzeScriptIdInStack();"
17418 "}\n"
17419 "foo();\n");
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017420 v8::ScriptOrigin origin =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017421 v8::ScriptOrigin(v8::String::NewFromUtf8(isolate, "test"));
jkummerow@chromium.org8fa5bd92013-09-02 11:45:09 +000017422 v8::Local<v8::Script> script(v8::Script::Compile(scriptSource, &origin));
17423 script->Run();
17424 for (int i = 0; i < 2; i++) {
17425 CHECK(scriptIdInStack[i] != v8::Message::kNoScriptIdInfo);
17426 CHECK_EQ(scriptIdInStack[i], script->GetId());
17427 }
17428}
17429
17430
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017431void AnalyzeStackOfInlineScriptWithSourceURL(
17432 const v8::FunctionCallbackInfo<v8::Value>& args) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017433 v8::HandleScope scope(args.GetIsolate());
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017434 v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
17435 args.GetIsolate(), 10, v8::StackTrace::kDetailed);
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017436 CHECK_EQ(4, stackTrace->GetFrameCount());
17437 v8::Handle<v8::String> url = v8_str("url");
17438 for (int i = 0; i < 3; i++) {
17439 v8::Handle<v8::String> name =
17440 stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
17441 CHECK(!name.IsEmpty());
17442 CHECK_EQ(url, name);
17443 }
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017444}
17445
17446
17447TEST(InlineScriptWithSourceURLInStackTrace) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000017448 v8::Isolate* isolate = CcTest::isolate();
17449 v8::HandleScope scope(isolate);
17450 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017451 templ->Set(v8_str("AnalyzeStackOfInlineScriptWithSourceURL"),
17452 v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017453 CcTest::isolate(), AnalyzeStackOfInlineScriptWithSourceURL));
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017454 LocalContext context(0, templ);
17455
17456 const char *source =
17457 "function outer() {\n"
17458 "function bar() {\n"
17459 " AnalyzeStackOfInlineScriptWithSourceURL();\n"
17460 "}\n"
17461 "function foo() {\n"
17462 "\n"
17463 " bar();\n"
17464 "}\n"
17465 "foo();\n"
17466 "}\n"
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000017467 "outer()\n%s";
17468
17469 i::ScopedVector<char> code(1024);
17470 i::OS::SNPrintF(code, source, "//# sourceURL=source_url");
17471 CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
17472 i::OS::SNPrintF(code, source, "//@ sourceURL=source_url");
17473 CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017474}
17475
17476
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017477void AnalyzeStackOfDynamicScriptWithSourceURL(
17478 const v8::FunctionCallbackInfo<v8::Value>& args) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017479 v8::HandleScope scope(args.GetIsolate());
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017480 v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
17481 args.GetIsolate(), 10, v8::StackTrace::kDetailed);
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017482 CHECK_EQ(4, stackTrace->GetFrameCount());
17483 v8::Handle<v8::String> url = v8_str("source_url");
17484 for (int i = 0; i < 3; i++) {
17485 v8::Handle<v8::String> name =
17486 stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
17487 CHECK(!name.IsEmpty());
17488 CHECK_EQ(url, name);
17489 }
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017490}
17491
17492
17493TEST(DynamicWithSourceURLInStackTrace) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000017494 v8::Isolate* isolate = CcTest::isolate();
17495 v8::HandleScope scope(isolate);
17496 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017497 templ->Set(v8_str("AnalyzeStackOfDynamicScriptWithSourceURL"),
17498 v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017499 CcTest::isolate(), AnalyzeStackOfDynamicScriptWithSourceURL));
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017500 LocalContext context(0, templ);
17501
17502 const char *source =
17503 "function outer() {\n"
17504 "function bar() {\n"
17505 " AnalyzeStackOfDynamicScriptWithSourceURL();\n"
17506 "}\n"
17507 "function foo() {\n"
17508 "\n"
17509 " bar();\n"
17510 "}\n"
17511 "foo();\n"
17512 "}\n"
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000017513 "outer()\n%s";
17514
17515 i::ScopedVector<char> code(1024);
17516 i::OS::SNPrintF(code, source, "//# sourceURL=source_url");
17517 CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
17518 i::OS::SNPrintF(code, source, "//@ sourceURL=source_url");
17519 CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017520}
17521
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000017522
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017523static void CreateGarbageInOldSpace() {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017524 i::Factory* factory = CcTest::i_isolate()->factory();
17525 v8::HandleScope scope(CcTest::isolate());
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017526 i::AlwaysAllocateScope always_allocate;
17527 for (int i = 0; i < 1000; i++) {
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000017528 factory->NewFixedArray(1000, i::TENURED);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017529 }
svenpanne@chromium.orgecb9dd62011-12-01 08:22:35 +000017530}
17531
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000017532
svenpanne@chromium.orgecb9dd62011-12-01 08:22:35 +000017533// Test that idle notification can be handled and eventually returns true.
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017534TEST(IdleNotification) {
17535 const intptr_t MB = 1024 * 1024;
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017536 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017537 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017538 intptr_t initial_size = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017539 CreateGarbageInOldSpace();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017540 intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017541 CHECK_GT(size_with_garbage, initial_size + MB);
17542 bool finished = false;
17543 for (int i = 0; i < 200 && !finished; i++) {
17544 finished = v8::V8::IdleNotification();
17545 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017546 intptr_t final_size = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017547 CHECK(finished);
17548 CHECK_LT(final_size, initial_size + 1);
17549}
17550
17551
17552// Test that idle notification can be handled and eventually collects garbage.
yangguo@chromium.org56454712012-02-16 15:33:53 +000017553TEST(IdleNotificationWithSmallHint) {
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017554 const intptr_t MB = 1024 * 1024;
17555 const int IdlePauseInMs = 900;
svenpanne@chromium.orgecb9dd62011-12-01 08:22:35 +000017556 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017557 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017558 intptr_t initial_size = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017559 CreateGarbageInOldSpace();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017560 intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017561 CHECK_GT(size_with_garbage, initial_size + MB);
17562 bool finished = false;
17563 for (int i = 0; i < 200 && !finished; i++) {
17564 finished = v8::V8::IdleNotification(IdlePauseInMs);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017565 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017566 intptr_t final_size = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017567 CHECK(finished);
17568 CHECK_LT(final_size, initial_size + 1);
yangguo@chromium.org56454712012-02-16 15:33:53 +000017569}
17570
17571
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017572// Test that idle notification can be handled and eventually collects garbage.
yangguo@chromium.org56454712012-02-16 15:33:53 +000017573TEST(IdleNotificationWithLargeHint) {
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017574 const intptr_t MB = 1024 * 1024;
17575 const int IdlePauseInMs = 900;
yangguo@chromium.org56454712012-02-16 15:33:53 +000017576 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017577 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017578 intptr_t initial_size = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017579 CreateGarbageInOldSpace();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017580 intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017581 CHECK_GT(size_with_garbage, initial_size + MB);
17582 bool finished = false;
17583 for (int i = 0; i < 200 && !finished; i++) {
17584 finished = v8::V8::IdleNotification(IdlePauseInMs);
yangguo@chromium.org56454712012-02-16 15:33:53 +000017585 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017586 intptr_t final_size = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017587 CHECK(finished);
17588 CHECK_LT(final_size, initial_size + 1);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017589}
17590
17591
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017592TEST(Regress2107) {
17593 const intptr_t MB = 1024 * 1024;
17594 const int kShortIdlePauseInMs = 100;
17595 const int kLongIdlePauseInMs = 1000;
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017596 LocalContext env;
ulan@chromium.org57ff8812013-05-10 08:16:55 +000017597 v8::Isolate* isolate = env->GetIsolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017598 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017599 intptr_t initial_size = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017600 // Send idle notification to start a round of incremental GCs.
17601 v8::V8::IdleNotification(kShortIdlePauseInMs);
17602 // Emulate 7 page reloads.
17603 for (int i = 0; i < 7; i++) {
ulan@chromium.org57ff8812013-05-10 08:16:55 +000017604 {
17605 v8::HandleScope inner_scope(env->GetIsolate());
17606 v8::Local<v8::Context> ctx = v8::Context::New(isolate);
17607 ctx->Enter();
17608 CreateGarbageInOldSpace();
17609 ctx->Exit();
17610 }
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017611 v8::V8::ContextDisposedNotification();
17612 v8::V8::IdleNotification(kLongIdlePauseInMs);
17613 }
17614 // Create garbage and check that idle notification still collects it.
17615 CreateGarbageInOldSpace();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017616 intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017617 CHECK_GT(size_with_garbage, initial_size + MB);
17618 bool finished = false;
17619 for (int i = 0; i < 200 && !finished; i++) {
17620 finished = v8::V8::IdleNotification(kShortIdlePauseInMs);
17621 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017622 intptr_t final_size = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017623 CHECK_LT(final_size, initial_size + 1);
17624}
17625
machenbach@chromium.orgb5be0a92013-11-15 10:32:41 +000017626
17627TEST(Regress2333) {
17628 LocalContext env;
17629 for (int i = 0; i < 3; i++) {
17630 CcTest::heap()->PerformScavenge();
17631 }
17632}
17633
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017634static uint32_t* stack_limit;
17635
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017636static void GetStackLimitCallback(
17637 const v8::FunctionCallbackInfo<v8::Value>& args) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000017638 stack_limit = reinterpret_cast<uint32_t*>(
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017639 CcTest::i_isolate()->stack_guard()->real_climit());
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017640}
17641
17642
17643// Uses the address of a local variable to determine the stack top now.
17644// Given a size, returns an address that is that far from the current
17645// top of stack.
17646static uint32_t* ComputeStackLimit(uint32_t size) {
17647 uint32_t* answer = &size - (size / sizeof(size));
17648 // If the size is very large and the stack is very near the bottom of
17649 // memory then the calculation above may wrap around and give an address
17650 // that is above the (downwards-growing) stack. In that case we return
17651 // a very low address.
17652 if (answer > &size) return reinterpret_cast<uint32_t*>(sizeof(size));
17653 return answer;
17654}
17655
17656
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +000017657// We need at least 165kB for an x64 debug build with clang and ASAN.
17658static const int stack_breathing_room = 256 * i::KB;
17659
17660
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017661TEST(SetResourceConstraints) {
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +000017662 uint32_t* set_limit = ComputeStackLimit(stack_breathing_room);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017663
17664 // Set stack limit.
17665 v8::ResourceConstraints constraints;
17666 constraints.set_stack_limit(set_limit);
machenbach@chromium.org7ff76072013-11-21 09:47:43 +000017667 CHECK(v8::SetResourceConstraints(CcTest::isolate(), &constraints));
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017668
17669 // Execute a script.
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017670 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017671 v8::HandleScope scope(env->GetIsolate());
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017672 Local<v8::FunctionTemplate> fun_templ =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017673 v8::FunctionTemplate::New(env->GetIsolate(), GetStackLimitCallback);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017674 Local<Function> fun = fun_templ->GetFunction();
17675 env->Global()->Set(v8_str("get_stack_limit"), fun);
17676 CompileRun("get_stack_limit();");
17677
17678 CHECK(stack_limit == set_limit);
17679}
17680
17681
17682TEST(SetResourceConstraintsInThread) {
17683 uint32_t* set_limit;
17684 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017685 v8::Locker locker(CcTest::isolate());
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +000017686 set_limit = ComputeStackLimit(stack_breathing_room);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017687
17688 // Set stack limit.
17689 v8::ResourceConstraints constraints;
17690 constraints.set_stack_limit(set_limit);
machenbach@chromium.org7ff76072013-11-21 09:47:43 +000017691 CHECK(v8::SetResourceConstraints(CcTest::isolate(), &constraints));
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017692
17693 // Execute a script.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017694 v8::HandleScope scope(CcTest::isolate());
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017695 LocalContext env;
17696 Local<v8::FunctionTemplate> fun_templ =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017697 v8::FunctionTemplate::New(CcTest::isolate(), GetStackLimitCallback);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017698 Local<Function> fun = fun_templ->GetFunction();
17699 env->Global()->Set(v8_str("get_stack_limit"), fun);
17700 CompileRun("get_stack_limit();");
17701
17702 CHECK(stack_limit == set_limit);
17703 }
17704 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017705 v8::Locker locker(CcTest::isolate());
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017706 CHECK(stack_limit == set_limit);
17707 }
ager@chromium.org96c75b52009-08-26 09:13:16 +000017708}
ager@chromium.org3811b432009-10-28 14:53:37 +000017709
17710
17711THREADED_TEST(GetHeapStatistics) {
ager@chromium.org3811b432009-10-28 14:53:37 +000017712 LocalContext c1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017713 v8::HandleScope scope(c1->GetIsolate());
ager@chromium.org3811b432009-10-28 14:53:37 +000017714 v8::HeapStatistics heap_statistics;
ager@chromium.orgc4c92722009-11-18 14:12:51 +000017715 CHECK_EQ(static_cast<int>(heap_statistics.total_heap_size()), 0);
17716 CHECK_EQ(static_cast<int>(heap_statistics.used_heap_size()), 0);
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +000017717 c1->GetIsolate()->GetHeapStatistics(&heap_statistics);
ager@chromium.orgc4c92722009-11-18 14:12:51 +000017718 CHECK_NE(static_cast<int>(heap_statistics.total_heap_size()), 0);
17719 CHECK_NE(static_cast<int>(heap_statistics.used_heap_size()), 0);
ager@chromium.org3811b432009-10-28 14:53:37 +000017720}
17721
17722
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017723class VisitorImpl : public v8::ExternalResourceVisitor {
17724 public:
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017725 explicit VisitorImpl(TestResource** resource) {
17726 for (int i = 0; i < 4; i++) {
17727 resource_[i] = resource[i];
17728 found_resource_[i] = false;
17729 }
17730 }
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017731 virtual ~VisitorImpl() {}
17732 virtual void VisitExternalString(v8::Handle<v8::String> string) {
17733 if (!string->IsExternal()) {
17734 CHECK(string->IsExternalAscii());
17735 return;
17736 }
17737 v8::String::ExternalStringResource* resource =
17738 string->GetExternalStringResource();
17739 CHECK(resource);
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017740 for (int i = 0; i < 4; i++) {
17741 if (resource_[i] == resource) {
17742 CHECK(!found_resource_[i]);
17743 found_resource_[i] = true;
17744 }
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017745 }
17746 }
17747 void CheckVisitedResources() {
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017748 for (int i = 0; i < 4; i++) {
17749 CHECK(found_resource_[i]);
17750 }
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017751 }
17752
17753 private:
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017754 v8::String::ExternalStringResource* resource_[4];
17755 bool found_resource_[4];
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017756};
17757
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000017758
machenbach@chromium.org82975302014-02-06 01:06:18 +000017759TEST(ExternalizeOldSpaceTwoByteCons) {
17760 LocalContext env;
17761 v8::HandleScope scope(env->GetIsolate());
17762 v8::Local<v8::String> cons =
17763 CompileRun("'Romeo Montague ' + 'Juliet Capulet'")->ToString();
17764 CHECK(v8::Utils::OpenHandle(*cons)->IsConsString());
17765 CcTest::heap()->CollectAllAvailableGarbage();
17766 CHECK(CcTest::heap()->old_pointer_space()->Contains(
17767 *v8::Utils::OpenHandle(*cons)));
17768
17769 TestResource* resource = new TestResource(
17770 AsciiToTwoByteString("Romeo Montague Juliet Capulet"));
17771 cons->MakeExternal(resource);
17772
17773 CHECK(cons->IsExternal());
17774 CHECK_EQ(resource, cons->GetExternalStringResource());
17775 String::Encoding encoding;
17776 CHECK_EQ(resource, cons->GetExternalStringResourceBase(&encoding));
17777 CHECK_EQ(String::TWO_BYTE_ENCODING, encoding);
17778}
17779
17780
17781TEST(ExternalizeOldSpaceOneByteCons) {
17782 LocalContext env;
17783 v8::HandleScope scope(env->GetIsolate());
17784 v8::Local<v8::String> cons =
17785 CompileRun("'Romeo Montague ' + 'Juliet Capulet'")->ToString();
17786 CHECK(v8::Utils::OpenHandle(*cons)->IsConsString());
17787 CcTest::heap()->CollectAllAvailableGarbage();
17788 CHECK(CcTest::heap()->old_pointer_space()->Contains(
17789 *v8::Utils::OpenHandle(*cons)));
17790
17791 TestAsciiResource* resource =
17792 new TestAsciiResource(i::StrDup("Romeo Montague Juliet Capulet"));
17793 cons->MakeExternal(resource);
17794
17795 CHECK(cons->IsExternalAscii());
17796 CHECK_EQ(resource, cons->GetExternalAsciiStringResource());
17797 String::Encoding encoding;
17798 CHECK_EQ(resource, cons->GetExternalStringResourceBase(&encoding));
17799 CHECK_EQ(String::ONE_BYTE_ENCODING, encoding);
17800}
17801
17802
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017803TEST(VisitExternalStrings) {
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017804 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017805 v8::HandleScope scope(env->GetIsolate());
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017806 const char* string = "Some string";
17807 uint16_t* two_byte_string = AsciiToTwoByteString(string);
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017808 TestResource* resource[4];
17809 resource[0] = new TestResource(two_byte_string);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017810 v8::Local<v8::String> string0 =
17811 v8::String::NewExternal(env->GetIsolate(), resource[0]);
machenbach@chromium.org57a54ac2014-01-31 14:01:53 +000017812 resource[1] = new TestResource(two_byte_string, NULL, false);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017813 v8::Local<v8::String> string1 =
17814 v8::String::NewExternal(env->GetIsolate(), resource[1]);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017815
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017816 // Externalized symbol.
machenbach@chromium.org57a54ac2014-01-31 14:01:53 +000017817 resource[2] = new TestResource(two_byte_string, NULL, false);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017818 v8::Local<v8::String> string2 = v8::String::NewFromUtf8(
17819 env->GetIsolate(), string, v8::String::kInternalizedString);
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017820 CHECK(string2->MakeExternal(resource[2]));
17821
17822 // Symbolized External.
17823 resource[3] = new TestResource(AsciiToTwoByteString("Some other string"));
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017824 v8::Local<v8::String> string3 =
17825 v8::String::NewExternal(env->GetIsolate(), resource[3]);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017826 CcTest::heap()->CollectAllAvailableGarbage(); // Tenure string.
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017827 // Turn into a symbol.
17828 i::Handle<i::String> string3_i = v8::Utils::OpenHandle(*string3);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017829 CHECK(!CcTest::heap()->InternalizeString(*string3_i)->IsFailure());
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +000017830 CHECK(string3_i->IsInternalizedString());
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017831
17832 // We need to add usages for string* to avoid warnings in GCC 4.7
17833 CHECK(string0->IsExternal());
ulan@chromium.org2efb9002012-01-19 15:36:35 +000017834 CHECK(string1->IsExternal());
17835 CHECK(string2->IsExternal());
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017836 CHECK(string3->IsExternal());
ulan@chromium.org2efb9002012-01-19 15:36:35 +000017837
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017838 VisitorImpl visitor(resource);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017839 v8::V8::VisitExternalResources(&visitor);
17840 visitor.CheckVisitedResources();
17841}
17842
17843
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017844TEST(ExternalStringCollectedAtTearDown) {
17845 int destroyed = 0;
17846 v8::Isolate* isolate = v8::Isolate::New();
17847 { v8::Isolate::Scope isolate_scope(isolate);
17848 v8::HandleScope handle_scope(isolate);
17849 const char* s = "One string to test them all, one string to find them.";
17850 TestAsciiResource* inscription =
17851 new TestAsciiResource(i::StrDup(s), &destroyed);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017852 v8::Local<v8::String> ring = v8::String::NewExternal(isolate, inscription);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017853 // Ring is still alive. Orcs are roaming freely across our lands.
17854 CHECK_EQ(0, destroyed);
17855 USE(ring);
17856 }
17857
17858 isolate->Dispose();
17859 // Ring has been destroyed. Free Peoples of Middle-earth Rejoice.
17860 CHECK_EQ(1, destroyed);
17861}
17862
17863
jkummerow@chromium.org113035e2013-12-13 15:13:40 +000017864TEST(ExternalInternalizedStringCollectedAtTearDown) {
17865 int destroyed = 0;
17866 v8::Isolate* isolate = v8::Isolate::New();
17867 { v8::Isolate::Scope isolate_scope(isolate);
17868 LocalContext env(isolate);
17869 v8::HandleScope handle_scope(isolate);
17870 CompileRun("var ring = 'One string to test them all';");
17871 const char* s = "One string to test them all";
17872 TestAsciiResource* inscription =
17873 new TestAsciiResource(i::StrDup(s), &destroyed);
17874 v8::Local<v8::String> ring = CompileRun("ring")->ToString();
17875 CHECK(v8::Utils::OpenHandle(*ring)->IsInternalizedString());
17876 ring->MakeExternal(inscription);
17877 // Ring is still alive. Orcs are roaming freely across our lands.
17878 CHECK_EQ(0, destroyed);
17879 USE(ring);
17880 }
17881
17882 isolate->Dispose();
17883 // Ring has been destroyed. Free Peoples of Middle-earth Rejoice.
17884 CHECK_EQ(1, destroyed);
17885}
17886
17887
17888TEST(ExternalInternalizedStringCollectedAtGC) {
17889 int destroyed = 0;
17890 { LocalContext env;
17891 v8::HandleScope handle_scope(env->GetIsolate());
17892 CompileRun("var ring = 'One string to test them all';");
17893 const char* s = "One string to test them all";
17894 TestAsciiResource* inscription =
17895 new TestAsciiResource(i::StrDup(s), &destroyed);
17896 v8::Local<v8::String> ring = CompileRun("ring")->ToString();
17897 CHECK(v8::Utils::OpenHandle(*ring)->IsInternalizedString());
17898 ring->MakeExternal(inscription);
17899 // Ring is still alive. Orcs are roaming freely across our lands.
17900 CHECK_EQ(0, destroyed);
17901 USE(ring);
17902 }
17903
17904 // Garbage collector deals swift blows to evil.
17905 CcTest::i_isolate()->compilation_cache()->Clear();
17906 CcTest::heap()->CollectAllAvailableGarbage();
17907
17908 // Ring has been destroyed. Free Peoples of Middle-earth Rejoice.
17909 CHECK_EQ(1, destroyed);
17910}
17911
17912
ager@chromium.org3811b432009-10-28 14:53:37 +000017913static double DoubleFromBits(uint64_t value) {
17914 double target;
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +000017915 i::OS::MemCopy(&target, &value, sizeof(target));
ager@chromium.org3811b432009-10-28 14:53:37 +000017916 return target;
17917}
17918
17919
17920static uint64_t DoubleToBits(double value) {
17921 uint64_t target;
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +000017922 i::OS::MemCopy(&target, &value, sizeof(target));
ager@chromium.org3811b432009-10-28 14:53:37 +000017923 return target;
17924}
17925
17926
17927static double DoubleToDateTime(double input) {
17928 double date_limit = 864e13;
ulan@chromium.org77ca49a2013-04-22 09:43:56 +000017929 if (std::isnan(input) || input < -date_limit || input > date_limit) {
ager@chromium.org3811b432009-10-28 14:53:37 +000017930 return i::OS::nan_value();
17931 }
machenbach@chromium.orge31286d2014-01-15 10:29:52 +000017932 return (input < 0) ? -(std::floor(-input)) : std::floor(input);
ager@chromium.org3811b432009-10-28 14:53:37 +000017933}
17934
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000017935
ager@chromium.org3811b432009-10-28 14:53:37 +000017936// We don't have a consistent way to write 64-bit constants syntactically, so we
17937// split them into two 32-bit constants and combine them programmatically.
17938static double DoubleFromBits(uint32_t high_bits, uint32_t low_bits) {
17939 return DoubleFromBits((static_cast<uint64_t>(high_bits) << 32) | low_bits);
17940}
17941
17942
17943THREADED_TEST(QuietSignalingNaNs) {
ager@chromium.org3811b432009-10-28 14:53:37 +000017944 LocalContext context;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000017945 v8::Isolate* isolate = context->GetIsolate();
17946 v8::HandleScope scope(isolate);
ager@chromium.org3811b432009-10-28 14:53:37 +000017947 v8::TryCatch try_catch;
17948
17949 // Special double values.
17950 double snan = DoubleFromBits(0x7ff00000, 0x00000001);
17951 double qnan = DoubleFromBits(0x7ff80000, 0x00000000);
17952 double infinity = DoubleFromBits(0x7ff00000, 0x00000000);
17953 double max_normal = DoubleFromBits(0x7fefffff, 0xffffffffu);
17954 double min_normal = DoubleFromBits(0x00100000, 0x00000000);
17955 double max_denormal = DoubleFromBits(0x000fffff, 0xffffffffu);
17956 double min_denormal = DoubleFromBits(0x00000000, 0x00000001);
17957
17958 // Date values are capped at +/-100000000 days (times 864e5 ms per day)
17959 // on either side of the epoch.
17960 double date_limit = 864e13;
17961
17962 double test_values[] = {
17963 snan,
17964 qnan,
17965 infinity,
17966 max_normal,
17967 date_limit + 1,
17968 date_limit,
17969 min_normal,
17970 max_denormal,
17971 min_denormal,
17972 0,
17973 -0,
17974 -min_denormal,
17975 -max_denormal,
17976 -min_normal,
17977 -date_limit,
17978 -date_limit - 1,
17979 -max_normal,
17980 -infinity,
17981 -qnan,
17982 -snan
17983 };
17984 int num_test_values = 20;
17985
17986 for (int i = 0; i < num_test_values; i++) {
17987 double test_value = test_values[i];
17988
17989 // Check that Number::New preserves non-NaNs and quiets SNaNs.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000017990 v8::Handle<v8::Value> number = v8::Number::New(isolate, test_value);
ager@chromium.org3811b432009-10-28 14:53:37 +000017991 double stored_number = number->NumberValue();
ulan@chromium.org77ca49a2013-04-22 09:43:56 +000017992 if (!std::isnan(test_value)) {
ager@chromium.org3811b432009-10-28 14:53:37 +000017993 CHECK_EQ(test_value, stored_number);
17994 } else {
17995 uint64_t stored_bits = DoubleToBits(stored_number);
17996 // Check if quiet nan (bits 51..62 all set).
danno@chromium.orgc612e022011-11-10 11:38:15 +000017997#if defined(V8_TARGET_ARCH_MIPS) && !defined(USE_SIMULATOR)
17998 // Most significant fraction bit for quiet nan is set to 0
17999 // on MIPS architecture. Allowed by IEEE-754.
18000 CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
18001#else
ager@chromium.org3811b432009-10-28 14:53:37 +000018002 CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
danno@chromium.orgc612e022011-11-10 11:38:15 +000018003#endif
ager@chromium.org3811b432009-10-28 14:53:37 +000018004 }
18005
18006 // Check that Date::New preserves non-NaNs in the date range and
18007 // quiets SNaNs.
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000018008 v8::Handle<v8::Value> date =
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018009 v8::Date::New(isolate, test_value);
ager@chromium.org3811b432009-10-28 14:53:37 +000018010 double expected_stored_date = DoubleToDateTime(test_value);
18011 double stored_date = date->NumberValue();
ulan@chromium.org77ca49a2013-04-22 09:43:56 +000018012 if (!std::isnan(expected_stored_date)) {
ager@chromium.org3811b432009-10-28 14:53:37 +000018013 CHECK_EQ(expected_stored_date, stored_date);
18014 } else {
18015 uint64_t stored_bits = DoubleToBits(stored_date);
18016 // Check if quiet nan (bits 51..62 all set).
danno@chromium.orgc612e022011-11-10 11:38:15 +000018017#if defined(V8_TARGET_ARCH_MIPS) && !defined(USE_SIMULATOR)
18018 // Most significant fraction bit for quiet nan is set to 0
18019 // on MIPS architecture. Allowed by IEEE-754.
18020 CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
18021#else
ager@chromium.org3811b432009-10-28 14:53:37 +000018022 CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
danno@chromium.orgc612e022011-11-10 11:38:15 +000018023#endif
ager@chromium.org3811b432009-10-28 14:53:37 +000018024 }
18025 }
18026}
christian.plesner.hansen@gmail.comb9ce6372009-11-03 11:38:18 +000018027
18028
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018029static void SpaghettiIncident(
18030 const v8::FunctionCallbackInfo<v8::Value>& args) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018031 v8::HandleScope scope(args.GetIsolate());
christian.plesner.hansen@gmail.comb9ce6372009-11-03 11:38:18 +000018032 v8::TryCatch tc;
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000018033 v8::Handle<v8::String> str(args[0]->ToString());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000018034 USE(str);
christian.plesner.hansen@gmail.comb9ce6372009-11-03 11:38:18 +000018035 if (tc.HasCaught())
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018036 tc.ReThrow();
christian.plesner.hansen@gmail.comb9ce6372009-11-03 11:38:18 +000018037}
18038
18039
18040// Test that an exception can be propagated down through a spaghetti
18041// stack using ReThrow.
18042THREADED_TEST(SpaghettiStackReThrow) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000018043 v8::Isolate* isolate = CcTest::isolate();
18044 v8::HandleScope scope(isolate);
christian.plesner.hansen@gmail.comb9ce6372009-11-03 11:38:18 +000018045 LocalContext context;
18046 context->Global()->Set(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000018047 v8::String::NewFromUtf8(isolate, "s"),
18048 v8::FunctionTemplate::New(isolate, SpaghettiIncident)->GetFunction());
christian.plesner.hansen@gmail.comb9ce6372009-11-03 11:38:18 +000018049 v8::TryCatch try_catch;
18050 CompileRun(
18051 "var i = 0;"
18052 "var o = {"
18053 " toString: function () {"
18054 " if (i == 10) {"
18055 " throw 'Hey!';"
18056 " } else {"
18057 " i++;"
18058 " return s(o);"
18059 " }"
18060 " }"
18061 "};"
18062 "s(o);");
18063 CHECK(try_catch.HasCaught());
18064 v8::String::Utf8Value value(try_catch.Exception());
18065 CHECK_EQ(0, strcmp(*value, "Hey!"));
18066}
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018067
18068
sgjesse@chromium.org98180592009-12-02 08:17:28 +000018069TEST(Regress528) {
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018070 v8::V8::Initialize();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018071 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000018072 v8::HandleScope scope(isolate);
18073 v8::Local<Context> other_context;
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018074 int gc_count;
18075
ager@chromium.org60121232009-12-03 11:25:37 +000018076 // Create a context used to keep the code from aging in the compilation
18077 // cache.
ulan@chromium.org57ff8812013-05-10 08:16:55 +000018078 other_context = Context::New(isolate);
ager@chromium.org60121232009-12-03 11:25:37 +000018079
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018080 // Context-dependent context data creates reference from the compilation
18081 // cache to the global object.
ager@chromium.org60121232009-12-03 11:25:37 +000018082 const char* source_simple = "1";
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018083 {
ulan@chromium.org57ff8812013-05-10 08:16:55 +000018084 v8::HandleScope scope(isolate);
18085 v8::Local<Context> context = Context::New(isolate);
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018086
18087 context->Enter();
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018088 Local<v8::String> obj = v8::String::NewFromUtf8(isolate, "");
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000018089 context->SetEmbedderData(0, obj);
ager@chromium.org60121232009-12-03 11:25:37 +000018090 CompileRun(source_simple);
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018091 context->Exit();
18092 }
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000018093 v8::V8::ContextDisposedNotification();
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018094 for (gc_count = 1; gc_count < 10; gc_count++) {
ager@chromium.org60121232009-12-03 11:25:37 +000018095 other_context->Enter();
18096 CompileRun(source_simple);
18097 other_context->Exit();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018098 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org60121232009-12-03 11:25:37 +000018099 if (GetGlobalObjectsCount() == 1) break;
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018100 }
ager@chromium.org60121232009-12-03 11:25:37 +000018101 CHECK_GE(2, gc_count);
18102 CHECK_EQ(1, GetGlobalObjectsCount());
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018103
18104 // Eval in a function creates reference from the compilation cache to the
18105 // global object.
ager@chromium.org60121232009-12-03 11:25:37 +000018106 const char* source_eval = "function f(){eval('1')}; f()";
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018107 {
ulan@chromium.org57ff8812013-05-10 08:16:55 +000018108 v8::HandleScope scope(isolate);
18109 v8::Local<Context> context = Context::New(isolate);
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018110
18111 context->Enter();
ager@chromium.org60121232009-12-03 11:25:37 +000018112 CompileRun(source_eval);
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018113 context->Exit();
18114 }
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000018115 v8::V8::ContextDisposedNotification();
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018116 for (gc_count = 1; gc_count < 10; gc_count++) {
ager@chromium.org60121232009-12-03 11:25:37 +000018117 other_context->Enter();
18118 CompileRun(source_eval);
18119 other_context->Exit();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018120 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org60121232009-12-03 11:25:37 +000018121 if (GetGlobalObjectsCount() == 1) break;
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018122 }
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +000018123 CHECK_GE(2, gc_count);
sgjesse@chromium.org98180592009-12-02 08:17:28 +000018124 CHECK_EQ(1, GetGlobalObjectsCount());
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018125
18126 // Looking up the line number for an exception creates reference from the
18127 // compilation cache to the global object.
ager@chromium.org60121232009-12-03 11:25:37 +000018128 const char* source_exception = "function f(){throw 1;} f()";
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018129 {
ulan@chromium.org57ff8812013-05-10 08:16:55 +000018130 v8::HandleScope scope(isolate);
18131 v8::Local<Context> context = Context::New(isolate);
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018132
18133 context->Enter();
18134 v8::TryCatch try_catch;
ager@chromium.org60121232009-12-03 11:25:37 +000018135 CompileRun(source_exception);
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018136 CHECK(try_catch.HasCaught());
18137 v8::Handle<v8::Message> message = try_catch.Message();
18138 CHECK(!message.IsEmpty());
18139 CHECK_EQ(1, message->GetLineNumber());
18140 context->Exit();
18141 }
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +000018142 v8::V8::ContextDisposedNotification();
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018143 for (gc_count = 1; gc_count < 10; gc_count++) {
ager@chromium.org60121232009-12-03 11:25:37 +000018144 other_context->Enter();
18145 CompileRun(source_exception);
18146 other_context->Exit();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018147 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org60121232009-12-03 11:25:37 +000018148 if (GetGlobalObjectsCount() == 1) break;
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018149 }
ager@chromium.org60121232009-12-03 11:25:37 +000018150 CHECK_GE(2, gc_count);
18151 CHECK_EQ(1, GetGlobalObjectsCount());
18152
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000018153 v8::V8::ContextDisposedNotification();
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018154}
ager@chromium.org5c838252010-02-19 08:53:10 +000018155
18156
18157THREADED_TEST(ScriptOrigin) {
ager@chromium.org5c838252010-02-19 08:53:10 +000018158 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018159 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018160 v8::ScriptOrigin origin =
18161 v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
18162 v8::Handle<v8::String> script = v8::String::NewFromUtf8(
18163 env->GetIsolate(), "function f() {}\n\nfunction g() {}");
ager@chromium.org5c838252010-02-19 08:53:10 +000018164 v8::Script::Compile(script, &origin)->Run();
18165 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018166 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
ager@chromium.org5c838252010-02-19 08:53:10 +000018167 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018168 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
ager@chromium.org5c838252010-02-19 08:53:10 +000018169
18170 v8::ScriptOrigin script_origin_f = f->GetScriptOrigin();
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000018171 CHECK_EQ("test", *v8::String::Utf8Value(script_origin_f.ResourceName()));
ager@chromium.org5c838252010-02-19 08:53:10 +000018172 CHECK_EQ(0, script_origin_f.ResourceLineOffset()->Int32Value());
18173
18174 v8::ScriptOrigin script_origin_g = g->GetScriptOrigin();
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000018175 CHECK_EQ("test", *v8::String::Utf8Value(script_origin_g.ResourceName()));
ager@chromium.org5c838252010-02-19 08:53:10 +000018176 CHECK_EQ(0, script_origin_g.ResourceLineOffset()->Int32Value());
18177}
18178
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000018179
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000018180THREADED_TEST(FunctionGetInferredName) {
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000018181 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018182 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018183 v8::ScriptOrigin origin =
18184 v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
18185 v8::Handle<v8::String> script = v8::String::NewFromUtf8(
18186 env->GetIsolate(),
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000018187 "var foo = { bar : { baz : function() {}}}; var f = foo.bar.baz;");
18188 v8::Script::Compile(script, &origin)->Run();
18189 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018190 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000018191 CHECK_EQ("foo.bar.baz", *v8::String::Utf8Value(f->GetInferredName()));
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000018192}
ager@chromium.org5c838252010-02-19 08:53:10 +000018193
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000018194
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +000018195THREADED_TEST(FunctionGetDisplayName) {
18196 LocalContext env;
18197 v8::HandleScope scope(env->GetIsolate());
18198 const char* code = "var error = false;"
18199 "function a() { this.x = 1; };"
18200 "a.displayName = 'display_a';"
18201 "var b = (function() {"
18202 " var f = function() { this.x = 2; };"
18203 " f.displayName = 'display_b';"
18204 " return f;"
18205 "})();"
18206 "var c = function() {};"
18207 "c.__defineGetter__('displayName', function() {"
18208 " error = true;"
18209 " throw new Error();"
18210 "});"
18211 "function d() {};"
18212 "d.__defineGetter__('displayName', function() {"
18213 " error = true;"
18214 " return 'wrong_display_name';"
18215 "});"
18216 "function e() {};"
18217 "e.displayName = 'wrong_display_name';"
18218 "e.__defineSetter__('displayName', function() {"
18219 " error = true;"
18220 " throw new Error();"
18221 "});"
18222 "function f() {};"
18223 "f.displayName = { 'foo': 6, toString: function() {"
18224 " error = true;"
18225 " return 'wrong_display_name';"
18226 "}};"
18227 "var g = function() {"
18228 " arguments.callee.displayName = 'set_in_runtime';"
18229 "}; g();"
18230 ;
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018231 v8::ScriptOrigin origin =
18232 v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
18233 v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), code), &origin)
18234 ->Run();
18235 v8::Local<v8::Value> error =
18236 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "error"));
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +000018237 v8::Local<v8::Function> a = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018238 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "a")));
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +000018239 v8::Local<v8::Function> b = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018240 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "b")));
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +000018241 v8::Local<v8::Function> c = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018242 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "c")));
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +000018243 v8::Local<v8::Function> d = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018244 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "d")));
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +000018245 v8::Local<v8::Function> e = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018246 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "e")));
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +000018247 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018248 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +000018249 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018250 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +000018251 CHECK_EQ(false, error->BooleanValue());
18252 CHECK_EQ("display_a", *v8::String::Utf8Value(a->GetDisplayName()));
18253 CHECK_EQ("display_b", *v8::String::Utf8Value(b->GetDisplayName()));
18254 CHECK(c->GetDisplayName()->IsUndefined());
18255 CHECK(d->GetDisplayName()->IsUndefined());
18256 CHECK(e->GetDisplayName()->IsUndefined());
18257 CHECK(f->GetDisplayName()->IsUndefined());
18258 CHECK_EQ("set_in_runtime", *v8::String::Utf8Value(g->GetDisplayName()));
18259}
18260
18261
ager@chromium.org5c838252010-02-19 08:53:10 +000018262THREADED_TEST(ScriptLineNumber) {
ager@chromium.org5c838252010-02-19 08:53:10 +000018263 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018264 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018265 v8::ScriptOrigin origin =
18266 v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
18267 v8::Handle<v8::String> script = v8::String::NewFromUtf8(
18268 env->GetIsolate(), "function f() {}\n\nfunction g() {}");
ager@chromium.org5c838252010-02-19 08:53:10 +000018269 v8::Script::Compile(script, &origin)->Run();
18270 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018271 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
ager@chromium.org5c838252010-02-19 08:53:10 +000018272 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018273 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
ager@chromium.org5c838252010-02-19 08:53:10 +000018274 CHECK_EQ(0, f->GetScriptLineNumber());
18275 CHECK_EQ(2, g->GetScriptLineNumber());
18276}
18277
18278
danno@chromium.orgc612e022011-11-10 11:38:15 +000018279THREADED_TEST(ScriptColumnNumber) {
danno@chromium.orgc612e022011-11-10 11:38:15 +000018280 LocalContext env;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018281 v8::Isolate* isolate = env->GetIsolate();
18282 v8::HandleScope scope(isolate);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018283 v8::ScriptOrigin origin =
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018284 v8::ScriptOrigin(v8::String::NewFromUtf8(isolate, "test"),
18285 v8::Integer::New(isolate, 3),
18286 v8::Integer::New(isolate, 2));
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018287 v8::Handle<v8::String> script = v8::String::NewFromUtf8(
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018288 isolate, "function foo() {}\n\n function bar() {}");
danno@chromium.orgc612e022011-11-10 11:38:15 +000018289 v8::Script::Compile(script, &origin)->Run();
18290 v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018291 env->Global()->Get(v8::String::NewFromUtf8(isolate, "foo")));
danno@chromium.orgc612e022011-11-10 11:38:15 +000018292 v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018293 env->Global()->Get(v8::String::NewFromUtf8(isolate, "bar")));
danno@chromium.orgc612e022011-11-10 11:38:15 +000018294 CHECK_EQ(14, foo->GetScriptColumnNumber());
18295 CHECK_EQ(17, bar->GetScriptColumnNumber());
18296}
18297
18298
bmeurer@chromium.orgdb783292013-10-23 06:51:00 +000018299THREADED_TEST(FunctionIsBuiltin) {
18300 LocalContext env;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018301 v8::Isolate* isolate = env->GetIsolate();
18302 v8::HandleScope scope(isolate);
bmeurer@chromium.orgdb783292013-10-23 06:51:00 +000018303 v8::Local<v8::Function> f;
18304 f = v8::Local<v8::Function>::Cast(CompileRun("Math.floor"));
18305 CHECK(f->IsBuiltin());
18306 f = v8::Local<v8::Function>::Cast(CompileRun("Object"));
18307 CHECK(f->IsBuiltin());
18308 f = v8::Local<v8::Function>::Cast(CompileRun("Object.__defineSetter__"));
18309 CHECK(f->IsBuiltin());
18310 f = v8::Local<v8::Function>::Cast(CompileRun("Array.prototype.toString"));
18311 CHECK(f->IsBuiltin());
18312 f = v8::Local<v8::Function>::Cast(CompileRun("function a() {}; a;"));
18313 CHECK(!f->IsBuiltin());
18314}
18315
18316
danno@chromium.orgc612e022011-11-10 11:38:15 +000018317THREADED_TEST(FunctionGetScriptId) {
danno@chromium.orgc612e022011-11-10 11:38:15 +000018318 LocalContext env;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018319 v8::Isolate* isolate = env->GetIsolate();
18320 v8::HandleScope scope(isolate);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018321 v8::ScriptOrigin origin =
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018322 v8::ScriptOrigin(v8::String::NewFromUtf8(isolate, "test"),
18323 v8::Integer::New(isolate, 3),
18324 v8::Integer::New(isolate, 2));
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018325 v8::Handle<v8::String> scriptSource = v8::String::NewFromUtf8(
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018326 isolate, "function foo() {}\n\n function bar() {}");
danno@chromium.orgc612e022011-11-10 11:38:15 +000018327 v8::Local<v8::Script> script(v8::Script::Compile(scriptSource, &origin));
18328 script->Run();
18329 v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018330 env->Global()->Get(v8::String::NewFromUtf8(isolate, "foo")));
danno@chromium.orgc612e022011-11-10 11:38:15 +000018331 v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018332 env->Global()->Get(v8::String::NewFromUtf8(isolate, "bar")));
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018333 CHECK_EQ(script->GetId(), foo->ScriptId());
18334 CHECK_EQ(script->GetId(), bar->ScriptId());
danno@chromium.orgc612e022011-11-10 11:38:15 +000018335}
18336
18337
yangguo@chromium.org49546742013-12-23 16:17:49 +000018338THREADED_TEST(FunctionGetBoundFunction) {
18339 LocalContext env;
18340 v8::HandleScope scope(env->GetIsolate());
18341 v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::NewFromUtf8(
18342 env->GetIsolate(), "test"));
18343 v8::Handle<v8::String> script = v8::String::NewFromUtf8(
18344 env->GetIsolate(),
18345 "var a = new Object();\n"
18346 "a.x = 1;\n"
18347 "function f () { return this.x };\n"
18348 "var g = f.bind(a);\n"
18349 "var b = g();");
18350 v8::Script::Compile(script, &origin)->Run();
18351 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
18352 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
18353 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
18354 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
18355 CHECK(g->GetBoundFunction()->IsFunction());
18356 Local<v8::Function> original_function = Local<v8::Function>::Cast(
18357 g->GetBoundFunction());
18358 CHECK_EQ(f->GetName(), original_function->GetName());
18359 CHECK_EQ(f->GetScriptLineNumber(), original_function->GetScriptLineNumber());
18360 CHECK_EQ(f->GetScriptColumnNumber(),
18361 original_function->GetScriptColumnNumber());
18362}
18363
18364
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018365static void GetterWhichReturns42(
18366 Local<String> name,
18367 const v8::PropertyCallbackInfo<v8::Value>& info) {
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000018368 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
18369 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018370 info.GetReturnValue().Set(v8_num(42));
ager@chromium.org5c838252010-02-19 08:53:10 +000018371}
18372
18373
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018374static void SetterWhichSetsYOnThisTo23(
18375 Local<String> name,
18376 Local<Value> value,
18377 const v8::PropertyCallbackInfo<void>& info) {
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000018378 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
18379 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
ager@chromium.org5c838252010-02-19 08:53:10 +000018380 info.This()->Set(v8_str("y"), v8_num(23));
18381}
18382
18383
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018384void FooGetInterceptor(Local<String> name,
18385 const v8::PropertyCallbackInfo<v8::Value>& info) {
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000018386 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
18387 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018388 if (!name->Equals(v8_str("foo"))) return;
18389 info.GetReturnValue().Set(v8_num(42));
erik.corry@gmail.com88767242012-08-08 14:43:45 +000018390}
18391
18392
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018393void FooSetInterceptor(Local<String> name,
18394 Local<Value> value,
18395 const v8::PropertyCallbackInfo<v8::Value>& info) {
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000018396 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
18397 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018398 if (!name->Equals(v8_str("foo"))) return;
erik.corry@gmail.com88767242012-08-08 14:43:45 +000018399 info.This()->Set(v8_str("y"), v8_num(23));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018400 info.GetReturnValue().Set(v8_num(23));
erik.corry@gmail.com88767242012-08-08 14:43:45 +000018401}
18402
18403
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000018404TEST(SetterOnConstructorPrototype) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000018405 v8::Isolate* isolate = CcTest::isolate();
18406 v8::HandleScope scope(isolate);
18407 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +000018408 templ->SetAccessor(v8_str("x"),
18409 GetterWhichReturns42,
18410 SetterWhichSetsYOnThisTo23);
18411 LocalContext context;
18412 context->Global()->Set(v8_str("P"), templ->NewInstance());
18413 CompileRun("function C1() {"
18414 " this.x = 23;"
18415 "};"
18416 "C1.prototype = P;"
18417 "function C2() {"
18418 " this.x = 23"
18419 "};"
18420 "C2.prototype = { };"
18421 "C2.prototype.__proto__ = P;");
18422
18423 v8::Local<v8::Script> script;
18424 script = v8::Script::Compile(v8_str("new C1();"));
18425 for (int i = 0; i < 10; i++) {
18426 v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
18427 CHECK_EQ(42, c1->Get(v8_str("x"))->Int32Value());
18428 CHECK_EQ(23, c1->Get(v8_str("y"))->Int32Value());
18429 }
18430
18431 script = v8::Script::Compile(v8_str("new C2();"));
18432 for (int i = 0; i < 10; i++) {
18433 v8::Handle<v8::Object> c2 = v8::Handle<v8::Object>::Cast(script->Run());
18434 CHECK_EQ(42, c2->Get(v8_str("x"))->Int32Value());
18435 CHECK_EQ(23, c2->Get(v8_str("y"))->Int32Value());
18436 }
18437}
18438
18439
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018440static void NamedPropertyGetterWhichReturns42(
18441 Local<String> name,
18442 const v8::PropertyCallbackInfo<v8::Value>& info) {
18443 info.GetReturnValue().Set(v8_num(42));
ager@chromium.org5c838252010-02-19 08:53:10 +000018444}
18445
18446
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018447static void NamedPropertySetterWhichSetsYOnThisTo23(
18448 Local<String> name,
18449 Local<Value> value,
18450 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.org5c838252010-02-19 08:53:10 +000018451 if (name->Equals(v8_str("x"))) {
18452 info.This()->Set(v8_str("y"), v8_num(23));
18453 }
ager@chromium.org5c838252010-02-19 08:53:10 +000018454}
18455
18456
18457THREADED_TEST(InterceptorOnConstructorPrototype) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000018458 v8::Isolate* isolate = CcTest::isolate();
18459 v8::HandleScope scope(isolate);
18460 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +000018461 templ->SetNamedPropertyHandler(NamedPropertyGetterWhichReturns42,
18462 NamedPropertySetterWhichSetsYOnThisTo23);
18463 LocalContext context;
18464 context->Global()->Set(v8_str("P"), templ->NewInstance());
18465 CompileRun("function C1() {"
18466 " this.x = 23;"
18467 "};"
18468 "C1.prototype = P;"
18469 "function C2() {"
18470 " this.x = 23"
18471 "};"
18472 "C2.prototype = { };"
18473 "C2.prototype.__proto__ = P;");
18474
18475 v8::Local<v8::Script> script;
18476 script = v8::Script::Compile(v8_str("new C1();"));
18477 for (int i = 0; i < 10; i++) {
18478 v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
18479 CHECK_EQ(23, c1->Get(v8_str("x"))->Int32Value());
18480 CHECK_EQ(42, c1->Get(v8_str("y"))->Int32Value());
18481 }
18482
18483 script = v8::Script::Compile(v8_str("new C2();"));
18484 for (int i = 0; i < 10; i++) {
18485 v8::Handle<v8::Object> c2 = v8::Handle<v8::Object>::Cast(script->Run());
18486 CHECK_EQ(23, c2->Get(v8_str("x"))->Int32Value());
18487 CHECK_EQ(42, c2->Get(v8_str("y"))->Int32Value());
18488 }
18489}
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000018490
18491
danno@chromium.orgf005df62013-04-30 16:36:45 +000018492TEST(Regress618) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000018493 const char* source = "function C1() {"
18494 " this.x = 23;"
18495 "};"
18496 "C1.prototype = P;";
18497
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000018498 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000018499 v8::Isolate* isolate = context->GetIsolate();
18500 v8::HandleScope scope(isolate);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000018501 v8::Local<v8::Script> script;
18502
18503 // Use a simple object as prototype.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000018504 v8::Local<v8::Object> prototype = v8::Object::New(isolate);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000018505 prototype->Set(v8_str("y"), v8_num(42));
18506 context->Global()->Set(v8_str("P"), prototype);
18507
18508 // This compile will add the code to the compilation cache.
18509 CompileRun(source);
18510
18511 script = v8::Script::Compile(v8_str("new C1();"));
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +000018512 // Allow enough iterations for the inobject slack tracking logic
18513 // to finalize instance size and install the fast construct stub.
18514 for (int i = 0; i < 256; i++) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000018515 v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
18516 CHECK_EQ(23, c1->Get(v8_str("x"))->Int32Value());
18517 CHECK_EQ(42, c1->Get(v8_str("y"))->Int32Value());
18518 }
18519
18520 // Use an API object with accessors as prototype.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000018521 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000018522 templ->SetAccessor(v8_str("x"),
18523 GetterWhichReturns42,
18524 SetterWhichSetsYOnThisTo23);
18525 context->Global()->Set(v8_str("P"), templ->NewInstance());
18526
18527 // This compile will get the code from the compilation cache.
18528 CompileRun(source);
18529
18530 script = v8::Script::Compile(v8_str("new C1();"));
18531 for (int i = 0; i < 10; i++) {
18532 v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
18533 CHECK_EQ(42, c1->Get(v8_str("x"))->Int32Value());
18534 CHECK_EQ(23, c1->Get(v8_str("y"))->Int32Value());
18535 }
18536}
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018537
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018538v8::Isolate* gc_callbacks_isolate = NULL;
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018539int prologue_call_count = 0;
18540int epilogue_call_count = 0;
18541int prologue_call_count_second = 0;
18542int epilogue_call_count_second = 0;
18543
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018544void PrologueCallback(v8::GCType, v8::GCCallbackFlags flags) {
18545 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018546 ++prologue_call_count;
18547}
18548
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000018549
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018550void PrologueCallback(v8::Isolate* isolate,
18551 v8::GCType,
18552 v8::GCCallbackFlags flags) {
18553 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
18554 CHECK_EQ(gc_callbacks_isolate, isolate);
18555 ++prologue_call_count;
18556}
18557
18558
18559void EpilogueCallback(v8::GCType, v8::GCCallbackFlags flags) {
18560 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018561 ++epilogue_call_count;
18562}
18563
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000018564
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018565void EpilogueCallback(v8::Isolate* isolate,
18566 v8::GCType,
18567 v8::GCCallbackFlags flags) {
18568 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
18569 CHECK_EQ(gc_callbacks_isolate, isolate);
18570 ++epilogue_call_count;
18571}
18572
18573
18574void PrologueCallbackSecond(v8::GCType, v8::GCCallbackFlags flags) {
18575 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018576 ++prologue_call_count_second;
18577}
18578
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000018579
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018580void PrologueCallbackSecond(v8::Isolate* isolate,
18581 v8::GCType,
18582 v8::GCCallbackFlags flags) {
18583 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
18584 CHECK_EQ(gc_callbacks_isolate, isolate);
18585 ++prologue_call_count_second;
18586}
18587
18588
18589void EpilogueCallbackSecond(v8::GCType, v8::GCCallbackFlags flags) {
18590 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018591 ++epilogue_call_count_second;
18592}
18593
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000018594
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018595void EpilogueCallbackSecond(v8::Isolate* isolate,
18596 v8::GCType,
18597 v8::GCCallbackFlags flags) {
18598 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
18599 CHECK_EQ(gc_callbacks_isolate, isolate);
18600 ++epilogue_call_count_second;
18601}
18602
18603
18604TEST(GCCallbacksOld) {
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018605 LocalContext context;
18606
18607 v8::V8::AddGCPrologueCallback(PrologueCallback);
18608 v8::V8::AddGCEpilogueCallback(EpilogueCallback);
18609 CHECK_EQ(0, prologue_call_count);
18610 CHECK_EQ(0, epilogue_call_count);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018611 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018612 CHECK_EQ(1, prologue_call_count);
18613 CHECK_EQ(1, epilogue_call_count);
18614 v8::V8::AddGCPrologueCallback(PrologueCallbackSecond);
18615 v8::V8::AddGCEpilogueCallback(EpilogueCallbackSecond);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018616 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018617 CHECK_EQ(2, prologue_call_count);
18618 CHECK_EQ(2, epilogue_call_count);
18619 CHECK_EQ(1, prologue_call_count_second);
18620 CHECK_EQ(1, epilogue_call_count_second);
18621 v8::V8::RemoveGCPrologueCallback(PrologueCallback);
18622 v8::V8::RemoveGCEpilogueCallback(EpilogueCallback);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018623 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018624 CHECK_EQ(2, prologue_call_count);
18625 CHECK_EQ(2, epilogue_call_count);
18626 CHECK_EQ(2, prologue_call_count_second);
18627 CHECK_EQ(2, epilogue_call_count_second);
18628 v8::V8::RemoveGCPrologueCallback(PrologueCallbackSecond);
18629 v8::V8::RemoveGCEpilogueCallback(EpilogueCallbackSecond);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018630 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
18631 CHECK_EQ(2, prologue_call_count);
18632 CHECK_EQ(2, epilogue_call_count);
18633 CHECK_EQ(2, prologue_call_count_second);
18634 CHECK_EQ(2, epilogue_call_count_second);
18635}
18636
18637
18638TEST(GCCallbacks) {
18639 LocalContext context;
18640 v8::Isolate* isolate = context->GetIsolate();
18641 gc_callbacks_isolate = isolate;
18642 isolate->AddGCPrologueCallback(PrologueCallback);
18643 isolate->AddGCEpilogueCallback(EpilogueCallback);
18644 CHECK_EQ(0, prologue_call_count);
18645 CHECK_EQ(0, epilogue_call_count);
18646 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
18647 CHECK_EQ(1, prologue_call_count);
18648 CHECK_EQ(1, epilogue_call_count);
18649 isolate->AddGCPrologueCallback(PrologueCallbackSecond);
18650 isolate->AddGCEpilogueCallback(EpilogueCallbackSecond);
18651 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
18652 CHECK_EQ(2, prologue_call_count);
18653 CHECK_EQ(2, epilogue_call_count);
18654 CHECK_EQ(1, prologue_call_count_second);
18655 CHECK_EQ(1, epilogue_call_count_second);
18656 isolate->RemoveGCPrologueCallback(PrologueCallback);
18657 isolate->RemoveGCEpilogueCallback(EpilogueCallback);
18658 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
18659 CHECK_EQ(2, prologue_call_count);
18660 CHECK_EQ(2, epilogue_call_count);
18661 CHECK_EQ(2, prologue_call_count_second);
18662 CHECK_EQ(2, epilogue_call_count_second);
18663 isolate->RemoveGCPrologueCallback(PrologueCallbackSecond);
18664 isolate->RemoveGCEpilogueCallback(EpilogueCallbackSecond);
18665 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018666 CHECK_EQ(2, prologue_call_count);
18667 CHECK_EQ(2, epilogue_call_count);
18668 CHECK_EQ(2, prologue_call_count_second);
18669 CHECK_EQ(2, epilogue_call_count_second);
18670}
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018671
18672
18673THREADED_TEST(AddToJSFunctionResultCache) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018674 i::FLAG_stress_compaction = false;
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018675 i::FLAG_allow_natives_syntax = true;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018676 v8::HandleScope scope(CcTest::isolate());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018677
18678 LocalContext context;
18679
18680 const char* code =
18681 "(function() {"
18682 " var key0 = 'a';"
18683 " var key1 = 'b';"
18684 " var r0 = %_GetFromCache(0, key0);"
18685 " var r1 = %_GetFromCache(0, key1);"
18686 " var r0_ = %_GetFromCache(0, key0);"
18687 " if (r0 !== r0_)"
18688 " return 'Different results for ' + key0 + ': ' + r0 + ' vs. ' + r0_;"
18689 " var r1_ = %_GetFromCache(0, key1);"
18690 " if (r1 !== r1_)"
18691 " return 'Different results for ' + key1 + ': ' + r1 + ' vs. ' + r1_;"
18692 " return 'PASSED';"
18693 "})()";
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018694 CcTest::heap()->ClearJSFunctionResultCaches();
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018695 ExpectString(code, "PASSED");
18696}
18697
18698
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018699THREADED_TEST(FillJSFunctionResultCache) {
18700 i::FLAG_allow_natives_syntax = true;
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018701 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018702 v8::HandleScope scope(context->GetIsolate());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018703
18704 const char* code =
18705 "(function() {"
18706 " var k = 'a';"
18707 " var r = %_GetFromCache(0, k);"
18708 " for (var i = 0; i < 16; i++) {"
18709 " %_GetFromCache(0, 'a' + i);"
18710 " };"
18711 " if (r === %_GetFromCache(0, k))"
18712 " return 'FAILED: k0CacheSize is too small';"
18713 " return 'PASSED';"
18714 "})()";
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018715 CcTest::heap()->ClearJSFunctionResultCaches();
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018716 ExpectString(code, "PASSED");
18717}
18718
18719
18720THREADED_TEST(RoundRobinGetFromCache) {
18721 i::FLAG_allow_natives_syntax = true;
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018722 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018723 v8::HandleScope scope(context->GetIsolate());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018724
18725 const char* code =
18726 "(function() {"
18727 " var keys = [];"
18728 " for (var i = 0; i < 16; i++) keys.push(i);"
18729 " var values = [];"
18730 " for (var i = 0; i < 16; i++) values[i] = %_GetFromCache(0, keys[i]);"
18731 " for (var i = 0; i < 16; i++) {"
18732 " var v = %_GetFromCache(0, keys[i]);"
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000018733 " if (v.toString() !== values[i].toString())"
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018734 " return 'Wrong value for ' + "
18735 " keys[i] + ': ' + v + ' vs. ' + values[i];"
18736 " };"
18737 " return 'PASSED';"
18738 "})()";
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018739 CcTest::heap()->ClearJSFunctionResultCaches();
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018740 ExpectString(code, "PASSED");
18741}
18742
18743
18744THREADED_TEST(ReverseGetFromCache) {
18745 i::FLAG_allow_natives_syntax = true;
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018746 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018747 v8::HandleScope scope(context->GetIsolate());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018748
18749 const char* code =
18750 "(function() {"
18751 " var keys = [];"
18752 " for (var i = 0; i < 16; i++) keys.push(i);"
18753 " var values = [];"
18754 " for (var i = 0; i < 16; i++) values[i] = %_GetFromCache(0, keys[i]);"
18755 " for (var i = 15; i >= 16; i--) {"
18756 " var v = %_GetFromCache(0, keys[i]);"
18757 " if (v !== values[i])"
18758 " return 'Wrong value for ' + "
18759 " keys[i] + ': ' + v + ' vs. ' + values[i];"
18760 " };"
18761 " return 'PASSED';"
18762 "})()";
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018763 CcTest::heap()->ClearJSFunctionResultCaches();
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018764 ExpectString(code, "PASSED");
18765}
18766
18767
18768THREADED_TEST(TestEviction) {
18769 i::FLAG_allow_natives_syntax = true;
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018770 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018771 v8::HandleScope scope(context->GetIsolate());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018772
18773 const char* code =
18774 "(function() {"
18775 " for (var i = 0; i < 2*16; i++) {"
18776 " %_GetFromCache(0, 'a' + i);"
18777 " };"
18778 " return 'PASSED';"
18779 "})()";
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018780 CcTest::heap()->ClearJSFunctionResultCaches();
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018781 ExpectString(code, "PASSED");
18782}
lrn@chromium.org32d961d2010-06-30 09:09:34 +000018783
18784
18785THREADED_TEST(TwoByteStringInAsciiCons) {
18786 // See Chromium issue 47824.
lrn@chromium.org32d961d2010-06-30 09:09:34 +000018787 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018788 v8::HandleScope scope(context->GetIsolate());
18789
lrn@chromium.org32d961d2010-06-30 09:09:34 +000018790 const char* init_code =
18791 "var str1 = 'abelspendabel';"
18792 "var str2 = str1 + str1 + str1;"
18793 "str2;";
18794 Local<Value> result = CompileRun(init_code);
18795
ricow@chromium.orgddd545c2011-08-24 12:02:41 +000018796 Local<Value> indexof = CompileRun("str2.indexOf('els')");
18797 Local<Value> lastindexof = CompileRun("str2.lastIndexOf('dab')");
18798
lrn@chromium.org32d961d2010-06-30 09:09:34 +000018799 CHECK(result->IsString());
18800 i::Handle<i::String> string = v8::Utils::OpenHandle(String::Cast(*result));
18801 int length = string->length();
ulan@chromium.org8e8d8822012-11-23 14:36:46 +000018802 CHECK(string->IsOneByteRepresentation());
lrn@chromium.org32d961d2010-06-30 09:09:34 +000018803
18804 FlattenString(string);
18805 i::Handle<i::String> flat_string = FlattenGetString(string);
18806
ulan@chromium.org8e8d8822012-11-23 14:36:46 +000018807 CHECK(string->IsOneByteRepresentation());
18808 CHECK(flat_string->IsOneByteRepresentation());
lrn@chromium.org32d961d2010-06-30 09:09:34 +000018809
18810 // Create external resource.
18811 uint16_t* uc16_buffer = new uint16_t[length + 1];
18812
18813 i::String::WriteToFlat(*flat_string, uc16_buffer, 0, length);
18814 uc16_buffer[length] = 0;
18815
18816 TestResource resource(uc16_buffer);
18817
18818 flat_string->MakeExternal(&resource);
18819
18820 CHECK(flat_string->IsTwoByteRepresentation());
18821
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +000018822 // If the cons string has been short-circuited, skip the following checks.
18823 if (!string.is_identical_to(flat_string)) {
18824 // At this point, we should have a Cons string which is flat and ASCII,
18825 // with a first half that is a two-byte string (although it only contains
18826 // ASCII characters). This is a valid sequence of steps, and it can happen
18827 // in real pages.
18828 CHECK(string->IsOneByteRepresentation());
18829 i::ConsString* cons = i::ConsString::cast(*string);
18830 CHECK_EQ(0, cons->second()->length());
18831 CHECK(cons->first()->IsTwoByteRepresentation());
18832 }
lrn@chromium.org32d961d2010-06-30 09:09:34 +000018833
18834 // Check that some string operations work.
18835
18836 // Atom RegExp.
18837 Local<Value> reresult = CompileRun("str2.match(/abel/g).length;");
18838 CHECK_EQ(6, reresult->Int32Value());
18839
18840 // Nonatom RegExp.
18841 reresult = CompileRun("str2.match(/abe./g).length;");
18842 CHECK_EQ(6, reresult->Int32Value());
18843
18844 reresult = CompileRun("str2.search(/bel/g);");
18845 CHECK_EQ(1, reresult->Int32Value());
18846
18847 reresult = CompileRun("str2.search(/be./g);");
18848 CHECK_EQ(1, reresult->Int32Value());
18849
18850 ExpectTrue("/bel/g.test(str2);");
18851
18852 ExpectTrue("/be./g.test(str2);");
18853
18854 reresult = CompileRun("/bel/g.exec(str2);");
18855 CHECK(!reresult->IsNull());
18856
18857 reresult = CompileRun("/be./g.exec(str2);");
18858 CHECK(!reresult->IsNull());
18859
18860 ExpectString("str2.substring(2, 10);", "elspenda");
18861
18862 ExpectString("str2.substring(2, 20);", "elspendabelabelspe");
18863
18864 ExpectString("str2.charAt(2);", "e");
18865
ricow@chromium.orgddd545c2011-08-24 12:02:41 +000018866 ExpectObject("str2.indexOf('els');", indexof);
18867
18868 ExpectObject("str2.lastIndexOf('dab');", lastindexof);
18869
lrn@chromium.org32d961d2010-06-30 09:09:34 +000018870 reresult = CompileRun("str2.charCodeAt(2);");
18871 CHECK_EQ(static_cast<int32_t>('e'), reresult->Int32Value());
18872}
ager@chromium.orgea4f62e2010-08-16 16:28:43 +000018873
18874
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000018875TEST(ContainsOnlyOneByte) {
18876 v8::V8::Initialize();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018877 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000018878 v8::HandleScope scope(isolate);
18879 // Make a buffer long enough that it won't automatically be converted.
verwaest@chromium.org8a00e822013-06-10 15:11:22 +000018880 const int length = 512;
18881 // Ensure word aligned assignment.
18882 const int aligned_length = length*sizeof(uintptr_t)/sizeof(uint16_t);
18883 i::SmartArrayPointer<uintptr_t>
18884 aligned_contents(new uintptr_t[aligned_length]);
machenbach@chromium.orgafbdadc2013-12-09 16:12:18 +000018885 uint16_t* string_contents =
18886 reinterpret_cast<uint16_t*>(aligned_contents.get());
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000018887 // Set to contain only one byte.
18888 for (int i = 0; i < length-1; i++) {
18889 string_contents[i] = 0x41;
18890 }
18891 string_contents[length-1] = 0;
18892 // Simple case.
machenbach@chromium.org57a54ac2014-01-31 14:01:53 +000018893 Handle<String> string =
18894 String::NewExternal(isolate,
18895 new TestResource(string_contents, NULL, false));
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000018896 CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
18897 // Counter example.
verwaest@chromium.org8a00e822013-06-10 15:11:22 +000018898 string = String::NewFromTwoByte(isolate, string_contents);
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000018899 CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
18900 // Test left right and balanced cons strings.
18901 Handle<String> base = String::NewFromUtf8(isolate, "a");
18902 Handle<String> left = base;
18903 Handle<String> right = base;
18904 for (int i = 0; i < 1000; i++) {
18905 left = String::Concat(base, left);
18906 right = String::Concat(right, base);
18907 }
18908 Handle<String> balanced = String::Concat(left, base);
18909 balanced = String::Concat(balanced, right);
18910 Handle<String> cons_strings[] = {left, balanced, right};
18911 Handle<String> two_byte =
machenbach@chromium.org57a54ac2014-01-31 14:01:53 +000018912 String::NewExternal(isolate,
18913 new TestResource(string_contents, NULL, false));
18914 USE(two_byte); USE(cons_strings);
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000018915 for (size_t i = 0; i < ARRAY_SIZE(cons_strings); i++) {
18916 // Base assumptions.
18917 string = cons_strings[i];
18918 CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
18919 // Test left and right concatentation.
18920 string = String::Concat(two_byte, cons_strings[i]);
18921 CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
18922 string = String::Concat(cons_strings[i], two_byte);
18923 CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
18924 }
verwaest@chromium.org8a00e822013-06-10 15:11:22 +000018925 // Set bits in different positions
18926 // for strings of different lengths and alignments.
18927 for (int alignment = 0; alignment < 7; alignment++) {
18928 for (int size = 2; alignment + size < length; size *= 2) {
18929 int zero_offset = size + alignment;
18930 string_contents[zero_offset] = 0;
18931 for (int i = 0; i < size; i++) {
18932 int shift = 8 + (i % 7);
18933 string_contents[alignment + i] = 1 << shift;
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000018934 string = String::NewExternal(
machenbach@chromium.org57a54ac2014-01-31 14:01:53 +000018935 isolate,
18936 new TestResource(string_contents + alignment, NULL, false));
verwaest@chromium.org8a00e822013-06-10 15:11:22 +000018937 CHECK_EQ(size, string->Length());
18938 CHECK(!string->ContainsOnlyOneByte());
18939 string_contents[alignment + i] = 0x41;
18940 }
18941 string_contents[zero_offset] = 0x41;
18942 }
18943 }
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000018944}
18945
18946
ager@chromium.orgea4f62e2010-08-16 16:28:43 +000018947// Failed access check callback that performs a GC on each invocation.
18948void FailedAccessCheckCallbackGC(Local<v8::Object> target,
18949 v8::AccessType type,
18950 Local<v8::Value> data) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018951 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.orgea4f62e2010-08-16 16:28:43 +000018952}
18953
18954
18955TEST(GCInFailedAccessCheckCallback) {
18956 // Install a failed access check callback that performs a GC on each
18957 // invocation. Then force the callback to be called from va
18958
18959 v8::V8::Initialize();
18960 v8::V8::SetFailedAccessCheckCallbackFunction(&FailedAccessCheckCallbackGC);
18961
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000018962 v8::Isolate* isolate = CcTest::isolate();
18963 v8::HandleScope scope(isolate);
ager@chromium.orgea4f62e2010-08-16 16:28:43 +000018964
18965 // Create an ObjectTemplate for global objects and install access
18966 // check callbacks that will block access.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000018967 v8::Handle<v8::ObjectTemplate> global_template =
18968 v8::ObjectTemplate::New(isolate);
ager@chromium.orgea4f62e2010-08-16 16:28:43 +000018969 global_template->SetAccessCheckCallbacks(NamedGetAccessBlocker,
18970 IndexedGetAccessBlocker,
18971 v8::Handle<v8::Value>(),
18972 false);
18973
18974 // Create a context and set an x property on it's global object.
18975 LocalContext context0(NULL, global_template);
18976 context0->Global()->Set(v8_str("x"), v8_num(42));
18977 v8::Handle<v8::Object> global0 = context0->Global();
18978
18979 // Create a context with a different security token so that the
18980 // failed access check callback will be called on each access.
18981 LocalContext context1(NULL, global_template);
18982 context1->Global()->Set(v8_str("other"), global0);
18983
18984 // Get property with failed access check.
18985 ExpectUndefined("other.x");
18986
18987 // Get element with failed access check.
18988 ExpectUndefined("other[0]");
18989
18990 // Set property with failed access check.
18991 v8::Handle<v8::Value> result = CompileRun("other.x = new Object()");
18992 CHECK(result->IsObject());
18993
18994 // Set element with failed access check.
18995 result = CompileRun("other[0] = new Object()");
18996 CHECK(result->IsObject());
18997
18998 // Get property attribute with failed access check.
18999 ExpectFalse("\'x\' in other");
19000
19001 // Get property attribute for element with failed access check.
19002 ExpectFalse("0 in other");
19003
19004 // Delete property.
19005 ExpectFalse("delete other.x");
19006
19007 // Delete element.
19008 CHECK_EQ(false, global0->Delete(0));
19009
19010 // DefineAccessor.
19011 CHECK_EQ(false,
19012 global0->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("x")));
19013
19014 // Define JavaScript accessor.
19015 ExpectUndefined("Object.prototype.__defineGetter__.call("
19016 " other, \'x\', function() { return 42; })");
19017
19018 // LookupAccessor.
19019 ExpectUndefined("Object.prototype.__lookupGetter__.call("
19020 " other, \'x\')");
19021
19022 // HasLocalElement.
19023 ExpectFalse("Object.prototype.hasOwnProperty.call(other, \'0\')");
19024
19025 CHECK_EQ(false, global0->HasRealIndexedProperty(0));
19026 CHECK_EQ(false, global0->HasRealNamedProperty(v8_str("x")));
19027 CHECK_EQ(false, global0->HasRealNamedCallbackProperty(v8_str("x")));
19028
19029 // Reset the failed access check callback so it does not influence
19030 // the other tests.
19031 v8::V8::SetFailedAccessCheckCallbackFunction(NULL);
19032}
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019033
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019034
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019035TEST(IsolateNewDispose) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019036 v8::Isolate* current_isolate = CcTest::isolate();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019037 v8::Isolate* isolate = v8::Isolate::New();
19038 CHECK(isolate != NULL);
19039 CHECK(!reinterpret_cast<i::Isolate*>(isolate)->IsDefaultIsolate());
19040 CHECK(current_isolate != isolate);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019041 CHECK(current_isolate == CcTest::isolate());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019042
19043 v8::V8::SetFatalErrorHandler(StoringErrorCallback);
19044 last_location = last_message = NULL;
19045 isolate->Dispose();
19046 CHECK_EQ(last_location, NULL);
19047 CHECK_EQ(last_message, NULL);
19048}
19049
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019050
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019051UNINITIALIZED_TEST(DisposeIsolateWhenInUse) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019052 v8::Isolate* isolate = v8::Isolate::New();
machenbach@chromium.orgbb8234d2014-02-10 09:01:23 +000019053 {
19054 v8::Isolate::Scope i_scope(isolate);
19055 v8::HandleScope scope(isolate);
19056 LocalContext context(isolate);
19057 // Run something in this isolate.
19058 ExpectTrue("true");
19059 v8::V8::SetFatalErrorHandler(StoringErrorCallback);
19060 last_location = last_message = NULL;
19061 // Still entered, should fail.
19062 isolate->Dispose();
19063 CHECK_NE(last_location, NULL);
19064 CHECK_NE(last_message, NULL);
19065 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019066 isolate->Dispose();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019067}
19068
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019069
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019070TEST(RunTwoIsolatesOnSingleThread) {
19071 // Run isolate 1.
19072 v8::Isolate* isolate1 = v8::Isolate::New();
19073 isolate1->Enter();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000019074 v8::Persistent<v8::Context> context1;
19075 {
19076 v8::HandleScope scope(isolate1);
19077 context1.Reset(isolate1, Context::New(isolate1));
19078 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019079
19080 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019081 v8::HandleScope scope(isolate1);
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000019082 v8::Local<v8::Context> context =
19083 v8::Local<v8::Context>::New(isolate1, context1);
19084 v8::Context::Scope context_scope(context);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019085 // Run something in new isolate.
19086 CompileRun("var foo = 'isolate 1';");
19087 ExpectString("function f() { return foo; }; f()", "isolate 1");
19088 }
19089
19090 // Run isolate 2.
19091 v8::Isolate* isolate2 = v8::Isolate::New();
19092 v8::Persistent<v8::Context> context2;
19093
19094 {
19095 v8::Isolate::Scope iscope(isolate2);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019096 v8::HandleScope scope(isolate2);
ulan@chromium.org57ff8812013-05-10 08:16:55 +000019097 context2.Reset(isolate2, Context::New(isolate2));
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000019098 v8::Local<v8::Context> context =
19099 v8::Local<v8::Context>::New(isolate2, context2);
19100 v8::Context::Scope context_scope(context);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019101
19102 // Run something in new isolate.
19103 CompileRun("var foo = 'isolate 2';");
19104 ExpectString("function f() { return foo; }; f()", "isolate 2");
19105 }
19106
19107 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019108 v8::HandleScope scope(isolate1);
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000019109 v8::Local<v8::Context> context =
19110 v8::Local<v8::Context>::New(isolate1, context1);
19111 v8::Context::Scope context_scope(context);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019112 // Now again in isolate 1
19113 ExpectString("function f() { return foo; }; f()", "isolate 1");
19114 }
19115
19116 isolate1->Exit();
19117
19118 // Run some stuff in default isolate.
ulan@chromium.org57ff8812013-05-10 08:16:55 +000019119 v8::Persistent<v8::Context> context_default;
19120 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019121 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000019122 v8::Isolate::Scope iscope(isolate);
19123 v8::HandleScope scope(isolate);
19124 context_default.Reset(isolate, Context::New(isolate));
19125 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019126
19127 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019128 v8::HandleScope scope(CcTest::isolate());
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000019129 v8::Local<v8::Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019130 v8::Local<v8::Context>::New(CcTest::isolate(), context_default);
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000019131 v8::Context::Scope context_scope(context);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019132 // Variables in other isolates should be not available, verify there
19133 // is an exception.
19134 ExpectTrue("function f() {"
19135 " try {"
19136 " foo;"
19137 " return false;"
19138 " } catch(e) {"
19139 " return true;"
19140 " }"
19141 "};"
19142 "var isDefaultIsolate = true;"
19143 "f()");
19144 }
19145
19146 isolate1->Enter();
19147
19148 {
19149 v8::Isolate::Scope iscope(isolate2);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019150 v8::HandleScope scope(isolate2);
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000019151 v8::Local<v8::Context> context =
19152 v8::Local<v8::Context>::New(isolate2, context2);
19153 v8::Context::Scope context_scope(context);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019154 ExpectString("function f() { return foo; }; f()", "isolate 2");
19155 }
19156
19157 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019158 v8::HandleScope scope(v8::Isolate::GetCurrent());
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000019159 v8::Local<v8::Context> context =
19160 v8::Local<v8::Context>::New(v8::Isolate::GetCurrent(), context1);
19161 v8::Context::Scope context_scope(context);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019162 ExpectString("function f() { return foo; }; f()", "isolate 1");
19163 }
19164
19165 {
19166 v8::Isolate::Scope iscope(isolate2);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000019167 context2.Reset();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019168 }
19169
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000019170 context1.Reset();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019171 isolate1->Exit();
19172
19173 v8::V8::SetFatalErrorHandler(StoringErrorCallback);
19174 last_location = last_message = NULL;
19175
19176 isolate1->Dispose();
19177 CHECK_EQ(last_location, NULL);
19178 CHECK_EQ(last_message, NULL);
19179
19180 isolate2->Dispose();
19181 CHECK_EQ(last_location, NULL);
19182 CHECK_EQ(last_message, NULL);
19183
19184 // Check that default isolate still runs.
19185 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019186 v8::HandleScope scope(CcTest::isolate());
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000019187 v8::Local<v8::Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019188 v8::Local<v8::Context>::New(CcTest::isolate(), context_default);
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000019189 v8::Context::Scope context_scope(context);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019190 ExpectTrue("function f() { return isDefaultIsolate; }; f()");
19191 }
19192}
19193
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019194
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019195static int CalcFibonacci(v8::Isolate* isolate, int limit) {
19196 v8::Isolate::Scope isolate_scope(isolate);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019197 v8::HandleScope scope(isolate);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019198 LocalContext context(isolate);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019199 i::ScopedVector<char> code(1024);
19200 i::OS::SNPrintF(code, "function fib(n) {"
19201 " if (n <= 2) return 1;"
19202 " return fib(n-1) + fib(n-2);"
19203 "}"
19204 "fib(%d)", limit);
19205 Local<Value> value = CompileRun(code.start());
19206 CHECK(value->IsNumber());
19207 return static_cast<int>(value->NumberValue());
19208}
19209
19210class IsolateThread : public v8::internal::Thread {
19211 public:
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000019212 IsolateThread(v8::Isolate* isolate, int fib_limit)
19213 : Thread("IsolateThread"),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019214 isolate_(isolate),
19215 fib_limit_(fib_limit),
19216 result_(0) { }
19217
19218 void Run() {
19219 result_ = CalcFibonacci(isolate_, fib_limit_);
19220 }
19221
19222 int result() { return result_; }
19223
19224 private:
19225 v8::Isolate* isolate_;
19226 int fib_limit_;
19227 int result_;
19228};
19229
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019230
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019231TEST(MultipleIsolatesOnIndividualThreads) {
19232 v8::Isolate* isolate1 = v8::Isolate::New();
19233 v8::Isolate* isolate2 = v8::Isolate::New();
19234
19235 IsolateThread thread1(isolate1, 21);
19236 IsolateThread thread2(isolate2, 12);
19237
19238 // Compute some fibonacci numbers on 3 threads in 3 isolates.
19239 thread1.Start();
19240 thread2.Start();
19241
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019242 int result1 = CalcFibonacci(CcTest::isolate(), 21);
19243 int result2 = CalcFibonacci(CcTest::isolate(), 12);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019244
19245 thread1.Join();
19246 thread2.Join();
19247
19248 // Compare results. The actual fibonacci numbers for 12 and 21 are taken
19249 // (I'm lazy!) from http://en.wikipedia.org/wiki/Fibonacci_number
19250 CHECK_EQ(result1, 10946);
19251 CHECK_EQ(result2, 144);
19252 CHECK_EQ(result1, thread1.result());
19253 CHECK_EQ(result2, thread2.result());
19254
19255 isolate1->Dispose();
19256 isolate2->Dispose();
19257}
19258
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019259
lrn@chromium.org1c092762011-05-09 09:42:16 +000019260TEST(IsolateDifferentContexts) {
19261 v8::Isolate* isolate = v8::Isolate::New();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000019262 Local<v8::Context> context;
lrn@chromium.org1c092762011-05-09 09:42:16 +000019263 {
19264 v8::Isolate::Scope isolate_scope(isolate);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019265 v8::HandleScope handle_scope(isolate);
ulan@chromium.org57ff8812013-05-10 08:16:55 +000019266 context = v8::Context::New(isolate);
lrn@chromium.org1c092762011-05-09 09:42:16 +000019267 v8::Context::Scope context_scope(context);
19268 Local<Value> v = CompileRun("2");
19269 CHECK(v->IsNumber());
19270 CHECK_EQ(2, static_cast<int>(v->NumberValue()));
19271 }
19272 {
19273 v8::Isolate::Scope isolate_scope(isolate);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019274 v8::HandleScope handle_scope(isolate);
ulan@chromium.org57ff8812013-05-10 08:16:55 +000019275 context = v8::Context::New(isolate);
lrn@chromium.org1c092762011-05-09 09:42:16 +000019276 v8::Context::Scope context_scope(context);
19277 Local<Value> v = CompileRun("22");
19278 CHECK(v->IsNumber());
19279 CHECK_EQ(22, static_cast<int>(v->NumberValue()));
19280 }
machenbach@chromium.orgbb8234d2014-02-10 09:01:23 +000019281 isolate->Dispose();
lrn@chromium.org1c092762011-05-09 09:42:16 +000019282}
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019283
19284class InitDefaultIsolateThread : public v8::internal::Thread {
19285 public:
sgjesse@chromium.orge0599052011-03-25 07:34:35 +000019286 enum TestCase {
19287 IgnoreOOM,
19288 SetResourceConstraints,
19289 SetFatalHandler,
19290 SetCounterFunction,
19291 SetCreateHistogramFunction,
19292 SetAddHistogramSampleFunction
19293 };
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019294
19295 explicit InitDefaultIsolateThread(TestCase testCase)
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000019296 : Thread("InitDefaultIsolateThread"),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019297 testCase_(testCase),
19298 result_(false) { }
19299
19300 void Run() {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019301 v8::Isolate* isolate = v8::Isolate::New();
19302 isolate->Enter();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019303 switch (testCase_) {
19304 case IgnoreOOM:
19305 v8::V8::IgnoreOutOfMemoryException();
19306 break;
19307
19308 case SetResourceConstraints: {
19309 static const int K = 1024;
19310 v8::ResourceConstraints constraints;
19311 constraints.set_max_young_space_size(256 * K);
19312 constraints.set_max_old_space_size(4 * K * K);
machenbach@chromium.org7ff76072013-11-21 09:47:43 +000019313 v8::SetResourceConstraints(CcTest::isolate(), &constraints);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019314 break;
19315 }
19316
19317 case SetFatalHandler:
19318 v8::V8::SetFatalErrorHandler(NULL);
19319 break;
sgjesse@chromium.orge0599052011-03-25 07:34:35 +000019320
19321 case SetCounterFunction:
19322 v8::V8::SetCounterFunction(NULL);
19323 break;
19324
19325 case SetCreateHistogramFunction:
19326 v8::V8::SetCreateHistogramFunction(NULL);
19327 break;
19328
19329 case SetAddHistogramSampleFunction:
19330 v8::V8::SetAddHistogramSampleFunction(NULL);
19331 break;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019332 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019333 isolate->Exit();
19334 isolate->Dispose();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019335 result_ = true;
19336 }
19337
19338 bool result() { return result_; }
19339
19340 private:
19341 TestCase testCase_;
19342 bool result_;
19343};
19344
19345
19346static void InitializeTestHelper(InitDefaultIsolateThread::TestCase testCase) {
19347 InitDefaultIsolateThread thread(testCase);
19348 thread.Start();
19349 thread.Join();
19350 CHECK_EQ(thread.result(), true);
19351}
19352
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019353
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019354TEST(InitializeDefaultIsolateOnSecondaryThread1) {
19355 InitializeTestHelper(InitDefaultIsolateThread::IgnoreOOM);
19356}
19357
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019358
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019359TEST(InitializeDefaultIsolateOnSecondaryThread2) {
19360 InitializeTestHelper(InitDefaultIsolateThread::SetResourceConstraints);
19361}
19362
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019363
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019364TEST(InitializeDefaultIsolateOnSecondaryThread3) {
19365 InitializeTestHelper(InitDefaultIsolateThread::SetFatalHandler);
19366}
19367
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019368
sgjesse@chromium.orge0599052011-03-25 07:34:35 +000019369TEST(InitializeDefaultIsolateOnSecondaryThread4) {
19370 InitializeTestHelper(InitDefaultIsolateThread::SetCounterFunction);
19371}
19372
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019373
sgjesse@chromium.orge0599052011-03-25 07:34:35 +000019374TEST(InitializeDefaultIsolateOnSecondaryThread5) {
19375 InitializeTestHelper(InitDefaultIsolateThread::SetCreateHistogramFunction);
19376}
19377
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019378
sgjesse@chromium.orge0599052011-03-25 07:34:35 +000019379TEST(InitializeDefaultIsolateOnSecondaryThread6) {
19380 InitializeTestHelper(InitDefaultIsolateThread::SetAddHistogramSampleFunction);
19381}
19382
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019383
19384TEST(StringCheckMultipleContexts) {
19385 const char* code =
19386 "(function() { return \"a\".charAt(0); })()";
19387
19388 {
19389 // Run the code twice in the first context to initialize the call IC.
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019390 LocalContext context1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019391 v8::HandleScope scope(context1->GetIsolate());
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019392 ExpectString(code, "a");
19393 ExpectString(code, "a");
19394 }
19395
19396 {
19397 // Change the String.prototype in the second context and check
19398 // that the right function gets called.
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019399 LocalContext context2;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019400 v8::HandleScope scope(context2->GetIsolate());
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019401 CompileRun("String.prototype.charAt = function() { return \"not a\"; }");
19402 ExpectString(code, "not a");
19403 }
19404}
19405
19406
19407TEST(NumberCheckMultipleContexts) {
19408 const char* code =
19409 "(function() { return (42).toString(); })()";
19410
19411 {
19412 // Run the code twice in the first context to initialize the call IC.
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019413 LocalContext context1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019414 v8::HandleScope scope(context1->GetIsolate());
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019415 ExpectString(code, "42");
19416 ExpectString(code, "42");
19417 }
19418
19419 {
19420 // Change the Number.prototype in the second context and check
19421 // that the right function gets called.
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019422 LocalContext context2;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019423 v8::HandleScope scope(context2->GetIsolate());
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019424 CompileRun("Number.prototype.toString = function() { return \"not 42\"; }");
19425 ExpectString(code, "not 42");
19426 }
19427}
19428
19429
19430TEST(BooleanCheckMultipleContexts) {
19431 const char* code =
19432 "(function() { return true.toString(); })()";
19433
19434 {
19435 // Run the code twice in the first context to initialize the call IC.
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019436 LocalContext context1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019437 v8::HandleScope scope(context1->GetIsolate());
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019438 ExpectString(code, "true");
19439 ExpectString(code, "true");
19440 }
19441
19442 {
19443 // Change the Boolean.prototype in the second context and check
19444 // that the right function gets called.
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019445 LocalContext context2;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019446 v8::HandleScope scope(context2->GetIsolate());
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019447 CompileRun("Boolean.prototype.toString = function() { return \"\"; }");
19448 ExpectString(code, "");
19449 }
19450}
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019451
19452
19453TEST(DontDeleteCellLoadIC) {
19454 const char* function_code =
19455 "function readCell() { while (true) { return cell; } }";
19456
19457 {
19458 // Run the code twice in the first context to initialize the load
19459 // IC for a don't delete cell.
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019460 LocalContext context1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019461 v8::HandleScope scope(context1->GetIsolate());
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019462 CompileRun("var cell = \"first\";");
19463 ExpectBoolean("delete cell", false);
19464 CompileRun(function_code);
19465 ExpectString("readCell()", "first");
19466 ExpectString("readCell()", "first");
19467 }
19468
19469 {
19470 // Use a deletable cell in the second context.
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019471 LocalContext context2;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019472 v8::HandleScope scope(context2->GetIsolate());
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019473 CompileRun("cell = \"second\";");
19474 CompileRun(function_code);
19475 ExpectString("readCell()", "second");
19476 ExpectBoolean("delete cell", true);
19477 ExpectString("(function() {"
19478 " try {"
19479 " return readCell();"
19480 " } catch(e) {"
19481 " return e.toString();"
19482 " }"
19483 "})()",
19484 "ReferenceError: cell is not defined");
19485 CompileRun("cell = \"new_second\";");
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019486 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019487 ExpectString("readCell()", "new_second");
19488 ExpectString("readCell()", "new_second");
19489 }
19490}
19491
19492
19493TEST(DontDeleteCellLoadICForceDelete) {
19494 const char* function_code =
19495 "function readCell() { while (true) { return cell; } }";
19496
19497 // Run the code twice to initialize the load IC for a don't delete
19498 // cell.
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019499 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019500 v8::HandleScope scope(context->GetIsolate());
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019501 CompileRun("var cell = \"value\";");
19502 ExpectBoolean("delete cell", false);
19503 CompileRun(function_code);
19504 ExpectString("readCell()", "value");
19505 ExpectString("readCell()", "value");
19506
19507 // Delete the cell using the API and check the inlined code works
19508 // correctly.
19509 CHECK(context->Global()->ForceDelete(v8_str("cell")));
19510 ExpectString("(function() {"
19511 " try {"
19512 " return readCell();"
19513 " } catch(e) {"
19514 " return e.toString();"
19515 " }"
19516 "})()",
19517 "ReferenceError: cell is not defined");
19518}
19519
19520
19521TEST(DontDeleteCellLoadICAPI) {
19522 const char* function_code =
19523 "function readCell() { while (true) { return cell; } }";
19524
19525 // Run the code twice to initialize the load IC for a don't delete
19526 // cell created using the API.
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019527 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019528 v8::HandleScope scope(context->GetIsolate());
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019529 context->Global()->Set(v8_str("cell"), v8_str("value"), v8::DontDelete);
19530 ExpectBoolean("delete cell", false);
19531 CompileRun(function_code);
19532 ExpectString("readCell()", "value");
19533 ExpectString("readCell()", "value");
19534
19535 // Delete the cell using the API and check the inlined code works
19536 // correctly.
19537 CHECK(context->Global()->ForceDelete(v8_str("cell")));
19538 ExpectString("(function() {"
19539 " try {"
19540 " return readCell();"
19541 " } catch(e) {"
19542 " return e.toString();"
19543 " }"
19544 "})()",
19545 "ReferenceError: cell is not defined");
19546}
19547
19548
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000019549class Visitor42 : public v8::PersistentHandleVisitor {
19550 public:
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000019551 explicit Visitor42(v8::Persistent<v8::Object>* object)
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000019552 : counter_(0), object_(object) { }
19553
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000019554 virtual void VisitPersistentHandle(Persistent<Value>* value,
19555 uint16_t class_id) {
19556 if (class_id != 42) return;
19557 CHECK_EQ(42, value->WrapperClassId());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019558 v8::Isolate* isolate = CcTest::isolate();
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000019559 v8::HandleScope handle_scope(isolate);
19560 v8::Handle<v8::Value> handle = v8::Local<v8::Value>::New(isolate, *value);
19561 v8::Handle<v8::Value> object =
19562 v8::Local<v8::Object>::New(isolate, *object_);
19563 CHECK(handle->IsObject());
19564 CHECK_EQ(Handle<Object>::Cast(handle), object);
19565 ++counter_;
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000019566 }
19567
19568 int counter_;
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000019569 v8::Persistent<v8::Object>* object_;
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000019570};
19571
19572
19573TEST(PersistentHandleVisitor) {
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000019574 LocalContext context;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000019575 v8::Isolate* isolate = context->GetIsolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019576 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000019577 v8::Persistent<v8::Object> object(isolate, v8::Object::New(isolate));
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000019578 CHECK_EQ(0, object.WrapperClassId());
19579 object.SetWrapperClassId(42);
19580 CHECK_EQ(42, object.WrapperClassId());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000019581
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000019582 Visitor42 visitor(&object);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000019583 v8::V8::VisitHandlesWithClassIds(&visitor);
19584 CHECK_EQ(1, visitor.counter_);
19585
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000019586 object.Reset();
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000019587}
19588
19589
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000019590TEST(WrapperClassId) {
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000019591 LocalContext context;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000019592 v8::Isolate* isolate = context->GetIsolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019593 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000019594 v8::Persistent<v8::Object> object(isolate, v8::Object::New(isolate));
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000019595 CHECK_EQ(0, object.WrapperClassId());
19596 object.SetWrapperClassId(65535);
19597 CHECK_EQ(65535, object.WrapperClassId());
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000019598 object.Reset();
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000019599}
19600
19601
yangguo@chromium.org003650e2013-01-24 16:31:08 +000019602TEST(PersistentHandleInNewSpaceVisitor) {
yangguo@chromium.org003650e2013-01-24 16:31:08 +000019603 LocalContext context;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000019604 v8::Isolate* isolate = context->GetIsolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019605 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000019606 v8::Persistent<v8::Object> object1(isolate, v8::Object::New(isolate));
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000019607 CHECK_EQ(0, object1.WrapperClassId());
19608 object1.SetWrapperClassId(42);
19609 CHECK_EQ(42, object1.WrapperClassId());
yangguo@chromium.org003650e2013-01-24 16:31:08 +000019610
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019611 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
yangguo@chromium.org003650e2013-01-24 16:31:08 +000019612
ulan@chromium.org0f13e742014-01-03 15:51:11 +000019613 v8::Persistent<v8::Object> object2(isolate, v8::Object::New(isolate));
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000019614 CHECK_EQ(0, object2.WrapperClassId());
19615 object2.SetWrapperClassId(42);
19616 CHECK_EQ(42, object2.WrapperClassId());
yangguo@chromium.org003650e2013-01-24 16:31:08 +000019617
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000019618 Visitor42 visitor(&object2);
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000019619 v8::V8::VisitHandlesForPartialDependence(isolate, &visitor);
yangguo@chromium.org003650e2013-01-24 16:31:08 +000019620 CHECK_EQ(1, visitor.counter_);
19621
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000019622 object1.Reset();
19623 object2.Reset();
yangguo@chromium.org003650e2013-01-24 16:31:08 +000019624}
19625
19626
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019627TEST(RegExp) {
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019628 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019629 v8::HandleScope scope(context->GetIsolate());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019630
19631 v8::Handle<v8::RegExp> re = v8::RegExp::New(v8_str("foo"), v8::RegExp::kNone);
19632 CHECK(re->IsRegExp());
19633 CHECK(re->GetSource()->Equals(v8_str("foo")));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000019634 CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019635
19636 re = v8::RegExp::New(v8_str("bar"),
19637 static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
19638 v8::RegExp::kGlobal));
19639 CHECK(re->IsRegExp());
19640 CHECK(re->GetSource()->Equals(v8_str("bar")));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000019641 CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kGlobal,
19642 static_cast<int>(re->GetFlags()));
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019643
19644 re = v8::RegExp::New(v8_str("baz"),
19645 static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
19646 v8::RegExp::kMultiline));
19647 CHECK(re->IsRegExp());
19648 CHECK(re->GetSource()->Equals(v8_str("baz")));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000019649 CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
19650 static_cast<int>(re->GetFlags()));
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019651
19652 re = CompileRun("/quux/").As<v8::RegExp>();
19653 CHECK(re->IsRegExp());
19654 CHECK(re->GetSource()->Equals(v8_str("quux")));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000019655 CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019656
19657 re = CompileRun("/quux/gm").As<v8::RegExp>();
19658 CHECK(re->IsRegExp());
19659 CHECK(re->GetSource()->Equals(v8_str("quux")));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000019660 CHECK_EQ(v8::RegExp::kGlobal | v8::RegExp::kMultiline,
19661 static_cast<int>(re->GetFlags()));
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019662
19663 // Override the RegExp constructor and check the API constructor
19664 // still works.
19665 CompileRun("RegExp = function() {}");
19666
19667 re = v8::RegExp::New(v8_str("foobar"), v8::RegExp::kNone);
19668 CHECK(re->IsRegExp());
19669 CHECK(re->GetSource()->Equals(v8_str("foobar")));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000019670 CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019671
19672 re = v8::RegExp::New(v8_str("foobarbaz"),
19673 static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
19674 v8::RegExp::kMultiline));
19675 CHECK(re->IsRegExp());
19676 CHECK(re->GetSource()->Equals(v8_str("foobarbaz")));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000019677 CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
19678 static_cast<int>(re->GetFlags()));
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019679
19680 context->Global()->Set(v8_str("re"), re);
19681 ExpectTrue("re.test('FoobarbaZ')");
19682
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000019683 // RegExps are objects on which you can set properties.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000019684 re->Set(v8_str("property"), v8::Integer::New(context->GetIsolate(), 32));
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000019685 v8::Handle<v8::Value> value(CompileRun("re.property"));
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000019686 CHECK_EQ(32, value->Int32Value());
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000019687
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019688 v8::TryCatch try_catch;
19689 re = v8::RegExp::New(v8_str("foo["), v8::RegExp::kNone);
19690 CHECK(re.IsEmpty());
19691 CHECK(try_catch.HasCaught());
19692 context->Global()->Set(v8_str("ex"), try_catch.Exception());
19693 ExpectTrue("ex instanceof SyntaxError");
19694}
19695
19696
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000019697THREADED_TEST(Equals) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000019698 LocalContext localContext;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019699 v8::HandleScope handleScope(localContext->GetIsolate());
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000019700
19701 v8::Handle<v8::Object> globalProxy = localContext->Global();
19702 v8::Handle<Value> global = globalProxy->GetPrototype();
19703
19704 CHECK(global->StrictEquals(global));
19705 CHECK(!global->StrictEquals(globalProxy));
19706 CHECK(!globalProxy->StrictEquals(global));
19707 CHECK(globalProxy->StrictEquals(globalProxy));
19708
19709 CHECK(global->Equals(global));
19710 CHECK(!global->Equals(globalProxy));
19711 CHECK(!globalProxy->Equals(global));
19712 CHECK(globalProxy->Equals(globalProxy));
19713}
19714
19715
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019716static void Getter(v8::Local<v8::String> property,
19717 const v8::PropertyCallbackInfo<v8::Value>& info ) {
19718 info.GetReturnValue().Set(v8_str("42!"));
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019719}
19720
19721
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019722static void Enumerator(const v8::PropertyCallbackInfo<v8::Array>& info) {
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000019723 v8::Handle<v8::Array> result = v8::Array::New(info.GetIsolate());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019724 result->Set(0, v8_str("universalAnswer"));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019725 info.GetReturnValue().Set(result);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019726}
19727
19728
19729TEST(NamedEnumeratorAndForIn) {
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019730 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000019731 v8::Isolate* isolate = context->GetIsolate();
19732 v8::HandleScope handle_scope(isolate);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019733 v8::Context::Scope context_scope(context.local());
19734
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000019735 v8::Handle<v8::ObjectTemplate> tmpl = v8::ObjectTemplate::New(isolate);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019736 tmpl->SetNamedPropertyHandler(Getter, NULL, NULL, NULL, Enumerator);
19737 context->Global()->Set(v8_str("o"), tmpl->NewInstance());
19738 v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
19739 "var result = []; for (var k in o) result.push(k); result"));
19740 CHECK_EQ(1, result->Length());
19741 CHECK_EQ(v8_str("universalAnswer"), result->Get(0));
19742}
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +000019743
19744
19745TEST(DefinePropertyPostDetach) {
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +000019746 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019747 v8::HandleScope scope(context->GetIsolate());
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +000019748 v8::Handle<v8::Object> proxy = context->Global();
19749 v8::Handle<v8::Function> define_property =
19750 CompileRun("(function() {"
19751 " Object.defineProperty("
19752 " this,"
19753 " 1,"
19754 " { configurable: true, enumerable: true, value: 3 });"
19755 "})").As<Function>();
19756 context->DetachGlobal();
19757 define_property->Call(proxy, 0, NULL);
19758}
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000019759
19760
19761static void InstallContextId(v8::Handle<Context> context, int id) {
19762 Context::Scope scope(context);
19763 CompileRun("Object.prototype").As<Object>()->
ulan@chromium.org0f13e742014-01-03 15:51:11 +000019764 Set(v8_str("context_id"), v8::Integer::New(context->GetIsolate(), id));
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000019765}
19766
19767
19768static void CheckContextId(v8::Handle<Object> object, int expected) {
19769 CHECK_EQ(expected, object->Get(v8_str("context_id"))->Int32Value());
19770}
19771
19772
19773THREADED_TEST(CreationContext) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000019774 v8::Isolate* isolate = CcTest::isolate();
19775 HandleScope handle_scope(isolate);
19776 Handle<Context> context1 = Context::New(isolate);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000019777 InstallContextId(context1, 1);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000019778 Handle<Context> context2 = Context::New(isolate);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000019779 InstallContextId(context2, 2);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000019780 Handle<Context> context3 = Context::New(isolate);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000019781 InstallContextId(context3, 3);
19782
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000019783 Local<v8::FunctionTemplate> tmpl = v8::FunctionTemplate::New(isolate);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000019784
19785 Local<Object> object1;
19786 Local<Function> func1;
19787 {
19788 Context::Scope scope(context1);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000019789 object1 = Object::New(isolate);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000019790 func1 = tmpl->GetFunction();
19791 }
19792
19793 Local<Object> object2;
19794 Local<Function> func2;
19795 {
19796 Context::Scope scope(context2);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000019797 object2 = Object::New(isolate);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000019798 func2 = tmpl->GetFunction();
19799 }
19800
19801 Local<Object> instance1;
19802 Local<Object> instance2;
19803
19804 {
19805 Context::Scope scope(context3);
19806 instance1 = func1->NewInstance();
19807 instance2 = func2->NewInstance();
19808 }
19809
19810 CHECK(object1->CreationContext() == context1);
19811 CheckContextId(object1, 1);
19812 CHECK(func1->CreationContext() == context1);
19813 CheckContextId(func1, 1);
19814 CHECK(instance1->CreationContext() == context1);
19815 CheckContextId(instance1, 1);
19816 CHECK(object2->CreationContext() == context2);
19817 CheckContextId(object2, 2);
19818 CHECK(func2->CreationContext() == context2);
19819 CheckContextId(func2, 2);
19820 CHECK(instance2->CreationContext() == context2);
19821 CheckContextId(instance2, 2);
19822
19823 {
19824 Context::Scope scope(context1);
19825 CHECK(object1->CreationContext() == context1);
19826 CheckContextId(object1, 1);
19827 CHECK(func1->CreationContext() == context1);
19828 CheckContextId(func1, 1);
19829 CHECK(instance1->CreationContext() == context1);
19830 CheckContextId(instance1, 1);
19831 CHECK(object2->CreationContext() == context2);
19832 CheckContextId(object2, 2);
19833 CHECK(func2->CreationContext() == context2);
19834 CheckContextId(func2, 2);
19835 CHECK(instance2->CreationContext() == context2);
19836 CheckContextId(instance2, 2);
19837 }
19838
19839 {
19840 Context::Scope scope(context2);
19841 CHECK(object1->CreationContext() == context1);
19842 CheckContextId(object1, 1);
19843 CHECK(func1->CreationContext() == context1);
19844 CheckContextId(func1, 1);
19845 CHECK(instance1->CreationContext() == context1);
19846 CheckContextId(instance1, 1);
19847 CHECK(object2->CreationContext() == context2);
19848 CheckContextId(object2, 2);
19849 CHECK(func2->CreationContext() == context2);
19850 CheckContextId(func2, 2);
19851 CHECK(instance2->CreationContext() == context2);
19852 CheckContextId(instance2, 2);
19853 }
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000019854}
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019855
19856
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +000019857THREADED_TEST(CreationContextOfJsFunction) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019858 HandleScope handle_scope(CcTest::isolate());
19859 Handle<Context> context = Context::New(CcTest::isolate());
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +000019860 InstallContextId(context, 1);
19861
19862 Local<Object> function;
19863 {
19864 Context::Scope scope(context);
19865 function = CompileRun("function foo() {}; foo").As<Object>();
19866 }
19867
19868 CHECK(function->CreationContext() == context);
19869 CheckContextId(function, 1);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +000019870}
19871
19872
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019873void HasOwnPropertyIndexedPropertyGetter(
19874 uint32_t index,
19875 const v8::PropertyCallbackInfo<v8::Value>& info) {
19876 if (index == 42) info.GetReturnValue().Set(v8_str("yes"));
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019877}
19878
19879
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019880void HasOwnPropertyNamedPropertyGetter(
19881 Local<String> property,
19882 const v8::PropertyCallbackInfo<v8::Value>& info) {
19883 if (property->Equals(v8_str("foo"))) info.GetReturnValue().Set(v8_str("yes"));
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019884}
19885
19886
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019887void HasOwnPropertyIndexedPropertyQuery(
19888 uint32_t index, const v8::PropertyCallbackInfo<v8::Integer>& info) {
19889 if (index == 42) info.GetReturnValue().Set(1);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019890}
19891
19892
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019893void HasOwnPropertyNamedPropertyQuery(
19894 Local<String> property,
19895 const v8::PropertyCallbackInfo<v8::Integer>& info) {
19896 if (property->Equals(v8_str("foo"))) info.GetReturnValue().Set(1);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019897}
19898
19899
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019900void HasOwnPropertyNamedPropertyQuery2(
19901 Local<String> property,
19902 const v8::PropertyCallbackInfo<v8::Integer>& info) {
19903 if (property->Equals(v8_str("bar"))) info.GetReturnValue().Set(1);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019904}
19905
19906
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019907void HasOwnPropertyAccessorGetter(
19908 Local<String> property,
19909 const v8::PropertyCallbackInfo<v8::Value>& info) {
19910 info.GetReturnValue().Set(v8_str("yes"));
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019911}
19912
19913
19914TEST(HasOwnProperty) {
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019915 LocalContext env;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000019916 v8::Isolate* isolate = env->GetIsolate();
19917 v8::HandleScope scope(isolate);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019918 { // Check normal properties and defined getters.
19919 Handle<Value> value = CompileRun(
19920 "function Foo() {"
19921 " this.foo = 11;"
19922 " this.__defineGetter__('baz', function() { return 1; });"
19923 "};"
19924 "function Bar() { "
19925 " this.bar = 13;"
19926 " this.__defineGetter__('bla', function() { return 2; });"
19927 "};"
19928 "Bar.prototype = new Foo();"
19929 "new Bar();");
19930 CHECK(value->IsObject());
19931 Handle<Object> object = value->ToObject();
19932 CHECK(object->Has(v8_str("foo")));
19933 CHECK(!object->HasOwnProperty(v8_str("foo")));
19934 CHECK(object->HasOwnProperty(v8_str("bar")));
19935 CHECK(object->Has(v8_str("baz")));
19936 CHECK(!object->HasOwnProperty(v8_str("baz")));
19937 CHECK(object->HasOwnProperty(v8_str("bla")));
19938 }
19939 { // Check named getter interceptors.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000019940 Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019941 templ->SetNamedPropertyHandler(HasOwnPropertyNamedPropertyGetter);
19942 Handle<Object> instance = templ->NewInstance();
19943 CHECK(!instance->HasOwnProperty(v8_str("42")));
19944 CHECK(instance->HasOwnProperty(v8_str("foo")));
19945 CHECK(!instance->HasOwnProperty(v8_str("bar")));
19946 }
19947 { // Check indexed getter interceptors.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000019948 Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019949 templ->SetIndexedPropertyHandler(HasOwnPropertyIndexedPropertyGetter);
19950 Handle<Object> instance = templ->NewInstance();
19951 CHECK(instance->HasOwnProperty(v8_str("42")));
19952 CHECK(!instance->HasOwnProperty(v8_str("43")));
19953 CHECK(!instance->HasOwnProperty(v8_str("foo")));
19954 }
19955 { // Check named query interceptors.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000019956 Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019957 templ->SetNamedPropertyHandler(0, 0, HasOwnPropertyNamedPropertyQuery);
19958 Handle<Object> instance = templ->NewInstance();
19959 CHECK(instance->HasOwnProperty(v8_str("foo")));
19960 CHECK(!instance->HasOwnProperty(v8_str("bar")));
19961 }
19962 { // Check indexed query interceptors.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000019963 Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019964 templ->SetIndexedPropertyHandler(0, 0, HasOwnPropertyIndexedPropertyQuery);
19965 Handle<Object> instance = templ->NewInstance();
19966 CHECK(instance->HasOwnProperty(v8_str("42")));
19967 CHECK(!instance->HasOwnProperty(v8_str("41")));
19968 }
19969 { // Check callbacks.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000019970 Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019971 templ->SetAccessor(v8_str("foo"), HasOwnPropertyAccessorGetter);
19972 Handle<Object> instance = templ->NewInstance();
19973 CHECK(instance->HasOwnProperty(v8_str("foo")));
19974 CHECK(!instance->HasOwnProperty(v8_str("bar")));
19975 }
19976 { // Check that query wins on disagreement.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000019977 Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019978 templ->SetNamedPropertyHandler(HasOwnPropertyNamedPropertyGetter,
19979 0,
19980 HasOwnPropertyNamedPropertyQuery2);
19981 Handle<Object> instance = templ->NewInstance();
19982 CHECK(!instance->HasOwnProperty(v8_str("foo")));
19983 CHECK(instance->HasOwnProperty(v8_str("bar")));
19984 }
19985}
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000019986
19987
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +000019988TEST(IndexedInterceptorWithStringProto) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000019989 v8::Isolate* isolate = CcTest::isolate();
19990 v8::HandleScope scope(isolate);
19991 Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +000019992 templ->SetIndexedPropertyHandler(NULL,
19993 NULL,
19994 HasOwnPropertyIndexedPropertyQuery);
19995 LocalContext context;
19996 context->Global()->Set(v8_str("obj"), templ->NewInstance());
19997 CompileRun("var s = new String('foobar'); obj.__proto__ = s;");
19998 // These should be intercepted.
19999 CHECK(CompileRun("42 in obj")->BooleanValue());
20000 CHECK(CompileRun("'42' in obj")->BooleanValue());
20001 // These should fall through to the String prototype.
20002 CHECK(CompileRun("0 in obj")->BooleanValue());
20003 CHECK(CompileRun("'0' in obj")->BooleanValue());
20004 // And these should both fail.
20005 CHECK(!CompileRun("32 in obj")->BooleanValue());
20006 CHECK(!CompileRun("'32' in obj")->BooleanValue());
20007}
20008
20009
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000020010void CheckCodeGenerationAllowed() {
20011 Handle<Value> result = CompileRun("eval('42')");
20012 CHECK_EQ(42, result->Int32Value());
20013 result = CompileRun("(function(e) { return e('42'); })(eval)");
20014 CHECK_EQ(42, result->Int32Value());
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000020015 result = CompileRun("var f = new Function('return 42'); f()");
20016 CHECK_EQ(42, result->Int32Value());
20017}
20018
20019
20020void CheckCodeGenerationDisallowed() {
20021 TryCatch try_catch;
20022
20023 Handle<Value> result = CompileRun("eval('42')");
20024 CHECK(result.IsEmpty());
20025 CHECK(try_catch.HasCaught());
20026 try_catch.Reset();
20027
20028 result = CompileRun("(function(e) { return e('42'); })(eval)");
20029 CHECK(result.IsEmpty());
20030 CHECK(try_catch.HasCaught());
20031 try_catch.Reset();
20032
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000020033 result = CompileRun("var f = new Function('return 42'); f()");
20034 CHECK(result.IsEmpty());
20035 CHECK(try_catch.HasCaught());
20036}
20037
20038
20039bool CodeGenerationAllowed(Local<Context> context) {
20040 ApiTestFuzzer::Fuzz();
20041 return true;
20042}
20043
20044
20045bool CodeGenerationDisallowed(Local<Context> context) {
20046 ApiTestFuzzer::Fuzz();
20047 return false;
20048}
20049
20050
20051THREADED_TEST(AllowCodeGenFromStrings) {
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000020052 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020053 v8::HandleScope scope(context->GetIsolate());
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000020054
ager@chromium.orgea91cc52011-05-23 06:06:11 +000020055 // eval and the Function constructor allowed by default.
jkummerow@chromium.org1145ef82012-02-02 16:21:15 +000020056 CHECK(context->IsCodeGenerationFromStringsAllowed());
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000020057 CheckCodeGenerationAllowed();
20058
ager@chromium.orgea91cc52011-05-23 06:06:11 +000020059 // Disallow eval and the Function constructor.
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000020060 context->AllowCodeGenerationFromStrings(false);
jkummerow@chromium.org1145ef82012-02-02 16:21:15 +000020061 CHECK(!context->IsCodeGenerationFromStringsAllowed());
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000020062 CheckCodeGenerationDisallowed();
20063
20064 // Allow again.
20065 context->AllowCodeGenerationFromStrings(true);
20066 CheckCodeGenerationAllowed();
20067
20068 // Disallow but setting a global callback that will allow the calls.
20069 context->AllowCodeGenerationFromStrings(false);
20070 V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationAllowed);
jkummerow@chromium.org1145ef82012-02-02 16:21:15 +000020071 CHECK(!context->IsCodeGenerationFromStringsAllowed());
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000020072 CheckCodeGenerationAllowed();
20073
20074 // Set a callback that disallows the code generation.
20075 V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationDisallowed);
jkummerow@chromium.org1145ef82012-02-02 16:21:15 +000020076 CHECK(!context->IsCodeGenerationFromStringsAllowed());
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000020077 CheckCodeGenerationDisallowed();
20078}
lrn@chromium.org1c092762011-05-09 09:42:16 +000020079
20080
ulan@chromium.org56c14af2012-09-20 12:51:09 +000020081TEST(SetErrorMessageForCodeGenFromStrings) {
ulan@chromium.org56c14af2012-09-20 12:51:09 +000020082 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020083 v8::HandleScope scope(context->GetIsolate());
ulan@chromium.org56c14af2012-09-20 12:51:09 +000020084 TryCatch try_catch;
20085
20086 Handle<String> message = v8_str("Message") ;
20087 Handle<String> expected_message = v8_str("Uncaught EvalError: Message");
20088 V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationDisallowed);
20089 context->AllowCodeGenerationFromStrings(false);
20090 context->SetErrorMessageForCodeGenerationFromStrings(message);
20091 Handle<Value> result = CompileRun("eval('42')");
20092 CHECK(result.IsEmpty());
20093 CHECK(try_catch.HasCaught());
20094 Handle<String> actual_message = try_catch.Message()->Get();
20095 CHECK(expected_message->Equals(actual_message));
20096}
20097
20098
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000020099static void NonObjectThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
lrn@chromium.org1c092762011-05-09 09:42:16 +000020100}
20101
20102
20103THREADED_TEST(CallAPIFunctionOnNonObject) {
lrn@chromium.org1c092762011-05-09 09:42:16 +000020104 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000020105 v8::Isolate* isolate = context->GetIsolate();
20106 v8::HandleScope scope(isolate);
20107 Handle<FunctionTemplate> templ =
20108 v8::FunctionTemplate::New(isolate, NonObjectThis);
lrn@chromium.org1c092762011-05-09 09:42:16 +000020109 Handle<Function> function = templ->GetFunction();
20110 context->Global()->Set(v8_str("f"), function);
20111 TryCatch try_catch;
20112 CompileRun("f.call(2)");
lrn@chromium.org1c092762011-05-09 09:42:16 +000020113}
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000020114
20115
20116// Regression test for issue 1470.
20117THREADED_TEST(ReadOnlyIndexedProperties) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000020118 v8::Isolate* isolate = CcTest::isolate();
20119 v8::HandleScope scope(isolate);
20120 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000020121
20122 LocalContext context;
20123 Local<v8::Object> obj = templ->NewInstance();
20124 context->Global()->Set(v8_str("obj"), obj);
20125 obj->Set(v8_str("1"), v8_str("DONT_CHANGE"), v8::ReadOnly);
20126 obj->Set(v8_str("1"), v8_str("foobar"));
20127 CHECK_EQ(v8_str("DONT_CHANGE"), obj->Get(v8_str("1")));
20128 obj->Set(v8_num(2), v8_str("DONT_CHANGE"), v8::ReadOnly);
20129 obj->Set(v8_num(2), v8_str("foobar"));
20130 CHECK_EQ(v8_str("DONT_CHANGE"), obj->Get(v8_num(2)));
20131
20132 // Test non-smi case.
20133 obj->Set(v8_str("2000000000"), v8_str("DONT_CHANGE"), v8::ReadOnly);
20134 obj->Set(v8_str("2000000000"), v8_str("foobar"));
20135 CHECK_EQ(v8_str("DONT_CHANGE"), obj->Get(v8_str("2000000000")));
20136}
ricow@chromium.org4f693d62011-07-04 14:01:31 +000020137
20138
20139THREADED_TEST(Regress1516) {
ricow@chromium.org4f693d62011-07-04 14:01:31 +000020140 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020141 v8::HandleScope scope(context->GetIsolate());
20142
20143 { v8::HandleScope temp_scope(context->GetIsolate());
ricow@chromium.org4f693d62011-07-04 14:01:31 +000020144 CompileRun("({'a': 0})");
20145 }
20146
20147 int elements;
20148 { i::MapCache* map_cache =
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020149 i::MapCache::cast(CcTest::i_isolate()->context()->map_cache());
ricow@chromium.org4f693d62011-07-04 14:01:31 +000020150 elements = map_cache->NumberOfElements();
20151 CHECK_LE(1, elements);
20152 }
20153
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020154 CcTest::heap()->CollectAllGarbage(
yangguo@chromium.orgd2899aa2012-06-21 11:16:20 +000020155 i::Heap::kAbortIncrementalMarkingMask);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020156 { i::Object* raw_map_cache = CcTest::i_isolate()->context()->map_cache();
20157 if (raw_map_cache != CcTest::heap()->undefined_value()) {
ricow@chromium.org4f693d62011-07-04 14:01:31 +000020158 i::MapCache* map_cache = i::MapCache::cast(raw_map_cache);
20159 CHECK_GT(elements, map_cache->NumberOfElements());
20160 }
20161 }
20162}
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020163
20164
20165static bool BlockProtoNamedSecurityTestCallback(Local<v8::Object> global,
20166 Local<Value> name,
20167 v8::AccessType type,
20168 Local<Value> data) {
20169 // Only block read access to __proto__.
20170 if (type == v8::ACCESS_GET &&
20171 name->IsString() &&
20172 name->ToString()->Length() == 9 &&
20173 name->ToString()->Utf8Length() == 9) {
20174 char buffer[10];
20175 CHECK_EQ(10, name->ToString()->WriteUtf8(buffer));
20176 return strncmp(buffer, "__proto__", 9) != 0;
20177 }
20178
20179 return true;
20180}
20181
20182
20183THREADED_TEST(Regress93759) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020184 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000020185 HandleScope scope(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020186
20187 // Template for object with security check.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000020188 Local<ObjectTemplate> no_proto_template = v8::ObjectTemplate::New(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020189 // We don't do indexing, so any callback can be used for that.
20190 no_proto_template->SetAccessCheckCallbacks(
20191 BlockProtoNamedSecurityTestCallback,
20192 IndexedSecurityTestCallback);
20193
20194 // Templates for objects with hidden prototypes and possibly security check.
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000020195 Local<FunctionTemplate> hidden_proto_template =
20196 v8::FunctionTemplate::New(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020197 hidden_proto_template->SetHiddenPrototype(true);
20198
20199 Local<FunctionTemplate> protected_hidden_proto_template =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000020200 v8::FunctionTemplate::New(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020201 protected_hidden_proto_template->InstanceTemplate()->SetAccessCheckCallbacks(
20202 BlockProtoNamedSecurityTestCallback,
20203 IndexedSecurityTestCallback);
20204 protected_hidden_proto_template->SetHiddenPrototype(true);
20205
20206 // Context for "foreign" objects used in test.
ulan@chromium.org57ff8812013-05-10 08:16:55 +000020207 Local<Context> context = v8::Context::New(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020208 context->Enter();
20209
20210 // Plain object, no security check.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000020211 Local<Object> simple_object = Object::New(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020212
20213 // Object with explicit security check.
20214 Local<Object> protected_object =
20215 no_proto_template->NewInstance();
20216
20217 // JSGlobalProxy object, always have security check.
20218 Local<Object> proxy_object =
20219 context->Global();
20220
20221 // Global object, the prototype of proxy_object. No security checks.
20222 Local<Object> global_object =
20223 proxy_object->GetPrototype()->ToObject();
20224
20225 // Hidden prototype without security check.
20226 Local<Object> hidden_prototype =
20227 hidden_proto_template->GetFunction()->NewInstance();
20228 Local<Object> object_with_hidden =
ulan@chromium.org0f13e742014-01-03 15:51:11 +000020229 Object::New(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020230 object_with_hidden->SetPrototype(hidden_prototype);
20231
20232 // Hidden prototype with security check on the hidden prototype.
20233 Local<Object> protected_hidden_prototype =
20234 protected_hidden_proto_template->GetFunction()->NewInstance();
20235 Local<Object> object_with_protected_hidden =
ulan@chromium.org0f13e742014-01-03 15:51:11 +000020236 Object::New(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020237 object_with_protected_hidden->SetPrototype(protected_hidden_prototype);
20238
20239 context->Exit();
20240
20241 // Template for object for second context. Values to test are put on it as
20242 // properties.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000020243 Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020244 global_template->Set(v8_str("simple"), simple_object);
20245 global_template->Set(v8_str("protected"), protected_object);
20246 global_template->Set(v8_str("global"), global_object);
20247 global_template->Set(v8_str("proxy"), proxy_object);
20248 global_template->Set(v8_str("hidden"), object_with_hidden);
20249 global_template->Set(v8_str("phidden"), object_with_protected_hidden);
20250
20251 LocalContext context2(NULL, global_template);
20252
20253 Local<Value> result1 = CompileRun("Object.getPrototypeOf(simple)");
20254 CHECK(result1->Equals(simple_object->GetPrototype()));
20255
20256 Local<Value> result2 = CompileRun("Object.getPrototypeOf(protected)");
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000020257 CHECK(result2->Equals(Undefined(isolate)));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020258
20259 Local<Value> result3 = CompileRun("Object.getPrototypeOf(global)");
20260 CHECK(result3->Equals(global_object->GetPrototype()));
20261
20262 Local<Value> result4 = CompileRun("Object.getPrototypeOf(proxy)");
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000020263 CHECK(result4->Equals(Undefined(isolate)));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020264
20265 Local<Value> result5 = CompileRun("Object.getPrototypeOf(hidden)");
20266 CHECK(result5->Equals(
20267 object_with_hidden->GetPrototype()->ToObject()->GetPrototype()));
20268
20269 Local<Value> result6 = CompileRun("Object.getPrototypeOf(phidden)");
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000020270 CHECK(result6->Equals(Undefined(isolate)));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020271}
20272
20273
jkummerow@chromium.org212d9642012-05-11 15:02:09 +000020274THREADED_TEST(Regress125988) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020275 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000020276 Handle<FunctionTemplate> intercept = FunctionTemplate::New(CcTest::isolate());
jkummerow@chromium.org212d9642012-05-11 15:02:09 +000020277 AddInterceptor(intercept, EmptyInterceptorGetter, EmptyInterceptorSetter);
20278 LocalContext env;
20279 env->Global()->Set(v8_str("Intercept"), intercept->GetFunction());
20280 CompileRun("var a = new Object();"
20281 "var b = new Intercept();"
20282 "var c = new Object();"
20283 "c.__proto__ = b;"
20284 "b.__proto__ = a;"
20285 "a.x = 23;"
20286 "for (var i = 0; i < 3; i++) c.x;");
20287 ExpectBoolean("c.hasOwnProperty('x')", false);
20288 ExpectInt32("c.x", 23);
20289 CompileRun("a.y = 42;"
20290 "for (var i = 0; i < 3; i++) c.x;");
20291 ExpectBoolean("c.hasOwnProperty('x')", false);
20292 ExpectInt32("c.x", 23);
20293 ExpectBoolean("c.hasOwnProperty('y')", false);
20294 ExpectInt32("c.y", 42);
20295}
20296
20297
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020298static void TestReceiver(Local<Value> expected_result,
20299 Local<Value> expected_receiver,
20300 const char* code) {
20301 Local<Value> result = CompileRun(code);
20302 CHECK(result->IsObject());
20303 CHECK(expected_receiver->Equals(result->ToObject()->Get(1)));
20304 CHECK(expected_result->Equals(result->ToObject()->Get(0)));
20305}
20306
20307
20308THREADED_TEST(ForeignFunctionReceiver) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020309 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000020310 HandleScope scope(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020311
20312 // Create two contexts with different "id" properties ('i' and 'o').
20313 // Call a function both from its own context and from a the foreign
20314 // context, and see what "this" is bound to (returning both "this"
20315 // and "this.id" for comparison).
20316
ulan@chromium.org57ff8812013-05-10 08:16:55 +000020317 Local<Context> foreign_context = v8::Context::New(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020318 foreign_context->Enter();
20319 Local<Value> foreign_function =
20320 CompileRun("function func() { return { 0: this.id, "
20321 " 1: this, "
20322 " toString: function() { "
20323 " return this[0];"
20324 " }"
20325 " };"
20326 "}"
20327 "var id = 'i';"
20328 "func;");
20329 CHECK(foreign_function->IsFunction());
20330 foreign_context->Exit();
20331
20332 LocalContext context;
20333
20334 Local<String> password = v8_str("Password");
20335 // Don't get hit by security checks when accessing foreign_context's
20336 // global receiver (aka. global proxy).
20337 context->SetSecurityToken(password);
20338 foreign_context->SetSecurityToken(password);
20339
20340 Local<String> i = v8_str("i");
20341 Local<String> o = v8_str("o");
20342 Local<String> id = v8_str("id");
20343
20344 CompileRun("function ownfunc() { return { 0: this.id, "
20345 " 1: this, "
20346 " toString: function() { "
20347 " return this[0];"
20348 " }"
20349 " };"
20350 "}"
20351 "var id = 'o';"
20352 "ownfunc");
20353 context->Global()->Set(v8_str("func"), foreign_function);
20354
20355 // Sanity check the contexts.
20356 CHECK(i->Equals(foreign_context->Global()->Get(id)));
20357 CHECK(o->Equals(context->Global()->Get(id)));
20358
20359 // Checking local function's receiver.
20360 // Calling function using its call/apply methods.
20361 TestReceiver(o, context->Global(), "ownfunc.call()");
20362 TestReceiver(o, context->Global(), "ownfunc.apply()");
20363 // Making calls through built-in functions.
20364 TestReceiver(o, context->Global(), "[1].map(ownfunc)[0]");
20365 CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/,ownfunc)[1]")));
20366 CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/g,ownfunc)[1]")));
20367 CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/g,ownfunc)[3]")));
20368 // Calling with environment record as base.
20369 TestReceiver(o, context->Global(), "ownfunc()");
20370 // Calling with no base.
20371 TestReceiver(o, context->Global(), "(1,ownfunc)()");
20372
20373 // Checking foreign function return value.
20374 // Calling function using its call/apply methods.
20375 TestReceiver(i, foreign_context->Global(), "func.call()");
20376 TestReceiver(i, foreign_context->Global(), "func.apply()");
20377 // Calling function using another context's call/apply methods.
20378 TestReceiver(i, foreign_context->Global(),
20379 "Function.prototype.call.call(func)");
20380 TestReceiver(i, foreign_context->Global(),
20381 "Function.prototype.call.apply(func)");
20382 TestReceiver(i, foreign_context->Global(),
20383 "Function.prototype.apply.call(func)");
20384 TestReceiver(i, foreign_context->Global(),
20385 "Function.prototype.apply.apply(func)");
20386 // Making calls through built-in functions.
20387 TestReceiver(i, foreign_context->Global(), "[1].map(func)[0]");
20388 // ToString(func()) is func()[0], i.e., the returned this.id.
20389 CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/,func)[1]")));
20390 CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/g,func)[1]")));
20391 CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/g,func)[3]")));
20392
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020393 // Calling with environment record as base.
rossberg@chromium.org9ed27462014-01-07 14:16:41 +000020394 TestReceiver(i, foreign_context->Global(), "func()");
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020395 // Calling with no base.
rossberg@chromium.org9ed27462014-01-07 14:16:41 +000020396 TestReceiver(i, foreign_context->Global(), "(1,func)()");
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020397}
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020398
20399
20400uint8_t callback_fired = 0;
20401
20402
20403void CallCompletedCallback1() {
20404 i::OS::Print("Firing callback 1.\n");
20405 callback_fired ^= 1; // Toggle first bit.
20406}
20407
20408
20409void CallCompletedCallback2() {
20410 i::OS::Print("Firing callback 2.\n");
20411 callback_fired ^= 2; // Toggle second bit.
20412}
20413
20414
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000020415void RecursiveCall(const v8::FunctionCallbackInfo<v8::Value>& args) {
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020416 int32_t level = args[0]->Int32Value();
20417 if (level < 3) {
20418 level++;
20419 i::OS::Print("Entering recursion level %d.\n", level);
20420 char script[64];
20421 i::Vector<char> script_vector(script, sizeof(script));
20422 i::OS::SNPrintF(script_vector, "recursion(%d)", level);
20423 CompileRun(script_vector.start());
20424 i::OS::Print("Leaving recursion level %d.\n", level);
20425 CHECK_EQ(0, callback_fired);
20426 } else {
20427 i::OS::Print("Recursion ends.\n");
20428 CHECK_EQ(0, callback_fired);
20429 }
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020430}
20431
20432
20433TEST(CallCompletedCallback) {
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020434 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020435 v8::HandleScope scope(env->GetIsolate());
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020436 v8::Handle<v8::FunctionTemplate> recursive_runtime =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000020437 v8::FunctionTemplate::New(env->GetIsolate(), RecursiveCall);
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020438 env->Global()->Set(v8_str("recursion"),
20439 recursive_runtime->GetFunction());
20440 // Adding the same callback a second time has no effect.
20441 v8::V8::AddCallCompletedCallback(CallCompletedCallback1);
20442 v8::V8::AddCallCompletedCallback(CallCompletedCallback1);
20443 v8::V8::AddCallCompletedCallback(CallCompletedCallback2);
20444 i::OS::Print("--- Script (1) ---\n");
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000020445 Local<Script> script = v8::Script::Compile(
20446 v8::String::NewFromUtf8(env->GetIsolate(), "recursion(0)"));
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020447 script->Run();
20448 CHECK_EQ(3, callback_fired);
20449
20450 i::OS::Print("\n--- Script (2) ---\n");
20451 callback_fired = 0;
20452 v8::V8::RemoveCallCompletedCallback(CallCompletedCallback1);
20453 script->Run();
20454 CHECK_EQ(2, callback_fired);
20455
20456 i::OS::Print("\n--- Function ---\n");
20457 callback_fired = 0;
20458 Local<Function> recursive_function =
20459 Local<Function>::Cast(env->Global()->Get(v8_str("recursion")));
20460 v8::Handle<Value> args[] = { v8_num(0) };
20461 recursive_function->Call(env->Global(), 1, args);
20462 CHECK_EQ(2, callback_fired);
20463}
20464
20465
20466void CallCompletedCallbackNoException() {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020467 v8::HandleScope scope(CcTest::isolate());
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020468 CompileRun("1+1;");
20469}
20470
20471
20472void CallCompletedCallbackException() {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020473 v8::HandleScope scope(CcTest::isolate());
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020474 CompileRun("throw 'second exception';");
20475}
20476
20477
20478TEST(CallCompletedCallbackOneException) {
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020479 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020480 v8::HandleScope scope(env->GetIsolate());
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020481 v8::V8::AddCallCompletedCallback(CallCompletedCallbackNoException);
20482 CompileRun("throw 'exception';");
20483}
20484
20485
20486TEST(CallCompletedCallbackTwoExceptions) {
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020487 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020488 v8::HandleScope scope(env->GetIsolate());
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020489 v8::V8::AddCallCompletedCallback(CallCompletedCallbackException);
20490 CompileRun("throw 'first exception';");
20491}
ulan@chromium.org812308e2012-02-29 15:58:45 +000020492
20493
20494static int probes_counter = 0;
20495static int misses_counter = 0;
20496static int updates_counter = 0;
20497
20498
20499static int* LookupCounter(const char* name) {
20500 if (strcmp(name, "c:V8.MegamorphicStubCacheProbes") == 0) {
20501 return &probes_counter;
20502 } else if (strcmp(name, "c:V8.MegamorphicStubCacheMisses") == 0) {
20503 return &misses_counter;
20504 } else if (strcmp(name, "c:V8.MegamorphicStubCacheUpdates") == 0) {
20505 return &updates_counter;
20506 }
20507 return NULL;
20508}
20509
20510
20511static const char* kMegamorphicTestProgram =
20512 "function ClassA() { };"
20513 "function ClassB() { };"
20514 "ClassA.prototype.foo = function() { };"
20515 "ClassB.prototype.foo = function() { };"
20516 "function fooify(obj) { obj.foo(); };"
20517 "var a = new ClassA();"
20518 "var b = new ClassB();"
20519 "for (var i = 0; i < 10000; i++) {"
20520 " fooify(a);"
20521 " fooify(b);"
20522 "}";
20523
20524
20525static void StubCacheHelper(bool primary) {
20526 V8::SetCounterFunction(LookupCounter);
20527 USE(kMegamorphicTestProgram);
20528#ifdef DEBUG
20529 i::FLAG_native_code_counters = true;
20530 if (primary) {
20531 i::FLAG_test_primary_stub_cache = true;
20532 } else {
20533 i::FLAG_test_secondary_stub_cache = true;
20534 }
20535 i::FLAG_crankshaft = false;
ulan@chromium.org812308e2012-02-29 15:58:45 +000020536 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020537 v8::HandleScope scope(env->GetIsolate());
ulan@chromium.org812308e2012-02-29 15:58:45 +000020538 int initial_probes = probes_counter;
20539 int initial_misses = misses_counter;
20540 int initial_updates = updates_counter;
20541 CompileRun(kMegamorphicTestProgram);
20542 int probes = probes_counter - initial_probes;
20543 int misses = misses_counter - initial_misses;
20544 int updates = updates_counter - initial_updates;
20545 CHECK_LT(updates, 10);
20546 CHECK_LT(misses, 10);
machenbach@chromium.orga03ba1e2014-02-01 08:54:43 +000020547 // TODO(verwaest): Update this test to overflow the degree of polymorphism
20548 // before megamorphism. The number of probes will only work once we teach the
20549 // serializer to embed references to counters in the stubs, given that the
20550 // megamorphic_stub_cache_probes is updated in a snapshot-generated stub.
20551 CHECK_GE(probes, 0);
ulan@chromium.org812308e2012-02-29 15:58:45 +000020552#endif
20553}
20554
20555
20556TEST(SecondaryStubCache) {
20557 StubCacheHelper(true);
20558}
20559
20560
20561TEST(PrimaryStubCache) {
20562 StubCacheHelper(false);
20563}
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020564
20565
verwaest@chromium.org057bd502013-11-06 12:03:29 +000020566static int cow_arrays_created_runtime = 0;
20567
20568
20569static int* LookupCounterCOWArrays(const char* name) {
20570 if (strcmp(name, "c:V8.COWArraysCreatedRuntime") == 0) {
20571 return &cow_arrays_created_runtime;
20572 }
20573 return NULL;
20574}
20575
20576
20577TEST(CheckCOWArraysCreatedRuntimeCounter) {
20578 V8::SetCounterFunction(LookupCounterCOWArrays);
20579#ifdef DEBUG
20580 i::FLAG_native_code_counters = true;
20581 LocalContext env;
20582 v8::HandleScope scope(env->GetIsolate());
20583 int initial_cow_arrays = cow_arrays_created_runtime;
20584 CompileRun("var o = [1, 2, 3];");
20585 CHECK_EQ(1, cow_arrays_created_runtime - initial_cow_arrays);
20586 CompileRun("var o = {foo: [4, 5, 6], bar: [3, 0]};");
20587 CHECK_EQ(3, cow_arrays_created_runtime - initial_cow_arrays);
20588 CompileRun("var o = {foo: [1, 2, 3, [4, 5, 6]], bar: 'hi'};");
20589 CHECK_EQ(4, cow_arrays_created_runtime - initial_cow_arrays);
20590#endif
20591}
20592
20593
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020594TEST(StaticGetters) {
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020595 LocalContext context;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020596 i::Factory* factory = CcTest::i_isolate()->factory();
20597 v8::Isolate* isolate = CcTest::isolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020598 v8::HandleScope scope(isolate);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000020599 i::Handle<i::Object> undefined_value = factory->undefined_value();
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020600 CHECK(*v8::Utils::OpenHandle(*v8::Undefined(isolate)) == *undefined_value);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000020601 i::Handle<i::Object> null_value = factory->null_value();
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020602 CHECK(*v8::Utils::OpenHandle(*v8::Null(isolate)) == *null_value);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000020603 i::Handle<i::Object> true_value = factory->true_value();
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020604 CHECK(*v8::Utils::OpenHandle(*v8::True(isolate)) == *true_value);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000020605 i::Handle<i::Object> false_value = factory->false_value();
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020606 CHECK(*v8::Utils::OpenHandle(*v8::False(isolate)) == *false_value);
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020607}
20608
20609
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020610UNINITIALIZED_TEST(IsolateEmbedderData) {
20611 CcTest::DisableAutomaticDispose();
20612 v8::Isolate* isolate = v8::Isolate::New();
20613 isolate->Enter();
hpayer@chromium.orgc5d49712013-09-11 08:25:48 +000020614 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
machenbach@chromium.org7ff76072013-11-21 09:47:43 +000020615 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
20616 CHECK_EQ(NULL, isolate->GetData(slot));
20617 CHECK_EQ(NULL, i_isolate->GetData(slot));
20618 }
20619 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
20620 void* data = reinterpret_cast<void*>(0xacce55ed + slot);
20621 isolate->SetData(slot, data);
20622 }
20623 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
20624 void* data = reinterpret_cast<void*>(0xacce55ed + slot);
20625 CHECK_EQ(data, isolate->GetData(slot));
20626 CHECK_EQ(data, i_isolate->GetData(slot));
20627 }
20628 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
20629 void* data = reinterpret_cast<void*>(0xdecea5ed + slot);
20630 isolate->SetData(slot, data);
20631 }
20632 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
20633 void* data = reinterpret_cast<void*>(0xdecea5ed + slot);
20634 CHECK_EQ(data, isolate->GetData(slot));
20635 CHECK_EQ(data, i_isolate->GetData(slot));
20636 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020637 isolate->Exit();
20638 isolate->Dispose();
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020639}
20640
20641
20642TEST(StringEmpty) {
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020643 LocalContext context;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020644 i::Factory* factory = CcTest::i_isolate()->factory();
20645 v8::Isolate* isolate = CcTest::isolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020646 v8::HandleScope scope(isolate);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000020647 i::Handle<i::Object> empty_string = factory->empty_string();
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020648 CHECK(*v8::Utils::OpenHandle(*v8::String::Empty(isolate)) == *empty_string);
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020649}
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020650
20651
20652static int instance_checked_getter_count = 0;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000020653static void InstanceCheckedGetter(
20654 Local<String> name,
20655 const v8::PropertyCallbackInfo<v8::Value>& info) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020656 CHECK_EQ(name, v8_str("foo"));
20657 instance_checked_getter_count++;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000020658 info.GetReturnValue().Set(v8_num(11));
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020659}
20660
20661
20662static int instance_checked_setter_count = 0;
20663static void InstanceCheckedSetter(Local<String> name,
20664 Local<Value> value,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000020665 const v8::PropertyCallbackInfo<void>& info) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020666 CHECK_EQ(name, v8_str("foo"));
20667 CHECK_EQ(value, v8_num(23));
20668 instance_checked_setter_count++;
20669}
20670
20671
20672static void CheckInstanceCheckedResult(int getters,
20673 int setters,
20674 bool expects_callbacks,
20675 TryCatch* try_catch) {
20676 if (expects_callbacks) {
20677 CHECK(!try_catch->HasCaught());
20678 CHECK_EQ(getters, instance_checked_getter_count);
20679 CHECK_EQ(setters, instance_checked_setter_count);
20680 } else {
20681 CHECK(try_catch->HasCaught());
20682 CHECK_EQ(0, instance_checked_getter_count);
20683 CHECK_EQ(0, instance_checked_setter_count);
20684 }
20685 try_catch->Reset();
20686}
20687
20688
20689static void CheckInstanceCheckedAccessors(bool expects_callbacks) {
20690 instance_checked_getter_count = 0;
20691 instance_checked_setter_count = 0;
20692 TryCatch try_catch;
20693
20694 // Test path through generic runtime code.
20695 CompileRun("obj.foo");
20696 CheckInstanceCheckedResult(1, 0, expects_callbacks, &try_catch);
20697 CompileRun("obj.foo = 23");
20698 CheckInstanceCheckedResult(1, 1, expects_callbacks, &try_catch);
20699
20700 // Test path through generated LoadIC and StoredIC.
20701 CompileRun("function test_get(o) { o.foo; }"
20702 "test_get(obj);");
20703 CheckInstanceCheckedResult(2, 1, expects_callbacks, &try_catch);
20704 CompileRun("test_get(obj);");
20705 CheckInstanceCheckedResult(3, 1, expects_callbacks, &try_catch);
20706 CompileRun("test_get(obj);");
20707 CheckInstanceCheckedResult(4, 1, expects_callbacks, &try_catch);
20708 CompileRun("function test_set(o) { o.foo = 23; }"
20709 "test_set(obj);");
20710 CheckInstanceCheckedResult(4, 2, expects_callbacks, &try_catch);
20711 CompileRun("test_set(obj);");
20712 CheckInstanceCheckedResult(4, 3, expects_callbacks, &try_catch);
20713 CompileRun("test_set(obj);");
20714 CheckInstanceCheckedResult(4, 4, expects_callbacks, &try_catch);
20715
20716 // Test path through optimized code.
20717 CompileRun("%OptimizeFunctionOnNextCall(test_get);"
20718 "test_get(obj);");
20719 CheckInstanceCheckedResult(5, 4, expects_callbacks, &try_catch);
20720 CompileRun("%OptimizeFunctionOnNextCall(test_set);"
20721 "test_set(obj);");
20722 CheckInstanceCheckedResult(5, 5, expects_callbacks, &try_catch);
20723
20724 // Cleanup so that closures start out fresh in next check.
20725 CompileRun("%DeoptimizeFunction(test_get);"
20726 "%ClearFunctionTypeFeedback(test_get);"
20727 "%DeoptimizeFunction(test_set);"
20728 "%ClearFunctionTypeFeedback(test_set);");
20729}
20730
20731
20732THREADED_TEST(InstanceCheckOnInstanceAccessor) {
20733 v8::internal::FLAG_allow_natives_syntax = true;
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020734 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020735 v8::HandleScope scope(context->GetIsolate());
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020736
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000020737 Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020738 Local<ObjectTemplate> inst = templ->InstanceTemplate();
20739 inst->SetAccessor(v8_str("foo"),
20740 InstanceCheckedGetter, InstanceCheckedSetter,
20741 Handle<Value>(),
20742 v8::DEFAULT,
20743 v8::None,
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000020744 v8::AccessorSignature::New(context->GetIsolate(), templ));
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020745 context->Global()->Set(v8_str("f"), templ->GetFunction());
20746
20747 printf("Testing positive ...\n");
20748 CompileRun("var obj = new f();");
20749 CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
20750 CheckInstanceCheckedAccessors(true);
20751
20752 printf("Testing negative ...\n");
20753 CompileRun("var obj = {};"
20754 "obj.__proto__ = new f();");
20755 CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
20756 CheckInstanceCheckedAccessors(false);
20757}
20758
20759
20760THREADED_TEST(InstanceCheckOnInstanceAccessorWithInterceptor) {
20761 v8::internal::FLAG_allow_natives_syntax = true;
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020762 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020763 v8::HandleScope scope(context->GetIsolate());
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020764
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000020765 Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020766 Local<ObjectTemplate> inst = templ->InstanceTemplate();
20767 AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter);
20768 inst->SetAccessor(v8_str("foo"),
20769 InstanceCheckedGetter, InstanceCheckedSetter,
20770 Handle<Value>(),
20771 v8::DEFAULT,
20772 v8::None,
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000020773 v8::AccessorSignature::New(context->GetIsolate(), templ));
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020774 context->Global()->Set(v8_str("f"), templ->GetFunction());
20775
20776 printf("Testing positive ...\n");
20777 CompileRun("var obj = new f();");
20778 CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
20779 CheckInstanceCheckedAccessors(true);
20780
20781 printf("Testing negative ...\n");
20782 CompileRun("var obj = {};"
20783 "obj.__proto__ = new f();");
20784 CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
20785 CheckInstanceCheckedAccessors(false);
20786}
20787
20788
20789THREADED_TEST(InstanceCheckOnPrototypeAccessor) {
20790 v8::internal::FLAG_allow_natives_syntax = true;
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020791 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020792 v8::HandleScope scope(context->GetIsolate());
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020793
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000020794 Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020795 Local<ObjectTemplate> proto = templ->PrototypeTemplate();
20796 proto->SetAccessor(v8_str("foo"),
20797 InstanceCheckedGetter, InstanceCheckedSetter,
20798 Handle<Value>(),
20799 v8::DEFAULT,
20800 v8::None,
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000020801 v8::AccessorSignature::New(context->GetIsolate(), templ));
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020802 context->Global()->Set(v8_str("f"), templ->GetFunction());
20803
20804 printf("Testing positive ...\n");
20805 CompileRun("var obj = new f();");
20806 CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
20807 CheckInstanceCheckedAccessors(true);
20808
20809 printf("Testing negative ...\n");
20810 CompileRun("var obj = {};"
20811 "obj.__proto__ = new f();");
20812 CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
20813 CheckInstanceCheckedAccessors(false);
20814
20815 printf("Testing positive with modified prototype chain ...\n");
20816 CompileRun("var obj = new f();"
20817 "var pro = {};"
20818 "pro.__proto__ = obj.__proto__;"
20819 "obj.__proto__ = pro;");
20820 CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
20821 CheckInstanceCheckedAccessors(true);
20822}
20823
20824
20825TEST(TryFinallyMessage) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020826 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020827 v8::HandleScope scope(context->GetIsolate());
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020828 {
20829 // Test that the original error message is not lost if there is a
20830 // recursive call into Javascript is done in the finally block, e.g. to
20831 // initialize an IC. (crbug.com/129171)
20832 TryCatch try_catch;
20833 const char* trigger_ic =
20834 "try { \n"
20835 " throw new Error('test'); \n"
20836 "} finally { \n"
20837 " var x = 0; \n"
20838 " x++; \n" // Trigger an IC initialization here.
20839 "} \n";
20840 CompileRun(trigger_ic);
20841 CHECK(try_catch.HasCaught());
20842 Local<Message> message = try_catch.Message();
20843 CHECK(!message.IsEmpty());
20844 CHECK_EQ(2, message->GetLineNumber());
20845 }
20846
20847 {
20848 // Test that the original exception message is indeed overwritten if
20849 // a new error is thrown in the finally block.
20850 TryCatch try_catch;
20851 const char* throw_again =
20852 "try { \n"
20853 " throw new Error('test'); \n"
20854 "} finally { \n"
20855 " var x = 0; \n"
20856 " x++; \n"
20857 " throw new Error('again'); \n" // This is the new uncaught error.
20858 "} \n";
20859 CompileRun(throw_again);
20860 CHECK(try_catch.HasCaught());
20861 Local<Message> message = try_catch.Message();
20862 CHECK(!message.IsEmpty());
20863 CHECK_EQ(6, message->GetLineNumber());
20864 }
20865}
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000020866
20867
erik.corry@gmail.com88767242012-08-08 14:43:45 +000020868static void Helper137002(bool do_store,
20869 bool polymorphic,
20870 bool remove_accessor,
20871 bool interceptor) {
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000020872 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000020873 Local<ObjectTemplate> templ = ObjectTemplate::New(context->GetIsolate());
erik.corry@gmail.com88767242012-08-08 14:43:45 +000020874 if (interceptor) {
20875 templ->SetNamedPropertyHandler(FooGetInterceptor, FooSetInterceptor);
20876 } else {
20877 templ->SetAccessor(v8_str("foo"),
20878 GetterWhichReturns42,
20879 SetterWhichSetsYOnThisTo23);
20880 }
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000020881 context->Global()->Set(v8_str("obj"), templ->NewInstance());
20882
20883 // Turn monomorphic on slow object with native accessor, then turn
20884 // polymorphic, finally optimize to create negative lookup and fail.
erik.corry@gmail.com88767242012-08-08 14:43:45 +000020885 CompileRun(do_store ?
20886 "function f(x) { x.foo = void 0; }" :
20887 "function f(x) { return x.foo; }");
20888 CompileRun("obj.y = void 0;");
20889 if (!interceptor) {
20890 CompileRun("%OptimizeObjectForAddingMultipleProperties(obj, 1);");
20891 }
20892 CompileRun("obj.__proto__ = null;"
20893 "f(obj); f(obj); f(obj);");
20894 if (polymorphic) {
20895 CompileRun("f({});");
20896 }
20897 CompileRun("obj.y = void 0;"
20898 "%OptimizeFunctionOnNextCall(f);");
20899 if (remove_accessor) {
20900 CompileRun("delete obj.foo;");
20901 }
20902 CompileRun("var result = f(obj);");
20903 if (do_store) {
20904 CompileRun("result = obj.y;");
20905 }
20906 if (remove_accessor && !interceptor) {
20907 CHECK(context->Global()->Get(v8_str("result"))->IsUndefined());
20908 } else {
20909 CHECK_EQ(do_store ? 23 : 42,
20910 context->Global()->Get(v8_str("result"))->Int32Value());
20911 }
20912}
20913
20914
20915THREADED_TEST(Regress137002a) {
20916 i::FLAG_allow_natives_syntax = true;
20917 i::FLAG_compilation_cache = false;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020918 v8::HandleScope scope(CcTest::isolate());
erik.corry@gmail.com88767242012-08-08 14:43:45 +000020919 for (int i = 0; i < 16; i++) {
20920 Helper137002(i & 8, i & 4, i & 2, i & 1);
20921 }
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000020922}
20923
20924
20925THREADED_TEST(Regress137002b) {
20926 i::FLAG_allow_natives_syntax = true;
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000020927 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000020928 v8::Isolate* isolate = context->GetIsolate();
20929 v8::HandleScope scope(isolate);
20930 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000020931 templ->SetAccessor(v8_str("foo"),
20932 GetterWhichReturns42,
20933 SetterWhichSetsYOnThisTo23);
20934 context->Global()->Set(v8_str("obj"), templ->NewInstance());
20935
20936 // Turn monomorphic on slow object with native accessor, then just
20937 // delete the property and fail.
erik.corry@gmail.com88767242012-08-08 14:43:45 +000020938 CompileRun("function load(x) { return x.foo; }"
20939 "function store(x) { x.foo = void 0; }"
20940 "function keyed_load(x, key) { return x[key]; }"
20941 // Second version of function has a different source (add void 0)
20942 // so that it does not share code with the first version. This
20943 // ensures that the ICs are monomorphic.
20944 "function load2(x) { void 0; return x.foo; }"
20945 "function store2(x) { void 0; x.foo = void 0; }"
20946 "function keyed_load2(x, key) { void 0; return x[key]; }"
20947
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000020948 "obj.y = void 0;"
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000020949 "obj.__proto__ = null;"
erik.corry@gmail.com88767242012-08-08 14:43:45 +000020950 "var subobj = {};"
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000020951 "subobj.y = void 0;"
erik.corry@gmail.com88767242012-08-08 14:43:45 +000020952 "subobj.__proto__ = obj;"
20953 "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
20954
20955 // Make the ICs monomorphic.
20956 "load(obj); load(obj);"
20957 "load2(subobj); load2(subobj);"
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000020958 "store(obj); store(obj);"
20959 "store2(subobj); store2(subobj);"
erik.corry@gmail.com88767242012-08-08 14:43:45 +000020960 "keyed_load(obj, 'foo'); keyed_load(obj, 'foo');"
20961 "keyed_load2(subobj, 'foo'); keyed_load2(subobj, 'foo');"
20962
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000020963 // Actually test the shiny new ICs and better not crash. This
20964 // serves as a regression test for issue 142088 as well.
20965 "load(obj);"
20966 "load2(subobj);"
20967 "store(obj);"
20968 "store2(subobj);"
20969 "keyed_load(obj, 'foo');"
20970 "keyed_load2(subobj, 'foo');"
20971
erik.corry@gmail.com88767242012-08-08 14:43:45 +000020972 // Delete the accessor. It better not be called any more now.
20973 "delete obj.foo;"
20974 "obj.y = void 0;"
20975 "subobj.y = void 0;"
20976
20977 "var load_result = load(obj);"
20978 "var load_result2 = load2(subobj);"
20979 "var keyed_load_result = keyed_load(obj, 'foo');"
20980 "var keyed_load_result2 = keyed_load2(subobj, 'foo');"
20981 "store(obj);"
20982 "store2(subobj);"
20983 "var y_from_obj = obj.y;"
20984 "var y_from_subobj = subobj.y;");
20985 CHECK(context->Global()->Get(v8_str("load_result"))->IsUndefined());
20986 CHECK(context->Global()->Get(v8_str("load_result2"))->IsUndefined());
20987 CHECK(context->Global()->Get(v8_str("keyed_load_result"))->IsUndefined());
20988 CHECK(context->Global()->Get(v8_str("keyed_load_result2"))->IsUndefined());
20989 CHECK(context->Global()->Get(v8_str("y_from_obj"))->IsUndefined());
20990 CHECK(context->Global()->Get(v8_str("y_from_subobj"))->IsUndefined());
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000020991}
verwaest@chromium.org753aee42012-07-17 16:15:42 +000020992
20993
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000020994THREADED_TEST(Regress142088) {
20995 i::FLAG_allow_natives_syntax = true;
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000020996 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000020997 v8::Isolate* isolate = context->GetIsolate();
20998 v8::HandleScope scope(isolate);
20999 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000021000 templ->SetAccessor(v8_str("foo"),
21001 GetterWhichReturns42,
21002 SetterWhichSetsYOnThisTo23);
21003 context->Global()->Set(v8_str("obj"), templ->NewInstance());
21004
21005 CompileRun("function load(x) { return x.foo; }"
21006 "var o = Object.create(obj);"
21007 "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
21008 "load(o); load(o); load(o); load(o);");
21009}
21010
21011
verwaest@chromium.org753aee42012-07-17 16:15:42 +000021012THREADED_TEST(Regress137496) {
21013 i::FLAG_expose_gc = true;
verwaest@chromium.org753aee42012-07-17 16:15:42 +000021014 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000021015 v8::HandleScope scope(context->GetIsolate());
verwaest@chromium.org753aee42012-07-17 16:15:42 +000021016
21017 // Compile a try-finally clause where the finally block causes a GC
21018 // while there still is a message pending for external reporting.
21019 TryCatch try_catch;
21020 try_catch.SetVerbose(true);
21021 CompileRun("try { throw new Error(); } finally { gc(); }");
21022 CHECK(try_catch.HasCaught());
21023}
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000021024
21025
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000021026THREADED_TEST(Regress149912) {
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000021027 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000021028 v8::HandleScope scope(context->GetIsolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000021029 Handle<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000021030 AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter);
21031 context->Global()->Set(v8_str("Bug"), templ->GetFunction());
21032 CompileRun("Number.prototype.__proto__ = new Bug; var x = 0; x.foo();");
21033}
21034
21035
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000021036THREADED_TEST(Regress157124) {
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000021037 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000021038 v8::Isolate* isolate = context->GetIsolate();
21039 v8::HandleScope scope(isolate);
21040 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000021041 Local<Object> obj = templ->NewInstance();
21042 obj->GetIdentityHash();
21043 obj->DeleteHiddenValue(v8_str("Bug"));
21044}
21045
21046
ulan@chromium.org6e196bf2013-03-13 09:38:22 +000021047THREADED_TEST(Regress2535) {
21048 i::FLAG_harmony_collections = true;
ulan@chromium.org6e196bf2013-03-13 09:38:22 +000021049 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000021050 v8::HandleScope scope(context->GetIsolate());
ulan@chromium.org6e196bf2013-03-13 09:38:22 +000021051 Local<Value> set_value = CompileRun("new Set();");
danno@chromium.orgf95d4b92013-06-13 14:40:17 +000021052 Local<Object> set_object(Local<Object>::Cast(set_value));
ulan@chromium.org6e196bf2013-03-13 09:38:22 +000021053 CHECK_EQ(0, set_object->InternalFieldCount());
21054 Local<Value> map_value = CompileRun("new Map();");
danno@chromium.orgf95d4b92013-06-13 14:40:17 +000021055 Local<Object> map_object(Local<Object>::Cast(map_value));
ulan@chromium.org6e196bf2013-03-13 09:38:22 +000021056 CHECK_EQ(0, map_object->InternalFieldCount());
21057}
21058
21059
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000021060THREADED_TEST(Regress2746) {
21061 LocalContext context;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000021062 v8::Isolate* isolate = context->GetIsolate();
21063 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000021064 Local<Object> obj = Object::New(isolate);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000021065 Local<String> key = String::NewFromUtf8(context->GetIsolate(), "key");
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000021066 obj->SetHiddenValue(key, v8::Undefined(isolate));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000021067 Local<Value> value = obj->GetHiddenValue(key);
21068 CHECK(!value.IsEmpty());
21069 CHECK(value->IsUndefined());
21070}
21071
21072
jkummerow@chromium.org10480472013-07-17 08:22:15 +000021073THREADED_TEST(Regress260106) {
21074 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000021075 v8::Isolate* isolate = context->GetIsolate();
21076 v8::HandleScope scope(isolate);
21077 Local<FunctionTemplate> templ = FunctionTemplate::New(isolate,
21078 DummyCallHandler);
jkummerow@chromium.org10480472013-07-17 08:22:15 +000021079 CompileRun("for (var i = 0; i < 128; i++) Object.prototype[i] = 0;");
21080 Local<Function> function = templ->GetFunction();
21081 CHECK(!function.IsEmpty());
21082 CHECK(function->IsFunction());
21083}
21084
21085
danno@chromium.org59400602013-08-13 17:09:37 +000021086THREADED_TEST(JSONParseObject) {
21087 LocalContext context;
21088 HandleScope scope(context->GetIsolate());
21089 Local<Value> obj = v8::JSON::Parse(v8_str("{\"x\":42}"));
21090 Handle<Object> global = context->Global();
21091 global->Set(v8_str("obj"), obj);
21092 ExpectString("JSON.stringify(obj)", "{\"x\":42}");
21093}
21094
21095
21096THREADED_TEST(JSONParseNumber) {
21097 LocalContext context;
21098 HandleScope scope(context->GetIsolate());
21099 Local<Value> obj = v8::JSON::Parse(v8_str("42"));
21100 Handle<Object> global = context->Global();
21101 global->Set(v8_str("obj"), obj);
21102 ExpectString("JSON.stringify(obj)", "42");
21103}
21104
21105
verwaest@chromium.org662436e2013-08-28 08:41:27 +000021106#if V8_OS_POSIX
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000021107class ThreadInterruptTest {
21108 public:
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000021109 ThreadInterruptTest() : sem_(0), sem_value_(0) { }
21110 ~ThreadInterruptTest() {}
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000021111
21112 void RunTest() {
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000021113 InterruptThread i_thread(this);
21114 i_thread.Start();
21115
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000021116 sem_.Wait();
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000021117 CHECK_EQ(kExpectedValue, sem_value_);
21118 }
21119
21120 private:
21121 static const int kExpectedValue = 1;
21122
21123 class InterruptThread : public i::Thread {
21124 public:
21125 explicit InterruptThread(ThreadInterruptTest* test)
21126 : Thread("InterruptThread"), test_(test) {}
21127
21128 virtual void Run() {
21129 struct sigaction action;
21130
21131 // Ensure that we'll enter waiting condition
21132 i::OS::Sleep(100);
21133
21134 // Setup signal handler
21135 memset(&action, 0, sizeof(action));
21136 action.sa_handler = SignalHandler;
21137 sigaction(SIGCHLD, &action, NULL);
21138
21139 // Send signal
21140 kill(getpid(), SIGCHLD);
21141
21142 // Ensure that if wait has returned because of error
21143 i::OS::Sleep(100);
21144
21145 // Set value and signal semaphore
21146 test_->sem_value_ = 1;
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000021147 test_->sem_.Signal();
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000021148 }
21149
21150 static void SignalHandler(int signal) {
21151 }
21152
21153 private:
21154 ThreadInterruptTest* test_;
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000021155 };
21156
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000021157 i::Semaphore sem_;
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000021158 volatile int sem_value_;
21159};
21160
21161
21162THREADED_TEST(SemaphoreInterruption) {
21163 ThreadInterruptTest().RunTest();
21164}
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000021165
danno@chromium.org169691d2013-07-15 08:01:13 +000021166
hpayer@chromium.orgea9b8ba2013-12-20 19:22:39 +000021167#endif // V8_OS_POSIX
21168
21169
danno@chromium.org169691d2013-07-15 08:01:13 +000021170static bool NamedAccessAlwaysBlocked(Local<v8::Object> global,
21171 Local<Value> name,
21172 v8::AccessType type,
21173 Local<Value> data) {
21174 i::PrintF("Named access blocked.\n");
21175 return false;
21176}
21177
21178
21179static bool IndexAccessAlwaysBlocked(Local<v8::Object> global,
21180 uint32_t key,
21181 v8::AccessType type,
21182 Local<Value> data) {
21183 i::PrintF("Indexed access blocked.\n");
21184 return false;
21185}
21186
21187
21188void UnreachableCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
21189 CHECK(false);
21190}
21191
21192
21193TEST(JSONStringifyAccessCheck) {
21194 v8::V8::Initialize();
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000021195 v8::Isolate* isolate = CcTest::isolate();
21196 v8::HandleScope scope(isolate);
danno@chromium.org169691d2013-07-15 08:01:13 +000021197
21198 // Create an ObjectTemplate for global objects and install access
21199 // check callbacks that will block access.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000021200 v8::Handle<v8::ObjectTemplate> global_template =
21201 v8::ObjectTemplate::New(isolate);
danno@chromium.org169691d2013-07-15 08:01:13 +000021202 global_template->SetAccessCheckCallbacks(NamedAccessAlwaysBlocked,
21203 IndexAccessAlwaysBlocked);
21204
21205 // Create a context and set an x property on it's global object.
21206 LocalContext context0(NULL, global_template);
21207 v8::Handle<v8::Object> global0 = context0->Global();
21208 global0->Set(v8_str("x"), v8_num(42));
21209 ExpectString("JSON.stringify(this)", "{\"x\":42}");
21210
21211 for (int i = 0; i < 2; i++) {
21212 if (i == 1) {
21213 // Install a toJSON function on the second run.
21214 v8::Handle<v8::FunctionTemplate> toJSON =
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000021215 v8::FunctionTemplate::New(isolate, UnreachableCallback);
danno@chromium.org169691d2013-07-15 08:01:13 +000021216
21217 global0->Set(v8_str("toJSON"), toJSON->GetFunction());
21218 }
21219 // Create a context with a different security token so that the
21220 // failed access check callback will be called on each access.
21221 LocalContext context1(NULL, global_template);
21222 context1->Global()->Set(v8_str("other"), global0);
21223
21224 ExpectString("JSON.stringify(other)", "{}");
21225 ExpectString("JSON.stringify({ 'a' : other, 'b' : ['c'] })",
21226 "{\"a\":{},\"b\":[\"c\"]}");
21227 ExpectString("JSON.stringify([other, 'b', 'c'])",
21228 "[{},\"b\",\"c\"]");
21229
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000021230 v8::Handle<v8::Array> array = v8::Array::New(isolate, 2);
danno@chromium.org169691d2013-07-15 08:01:13 +000021231 array->Set(0, v8_str("a"));
21232 array->Set(1, v8_str("b"));
21233 context1->Global()->Set(v8_str("array"), array);
21234 ExpectString("JSON.stringify(array)", "[\"a\",\"b\"]");
21235 array->TurnOnAccessCheck();
21236 ExpectString("JSON.stringify(array)", "[]");
21237 ExpectString("JSON.stringify([array])", "[[]]");
21238 ExpectString("JSON.stringify({'a' : array})", "{\"a\":[]}");
21239 }
21240}
21241
21242
21243bool access_check_fail_thrown = false;
21244bool catch_callback_called = false;
21245
21246
21247// Failed access check callback that performs a GC on each invocation.
21248void FailedAccessCheckThrows(Local<v8::Object> target,
21249 v8::AccessType type,
21250 Local<v8::Value> data) {
21251 access_check_fail_thrown = true;
21252 i::PrintF("Access check failed. Error thrown.\n");
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000021253 CcTest::isolate()->ThrowException(
21254 v8::Exception::Error(v8_str("cross context")));
danno@chromium.org169691d2013-07-15 08:01:13 +000021255}
21256
21257
21258void CatcherCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
21259 for (int i = 0; i < args.Length(); i++) {
21260 i::PrintF("%s\n", *String::Utf8Value(args[i]));
21261 }
21262 catch_callback_called = true;
21263}
21264
21265
21266void HasOwnPropertyCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
21267 args[0]->ToObject()->HasOwnProperty(args[1]->ToString());
21268}
21269
21270
21271void CheckCorrectThrow(const char* script) {
21272 // Test that the script, when wrapped into a try-catch, triggers the catch
21273 // clause due to failed access check throwing an exception.
21274 // The subsequent try-catch should run without any exception.
21275 access_check_fail_thrown = false;
21276 catch_callback_called = false;
21277 i::ScopedVector<char> source(1024);
21278 i::OS::SNPrintF(source, "try { %s; } catch (e) { catcher(e); }", script);
21279 CompileRun(source.start());
21280 CHECK(access_check_fail_thrown);
21281 CHECK(catch_callback_called);
21282
21283 access_check_fail_thrown = false;
21284 catch_callback_called = false;
21285 CompileRun("try { [1, 2, 3].sort(); } catch (e) { catcher(e) };");
21286 CHECK(!access_check_fail_thrown);
21287 CHECK(!catch_callback_called);
21288}
21289
21290
21291TEST(AccessCheckThrows) {
21292 i::FLAG_allow_natives_syntax = true;
21293 v8::V8::Initialize();
21294 v8::V8::SetFailedAccessCheckCallbackFunction(&FailedAccessCheckThrows);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000021295 v8::Isolate* isolate = CcTest::isolate();
21296 v8::HandleScope scope(isolate);
danno@chromium.org169691d2013-07-15 08:01:13 +000021297
21298 // Create an ObjectTemplate for global objects and install access
21299 // check callbacks that will block access.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000021300 v8::Handle<v8::ObjectTemplate> global_template =
21301 v8::ObjectTemplate::New(isolate);
danno@chromium.org169691d2013-07-15 08:01:13 +000021302 global_template->SetAccessCheckCallbacks(NamedAccessAlwaysBlocked,
21303 IndexAccessAlwaysBlocked);
21304
21305 // Create a context and set an x property on it's global object.
21306 LocalContext context0(NULL, global_template);
21307 context0->Global()->Set(v8_str("x"), v8_num(42));
21308 v8::Handle<v8::Object> global0 = context0->Global();
21309
21310 // Create a context with a different security token so that the
21311 // failed access check callback will be called on each access.
21312 LocalContext context1(NULL, global_template);
21313 context1->Global()->Set(v8_str("other"), global0);
21314
21315 v8::Handle<v8::FunctionTemplate> catcher_fun =
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000021316 v8::FunctionTemplate::New(isolate, CatcherCallback);
danno@chromium.org169691d2013-07-15 08:01:13 +000021317 context1->Global()->Set(v8_str("catcher"), catcher_fun->GetFunction());
21318
21319 v8::Handle<v8::FunctionTemplate> has_own_property_fun =
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000021320 v8::FunctionTemplate::New(isolate, HasOwnPropertyCallback);
danno@chromium.org169691d2013-07-15 08:01:13 +000021321 context1->Global()->Set(v8_str("has_own_property"),
21322 has_own_property_fun->GetFunction());
21323
21324 { v8::TryCatch try_catch;
21325 access_check_fail_thrown = false;
21326 CompileRun("other.x;");
21327 CHECK(access_check_fail_thrown);
21328 CHECK(try_catch.HasCaught());
21329 }
21330
21331 CheckCorrectThrow("other.x");
21332 CheckCorrectThrow("other[1]");
21333 CheckCorrectThrow("JSON.stringify(other)");
21334 CheckCorrectThrow("has_own_property(other, 'x')");
21335 CheckCorrectThrow("%GetProperty(other, 'x')");
21336 CheckCorrectThrow("%SetProperty(other, 'x', 'foo', 1, 0)");
21337 CheckCorrectThrow("%IgnoreAttributesAndSetProperty(other, 'x', 'foo')");
21338 CheckCorrectThrow("%DeleteProperty(other, 'x', 0)");
21339 CheckCorrectThrow("%DeleteProperty(other, '1', 0)");
21340 CheckCorrectThrow("%HasLocalProperty(other, 'x')");
21341 CheckCorrectThrow("%HasProperty(other, 'x')");
21342 CheckCorrectThrow("%HasElement(other, 1)");
21343 CheckCorrectThrow("%IsPropertyEnumerable(other, 'x')");
21344 CheckCorrectThrow("%GetPropertyNames(other)");
machenbach@chromium.org03453962014-01-10 14:16:31 +000021345 // PROPERTY_ATTRIBUTES_NONE = 0
21346 CheckCorrectThrow("%GetLocalPropertyNames(other, 0)");
danno@chromium.org169691d2013-07-15 08:01:13 +000021347 CheckCorrectThrow("%DefineOrRedefineAccessorProperty("
21348 "other, 'x', null, null, 1)");
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +000021349
21350 // Reset the failed access check callback so it does not influence
21351 // the other tests.
21352 v8::V8::SetFailedAccessCheckCallbackFunction(NULL);
danno@chromium.org169691d2013-07-15 08:01:13 +000021353}
21354
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000021355
21356THREADED_TEST(Regress256330) {
21357 i::FLAG_allow_natives_syntax = true;
21358 LocalContext context;
21359 v8::HandleScope scope(context->GetIsolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000021360 Handle<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000021361 AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter);
21362 context->Global()->Set(v8_str("Bug"), templ->GetFunction());
21363 CompileRun("\"use strict\"; var o = new Bug;"
21364 "function f(o) { o.x = 10; };"
21365 "f(o); f(o); f(o);"
21366 "%OptimizeFunctionOnNextCall(f);"
21367 "f(o);");
21368 ExpectBoolean("%GetOptimizationStatus(f) != 2", true);
21369}
21370
21371
21372THREADED_TEST(CrankshaftInterceptorSetter) {
21373 i::FLAG_allow_natives_syntax = true;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000021374 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000021375 Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000021376 AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
21377 LocalContext env;
21378 env->Global()->Set(v8_str("Obj"), templ->GetFunction());
21379 CompileRun("var obj = new Obj;"
21380 // Initialize fields to avoid transitions later.
21381 "obj.age = 0;"
21382 "obj.accessor_age = 42;"
21383 "function setter(i) { this.accessor_age = i; };"
21384 "function getter() { return this.accessor_age; };"
21385 "function setAge(i) { obj.age = i; };"
21386 "Object.defineProperty(obj, 'age', { get:getter, set:setter });"
21387 "setAge(1);"
21388 "setAge(2);"
21389 "setAge(3);"
21390 "%OptimizeFunctionOnNextCall(setAge);"
21391 "setAge(4);");
21392 // All stores went through the interceptor.
21393 ExpectInt32("obj.interceptor_age", 4);
21394 ExpectInt32("obj.accessor_age", 42);
21395}
21396
21397
21398THREADED_TEST(CrankshaftInterceptorGetter) {
21399 i::FLAG_allow_natives_syntax = true;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000021400 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000021401 Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000021402 AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
21403 LocalContext env;
21404 env->Global()->Set(v8_str("Obj"), templ->GetFunction());
21405 CompileRun("var obj = new Obj;"
21406 // Initialize fields to avoid transitions later.
21407 "obj.age = 1;"
21408 "obj.accessor_age = 42;"
21409 "function getter() { return this.accessor_age; };"
21410 "function getAge() { return obj.interceptor_age; };"
21411 "Object.defineProperty(obj, 'interceptor_age', { get:getter });"
21412 "getAge();"
21413 "getAge();"
21414 "getAge();"
21415 "%OptimizeFunctionOnNextCall(getAge);");
21416 // Access through interceptor.
21417 ExpectInt32("getAge()", 1);
21418}
21419
21420
21421THREADED_TEST(CrankshaftInterceptorFieldRead) {
21422 i::FLAG_allow_natives_syntax = true;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000021423 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000021424 Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000021425 AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
21426 LocalContext env;
21427 env->Global()->Set(v8_str("Obj"), templ->GetFunction());
21428 CompileRun("var obj = new Obj;"
21429 "obj.__proto__.interceptor_age = 42;"
21430 "obj.age = 100;"
21431 "function getAge() { return obj.interceptor_age; };");
21432 ExpectInt32("getAge();", 100);
21433 ExpectInt32("getAge();", 100);
21434 ExpectInt32("getAge();", 100);
21435 CompileRun("%OptimizeFunctionOnNextCall(getAge);");
21436 // Access through interceptor.
21437 ExpectInt32("getAge();", 100);
21438}
21439
21440
21441THREADED_TEST(CrankshaftInterceptorFieldWrite) {
21442 i::FLAG_allow_natives_syntax = true;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000021443 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000021444 Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000021445 AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
21446 LocalContext env;
21447 env->Global()->Set(v8_str("Obj"), templ->GetFunction());
21448 CompileRun("var obj = new Obj;"
21449 "obj.age = 100000;"
21450 "function setAge(i) { obj.age = i };"
21451 "setAge(100);"
21452 "setAge(101);"
21453 "setAge(102);"
21454 "%OptimizeFunctionOnNextCall(setAge);"
21455 "setAge(103);");
21456 ExpectInt32("obj.age", 100000);
21457 ExpectInt32("obj.interceptor_age", 103);
21458}
21459
dslomov@chromium.org639bac02013-09-09 11:58:54 +000021460
hpayer@chromium.orgea9b8ba2013-12-20 19:22:39 +000021461class RequestInterruptTestBase {
21462 public:
21463 RequestInterruptTestBase()
21464 : env_(),
21465 isolate_(env_->GetIsolate()),
21466 sem_(0),
21467 warmup_(20000),
21468 should_continue_(true) {
21469 }
21470
21471 virtual ~RequestInterruptTestBase() { }
21472
21473 virtual void TestBody() = 0;
21474
21475 void RunTest() {
21476 InterruptThread i_thread(this);
21477 i_thread.Start();
21478
21479 v8::HandleScope handle_scope(isolate_);
21480
21481 TestBody();
21482
21483 isolate_->ClearInterrupt();
21484
21485 // Verify we arrived here because interruptor was called
21486 // not due to a bug causing us to exit the loop too early.
21487 CHECK(!should_continue());
21488 }
21489
21490 void WakeUpInterruptor() {
21491 sem_.Signal();
21492 }
21493
21494 bool should_continue() const { return should_continue_; }
21495
21496 bool ShouldContinue() {
21497 if (warmup_ > 0) {
21498 if (--warmup_ == 0) {
21499 WakeUpInterruptor();
21500 }
21501 }
21502
21503 return should_continue_;
21504 }
21505
21506 protected:
21507 static void ShouldContinueCallback(
21508 const v8::FunctionCallbackInfo<Value>& info) {
21509 RequestInterruptTestBase* test =
21510 reinterpret_cast<RequestInterruptTestBase*>(
21511 info.Data().As<v8::External>()->Value());
21512 info.GetReturnValue().Set(test->ShouldContinue());
21513 }
21514
21515 class InterruptThread : public i::Thread {
21516 public:
21517 explicit InterruptThread(RequestInterruptTestBase* test)
21518 : Thread("RequestInterruptTest"), test_(test) {}
21519
21520 virtual void Run() {
21521 test_->sem_.Wait();
21522 test_->isolate_->RequestInterrupt(&OnInterrupt, test_);
21523 }
21524
21525 static void OnInterrupt(v8::Isolate* isolate, void* data) {
21526 reinterpret_cast<RequestInterruptTestBase*>(data)->
21527 should_continue_ = false;
21528 }
21529
21530 private:
21531 RequestInterruptTestBase* test_;
21532 };
21533
21534 LocalContext env_;
21535 v8::Isolate* isolate_;
21536 i::Semaphore sem_;
21537 int warmup_;
21538 bool should_continue_;
21539};
21540
21541
21542class RequestInterruptTestWithFunctionCall : public RequestInterruptTestBase {
21543 public:
21544 virtual void TestBody() {
21545 Local<Function> func = Function::New(
21546 isolate_, ShouldContinueCallback, v8::External::New(isolate_, this));
21547 env_->Global()->Set(v8_str("ShouldContinue"), func);
21548
21549 CompileRun("while (ShouldContinue()) { }");
21550 }
21551};
21552
21553
21554class RequestInterruptTestWithMethodCall : public RequestInterruptTestBase {
21555 public:
21556 virtual void TestBody() {
21557 v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
21558 v8::Local<v8::Template> proto = t->PrototypeTemplate();
21559 proto->Set(v8_str("shouldContinue"), Function::New(
21560 isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
21561 env_->Global()->Set(v8_str("Klass"), t->GetFunction());
21562
21563 CompileRun("var obj = new Klass; while (obj.shouldContinue()) { }");
21564 }
21565};
21566
21567
21568class RequestInterruptTestWithAccessor : public RequestInterruptTestBase {
21569 public:
21570 virtual void TestBody() {
21571 v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
21572 v8::Local<v8::Template> proto = t->PrototypeTemplate();
21573 proto->SetAccessorProperty(v8_str("shouldContinue"), FunctionTemplate::New(
21574 isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
21575 env_->Global()->Set(v8_str("Klass"), t->GetFunction());
21576
21577 CompileRun("var obj = new Klass; while (obj.shouldContinue) { }");
21578 }
21579};
21580
21581
21582class RequestInterruptTestWithNativeAccessor : public RequestInterruptTestBase {
21583 public:
21584 virtual void TestBody() {
21585 v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
21586 t->InstanceTemplate()->SetNativeDataProperty(
21587 v8_str("shouldContinue"),
21588 &ShouldContinueNativeGetter,
21589 NULL,
21590 v8::External::New(isolate_, this));
21591 env_->Global()->Set(v8_str("Klass"), t->GetFunction());
21592
21593 CompileRun("var obj = new Klass; while (obj.shouldContinue) { }");
21594 }
21595
21596 private:
21597 static void ShouldContinueNativeGetter(
21598 Local<String> property,
21599 const v8::PropertyCallbackInfo<v8::Value>& info) {
21600 RequestInterruptTestBase* test =
21601 reinterpret_cast<RequestInterruptTestBase*>(
21602 info.Data().As<v8::External>()->Value());
21603 info.GetReturnValue().Set(test->ShouldContinue());
21604 }
21605};
21606
21607
21608class RequestInterruptTestWithMethodCallAndInterceptor
21609 : public RequestInterruptTestBase {
21610 public:
21611 virtual void TestBody() {
21612 v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
21613 v8::Local<v8::Template> proto = t->PrototypeTemplate();
21614 proto->Set(v8_str("shouldContinue"), Function::New(
21615 isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
21616 v8::Local<v8::ObjectTemplate> instance_template = t->InstanceTemplate();
21617 instance_template->SetNamedPropertyHandler(EmptyInterceptor);
21618
21619 env_->Global()->Set(v8_str("Klass"), t->GetFunction());
21620
21621 CompileRun("var obj = new Klass; while (obj.shouldContinue()) { }");
21622 }
21623
21624 private:
21625 static void EmptyInterceptor(
21626 Local<String> property,
21627 const v8::PropertyCallbackInfo<v8::Value>& info) {
21628 }
21629};
21630
21631
21632class RequestInterruptTestWithMathAbs : public RequestInterruptTestBase {
21633 public:
21634 virtual void TestBody() {
21635 env_->Global()->Set(v8_str("WakeUpInterruptor"), Function::New(
21636 isolate_,
21637 WakeUpInterruptorCallback,
21638 v8::External::New(isolate_, this)));
21639
21640 env_->Global()->Set(v8_str("ShouldContinue"), Function::New(
21641 isolate_,
21642 ShouldContinueCallback,
21643 v8::External::New(isolate_, this)));
21644
21645 i::FLAG_allow_natives_syntax = true;
21646 CompileRun("function loopish(o) {"
21647 " var pre = 10;"
21648 " while (o.abs(1) > 0) {"
21649 " if (o.abs(1) >= 0 && !ShouldContinue()) break;"
21650 " if (pre > 0) {"
21651 " if (--pre === 0) WakeUpInterruptor(o === Math);"
21652 " }"
21653 " }"
21654 "}"
21655 "var i = 50;"
21656 "var obj = {abs: function () { return i-- }, x: null};"
21657 "delete obj.x;"
21658 "loopish(obj);"
21659 "%OptimizeFunctionOnNextCall(loopish);"
21660 "loopish(Math);");
21661
21662 i::FLAG_allow_natives_syntax = false;
21663 }
21664
21665 private:
21666 static void WakeUpInterruptorCallback(
21667 const v8::FunctionCallbackInfo<Value>& info) {
21668 if (!info[0]->BooleanValue()) return;
21669
21670 RequestInterruptTestBase* test =
21671 reinterpret_cast<RequestInterruptTestBase*>(
21672 info.Data().As<v8::External>()->Value());
21673 test->WakeUpInterruptor();
21674 }
21675
21676 static void ShouldContinueCallback(
21677 const v8::FunctionCallbackInfo<Value>& info) {
21678 RequestInterruptTestBase* test =
21679 reinterpret_cast<RequestInterruptTestBase*>(
21680 info.Data().As<v8::External>()->Value());
21681 info.GetReturnValue().Set(test->should_continue());
21682 }
21683};
21684
21685
21686TEST(RequestInterruptTestWithFunctionCall) {
21687 RequestInterruptTestWithFunctionCall().RunTest();
21688}
21689
21690
21691TEST(RequestInterruptTestWithMethodCall) {
21692 RequestInterruptTestWithMethodCall().RunTest();
21693}
21694
21695
21696TEST(RequestInterruptTestWithAccessor) {
21697 RequestInterruptTestWithAccessor().RunTest();
21698}
21699
21700
21701TEST(RequestInterruptTestWithNativeAccessor) {
21702 RequestInterruptTestWithNativeAccessor().RunTest();
21703}
21704
21705
21706TEST(RequestInterruptTestWithMethodCallAndInterceptor) {
21707 RequestInterruptTestWithMethodCallAndInterceptor().RunTest();
21708}
21709
21710
21711TEST(RequestInterruptTestWithMathAbs) {
21712 RequestInterruptTestWithMathAbs().RunTest();
21713}
dslomov@chromium.org639bac02013-09-09 11:58:54 +000021714
21715
21716static Local<Value> function_new_expected_env;
21717static void FunctionNewCallback(const v8::FunctionCallbackInfo<Value>& info) {
21718 CHECK_EQ(function_new_expected_env, info.Data());
21719 info.GetReturnValue().Set(17);
21720}
21721
21722
21723THREADED_TEST(FunctionNew) {
21724 LocalContext env;
21725 v8::Isolate* isolate = env->GetIsolate();
21726 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000021727 Local<Object> data = v8::Object::New(isolate);
dslomov@chromium.org639bac02013-09-09 11:58:54 +000021728 function_new_expected_env = data;
21729 Local<Function> func = Function::New(isolate, FunctionNewCallback, data);
21730 env->Global()->Set(v8_str("func"), func);
21731 Local<Value> result = CompileRun("func();");
ulan@chromium.org0f13e742014-01-03 15:51:11 +000021732 CHECK_EQ(v8::Integer::New(isolate, 17), result);
dslomov@chromium.org639bac02013-09-09 11:58:54 +000021733 // Verify function not cached
21734 int serial_number =
21735 i::Smi::cast(v8::Utils::OpenHandle(*func)
21736 ->shared()->get_api_func_data()->serial_number())->value();
21737 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
21738 i::Object* elm = i_isolate->native_context()->function_cache()
21739 ->GetElementNoExceptionThrown(i_isolate, serial_number);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000021740 CHECK(elm->IsUndefined());
21741 // Verify that each Function::New creates a new function instance
ulan@chromium.org0f13e742014-01-03 15:51:11 +000021742 Local<Object> data2 = v8::Object::New(isolate);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000021743 function_new_expected_env = data2;
21744 Local<Function> func2 = Function::New(isolate, FunctionNewCallback, data2);
21745 CHECK(!func2->IsNull());
21746 CHECK_NE(func, func2);
21747 env->Global()->Set(v8_str("func2"), func2);
21748 Local<Value> result2 = CompileRun("func2();");
ulan@chromium.org0f13e742014-01-03 15:51:11 +000021749 CHECK_EQ(v8::Integer::New(isolate, 17), result2);
dslomov@chromium.org639bac02013-09-09 11:58:54 +000021750}
21751
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000021752
21753TEST(EscapeableHandleScope) {
21754 HandleScope outer_scope(CcTest::isolate());
21755 LocalContext context;
21756 const int runs = 10;
21757 Local<String> values[runs];
21758 for (int i = 0; i < runs; i++) {
21759 v8::EscapableHandleScope inner_scope(CcTest::isolate());
21760 Local<String> value;
21761 if (i != 0) value = v8_str("escape value");
21762 values[i] = inner_scope.Escape(value);
21763 }
21764 for (int i = 0; i < runs; i++) {
21765 Local<String> expected;
21766 if (i != 0) {
21767 CHECK_EQ(v8_str("escape value"), values[i]);
21768 } else {
21769 CHECK(values[i].IsEmpty());
21770 }
21771 }
21772}
machenbach@chromium.org43c51e52014-01-20 07:57:28 +000021773
21774
21775static void SetterWhichExpectsThisAndHolderToDiffer(
21776 Local<String>, Local<Value>, const v8::PropertyCallbackInfo<void>& info) {
21777 CHECK(info.Holder() != info.This());
21778}
21779
21780
21781TEST(Regress239669) {
21782 LocalContext context;
21783 v8::Isolate* isolate = context->GetIsolate();
21784 v8::HandleScope scope(isolate);
21785 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
21786 templ->SetAccessor(v8_str("x"), 0, SetterWhichExpectsThisAndHolderToDiffer);
21787 context->Global()->Set(v8_str("P"), templ->NewInstance());
21788 CompileRun(
21789 "function C1() {"
21790 " this.x = 23;"
21791 "};"
21792 "C1.prototype = P;"
21793 "for (var i = 0; i < 4; i++ ) {"
21794 " new C1();"
21795 "}");
21796}
machenbach@chromium.org57a54ac2014-01-31 14:01:53 +000021797
21798
21799class ApiCallOptimizationChecker {
21800 private:
21801 static Local<Object> data;
21802 static Local<Object> receiver;
21803 static Local<Object> holder;
21804 static Local<Object> callee;
21805 static int count;
21806
21807 static void OptimizationCallback(
21808 const v8::FunctionCallbackInfo<v8::Value>& info) {
21809 CHECK(callee == info.Callee());
21810 CHECK(data == info.Data());
21811 CHECK(receiver == info.This());
bmeurer@chromium.org25530ce2014-02-07 09:11:16 +000021812 if (info.Length() == 1) {
21813 CHECK_EQ(v8_num(1), info[0]);
21814 }
machenbach@chromium.org57a54ac2014-01-31 14:01:53 +000021815 CHECK(holder == info.Holder());
21816 count++;
21817 }
21818
machenbach@chromium.org82975302014-02-06 01:06:18 +000021819 // TODO(dcarney): move this to v8.h
21820 static void SetAccessorProperty(Local<Object> object,
21821 Local<String> name,
21822 Local<Function> getter,
21823 Local<Function> setter = Local<Function>()) {
21824 i::Isolate* isolate = CcTest::i_isolate();
21825 v8::AccessControl settings = v8::DEFAULT;
21826 v8::PropertyAttribute attribute = v8::None;
21827 i::Handle<i::Object> getter_i = v8::Utils::OpenHandle(*getter);
21828 i::Handle<i::Object> setter_i = v8::Utils::OpenHandle(*setter, true);
21829 if (setter_i.is_null()) setter_i = isolate->factory()->null_value();
21830 i::JSObject::DefineAccessor(v8::Utils::OpenHandle(*object),
21831 v8::Utils::OpenHandle(*name),
21832 getter_i,
21833 setter_i,
21834 static_cast<PropertyAttributes>(attribute),
21835 settings);
21836 }
21837
machenbach@chromium.org57a54ac2014-01-31 14:01:53 +000021838 public:
21839 void Run(bool use_signature, bool global) {
21840 v8::Isolate* isolate = CcTest::isolate();
21841 v8::HandleScope scope(isolate);
21842 // Build a template for signature checks.
21843 Local<v8::ObjectTemplate> signature_template;
21844 Local<v8::Signature> signature;
21845 {
21846 Local<v8::FunctionTemplate> parent_template =
21847 FunctionTemplate::New(isolate);
21848 parent_template->SetHiddenPrototype(true);
21849 Local<v8::FunctionTemplate> function_template
21850 = FunctionTemplate::New(isolate);
21851 function_template->Inherit(parent_template);
21852 if (use_signature) {
21853 signature = v8::Signature::New(isolate, parent_template);
21854 }
21855 signature_template = function_template->InstanceTemplate();
21856 }
21857 // Global object must pass checks.
21858 Local<v8::Context> context =
21859 v8::Context::New(isolate, NULL, signature_template);
21860 v8::Context::Scope context_scope(context);
21861 // Install regular object that can pass signature checks.
21862 Local<Object> function_receiver = signature_template->NewInstance();
21863 context->Global()->Set(v8_str("function_receiver"), function_receiver);
21864 // Get the holder objects.
21865 Local<Object> inner_global =
21866 Local<Object>::Cast(context->Global()->GetPrototype());
21867 Local<Object> function_holder =
21868 Local<Object>::Cast(function_receiver->GetPrototype());
21869 // Install function on hidden prototype object.
21870 data = Object::New(isolate);
21871 Local<FunctionTemplate> function_template = FunctionTemplate::New(
21872 isolate, OptimizationCallback, data, signature);
21873 Local<Function> function = function_template->GetFunction();
machenbach@chromium.org82975302014-02-06 01:06:18 +000021874 Local<Object> global_holder = Local<Object>::Cast(
21875 inner_global->GetPrototype());
21876 global_holder->Set(v8_str("g_f"), function);
bmeurer@chromium.org25530ce2014-02-07 09:11:16 +000021877 SetAccessorProperty(global_holder, v8_str("g_acc"), function, function);
machenbach@chromium.org57a54ac2014-01-31 14:01:53 +000021878 function_holder->Set(v8_str("f"), function);
bmeurer@chromium.org25530ce2014-02-07 09:11:16 +000021879 SetAccessorProperty(function_holder, v8_str("acc"), function, function);
machenbach@chromium.org57a54ac2014-01-31 14:01:53 +000021880 // Initialize expected values.
21881 callee = function;
21882 count = 0;
21883 if (global) {
21884 receiver = context->Global();
21885 holder = inner_global;
21886 } else {
21887 holder = function_receiver;
21888 // If not using a signature, add something else to the prototype chain
21889 // to test the case that holder != receiver
21890 if (!use_signature) {
21891 receiver = Local<Object>::Cast(CompileRun(
21892 "var receiver_subclass = {};\n"
21893 "receiver_subclass.__proto__ = function_receiver;\n"
21894 "receiver_subclass"));
21895 } else {
21896 receiver = Local<Object>::Cast(CompileRun(
21897 "var receiver_subclass = function_receiver;\n"
21898 "receiver_subclass"));
21899 }
21900 }
21901 // With no signature, the holder is not set.
21902 if (!use_signature) holder = receiver;
21903 // build wrap_function
21904 int key = (use_signature ? 1 : 0) + 2 * (global ? 1 : 0);
machenbach@chromium.org82975302014-02-06 01:06:18 +000021905 i::ScopedVector<char> wrap_function(200);
machenbach@chromium.org57a54ac2014-01-31 14:01:53 +000021906 if (global) {
21907 i::OS::SNPrintF(
21908 wrap_function,
machenbach@chromium.org82975302014-02-06 01:06:18 +000021909 "function wrap_f_%d() { var f = g_f; return f(); }\n"
bmeurer@chromium.org25530ce2014-02-07 09:11:16 +000021910 "function wrap_get_%d() { return this.g_acc; }\n"
21911 "function wrap_set_%d() { this.g_acc = 1; }\n",
21912 key, key, key);
machenbach@chromium.org57a54ac2014-01-31 14:01:53 +000021913 } else {
21914 i::OS::SNPrintF(
21915 wrap_function,
machenbach@chromium.org82975302014-02-06 01:06:18 +000021916 "function wrap_f_%d() { return receiver_subclass.f(); }\n"
bmeurer@chromium.org25530ce2014-02-07 09:11:16 +000021917 "function wrap_get_%d() { return receiver_subclass.acc; }\n"
21918 "function wrap_set_%d() { receiver_subclass.acc = 1; }\n",
21919 key, key, key);
machenbach@chromium.org57a54ac2014-01-31 14:01:53 +000021920 }
21921 // build source string
21922 i::ScopedVector<char> source(500);
21923 i::OS::SNPrintF(
21924 source,
machenbach@chromium.org82975302014-02-06 01:06:18 +000021925 "%s\n" // wrap functions
21926 "function wrap_f() { wrap_f_%d(); }\n"
bmeurer@chromium.org25530ce2014-02-07 09:11:16 +000021927 "function wrap_get() { wrap_get_%d(); }\n"
21928 "function wrap_set() { wrap_set_%d(); }\n"
21929 "\n"
machenbach@chromium.org82975302014-02-06 01:06:18 +000021930 "wrap_f();\n"
21931 "wrap_f();\n"
21932 "%%OptimizeFunctionOnNextCall(wrap_f_%d);\n"
21933 "wrap_f();\n"
bmeurer@chromium.org25530ce2014-02-07 09:11:16 +000021934 "\n"
21935 "wrap_get();\n"
21936 "wrap_get();\n"
21937 "%%OptimizeFunctionOnNextCall(wrap_get_%d);\n"
21938 "wrap_get();\n"
21939 "\n"
21940 "wrap_set();\n"
21941 "wrap_set();\n"
21942 "%%OptimizeFunctionOnNextCall(wrap_set_%d);\n"
21943 "wrap_set();\n",
21944 wrap_function.start(), key, key, key, key, key, key);
machenbach@chromium.org57a54ac2014-01-31 14:01:53 +000021945 v8::TryCatch try_catch;
21946 CompileRun(source.start());
21947 ASSERT(!try_catch.HasCaught());
bmeurer@chromium.org25530ce2014-02-07 09:11:16 +000021948 CHECK_EQ(9, count);
machenbach@chromium.org57a54ac2014-01-31 14:01:53 +000021949 }
21950};
21951
21952
21953Local<Object> ApiCallOptimizationChecker::data;
21954Local<Object> ApiCallOptimizationChecker::receiver;
21955Local<Object> ApiCallOptimizationChecker::holder;
21956Local<Object> ApiCallOptimizationChecker::callee;
21957int ApiCallOptimizationChecker::count = 0;
21958
21959
21960TEST(TestFunctionCallOptimization) {
21961 i::FLAG_allow_natives_syntax = true;
21962 ApiCallOptimizationChecker checker;
21963 checker.Run(true, true);
21964 checker.Run(false, true);
21965 checker.Run(true, false);
21966 checker.Run(false, false);
21967}