13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without
3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met:
5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions of source code must retain the above copyright
7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       notice, this list of conditions and the following disclaimer.
8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions in binary form must reproduce the above
9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       copyright notice, this list of conditions and the following
10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       disclaimer in the documentation and/or other materials provided
11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       with the distribution.
12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Neither the name of Google Inc. nor the names of its
13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       contributors may be used to endorse or promote products derived
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       from this software without specific prior written permission.
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <climits>
29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <csignal>
30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <map>
31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <string>
32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/v8.h"
34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_OS_POSIX
36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <unistd.h>  // NOLINT
37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "include/v8-util.h"
40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/api.h"
41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/arguments.h"
42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/platform/platform.h"
43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/compilation-cache.h"
44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/cpu-profiler.h"
45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/execution.h"
46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/isolate.h"
47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/objects.h"
48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/parser.h"
49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/snapshot.h"
50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/unicode-inl.h"
51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/utils.h"
52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/vm-state.h"
53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "test/cctest/cctest.h"
54d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic const bool kLogThreading = false;
56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochusing ::v8::Boolean;
58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochusing ::v8::BooleanObject;
59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockusing ::v8::Context;
6044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockusing ::v8::Extension;
6144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockusing ::v8::Function;
628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochusing ::v8::FunctionTemplate;
638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochusing ::v8::Handle;
6444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockusing ::v8::HandleScope;
65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockusing ::v8::Local;
66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochusing ::v8::Name;
678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochusing ::v8::Message;
688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochusing ::v8::MessageCallback;
6944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockusing ::v8::Object;
7044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockusing ::v8::ObjectTemplate;
7144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockusing ::v8::Persistent;
72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockusing ::v8::Script;
738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochusing ::v8::StackTrace;
7444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockusing ::v8::String;
75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochusing ::v8::Symbol;
768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochusing ::v8::TryCatch;
778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochusing ::v8::Undefined;
78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochusing ::v8::UniqueId;
7944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockusing ::v8::V8;
808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochusing ::v8::Value;
81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define THREADED_PROFILED_TEST(Name)                                 \
84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static void Test##Name();                                          \
85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TEST(Name##WithProfiler) {                                         \
86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    RunWithProfiler(&Test##Name);                                    \
87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }                                                                  \
88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  THREADED_TEST(Name)
89756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
90d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid RunWithProfiler(void (*test)()) {
92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::String> profile_name =
95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(env->GetIsolate(), "my_profile1");
96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler();
97d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cpu_profiler->StartProfiling(profile_name);
99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  (*test)();
100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  reinterpret_cast<i::CpuProfiler*>(cpu_profiler)->DeleteAllProfiles();
101756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
102756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
103756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic int signature_callback_count;
105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic Local<Value> signature_expected_receiver;
106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void IncrementingSignatureCallback(
107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::FunctionCallbackInfo<v8::Value>& args) {
108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  signature_callback_count++;
110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(signature_expected_receiver, args.Holder());
111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(signature_expected_receiver, args.This());
112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Array> result =
113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Array::New(args.GetIsolate(), args.Length());
114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < args.Length(); i++)
115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    result->Set(v8::Integer::New(args.GetIsolate(), i), args[i]);
116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  args.GetReturnValue().Set(result);
117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void SignatureCallback(
121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::FunctionCallbackInfo<v8::Value>& args) {
122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Array> result =
124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Array::New(args.GetIsolate(), args.Length());
125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < args.Length(); i++) {
126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    result->Set(v8::Integer::New(args.GetIsolate(), i), args[i]);
127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  args.GetReturnValue().Set(result);
129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Tests that call v8::V8::Dispose() cannot be threaded.
133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochUNINITIALIZED_TEST(InitializeAndDisposeOnce) {
134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(v8::V8::Initialize());
135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(v8::V8::Dispose());
136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Tests that call v8::V8::Dispose() cannot be threaded.
140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochUNINITIALIZED_TEST(InitializeAndDisposeMultiple) {
141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < 3; ++i) CHECK(v8::V8::Initialize());
143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < 3; ++i) CHECK(v8::V8::Initialize());
145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(Handles) {
150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(CcTest::isolate());
151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Context> local_env;
152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {
153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    LocalContext env;
154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    local_env = env.local();
155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Local context should still be live.
158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(!local_env.IsEmpty());
159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  local_env->Enter();
160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Primitive> undef = v8::Undefined(CcTest::isolate());
162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(!undef.IsEmpty());
163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(undef->IsUndefined());
164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* source = "1 + 2 + 3";
166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Script> script = v8_compile(source);
167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(6, script->Run()->Int32Value());
168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  local_env->Exit();
170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(IsolateOfContext) {
174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(CcTest::isolate());
175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<Context> env = Context::New(CcTest::isolate());
176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!env->GetIsolate()->InContext());
178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(env->GetIsolate() == CcTest::isolate());
179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->Enter();
180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(env->GetIsolate()->InContext());
181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(env->GetIsolate() == CcTest::isolate());
182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->Exit();
183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!env->GetIsolate()->InContext());
184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(env->GetIsolate() == CcTest::isolate());
185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void TestSignature(const char* loop_js, Local<Value> receiver) {
189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::ScopedVector<char> source(200);
190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::SNPrintF(source,
191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              "for (var i = 0; i < 10; i++) {"
192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              "  %s"
193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              "}",
194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              loop_js);
195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  signature_callback_count = 0;
196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  signature_expected_receiver = receiver;
197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool expected_to_throw = receiver.IsEmpty();
198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::TryCatch try_catch;
199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun(source.start());
200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(expected_to_throw, try_catch.HasCaught());
201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!expected_to_throw) {
202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(10, signature_callback_count);
203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(v8_str("TypeError: Illegal invocation"),
205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             try_catch.Exception()->ToString());
206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(ReceiverSignature) {
211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Setup templates.
215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(isolate);
216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Signature> sig = v8::Signature::New(isolate, fun);
217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::FunctionTemplate> callback_sig =
218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::FunctionTemplate::New(
219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          isolate, IncrementingSignatureCallback, Local<Value>(), sig);
220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::FunctionTemplate> callback =
221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::FunctionTemplate::New(isolate, IncrementingSignatureCallback);
222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::FunctionTemplate> sub_fun = v8::FunctionTemplate::New(isolate);
223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  sub_fun->Inherit(fun);
224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::FunctionTemplate> unrel_fun =
225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::FunctionTemplate::New(isolate);
226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Install properties.
227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> fun_proto = fun->PrototypeTemplate();
228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fun_proto->Set(v8_str("prop_sig"), callback_sig);
229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fun_proto->Set(v8_str("prop"), callback);
230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fun_proto->SetAccessorProperty(
231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8_str("accessor_sig"), callback_sig, callback_sig);
232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fun_proto->SetAccessorProperty(v8_str("accessor"), callback, callback);
233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Instantiate templates.
234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Value> fun_instance = fun->InstanceTemplate()->NewInstance();
235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Value> sub_fun_instance = sub_fun->InstanceTemplate()->NewInstance();
236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Setup global variables.
237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->Global()->Set(v8_str("Fun"), fun->GetFunction());
238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env->Global()->Set(v8_str("UnrelFun"), unrel_fun->GetFunction());
239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->Global()->Set(v8_str("fun_instance"), fun_instance);
240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->Global()->Set(v8_str("sub_fun_instance"), sub_fun_instance);
241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CompileRun(
242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "var accessor_sig_key = 'accessor_sig';"
243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "var accessor_key = 'accessor';"
244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "var prop_sig_key = 'prop_sig';"
245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "var prop_key = 'prop';"
246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ""
247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "function copy_props(obj) {"
248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  var keys = [accessor_sig_key, accessor_key, prop_sig_key, prop_key];"
249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  var source = Fun.prototype;"
250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  for (var i in keys) {"
251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "    var key = keys[i];"
252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "    var desc = Object.getOwnPropertyDescriptor(source, key);"
253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "    Object.defineProperty(obj, key, desc);"
254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  }"
255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "}"
256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ""
257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "var obj = {};"
258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "copy_props(obj);"
259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "var unrel = new UnrelFun();"
260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "copy_props(unrel);");
261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Test with and without ICs
262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* test_objects[] = {
263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "fun_instance", "sub_fun_instance", "obj", "unrel" };
264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  unsigned bad_signature_start_offset = 2;
265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (unsigned i = 0; i < arraysize(test_objects); i++) {
266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    i::ScopedVector<char> source(200);
267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    i::SNPrintF(
268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        source, "var test_object = %s; test_object", test_objects[i]);
269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<Value> test_object = CompileRun(source.start());
270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    TestSignature("test_object.prop();", test_object);
271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    TestSignature("test_object.accessor;", test_object);
272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    TestSignature("test_object[accessor_key];", test_object);
273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    TestSignature("test_object.accessor = 1;", test_object);
274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    TestSignature("test_object[accessor_key] = 1;", test_object);
275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (i >= bad_signature_start_offset) test_object = Local<Value>();
276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    TestSignature("test_object.prop_sig();", test_object);
277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    TestSignature("test_object.accessor_sig;", test_object);
278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    TestSignature("test_object[accessor_sig_key];", test_object);
279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    TestSignature("test_object.accessor_sig = 1;", test_object);
280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    TestSignature("test_object[accessor_sig_key] = 1;", test_object);
281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(ArgumentSignature) {
286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext env;
287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::FunctionTemplate> cons = v8::FunctionTemplate::New(isolate);
290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  cons->SetClassName(v8_str("Cons"));
291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Signature> sig = v8::Signature::New(
292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate, v8::Handle<v8::FunctionTemplate>(), 1, &cons);
293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::FunctionTemplate> fun =
294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::FunctionTemplate::New(isolate,
295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                SignatureCallback,
296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                v8::Handle<Value>(),
297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                sig);
298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env->Global()->Set(v8_str("Cons"), cons->GetFunction());
299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env->Global()->Set(v8_str("Fun1"), fun->GetFunction());
300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> value1 = CompileRun("Fun1(4) == '';");
302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(value1->IsTrue());
303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> value2 = CompileRun("Fun1(new Cons()) == '[object Cons]';");
305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(value2->IsTrue());
306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> value3 = CompileRun("Fun1() == '';");
308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(value3->IsTrue());
309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::FunctionTemplate> cons1 = v8::FunctionTemplate::New(isolate);
311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  cons1->SetClassName(v8_str("Cons1"));
312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::FunctionTemplate> cons2 = v8::FunctionTemplate::New(isolate);
313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  cons2->SetClassName(v8_str("Cons2"));
314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::FunctionTemplate> cons3 = v8::FunctionTemplate::New(isolate);
315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  cons3->SetClassName(v8_str("Cons3"));
316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::FunctionTemplate> args[3] = { cons1, cons2, cons3 };
318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Signature> wsig = v8::Signature::New(
319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate, v8::Handle<v8::FunctionTemplate>(), 3, args);
320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::FunctionTemplate> fun2 =
321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::FunctionTemplate::New(isolate,
322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                SignatureCallback,
323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                v8::Handle<Value>(),
324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                wsig);
325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env->Global()->Set(v8_str("Cons1"), cons1->GetFunction());
327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env->Global()->Set(v8_str("Cons2"), cons2->GetFunction());
328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env->Global()->Set(v8_str("Cons3"), cons3->GetFunction());
329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env->Global()->Set(v8_str("Fun2"), fun2->GetFunction());
330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> value4 = CompileRun(
331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "Fun2(new Cons1(), new Cons2(), new Cons3()) =="
332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "'[object Cons1],[object Cons2],[object Cons3]'");
333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(value4->IsTrue());
334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> value5 = CompileRun(
336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "Fun2(new Cons1(), new Cons2(), 5) == '[object Cons1],[object Cons2],'");
337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(value5->IsTrue());
338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> value6 = CompileRun(
340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "Fun2(new Cons3(), new Cons2(), new Cons1()) == ',[object Cons2],'");
341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(value6->IsTrue());
342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> value7 = CompileRun(
344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "Fun2(new Cons1(), new Cons2(), new Cons3(), 'd') == "
345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "'[object Cons1],[object Cons2],[object Cons3],d';");
346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(value7->IsTrue());
347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> value8 = CompileRun(
349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "Fun2(new Cons1(), new Cons2()) == '[object Cons1],[object Cons2]'");
350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(value8->IsTrue());
351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(HulIgennem) {
355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext env;
356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Primitive> undef = v8::Undefined(isolate);
359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<String> undef_str = undef->ToString();
360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  char* value = i::NewArray<char>(undef_str->Utf8Length() + 1);
361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  undef_str->WriteUtf8(value);
362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, strcmp(value, "undefined"));
363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  i::DeleteArray(value);
364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(Access) {
368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext env;
369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::Object> obj = v8::Object::New(isolate);
372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Value> foo_before = obj->Get(v8_str("foo"));
373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(foo_before->IsUndefined());
374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<String> bar_str = v8_str("bar");
375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  obj->Set(v8_str("foo"), bar_str);
376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Value> foo_after = obj->Get(v8_str("foo"));
377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(!foo_after->IsUndefined());
378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(foo_after->IsString());
379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(bar_str, foo_after);
380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3836ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockTHREADED_TEST(AccessElement) {
3846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  LocalContext env;
385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
3876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Local<Value> before = obj->Get(1);
3886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(before->IsUndefined());
3896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Local<String> bar_str = v8_str("bar");
3906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  obj->Set(1, bar_str);
3916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Local<Value> after = obj->Get(1);
3926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(!after->IsUndefined());
3936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(after->IsString());
3946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(bar_str, after);
3956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Local<v8::Array> value = CompileRun("[\"a\", \"b\"]").As<v8::Array>();
3976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(v8_str("a"), value->Get(0));
3986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(v8_str("b"), value->Get(1));
3996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
4006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(Script) {
403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext env;
404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* source = "1 + 2 + 3";
406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Script> script = v8_compile(source);
407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(6, script->Run()->Int32Value());
408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass TestResource: public String::ExternalStringResource {
412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  explicit TestResource(uint16_t* data, int* counter = NULL,
414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        bool owning_data = true)
415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : data_(data), length_(0), counter_(counter), owning_data_(owning_data) {
416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    while (data[length_]) ++length_;
417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ~TestResource() {
420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (owning_data_) i::DeleteArray(data_);
42169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    if (counter_ != NULL) ++*counter_;
422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const uint16_t* data() const {
425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return data_;
426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  size_t length() const {
429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return length_;
430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  uint16_t* data_;
434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  size_t length_;
43569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  int* counter_;
436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool owning_data_;
437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass TestOneByteResource : public String::ExternalOneByteStringResource {
441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  explicit TestOneByteResource(const char* data, int* counter = NULL,
443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               size_t offset = 0)
444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : orig_data_(data),
445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        data_(data + offset),
446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        length_(strlen(data) - offset),
447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        counter_(counter) {}
448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ~TestOneByteResource() {
450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    i::DeleteArray(orig_data_);
45169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    if (counter_ != NULL) ++*counter_;
452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* data() const {
455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return data_;
456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  size_t length() const {
459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return length_;
460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* orig_data_;
464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* data_;
465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  size_t length_;
46669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  int* counter_;
467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(ScriptUsingStringResource) {
47169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  int dispose_count = 0;
472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* c_source = "1 + 2 * 3";
473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  uint16_t* two_byte_source = AsciiToTwoByteString(c_source);
474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {
475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    LocalContext env;
476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(env->GetIsolate());
47769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    TestResource* resource = new TestResource(two_byte_source, &dispose_count);
478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<String> source = String::NewExternal(env->GetIsolate(), resource);
479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<Script> script = v8_compile(source);
480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Local<Value> value = script->Run();
481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK(value->IsNumber());
482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(7, value->Int32Value());
483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK(source->IsExternal());
484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(resource,
485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block             static_cast<TestResource*>(source->GetExternalStringResource()));
486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    String::Encoding encoding = String::UNKNOWN_ENCODING;
487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             source->GetExternalStringResourceBase(&encoding));
489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(String::TWO_BYTE_ENCODING, encoding);
490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
49169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    CHECK_EQ(0, dispose_count);
492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::i_isolate()->compilation_cache()->Clear();
494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllAvailableGarbage();
49569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK_EQ(1, dispose_count);
496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(ScriptUsingOneByteStringResource) {
50069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  int dispose_count = 0;
501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* c_source = "1 + 2 * 3";
502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {
503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    LocalContext env;
504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(env->GetIsolate());
505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    TestOneByteResource* resource =
506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        new TestOneByteResource(i::StrDup(c_source), &dispose_count);
507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<String> source = String::NewExternal(env->GetIsolate(), resource);
508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(source->IsExternalOneByte());
509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             source->GetExternalOneByteStringResource());
511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    String::Encoding encoding = String::UNKNOWN_ENCODING;
512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             source->GetExternalStringResourceBase(&encoding));
514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(String::ONE_BYTE_ENCODING, encoding);
515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<Script> script = v8_compile(source);
516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Local<Value> value = script->Run();
517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK(value->IsNumber());
518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(7, value->Int32Value());
519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
52069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    CHECK_EQ(0, dispose_count);
521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::i_isolate()->compilation_cache()->Clear();
523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllAvailableGarbage();
52469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK_EQ(1, dispose_count);
525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(ScriptMakingExternalString) {
52969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  int dispose_count = 0;
530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  uint16_t* two_byte_source = AsciiToTwoByteString("1 + 2 * 3");
531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {
532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    LocalContext env;
533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(env->GetIsolate());
534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<String> source =
535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        String::NewFromTwoByte(env->GetIsolate(), two_byte_source);
536402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    // Trigger GCs so that the newly allocated string moves to old gen.
537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(source->IsExternal(), false);
540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(source->IsExternalOneByte(), false);
541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    String::Encoding encoding = String::UNKNOWN_ENCODING;
542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(NULL, source->GetExternalStringResourceBase(&encoding));
543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(String::ONE_BYTE_ENCODING, encoding);
54469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    bool success = source->MakeExternal(new TestResource(two_byte_source,
54569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                                         &dispose_count));
546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK(success);
547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<Script> script = v8_compile(source);
548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Local<Value> value = script->Run();
549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK(value->IsNumber());
550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(7, value->Int32Value());
551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
55269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    CHECK_EQ(0, dispose_count);
553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::i_isolate()->compilation_cache()->Clear();
555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
55669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK_EQ(1, dispose_count);
557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(ScriptMakingExternalOneByteString) {
56169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  int dispose_count = 0;
562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* c_source = "1 + 2 * 3";
563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {
564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    LocalContext env;
565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(env->GetIsolate());
566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Local<String> source = v8_str(c_source);
567402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    // Trigger GCs so that the newly allocated string moves to old gen.
568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    bool success = source->MakeExternal(
571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        new TestOneByteResource(i::StrDup(c_source), &dispose_count));
572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK(success);
573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<Script> script = v8_compile(source);
574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Local<Value> value = script->Run();
575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK(value->IsNumber());
576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(7, value->Int32Value());
577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
57869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    CHECK_EQ(0, dispose_count);
579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::i_isolate()->compilation_cache()->Clear();
581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
58269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK_EQ(1, dispose_count);
583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
586402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei PopescuTEST(MakingExternalStringConditions) {
587402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  LocalContext env;
588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
589402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
590402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Free some space in the new space so that we can check freshness.
591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectGarbage(i::NEW_SPACE);
592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectGarbage(i::NEW_SPACE);
593402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
5943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  uint16_t* two_byte_string = AsciiToTwoByteString("s1");
595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<String> small_string =
596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      String::NewFromTwoByte(env->GetIsolate(), two_byte_string);
5973bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  i::DeleteArray(two_byte_string);
5983bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
599402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // We should refuse to externalize newly created small string.
600402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK(!small_string->CanMakeExternal());
601402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Trigger GCs so that the newly allocated string moves to old gen.
602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
604402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Old space strings should be accepted.
605402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK(small_string->CanMakeExternal());
606402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
6073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  two_byte_string = AsciiToTwoByteString("small string 2");
608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  small_string = String::NewFromTwoByte(env->GetIsolate(), two_byte_string);
6093bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  i::DeleteArray(two_byte_string);
6103bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
611402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // We should refuse externalizing newly created small string.
612402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK(!small_string->CanMakeExternal());
613402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  for (int i = 0; i < 100; i++) {
614402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    String::Value value(small_string);
615402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
616402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Frequently used strings should be accepted.
617402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK(small_string->CanMakeExternal());
618402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
619402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  const int buf_size = 10 * 1024;
620402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  char* buf = i::NewArray<char>(buf_size);
621402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  memset(buf, 'a', buf_size);
622402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  buf[buf_size - 1] = '\0';
6233bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
6243bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  two_byte_string = AsciiToTwoByteString(buf);
625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<String> large_string =
626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      String::NewFromTwoByte(env->GetIsolate(), two_byte_string);
627402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  i::DeleteArray(buf);
6283bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  i::DeleteArray(two_byte_string);
629402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Large strings should be immediately accepted.
630402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK(large_string->CanMakeExternal());
631402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
632402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
633402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(MakingExternalOneByteStringConditions) {
635402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  LocalContext env;
636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
637402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
638402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Free some space in the new space so that we can check freshness.
639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectGarbage(i::NEW_SPACE);
640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectGarbage(i::NEW_SPACE);
641402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<String> small_string = String::NewFromUtf8(env->GetIsolate(), "s1");
643402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // We should refuse to externalize newly created small string.
644402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK(!small_string->CanMakeExternal());
645402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Trigger GCs so that the newly allocated string moves to old gen.
646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
648402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Old space strings should be accepted.
649402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK(small_string->CanMakeExternal());
650402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  small_string = String::NewFromUtf8(env->GetIsolate(), "small string 2");
652402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // We should refuse externalizing newly created small string.
653402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK(!small_string->CanMakeExternal());
654402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  for (int i = 0; i < 100; i++) {
655402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    String::Value value(small_string);
656402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
657402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Frequently used strings should be accepted.
658402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK(small_string->CanMakeExternal());
659402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
660402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  const int buf_size = 10 * 1024;
661402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  char* buf = i::NewArray<char>(buf_size);
662402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  memset(buf, 'a', buf_size);
663402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  buf[buf_size - 1] = '\0';
664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<String> large_string = String::NewFromUtf8(env->GetIsolate(), buf);
665402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  i::DeleteArray(buf);
666402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Large strings should be immediately accepted.
667402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK(large_string->CanMakeExternal());
668402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
669402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
670402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(MakingExternalUnalignedOneByteString) {
672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("function cons(a, b) { return a + b; }"
676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "function slice(a) { return a.substring(1); }");
677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Create a cons string that will land in old pointer space.
678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<String> cons = Local<String>::Cast(CompileRun(
679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "cons('abcdefghijklm', 'nopqrstuvwxyz');"));
680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Create a sliced string that will land in old pointer space.
681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<String> slice = Local<String>::Cast(CompileRun(
682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "slice('abcdefghijklmnopqrstuvwxyz');"));
683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Trigger GCs so that the newly allocated string moves to old gen.
685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SimulateFullSpace(CcTest::heap()->old_pointer_space());
686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Turn into external string with unaligned resource data.
690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* c_cons = "_abcdefghijklmnopqrstuvwxyz";
691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool success =
692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      cons->MakeExternal(new TestOneByteResource(i::StrDup(c_cons), NULL, 1));
693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(success);
694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* c_slice = "_bcdefghijklmnopqrstuvwxyz";
695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  success =
696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      slice->MakeExternal(new TestOneByteResource(i::StrDup(c_slice), NULL, 1));
697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(success);
698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Trigger GCs and force evacuation.
700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(i::Heap::kReduceMemoryFootprintMask);
702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(UsingExternalString) {
706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::Factory* factory = CcTest::i_isolate()->factory();
707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {
708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(CcTest::isolate());
709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    uint16_t* two_byte_string = AsciiToTwoByteString("test string");
710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<String> string = String::NewExternal(
711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        CcTest::isolate(), new TestResource(two_byte_string));
712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Trigger GCs so that the newly allocated string moves to old gen.
714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    i::Handle<i::String> isymbol =
717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        factory->InternalizeString(istring);
718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(isymbol->IsInternalizedString());
719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(UsingExternalOneByteString) {
726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::Factory* factory = CcTest::i_isolate()->factory();
727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {
728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(CcTest::isolate());
729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    const char* one_byte_string = "test string";
730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Local<String> string = String::NewExternal(
731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        CcTest::isolate(), new TestOneByteResource(i::StrDup(one_byte_string)));
732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Trigger GCs so that the newly allocated string moves to old gen.
734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    i::Handle<i::String> isymbol =
737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        factory->InternalizeString(istring);
738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(isymbol->IsInternalizedString());
739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
745e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon ClarkeTHREADED_TEST(ScavengeExternalString) {
746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::FLAG_stress_compaction = false;
747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::FLAG_gc_global = false;
74869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  int dispose_count = 0;
7496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  bool in_new_space = false;
750e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  {
751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(CcTest::isolate());
752e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    uint16_t* two_byte_string = AsciiToTwoByteString("test string");
753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<String> string = String::NewExternal(
754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        CcTest::isolate(), new TestResource(two_byte_string, &dispose_count));
755e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CcTest::heap()->CollectGarbage(i::NEW_SPACE);
757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    in_new_space = CcTest::heap()->InNewSpace(*istring);
758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(in_new_space || CcTest::heap()->old_data_space()->Contains(*istring));
75969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    CHECK_EQ(0, dispose_count);
760e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectGarbage(
762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      in_new_space ? i::NEW_SPACE : i::OLD_DATA_SPACE);
76369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK_EQ(1, dispose_count);
764e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
765e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
766e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(ScavengeExternalOneByteString) {
768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::FLAG_stress_compaction = false;
769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::FLAG_gc_global = false;
77069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  int dispose_count = 0;
7716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  bool in_new_space = false;
772e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  {
773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(CcTest::isolate());
774e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    const char* one_byte_string = "test string";
775e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    Local<String> string = String::NewExternal(
776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        CcTest::isolate(),
777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        new TestOneByteResource(i::StrDup(one_byte_string), &dispose_count));
778e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CcTest::heap()->CollectGarbage(i::NEW_SPACE);
780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    in_new_space = CcTest::heap()->InNewSpace(*istring);
781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(in_new_space || CcTest::heap()->old_data_space()->Contains(*istring));
78269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    CHECK_EQ(0, dispose_count);
783e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectGarbage(
785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      in_new_space ? i::NEW_SPACE : i::OLD_DATA_SPACE);
78669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK_EQ(1, dispose_count);
787e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
788e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
789e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass TestOneByteResourceWithDisposeControl : public TestOneByteResource {
7917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch public:
79269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Only used by non-threaded tests, so it can use static fields.
7937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  static int dispose_calls;
79469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  static int dispose_count;
7957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TestOneByteResourceWithDisposeControl(const char* data, bool dispose)
797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : TestOneByteResource(data, &dispose_count), dispose_(dispose) {}
7987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
7997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  void Dispose() {
8007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    ++dispose_calls;
8017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    if (dispose_) delete this;
8027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
8037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch private:
8047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  bool dispose_;
8057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch};
8067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
8077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint TestOneByteResourceWithDisposeControl::dispose_count = 0;
809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint TestOneByteResourceWithDisposeControl::dispose_calls = 0;
8107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
8117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
8127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen MurdochTEST(ExternalStringWithDisposeHandling) {
8137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  const char* c_source = "1 + 2 * 3";
8147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
8157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Use a stack allocated external string resource allocated object.
816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TestOneByteResourceWithDisposeControl::dispose_count = 0;
817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TestOneByteResourceWithDisposeControl::dispose_calls = 0;
818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TestOneByteResourceWithDisposeControl res_stack(i::StrDup(c_source), false);
8197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  {
8207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    LocalContext env;
821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(env->GetIsolate());
822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<String> source =  String::NewExternal(env->GetIsolate(), &res_stack);
823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<Script> script = v8_compile(source);
8247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    Local<Value> value = script->Run();
8257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    CHECK(value->IsNumber());
8267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    CHECK_EQ(7, value->Int32Value());
827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CcTest::heap()->CollectAllAvailableGarbage();
828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(0, TestOneByteResourceWithDisposeControl::dispose_count);
8297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::i_isolate()->compilation_cache()->Clear();
831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllAvailableGarbage();
832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1, TestOneByteResourceWithDisposeControl::dispose_calls);
833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, TestOneByteResourceWithDisposeControl::dispose_count);
8347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
8357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Use a heap allocated external string resource allocated object.
836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TestOneByteResourceWithDisposeControl::dispose_count = 0;
837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TestOneByteResourceWithDisposeControl::dispose_calls = 0;
838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TestOneByteResource* res_heap =
839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      new TestOneByteResourceWithDisposeControl(i::StrDup(c_source), true);
8407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  {
8417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    LocalContext env;
842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(env->GetIsolate());
843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<String> source =  String::NewExternal(env->GetIsolate(), res_heap);
844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<Script> script = v8_compile(source);
8457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    Local<Value> value = script->Run();
8467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    CHECK(value->IsNumber());
8477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    CHECK_EQ(7, value->Int32Value());
848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CcTest::heap()->CollectAllAvailableGarbage();
849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(0, TestOneByteResourceWithDisposeControl::dispose_count);
8507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::i_isolate()->compilation_cache()->Clear();
852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllAvailableGarbage();
853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1, TestOneByteResourceWithDisposeControl::dispose_calls);
854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1, TestOneByteResourceWithDisposeControl::dispose_count);
8557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
8567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
8577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
8583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockTHREADED_TEST(StringConcat) {
8593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  {
8603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    LocalContext env;
861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(env->GetIsolate());
8623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    const char* one_byte_string_1 = "function a_times_t";
8633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    const char* two_byte_string_1 = "wo_plus_b(a, b) {return ";
8643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    const char* one_byte_extern_1 = "a * 2 + b;} a_times_two_plus_b(4, 8) + ";
8653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    const char* two_byte_extern_1 = "a_times_two_plus_b(4, 8) + ";
8663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    const char* one_byte_string_2 = "a_times_two_plus_b(4, 8) + ";
8673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    const char* two_byte_string_2 = "a_times_two_plus_b(4, 8) + ";
8683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    const char* two_byte_extern_2 = "a_times_two_plus_b(1, 2);";
8693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Local<String> left = v8_str(one_byte_string_1);
8703bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
8713bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    uint16_t* two_byte_source = AsciiToTwoByteString(two_byte_string_1);
872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<String> right =
873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        String::NewFromTwoByte(env->GetIsolate(), two_byte_source);
8743bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    i::DeleteArray(two_byte_source);
8753bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
8763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Local<String> source = String::Concat(left, right);
8773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    right = String::NewExternal(
878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        env->GetIsolate(),
879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        new TestOneByteResource(i::StrDup(one_byte_extern_1)));
8803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    source = String::Concat(source, right);
8813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    right = String::NewExternal(
882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        env->GetIsolate(),
8833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block        new TestResource(AsciiToTwoByteString(two_byte_extern_1)));
8843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    source = String::Concat(source, right);
8853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    right = v8_str(one_byte_string_2);
8863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    source = String::Concat(source, right);
8873bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
8883bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    two_byte_source = AsciiToTwoByteString(two_byte_string_2);
889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    right = String::NewFromTwoByte(env->GetIsolate(), two_byte_source);
8903bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    i::DeleteArray(two_byte_source);
8913bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
8923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    source = String::Concat(source, right);
8933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    right = String::NewExternal(
894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        env->GetIsolate(),
8953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block        new TestResource(AsciiToTwoByteString(two_byte_extern_2)));
8963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    source = String::Concat(source, right);
897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<Script> script = v8_compile(source);
8983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Local<Value> value = script->Run();
8993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    CHECK(value->IsNumber());
9003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    CHECK_EQ(68, value->Int32Value());
9013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::i_isolate()->compilation_cache()->Clear();
903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
9053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
9063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
9073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(GlobalProperties) {
909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext env;
910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Object> global = env->Global();
912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  global->Set(v8_str("pi"), v8_num(3.1415926));
913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Value> pi = global->Get(v8_str("pi"));
914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(3.1415926, pi->NumberValue());
915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<typename T>
919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void CheckReturnValue(const T& t, i::Address callback) {
920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::ReturnValue<v8::Value> rv = t.GetReturnValue();
921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::Object** o = *reinterpret_cast<i::Object***>(&rv);
922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(CcTest::isolate(), t.GetIsolate());
923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(t.GetIsolate(), rv.GetIsolate());
924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK((*o)->IsTheHole() || (*o)->IsUndefined());
925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Verify reset
926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool is_runtime = (*o)->IsTheHole();
927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  rv.Set(true);
928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!(*o)->IsTheHole() && !(*o)->IsUndefined());
929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  rv.Set(v8::Handle<v8::Object>());
930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK((*o)->IsTheHole() || (*o)->IsUndefined());
931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(is_runtime, (*o)->IsTheHole());
932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(t.GetIsolate());
934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If CPU profiler is active check that when API callback is invoked
935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // VMState is set to EXTERNAL.
936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (isolate->cpu_profiler()->is_profiling()) {
937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(i::EXTERNAL, isolate->current_vm_state());
938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(isolate->external_callback_scope());
939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(callback, isolate->external_callback_scope()->callback());
940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void handle_callback_impl(const v8::FunctionCallbackInfo<Value>& info,
945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 i::Address callback) {
946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckReturnValue(info, callback);
948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(v8_str("bad value"));
949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(v8_num(102));
950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void handle_callback(const v8::FunctionCallbackInfo<Value>& info) {
954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return handle_callback_impl(info, FUNCTION_ADDR(handle_callback));
955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void handle_callback_2(const v8::FunctionCallbackInfo<Value>& info) {
959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return handle_callback_impl(info, FUNCTION_ADDR(handle_callback_2));
960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void construct_callback(
963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::FunctionCallbackInfo<Value>& info) {
964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckReturnValue(info, FUNCTION_ADDR(construct_callback));
966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.This()->Set(v8_str("x"), v8_num(1));
967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.This()->Set(v8_str("y"), v8_num(2));
968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(v8_str("bad value"));
969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(info.This());
970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void Return239Callback(
974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<String> name, const v8::PropertyCallbackInfo<Value>& info) {
975f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  ApiTestFuzzer::Fuzz();
976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckReturnValue(info, FUNCTION_ADDR(Return239Callback));
977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(v8_str("bad value"));
978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(v8_num(239));
979f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch}
980f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
981f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<typename Handler>
983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void TestFunctionTemplateInitializer(Handler handler,
984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                            Handler handler_2) {
985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Test constructor calls.
986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {
987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LocalContext env;
988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Isolate* isolate = env->GetIsolate();
989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(isolate);
990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Local<v8::FunctionTemplate> fun_templ =
992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v8::FunctionTemplate::New(isolate, handler);
993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Local<Function> fun = fun_templ->GetFunction();
994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    env->Global()->Set(v8_str("obj"), fun);
995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Local<Script> script = v8_compile("obj()");
996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int i = 0; i < 30; i++) {
997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CHECK_EQ(102, script->Run()->Int32Value());
998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Use SetCallHandler to initialize a function template, should work like
1001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the previous one.
1002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {
1003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LocalContext env;
1004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Isolate* isolate = env->GetIsolate();
1005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(isolate);
1006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(isolate);
1008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    fun_templ->SetCallHandler(handler_2);
1009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Local<Function> fun = fun_templ->GetFunction();
1010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    env->Global()->Set(v8_str("obj"), fun);
1011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Local<Script> script = v8_compile("obj()");
1012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int i = 0; i < 30; i++) {
1013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CHECK_EQ(102, script->Run()->Int32Value());
1014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<typename Constructor, typename Accessor>
1020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void TestFunctionTemplateAccessor(Constructor constructor,
1021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                         Accessor accessor) {
1022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
1023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
1024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::FunctionTemplate> fun_templ =
1026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::FunctionTemplate::New(env->GetIsolate(), constructor);
1027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fun_templ->SetClassName(v8_str("funky"));
1028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fun_templ->InstanceTemplate()->SetAccessor(v8_str("m"), accessor);
1029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Function> fun = fun_templ->GetFunction();
1030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->Global()->Set(v8_str("obj"), fun);
1031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Value> result = v8_compile("(new obj()).toString()")->Run();
1032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(v8_str("[object funky]"), result);
1033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("var obj_instance = new obj();");
1034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Script> script;
1035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  script = v8_compile("obj_instance.x");
1036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < 30; i++) {
1037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(1, script->Run()->Int32Value());
1038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  script = v8_compile("obj_instance.m");
1040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < 30; i++) {
1041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(239, script->Run()->Int32Value());
1042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_PROFILED_TEST(FunctionTemplate) {
1047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TestFunctionTemplateInitializer(handle_callback, handle_callback_2);
1048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TestFunctionTemplateAccessor(construct_callback, Return239Callback);
1049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void SimpleCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
1053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ApiTestFuzzer::Fuzz();
1054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckReturnValue(info, FUNCTION_ADDR(SimpleCallback));
1055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(v8_num(51423 + info.Length()));
1056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<typename Callback>
1060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void TestSimpleCallback(Callback callback) {
1061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
1062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
1063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
1064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> object_template =
1066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::ObjectTemplate::New(isolate);
1067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  object_template->Set(isolate, "callback",
1068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       v8::FunctionTemplate::New(isolate, callback));
1069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Object> object = object_template->NewInstance();
1070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  (*env)->Global()->Set(v8_str("callback_object"), object);
1071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Script> script;
1072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  script = v8_compile("callback_object.callback(17)");
1073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < 30; i++) {
1074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(51424, script->Run()->Int32Value());
1075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  script = v8_compile("callback_object.callback(17, 24)");
1077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < 30; i++) {
1078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(51425, script->Run()->Int32Value());
1079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_PROFILED_TEST(SimpleCallback) {
1084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TestSimpleCallback(SimpleCallback);
1085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<typename T>
1089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FastReturnValueCallback(const v8::FunctionCallbackInfo<v8::Value>& info);
1090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// constant return values
1092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic int32_t fast_return_value_int32 = 471;
1093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic uint32_t fast_return_value_uint32 = 571;
1094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic const double kFastReturnValueDouble = 2.7;
1095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// variable return values
1096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic bool fast_return_value_bool = false;
1097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochenum ReturnValueOddball {
1098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  kNullReturnValue,
1099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  kUndefinedReturnValue,
1100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  kEmptyStringReturnValue
1101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
1102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic ReturnValueOddball fast_return_value_void;
1103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic bool fast_return_value_object_is_empty = false;
1104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Helper function to avoid compiler error: insufficient contextual information
1106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// to determine type when applying FUNCTION_ADDR to a template function.
1107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic i::Address address_of(v8::FunctionCallback callback) {
1108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return FUNCTION_ADDR(callback);
1109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<>
1112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FastReturnValueCallback<int32_t>(
1113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::FunctionCallbackInfo<v8::Value>& info) {
1114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckReturnValue(info, address_of(FastReturnValueCallback<int32_t>));
1115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(fast_return_value_int32);
1116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<>
1119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FastReturnValueCallback<uint32_t>(
1120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::FunctionCallbackInfo<v8::Value>& info) {
1121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckReturnValue(info, address_of(FastReturnValueCallback<uint32_t>));
1122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(fast_return_value_uint32);
1123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<>
1126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FastReturnValueCallback<double>(
1127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::FunctionCallbackInfo<v8::Value>& info) {
1128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckReturnValue(info, address_of(FastReturnValueCallback<double>));
1129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(kFastReturnValueDouble);
1130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<>
1133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FastReturnValueCallback<bool>(
1134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::FunctionCallbackInfo<v8::Value>& info) {
1135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckReturnValue(info, address_of(FastReturnValueCallback<bool>));
1136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(fast_return_value_bool);
1137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<>
1140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FastReturnValueCallback<void>(
1141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::FunctionCallbackInfo<v8::Value>& info) {
1142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckReturnValue(info, address_of(FastReturnValueCallback<void>));
1143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (fast_return_value_void) {
1144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kNullReturnValue:
1145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      info.GetReturnValue().SetNull();
1146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
1147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kUndefinedReturnValue:
1148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      info.GetReturnValue().SetUndefined();
1149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
1150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kEmptyStringReturnValue:
1151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      info.GetReturnValue().SetEmptyString();
1152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
1153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<>
1157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FastReturnValueCallback<Object>(
1158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::FunctionCallbackInfo<v8::Value>& info) {
1159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Object> object;
1160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!fast_return_value_object_is_empty) {
1161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    object = Object::New(info.GetIsolate());
1162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(object);
1164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<typename T>
1167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Value> TestFastReturnValues() {
1168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
1169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
1170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::EscapableHandleScope scope(isolate);
1171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> object_template =
1172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::ObjectTemplate::New(isolate);
1173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::FunctionCallback callback = &FastReturnValueCallback<T>;
1174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  object_template->Set(isolate, "callback",
1175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       v8::FunctionTemplate::New(isolate, callback));
1176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Object> object = object_template->NewInstance();
1177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  (*env)->Global()->Set(v8_str("callback_object"), object);
1178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return scope.Escape(CompileRun("callback_object.callback()"));
1179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_PROFILED_TEST(FastReturnValues) {
1183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
1184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(CcTest::isolate());
1185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Value> value;
1186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // check int32_t and uint32_t
1187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int32_t int_values[] = {
1188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      0, 234, -723,
1189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      i::Smi::kMinValue, i::Smi::kMaxValue
1190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  };
1191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (size_t i = 0; i < arraysize(int_values); i++) {
1192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int modifier = -1; modifier <= 1; modifier++) {
1193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      int int_value = int_values[i] + modifier;
1194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // check int32_t
1195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      fast_return_value_int32 = int_value;
1196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      value = TestFastReturnValues<int32_t>();
1197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CHECK(value->IsInt32());
1198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CHECK(fast_return_value_int32 == value->Int32Value());
1199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // check uint32_t
1200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      fast_return_value_uint32 = static_cast<uint32_t>(int_value);
1201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      value = TestFastReturnValues<uint32_t>();
1202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CHECK(value->IsUint32());
1203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CHECK(fast_return_value_uint32 == value->Uint32Value());
1204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // check double
1207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  value = TestFastReturnValues<double>();
1208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(value->IsNumber());
1209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(kFastReturnValueDouble, value->ToNumber()->Value());
1210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // check bool values
1211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < 2; i++) {
1212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    fast_return_value_bool = i == 0;
1213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    value = TestFastReturnValues<bool>();
1214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(value->IsBoolean());
1215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(fast_return_value_bool, value->ToBoolean()->Value());
1216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // check oddballs
1218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ReturnValueOddball oddballs[] = {
1219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      kNullReturnValue,
1220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      kUndefinedReturnValue,
1221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      kEmptyStringReturnValue
1222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  };
1223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (size_t i = 0; i < arraysize(oddballs); i++) {
1224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    fast_return_value_void = oddballs[i];
1225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    value = TestFastReturnValues<void>();
1226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    switch (fast_return_value_void) {
1227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case kNullReturnValue:
1228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        CHECK(value->IsNull());
1229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
1230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case kUndefinedReturnValue:
1231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        CHECK(value->IsUndefined());
1232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
1233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case kEmptyStringReturnValue:
1234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        CHECK(value->IsString());
1235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        CHECK_EQ(0, v8::String::Cast(*value)->Length());
1236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
1237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // check handles
1240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fast_return_value_object_is_empty = false;
1241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  value = TestFastReturnValues<Object>();
1242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(value->IsObject());
1243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fast_return_value_object_is_empty = true;
1244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  value = TestFastReturnValues<Object>();
1245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(value->IsUndefined());
1246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(FunctionTemplateSetLength) {
1250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
1251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
1252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
1253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {
1254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Local<v8::FunctionTemplate> fun_templ =
1255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v8::FunctionTemplate::New(isolate,
1256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                  handle_callback,
1257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                  Handle<v8::Value>(),
1258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                  Handle<v8::Signature>(),
1259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                  23);
1260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Local<Function> fun = fun_templ->GetFunction();
1261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    env->Global()->Set(v8_str("obj"), fun);
1262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<Script> script = v8_compile("obj.length");
1263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(23, script->Run()->Int32Value());
1264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
1266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<v8::FunctionTemplate> fun_templ =
1267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v8::FunctionTemplate::New(isolate, handle_callback);
1268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    fun_templ->SetLength(22);
1269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<Function> fun = fun_templ->GetFunction();
1270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    env->Global()->Set(v8_str("obj"), fun);
1271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<Script> script = v8_compile("obj.length");
1272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(22, script->Run()->Int32Value());
1273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
1275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Without setting length it defaults to 0.
1276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<v8::FunctionTemplate> fun_templ =
1277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v8::FunctionTemplate::New(isolate, handle_callback);
1278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<Function> fun = fun_templ->GetFunction();
1279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    env->Global()->Set(v8_str("obj"), fun);
1280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<Script> script = v8_compile("obj.length");
1281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(0, script->Run()->Int32Value());
1282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1286b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochstatic void* expected_ptr;
1287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void callback(const v8::FunctionCallbackInfo<v8::Value>& args) {
1288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void* ptr = v8::External::Cast(*args.Data())->Value();
1289b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  CHECK_EQ(expected_ptr, ptr);
1290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  args.GetReturnValue().Set(true);
1291b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch}
1292b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1293b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1294b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochstatic void TestExternalPointerWrapping() {
1295b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  LocalContext env;
1296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
1297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
1298b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Value> data =
1300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::External::New(isolate, expected_ptr);
1301b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Object> obj = v8::Object::New(isolate);
1303b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  obj->Set(v8_str("func"),
1304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           v8::FunctionTemplate::New(isolate, callback, data)->GetFunction());
1305b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  env->Global()->Set(v8_str("obj"), obj);
1306b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1307b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  CHECK(CompileRun(
1308b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        "function foo() {\n"
1309b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        "  for (var i = 0; i < 13; i++) obj.func();\n"
1310b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        "}\n"
1311b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        "foo(), true")->BooleanValue());
1312b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch}
1313b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1314b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1315b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben MurdochTHREADED_TEST(ExternalWrap) {
1316b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Check heap allocated object.
1317b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  int* ptr = new int;
1318b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  expected_ptr = ptr;
1319b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  TestExternalPointerWrapping();
1320b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  delete ptr;
1321b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1322b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Check stack allocated object.
1323b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  int foo;
1324b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  expected_ptr = &foo;
1325b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  TestExternalPointerWrapping();
1326b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1327b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Check not aligned addresses.
1328b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  const int n = 100;
1329b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  char* s = new char[n];
1330b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  for (int i = 0; i < n; i++) {
1331b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    expected_ptr = s + i;
1332b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    TestExternalPointerWrapping();
1333b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
1334b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1335b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  delete[] s;
1336b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1337b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Check several invalid addresses.
1338b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  expected_ptr = reinterpret_cast<void*>(1);
1339b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  TestExternalPointerWrapping();
1340b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1341b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  expected_ptr = reinterpret_cast<void*>(0xdeadbeef);
1342b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  TestExternalPointerWrapping();
1343b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1344b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  expected_ptr = reinterpret_cast<void*>(0xdeadbeef + 1);
1345b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  TestExternalPointerWrapping();
1346b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1347b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch#if defined(V8_HOST_ARCH_X64)
13481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Check a value with a leading 1 bit in x64 Smi encoding.
13491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  expected_ptr = reinterpret_cast<void*>(0x400000000);
13501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestExternalPointerWrapping();
13511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1352b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  expected_ptr = reinterpret_cast<void*>(0xdeadbeefdeadbeef);
1353b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  TestExternalPointerWrapping();
1354b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1355b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  expected_ptr = reinterpret_cast<void*>(0xdeadbeefdeadbeef + 1);
1356b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  TestExternalPointerWrapping();
1357b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch#endif
1358b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch}
1359b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1360b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(FindInstanceInPrototypeChain) {
1362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext env;
1363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
1364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
1365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::FunctionTemplate> base = v8::FunctionTemplate::New(isolate);
1367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::FunctionTemplate> derived = v8::FunctionTemplate::New(isolate);
1368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::FunctionTemplate> other = v8::FunctionTemplate::New(isolate);
1369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  derived->Inherit(base);
1370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<v8::Function> base_function = base->GetFunction();
1372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<v8::Function> derived_function = derived->GetFunction();
1373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<v8::Function> other_function = other->GetFunction();
1374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<v8::Object> base_instance = base_function->NewInstance();
1376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<v8::Object> derived_instance = derived_function->NewInstance();
1377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<v8::Object> derived_instance2 = derived_function->NewInstance();
1378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<v8::Object> other_instance = other_function->NewInstance();
1379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  derived_instance2->Set(v8_str("__proto__"), derived_instance);
1380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  other_instance->Set(v8_str("__proto__"), derived_instance2);
1381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // base_instance is only an instance of base.
1383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(base_instance,
1384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block           base_instance->FindInstanceInPrototypeChain(base));
1385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(base_instance->FindInstanceInPrototypeChain(derived).IsEmpty());
1386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(base_instance->FindInstanceInPrototypeChain(other).IsEmpty());
1387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // derived_instance is an instance of base and derived.
1389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(derived_instance,
1390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block           derived_instance->FindInstanceInPrototypeChain(base));
1391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(derived_instance,
1392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block           derived_instance->FindInstanceInPrototypeChain(derived));
1393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(derived_instance->FindInstanceInPrototypeChain(other).IsEmpty());
1394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // other_instance is an instance of other and its immediate
1396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // prototype derived_instance2 is an instance of base and derived.
1397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Note, derived_instance is an instance of base and derived too,
1398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // but it comes after derived_instance2 in the prototype chain of
1399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // other_instance.
1400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(derived_instance2,
1401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block           other_instance->FindInstanceInPrototypeChain(base));
1402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(derived_instance2,
1403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block           other_instance->FindInstanceInPrototypeChain(derived));
1404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(other_instance,
1405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block           other_instance->FindInstanceInPrototypeChain(other));
1406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockTHREADED_TEST(TinyInteger) {
14103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  LocalContext env;
1411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
1412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
1413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int32_t value = 239;
1415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
1416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  value_obj = v8::Integer::New(isolate, value);
14193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
14203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
14213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
14223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
14233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockTHREADED_TEST(BigSmiInteger) {
14243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  LocalContext env;
1425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
1426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
1427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int32_t value = i::Smi::kMaxValue;
14293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // We cannot add one to a Smi::kMaxValue without wrapping.
1430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (i::SmiValuesAre31Bits()) {
14313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    CHECK(i::Smi::IsValid(value));
14323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    CHECK(!i::Smi::IsValid(value + 1));
1433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
1435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    value_obj = v8::Integer::New(isolate, value);
14383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
14393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
14403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
14413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
14423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
14433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockTHREADED_TEST(BigInteger) {
14443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  LocalContext env;
1445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
1446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
1447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // We cannot add one to a Smi::kMaxValue without wrapping.
1449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (i::SmiValuesAre31Bits()) {
14503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // The casts allow this to compile, even if Smi::kMaxValue is 2^31-1.
14513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // The code will not be run in that case, due to the "if" guard.
14523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    int32_t value =
14533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block        static_cast<int32_t>(static_cast<uint32_t>(i::Smi::kMaxValue) + 1);
14543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    CHECK(value > i::Smi::kMaxValue);
14553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    CHECK(!i::Smi::IsValid(value));
1456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
1458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    value_obj = v8::Integer::New(isolate, value);
14613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
14623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
14633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
14643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
14653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
14663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockTHREADED_TEST(TinyUnsignedInteger) {
14673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  LocalContext env;
1468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
1469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
1470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  uint32_t value = 239;
1472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
1474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  value_obj = v8::Integer::NewFromUnsigned(isolate, value);
14773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
14783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
14793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
14803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
14813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockTHREADED_TEST(BigUnsignedSmiInteger) {
14823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  LocalContext env;
1483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
1484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
1485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue);
14873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK(i::Smi::IsValid(value));
14883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK(!i::Smi::IsValid(value + 1));
1489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
1491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  value_obj = v8::Integer::NewFromUnsigned(isolate, value);
14943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
14953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
14963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
14973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
14983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockTHREADED_TEST(BigUnsignedInteger) {
14993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  LocalContext env;
1500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
1501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
1502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
15033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue) + 1;
15043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK(value > static_cast<uint32_t>(i::Smi::kMaxValue));
15053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK(!i::Smi::IsValid(value));
1506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
1508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  value_obj = v8::Integer::NewFromUnsigned(isolate, value);
15113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
15123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
15133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
15143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
15153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockTHREADED_TEST(OutOfSignedRangeUnsignedInteger) {
15163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  LocalContext env;
1517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
1518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
1519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
15203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  uint32_t INT32_MAX_AS_UINT = (1U << 31) - 1;
15213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  uint32_t value = INT32_MAX_AS_UINT + 1;
15223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK(value > INT32_MAX_AS_UINT);  // No overflow.
1523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
1525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  value_obj = v8::Integer::NewFromUnsigned(isolate, value);
15283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
15293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
15303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
15313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
15323fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochTHREADED_TEST(IsNativeError) {
15333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  LocalContext env;
1534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
15353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  v8::Handle<Value> syntax_error = CompileRun(
15363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      "var out = 0; try { eval(\"#\"); } catch(x) { out = x; } out; ");
15373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK(syntax_error->IsNativeError());
15383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  v8::Handle<Value> not_error = CompileRun("{a:42}");
15393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK(!not_error->IsNativeError());
15403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  v8::Handle<Value> not_object = CompileRun("42");
15413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK(!not_object->IsNativeError());
15423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
15433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
15443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(ArgumentsObject) {
1546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
1547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
1548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<Value> arguments_object =
1549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CompileRun("var out = 0; (function(){ out = arguments; })(1,2,3); out;");
1550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(arguments_object->IsArgumentsObject());
1551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<Value> array = CompileRun("[1,2,3]");
1552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!array->IsArgumentsObject());
1553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<Value> object = CompileRun("{a:42}");
1554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!object->IsArgumentsObject());
1555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(IsMapOrSet) {
1559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
1560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
1561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<Value> map = CompileRun("new Map()");
1562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<Value> set = CompileRun("new Set()");
1563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<Value> weak_map = CompileRun("new WeakMap()");
1564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<Value> weak_set = CompileRun("new WeakSet()");
1565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(map->IsMap());
1566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(set->IsSet());
1567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(weak_map->IsWeakMap());
1568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(weak_set->IsWeakSet());
1569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!map->IsSet());
1571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!map->IsWeakMap());
1572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!map->IsWeakSet());
1573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!set->IsMap());
1575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!set->IsWeakMap());
1576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!set->IsWeakSet());
1577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!weak_map->IsMap());
1579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!weak_map->IsSet());
1580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!weak_map->IsWeakSet());
1581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!weak_set->IsMap());
1583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!weak_set->IsSet());
1584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!weak_set->IsWeakMap());
1585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<Value> object = CompileRun("{a:42}");
1587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!object->IsMap());
1588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!object->IsSet());
1589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!object->IsWeakMap());
1590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!object->IsWeakSet());
1591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
15943fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochTHREADED_TEST(StringObject) {
15953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  LocalContext env;
1596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
15973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  v8::Handle<Value> boxed_string = CompileRun("new String(\"test\")");
15983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK(boxed_string->IsStringObject());
15993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  v8::Handle<Value> unboxed_string = CompileRun("\"test\"");
16003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK(!unboxed_string->IsStringObject());
16013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  v8::Handle<Value> boxed_not_string = CompileRun("new Number(42)");
16023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK(!boxed_not_string->IsStringObject());
16033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  v8::Handle<Value> not_object = CompileRun("0");
16043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK(!not_object->IsStringObject());
16053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  v8::Handle<v8::StringObject> as_boxed = boxed_string.As<v8::StringObject>();
16063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK(!as_boxed.IsEmpty());
1607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::String> the_string = as_boxed->ValueOf();
16083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK(!the_string.IsEmpty());
16093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ExpectObject("\"test\"", the_string);
16103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  v8::Handle<v8::Value> new_boxed_string = v8::StringObject::New(the_string);
16113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK(new_boxed_string->IsStringObject());
16123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  as_boxed = new_boxed_string.As<v8::StringObject>();
1613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  the_string = as_boxed->ValueOf();
16143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK(!the_string.IsEmpty());
16153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ExpectObject("\"test\"", the_string);
16163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
16173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
16183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
16193fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochTHREADED_TEST(NumberObject) {
16203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  LocalContext env;
1621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
16223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  v8::Handle<Value> boxed_number = CompileRun("new Number(42)");
16233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK(boxed_number->IsNumberObject());
16243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  v8::Handle<Value> unboxed_number = CompileRun("42");
16253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK(!unboxed_number->IsNumberObject());
16263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  v8::Handle<Value> boxed_not_number = CompileRun("new Boolean(false)");
16273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK(!boxed_not_number->IsNumberObject());
16283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  v8::Handle<v8::NumberObject> as_boxed = boxed_number.As<v8::NumberObject>();
16293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK(!as_boxed.IsEmpty());
1630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  double the_number = as_boxed->ValueOf();
16313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK_EQ(42.0, the_number);
1632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Value> new_boxed_number =
1633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::NumberObject::New(env->GetIsolate(), 43);
16343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK(new_boxed_number->IsNumberObject());
16353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  as_boxed = new_boxed_number.As<v8::NumberObject>();
1636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  the_number = as_boxed->ValueOf();
16373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK_EQ(43.0, the_number);
16383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
16393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
16403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
16413fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochTHREADED_TEST(BooleanObject) {
16423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  LocalContext env;
1643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
16443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  v8::Handle<Value> boxed_boolean = CompileRun("new Boolean(true)");
16453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK(boxed_boolean->IsBooleanObject());
16463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  v8::Handle<Value> unboxed_boolean = CompileRun("true");
16473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK(!unboxed_boolean->IsBooleanObject());
16483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  v8::Handle<Value> boxed_not_boolean = CompileRun("new Number(42)");
16493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK(!boxed_not_boolean->IsBooleanObject());
16503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  v8::Handle<v8::BooleanObject> as_boxed =
16513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      boxed_boolean.As<v8::BooleanObject>();
16523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK(!as_boxed.IsEmpty());
1653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool the_boolean = as_boxed->ValueOf();
16543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK_EQ(true, the_boolean);
16553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  v8::Handle<v8::Value> boxed_true = v8::BooleanObject::New(true);
16563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  v8::Handle<v8::Value> boxed_false = v8::BooleanObject::New(false);
16573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK(boxed_true->IsBooleanObject());
16583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK(boxed_false->IsBooleanObject());
16593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  as_boxed = boxed_true.As<v8::BooleanObject>();
1660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(true, as_boxed->ValueOf());
16613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  as_boxed = boxed_false.As<v8::BooleanObject>();
1662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(false, as_boxed->ValueOf());
1663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(PrimitiveAndWrappedBooleans) {
1667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
1668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
1669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Value> primitive_false = Boolean::New(env->GetIsolate(), false);
1671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(primitive_false->IsBoolean());
1672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!primitive_false->IsBooleanObject());
1673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!primitive_false->BooleanValue());
1674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!primitive_false->IsTrue());
1675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(primitive_false->IsFalse());
1676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Value> false_value = BooleanObject::New(false);
1678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!false_value->IsBoolean());
1679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(false_value->IsBooleanObject());
1680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(false_value->BooleanValue());
1681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!false_value->IsTrue());
1682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!false_value->IsFalse());
1683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<BooleanObject> false_boolean_object = false_value.As<BooleanObject>();
1685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!false_boolean_object->IsBoolean());
1686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(false_boolean_object->IsBooleanObject());
1687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // TODO(svenpanne) Uncomment when BooleanObject::BooleanValue() is deleted.
1688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // CHECK(false_boolean_object->BooleanValue());
1689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!false_boolean_object->ValueOf());
1690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!false_boolean_object->IsTrue());
1691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!false_boolean_object->IsFalse());
1692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Value> primitive_true = Boolean::New(env->GetIsolate(), true);
1694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(primitive_true->IsBoolean());
1695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!primitive_true->IsBooleanObject());
1696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(primitive_true->BooleanValue());
1697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(primitive_true->IsTrue());
1698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!primitive_true->IsFalse());
1699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Value> true_value = BooleanObject::New(true);
1701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!true_value->IsBoolean());
1702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(true_value->IsBooleanObject());
1703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(true_value->BooleanValue());
1704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!true_value->IsTrue());
1705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!true_value->IsFalse());
1706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<BooleanObject> true_boolean_object = true_value.As<BooleanObject>();
1708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!true_boolean_object->IsBoolean());
1709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(true_boolean_object->IsBooleanObject());
1710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // TODO(svenpanne) Uncomment when BooleanObject::BooleanValue() is deleted.
1711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // CHECK(true_boolean_object->BooleanValue());
1712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(true_boolean_object->ValueOf());
1713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!true_boolean_object->IsTrue());
1714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!true_boolean_object->IsFalse());
17153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
17163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
17173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(Number) {
1719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext env;
1720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
1721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  double PI = 3.1415926;
1722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::Number> pi_obj = v8::Number::New(env->GetIsolate(), PI);
1723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(PI, pi_obj->NumberValue());
1724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(ToNumber) {
1728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext env;
1729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
1730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
1731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<String> str = v8_str("3.1415926");
1732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(3.1415926, str->NumberValue());
1733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Boolean> t = v8::True(isolate);
1734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1.0, t->NumberValue());
1735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Boolean> f = v8::False(isolate);
1736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0.0, f->NumberValue());
1737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(Date) {
1741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext env;
1742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
1743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  double PI = 3.1415926;
1744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Value> date = v8::Date::New(env->GetIsolate(), PI);
1745257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_EQ(3.0, date->NumberValue());
1746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  date.As<v8::Date>()->Set(v8_str("property"),
1747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           v8::Integer::New(env->GetIsolate(), 42));
1748257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_EQ(42, date.As<v8::Date>()->Get(v8_str("property"))->Int32Value());
1749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(Boolean) {
1753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext env;
1754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
1755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
1756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Boolean> t = v8::True(isolate);
1757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(t->Value());
1758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Boolean> f = v8::False(isolate);
1759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(!f->Value());
1760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Primitive> u = v8::Undefined(isolate);
1761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(!u->BooleanValue());
1762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Primitive> n = v8::Null(isolate);
1763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(!n->BooleanValue());
1764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<String> str1 = v8_str("");
1765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(!str1->BooleanValue());
1766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<String> str2 = v8_str("x");
1767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(str2->BooleanValue());
1768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!v8::Number::New(isolate, 0)->BooleanValue());
1769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(v8::Number::New(isolate, -1)->BooleanValue());
1770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(v8::Number::New(isolate, 1)->BooleanValue());
1771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(v8::Number::New(isolate, 42)->BooleanValue());
1772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(!v8_compile("NaN")->Run()->BooleanValue());
1773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void DummyCallHandler(const v8::FunctionCallbackInfo<v8::Value>& args) {
1777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
1778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  args.GetReturnValue().Set(v8_num(13.4));
1779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void GetM(Local<String> name,
1783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 const v8::PropertyCallbackInfo<v8::Value>& info) {
1784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
1785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(v8_num(876));
1786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(GlobalPrototype) {
1790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
1791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
1792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::FunctionTemplate> func_templ =
1793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::FunctionTemplate::New(isolate);
1794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  func_templ->PrototypeTemplate()->Set(
1795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate, "dummy", v8::FunctionTemplate::New(isolate, DummyCallHandler));
1796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<ObjectTemplate> templ = func_templ->InstanceTemplate();
1797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  templ->Set(isolate, "x", v8_num(200));
1798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  templ->SetAccessor(v8_str("m"), GetM);
1799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext env(0, templ);
18003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::Handle<Script> script(v8_compile("dummy()"));
18013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::Handle<Value> result(script->Run());
1802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(13.4, result->NumberValue());
1803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(200, v8_compile("x")->Run()->Int32Value());
1804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(876, v8_compile("m")->Run()->Int32Value());
1805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(ObjectTemplate) {
1809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
1810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
1811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> templ1 = ObjectTemplate::New(isolate);
1812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  templ1->Set(isolate, "x", v8_num(10));
1813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  templ1->Set(isolate, "y", v8_num(13));
1814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext env;
1815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<v8::Object> instance1 = templ1->NewInstance();
1816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env->Global()->Set(v8_str("p"), instance1);
1817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(v8_compile("(p.x == 10)")->Run()->BooleanValue());
1818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(v8_compile("(p.y == 13)")->Run()->BooleanValue());
1819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(isolate);
1820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fun->PrototypeTemplate()->Set(isolate, "nirk", v8_num(123));
1821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<ObjectTemplate> templ2 = fun->InstanceTemplate();
1822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  templ2->Set(isolate, "a", v8_num(12));
1823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  templ2->Set(isolate, "b", templ1);
1824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<v8::Object> instance2 = templ2->NewInstance();
1825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env->Global()->Set(v8_str("q"), instance2);
1826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(v8_compile("(q.nirk == 123)")->Run()->BooleanValue());
1827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(v8_compile("(q.a == 12)")->Run()->BooleanValue());
1828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(v8_compile("(q.b.x == 10)")->Run()->BooleanValue());
1829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(v8_compile("(q.b.y == 13)")->Run()->BooleanValue());
1830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void GetFlabby(const v8::FunctionCallbackInfo<v8::Value>& args) {
1834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
1835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  args.GetReturnValue().Set(v8_num(17.2));
1836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void GetKnurd(Local<String> property,
1840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     const v8::PropertyCallbackInfo<v8::Value>& info) {
1841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
1842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(v8_num(15.2));
1843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(DescriptorInheritance) {
1847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
1848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
1849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::FunctionTemplate> super = v8::FunctionTemplate::New(isolate);
1850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  super->PrototypeTemplate()->Set(isolate, "flabby",
1851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                  v8::FunctionTemplate::New(isolate,
1852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                            GetFlabby));
1853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  super->PrototypeTemplate()->Set(isolate, "PI", v8_num(3.14));
1854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  super->InstanceTemplate()->SetAccessor(v8_str("knurd"), GetKnurd);
1856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::FunctionTemplate> base1 = v8::FunctionTemplate::New(isolate);
1858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  base1->Inherit(super);
1859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  base1->PrototypeTemplate()->Set(isolate, "v1", v8_num(20.1));
1860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::FunctionTemplate> base2 = v8::FunctionTemplate::New(isolate);
1862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  base2->Inherit(super);
1863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  base2->PrototypeTemplate()->Set(isolate, "v2", v8_num(10.1));
1864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext env;
1866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env->Global()->Set(v8_str("s"), super->GetFunction());
1868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env->Global()->Set(v8_str("base1"), base1->GetFunction());
1869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env->Global()->Set(v8_str("base2"), base2->GetFunction());
1870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Checks right __proto__ chain.
1872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(CompileRun("base1.prototype.__proto__ == s.prototype")->BooleanValue());
1873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(CompileRun("base2.prototype.__proto__ == s.prototype")->BooleanValue());
1874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(v8_compile("s.prototype.PI == 3.14")->Run()->BooleanValue());
1876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Instance accessor should not be visible on function object or its prototype
1878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(CompileRun("s.knurd == undefined")->BooleanValue());
1879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(CompileRun("s.prototype.knurd == undefined")->BooleanValue());
1880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(CompileRun("base1.prototype.knurd == undefined")->BooleanValue());
1881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env->Global()->Set(v8_str("obj"),
1883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     base1->GetFunction()->NewInstance());
1884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(17.2, v8_compile("obj.flabby()")->Run()->NumberValue());
1885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(v8_compile("'flabby' in obj")->Run()->BooleanValue());
1886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(15.2, v8_compile("obj.knurd")->Run()->NumberValue());
1887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(v8_compile("'knurd' in obj")->Run()->BooleanValue());
1888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(20.1, v8_compile("obj.v1")->Run()->NumberValue());
1889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env->Global()->Set(v8_str("obj2"),
1891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     base2->GetFunction()->NewInstance());
1892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(17.2, v8_compile("obj2.flabby()")->Run()->NumberValue());
1893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(v8_compile("'flabby' in obj2")->Run()->BooleanValue());
1894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(15.2, v8_compile("obj2.knurd")->Run()->NumberValue());
1895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(v8_compile("'knurd' in obj2")->Run()->BooleanValue());
1896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(10.1, v8_compile("obj2.v2")->Run()->NumberValue());
1897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // base1 and base2 cannot cross reference to each's prototype
1899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(v8_compile("obj.v2")->Run()->IsUndefined());
1900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(v8_compile("obj2.v1")->Run()->IsUndefined());
1901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint echo_named_call_count;
1905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void EchoNamedProperty(Local<String> name,
1908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              const v8::PropertyCallbackInfo<v8::Value>& info) {
1909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
1910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(v8_str("data"), info.Data());
1911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  echo_named_call_count++;
1912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(name);
1913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
19163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Helper functions for Interceptor/Accessor interaction tests
19173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid SimpleAccessorGetter(Local<String> name,
1919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          const v8::PropertyCallbackInfo<v8::Value>& info) {
1920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Object> self = Handle<Object>::Cast(info.This());
1921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(
1922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      self->Get(String::Concat(v8_str("accessor_"), name)));
19233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
19243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
19253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid SimpleAccessorSetter(Local<String> name, Local<Value> value,
1926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          const v8::PropertyCallbackInfo<void>& info) {
1927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Object> self = Handle<Object>::Cast(info.This());
19283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  self->Set(String::Concat(v8_str("accessor_"), name), value);
19293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
19303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid SymbolAccessorGetter(Local<Name> name,
1932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          const v8::PropertyCallbackInfo<v8::Value>& info) {
1933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(name->IsSymbol());
1934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Symbol> sym = Local<Symbol>::Cast(name);
1935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (sym->Name()->IsUndefined())
1936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
1937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SimpleAccessorGetter(Local<String>::Cast(sym->Name()), info);
1938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid SymbolAccessorSetter(Local<Name> name, Local<Value> value,
1941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          const v8::PropertyCallbackInfo<void>& info) {
1942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(name->IsSymbol());
1943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Symbol> sym = Local<Symbol>::Cast(name);
1944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (sym->Name()->IsUndefined())
1945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
1946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SimpleAccessorSetter(Local<String>::Cast(sym->Name()), value, info);
1947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid EmptyInterceptorGetter(Local<String> name,
1950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            const v8::PropertyCallbackInfo<v8::Value>& info) {
19513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
19523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid EmptyInterceptorSetter(Local<String> name,
1954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            Local<Value> value,
1955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            const v8::PropertyCallbackInfo<v8::Value>& info) {
19563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
19573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InterceptorGetter(Local<String> name,
1959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       const v8::PropertyCallbackInfo<v8::Value>& info) {
19603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Intercept names that start with 'interceptor_'.
1961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  String::Utf8Value utf8(name);
1962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  char* name_str = *utf8;
19633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  char prefix[] = "interceptor_";
19643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int i;
19653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (i = 0; name_str[i] && prefix[i]; ++i) {
1966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (name_str[i] != prefix[i]) return;
19673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Object> self = Handle<Object>::Cast(info.This());
1969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(self->GetHiddenValue(v8_str(name_str + i)));
19703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
19713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InterceptorSetter(Local<String> name,
1973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       Local<Value> value,
1974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       const v8::PropertyCallbackInfo<v8::Value>& info) {
1975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Intercept accesses that set certain integer values, for which the name does
1976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // not start with 'accessor_'.
1977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  String::Utf8Value utf8(name);
1978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  char* name_str = *utf8;
1979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  char prefix[] = "accessor_";
1980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int i;
1981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (i = 0; name_str[i] && prefix[i]; ++i) {
1982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (name_str[i] != prefix[i]) break;
1983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!prefix[i]) return;
1985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
19863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (value->IsInt32() && value->Int32Value() < 10000) {
1987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<Object> self = Handle<Object>::Cast(info.This());
19883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    self->SetHiddenValue(name, value);
1989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    info.GetReturnValue().Set(value);
19903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
19913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
19923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
19933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid AddAccessor(Handle<FunctionTemplate> templ,
19943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 Handle<String> name,
1995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 v8::AccessorGetterCallback getter,
1996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 v8::AccessorSetterCallback setter) {
19973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  templ->PrototypeTemplate()->SetAccessor(name, getter, setter);
19983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
19993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
20003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid AddInterceptor(Handle<FunctionTemplate> templ,
2001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                    v8::NamedPropertyGetterCallback getter,
2002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                    v8::NamedPropertySetterCallback setter) {
20033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  templ->InstanceTemplate()->SetNamedPropertyHandler(getter, setter);
20043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
20053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid AddAccessor(Handle<FunctionTemplate> templ,
2008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 Handle<Name> name,
2009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 v8::AccessorNameGetterCallback getter,
2010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 v8::AccessorNameSetterCallback setter) {
2011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  templ->PrototypeTemplate()->SetAccessor(name, getter, setter);
2012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
20153ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochTHREADED_TEST(EmptyInterceptorDoesNotShadowAccessors) {
2016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(CcTest::isolate());
2017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<FunctionTemplate> parent = FunctionTemplate::New(CcTest::isolate());
2018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<FunctionTemplate> child = FunctionTemplate::New(CcTest::isolate());
20193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  child->Inherit(parent);
20203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  AddAccessor(parent, v8_str("age"),
20213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              SimpleAccessorGetter, SimpleAccessorSetter);
20223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter);
20233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LocalContext env;
20243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  env->Global()->Set(v8_str("Child"), child->GetFunction());
20253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileRun("var child = new Child;"
20263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             "child.age = 10;");
20273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExpectBoolean("child.hasOwnProperty('age')", false);
20283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExpectInt32("child.age", 10);
20293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExpectInt32("child.accessor_age", 10);
20303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
20313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(ExecutableAccessorIsPreservedOnAttributeChange) {
2034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
2035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
2036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
2037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Value> res = CompileRun("var a = []; a;");
2038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::Handle<i::JSObject> a(v8::Utils::OpenHandle(v8::Object::Cast(*res)));
2039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(a->map()->instance_descriptors()->IsFixedArray());
2040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_GT(i::FixedArray::cast(a->map()->instance_descriptors())->length(), 0);
2041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("Object.defineProperty(a, 'length', { writable: false });");
2042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(i::FixedArray::cast(a->map()->instance_descriptors())->length(), 0);
2043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // But we should still have an ExecutableAccessorInfo.
2044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
2045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::LookupResult lookup(i_isolate);
2046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::Handle<i::String> name(v8::Utils::OpenHandle(*v8_str("length")));
2047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::LookupIterator it(a, name, i::LookupIterator::OWN_SKIP_INTERCEPTOR);
2048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(i::LookupIterator::ACCESSOR, it.state());
2049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(it.GetAccessors()->IsExecutableAccessorInfo());
2050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(EmptyInterceptorBreakTransitions) {
2054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(CcTest::isolate());
2055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
2056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter);
2057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
2058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->Global()->Set(v8_str("Constructor"), templ->GetFunction());
2059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("var o1 = new Constructor;"
2060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "o1.a = 1;"  // Ensure a and x share the descriptor array.
2061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "Object.defineProperty(o1, 'x', {value: 10});");
2062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("var o2 = new Constructor;"
2063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "o2.a = 1;"
2064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "Object.defineProperty(o2, 'x', {value: 10});");
2065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
20683ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochTHREADED_TEST(EmptyInterceptorDoesNotShadowJSAccessors) {
2069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
2070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
2071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<FunctionTemplate> parent = FunctionTemplate::New(isolate);
2072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<FunctionTemplate> child = FunctionTemplate::New(isolate);
20733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  child->Inherit(parent);
20743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter);
20753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LocalContext env;
20763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  env->Global()->Set(v8_str("Child"), child->GetFunction());
20773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileRun("var child = new Child;"
20783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             "var parent = child.__proto__;"
20793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             "Object.defineProperty(parent, 'age', "
20803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             "  {get: function(){ return this.accessor_age; }, "
20813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             "   set: function(v){ this.accessor_age = v; }, "
20823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             "   enumerable: true, configurable: true});"
20833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             "child.age = 10;");
20843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExpectBoolean("child.hasOwnProperty('age')", false);
20853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExpectInt32("child.age", 10);
20863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExpectInt32("child.accessor_age", 10);
20873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
20883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
20903ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochTHREADED_TEST(EmptyInterceptorDoesNotAffectJSProperties) {
2091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
2092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
2093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<FunctionTemplate> parent = FunctionTemplate::New(isolate);
2094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<FunctionTemplate> child = FunctionTemplate::New(isolate);
20953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  child->Inherit(parent);
20963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter);
20973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LocalContext env;
20983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  env->Global()->Set(v8_str("Child"), child->GetFunction());
20993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileRun("var child = new Child;"
21003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             "var parent = child.__proto__;"
21013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             "parent.name = 'Alice';");
21023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExpectBoolean("child.hasOwnProperty('name')", false);
21033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExpectString("child.name", "Alice");
21043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileRun("child.name = 'Bob';");
21053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExpectString("child.name", "Bob");
21063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExpectBoolean("child.hasOwnProperty('name')", true);
21073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExpectString("parent.name", "Alice");
21083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
21093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21113ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochTHREADED_TEST(SwitchFromInterceptorToAccessor) {
2112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(CcTest::isolate());
2113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
21143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  AddAccessor(templ, v8_str("age"),
21153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              SimpleAccessorGetter, SimpleAccessorSetter);
21163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
21173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LocalContext env;
21183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  env->Global()->Set(v8_str("Obj"), templ->GetFunction());
21193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileRun("var obj = new Obj;"
21203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             "function setAge(i){ obj.age = i; };"
21213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             "for(var i = 0; i <= 10000; i++) setAge(i);");
21223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // All i < 10000 go to the interceptor.
21233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExpectInt32("obj.interceptor_age", 9999);
21243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The last i goes to the accessor.
21253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExpectInt32("obj.accessor_age", 10000);
21263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
21273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21293ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochTHREADED_TEST(SwitchFromAccessorToInterceptor) {
2130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(CcTest::isolate());
2131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
21323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  AddAccessor(templ, v8_str("age"),
21333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              SimpleAccessorGetter, SimpleAccessorSetter);
21343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
21353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LocalContext env;
21363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  env->Global()->Set(v8_str("Obj"), templ->GetFunction());
21373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileRun("var obj = new Obj;"
21383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             "function setAge(i){ obj.age = i; };"
21393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             "for(var i = 20000; i >= 9999; i--) setAge(i);");
21403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // All i >= 10000 go to the accessor.
21413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExpectInt32("obj.accessor_age", 10000);
21423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The last i goes to the interceptor.
21433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExpectInt32("obj.interceptor_age", 9999);
21443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
21453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21473ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochTHREADED_TEST(SwitchFromInterceptorToAccessorWithInheritance) {
2148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(CcTest::isolate());
2149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<FunctionTemplate> parent = FunctionTemplate::New(CcTest::isolate());
2150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<FunctionTemplate> child = FunctionTemplate::New(CcTest::isolate());
21513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  child->Inherit(parent);
21523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  AddAccessor(parent, v8_str("age"),
21533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              SimpleAccessorGetter, SimpleAccessorSetter);
21543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  AddInterceptor(child, InterceptorGetter, InterceptorSetter);
21553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LocalContext env;
21563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  env->Global()->Set(v8_str("Child"), child->GetFunction());
21573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileRun("var child = new Child;"
21583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             "function setAge(i){ child.age = i; };"
21593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             "for(var i = 0; i <= 10000; i++) setAge(i);");
21603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // All i < 10000 go to the interceptor.
21613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExpectInt32("child.interceptor_age", 9999);
21623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The last i goes to the accessor.
21633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExpectInt32("child.accessor_age", 10000);
21643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
21653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21673ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochTHREADED_TEST(SwitchFromAccessorToInterceptorWithInheritance) {
2168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(CcTest::isolate());
2169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<FunctionTemplate> parent = FunctionTemplate::New(CcTest::isolate());
2170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<FunctionTemplate> child = FunctionTemplate::New(CcTest::isolate());
21713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  child->Inherit(parent);
21723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  AddAccessor(parent, v8_str("age"),
21733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              SimpleAccessorGetter, SimpleAccessorSetter);
21743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  AddInterceptor(child, InterceptorGetter, InterceptorSetter);
21753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LocalContext env;
21763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  env->Global()->Set(v8_str("Child"), child->GetFunction());
21773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileRun("var child = new Child;"
21783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             "function setAge(i){ child.age = i; };"
21793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             "for(var i = 20000; i >= 9999; i--) setAge(i);");
21803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // All i >= 10000 go to the accessor.
21813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExpectInt32("child.accessor_age", 10000);
21823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The last i goes to the interceptor.
21833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExpectInt32("child.interceptor_age", 9999);
21843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
21853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21873ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochTHREADED_TEST(SwitchFromInterceptorToJSAccessor) {
2188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(CcTest::isolate());
2189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
21903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
21913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LocalContext env;
21923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  env->Global()->Set(v8_str("Obj"), templ->GetFunction());
21933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileRun("var obj = new Obj;"
21943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             "function setter(i) { this.accessor_age = i; };"
21953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             "function getter() { return this.accessor_age; };"
21963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             "function setAge(i) { obj.age = i; };"
21973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             "Object.defineProperty(obj, 'age', { get:getter, set:setter });"
21983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             "for(var i = 0; i <= 10000; i++) setAge(i);");
21993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // All i < 10000 go to the interceptor.
22003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExpectInt32("obj.interceptor_age", 9999);
22013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The last i goes to the JavaScript accessor.
22023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExpectInt32("obj.accessor_age", 10000);
22033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The installed JavaScript getter is still intact.
22043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // This last part is a regression test for issue 1651 and relies on the fact
22053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // that both interceptor and accessor are being installed on the same object.
22063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExpectInt32("obj.age", 10000);
22073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExpectBoolean("obj.hasOwnProperty('age')", true);
22083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExpectUndefined("Object.getOwnPropertyDescriptor(obj, 'age').value");
22093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
22103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22123ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochTHREADED_TEST(SwitchFromJSAccessorToInterceptor) {
2213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(CcTest::isolate());
2214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
22153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
22163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LocalContext env;
22173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  env->Global()->Set(v8_str("Obj"), templ->GetFunction());
22183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileRun("var obj = new Obj;"
22193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             "function setter(i) { this.accessor_age = i; };"
22203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             "function getter() { return this.accessor_age; };"
22213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             "function setAge(i) { obj.age = i; };"
22223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             "Object.defineProperty(obj, 'age', { get:getter, set:setter });"
22233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             "for(var i = 20000; i >= 9999; i--) setAge(i);");
22243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // All i >= 10000 go to the accessor.
22253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExpectInt32("obj.accessor_age", 10000);
22263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The last i goes to the interceptor.
22273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExpectInt32("obj.interceptor_age", 9999);
22283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The installed JavaScript getter is still intact.
22293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // This last part is a regression test for issue 1651 and relies on the fact
22303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // that both interceptor and accessor are being installed on the same object.
22313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExpectInt32("obj.age", 10000);
22323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExpectBoolean("obj.hasOwnProperty('age')", true);
22333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExpectUndefined("Object.getOwnPropertyDescriptor(obj, 'age').value");
22343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
22353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22373ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochTHREADED_TEST(SwitchFromInterceptorToProperty) {
2238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(CcTest::isolate());
2239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<FunctionTemplate> parent = FunctionTemplate::New(CcTest::isolate());
2240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<FunctionTemplate> child = FunctionTemplate::New(CcTest::isolate());
22413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  child->Inherit(parent);
22423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  AddInterceptor(child, InterceptorGetter, InterceptorSetter);
22433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LocalContext env;
22443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  env->Global()->Set(v8_str("Child"), child->GetFunction());
22453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileRun("var child = new Child;"
22463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             "function setAge(i){ child.age = i; };"
22473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             "for(var i = 0; i <= 10000; i++) setAge(i);");
22483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // All i < 10000 go to the interceptor.
22493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExpectInt32("child.interceptor_age", 9999);
22503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The last i goes to child's own property.
22513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExpectInt32("child.age", 10000);
22523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
22533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22553ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochTHREADED_TEST(SwitchFromPropertyToInterceptor) {
2256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(CcTest::isolate());
2257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<FunctionTemplate> parent = FunctionTemplate::New(CcTest::isolate());
2258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<FunctionTemplate> child = FunctionTemplate::New(CcTest::isolate());
22593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  child->Inherit(parent);
22603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  AddInterceptor(child, InterceptorGetter, InterceptorSetter);
22613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LocalContext env;
22623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  env->Global()->Set(v8_str("Child"), child->GetFunction());
22633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileRun("var child = new Child;"
22643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             "function setAge(i){ child.age = i; };"
22653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             "for(var i = 20000; i >= 9999; i--) setAge(i);");
22663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // All i >= 10000 go to child's own property.
22673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExpectInt32("child.age", 10000);
22683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The last i goes to the interceptor.
22693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExpectInt32("child.interceptor_age", 9999);
22703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
2271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(NamedPropertyHandlerGetter) {
2274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  echo_named_call_count = 0;
2275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(CcTest::isolate());
2276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::FunctionTemplate> templ =
2277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::FunctionTemplate::New(CcTest::isolate());
2278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  templ->InstanceTemplate()->SetNamedPropertyHandler(EchoNamedProperty,
2279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                     0, 0, 0, 0,
2280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                     v8_str("data"));
2281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext env;
2282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env->Global()->Set(v8_str("obj"),
2283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     templ->GetFunction()->NewInstance());
2284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(echo_named_call_count, 0);
2285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8_compile("obj.x")->Run();
2286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(echo_named_call_count, 1);
2287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* code = "var str = 'oddle'; obj[str] + obj.poddle;";
2288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> str = CompileRun(code);
2289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  String::Utf8Value value(str);
2290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(*value, "oddlepoddle");
2291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check default behavior
2292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(v8_compile("obj.flob = 10;")->Run()->Int32Value(), 10);
2293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(v8_compile("'myProperty' in obj")->Run()->BooleanValue());
2294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(v8_compile("delete obj.myProperty")->Run()->BooleanValue());
2295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint echo_indexed_call_count = 0;
2299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void EchoIndexedProperty(
2302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t index,
2303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Value>& info) {
2304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
2305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(v8_num(637), info.Data());
2306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  echo_indexed_call_count++;
2307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(v8_num(index));
2308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(IndexedPropertyHandlerGetter) {
2312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
2313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
2314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
2315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  templ->InstanceTemplate()->SetIndexedPropertyHandler(EchoIndexedProperty,
2316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                       0, 0, 0, 0,
2317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                       v8_num(637));
2318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext env;
2319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env->Global()->Set(v8_str("obj"),
2320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     templ->GetFunction()->NewInstance());
2321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Script> script = v8_compile("obj[900]");
2322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(script->Run()->Int32Value(), 900);
2323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockv8::Handle<v8::Object> bottom;
2327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void CheckThisIndexedPropertyHandler(
2329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    uint32_t index,
2330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Value>& info) {
2331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyHandler));
2332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
2333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(info.This()->Equals(bottom));
2334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void CheckThisNamedPropertyHandler(
2337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Local<String> name,
2338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Value>& info) {
2339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyHandler));
2340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
2341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(info.This()->Equals(bottom));
2342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CheckThisIndexedPropertySetter(
2345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t index,
2346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<Value> value,
2347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Value>& info) {
2348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertySetter));
2349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
2350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(info.This()->Equals(bottom));
2351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CheckThisNamedPropertySetter(
2355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<String> property,
2356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<Value> value,
2357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Value>& info) {
2358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertySetter));
2359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
2360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(info.This()->Equals(bottom));
2361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CheckThisIndexedPropertyQuery(
2364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    uint32_t index,
2365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Integer>& info) {
2366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyQuery));
2367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
2368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(info.This()->Equals(bottom));
2369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CheckThisNamedPropertyQuery(
2373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<String> property,
2374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Integer>& info) {
2375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyQuery));
2376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
2377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(info.This()->Equals(bottom));
2378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CheckThisIndexedPropertyDeleter(
2382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    uint32_t index,
2383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Boolean>& info) {
2384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyDeleter));
2385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
2386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(info.This()->Equals(bottom));
2387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CheckThisNamedPropertyDeleter(
2391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Local<String> property,
2392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Boolean>& info) {
2393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyDeleter));
2394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
2395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(info.This()->Equals(bottom));
2396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CheckThisIndexedPropertyEnumerator(
2400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Array>& info) {
2401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyEnumerator));
2402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
2403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(info.This()->Equals(bottom));
2404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CheckThisNamedPropertyEnumerator(
2408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Array>& info) {
2409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyEnumerator));
2410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
2411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(info.This()->Equals(bottom));
2412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_PROFILED_TEST(PropertyHandlerInPrototype) {
2416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext env;
2417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
2418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
2419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set up a prototype chain with three interceptors.
2421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
2422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  templ->InstanceTemplate()->SetIndexedPropertyHandler(
2423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      CheckThisIndexedPropertyHandler,
2424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      CheckThisIndexedPropertySetter,
2425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      CheckThisIndexedPropertyQuery,
2426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      CheckThisIndexedPropertyDeleter,
2427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      CheckThisIndexedPropertyEnumerator);
2428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  templ->InstanceTemplate()->SetNamedPropertyHandler(
2430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      CheckThisNamedPropertyHandler,
2431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      CheckThisNamedPropertySetter,
2432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      CheckThisNamedPropertyQuery,
2433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      CheckThisNamedPropertyDeleter,
2434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      CheckThisNamedPropertyEnumerator);
2435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bottom = templ->GetFunction()->NewInstance();
2437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<v8::Object> top = templ->GetFunction()->NewInstance();
2438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<v8::Object> middle = templ->GetFunction()->NewInstance();
2439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bottom->SetPrototype(middle);
2441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  middle->SetPrototype(top);
2442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env->Global()->Set(v8_str("obj"), bottom);
2443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Indexed and named get.
2445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("obj[0]");
2446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("obj.x");
2447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Indexed and named set.
2449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("obj[1] = 42");
2450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("obj.y = 42");
2451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Indexed and named query.
2453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("0 in obj");
2454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("'x' in obj");
2455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Indexed and named deleter.
2457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("delete obj[0]");
2458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("delete obj.x");
2459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Enumerators.
2461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("for (var p in obj) ;");
2462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void PrePropertyHandlerGet(
2466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<String> key,
2467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Value>& info) {
2468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
2469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (v8_str("pre")->Equals(key)) {
2470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    info.GetReturnValue().Set(v8_str("PrePropertyHandler: pre"));
2471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void PrePropertyHandlerQuery(
2476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<String> key,
2477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Integer>& info) {
2478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (v8_str("pre")->Equals(key)) {
2479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    info.GetReturnValue().Set(static_cast<int32_t>(v8::None));
2480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(PrePropertyHandler) {
2485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
2486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
2487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
2488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  desc->InstanceTemplate()->SetNamedPropertyHandler(PrePropertyHandlerGet,
2489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                    0,
24907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                                    PrePropertyHandlerQuery);
2491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext env(NULL, desc->InstanceTemplate());
2492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("var pre = 'Object: pre'; var on = 'Object: on';");
2493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<Value> result_pre = CompileRun("pre");
2494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(v8_str("PrePropertyHandler: pre"), result_pre);
2495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<Value> result_on = CompileRun("on");
2496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(v8_str("Object: on"), result_on);
2497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<Value> result_post = CompileRun("post");
2498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(result_post.IsEmpty());
2499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(UndefinedIsNotEnumerable) {
2503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext env;
2504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
2505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<Value> result = CompileRun("this.propertyIsEnumerable(undefined)");
2506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(result->IsFalse());
2507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockv8::Handle<Script> call_recursively_script;
25114515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkestatic const int kTargetRecursionDepth = 200;  // near maximum
2512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void CallScriptRecursivelyCall(
2515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::FunctionCallbackInfo<v8::Value>& args) {
2516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
2517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int depth = args.This()->Get(v8_str("depth"))->Int32Value();
2518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (depth == kTargetRecursionDepth) return;
2519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  args.This()->Set(v8_str("depth"),
2520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   v8::Integer::New(args.GetIsolate(), depth + 1));
2521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  args.GetReturnValue().Set(call_recursively_script->Run());
2522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void CallFunctionRecursivelyCall(
2526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::FunctionCallbackInfo<v8::Value>& args) {
2527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
2528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int depth = args.This()->Get(v8_str("depth"))->Int32Value();
2529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (depth == kTargetRecursionDepth) {
2530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    printf("[depth = %d]\n", depth);
2531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
2532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  args.This()->Set(v8_str("depth"),
2534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   v8::Integer::New(args.GetIsolate(), depth + 1));
2535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> function =
2536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      args.This()->Get(v8_str("callFunctionRecursively"));
2537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  args.GetReturnValue().Set(
2538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      function.As<Function>()->Call(args.This(), 0, NULL));
2539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(DeepCrossLanguageRecursion) {
2543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
2544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
2545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> global = ObjectTemplate::New(isolate);
2546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  global->Set(v8_str("callScriptRecursively"),
2547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              v8::FunctionTemplate::New(isolate, CallScriptRecursivelyCall));
2548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  global->Set(v8_str("callFunctionRecursively"),
2549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              v8::FunctionTemplate::New(isolate, CallFunctionRecursivelyCall));
2550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext env(NULL, global);
2551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->Global()->Set(v8_str("depth"), v8::Integer::New(isolate, 0));
2553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  call_recursively_script = v8_compile("callScriptRecursively()");
25543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  call_recursively_script->Run();
2555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  call_recursively_script = v8::Handle<Script>();
2556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->Global()->Set(v8_str("depth"), v8::Integer::New(isolate, 0));
2558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("callFunctionRecursively()");
2559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void ThrowingPropertyHandlerGet(
2563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<String> key,
2564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Value>& info) {
2565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
2566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(info.GetIsolate()->ThrowException(key));
2567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void ThrowingPropertyHandlerSet(
2571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<String> key,
2572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<Value>,
2573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Value>& info) {
2574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetIsolate()->ThrowException(key);
2575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().SetUndefined();  // not the same as empty handle
2576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(CallbackExceptionRegression) {
2580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
2581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
2582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
2583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  obj->SetNamedPropertyHandler(ThrowingPropertyHandlerGet,
2584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                               ThrowingPropertyHandlerSet);
2585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext env;
2586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env->Global()->Set(v8_str("obj"), obj->NewInstance());
2587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<Value> otto = CompileRun(
2588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "try { with (obj) { otto; } } catch (e) { e; }");
2589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(v8_str("otto"), otto);
2590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<Value> netto = CompileRun(
2591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "try { with (obj) { netto = 4; } } catch (e) { e; }");
2592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(v8_str("netto"), netto);
2593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(FunctionPrototype) {
2597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
2598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
2599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::FunctionTemplate> Foo = v8::FunctionTemplate::New(isolate);
2600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Foo->PrototypeTemplate()->Set(v8_str("plak"), v8_num(321));
2601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext env;
2602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env->Global()->Set(v8_str("Foo"), Foo->GetFunction());
2603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Script> script = v8_compile("Foo.prototype.plak");
2604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(script->Run()->Int32Value(), 321);
2605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(InternalFields) {
2609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext env;
2610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
2611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
2612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
2614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
2615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  instance_templ->SetInternalFieldCount(1);
2616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<v8::Object> obj = templ->GetFunction()->NewInstance();
2617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, obj->InternalFieldCount());
2618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(obj->GetInternalField(0)->IsUndefined());
2619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  obj->SetInternalField(0, v8_num(17));
2620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(17, obj->GetInternalField(0)->Int32Value());
2621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
26246ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockTHREADED_TEST(GlobalObjectInternalFields) {
2625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
2626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
2627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New(isolate);
26286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  global_template->SetInternalFieldCount(1);
26296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  LocalContext env(NULL, global_template);
26306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  v8::Handle<v8::Object> global_proxy = env->Global();
26316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  v8::Handle<v8::Object> global = global_proxy->GetPrototype().As<v8::Object>();
26326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(1, global->InternalFieldCount());
26336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(global->GetInternalField(0)->IsUndefined());
26346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  global->SetInternalField(0, v8_num(17));
26356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(17, global->GetInternalField(0)->Int32Value());
26366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
26376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
26386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(GlobalObjectHasRealIndexedProperty) {
2640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext env;
2641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(CcTest::isolate());
2642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Object> global = env->Global();
2644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  global->Set(0, v8::String::NewFromUtf8(CcTest::isolate(), "value"));
2645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(global->HasRealIndexedProperty(0));
2646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void CheckAlignedPointerInInternalField(Handle<v8::Object> obj,
2650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               void* value) {
2651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(value) & 0x1));
2652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  obj->SetAlignedPointerInInternalField(0, value);
2653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
2654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(value, obj->GetAlignedPointerFromInternalField(0));
2655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(InternalFieldsAlignedPointers) {
2659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
2660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
2661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
2662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
2664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
2665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  instance_templ->SetInternalFieldCount(1);
2666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<v8::Object> obj = templ->GetFunction()->NewInstance();
2667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, obj->InternalFieldCount());
2668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckAlignedPointerInInternalField(obj, NULL);
2670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int* heap_allocated = new int[100];
2672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckAlignedPointerInInternalField(obj, heap_allocated);
2673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  delete[] heap_allocated;
2674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int stack_allocated[100];
2676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckAlignedPointerInInternalField(obj, stack_allocated);
2677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void* huge = reinterpret_cast<void*>(~static_cast<uintptr_t>(1));
2679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckAlignedPointerInInternalField(obj, huge);
2680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::UniquePersistent<v8::Object> persistent(isolate, obj);
2682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1, Object::InternalFieldCount(persistent));
2683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(huge, Object::GetAlignedPointerFromInternalField(persistent, 0));
2684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void CheckAlignedPointerInEmbedderData(LocalContext* env,
2688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              int index,
2689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              void* value) {
2690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(value) & 0x1));
2691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  (*env)->SetAlignedPointerInEmbedderData(index, value);
2692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
2693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(value, (*env)->GetAlignedPointerFromEmbedderData(index));
2694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void* AlignedTestPointer(int i) {
2698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return reinterpret_cast<void*>(i * 1234);
2699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(EmbedderDataAlignedPointers) {
27033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  LocalContext env;
2704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
27053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckAlignedPointerInEmbedderData(&env, 0, NULL);
2707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int* heap_allocated = new int[100];
2709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckAlignedPointerInEmbedderData(&env, 1, heap_allocated);
2710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  delete[] heap_allocated;
27113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int stack_allocated[100];
2713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckAlignedPointerInEmbedderData(&env, 2, stack_allocated);
27143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void* huge = reinterpret_cast<void*>(~static_cast<uintptr_t>(1));
2716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckAlignedPointerInEmbedderData(&env, 3, huge);
2717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Test growing of the embedder data's backing store.
2719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < 100; i++) {
2720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    env->SetAlignedPointerInEmbedderData(i, AlignedTestPointer(i));
2721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
2723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < 100; i++) {
2724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(AlignedTestPointer(i), env->GetAlignedPointerFromEmbedderData(i));
2725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
27273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
27283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void CheckEmbedderData(LocalContext* env,
2730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              int index,
2731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              v8::Handle<Value> data) {
2732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  (*env)->SetEmbedderData(index, data);
2733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK((*env)->GetEmbedderData(index)->StrictEquals(data));
2734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
27353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
27363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(EmbedderData) {
2738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
2739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
2740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
27413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckEmbedderData(
2743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      &env, 3,
2744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(isolate, "The quick brown fox jumps"));
2745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckEmbedderData(&env, 2, v8::String::NewFromUtf8(isolate,
2746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                     "over the lazy dog."));
2747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckEmbedderData(&env, 1, v8::Number::New(isolate, 1.2345));
2748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckEmbedderData(&env, 0, v8::Boolean::New(isolate, true));
27493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
27503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
27513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(IdentityHash) {
2753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext env;
2754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
2755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
2756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Ensure that the test starts with an fresh heap to test whether the hash
2758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // code is based on the address.
2759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
2760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::Object> obj = v8::Object::New(isolate);
2761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int hash = obj->GetIdentityHash();
2762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int hash1 = obj->GetIdentityHash();
2763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(hash, hash1);
2764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int hash2 = v8::Object::New(isolate)->GetIdentityHash();
2765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Since the identity hash is essentially a random number two consecutive
2766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // objects should not be assigned the same hash code. If the test below fails
2767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the random number generator should be evaluated.
2768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_NE(hash, hash2);
2769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
2770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int hash3 = v8::Object::New(isolate)->GetIdentityHash();
2771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make sure that the identity hash is not based on the initial address of
2772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the object alone. If the test below fails the random number generator
2773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // should be evaluated.
2774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_NE(hash, hash3);
2775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int hash4 = obj->GetIdentityHash();
2776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(hash, hash4);
27771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
27781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Check identity hashes behaviour in the presence of JS accessors.
27791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Put a getter for 'v8::IdentityHash' on the Object's prototype:
27801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  {
27811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    CompileRun("Object.prototype['v8::IdentityHash'] = 42;\n");
2782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<v8::Object> o1 = v8::Object::New(isolate);
2783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<v8::Object> o2 = v8::Object::New(isolate);
27841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash());
27851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
27861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  {
27871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    CompileRun(
27881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        "function cnst() { return 42; };\n"
27891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        "Object.prototype.__defineGetter__('v8::IdentityHash', cnst);\n");
2790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<v8::Object> o1 = v8::Object::New(isolate);
2791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<v8::Object> o2 = v8::Object::New(isolate);
27921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash());
27931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
2794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(GlobalProxyIdentityHash) {
2798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
2799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
2800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
2801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Object> global_proxy = env->Global();
2802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int hash1 = global_proxy->GetIdentityHash();
2803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Hash should be retained after being detached.
2804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->DetachGlobal();
2805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int hash2 = global_proxy->GetIdentityHash();
2806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(hash1, hash2);
2807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
2808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Re-attach global proxy to a new context, hash should stay the same.
2809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LocalContext env2(NULL, Handle<ObjectTemplate>(), global_proxy);
2810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int hash3 = global_proxy->GetIdentityHash();
2811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(hash1, hash3);
2812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(SymbolProperties) {
2817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
2818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
2819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
2820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Object> obj = v8::Object::New(isolate);
2822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Symbol> sym1 = v8::Symbol::New(isolate);
2823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Symbol> sym2 =
2824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Symbol::New(isolate, v8_str("my-symbol"));
2825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Symbol> sym3 =
2826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Symbol::New(isolate, v8_str("sym3"));
2827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
2829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check basic symbol functionality.
2831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(sym1->IsSymbol());
2832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(sym2->IsSymbol());
2833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!obj->IsSymbol());
2834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(sym1->Equals(sym1));
2836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(sym2->Equals(sym2));
2837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!sym1->Equals(sym2));
2838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!sym2->Equals(sym1));
2839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(sym1->StrictEquals(sym1));
2840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(sym2->StrictEquals(sym2));
2841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!sym1->StrictEquals(sym2));
2842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!sym2->StrictEquals(sym1));
2843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(sym2->Name()->Equals(v8_str("my-symbol")));
2845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Value> sym_val = sym2;
2847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(sym_val->IsSymbol());
2848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(sym_val->Equals(sym2));
2849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(sym_val->StrictEquals(sym2));
2850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(v8::Symbol::Cast(*sym_val)->Equals(sym2));
2851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Value> sym_obj = v8::SymbolObject::New(isolate, sym2);
2853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(sym_obj->IsSymbolObject());
2854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!sym2->IsSymbolObject());
2855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!obj->IsSymbolObject());
2856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!sym_obj->Equals(sym2));
2857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!sym_obj->StrictEquals(sym2));
2858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(v8::SymbolObject::Cast(*sym_obj)->Equals(sym_obj));
2859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(v8::SymbolObject::Cast(*sym_obj)->ValueOf()->Equals(sym2));
2860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Make sure delete of a non-existent symbol property works.
2862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(obj->Delete(sym1));
2863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!obj->Has(sym1));
2864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(obj->Set(sym1, v8::Integer::New(isolate, 1503)));
2866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(obj->Has(sym1));
2867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1503, obj->Get(sym1)->Int32Value());
2868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(obj->Set(sym1, v8::Integer::New(isolate, 2002)));
2869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(obj->Has(sym1));
2870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
2871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(v8::None, obj->GetPropertyAttributes(sym1));
2872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, obj->GetOwnPropertyNames()->Length());
2874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int num_props = obj->GetPropertyNames()->Length();
2875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(obj->Set(v8::String::NewFromUtf8(isolate, "bla"),
2876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 v8::Integer::New(isolate, 20)));
2877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
2878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(num_props + 1, obj->GetPropertyNames()->Length());
2879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
2881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(obj->SetAccessor(sym3, SymbolAccessorGetter, SymbolAccessorSetter));
2883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(obj->Get(sym3)->IsUndefined());
2884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(obj->Set(sym3, v8::Integer::New(isolate, 42)));
2885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(obj->Get(sym3)->Equals(v8::Integer::New(isolate, 42)));
2886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(obj->Get(v8::String::NewFromUtf8(isolate, "accessor_sym3"))->Equals(
2887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Integer::New(isolate, 42)));
2888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Add another property and delete it afterwards to force the object in
2890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // slow case.
2891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(obj->Set(sym2, v8::Integer::New(isolate, 2008)));
2892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
2893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2008, obj->Get(sym2)->Int32Value());
2894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
2895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2, obj->GetOwnPropertyNames()->Length());
2896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(obj->Has(sym1));
2898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(obj->Has(sym2));
2899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(obj->Has(sym3));
2900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(obj->Has(v8::String::NewFromUtf8(isolate, "accessor_sym3")));
2901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(obj->Delete(sym2));
2902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(obj->Has(sym1));
2903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!obj->Has(sym2));
2904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(obj->Has(sym3));
2905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(obj->Has(v8::String::NewFromUtf8(isolate, "accessor_sym3")));
2906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
2907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(obj->Get(sym3)->Equals(v8::Integer::New(isolate, 42)));
2908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(obj->Get(v8::String::NewFromUtf8(isolate, "accessor_sym3"))->Equals(
2909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Integer::New(isolate, 42)));
2910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2, obj->GetOwnPropertyNames()->Length());
2911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Symbol properties are inherited.
2913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Object> child = v8::Object::New(isolate);
2914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  child->SetPrototype(obj);
2915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(child->Has(sym1));
2916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2002, child->Get(sym1)->Int32Value());
2917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(obj->Get(sym3)->Equals(v8::Integer::New(isolate, 42)));
2918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(obj->Get(v8::String::NewFromUtf8(isolate, "accessor_sym3"))->Equals(
2919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Integer::New(isolate, 42)));
2920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, child->GetOwnPropertyNames()->Length());
2921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(SymbolTemplateProperties) {
2925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
2926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
2927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
2928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::FunctionTemplate> foo = v8::FunctionTemplate::New(isolate);
2929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Name> name = v8::Symbol::New(isolate);
2930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!name.IsEmpty());
2931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  foo->PrototypeTemplate()->Set(name, v8::FunctionTemplate::New(isolate));
2932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Object> new_instance = foo->InstanceTemplate()->NewInstance();
2933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!new_instance.IsEmpty());
2934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(new_instance->Has(name));
2935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(PrivateProperties) {
2939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
2940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
2941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
2942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Object> obj = v8::Object::New(isolate);
2944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Private> priv1 = v8::Private::New(isolate);
2945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Private> priv2 =
2946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Private::New(isolate, v8_str("my-private"));
2947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
2949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(priv2->Name()->Equals(v8::String::NewFromUtf8(isolate, "my-private")));
2951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Make sure delete of a non-existent private symbol property works.
2953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(obj->DeletePrivate(priv1));
2954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!obj->HasPrivate(priv1));
2955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(obj->SetPrivate(priv1, v8::Integer::New(isolate, 1503)));
2957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(obj->HasPrivate(priv1));
2958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1503, obj->GetPrivate(priv1)->Int32Value());
2959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(obj->SetPrivate(priv1, v8::Integer::New(isolate, 2002)));
2960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(obj->HasPrivate(priv1));
2961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2002, obj->GetPrivate(priv1)->Int32Value());
2962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, obj->GetOwnPropertyNames()->Length());
2964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int num_props = obj->GetPropertyNames()->Length();
2965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(obj->Set(v8::String::NewFromUtf8(isolate, "bla"),
2966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 v8::Integer::New(isolate, 20)));
2967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
2968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(num_props + 1, obj->GetPropertyNames()->Length());
2969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
2971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Add another property and delete it afterwards to force the object in
2973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // slow case.
2974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(obj->SetPrivate(priv2, v8::Integer::New(isolate, 2008)));
2975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2002, obj->GetPrivate(priv1)->Int32Value());
2976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2008, obj->GetPrivate(priv2)->Int32Value());
2977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2002, obj->GetPrivate(priv1)->Int32Value());
2978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
2979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(obj->HasPrivate(priv1));
2981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(obj->HasPrivate(priv2));
2982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(obj->DeletePrivate(priv2));
2983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(obj->HasPrivate(priv1));
2984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!obj->HasPrivate(priv2));
2985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2002, obj->GetPrivate(priv1)->Int32Value());
2986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
2987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Private properties are inherited (for the time being).
2989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Object> child = v8::Object::New(isolate);
2990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  child->SetPrototype(obj);
2991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(child->HasPrivate(priv1));
2992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2002, child->GetPrivate(priv1)->Int32Value());
2993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, child->GetOwnPropertyNames()->Length());
2994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(GlobalSymbols) {
2998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
2999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
3000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
3001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<String> name = v8_str("my-symbol");
3003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Symbol> glob = v8::Symbol::For(isolate, name);
3004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Symbol> glob2 = v8::Symbol::For(isolate, name);
3005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(glob2->SameValue(glob));
3006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Symbol> glob_api = v8::Symbol::ForApi(isolate, name);
3008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Symbol> glob_api2 = v8::Symbol::ForApi(isolate, name);
3009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(glob_api2->SameValue(glob_api));
3010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!glob_api->SameValue(glob));
3011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Symbol> sym = v8::Symbol::New(isolate, name);
3013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!sym->SameValue(glob));
3014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("var sym2 = Symbol.for('my-symbol')");
3016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<Value> sym2 = env->Global()->Get(v8_str("sym2"));
3017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(sym2->SameValue(glob));
3018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!sym2->SameValue(glob_api));
3019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void CheckWellKnownSymbol(v8::Local<v8::Symbol>(*getter)(v8::Isolate*),
3023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 const char* name) {
3024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
3025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
3026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
3027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Symbol> symbol = getter(isolate);
3029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  std::string script = std::string("var sym = ") + name;
3030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun(script.c_str());
3031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<Value> value = env->Global()->Get(v8_str("sym"));
3032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!value.IsEmpty());
3034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!symbol.IsEmpty());
3035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(value->SameValue(symbol));
3036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(WellKnownSymbols) {
3040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckWellKnownSymbol(v8::Symbol::GetIterator, "Symbol.iterator");
3041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckWellKnownSymbol(v8::Symbol::GetUnscopables, "Symbol.unscopables");
3042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(GlobalPrivates) {
3046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
3047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
3048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
3049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<String> name = v8_str("my-private");
3051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Private> glob = v8::Private::ForApi(isolate, name);
3052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Object> obj = v8::Object::New(isolate);
3053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(obj->SetPrivate(glob, v8::Integer::New(isolate, 3)));
3054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Private> glob2 = v8::Private::ForApi(isolate, name);
3056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(obj->HasPrivate(glob2));
3057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Private> priv = v8::Private::New(isolate, name);
3059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!obj->HasPrivate(priv));
3060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("var intern = %CreateGlobalPrivateSymbol('my-private')");
3062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<Value> intern = env->Global()->Get(v8_str("intern"));
3063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!obj->Has(intern));
3064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass ScopedArrayBufferContents {
3068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
3069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  explicit ScopedArrayBufferContents(
3070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      const v8::ArrayBuffer::Contents& contents)
3071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    : contents_(contents) {}
3072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ~ScopedArrayBufferContents() { free(contents_.Data()); }
3073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void* Data() const { return contents_.Data(); }
3074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  size_t ByteLength() const { return contents_.ByteLength(); }
3075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
3076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const v8::ArrayBuffer::Contents contents_;
3077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
3078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate <typename T>
3080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void CheckInternalFieldsAreZero(v8::Handle<T> value) {
3081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(T::kInternalFieldCount, value->InternalFieldCount());
3082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < value->InternalFieldCount(); i++) {
3083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(0, value->GetInternalField(i)->Int32Value());
3084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(ArrayBuffer_ApiInternalToExternal) {
3089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
3090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
3091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(isolate);
3092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, 1024);
3094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckInternalFieldsAreZero(ab);
3095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1024, static_cast<int>(ab->ByteLength()));
3096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!ab->IsExternal());
3097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
3098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ScopedArrayBufferContents ab_contents(ab->Externalize());
3100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(ab->IsExternal());
3101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1024, static_cast<int>(ab_contents.ByteLength()));
3103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  uint8_t* data = static_cast<uint8_t*>(ab_contents.Data());
3104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(data != NULL);
3105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->Global()->Set(v8_str("ab"), ab);
3106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Value> result = CompileRun("ab.byteLength");
3108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1024, result->Int32Value());
3109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  result = CompileRun("var u8 = new Uint8Array(ab);"
3111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      "u8[0] = 0xFF;"
3112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      "u8[1] = 0xAA;"
3113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      "u8.length");
3114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1024, result->Int32Value());
3115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0xFF, data[0]);
3116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0xAA, data[1]);
3117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  data[0] = 0xCC;
3118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  data[1] = 0x11;
3119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  result = CompileRun("u8[0] + u8[1]");
3120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0xDD, result->Int32Value());
3121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(ArrayBuffer_JSInternalToExternal) {
3125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
3126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
3127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(isolate);
3128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Value> result =
3131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CompileRun("var ab1 = new ArrayBuffer(2);"
3132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 "var u8_a = new Uint8Array(ab1);"
3133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 "u8_a[0] = 0xAA;"
3134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 "u8_a[1] = 0xFF; u8_a.buffer");
3135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::ArrayBuffer> ab1 = Local<v8::ArrayBuffer>::Cast(result);
3136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckInternalFieldsAreZero(ab1);
3137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2, static_cast<int>(ab1->ByteLength()));
3138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!ab1->IsExternal());
3139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ScopedArrayBufferContents ab1_contents(ab1->Externalize());
3140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(ab1->IsExternal());
3141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  result = CompileRun("ab1.byteLength");
3143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2, result->Int32Value());
3144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  result = CompileRun("u8_a[0]");
3145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0xAA, result->Int32Value());
3146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  result = CompileRun("u8_a[1]");
3147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0xFF, result->Int32Value());
3148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  result = CompileRun("var u8_b = new Uint8Array(ab1);"
3149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      "u8_b[0] = 0xBB;"
3150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      "u8_a[0]");
3151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0xBB, result->Int32Value());
3152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  result = CompileRun("u8_b[1]");
3153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0xFF, result->Int32Value());
3154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2, static_cast<int>(ab1_contents.ByteLength()));
3156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  uint8_t* ab1_data = static_cast<uint8_t*>(ab1_contents.Data());
3157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0xBB, ab1_data[0]);
3158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0xFF, ab1_data[1]);
3159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ab1_data[0] = 0xCC;
3160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ab1_data[1] = 0x11;
3161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  result = CompileRun("u8_a[0] + u8_a[1]");
3162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0xDD, result->Int32Value());
3163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(ArrayBuffer_External) {
3167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
3168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
3169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(isolate);
3170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::ScopedVector<uint8_t> my_data(100);
3172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  memset(my_data.start(), 0, 100);
3173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::ArrayBuffer> ab3 =
3174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::ArrayBuffer::New(isolate, my_data.start(), 100);
3175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckInternalFieldsAreZero(ab3);
3176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(100, static_cast<int>(ab3->ByteLength()));
3177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(ab3->IsExternal());
3178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->Global()->Set(v8_str("ab3"), ab3);
3180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Value> result = CompileRun("ab3.byteLength");
3182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(100, result->Int32Value());
3183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  result = CompileRun("var u8_b = new Uint8Array(ab3);"
3185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      "u8_b[0] = 0xBB;"
3186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      "u8_b[1] = 0xCC;"
3187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      "u8_b.length");
3188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(100, result->Int32Value());
3189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0xBB, my_data[0]);
3190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0xCC, my_data[1]);
3191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  my_data[0] = 0xCC;
3192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  my_data[1] = 0x11;
3193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  result = CompileRun("u8_b[0] + u8_b[1]");
3194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0xDD, result->Int32Value());
3195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void CheckDataViewIsNeutered(v8::Handle<v8::DataView> dv) {
3199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, static_cast<int>(dv->ByteLength()));
3200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, static_cast<int>(dv->ByteOffset()));
3201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void CheckIsNeutered(v8::Handle<v8::TypedArray> ta) {
3205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, static_cast<int>(ta->ByteLength()));
3206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, static_cast<int>(ta->Length()));
3207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, static_cast<int>(ta->ByteOffset()));
3208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void CheckIsTypedArrayVarNeutered(const char* name) {
3212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::ScopedVector<char> source(1024);
3213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::SNPrintF(source,
3214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "%s.byteLength == 0 && %s.byteOffset == 0 && %s.length == 0",
3215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      name, name, name);
3216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(CompileRun(source.start())->IsTrue());
3217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::TypedArray> ta =
3218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Handle<v8::TypedArray>::Cast(CompileRun(name));
3219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckIsNeutered(ta);
3220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate <typename TypedArray, int kElementSize>
3224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic Handle<TypedArray> CreateAndCheck(Handle<v8::ArrayBuffer> ab,
3225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                         int byteOffset,
3226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                         int length) {
3227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<TypedArray> ta = TypedArray::New(ab, byteOffset, length);
3228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
3229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(byteOffset, static_cast<int>(ta->ByteOffset()));
3230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(length, static_cast<int>(ta->Length()));
3231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(length * kElementSize, static_cast<int>(ta->ByteLength()));
3232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return ta;
3233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(ArrayBuffer_NeuteringApi) {
3237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
3238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
3239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(isolate);
3240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ArrayBuffer> buffer = v8::ArrayBuffer::New(isolate, 1024);
3242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Uint8Array> u8a =
3244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CreateAndCheck<v8::Uint8Array, 1>(buffer, 1, 1023);
3245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Uint8ClampedArray> u8c =
3246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CreateAndCheck<v8::Uint8ClampedArray, 1>(buffer, 1, 1023);
3247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Int8Array> i8a =
3248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CreateAndCheck<v8::Int8Array, 1>(buffer, 1, 1023);
3249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Uint16Array> u16a =
3251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CreateAndCheck<v8::Uint16Array, 2>(buffer, 2, 511);
3252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Int16Array> i16a =
3253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CreateAndCheck<v8::Int16Array, 2>(buffer, 2, 511);
3254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Uint32Array> u32a =
3256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CreateAndCheck<v8::Uint32Array, 4>(buffer, 4, 255);
3257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Int32Array> i32a =
3258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CreateAndCheck<v8::Int32Array, 4>(buffer, 4, 255);
3259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Float32Array> f32a =
3261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CreateAndCheck<v8::Float32Array, 4>(buffer, 4, 255);
3262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Float64Array> f64a =
3263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CreateAndCheck<v8::Float64Array, 8>(buffer, 8, 127);
3264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::DataView> dv = v8::DataView::New(buffer, 1, 1023);
3266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
3267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1, static_cast<int>(dv->ByteOffset()));
3268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1023, static_cast<int>(dv->ByteLength()));
3269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ScopedArrayBufferContents contents(buffer->Externalize());
3271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  buffer->Neuter();
3272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, static_cast<int>(buffer->ByteLength()));
3273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckIsNeutered(u8a);
3274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckIsNeutered(u8c);
3275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckIsNeutered(i8a);
3276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckIsNeutered(u16a);
3277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckIsNeutered(i16a);
3278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckIsNeutered(u32a);
3279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckIsNeutered(i32a);
3280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckIsNeutered(f32a);
3281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckIsNeutered(f64a);
3282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckDataViewIsNeutered(dv);
3283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(ArrayBuffer_NeuteringScript) {
3287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
3288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
3289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(isolate);
3290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun(
3292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "var ab = new ArrayBuffer(1024);"
3293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "var u8a = new Uint8Array(ab, 1, 1023);"
3294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "var u8c = new Uint8ClampedArray(ab, 1, 1023);"
3295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "var i8a = new Int8Array(ab, 1, 1023);"
3296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "var u16a = new Uint16Array(ab, 2, 511);"
3297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "var i16a = new Int16Array(ab, 2, 511);"
3298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "var u32a = new Uint32Array(ab, 4, 255);"
3299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "var i32a = new Int32Array(ab, 4, 255);"
3300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "var f32a = new Float32Array(ab, 4, 255);"
3301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "var f64a = new Float64Array(ab, 8, 127);"
3302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "var dv = new DataView(ab, 1, 1023);");
3303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ArrayBuffer> ab =
3305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Local<v8::ArrayBuffer>::Cast(CompileRun("ab"));
3306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::DataView> dv =
3308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Handle<v8::DataView>::Cast(CompileRun("dv"));
3309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ScopedArrayBufferContents contents(ab->Externalize());
3311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ab->Neuter();
3312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, static_cast<int>(ab->ByteLength()));
3313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, CompileRun("ab.byteLength")->Int32Value());
3314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckIsTypedArrayVarNeutered("u8a");
3316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckIsTypedArrayVarNeutered("u8c");
3317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckIsTypedArrayVarNeutered("i8a");
3318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckIsTypedArrayVarNeutered("u16a");
3319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckIsTypedArrayVarNeutered("i16a");
3320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckIsTypedArrayVarNeutered("u32a");
3321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckIsTypedArrayVarNeutered("i32a");
3322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckIsTypedArrayVarNeutered("f32a");
3323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckIsTypedArrayVarNeutered("f64a");
3324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(CompileRun("dv.byteLength == 0 && dv.byteOffset == 0")->IsTrue());
3326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckDataViewIsNeutered(dv);
3327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(HiddenProperties) {
3332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext env;
3333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
3334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
3335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
3337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Local<v8::String> key = v8_str("api-test::hidden-key");
3338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Local<v8::String> empty = v8_str("");
3339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Local<v8::String> prop_name = v8_str("prop_name");
3340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
3342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make sure delete of a non-existent hidden value works
3344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(obj->DeleteHiddenValue(key));
3345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(obj->SetHiddenValue(key, v8::Integer::New(isolate, 1503)));
3347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1503, obj->GetHiddenValue(key)->Int32Value());
3348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(obj->SetHiddenValue(key, v8::Integer::New(isolate, 2002)));
3349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
3350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
3352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make sure we do not find the hidden property.
3354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(!obj->Has(empty));
3355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
3356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(obj->Get(empty)->IsUndefined());
3357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
3358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(obj->Set(empty, v8::Integer::New(isolate, 2003)));
3359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
3360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2003, obj->Get(empty)->Int32Value());
3361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
3363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Add another property and delete it afterwards to force the object in
3365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // slow case.
3366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(obj->Set(prop_name, v8::Integer::New(isolate, 2008)));
3367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
3368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2008, obj->Get(prop_name)->Int32Value());
3369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
3370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(obj->Delete(prop_name));
3371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
3372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
3374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(obj->SetHiddenValue(key, Handle<Value>()));
3376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(obj->GetHiddenValue(key).IsEmpty());
3377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(obj->SetHiddenValue(key, v8::Integer::New(isolate, 2002)));
3379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(obj->DeleteHiddenValue(key));
3380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(obj->GetHiddenValue(key).IsEmpty());
3381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
33843fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochTHREADED_TEST(Regress97784) {
33853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Regression test for crbug.com/97784
33863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Messing with the Object.prototype should not have effect on
33873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // hidden properties.
33883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  LocalContext env;
3389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
33903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
33923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  v8::Local<v8::String> key = v8_str("hidden");
33933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
33943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CompileRun(
33953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      "set_called = false;"
33963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      "Object.defineProperty("
33973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      "    Object.prototype,"
33983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      "    'hidden',"
33993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      "    {get: function() { return 45; },"
34003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      "     set: function() { set_called = true; }})");
34013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
34023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK(obj->GetHiddenValue(key).IsEmpty());
34033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Make sure that the getter and setter from Object.prototype is not invoked.
34043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // If it did we would have full access to the hidden properties in
34053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // the accessor.
3406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(obj->SetHiddenValue(key, v8::Integer::New(env->GetIsolate(), 42)));
34073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ExpectFalse("set_called");
34083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK_EQ(42, obj->GetHiddenValue(key)->Int32Value());
34093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
34103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
34113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3412d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockstatic bool interceptor_for_hidden_properties_called;
3413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void InterceptorForHiddenProperties(
3414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<String> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
3415d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  interceptor_for_hidden_properties_called = true;
3416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(HiddenPropertiesWithInterceptors) {
3420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
3421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
3422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
3423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3424d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  interceptor_for_hidden_properties_called = false;
3425d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Local<v8::String> key = v8_str("api-test::hidden-key");
3427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Associate an interceptor with an object and start setting hidden values.
3429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(isolate);
3430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<v8::ObjectTemplate> instance_templ = fun_templ->InstanceTemplate();
3431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  instance_templ->SetNamedPropertyHandler(InterceptorForHiddenProperties);
3432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<v8::Function> function = fun_templ->GetFunction();
3433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<v8::Object> obj = function->NewInstance();
3434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(obj->SetHiddenValue(key, v8::Integer::New(isolate, 2302)));
3435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2302, obj->GetHiddenValue(key)->Int32Value());
3436d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CHECK(!interceptor_for_hidden_properties_called);
3437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(External) {
3441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(CcTest::isolate());
3442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int x = 3;
3443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::External> ext = v8::External::New(CcTest::isolate(), &x);
3444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext env;
3445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env->Global()->Set(v8_str("ext"), ext);
3446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Value> reext_obj = CompileRun("this.ext");
34476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  v8::Handle<v8::External> reext = reext_obj.As<v8::External>();
3448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int* ptr = static_cast<int*>(reext->Value());
3449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(x, 3);
3450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  *ptr = 10;
3451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(x, 10);
3452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make sure unaligned pointers are wrapped properly.
3454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  char* data = i::StrDup("0123456789");
3455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::Value> zero = v8::External::New(CcTest::isolate(), &data[0]);
3456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::Value> one = v8::External::New(CcTest::isolate(), &data[1]);
3457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::Value> two = v8::External::New(CcTest::isolate(), &data[2]);
3458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::Value> three = v8::External::New(CcTest::isolate(), &data[3]);
3459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  char* char_ptr = reinterpret_cast<char*>(v8::External::Cast(*zero)->Value());
3461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ('0', *char_ptr);
3462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  char_ptr = reinterpret_cast<char*>(v8::External::Cast(*one)->Value());
3463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ('1', *char_ptr);
3464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  char_ptr = reinterpret_cast<char*>(v8::External::Cast(*two)->Value());
3465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ('2', *char_ptr);
3466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  char_ptr = reinterpret_cast<char*>(v8::External::Cast(*three)->Value());
3467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ('3', *char_ptr);
3468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  i::DeleteArray(data);
3469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(GlobalHandle) {
3473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
3474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Persistent<String> global;
3475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {
3476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(isolate);
3477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    global.Reset(isolate, v8_str("str"));
3478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
3480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(isolate);
3481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
3482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  global.Reset();
3484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
3485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(isolate);
3486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    global.Reset(isolate, v8_str("str"));
3487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
3489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(isolate);
3490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
3491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  global.Reset();
3493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(ResettingGlobalHandle) {
3497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
3498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Persistent<String> global;
3499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
3500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(isolate);
3501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    global.Reset(isolate, v8_str("str"));
3502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::internal::GlobalHandles* global_handles =
3504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
3505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int initial_handle_count = global_handles->global_handles_count();
3506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
3507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(isolate);
3508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
3509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
3511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(isolate);
3512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    global.Reset(isolate, v8_str("longer"));
3513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(global_handles->global_handles_count(), initial_handle_count);
3515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
3516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(isolate);
3517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 6);
3518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  global.Reset();
3520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(global_handles->global_handles_count(), initial_handle_count - 1);
3521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
35223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
35233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(ResettingGlobalHandleToEmpty) {
3525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
3526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Persistent<String> global;
3527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
3528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(isolate);
3529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    global.Reset(isolate, v8_str("str"));
3530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::internal::GlobalHandles* global_handles =
3532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
3533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int initial_handle_count = global_handles->global_handles_count();
3534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
3535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(isolate);
3536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
3537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
3539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(isolate);
3540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<String> empty;
3541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    global.Reset(isolate, empty);
3542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(global.IsEmpty());
3544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(global_handles->global_handles_count(), initial_handle_count - 1);
354544f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
354644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
35473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<class T>
3549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic v8::UniquePersistent<T> PassUnique(v8::UniquePersistent<T> unique) {
3550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return unique.Pass();
3551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
355244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
355344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<class T>
3555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic v8::UniquePersistent<T> ReturnUnique(v8::Isolate* isolate,
3556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                            const v8::Persistent<T> & global) {
3557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::UniquePersistent<String> unique(isolate, global);
3558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return unique.Pass();
3559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
35603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
356144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(UniquePersistent) {
3563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
3564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Persistent<String> global;
3565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
3566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(isolate);
3567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    global.Reset(isolate, v8_str("str"));
356844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
3569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::internal::GlobalHandles* global_handles =
3570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
3571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int initial_handle_count = global_handles->global_handles_count();
357244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  {
3573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::UniquePersistent<String> unique(isolate, global);
3574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
3575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Test assignment via Pass
3576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    {
3577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::UniquePersistent<String> copy = unique.Pass();
3578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CHECK(unique.IsEmpty());
3579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CHECK(copy == global);
3580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CHECK_EQ(initial_handle_count + 1,
3581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               global_handles->global_handles_count());
3582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      unique = copy.Pass();
3583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
3584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Test ctor via Pass
3585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    {
3586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::UniquePersistent<String> copy(unique.Pass());
3587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CHECK(unique.IsEmpty());
3588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CHECK(copy == global);
3589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CHECK_EQ(initial_handle_count + 1,
3590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               global_handles->global_handles_count());
3591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      unique = copy.Pass();
3592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
3593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Test pass through function call
3594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    {
3595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::UniquePersistent<String> copy = PassUnique(unique.Pass());
3596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CHECK(unique.IsEmpty());
3597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CHECK(copy == global);
3598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CHECK_EQ(initial_handle_count + 1,
3599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               global_handles->global_handles_count());
3600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      unique = copy.Pass();
3601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
3602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
360344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
3604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Test pass from function call
3605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
3606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::UniquePersistent<String> unique = ReturnUnique(isolate, global);
3607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(unique == global);
3608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
3609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(initial_handle_count, global_handles->global_handles_count());
3611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  global.Reset();
3612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
361344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
361444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<typename K, typename V>
3616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass WeakStdMapTraits : public v8::StdMapTraits<K, V> {
3617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
3618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  typedef typename v8::PersistentValueMap<K, V, WeakStdMapTraits<K, V> >
3619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      MapType;
3620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const v8::PersistentContainerCallbackType kCallbackType = v8::kWeak;
3621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  struct WeakCallbackDataType {
3622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MapType* map;
3623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    K key;
3624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  };
3625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static WeakCallbackDataType* WeakCallbackParameter(
3626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      MapType* map, const K& key, Local<V> value) {
3627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    WeakCallbackDataType* data = new WeakCallbackDataType;
3628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    data->map = map;
3629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    data->key = key;
3630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return data;
3631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static MapType* MapFromWeakCallbackData(
3633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      const v8::WeakCallbackData<V, WeakCallbackDataType>& data) {
3634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return data.GetParameter()->map;
3635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static K KeyFromWeakCallbackData(
3637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      const v8::WeakCallbackData<V, WeakCallbackDataType>& data) {
3638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return data.GetParameter()->key;
3639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static void DisposeCallbackData(WeakCallbackDataType* data) {
3641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    delete data;
3642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static void Dispose(v8::Isolate* isolate, v8::UniquePersistent<V> value,
3644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      K key) { }
3645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
364644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<typename Map>
3649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void TestPersistentValueMap() {
3650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
3651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
3652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Map map(isolate);
3653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::internal::GlobalHandles* global_handles =
3654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
3655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int initial_handle_count = global_handles->global_handles_count();
3656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, static_cast<int>(map.Size()));
365744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  {
3658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    HandleScope scope(isolate);
3659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<v8::Object> obj = map.Get(7);
3660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(obj.IsEmpty());
3661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<v8::Object> expected = v8::Object::New(isolate);
3662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    map.Set(7, expected);
3663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(1, static_cast<int>(map.Size()));
3664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    obj = map.Get(7);
3665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(expected, obj);
3666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    {
3667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      typename Map::PersistentValueReference ref = map.GetReference(7);
3668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CHECK_EQ(expected, ref.NewLocal(isolate));
3669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
3670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::UniquePersistent<v8::Object> removed = map.Remove(7);
3671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(0, static_cast<int>(map.Size()));
3672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(expected == removed);
3673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    removed = map.Remove(7);
3674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(removed.IsEmpty());
3675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    map.Set(8, expected);
3676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(1, static_cast<int>(map.Size()));
3677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    map.Set(8, expected);
3678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(1, static_cast<int>(map.Size()));
3679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    {
3680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      typename Map::PersistentValueReference ref;
3681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Local<v8::Object> expected2 = v8::Object::New(isolate);
3682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      removed = map.Set(8,
3683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          v8::UniquePersistent<v8::Object>(isolate, expected2), &ref);
3684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CHECK_EQ(1, static_cast<int>(map.Size()));
3685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CHECK(expected == removed);
3686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CHECK_EQ(expected2, ref.NewLocal(isolate));
3687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
368844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
3689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
3690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (map.IsWeak()) {
3691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    reinterpret_cast<v8::internal::Isolate*>(isolate)->heap()->
3692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
3693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
3694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    map.Clear();
3695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, static_cast<int>(map.Size()));
3697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(initial_handle_count, global_handles->global_handles_count());
3698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
369944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
370044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(PersistentValueMap) {
3702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Default case, w/o weak callbacks:
3703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TestPersistentValueMap<v8::StdPersistentValueMap<int, v8::Object> >();
370444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Custom traits with weak callbacks:
3706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  typedef v8::PersistentValueMap<int, v8::Object,
3707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      WeakStdMapTraits<int, v8::Object> > WeakPersistentValueMap;
3708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TestPersistentValueMap<WeakPersistentValueMap>();
370944f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
371044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
371144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(PersistentValueVector) {
371344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LocalContext env;
3714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
3715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::internal::GlobalHandles* global_handles =
3716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
3717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int handle_count = global_handles->global_handles_count();
3718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HandleScope scope(isolate);
371944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::PersistentValueVector<v8::Object> vector(isolate);
372144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::Object> obj1 = v8::Object::New(isolate);
3723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::Object> obj2 = v8::Object::New(isolate);
3724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::UniquePersistent<v8::Object> obj3(isolate, v8::Object::New(isolate));
372544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(vector.IsEmpty());
3727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, static_cast<int>(vector.Size()));
372844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  vector.ReserveCapacity(3);
3730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(vector.IsEmpty());
373144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  vector.Append(obj1);
3733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  vector.Append(obj2);
3734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  vector.Append(obj1);
3735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  vector.Append(obj3.Pass());
3736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  vector.Append(obj1);
373744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!vector.IsEmpty());
3739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(5, static_cast<int>(vector.Size()));
3740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(obj3.IsEmpty());
3741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(obj1, vector.Get(0));
3742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(obj1, vector.Get(2));
3743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(obj1, vector.Get(4));
3744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(obj2, vector.Get(1));
374544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(5 + handle_count, global_handles->global_handles_count());
3747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  vector.Clear();
3749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(vector.IsEmpty());
3750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, static_cast<int>(vector.Size()));
3751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(handle_count, global_handles->global_handles_count());
3752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(GlobalHandleUpcast) {
3756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
3757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
3758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<String> local = v8::Local<String>::New(isolate, v8_str("str"));
3759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Persistent<String> global_string(isolate, local);
3760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Persistent<Value>& global_value =
3761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Persistent<Value>::Cast(global_string);
3762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(v8::Local<v8::Value>::New(isolate, global_value)->IsString());
3763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(global_string == v8::Persistent<String>::Cast(global_value));
3764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  global_string.Reset();
3765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(HandleEquality) {
3769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
3770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Persistent<String> global1;
3771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Persistent<String> global2;
377244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  {
3773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(isolate);
3774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    global1.Reset(isolate, v8_str("str"));
3775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    global2.Reset(isolate, v8_str("str2"));
377644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
3777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(global1 == global1, true);
3778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(global1 != global1, false);
3779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
3780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(isolate);
3781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<String> local1 = Local<String>::New(isolate, global1);
3782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<String> local2 = Local<String>::New(isolate, global2);
378344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(global1 == local1, true);
3785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(global1 != local1, false);
3786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(local1 == global1, true);
3787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(local1 != global1, false);
378844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(global1 == local2, false);
3790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(global1 != local2, true);
3791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(local2 == global1, false);
3792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(local2 != global1, true);
379344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(local1 == local2, false);
3795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(local1 != local2, true);
379644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<String> anotherLocal1 = Local<String>::New(isolate, global1);
3798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(local1 == anotherLocal1, true);
3799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(local1 != anotherLocal1, false);
3800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  global1.Reset();
3802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  global2.Reset();
380344f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
380444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
380544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(LocalHandle) {
3807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(CcTest::isolate());
3808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<String> local =
3809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Local<String>::New(CcTest::isolate(), v8_str("str"));
3810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(local->Length(), 3);
3811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass WeakCallCounter {
3815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
3816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  explicit WeakCallCounter(int id) : id_(id), number_of_weak_calls_(0) { }
3817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int id() { return id_; }
3818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void increment() { number_of_weak_calls_++; }
3819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int NumberOfWeakCalls() { return number_of_weak_calls_; }
3820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
3821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int id_;
3822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int number_of_weak_calls_;
3823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
3824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<typename T>
3827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstruct WeakCallCounterAndPersistent {
3828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  explicit WeakCallCounterAndPersistent(WeakCallCounter* counter)
3829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : counter(counter) {}
3830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  WeakCallCounter* counter;
3831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Persistent<T> handle;
3832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
3833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate <typename T>
3836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void WeakPointerCallback(
3837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::WeakCallbackData<T, WeakCallCounterAndPersistent<T> >& data) {
3838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1234, data.GetParameter()->counter->id());
3839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  data.GetParameter()->counter->increment();
3840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  data.GetParameter()->handle.Reset();
3841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<typename T>
3845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic UniqueId MakeUniqueId(const Persistent<T>& p) {
3846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return UniqueId(reinterpret_cast<uintptr_t>(*v8::Utils::OpenPersistent(p)));
3847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(ApiObjectGroups) {
3851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
3852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* iso = env->GetIsolate();
3853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HandleScope scope(iso);
3854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  WeakCallCounter counter(1234);
3856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  WeakCallCounterAndPersistent<Value> g1s1(&counter);
3858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  WeakCallCounterAndPersistent<Value> g1s2(&counter);
3859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  WeakCallCounterAndPersistent<Value> g1c1(&counter);
3860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  WeakCallCounterAndPersistent<Value> g2s1(&counter);
3861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  WeakCallCounterAndPersistent<Value> g2s2(&counter);
3862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  WeakCallCounterAndPersistent<Value> g2c1(&counter);
3863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
3865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    HandleScope scope(iso);
3866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g1s1.handle.Reset(iso, Object::New(iso));
3867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g1s2.handle.Reset(iso, Object::New(iso));
3868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g1c1.handle.Reset(iso, Object::New(iso));
3869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback);
3870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback);
3871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback);
3872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g2s1.handle.Reset(iso, Object::New(iso));
3874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g2s2.handle.Reset(iso, Object::New(iso));
3875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g2c1.handle.Reset(iso, Object::New(iso));
3876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback);
3877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback);
3878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback);
3879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  WeakCallCounterAndPersistent<Value> root(&counter);
3882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  root.handle.Reset(iso, g1s1.handle);  // make a root.
3883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Connect group 1 and 2, make a cycle.
3885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
3886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    HandleScope scope(iso);
3887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(Local<Object>::New(iso, g1s2.handle.As<Object>())->
3888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            Set(0, Local<Value>::New(iso, g2s2.handle)));
3889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(Local<Object>::New(iso, g2s1.handle.As<Object>())->
3890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            Set(0, Local<Value>::New(iso, g1s1.handle)));
3891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
3894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    UniqueId id1 = MakeUniqueId(g1s1.handle);
3895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    UniqueId id2 = MakeUniqueId(g2s2.handle);
3896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetObjectGroupId(g1s1.handle, id1);
3897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetObjectGroupId(g1s2.handle, id1);
3898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetReferenceFromGroup(id1, g1c1.handle);
3899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetObjectGroupId(g2s1.handle, id2);
3900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetObjectGroupId(g2s2.handle, id2);
3901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetReferenceFromGroup(id2, g2c1.handle);
3902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Do a single full GC, ensure incremental marking is stopped.
3904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>(
3905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      iso)->heap();
3906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
3907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // All object should be alive.
3909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, counter.NumberOfWeakCalls());
3910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Weaken the root.
3912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  root.handle.SetWeak(&root, &WeakPointerCallback);
3913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // But make children strong roots---all the objects (except for children)
3914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // should be collectable now.
3915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  g1c1.handle.ClearWeak();
3916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  g2c1.handle.ClearWeak();
3917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Groups are deleted, rebuild groups.
3919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
3920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    UniqueId id1 = MakeUniqueId(g1s1.handle);
3921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    UniqueId id2 = MakeUniqueId(g2s2.handle);
3922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetObjectGroupId(g1s1.handle, id1);
3923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetObjectGroupId(g1s2.handle, id1);
3924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetReferenceFromGroup(id1, g1c1.handle);
3925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetObjectGroupId(g2s1.handle, id2);
3926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetObjectGroupId(g2s2.handle, id2);
3927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetReferenceFromGroup(id2, g2c1.handle);
3928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
3931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // All objects should be gone. 5 global handles in total.
3933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(5, counter.NumberOfWeakCalls());
3934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // And now make children weak again and collect them.
3936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback);
3937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback);
3938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
3940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(7, counter.NumberOfWeakCalls());
3941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(ApiObjectGroupsForSubtypes) {
3945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
3946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* iso = env->GetIsolate();
3947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HandleScope scope(iso);
3948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  WeakCallCounter counter(1234);
3950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  WeakCallCounterAndPersistent<Object> g1s1(&counter);
3952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  WeakCallCounterAndPersistent<String> g1s2(&counter);
3953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  WeakCallCounterAndPersistent<String> g1c1(&counter);
3954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  WeakCallCounterAndPersistent<Object> g2s1(&counter);
3955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  WeakCallCounterAndPersistent<String> g2s2(&counter);
3956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  WeakCallCounterAndPersistent<String> g2c1(&counter);
3957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
3959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    HandleScope scope(iso);
3960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g1s1.handle.Reset(iso, Object::New(iso));
3961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g1s2.handle.Reset(iso, String::NewFromUtf8(iso, "foo1"));
3962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g1c1.handle.Reset(iso, String::NewFromUtf8(iso, "foo2"));
3963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback);
3964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback);
3965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback);
3966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g2s1.handle.Reset(iso, Object::New(iso));
3968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g2s2.handle.Reset(iso, String::NewFromUtf8(iso, "foo3"));
3969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g2c1.handle.Reset(iso, String::NewFromUtf8(iso, "foo4"));
3970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback);
3971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback);
3972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback);
3973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  WeakCallCounterAndPersistent<Value> root(&counter);
3976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  root.handle.Reset(iso, g1s1.handle);  // make a root.
3977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Connect group 1 and 2, make a cycle.
3979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
3980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    HandleScope scope(iso);
3981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(Local<Object>::New(iso, g1s1.handle)
3982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              ->Set(0, Local<Object>::New(iso, g2s1.handle)));
3983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(Local<Object>::New(iso, g2s1.handle)
3984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              ->Set(0, Local<Object>::New(iso, g1s1.handle)));
3985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
3988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    UniqueId id1 = MakeUniqueId(g1s1.handle);
3989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    UniqueId id2 = MakeUniqueId(g2s2.handle);
3990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetObjectGroupId(g1s1.handle, id1);
3991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetObjectGroupId(g1s2.handle, id1);
3992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetReference(g1s1.handle, g1c1.handle);
3993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetObjectGroupId(g2s1.handle, id2);
3994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetObjectGroupId(g2s2.handle, id2);
3995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetReferenceFromGroup(id2, g2c1.handle);
3996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Do a single full GC, ensure incremental marking is stopped.
3998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>(
3999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      iso)->heap();
4000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
4001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // All object should be alive.
4003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, counter.NumberOfWeakCalls());
4004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Weaken the root.
4006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  root.handle.SetWeak(&root, &WeakPointerCallback);
4007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // But make children strong roots---all the objects (except for children)
4008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // should be collectable now.
4009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  g1c1.handle.ClearWeak();
4010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  g2c1.handle.ClearWeak();
4011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Groups are deleted, rebuild groups.
4013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
4014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    UniqueId id1 = MakeUniqueId(g1s1.handle);
4015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    UniqueId id2 = MakeUniqueId(g2s2.handle);
4016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetObjectGroupId(g1s1.handle, id1);
4017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetObjectGroupId(g1s2.handle, id1);
4018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetReference(g1s1.handle, g1c1.handle);
4019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetObjectGroupId(g2s1.handle, id2);
4020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetObjectGroupId(g2s2.handle, id2);
4021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetReferenceFromGroup(id2, g2c1.handle);
4022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
4025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // All objects should be gone. 5 global handles in total.
4027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(5, counter.NumberOfWeakCalls());
4028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // And now make children weak again and collect them.
4030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback);
4031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback);
4032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
4034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(7, counter.NumberOfWeakCalls());
4035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(ApiObjectGroupsCycle) {
4039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
4040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* iso = env->GetIsolate();
4041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HandleScope scope(iso);
4042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  WeakCallCounter counter(1234);
4044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  WeakCallCounterAndPersistent<Value> g1s1(&counter);
4046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  WeakCallCounterAndPersistent<Value> g1s2(&counter);
4047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  WeakCallCounterAndPersistent<Value> g2s1(&counter);
4048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  WeakCallCounterAndPersistent<Value> g2s2(&counter);
4049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  WeakCallCounterAndPersistent<Value> g3s1(&counter);
4050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  WeakCallCounterAndPersistent<Value> g3s2(&counter);
4051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  WeakCallCounterAndPersistent<Value> g4s1(&counter);
4052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  WeakCallCounterAndPersistent<Value> g4s2(&counter);
4053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
4055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    HandleScope scope(iso);
4056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g1s1.handle.Reset(iso, Object::New(iso));
4057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g1s2.handle.Reset(iso, Object::New(iso));
4058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback);
4059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback);
4060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(g1s1.handle.IsWeak());
4061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(g1s2.handle.IsWeak());
4062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g2s1.handle.Reset(iso, Object::New(iso));
4064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g2s2.handle.Reset(iso, Object::New(iso));
4065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback);
4066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback);
4067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(g2s1.handle.IsWeak());
4068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(g2s2.handle.IsWeak());
4069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g3s1.handle.Reset(iso, Object::New(iso));
4071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g3s2.handle.Reset(iso, Object::New(iso));
4072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g3s1.handle.SetWeak(&g3s1, &WeakPointerCallback);
4073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g3s2.handle.SetWeak(&g3s2, &WeakPointerCallback);
4074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(g3s1.handle.IsWeak());
4075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(g3s2.handle.IsWeak());
4076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g4s1.handle.Reset(iso, Object::New(iso));
4078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g4s2.handle.Reset(iso, Object::New(iso));
4079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g4s1.handle.SetWeak(&g4s1, &WeakPointerCallback);
4080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g4s2.handle.SetWeak(&g4s2, &WeakPointerCallback);
4081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(g4s1.handle.IsWeak());
4082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(g4s2.handle.IsWeak());
4083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  WeakCallCounterAndPersistent<Value> root(&counter);
4086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  root.handle.Reset(iso, g1s1.handle);  // make a root.
4087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Connect groups.  We're building the following cycle:
4089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other
4090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // groups.
4091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
4092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    UniqueId id1 = MakeUniqueId(g1s1.handle);
4093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    UniqueId id2 = MakeUniqueId(g2s1.handle);
4094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    UniqueId id3 = MakeUniqueId(g3s1.handle);
4095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    UniqueId id4 = MakeUniqueId(g4s1.handle);
4096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetObjectGroupId(g1s1.handle, id1);
4097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetObjectGroupId(g1s2.handle, id1);
4098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetReferenceFromGroup(id1, g2s1.handle);
4099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetObjectGroupId(g2s1.handle, id2);
4100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetObjectGroupId(g2s2.handle, id2);
4101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetReferenceFromGroup(id2, g3s1.handle);
4102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetObjectGroupId(g3s1.handle, id3);
4103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetObjectGroupId(g3s2.handle, id3);
4104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetReferenceFromGroup(id3, g4s1.handle);
4105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetObjectGroupId(g4s1.handle, id4);
4106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetObjectGroupId(g4s2.handle, id4);
4107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetReferenceFromGroup(id4, g1s1.handle);
4108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Do a single full GC
4110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>(
4111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      iso)->heap();
4112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
4113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // All object should be alive.
4115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, counter.NumberOfWeakCalls());
4116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Weaken the root.
4118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  root.handle.SetWeak(&root, &WeakPointerCallback);
4119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Groups are deleted, rebuild groups.
4121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
4122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    UniqueId id1 = MakeUniqueId(g1s1.handle);
4123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    UniqueId id2 = MakeUniqueId(g2s1.handle);
4124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    UniqueId id3 = MakeUniqueId(g3s1.handle);
4125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    UniqueId id4 = MakeUniqueId(g4s1.handle);
4126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetObjectGroupId(g1s1.handle, id1);
4127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetObjectGroupId(g1s2.handle, id1);
4128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetReferenceFromGroup(id1, g2s1.handle);
4129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetObjectGroupId(g2s1.handle, id2);
4130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetObjectGroupId(g2s2.handle, id2);
4131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetReferenceFromGroup(id2, g3s1.handle);
4132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetObjectGroupId(g3s1.handle, id3);
4133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetObjectGroupId(g3s2.handle, id3);
4134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetReferenceFromGroup(id3, g4s1.handle);
4135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetObjectGroupId(g4s1.handle, id4);
4136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetObjectGroupId(g4s2.handle, id4);
4137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetReferenceFromGroup(id4, g1s1.handle);
4138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
4141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // All objects should be gone. 9 global handles in total.
4143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(9, counter.NumberOfWeakCalls());
4144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// TODO(mstarzinger): This should be a THREADED_TEST but causes failures
4148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// on the buildbots, so was made non-threaded for the time being.
4149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(ApiObjectGroupsCycleForScavenger) {
4150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::FLAG_stress_compaction = false;
4151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::FLAG_gc_global = false;
4152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
4153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* iso = env->GetIsolate();
4154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HandleScope scope(iso);
4155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  WeakCallCounter counter(1234);
4157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  WeakCallCounterAndPersistent<Value> g1s1(&counter);
4159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  WeakCallCounterAndPersistent<Value> g1s2(&counter);
4160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  WeakCallCounterAndPersistent<Value> g2s1(&counter);
4161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  WeakCallCounterAndPersistent<Value> g2s2(&counter);
4162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  WeakCallCounterAndPersistent<Value> g3s1(&counter);
4163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  WeakCallCounterAndPersistent<Value> g3s2(&counter);
4164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
4166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    HandleScope scope(iso);
4167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g1s1.handle.Reset(iso, Object::New(iso));
4168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g1s2.handle.Reset(iso, Object::New(iso));
4169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback);
4170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback);
4171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g2s1.handle.Reset(iso, Object::New(iso));
4173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g2s2.handle.Reset(iso, Object::New(iso));
4174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback);
4175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback);
4176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g3s1.handle.Reset(iso, Object::New(iso));
4178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g3s2.handle.Reset(iso, Object::New(iso));
4179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g3s1.handle.SetWeak(&g3s1, &WeakPointerCallback);
4180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g3s2.handle.SetWeak(&g3s2, &WeakPointerCallback);
4181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Make a root.
4184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  WeakCallCounterAndPersistent<Value> root(&counter);
4185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  root.handle.Reset(iso, g1s1.handle);
4186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  root.handle.MarkPartiallyDependent();
4187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Connect groups.  We're building the following cycle:
4189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other
4190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // groups.
4191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
4192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    HandleScope handle_scope(iso);
4193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g1s1.handle.MarkPartiallyDependent();
4194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g1s2.handle.MarkPartiallyDependent();
4195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g2s1.handle.MarkPartiallyDependent();
4196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g2s2.handle.MarkPartiallyDependent();
4197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g3s1.handle.MarkPartiallyDependent();
4198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g3s2.handle.MarkPartiallyDependent();
4199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetObjectGroupId(g1s1.handle, UniqueId(1));
4200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetObjectGroupId(g1s2.handle, UniqueId(1));
4201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<Object>::New(iso, g1s1.handle.As<Object>())->Set(
4202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v8_str("x"), Local<Value>::New(iso, g2s1.handle));
4203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetObjectGroupId(g2s1.handle, UniqueId(2));
4204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetObjectGroupId(g2s2.handle, UniqueId(2));
4205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<Object>::New(iso, g2s1.handle.As<Object>())->Set(
4206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v8_str("x"), Local<Value>::New(iso, g3s1.handle));
4207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetObjectGroupId(g3s1.handle, UniqueId(3));
4208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetObjectGroupId(g3s2.handle, UniqueId(3));
4209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<Object>::New(iso, g3s1.handle.As<Object>())->Set(
4210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v8_str("x"), Local<Value>::New(iso, g1s1.handle));
4211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>(
4214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      iso)->heap();
4215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  heap->CollectAllGarbage(i::Heap::kNoGCFlags);
4216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // All objects should be alive.
4218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, counter.NumberOfWeakCalls());
4219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Weaken the root.
4221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  root.handle.SetWeak(&root, &WeakPointerCallback);
4222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  root.handle.MarkPartiallyDependent();
4223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Groups are deleted, rebuild groups.
4225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
4226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    HandleScope handle_scope(iso);
4227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g1s1.handle.MarkPartiallyDependent();
4228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g1s2.handle.MarkPartiallyDependent();
4229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g2s1.handle.MarkPartiallyDependent();
4230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g2s2.handle.MarkPartiallyDependent();
4231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g3s1.handle.MarkPartiallyDependent();
4232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    g3s2.handle.MarkPartiallyDependent();
4233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetObjectGroupId(g1s1.handle, UniqueId(1));
4234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetObjectGroupId(g1s2.handle, UniqueId(1));
4235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<Object>::New(iso, g1s1.handle.As<Object>())->Set(
4236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v8_str("x"), Local<Value>::New(iso, g2s1.handle));
4237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetObjectGroupId(g2s1.handle, UniqueId(2));
4238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetObjectGroupId(g2s2.handle, UniqueId(2));
4239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<Object>::New(iso, g2s1.handle.As<Object>())->Set(
4240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v8_str("x"), Local<Value>::New(iso, g3s1.handle));
4241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetObjectGroupId(g3s1.handle, UniqueId(3));
4242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iso->SetObjectGroupId(g3s2.handle, UniqueId(3));
4243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<Object>::New(iso, g3s1.handle.As<Object>())->Set(
4244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v8_str("x"), Local<Value>::New(iso, g1s1.handle));
4245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  heap->CollectAllGarbage(i::Heap::kNoGCFlags);
4248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // All objects should be gone. 7 global handles in total.
4250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(7, counter.NumberOfWeakCalls());
4251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(ScriptException) {
4255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
4256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
4257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Script> script = v8_compile("throw 'panama!';");
4258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::TryCatch try_catch;
4259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Value> result = script->Run();
4260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(result.IsEmpty());
4261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(try_catch.HasCaught());
4262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  String::Utf8Value exception_value(try_catch.Exception());
4263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(*exception_value, "panama!");
4264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(TryCatchCustomException) {
4268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
4269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
4270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::TryCatch try_catch;
4271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("function CustomError() { this.a = 'b'; }"
4272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "(function f() { throw new CustomError(); })();");
4273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(try_catch.HasCaught());
4274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(try_catch.Exception()->ToObject()->
4275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            Get(v8_str("a"))->Equals(v8_str("b")));
4276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool message_received;
4280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void check_message_0(v8::Handle<v8::Message> message,
4283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            v8::Handle<Value> data) {
4284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(5.76, data->NumberValue());
4285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(6.75, message->GetScriptOrigin().ResourceName()->NumberValue());
4286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!message->IsSharedCrossOrigin());
4287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  message_received = true;
4288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(MessageHandler0) {
4292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  message_received = false;
4293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(CcTest::isolate());
4294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!message_received);
4295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
4296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::V8::AddMessageListener(check_message_0, v8_num(5.76));
4297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Script> script = CompileWithOrigin("throw 'error'", "6.75");
4298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  script->Run();
4299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(message_received);
4300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // clear out the message listener
4301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::V8::RemoveMessageListeners(check_message_0);
4302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void check_message_1(v8::Handle<v8::Message> message,
4306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            v8::Handle<Value> data) {
4307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(data->IsNumber());
4308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1337, data->Int32Value());
4309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!message->IsSharedCrossOrigin());
4310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  message_received = true;
4311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(MessageHandler1) {
4315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  message_received = false;
4316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(CcTest::isolate());
4317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!message_received);
4318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::V8::AddMessageListener(check_message_1);
4319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
4320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("throw 1337;");
4321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(message_received);
4322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // clear out the message listener
4323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::V8::RemoveMessageListeners(check_message_1);
4324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void check_message_2(v8::Handle<v8::Message> message,
4328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            v8::Handle<Value> data) {
4329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
4330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(data->IsObject());
4331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Value> hidden_property =
4332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Object::Cast(*data)->GetHiddenValue(v8_str("hidden key"));
4333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(v8_str("hidden value")->Equals(hidden_property));
4334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!message->IsSharedCrossOrigin());
4335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  message_received = true;
4336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(MessageHandler2) {
4340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  message_received = false;
4341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(CcTest::isolate());
4342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!message_received);
4343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::V8::AddMessageListener(check_message_2);
4344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
4345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Value> error = v8::Exception::Error(v8_str("custom error"));
4346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Object::Cast(*error)->SetHiddenValue(v8_str("hidden key"),
4347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           v8_str("hidden value"));
4348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context->Global()->Set(v8_str("error"), error);
4349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("throw error;");
4350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(message_received);
4351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // clear out the message listener
4352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::V8::RemoveMessageListeners(check_message_2);
4353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void check_message_3(v8::Handle<v8::Message> message,
4357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            v8::Handle<Value> data) {
4358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(message->IsSharedCrossOrigin());
4359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(6.75, message->GetScriptOrigin().ResourceName()->NumberValue());
4360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  message_received = true;
4361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(MessageHandler3) {
4365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  message_received = false;
4366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
4367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
4368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!message_received);
4369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::V8::AddMessageListener(check_message_3);
4370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
4371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::ScriptOrigin origin =
4372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::ScriptOrigin(v8_str("6.75"),
4373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       v8::Integer::New(isolate, 1),
4374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       v8::Integer::New(isolate, 2),
4375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       v8::True(isolate));
4376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
4377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                  &origin);
4378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  script->Run();
4379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(message_received);
4380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // clear out the message listener
4381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::V8::RemoveMessageListeners(check_message_3);
4382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void check_message_4(v8::Handle<v8::Message> message,
4386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            v8::Handle<Value> data) {
4387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!message->IsSharedCrossOrigin());
4388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(6.75, message->GetScriptOrigin().ResourceName()->NumberValue());
4389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  message_received = true;
4390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(MessageHandler4) {
4394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  message_received = false;
4395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
4396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
4397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!message_received);
4398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::V8::AddMessageListener(check_message_4);
4399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
4400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::ScriptOrigin origin =
4401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::ScriptOrigin(v8_str("6.75"),
4402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       v8::Integer::New(isolate, 1),
4403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       v8::Integer::New(isolate, 2),
4404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       v8::False(isolate));
4405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
4406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                  &origin);
4407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  script->Run();
4408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(message_received);
4409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // clear out the message listener
4410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::V8::RemoveMessageListeners(check_message_4);
4411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void check_message_5a(v8::Handle<v8::Message> message,
4415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            v8::Handle<Value> data) {
4416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(message->IsSharedCrossOrigin());
4417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(6.75, message->GetScriptOrigin().ResourceName()->NumberValue());
4418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  message_received = true;
4419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void check_message_5b(v8::Handle<v8::Message> message,
4423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            v8::Handle<Value> data) {
4424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!message->IsSharedCrossOrigin());
4425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(6.75, message->GetScriptOrigin().ResourceName()->NumberValue());
4426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  message_received = true;
4427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(MessageHandler5) {
4431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  message_received = false;
4432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
4433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
4434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(!message_received);
4435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::V8::AddMessageListener(check_message_5a);
4436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
4437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::ScriptOrigin origin =
4438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::ScriptOrigin(v8_str("6.75"),
4439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       v8::Integer::New(isolate, 1),
4440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       v8::Integer::New(isolate, 2),
4441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       v8::True(isolate));
4442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
4443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                  &origin);
4444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  script->Run();
4445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(message_received);
4446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // clear out the message listener
4447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::V8::RemoveMessageListeners(check_message_5a);
4448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  message_received = false;
4450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::V8::AddMessageListener(check_message_5b);
4451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  origin =
4452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::ScriptOrigin(v8_str("6.75"),
4453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       v8::Integer::New(isolate, 1),
4454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       v8::Integer::New(isolate, 2),
4455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       v8::False(isolate));
4456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  script = Script::Compile(v8_str("throw 'error'"),
4457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           &origin);
4458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  script->Run();
4459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(message_received);
4460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // clear out the message listener
4461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::V8::RemoveMessageListeners(check_message_5b);
4462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(GetSetProperty) {
4466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
4467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
4468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
4469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context->Global()->Set(v8_str("foo"), v8_num(14));
4470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context->Global()->Set(v8_str("12"), v8_num(92));
4471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context->Global()->Set(v8::Integer::New(isolate, 16), v8_num(32));
4472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context->Global()->Set(v8_num(13), v8_num(56));
4473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Value> foo = CompileRun("this.foo");
4474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(14, foo->Int32Value());
4475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Value> twelve = CompileRun("this[12]");
4476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(92, twelve->Int32Value());
4477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Value> sixteen = CompileRun("this[16]");
4478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(32, sixteen->Int32Value());
4479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Value> thirteen = CompileRun("this[13]");
4480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(56, thirteen->Int32Value());
4481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(92,
4482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           context->Global()->Get(v8::Integer::New(isolate, 12))->Int32Value());
4483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(92, context->Global()->Get(v8_str("12"))->Int32Value());
4484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(92, context->Global()->Get(v8_num(12))->Int32Value());
4485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(32,
4486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           context->Global()->Get(v8::Integer::New(isolate, 16))->Int32Value());
4487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(32, context->Global()->Get(v8_str("16"))->Int32Value());
4488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(32, context->Global()->Get(v8_num(16))->Int32Value());
4489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(56,
4490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           context->Global()->Get(v8::Integer::New(isolate, 13))->Int32Value());
4491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(56, context->Global()->Get(v8_str("13"))->Int32Value());
4492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(56, context->Global()->Get(v8_num(13))->Int32Value());
4493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(PropertyAttributes) {
4497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
4498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(context->GetIsolate());
44993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // none
45003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Local<String> prop = v8_str("none");
45013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  context->Global()->Set(prop, v8_num(7));
45023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(prop));
4503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // read-only
45043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  prop = v8_str("read_only");
4505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context->Global()->ForceSet(prop, v8_num(7), v8::ReadOnly);
4506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
45073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK_EQ(v8::ReadOnly, context->Global()->GetPropertyAttributes(prop));
4508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("read_only = 9");
4509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
4510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context->Global()->Set(prop, v8_num(10));
4511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
4512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // dont-delete
4513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  prop = v8_str("dont_delete");
4514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context->Global()->ForceSet(prop, v8_num(13), v8::DontDelete);
4515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(13, context->Global()->Get(prop)->Int32Value());
4516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("delete dont_delete");
4517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(13, context->Global()->Get(prop)->Int32Value());
45183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK_EQ(v8::DontDelete, context->Global()->GetPropertyAttributes(prop));
45193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // dont-enum
45203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  prop = v8_str("dont_enum");
4521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context->Global()->ForceSet(prop, v8_num(28), v8::DontEnum);
45223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK_EQ(v8::DontEnum, context->Global()->GetPropertyAttributes(prop));
45233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // absent
45243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  prop = v8_str("absent");
45253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(prop));
45263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Local<Value> fake_prop = v8_num(1);
45273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(fake_prop));
45283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // exception
45293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  TryCatch try_catch;
45303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Local<Value> exception =
45313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      CompileRun("({ toString: function() { throw 'exception';} })");
45323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(exception));
45333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK(try_catch.HasCaught());
4534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  String::Utf8Value exception_value(try_catch.Exception());
45353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK_EQ("exception", *exception_value);
45363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  try_catch.Reset();
4537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(Array) {
4541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
4542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(context->GetIsolate());
4543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::Array> array = v8::Array::New(context->GetIsolate());
4544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, array->Length());
45456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(array->Get(0)->IsUndefined());
4546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(!array->Has(0));
45476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(array->Get(100)->IsUndefined());
4548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(!array->Has(100));
45496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  array->Set(2, v8_num(7));
4550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(3, array->Length());
4551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(!array->Has(0));
4552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(!array->Has(1));
4553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(array->Has(2));
45546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(7, array->Get(2)->Int32Value());
4555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Value> obj = CompileRun("[1, 2, 3]");
45566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Local<v8::Array> arr = obj.As<v8::Array>();
4557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(3, arr->Length());
45586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(1, arr->Get(0)->Int32Value());
45596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(2, arr->Get(1)->Int32Value());
45606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(3, arr->Get(2)->Int32Value());
4561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  array = v8::Array::New(context->GetIsolate(), 27);
456244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(27, array->Length());
4563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  array = v8::Array::New(context->GetIsolate(), -27);
456444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, array->Length());
4565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HandleF(const v8::FunctionCallbackInfo<v8::Value>& args) {
4569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::EscapableHandleScope scope(args.GetIsolate());
4570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
4571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::Array> result = v8::Array::New(args.GetIsolate(), args.Length());
4572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < args.Length(); i++)
45736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    result->Set(i, args[i]);
4574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  args.GetReturnValue().Set(scope.Escape(result));
4575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(Vector) {
4579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
4580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
4581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> global = ObjectTemplate::New(isolate);
4582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  global->Set(v8_str("f"), v8::FunctionTemplate::New(isolate, HandleF));
4583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context(0, global);
4584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* fun = "f()";
45866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Local<v8::Array> a0 = CompileRun(fun).As<v8::Array>();
4587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, a0->Length());
4588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* fun2 = "f(11)";
45906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Local<v8::Array> a1 = CompileRun(fun2).As<v8::Array>();
4591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, a1->Length());
45926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(11, a1->Get(0)->Int32Value());
4593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* fun3 = "f(12, 13)";
45956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Local<v8::Array> a2 = CompileRun(fun3).As<v8::Array>();
4596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, a2->Length());
45976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(12, a2->Get(0)->Int32Value());
45986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(13, a2->Get(1)->Int32Value());
4599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* fun4 = "f(14, 15, 16)";
46016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Local<v8::Array> a3 = CompileRun(fun4).As<v8::Array>();
4602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(3, a3->Length());
46036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(14, a3->Get(0)->Int32Value());
46046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(15, a3->Get(1)->Int32Value());
46056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(16, a3->Get(2)->Int32Value());
4606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* fun5 = "f(17, 18, 19, 20)";
46086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Local<v8::Array> a4 = CompileRun(fun5).As<v8::Array>();
4609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(4, a4->Length());
46106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(17, a4->Get(0)->Int32Value());
46116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(18, a4->Get(1)->Int32Value());
46126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(19, a4->Get(2)->Int32Value());
46136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(20, a4->Get(3)->Int32Value());
4614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(FunctionCall) {
4618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
4619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
4620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
4621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CompileRun(
4622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "function Foo() {"
4623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  var result = [];"
4624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  for (var i = 0; i < arguments.length; i++) {"
4625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "    result.push(arguments[i]);"
4626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  }"
4627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  return result;"
4628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "}"
4629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "function ReturnThisSloppy() {"
4630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "  return this;"
4631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "}"
4632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "function ReturnThisStrict() {"
4633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "  'use strict';"
4634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "  return this;"
4635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "}");
4636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Function> Foo =
4637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Local<Function>::Cast(context->Global()->Get(v8_str("Foo")));
4638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Function> ReturnThisSloppy =
4639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Local<Function>::Cast(context->Global()->Get(v8_str("ReturnThisSloppy")));
4640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Function> ReturnThisStrict =
4641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Local<Function>::Cast(context->Global()->Get(v8_str("ReturnThisStrict")));
4642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value>* args0 = NULL;
4644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<v8::Array> a0 = Local<v8::Array>::Cast(Foo->Call(Foo, 0, args0));
4645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, a0->Length());
4646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> args1[] = { v8_num(1.1) };
4648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<v8::Array> a1 = Local<v8::Array>::Cast(Foo->Call(Foo, 1, args1));
4649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, a1->Length());
4650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1.1, a1->Get(v8::Integer::New(isolate, 0))->NumberValue());
4651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> args2[] = { v8_num(2.2),
4653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                v8_num(3.3) };
4654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<v8::Array> a2 = Local<v8::Array>::Cast(Foo->Call(Foo, 2, args2));
4655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, a2->Length());
4656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2.2, a2->Get(v8::Integer::New(isolate, 0))->NumberValue());
4657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(3.3, a2->Get(v8::Integer::New(isolate, 1))->NumberValue());
4658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> args3[] = { v8_num(4.4),
4660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                v8_num(5.5),
4661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                v8_num(6.6) };
4662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<v8::Array> a3 = Local<v8::Array>::Cast(Foo->Call(Foo, 3, args3));
4663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(3, a3->Length());
4664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(4.4, a3->Get(v8::Integer::New(isolate, 0))->NumberValue());
4665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(5.5, a3->Get(v8::Integer::New(isolate, 1))->NumberValue());
4666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(6.6, a3->Get(v8::Integer::New(isolate, 2))->NumberValue());
4667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> args4[] = { v8_num(7.7),
4669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                v8_num(8.8),
4670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                v8_num(9.9),
4671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                v8_num(10.11) };
4672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<v8::Array> a4 = Local<v8::Array>::Cast(Foo->Call(Foo, 4, args4));
4673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(4, a4->Length());
4674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(7.7, a4->Get(v8::Integer::New(isolate, 0))->NumberValue());
4675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(8.8, a4->Get(v8::Integer::New(isolate, 1))->NumberValue());
4676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(9.9, a4->Get(v8::Integer::New(isolate, 2))->NumberValue());
4677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(10.11, a4->Get(v8::Integer::New(isolate, 3))->NumberValue());
4678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::Value> r1 = ReturnThisSloppy->Call(v8::Undefined(isolate), 0, NULL);
4680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(r1->StrictEquals(context->Global()));
4681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::Value> r2 = ReturnThisSloppy->Call(v8::Null(isolate), 0, NULL);
4682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(r2->StrictEquals(context->Global()));
4683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::Value> r3 = ReturnThisSloppy->Call(v8_num(42), 0, NULL);
4684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(r3->IsNumberObject());
4685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(42.0, r3.As<v8::NumberObject>()->ValueOf());
4686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::Value> r4 = ReturnThisSloppy->Call(v8_str("hello"), 0, NULL);
4687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(r4->IsStringObject());
4688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(r4.As<v8::StringObject>()->ValueOf()->StrictEquals(v8_str("hello")));
4689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::Value> r5 = ReturnThisSloppy->Call(v8::True(isolate), 0, NULL);
4690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(r5->IsBooleanObject());
4691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(r5.As<v8::BooleanObject>()->ValueOf());
4692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::Value> r6 = ReturnThisStrict->Call(v8::Undefined(isolate), 0, NULL);
4694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(r6->IsUndefined());
4695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::Value> r7 = ReturnThisStrict->Call(v8::Null(isolate), 0, NULL);
4696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(r7->IsNull());
4697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::Value> r8 = ReturnThisStrict->Call(v8_num(42), 0, NULL);
4698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(r8->StrictEquals(v8_num(42)));
4699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::Value> r9 = ReturnThisStrict->Call(v8_str("hello"), 0, NULL);
4700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(r9->StrictEquals(v8_str("hello")));
4701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::Value> r10 = ReturnThisStrict->Call(v8::True(isolate), 0, NULL);
4702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(r10->StrictEquals(v8::True(isolate)));
4703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(ConstructCall) {
4707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
4708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
4709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
4710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CompileRun(
4711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "function Foo() {"
4712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  var result = [];"
4713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  for (var i = 0; i < arguments.length; i++) {"
4714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "    result.push(arguments[i]);"
4715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  }"
4716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  return result;"
4717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "}");
4718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Function> Foo =
4719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Local<Function>::Cast(context->Global()->Get(v8_str("Foo")));
4720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value>* args0 = NULL;
4722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<v8::Array> a0 = Local<v8::Array>::Cast(Foo->NewInstance(0, args0));
4723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, a0->Length());
4724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> args1[] = { v8_num(1.1) };
4726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<v8::Array> a1 = Local<v8::Array>::Cast(Foo->NewInstance(1, args1));
4727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, a1->Length());
4728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1.1, a1->Get(v8::Integer::New(isolate, 0))->NumberValue());
4729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> args2[] = { v8_num(2.2),
4731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                v8_num(3.3) };
4732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<v8::Array> a2 = Local<v8::Array>::Cast(Foo->NewInstance(2, args2));
4733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, a2->Length());
4734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2.2, a2->Get(v8::Integer::New(isolate, 0))->NumberValue());
4735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(3.3, a2->Get(v8::Integer::New(isolate, 1))->NumberValue());
4736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> args3[] = { v8_num(4.4),
4738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                v8_num(5.5),
4739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                v8_num(6.6) };
4740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<v8::Array> a3 = Local<v8::Array>::Cast(Foo->NewInstance(3, args3));
4741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(3, a3->Length());
4742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(4.4, a3->Get(v8::Integer::New(isolate, 0))->NumberValue());
4743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(5.5, a3->Get(v8::Integer::New(isolate, 1))->NumberValue());
4744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(6.6, a3->Get(v8::Integer::New(isolate, 2))->NumberValue());
4745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> args4[] = { v8_num(7.7),
4747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                v8_num(8.8),
4748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                v8_num(9.9),
4749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                v8_num(10.11) };
4750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<v8::Array> a4 = Local<v8::Array>::Cast(Foo->NewInstance(4, args4));
4751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(4, a4->Length());
4752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(7.7, a4->Get(v8::Integer::New(isolate, 0))->NumberValue());
4753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(8.8, a4->Get(v8::Integer::New(isolate, 1))->NumberValue());
4754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(9.9, a4->Get(v8::Integer::New(isolate, 2))->NumberValue());
4755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(10.11, a4->Get(v8::Integer::New(isolate, 3))->NumberValue());
4756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void CheckUncle(v8::TryCatch* try_catch) {
4760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(try_catch->HasCaught());
4761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  String::Utf8Value str_value(try_catch->Exception());
4762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(*str_value, "uncle?");
4763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  try_catch->Reset();
4764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
47676ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockTHREADED_TEST(ConversionNumber) {
47686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  LocalContext env;
4769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
47706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Very large number.
47716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CompileRun("var obj = Math.pow(2,32) * 1237;");
47726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Local<Value> obj = env->Global()->Get(v8_str("obj"));
47736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(5312874545152.0, obj->ToNumber()->Value());
47746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(0, obj->ToInt32()->Value());
47756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(0u == obj->ToUint32()->Value());  // NOLINT - no CHECK_EQ for unsigned.
47766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Large number.
47776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CompileRun("var obj = -1234567890123;");
47786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  obj = env->Global()->Get(v8_str("obj"));
47796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(-1234567890123.0, obj->ToNumber()->Value());
47806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(-1912276171, obj->ToInt32()->Value());
47816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(2382691125u == obj->ToUint32()->Value());  // NOLINT
47826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Small positive integer.
47836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CompileRun("var obj = 42;");
47846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  obj = env->Global()->Get(v8_str("obj"));
47856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(42.0, obj->ToNumber()->Value());
47866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(42, obj->ToInt32()->Value());
47876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(42u == obj->ToUint32()->Value());  // NOLINT
47886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Negative integer.
47896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CompileRun("var obj = -37;");
47906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  obj = env->Global()->Get(v8_str("obj"));
47916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(-37.0, obj->ToNumber()->Value());
47926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(-37, obj->ToInt32()->Value());
47936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(4294967259u == obj->ToUint32()->Value());  // NOLINT
47946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Positive non-int32 integer.
47956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CompileRun("var obj = 0x81234567;");
47966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  obj = env->Global()->Get(v8_str("obj"));
47976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(2166572391.0, obj->ToNumber()->Value());
47986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(-2128394905, obj->ToInt32()->Value());
47996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(2166572391u == obj->ToUint32()->Value());  // NOLINT
48006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Fraction.
48016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CompileRun("var obj = 42.3;");
48026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  obj = env->Global()->Get(v8_str("obj"));
48036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(42.3, obj->ToNumber()->Value());
48046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(42, obj->ToInt32()->Value());
48056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(42u == obj->ToUint32()->Value());  // NOLINT
48066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Large negative fraction.
48076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CompileRun("var obj = -5726623061.75;");
48086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  obj = env->Global()->Get(v8_str("obj"));
48096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(-5726623061.75, obj->ToNumber()->Value());
48106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(-1431655765, obj->ToInt32()->Value());
48116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(2863311531u == obj->ToUint32()->Value());  // NOLINT
48126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
48136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
48146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
48156ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockTHREADED_TEST(isNumberType) {
48166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  LocalContext env;
4817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
48186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Very large number.
48196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CompileRun("var obj = Math.pow(2,32) * 1237;");
48206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Local<Value> obj = env->Global()->Get(v8_str("obj"));
48216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(!obj->IsInt32());
48226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(!obj->IsUint32());
48236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Large negative number.
48246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CompileRun("var obj = -1234567890123;");
48256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  obj = env->Global()->Get(v8_str("obj"));
48266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(!obj->IsInt32());
48276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(!obj->IsUint32());
48286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Small positive integer.
48296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CompileRun("var obj = 42;");
48306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  obj = env->Global()->Get(v8_str("obj"));
48316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(obj->IsInt32());
48326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(obj->IsUint32());
48336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Negative integer.
48346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CompileRun("var obj = -37;");
48356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  obj = env->Global()->Get(v8_str("obj"));
48366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(obj->IsInt32());
48376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(!obj->IsUint32());
48386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Positive non-int32 integer.
48396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CompileRun("var obj = 0x81234567;");
48406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  obj = env->Global()->Get(v8_str("obj"));
48416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(!obj->IsInt32());
48426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(obj->IsUint32());
48436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Fraction.
48446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CompileRun("var obj = 42.3;");
48456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  obj = env->Global()->Get(v8_str("obj"));
48466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(!obj->IsInt32());
48476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(!obj->IsUint32());
48486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Large negative fraction.
48496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CompileRun("var obj = -5726623061.75;");
48506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  obj = env->Global()->Get(v8_str("obj"));
48516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(!obj->IsInt32());
48526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(!obj->IsUint32());
48533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Positive zero
48543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileRun("var obj = 0.0;");
48553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  obj = env->Global()->Get(v8_str("obj"));
48563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(obj->IsInt32());
48573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(obj->IsUint32());
48583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Positive zero
48593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileRun("var obj = -0.0;");
48603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  obj = env->Global()->Get(v8_str("obj"));
48613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(!obj->IsInt32());
48623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(!obj->IsUint32());
48636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
48646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
48656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(ConversionException) {
4867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext env;
4868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
4869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
4870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CompileRun(
4871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "function TestClass() { };"
4872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "TestClass.prototype.toString = function () { throw 'uncle?'; };"
4873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "var obj = new TestClass();");
4874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Value> obj = env->Global()->Get(v8_str("obj"));
4875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::TryCatch try_catch;
4877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Value> to_string_result = obj->ToString();
4879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(to_string_result.IsEmpty());
4880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckUncle(&try_catch);
4881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Value> to_number_result = obj->ToNumber();
4883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(to_number_result.IsEmpty());
4884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckUncle(&try_catch);
4885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Value> to_integer_result = obj->ToInteger();
4887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(to_integer_result.IsEmpty());
4888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckUncle(&try_catch);
4889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Value> to_uint32_result = obj->ToUint32();
4891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(to_uint32_result.IsEmpty());
4892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckUncle(&try_catch);
4893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Value> to_int32_result = obj->ToInt32();
4895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(to_int32_result.IsEmpty());
4896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckUncle(&try_catch);
4897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Value> to_object_result = v8::Undefined(isolate)->ToObject();
4899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(to_object_result.IsEmpty());
4900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(try_catch.HasCaught());
4901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  try_catch.Reset();
4902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int32_t int32_value = obj->Int32Value();
4904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, int32_value);
4905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckUncle(&try_catch);
4906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  uint32_t uint32_value = obj->Uint32Value();
4908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, uint32_value);
4909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckUncle(&try_catch);
4910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  double number_value = obj->NumberValue();
4912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_NE(0, std::isnan(number_value));
4913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckUncle(&try_catch);
4914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int64_t integer_value = obj->IntegerValue();
4916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0.0, static_cast<double>(integer_value));
4917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckUncle(&try_catch);
4918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid ThrowFromC(const v8::FunctionCallbackInfo<v8::Value>& args) {
4922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
4923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  args.GetIsolate()->ThrowException(v8_str("konto"));
4924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CCatcher(const v8::FunctionCallbackInfo<v8::Value>& args) {
4928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (args.Length() < 1) {
4929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    args.GetReturnValue().Set(false);
4930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
4931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(args.GetIsolate());
4933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::TryCatch try_catch;
4934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Value> result = CompileRun(args[0]->ToString());
4935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(!try_catch.HasCaught() || result.IsEmpty());
4936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  args.GetReturnValue().Set(try_catch.HasCaught());
4937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(APICatch) {
4941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
4942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
4943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
4944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  templ->Set(v8_str("ThrowFromC"),
4945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             v8::FunctionTemplate::New(isolate, ThrowFromC));
4946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context(0, templ);
4947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CompileRun(
4948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "var thrown = false;"
4949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "try {"
4950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  ThrowFromC();"
4951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "} catch (e) {"
4952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  thrown = true;"
4953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "}");
4954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Value> thrown = context->Global()->Get(v8_str("thrown"));
4955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(thrown->BooleanValue());
4956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(APIThrowTryCatch) {
4960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
4961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
4962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
4963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  templ->Set(v8_str("ThrowFromC"),
4964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             v8::FunctionTemplate::New(isolate, ThrowFromC));
4965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context(0, templ);
4966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::TryCatch try_catch;
4967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CompileRun("ThrowFromC();");
4968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(try_catch.HasCaught());
4969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test that a try-finally block doesn't shadow a try-catch block
4973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// when setting up an external handler.
4974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
4975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// BUG(271): Some of the exception propagation does not work on the
4976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ARM simulator because the simulator separates the C++ stack and the
4977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// JS stack.  This test therefore fails on the simulator.  The test is
4978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// not threaded to allow the threading tests to run on the simulator.
4979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(TryCatchInTryFinally) {
4980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
4981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
4982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
4983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  templ->Set(v8_str("CCatcher"),
4984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             v8::FunctionTemplate::New(isolate, CCatcher));
4985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context(0, templ);
4986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Value> result = CompileRun("try {"
4987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   "  try {"
4988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   "    CCatcher('throw 7;');"
4989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   "  } finally {"
4990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   "  }"
4991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   "} catch (e) {"
4992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   "}");
4993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(result->IsTrue());
4994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4997b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochstatic void check_reference_error_message(
4998b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    v8::Handle<v8::Message> message,
4999b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    v8::Handle<v8::Value> data) {
5000b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  const char* reference_error = "Uncaught ReferenceError: asdf is not defined";
5001b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  CHECK(message->Get()->Equals(v8_str(reference_error)));
5002b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch}
5003b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
5004b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
5005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void Fail(const v8::FunctionCallbackInfo<v8::Value>& args) {
50061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ApiTestFuzzer::Fuzz();
50071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  CHECK(false);
50081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
50091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
50101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
50111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// Test that overwritten methods are not invoked on uncaught exception
50121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// formatting. However, they are invoked when performing normal error
50131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// string conversions.
5014b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben MurdochTEST(APIThrowMessageOverwrittenToString) {
5015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
5016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
5017b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  v8::V8::AddMessageListener(check_reference_error_message);
5018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  templ->Set(v8_str("fail"), v8::FunctionTemplate::New(isolate, Fail));
50201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  LocalContext context(NULL, templ);
50211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  CompileRun("asdf;");
50221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  CompileRun("var limit = {};"
50231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block             "limit.valueOf = fail;"
50241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block             "Error.stackTraceLimit = limit;");
50251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  CompileRun("asdf");
50261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  CompileRun("Array.prototype.pop = fail;");
50271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  CompileRun("Object.prototype.hasOwnProperty = fail;");
50281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  CompileRun("Object.prototype.toString = function f() { return 'Yikes'; }");
50291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  CompileRun("Number.prototype.toString = function f() { return 'Yikes'; }");
50301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  CompileRun("String.prototype.toString = function f() { return 'Yikes'; }");
5031b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  CompileRun("ReferenceError.prototype.toString ="
5032b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch             "  function() { return 'Whoops' }");
5033b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  CompileRun("asdf;");
50341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  CompileRun("ReferenceError.prototype.constructor.name = void 0;");
50351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  CompileRun("asdf;");
50361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  CompileRun("ReferenceError.prototype.constructor = void 0;");
50371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  CompileRun("asdf;");
50381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  CompileRun("ReferenceError.prototype.__proto__ = new Object();");
50391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  CompileRun("asdf;");
50401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  CompileRun("ReferenceError.prototype = new Object();");
50411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  CompileRun("asdf;");
5042b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  v8::Handle<Value> string = CompileRun("try { asdf; } catch(e) { e + ''; }");
5043b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  CHECK(string->Equals(v8_str("Whoops")));
50441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  CompileRun("ReferenceError.prototype.constructor = new Object();"
50451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block             "ReferenceError.prototype.constructor.name = 1;"
50461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block             "Number.prototype.toString = function() { return 'Whoops'; };"
50471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block             "ReferenceError.prototype.toString = Object.prototype.toString;");
50481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  CompileRun("asdf;");
5049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::V8::RemoveMessageListeners(check_reference_error_message);
5050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void check_custom_error_tostring(
5054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Handle<v8::Message> message,
5055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Handle<v8::Value> data) {
5056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* uncaught_error = "Uncaught MyError toString";
5057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(message->Get()->Equals(v8_str(uncaught_error)));
5058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(CustomErrorToString) {
5062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
5063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(context->GetIsolate());
5064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::V8::AddMessageListener(check_custom_error_tostring);
5065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun(
5066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "function MyError(name, message) {                   "
5067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "  this.name = name;                                 "
5068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "  this.message = message;                           "
5069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "}                                                   "
5070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "MyError.prototype = Object.create(Error.prototype); "
5071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "MyError.prototype.toString = function() {           "
5072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "  return 'MyError toString';                        "
5073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "};                                                  "
5074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "throw new MyError('my name', 'my message');         ");
5075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::V8::RemoveMessageListeners(check_custom_error_tostring);
5076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void check_custom_error_message(
5080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Handle<v8::Message> message,
5081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Handle<v8::Value> data) {
5082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* uncaught_error = "Uncaught MyError: my message";
5083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  printf("%s\n", *v8::String::Utf8Value(message->Get()));
5084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(message->Get()->Equals(v8_str(uncaught_error)));
5085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(CustomErrorMessage) {
5089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
5090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(context->GetIsolate());
5091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::V8::AddMessageListener(check_custom_error_message);
5092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Handlebars.
5094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun(
5095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "function MyError(msg) {                             "
5096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "  this.name = 'MyError';                            "
5097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "  this.message = msg;                               "
5098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "}                                                   "
5099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "MyError.prototype = new Error();                    "
5100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "throw new MyError('my message');                    ");
5101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Closure.
5103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun(
5104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "function MyError(msg) {                             "
5105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "  this.name = 'MyError';                            "
5106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "  this.message = msg;                               "
5107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "}                                                   "
5108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "inherits = function(childCtor, parentCtor) {        "
5109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "    function tempCtor() {};                         "
5110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "    tempCtor.prototype = parentCtor.prototype;      "
5111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "    childCtor.superClass_ = parentCtor.prototype;   "
5112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "    childCtor.prototype = new tempCtor();           "
5113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "    childCtor.prototype.constructor = childCtor;    "
5114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "};                                                  "
5115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "inherits(MyError, Error);                           "
5116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "throw new MyError('my message');                    ");
5117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Object.create.
5119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun(
5120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "function MyError(msg) {                             "
5121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "  this.name = 'MyError';                            "
5122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "  this.message = msg;                               "
5123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "}                                                   "
5124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "MyError.prototype = Object.create(Error.prototype); "
5125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "throw new MyError('my message');                    ");
5126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::V8::RemoveMessageListeners(check_custom_error_message);
5128b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch}
5129b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
5130b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
5131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void receive_message(v8::Handle<v8::Message> message,
5132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            v8::Handle<v8::Value> data) {
5133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  message->Get();
5134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  message_received = true;
5135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(APIThrowMessage) {
5139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  message_received = false;
5140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
5141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
5142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::V8::AddMessageListener(receive_message);
5143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  templ->Set(v8_str("ThrowFromC"),
5145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             v8::FunctionTemplate::New(isolate, ThrowFromC));
5146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context(0, templ);
5147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CompileRun("ThrowFromC();");
5148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(message_received);
5149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::V8::RemoveMessageListeners(receive_message);
5150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(APIThrowMessageAndVerboseTryCatch) {
5154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  message_received = false;
5155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
5156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
5157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::V8::AddMessageListener(receive_message);
5158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  templ->Set(v8_str("ThrowFromC"),
5160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             v8::FunctionTemplate::New(isolate, ThrowFromC));
5161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context(0, templ);
5162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::TryCatch try_catch;
5163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  try_catch.SetVerbose(true);
5164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Value> result = CompileRun("ThrowFromC();");
5165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(try_catch.HasCaught());
5166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(result.IsEmpty());
5167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(message_received);
5168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::V8::RemoveMessageListeners(receive_message);
5169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
51728b112d2025046f85ef7f6be087c6129c872ebad2Ben MurdochTEST(APIStackOverflowAndVerboseTryCatch) {
51738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  message_received = false;
51748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  LocalContext context;
5175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(context->GetIsolate());
5176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::V8::AddMessageListener(receive_message);
51778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  v8::TryCatch try_catch;
51788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  try_catch.SetVerbose(true);
51798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Local<Value> result = CompileRun("function foo() { foo(); } foo();");
51808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK(try_catch.HasCaught());
51818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK(result.IsEmpty());
51828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK(message_received);
51838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  v8::V8::RemoveMessageListeners(receive_message);
51848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}
51858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
51868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
5187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(ExternalScriptException) {
5188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
5189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
5190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  templ->Set(v8_str("ThrowFromC"),
5192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             v8::FunctionTemplate::New(isolate, ThrowFromC));
5193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context(0, templ);
5194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::TryCatch try_catch;
5196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Value> result = CompileRun("ThrowFromC(); throw 'panama';");
5197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(result.IsEmpty());
5198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(try_catch.HasCaught());
5199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  String::Utf8Value exception_value(try_catch.Exception());
5200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ("konto", *exception_value);
5201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CThrowCountDown(const v8::FunctionCallbackInfo<v8::Value>& args) {
5206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
5207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(4, args.Length());
5208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int count = args[0]->Int32Value();
5209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int cInterval = args[2]->Int32Value();
5210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (count == 0) {
5211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    args.GetIsolate()->ThrowException(v8_str("FromC"));
5212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
5213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
5214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<v8::Object> global =
5215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        args.GetIsolate()->GetCurrentContext()->Global();
5216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Local<Value> fun = global->Get(v8_str("JSThrowCountDown"));
5217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    v8::Handle<Value> argv[] = { v8_num(count - 1),
5218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 args[1],
5219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 args[2],
5220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 args[3] };
5221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (count % cInterval == 0) {
5222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      v8::TryCatch try_catch;
52236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      Local<Value> result = fun.As<Function>()->Call(global, 4, argv);
5224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      int expected = args[3]->Int32Value();
5225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (try_catch.HasCaught()) {
5226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        CHECK_EQ(expected, count);
5227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        CHECK(result.IsEmpty());
5228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        CHECK(!CcTest::i_isolate()->has_scheduled_exception());
5229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
5230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        CHECK_NE(expected, count);
5231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
5232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      args.GetReturnValue().Set(result);
5233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return;
5234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
5235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      args.GetReturnValue().Set(fun.As<Function>()->Call(global, 4, argv));
5236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return;
5237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
5238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
5239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid JSCheck(const v8::FunctionCallbackInfo<v8::Value>& args) {
5243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
5244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(3, args.Length());
5245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool equality = args[0]->BooleanValue();
5246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int count = args[1]->Int32Value();
5247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int expected = args[2]->Int32Value();
5248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (equality) {
5249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(count, expected);
5250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
5251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_NE(count, expected);
5252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
5253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(EvalInTryFinally) {
5257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
5258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(context->GetIsolate());
5259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::TryCatch try_catch;
5260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CompileRun("(function() {"
5261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block             "  try {"
5262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block             "    eval('asldkf (*&^&*^');"
5263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block             "  } finally {"
5264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block             "    return;"
5265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block             "  }"
5266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block             "})()");
5267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(!try_catch.HasCaught());
5268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// This test works by making a stack of alternating JavaScript and C
5272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// activations.  These activations set up exception handlers with regular
5273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// intervals, one interval for C activations and another for JavaScript
5274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// activations.  When enough activations have been created an exception is
5275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// thrown and we check that the right activation catches the exception and that
5276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// no other activations do.  The right activation is always the topmost one with
5277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// a handler, regardless of whether it is in JavaScript or C.
5278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
5279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The notation used to describe a test case looks like this:
5280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
5281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//    *JS[4] *C[3] @JS[2] C[1] JS[0]
5282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
5283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Each entry is an activation, either JS or C.  The index is the count at that
5284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// level.  Stars identify activations with exception handlers, the @ identifies
5285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the exception handler that should catch the exception.
5286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
5287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// BUG(271): Some of the exception propagation does not work on the
5288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ARM simulator because the simulator separates the C++ stack and the
5289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// JS stack.  This test therefore fails on the simulator.  The test is
5290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// not threaded to allow the threading tests to run on the simulator.
5291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(ExceptionOrder) {
5292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
5293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
5294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  templ->Set(v8_str("check"), v8::FunctionTemplate::New(isolate, JSCheck));
5296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  templ->Set(v8_str("CThrowCountDown"),
5297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             v8::FunctionTemplate::New(isolate, CThrowCountDown));
5298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context(0, templ);
5299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CompileRun(
5300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "function JSThrowCountDown(count, jsInterval, cInterval, expected) {"
5301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  if (count == 0) throw 'FromJS';"
5302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  if (count % jsInterval == 0) {"
5303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "    try {"
5304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "      var value = CThrowCountDown(count - 1,"
5305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "                                  jsInterval,"
5306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "                                  cInterval,"
5307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "                                  expected);"
5308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "      check(false, count, expected);"
5309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "      return value;"
5310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "    } catch (e) {"
5311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "      check(true, count, expected);"
5312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "    }"
5313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  } else {"
5314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "    return CThrowCountDown(count - 1, jsInterval, cInterval, expected);"
5315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  }"
5316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "}");
5317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Function> fun =
5318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Local<Function>::Cast(context->Global()->Get(v8_str("JSThrowCountDown")));
5319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int argc = 4;
5321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //                             count      jsInterval cInterval  expected
5322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // *JS[4] *C[3] @JS[2] C[1] JS[0]
5324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> a0[argc] = { v8_num(4), v8_num(2), v8_num(3), v8_num(2) };
5325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  fun->Call(fun, argc, a0);
5326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // JS[5] *C[4] JS[3] @C[2] JS[1] C[0]
5328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> a1[argc] = { v8_num(5), v8_num(6), v8_num(1), v8_num(2) };
5329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  fun->Call(fun, argc, a1);
5330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // JS[6] @C[5] JS[4] C[3] JS[2] C[1] JS[0]
5332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> a2[argc] = { v8_num(6), v8_num(7), v8_num(5), v8_num(5) };
5333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  fun->Call(fun, argc, a2);
5334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // @JS[6] C[5] JS[4] C[3] JS[2] C[1] JS[0]
5336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> a3[argc] = { v8_num(6), v8_num(6), v8_num(7), v8_num(6) };
5337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  fun->Call(fun, argc, a3);
5338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // JS[6] *C[5] @JS[4] C[3] JS[2] C[1] JS[0]
5340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> a4[argc] = { v8_num(6), v8_num(4), v8_num(5), v8_num(4) };
5341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  fun->Call(fun, argc, a4);
5342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // JS[6] C[5] *JS[4] @C[3] JS[2] C[1] JS[0]
5344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> a5[argc] = { v8_num(6), v8_num(4), v8_num(3), v8_num(3) };
5345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  fun->Call(fun, argc, a5);
5346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid ThrowValue(const v8::FunctionCallbackInfo<v8::Value>& args) {
5350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
5351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, args.Length());
5352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  args.GetIsolate()->ThrowException(args[0]);
5353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(ThrowValues) {
5357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
5358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
5359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  templ->Set(v8_str("Throw"), v8::FunctionTemplate::New(isolate, ThrowValue));
5361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context(0, templ);
5362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
5363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "function Run(obj) {"
5364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  try {"
5365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "    Throw(obj);"
5366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  } catch (e) {"
5367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "    return e;"
5368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  }"
5369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  return 'no exception';"
5370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "}"
5371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "[Run('str'), Run(1), Run(0), Run(null), Run(void 0)];"));
5372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(5, result->Length());
5373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(result->Get(v8::Integer::New(isolate, 0))->IsString());
5374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(result->Get(v8::Integer::New(isolate, 1))->IsNumber());
5375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1, result->Get(v8::Integer::New(isolate, 1))->Int32Value());
5376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(result->Get(v8::Integer::New(isolate, 2))->IsNumber());
5377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, result->Get(v8::Integer::New(isolate, 2))->Int32Value());
5378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(result->Get(v8::Integer::New(isolate, 3))->IsNull());
5379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(result->Get(v8::Integer::New(isolate, 4))->IsUndefined());
5380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(CatchZero) {
5384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
5385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(context->GetIsolate());
5386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::TryCatch try_catch;
5387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(!try_catch.HasCaught());
5388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("throw 10");
5389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(try_catch.HasCaught());
5390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(10, try_catch.Exception()->Int32Value());
5391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  try_catch.Reset();
5392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(!try_catch.HasCaught());
5393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("throw 0");
5394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(try_catch.HasCaught());
5395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, try_catch.Exception()->Int32Value());
5396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(CatchExceptionFromWith) {
5400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
5401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(context->GetIsolate());
5402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::TryCatch try_catch;
5403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(!try_catch.HasCaught());
5404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("var o = {}; with (o) { throw 42; }");
5405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(try_catch.HasCaught());
5406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5409e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochTHREADED_TEST(TryCatchAndFinallyHidingException) {
5410e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  LocalContext context;
5411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(context->GetIsolate());
5412e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v8::TryCatch try_catch;
5413e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  CHECK(!try_catch.HasCaught());
5414e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  CompileRun("function f(k) { try { this[k]; } finally { return 0; } };");
5415e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  CompileRun("f({toString: function() { throw 42; }});");
5416e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  CHECK(!try_catch.HasCaught());
5417e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
5418e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
5419e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
5420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid WithTryCatch(const v8::FunctionCallbackInfo<v8::Value>& args) {
5421e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v8::TryCatch try_catch;
5422e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
5423e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
5424e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
5425e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochTHREADED_TEST(TryCatchAndFinally) {
5426e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  LocalContext context;
5427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
5428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
5429e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  context->Global()->Set(
5430e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      v8_str("native_with_try_catch"),
5431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::FunctionTemplate::New(isolate, WithTryCatch)->GetFunction());
5432e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v8::TryCatch try_catch;
5433e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  CHECK(!try_catch.HasCaught());
5434e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  CompileRun(
5435e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      "try {\n"
5436e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      "  throw new Error('a');\n"
5437e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      "} finally {\n"
5438e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      "  native_with_try_catch();\n"
5439e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      "}\n");
5440e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  CHECK(try_catch.HasCaught());
5441e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
5442e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
5443e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
5444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void TryCatchNested1Helper(int depth) {
5445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (depth > 0) {
5446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::TryCatch try_catch;
5447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    try_catch.SetVerbose(true);
5448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    TryCatchNested1Helper(depth - 1);
5449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(try_catch.HasCaught());
5450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    try_catch.ReThrow();
5451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
5452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CcTest::isolate()->ThrowException(v8_str("E1"));
5453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void TryCatchNested2Helper(int depth) {
5458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (depth > 0) {
5459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::TryCatch try_catch;
5460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    try_catch.SetVerbose(true);
5461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    TryCatchNested2Helper(depth - 1);
5462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(try_catch.HasCaught());
5463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    try_catch.ReThrow();
5464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
5465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CompileRun("throw 'E2';");
5466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(TryCatchNested) {
5471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::V8::Initialize();
5472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
5473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(context->GetIsolate());
5474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
5476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Test nested try-catch with a native throw in the end.
5477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::TryCatch try_catch;
5478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    TryCatchNested1Helper(5);
5479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(try_catch.HasCaught());
5480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(0, strcmp(*v8::String::Utf8Value(try_catch.Exception()), "E1"));
5481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
5484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Test nested try-catch with a JavaScript throw in the end.
5485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::TryCatch try_catch;
5486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    TryCatchNested2Helper(5);
5487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(try_catch.HasCaught());
5488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(0, strcmp(*v8::String::Utf8Value(try_catch.Exception()), "E2"));
5489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid TryCatchMixedNestingCheck(v8::TryCatch* try_catch) {
5494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(try_catch->HasCaught());
5495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Message> message = try_catch->Message();
5496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Value> resource = message->GetScriptOrigin().ResourceName();
5497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, strcmp(*v8::String::Utf8Value(resource), "inner"));
5498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, strcmp(*v8::String::Utf8Value(message->Get()),
5499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     "Uncaught Error: a"));
5500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1, message->GetLineNumber());
5501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(6, message->GetStartColumn());
5502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid TryCatchMixedNestingHelper(
5506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::FunctionCallbackInfo<v8::Value>& args) {
5507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ApiTestFuzzer::Fuzz();
5508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::TryCatch try_catch;
5509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRunWithOrigin("throw new Error('a');\n", "inner", 0, 0);
5510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(try_catch.HasCaught());
5511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TryCatchMixedNestingCheck(&try_catch);
5512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  try_catch.ReThrow();
5513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// This test ensures that an outer TryCatch in the following situation:
5517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//   C++/TryCatch -> JS -> C++/TryCatch -> JS w/ SyntaxError
5518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// does not clobber the Message object generated for the inner TryCatch.
5519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// This exercises the ability of TryCatch.ReThrow() to restore the
5520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// inner pending Message before throwing the exception again.
5521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(TryCatchMixedNesting) {
5522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
5523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
5524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::V8::Initialize();
5525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::TryCatch try_catch;
5526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  templ->Set(v8_str("TryCatchMixedNestingHelper"),
5528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             v8::FunctionTemplate::New(isolate, TryCatchMixedNestingHelper));
5529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context(0, templ);
5530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRunWithOrigin("TryCatchMixedNestingHelper();\n", "outer", 1, 1);
5531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TryCatchMixedNestingCheck(&try_catch);
5532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid TryCatchNativeHelper(const v8::FunctionCallbackInfo<v8::Value>& args) {
5536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ApiTestFuzzer::Fuzz();
5537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::TryCatch try_catch;
5538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  args.GetIsolate()->ThrowException(v8_str("boom"));
5539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(try_catch.HasCaught());
5540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(TryCatchNative) {
5544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
5545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
5546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::V8::Initialize();
5547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::TryCatch try_catch;
5548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  templ->Set(v8_str("TryCatchNativeHelper"),
5550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             v8::FunctionTemplate::New(isolate, TryCatchNativeHelper));
5551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context(0, templ);
5552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("TryCatchNativeHelper();");
5553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!try_catch.HasCaught());
5554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid TryCatchNativeResetHelper(
5558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::FunctionCallbackInfo<v8::Value>& args) {
5559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ApiTestFuzzer::Fuzz();
5560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::TryCatch try_catch;
5561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  args.GetIsolate()->ThrowException(v8_str("boom"));
5562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(try_catch.HasCaught());
5563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  try_catch.Reset();
5564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!try_catch.HasCaught());
5565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(TryCatchNativeReset) {
5569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
5570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
5571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::V8::Initialize();
5572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::TryCatch try_catch;
5573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  templ->Set(v8_str("TryCatchNativeResetHelper"),
5575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             v8::FunctionTemplate::New(isolate, TryCatchNativeResetHelper));
5576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context(0, templ);
5577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("TryCatchNativeResetHelper();");
5578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!try_catch.HasCaught());
5579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(Equality) {
5583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
5584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
5585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(context->GetIsolate());
5586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that equality works at all before relying on CHECK_EQ
5587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(v8_str("a")->Equals(v8_str("a")));
5588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(!v8_str("a")->Equals(v8_str("b")));
5589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(v8_str("a"), v8_str("a"));
5591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_NE(v8_str("a"), v8_str("b"));
5592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(v8_num(1), v8_num(1));
5593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(v8_num(1.00), v8_num(1));
5594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_NE(v8_num(1), v8_num(2));
5595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Assume String is not internalized.
5597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(v8_str("a")->StrictEquals(v8_str("a")));
5598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(!v8_str("a")->StrictEquals(v8_str("b")));
5599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(!v8_str("5")->StrictEquals(v8_num(5)));
5600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(v8_num(1)->StrictEquals(v8_num(1)));
5601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(!v8_num(1)->StrictEquals(v8_num(2)));
5602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(v8_num(0.0)->StrictEquals(v8_num(-0.0)));
5603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Value> not_a_number = v8_num(v8::base::OS::nan_value());
5604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(!not_a_number->StrictEquals(not_a_number));
5605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(v8::False(isolate)->StrictEquals(v8::False(isolate)));
5606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!v8::False(isolate)->StrictEquals(v8::Undefined(isolate)));
5607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Object> obj = v8::Object::New(isolate);
5609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Persistent<v8::Object> alias(isolate, obj);
5610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(v8::Local<v8::Object>::New(isolate, alias)->StrictEquals(obj));
5611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  alias.Reset();
5612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(v8_str("a")->SameValue(v8_str("a")));
5614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!v8_str("a")->SameValue(v8_str("b")));
5615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!v8_str("5")->SameValue(v8_num(5)));
5616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(v8_num(1)->SameValue(v8_num(1)));
5617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!v8_num(1)->SameValue(v8_num(2)));
5618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!v8_num(0.0)->SameValue(v8_num(-0.0)));
5619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(not_a_number->SameValue(not_a_number));
5620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(v8::False(isolate)->SameValue(v8::False(isolate)));
5621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!v8::False(isolate)->SameValue(v8::Undefined(isolate)));
5622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(MultiRun) {
5626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
5627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(context->GetIsolate());
5628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Script> script = v8_compile("x");
5629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < 10; i++)
5630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    script->Run();
5631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void GetXValue(Local<String> name,
5635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      const v8::PropertyCallbackInfo<v8::Value>& info) {
5636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
5637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(info.Data(), v8_str("donut"));
5638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(name, v8_str("x"));
5639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(name);
5640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(SimplePropertyRead) {
5644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
5645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
5646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
5647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
5649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context->Global()->Set(v8_str("obj"), templ->NewInstance());
5650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Script> script = v8_compile("obj.x");
5651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < 10; i++) {
5652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Local<Value> result = script->Run();
5653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(result, v8_str("x"));
5654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
5655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
56583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei PopescuTHREADED_TEST(DefinePropertyOnAPIAccessor) {
56593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  LocalContext context;
5660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
5661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
5662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
56643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  context->Global()->Set(v8_str("obj"), templ->NewInstance());
56653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
56663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Uses getOwnPropertyDescriptor to check the configurable status
5667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Script> script_desc = v8_compile(
5668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "var prop = Object.getOwnPropertyDescriptor( "
5669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "obj, 'x');"
5670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "prop.configurable;");
56713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  Local<Value> result = script_desc->Run();
56723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  CHECK_EQ(result->BooleanValue(), true);
56733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
56743100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Redefine get - but still configurable
5675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Script> script_define = v8_compile(
5676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "var desc = { get: function(){return 42; },"
5677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "            configurable: true };"
5678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "Object.defineProperty(obj, 'x', desc);"
5679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "obj.x");
56803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  result = script_define->Run();
56813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  CHECK_EQ(result, v8_num(42));
56823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
56833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Check that the accessor is still configurable
56843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  result = script_desc->Run();
56853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  CHECK_EQ(result->BooleanValue(), true);
56863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
56873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Redefine to a non-configurable
5688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  script_define = v8_compile(
5689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "var desc = { get: function(){return 43; },"
5690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "             configurable: false };"
5691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "Object.defineProperty(obj, 'x', desc);"
5692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "obj.x");
56933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  result = script_define->Run();
56943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  CHECK_EQ(result, v8_num(43));
56953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  result = script_desc->Run();
56963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  CHECK_EQ(result->BooleanValue(), false);
56973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
56983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Make sure that it is not possible to redefine again
56993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  v8::TryCatch try_catch;
57003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  result = script_define->Run();
57013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  CHECK(try_catch.HasCaught());
5702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  String::Utf8Value exception_value(try_catch.Exception());
57033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
57043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
57053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
5706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
57073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei PopescuTHREADED_TEST(DefinePropertyOnDefineGetterSetter) {
5708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
5709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
5710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
57113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
57123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  LocalContext context;
57133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  context->Global()->Set(v8_str("obj"), templ->NewInstance());
57143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
5715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Script> script_desc = v8_compile(
5716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "var prop ="
5717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "Object.getOwnPropertyDescriptor( "
5718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "obj, 'x');"
5719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "prop.configurable;");
57203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  Local<Value> result = script_desc->Run();
57213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  CHECK_EQ(result->BooleanValue(), true);
57223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
5723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Script> script_define = v8_compile(
5724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "var desc = {get: function(){return 42; },"
5725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "            configurable: true };"
5726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "Object.defineProperty(obj, 'x', desc);"
5727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "obj.x");
57283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  result = script_define->Run();
57293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  CHECK_EQ(result, v8_num(42));
57303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
57313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
57323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  result = script_desc->Run();
57333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  CHECK_EQ(result->BooleanValue(), true);
57343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
57353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
5736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  script_define = v8_compile(
5737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "var desc = {get: function(){return 43; },"
5738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "            configurable: false };"
5739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "Object.defineProperty(obj, 'x', desc);"
5740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "obj.x");
57413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  result = script_define->Run();
57423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  CHECK_EQ(result, v8_num(43));
57433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  result = script_desc->Run();
57443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
57453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  CHECK_EQ(result->BooleanValue(), false);
57463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
57473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  v8::TryCatch try_catch;
57483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  result = script_define->Run();
57493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  CHECK(try_catch.HasCaught());
5750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  String::Utf8Value exception_value(try_catch.Exception());
57513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
57523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
57533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
57543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
5755f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkestatic v8::Handle<v8::Object> GetGlobalProperty(LocalContext* context,
5756f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                                                char const* name) {
5757f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  return v8::Handle<v8::Object>::Cast((*context)->Global()->Get(v8_str(name)));
5758f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
5759f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
5760f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
5761f7060e27768c550ace7ec48ad8c093466db52dfaLeon ClarkeTHREADED_TEST(DefineAPIAccessorOnObject) {
5762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
5763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
5764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5765f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  LocalContext context;
5766f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
5767f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  context->Global()->Set(v8_str("obj1"), templ->NewInstance());
5768f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CompileRun("var obj2 = {};");
5769f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
5770f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CHECK(CompileRun("obj1.x")->IsUndefined());
5771f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CHECK(CompileRun("obj2.x")->IsUndefined());
5772f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
5773f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CHECK(GetGlobalProperty(&context, "obj1")->
5774f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5775f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
5776f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ExpectString("obj1.x", "x");
5777f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CHECK(CompileRun("obj2.x")->IsUndefined());
5778f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
5779f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CHECK(GetGlobalProperty(&context, "obj2")->
5780f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5781f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
5782f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ExpectString("obj1.x", "x");
5783f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ExpectString("obj2.x", "x");
5784f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
5785f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5786f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5787f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
5788f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CompileRun("Object.defineProperty(obj1, 'x',"
5789f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke             "{ get: function() { return 'y'; }, configurable: true })");
5790f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
5791f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ExpectString("obj1.x", "y");
5792f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ExpectString("obj2.x", "x");
5793f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
5794f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CompileRun("Object.defineProperty(obj2, 'x',"
5795f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke             "{ get: function() { return 'y'; }, configurable: true })");
5796f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
5797f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ExpectString("obj1.x", "y");
5798f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ExpectString("obj2.x", "y");
5799f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
5800f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5801f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5802f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
5803f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CHECK(GetGlobalProperty(&context, "obj1")->
5804f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5805f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CHECK(GetGlobalProperty(&context, "obj2")->
5806f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5807f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
5808f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ExpectString("obj1.x", "x");
5809f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ExpectString("obj2.x", "x");
5810f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
5811f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5812f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5813f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
5814f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Define getters/setters, but now make them not configurable.
5815f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CompileRun("Object.defineProperty(obj1, 'x',"
5816f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke             "{ get: function() { return 'z'; }, configurable: false })");
5817f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CompileRun("Object.defineProperty(obj2, 'x',"
5818f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke             "{ get: function() { return 'z'; }, configurable: false })");
5819f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
5820f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5821f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5822f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
5823f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ExpectString("obj1.x", "z");
5824f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ExpectString("obj2.x", "z");
5825f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
5826f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CHECK(!GetGlobalProperty(&context, "obj1")->
5827f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5828f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CHECK(!GetGlobalProperty(&context, "obj2")->
5829f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5830f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
5831f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ExpectString("obj1.x", "z");
5832f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ExpectString("obj2.x", "z");
5833f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
5834f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
5835f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
5836f7060e27768c550ace7ec48ad8c093466db52dfaLeon ClarkeTHREADED_TEST(DontDeleteAPIAccessorsCannotBeOverriden) {
5837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
5838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
5839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5840f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  LocalContext context;
5841f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
5842f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  context->Global()->Set(v8_str("obj1"), templ->NewInstance());
5843f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CompileRun("var obj2 = {};");
5844f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
5845f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CHECK(GetGlobalProperty(&context, "obj1")->SetAccessor(
5846f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        v8_str("x"),
5847f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        GetXValue, NULL,
5848f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        v8_str("donut"), v8::DEFAULT, v8::DontDelete));
5849f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CHECK(GetGlobalProperty(&context, "obj2")->SetAccessor(
5850f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        v8_str("x"),
5851f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        GetXValue, NULL,
5852f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        v8_str("donut"), v8::DEFAULT, v8::DontDelete));
5853f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
5854f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ExpectString("obj1.x", "x");
5855f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ExpectString("obj2.x", "x");
5856f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
5857f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5858f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5859f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
5860f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CHECK(!GetGlobalProperty(&context, "obj1")->
5861f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5862f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CHECK(!GetGlobalProperty(&context, "obj2")->
5863f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5864f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
5865f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  {
5866f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    v8::TryCatch try_catch;
5867f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    CompileRun("Object.defineProperty(obj1, 'x',"
5868f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        "{get: function() { return 'func'; }})");
5869f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    CHECK(try_catch.HasCaught());
5870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    String::Utf8Value exception_value(try_catch.Exception());
58713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
5872f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
5873f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  {
5874f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    v8::TryCatch try_catch;
5875f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    CompileRun("Object.defineProperty(obj2, 'x',"
5876f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        "{get: function() { return 'func'; }})");
5877f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    CHECK(try_catch.HasCaught());
5878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    String::Utf8Value exception_value(try_catch.Exception());
58793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
5880f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
5881f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
5882f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
5883f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
5884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void Get239Value(Local<String> name,
5885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        const v8::PropertyCallbackInfo<v8::Value>& info) {
5886f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ApiTestFuzzer::Fuzz();
5887f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CHECK_EQ(info.Data(), v8_str("donut"));
5888f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CHECK_EQ(name, v8_str("239"));
5889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(name);
5890f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
5891f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
5892f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
5893f7060e27768c550ace7ec48ad8c093466db52dfaLeon ClarkeTHREADED_TEST(ElementAPIAccessor) {
5894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
5895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
5896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5897f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  LocalContext context;
58983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
5899f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  context->Global()->Set(v8_str("obj1"), templ->NewInstance());
5900f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CompileRun("var obj2 = {};");
5901f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
5902f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CHECK(GetGlobalProperty(&context, "obj1")->SetAccessor(
5903f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        v8_str("239"),
5904f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        Get239Value, NULL,
5905f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        v8_str("donut")));
5906f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CHECK(GetGlobalProperty(&context, "obj2")->SetAccessor(
5907f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        v8_str("239"),
5908f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        Get239Value, NULL,
5909f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        v8_str("donut")));
5910f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
5911f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ExpectString("obj1[239]", "239");
5912f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ExpectString("obj2[239]", "239");
5913f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ExpectString("obj1['239']", "239");
5914f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ExpectString("obj2['239']", "239");
5915f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
59163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
5917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockv8::Persistent<Value> xValue;
5919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void SetXValue(Local<String> name,
5922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Local<Value> value,
5923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      const v8::PropertyCallbackInfo<void>& info) {
5924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(value, v8_num(4));
5925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(info.Data(), v8_str("donut"));
5926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(name, v8_str("x"));
5927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(xValue.IsEmpty());
5928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  xValue.Reset(info.GetIsolate(), value);
5929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(SimplePropertyWrite) {
5933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
5934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
5935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  templ->SetAccessor(v8_str("x"), GetXValue, SetXValue, v8_str("donut"));
5937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
5938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context->Global()->Set(v8_str("obj"), templ->NewInstance());
5939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Script> script = v8_compile("obj.x = 4");
5940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < 10; i++) {
5941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(xValue.IsEmpty());
5942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    script->Run();
5943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(v8_num(4), Local<Value>::New(CcTest::isolate(), xValue));
5944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    xValue.Reset();
5945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(SetterOnly) {
5950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
5951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
5952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  templ->SetAccessor(v8_str("x"), NULL, SetXValue, v8_str("donut"));
5954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
5955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context->Global()->Set(v8_str("obj"), templ->NewInstance());
5956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Script> script = v8_compile("obj.x = 4; obj.x");
5957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < 10; i++) {
5958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK(xValue.IsEmpty());
5959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    script->Run();
5960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(v8_num(4), Local<Value>::New(CcTest::isolate(), xValue));
5961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    xValue.Reset();
5962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(NoAccessors) {
5967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
5968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
5969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  templ->SetAccessor(v8_str("x"),
5971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     static_cast<v8::AccessorGetterCallback>(NULL),
5972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     NULL,
5973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     v8_str("donut"));
5974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
5975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context->Global()->Set(v8_str("obj"), templ->NewInstance());
5976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Script> script = v8_compile("obj.x = 4; obj.x");
5977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < 10; i++) {
5978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    script->Run();
5979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
5980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void XPropertyGetter(Local<String> property,
5984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            const v8::PropertyCallbackInfo<v8::Value>& info) {
5985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
5986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(info.Data()->IsUndefined());
5987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(property);
5988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(NamedInterceptorPropertyRead) {
5992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
5993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
5994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  templ->SetNamedPropertyHandler(XPropertyGetter);
5996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
5997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context->Global()->Set(v8_str("obj"), templ->NewInstance());
5998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Script> script = v8_compile("obj.x");
5999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < 10; i++) {
6000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Local<Value> result = script->Run();
6001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(result, v8_str("x"));
6002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
6003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
6004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
60066ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockTHREADED_TEST(NamedInterceptorDictionaryIC) {
6007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
6008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
6009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
60106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  templ->SetNamedPropertyHandler(XPropertyGetter);
60116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  LocalContext context;
60126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Create an object with a named interceptor.
60136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  context->Global()->Set(v8_str("interceptor_obj"), templ->NewInstance());
6014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Script> script = v8_compile("interceptor_obj.x");
60156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (int i = 0; i < 10; i++) {
60166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Local<Value> result = script->Run();
60176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    CHECK_EQ(result, v8_str("x"));
60186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
60196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Create a slow case object and a function accessing a property in
60206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // that slow case object (with dictionary probing in generated
60216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // code). Then force object with a named interceptor into slow-case,
60226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // pass it to the function, and check that the interceptor is called
60236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // instead of accessing the local property.
60246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Local<Value> result =
60256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      CompileRun("function get_x(o) { return o.x; };"
60266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                 "var obj = { x : 42, y : 0 };"
60276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                 "delete obj.y;"
60286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                 "for (var i = 0; i < 10; i++) get_x(obj);"
60296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                 "interceptor_obj.x = 42;"
60306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                 "interceptor_obj.y = 10;"
60316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                 "delete interceptor_obj.y;"
60326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                 "get_x(interceptor_obj)");
60336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(result, v8_str("x"));
60346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
60356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
60366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
60370d5e116f6aee03185f237311a943491bb079a768Kristian MonsenTHREADED_TEST(NamedInterceptorDictionaryICMultipleContext) {
6038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
6039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
6040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<Context> context1 = Context::New(isolate);
60410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
60420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context1->Enter();
6043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
60440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  templ->SetNamedPropertyHandler(XPropertyGetter);
60450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Create an object with a named interceptor.
60460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  v8::Local<v8::Object> object = templ->NewInstance();
60470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context1->Global()->Set(v8_str("interceptor_obj"), object);
60480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
60490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Force the object into the slow case.
60500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  CompileRun("interceptor_obj.y = 0;"
60510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen             "delete interceptor_obj.y;");
60520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context1->Exit();
60530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
60540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  {
60550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    // Introduce the object into a different context.
60560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    // Repeat named loads to exercise ICs.
60570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    LocalContext context2;
60580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context2->Global()->Set(v8_str("interceptor_obj"), object);
60590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Local<Value> result =
60600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      CompileRun("function get_x(o) { return o.x; }"
60610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                 "interceptor_obj.x = 42;"
60620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                 "for (var i=0; i != 10; i++) {"
60630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                 "  get_x(interceptor_obj);"
60640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                 "}"
60650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                 "get_x(interceptor_obj)");
60660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    // Check that the interceptor was actually invoked.
60670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    CHECK_EQ(result, v8_str("x"));
60680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  }
60690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
60700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Return to the original context and force some object to the slow case
60710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // to cause the NormalizedMapCache to verify.
60720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context1->Enter();
60730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  CompileRun("var obj = { x : 0 }; delete obj.x;");
60740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context1->Exit();
60750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
60760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
60770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void SetXOnPrototypeGetter(
6079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<String> property,
6080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Value>& info) {
6081402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Set x on the prototype object and do not handle the get request.
6082402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  v8::Handle<v8::Value> proto = info.Holder()->GetPrototype();
6083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  proto.As<v8::Object>()->Set(v8_str("x"),
6084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              v8::Integer::New(info.GetIsolate(), 23));
6085402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
6086402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
6087402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
6088402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// This is a regression test for http://crbug.com/20104. Map
6089402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// transitions should not interfere with post interceptor lookup.
6090402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei PopescuTHREADED_TEST(NamedInterceptorMapTransitionRead) {
6091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
6092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
6093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::FunctionTemplate> function_template =
6094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::FunctionTemplate::New(isolate);
6095402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Local<v8::ObjectTemplate> instance_template
6096402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      = function_template->InstanceTemplate();
6097402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  instance_template->SetNamedPropertyHandler(SetXOnPrototypeGetter);
6098402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  LocalContext context;
6099402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  context->Global()->Set(v8_str("F"), function_template->GetFunction());
6100402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Create an instance of F and introduce a map transition for x.
6101402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CompileRun("var o = new F(); o.x = 23;");
6102402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Create an instance of F and invoke the getter. The result should be 23.
6103402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Local<Value> result = CompileRun("o = new F(); o.x");
6104402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK_EQ(result->Int32Value(), 23);
6105402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
6106402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
6107402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
6108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void IndexedPropertyGetter(
6109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t index,
6110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Value>& info) {
6111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
6112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (index == 37) {
6113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    info.GetReturnValue().Set(v8_num(625));
6114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
6115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
6116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void IndexedPropertySetter(
6119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t index,
6120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<Value> value,
6121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Value>& info) {
6122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
6123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (index == 39) {
6124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    info.GetReturnValue().Set(value);
6125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
6126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
6127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(IndexedInterceptorWithIndexedAccessor) {
6130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
6131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
6132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  templ->SetIndexedPropertyHandler(IndexedPropertyGetter,
6134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   IndexedPropertySetter);
6135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
6136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context->Global()->Set(v8_str("obj"), templ->NewInstance());
6137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Script> getter_script = v8_compile(
6138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "obj.__defineGetter__(\"3\", function(){return 5;});obj[3];");
6139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Script> setter_script = v8_compile(
6140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "obj.__defineSetter__(\"17\", function(val){this.foo = val;});"
6141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "obj[17] = 23;"
6142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "obj.foo;");
6143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Script> interceptor_setter_script = v8_compile(
6144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "obj.__defineSetter__(\"39\", function(val){this.foo = \"hit\";});"
6145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "obj[39] = 47;"
6146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "obj.foo;");  // This setter should not run, due to the interceptor.
6147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Script> interceptor_getter_script = v8_compile(
6148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "obj[37];");
6149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Value> result = getter_script->Run();
6150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(v8_num(5), result);
6151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  result = setter_script->Run();
6152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(v8_num(23), result);
6153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  result = interceptor_setter_script->Run();
6154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(v8_num(23), result);
6155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  result = interceptor_getter_script->Run();
6156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(v8_num(625), result);
6157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
6158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void UnboxedDoubleIndexedPropertyGetter(
616169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    uint32_t index,
6162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Value>& info) {
616369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  ApiTestFuzzer::Fuzz();
616469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  if (index < 25) {
6165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    info.GetReturnValue().Set(v8_num(index));
616669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
616769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch}
616869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
616969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
6170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void UnboxedDoubleIndexedPropertySetter(
617169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    uint32_t index,
617269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    Local<Value> value,
6173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Value>& info) {
617469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  ApiTestFuzzer::Fuzz();
617569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  if (index < 25) {
6176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    info.GetReturnValue().Set(v8_num(index));
617769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
617869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch}
617969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
618069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
6181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid UnboxedDoubleIndexedPropertyEnumerator(
6182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Array>& info) {
618369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Force the list of returned keys to be stored in a FastDoubleArray.
6184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Script> indexed_property_names_script = v8_compile(
618569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      "keys = new Array(); keys[125000] = 1;"
618669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      "for(i = 0; i < 80000; i++) { keys[i] = i; };"
6187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "keys.length = 25; keys;");
618869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Local<Value> result = indexed_property_names_script->Run();
6189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(Local<v8::Array>::Cast(result));
619069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch}
619169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
619269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
619369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// Make sure that the the interceptor code in the runtime properly handles
619469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// merging property name lists for double-array-backed arrays.
619569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen MurdochTHREADED_TEST(IndexedInterceptorUnboxedDoubleWithIndexedAccessor) {
6196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
6197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
6198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
619969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  templ->SetIndexedPropertyHandler(UnboxedDoubleIndexedPropertyGetter,
620069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                   UnboxedDoubleIndexedPropertySetter,
620169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                   0,
620269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                   0,
620369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                   UnboxedDoubleIndexedPropertyEnumerator);
620469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  LocalContext context;
620569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  context->Global()->Set(v8_str("obj"), templ->NewInstance());
620669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // When obj is created, force it to be Stored in a FastDoubleArray.
6207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Script> create_unboxed_double_script = v8_compile(
620869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      "obj[125000] = 1; for(i = 0; i < 80000; i+=2) { obj[i] = i; } "
620969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      "key_count = 0; "
621069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      "for (x in obj) {key_count++;};"
6211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "obj;");
621269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Local<Value> result = create_unboxed_double_script->Run();
621369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK(result->ToObject()->HasRealIndexedProperty(2000));
6214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Script> key_count_check = v8_compile("key_count;");
621569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  result = key_count_check->Run();
621669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK_EQ(v8_num(40013), result);
621769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch}
621869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
621969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
6220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid SloppyArgsIndexedPropertyEnumerator(
6221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Array>& info) {
622269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Force the list of returned keys to be stored in a Arguments object.
6223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Script> indexed_property_names_script = v8_compile(
622469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      "function f(w,x) {"
622569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      " return arguments;"
622669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      "}"
622769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      "keys = f(0, 1, 2, 3);"
6228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "keys;");
6229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Object> result =
6230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Local<Object>::Cast(indexed_property_names_script->Run());
6231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Have to populate the handle manually, as it's not Cast-able.
6232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::Handle<i::JSObject> o =
6233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Utils::OpenHandle<Object, i::JSObject>(result);
6234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::Handle<i::JSArray> array(reinterpret_cast<i::JSArray*>(*o));
6235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(v8::Utils::ToLocal(array));
623669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch}
623769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
623869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
6239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void SloppyIndexedPropertyGetter(
624069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    uint32_t index,
6241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Value>& info) {
624269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  ApiTestFuzzer::Fuzz();
624369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  if (index < 4) {
6244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    info.GetReturnValue().Set(v8_num(index));
624569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
624669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch}
624769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
624869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
624969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// Make sure that the the interceptor code in the runtime properly handles
625069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// merging property name lists for non-string arguments arrays.
6251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(IndexedInterceptorSloppyArgsWithIndexedAccessor) {
6252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
6253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
6254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  templ->SetIndexedPropertyHandler(SloppyIndexedPropertyGetter,
625669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                   0,
625769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                   0,
625869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                   0,
6259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   SloppyArgsIndexedPropertyEnumerator);
626069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  LocalContext context;
626169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  context->Global()->Set(v8_str("obj"), templ->NewInstance());
6262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Script> create_args_script = v8_compile(
6263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "var key_count = 0;"
6264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "for (x in obj) {key_count++;} key_count;");
626569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Local<Value> result = create_args_script->Run();
626669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK_EQ(v8_num(4), result);
626769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch}
626869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
626969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
6270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void IdentityIndexedPropertyGetter(
6271d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    uint32_t index,
6272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Value>& info) {
6273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(index);
6274d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
6275d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
6276d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
62770d5e116f6aee03185f237311a943491bb079a768Kristian MonsenTHREADED_TEST(IndexedInterceptorWithGetOwnPropertyDescriptor) {
6278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
6279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
6280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
62810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
62820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
62830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  LocalContext context;
62840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context->Global()->Set(v8_str("obj"), templ->NewInstance());
62850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
62860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Check fast object case.
62870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  const char* fast_case_code =
62880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "Object.getOwnPropertyDescriptor(obj, 0).value.toString()";
62890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ExpectString(fast_case_code, "0");
62900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
62910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Check slow case.
62920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  const char* slow_case_code =
62930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "obj.x = 1; delete obj.x;"
62940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "Object.getOwnPropertyDescriptor(obj, 1).value.toString()";
62950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ExpectString(slow_case_code, "1");
62960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
62970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
62980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6299d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeTHREADED_TEST(IndexedInterceptorWithNoSetter) {
6300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
6301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
6302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6303d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
6304d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
6305d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  LocalContext context;
6306d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  context->Global()->Set(v8_str("obj"), templ->NewInstance());
6307d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
6308d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  const char* code =
6309d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      "try {"
6310d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      "  obj[0] = 239;"
6311d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      "  for (var i = 0; i < 100; i++) {"
6312d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      "    var v = obj[0];"
6313d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      "    if (v != 0) throw 'Wrong value ' + v + ' at iteration ' + i;"
6314d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      "  }"
6315d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      "  'PASSED'"
6316d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      "} catch(e) {"
6317d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      "  e"
6318d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      "}";
6319d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  ExpectString(code, "PASSED");
6320d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
6321d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
6322d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
6323402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei PopescuTHREADED_TEST(IndexedInterceptorWithAccessorCheck) {
6324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
6325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
6326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6327402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
6328402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
6329402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  LocalContext context;
6330402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Local<v8::Object> obj = templ->NewInstance();
6331402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  obj->TurnOnAccessCheck();
6332402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  context->Global()->Set(v8_str("obj"), obj);
6333402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
6334402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  const char* code =
6335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "var result = 'PASSED';"
6336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "for (var i = 0; i < 100; i++) {"
6337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  try {"
6338402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "    var v = obj[0];"
6339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "    result = 'Wrong value ' + v + ' at iteration ' + i;"
6340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "    break;"
6341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  } catch (e) {"
6342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "    /* pass */"
6343402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "  }"
6344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "}"
6345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "result";
6346402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  ExpectString(code, "PASSED");
6347402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
6348402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
6349402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
6350402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei PopescuTHREADED_TEST(IndexedInterceptorWithAccessorCheckSwitchedOn) {
6351402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  i::FLAG_allow_natives_syntax = true;
6352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
6353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
6354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6355402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
6356402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
6357402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  LocalContext context;
6358402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Local<v8::Object> obj = templ->NewInstance();
6359402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  context->Global()->Set(v8_str("obj"), obj);
6360402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
6361402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  const char* code =
6362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "var result = 'PASSED';"
6363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "for (var i = 0; i < 100; i++) {"
6364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  var expected = i;"
6365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  if (i == 5) {"
6366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "    %EnableAccessChecks(obj);"
6367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  }"
6368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  try {"
6369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "    var v = obj[i];"
6370402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "    if (i == 5) {"
6371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "      result = 'Should not have reached this!';"
6372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "      break;"
6373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "    } else if (v != expected) {"
6374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "      result = 'Wrong value ' + v + ' at iteration ' + i;"
6375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "      break;"
6376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "    }"
6377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  } catch (e) {"
6378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "    if (i != 5) {"
6379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "      result = e;"
6380402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "    }"
6381402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "  }"
6382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  if (i == 5) %DisableAccessChecks(obj);"
6383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "}"
6384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "result";
6385402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  ExpectString(code, "PASSED");
6386402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
6387402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
6388402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
6389402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei PopescuTHREADED_TEST(IndexedInterceptorWithDifferentIndices) {
6390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
6391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
6392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6393402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
6394402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
6395402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  LocalContext context;
6396402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Local<v8::Object> obj = templ->NewInstance();
6397402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  context->Global()->Set(v8_str("obj"), obj);
6398402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
6399402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  const char* code =
6400402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "try {"
6401402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "  for (var i = 0; i < 100; i++) {"
6402402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "    var v = obj[i];"
6403402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "    if (v != i) throw 'Wrong value ' + v + ' at iteration ' + i;"
6404402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "  }"
6405402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "  'PASSED'"
6406402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "} catch(e) {"
6407402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "  e"
6408402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "}";
6409402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  ExpectString(code, "PASSED");
6410402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
6411402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
6412402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
6413f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochTHREADED_TEST(IndexedInterceptorWithNegativeIndices) {
6414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
6415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
6416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6417f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
6418f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
6419f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  LocalContext context;
6420f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  Local<v8::Object> obj = templ->NewInstance();
6421f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  context->Global()->Set(v8_str("obj"), obj);
6422f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
6423f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  const char* code =
6424f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      "try {"
6425f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      "  for (var i = 0; i < 100; i++) {"
6426f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      "    var expected = i;"
6427f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      "    var key = i;"
6428f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      "    if (i == 25) {"
6429f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      "       key = -1;"
6430f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      "       expected = undefined;"
6431f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      "    }"
6432f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      "    if (i == 50) {"
6433f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      "       /* probe minimal Smi number on 32-bit platforms */"
6434f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      "       key = -(1 << 30);"
6435f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      "       expected = undefined;"
6436f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      "    }"
6437f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      "    if (i == 75) {"
6438f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      "       /* probe minimal Smi number on 64-bit platforms */"
6439f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      "       key = 1 << 31;"
6440f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      "       expected = undefined;"
6441f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      "    }"
6442f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      "    var v = obj[key];"
6443f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      "    if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
6444f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      "  }"
6445f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      "  'PASSED'"
6446f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      "} catch(e) {"
6447f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      "  e"
6448f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      "}";
6449f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  ExpectString(code, "PASSED");
6450f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch}
6451f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
6452f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
6453402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei PopescuTHREADED_TEST(IndexedInterceptorWithNotSmiLookup) {
6454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
6455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
6456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6457402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
6458402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
6459402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  LocalContext context;
6460402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Local<v8::Object> obj = templ->NewInstance();
6461402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  context->Global()->Set(v8_str("obj"), obj);
6462402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
6463402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  const char* code =
6464402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "try {"
6465402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "  for (var i = 0; i < 100; i++) {"
6466402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "    var expected = i;"
6467f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      "    var key = i;"
6468402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "    if (i == 50) {"
6469f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      "       key = 'foobar';"
6470402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "       expected = undefined;"
6471402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "    }"
6472f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      "    var v = obj[key];"
6473402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "    if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
6474402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "  }"
6475402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "  'PASSED'"
6476402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "} catch(e) {"
6477402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "  e"
6478402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "}";
6479402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  ExpectString(code, "PASSED");
6480402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
6481402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
6482402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
6483402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei PopescuTHREADED_TEST(IndexedInterceptorGoingMegamorphic) {
6484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
6485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
6486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6487402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
6488402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
6489402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  LocalContext context;
6490402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Local<v8::Object> obj = templ->NewInstance();
6491402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  context->Global()->Set(v8_str("obj"), obj);
6492402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
6493402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  const char* code =
6494402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "var original = obj;"
6495402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "try {"
6496402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "  for (var i = 0; i < 100; i++) {"
6497402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "    var expected = i;"
6498402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "    if (i == 50) {"
6499402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "       obj = {50: 'foobar'};"
6500402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "       expected = 'foobar';"
6501402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "    }"
6502402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "    var v = obj[i];"
6503402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "    if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
6504402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "    if (i == 50) obj = original;"
6505402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "  }"
6506402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "  'PASSED'"
6507402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "} catch(e) {"
6508402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "  e"
6509402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "}";
6510402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  ExpectString(code, "PASSED");
6511402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
6512402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
6513402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
6514402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei PopescuTHREADED_TEST(IndexedInterceptorReceiverTurningSmi) {
6515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
6516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
6517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6518402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
6519402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
6520402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  LocalContext context;
6521402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Local<v8::Object> obj = templ->NewInstance();
6522402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  context->Global()->Set(v8_str("obj"), obj);
6523402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
6524402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  const char* code =
6525402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "var original = obj;"
6526402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "try {"
6527402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "  for (var i = 0; i < 100; i++) {"
6528402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "    var expected = i;"
6529402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "    if (i == 5) {"
6530402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "       obj = 239;"
6531402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "       expected = undefined;"
6532402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "    }"
6533402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "    var v = obj[i];"
6534402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "    if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
6535402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "    if (i == 5) obj = original;"
6536402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "  }"
6537402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "  'PASSED'"
6538402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "} catch(e) {"
6539402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "  e"
6540402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "}";
6541402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  ExpectString(code, "PASSED");
6542402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
6543402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
6544402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
6545402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei PopescuTHREADED_TEST(IndexedInterceptorOnProto) {
6546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
6547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
6548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6549402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
6550402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
6551402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  LocalContext context;
6552402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Local<v8::Object> obj = templ->NewInstance();
6553402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  context->Global()->Set(v8_str("obj"), obj);
6554402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
6555402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  const char* code =
6556402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "var o = {__proto__: obj};"
6557402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "try {"
6558402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "  for (var i = 0; i < 100; i++) {"
6559402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "    var v = o[i];"
6560402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "    if (v != i) throw 'Wrong value ' + v + ' at iteration ' + i;"
6561402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "  }"
6562402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "  'PASSED'"
6563402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "} catch(e) {"
6564402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "  e"
6565402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "}";
6566402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  ExpectString(code, "PASSED");
6567402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
6568402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
6569402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
6570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(MultiContexts) {
6571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
6572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
6573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  templ->Set(v8_str("dummy"), v8::FunctionTemplate::New(isolate,
6575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                        DummyCallHandler));
6576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<String> password = v8_str("Password");
6578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create an environment
6580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context0(0, templ);
6581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context0->SetSecurityToken(password);
6582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Object> global0 = context0->Global();
6583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  global0->Set(v8_str("custom"), v8_num(1234));
6584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1234, global0->Get(v8_str("custom"))->Int32Value());
6585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create an independent environment
6587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context1(0, templ);
6588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context1->SetSecurityToken(password);
6589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Object> global1 = context1->Global();
6590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  global1->Set(v8_str("custom"), v8_num(1234));
6591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_NE(global0, global1);
6592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1234, global0->Get(v8_str("custom"))->Int32Value());
6593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1234, global1->Get(v8_str("custom"))->Int32Value());
6594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Now create a new context with the old global
6596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context2(0, templ, global1);
6597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context2->SetSecurityToken(password);
6598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Object> global2 = context2->Global();
6599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(global1, global2);
6600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, global1->Get(v8_str("custom"))->Int32Value());
6601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, global2->Get(v8_str("custom"))->Int32Value());
6602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
6603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(FunctionPrototypeAcrossContexts) {
6606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make sure that functions created by cloning boilerplates cannot
6607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // communicate through their __proto__ field.
6608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(CcTest::isolate());
6610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext env0;
6612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Object> global0 =
6613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      env0->Global();
6614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Object> object0 =
66156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      global0->Get(v8_str("Object")).As<v8::Object>();
6616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Object> tostring0 =
66176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      object0->Get(v8_str("toString")).As<v8::Object>();
6618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Object> proto0 =
66196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      tostring0->Get(v8_str("__proto__")).As<v8::Object>();
6620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  proto0->Set(v8_str("custom"), v8_num(1234));
6621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext env1;
6623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Object> global1 =
6624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      env1->Global();
6625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Object> object1 =
66266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      global1->Get(v8_str("Object")).As<v8::Object>();
6627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Object> tostring1 =
66286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      object1->Get(v8_str("toString")).As<v8::Object>();
6629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Object> proto1 =
66306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      tostring1->Get(v8_str("__proto__")).As<v8::Object>();
6631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(!proto1->Has(v8_str("custom")));
6632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
6633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(Regress892105) {
6636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make sure that object and array literals created by cloning
6637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // boilerplates cannot communicate through their __proto__
6638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // field. This is rather difficult to check, but we try to add stuff
6639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // to Object.prototype and Array.prototype and create a new
6640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // environment. This should succeed.
6641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(CcTest::isolate());
6643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<String> source = v8_str("Object.prototype.obj = 1234;"
6645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                "Array.prototype.arr = 4567;"
6646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                "8901");
6647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext env0;
6649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Script> script0 = v8_compile(source);
6650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(8901.0, script0->Run()->NumberValue());
6651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext env1;
6653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Script> script1 = v8_compile(source);
6654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(8901.0, script1->Run()->NumberValue());
6655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
6656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(UndetectableObject) {
6659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext env;
6660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
6661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<v8::FunctionTemplate> desc =
6663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::FunctionTemplate::New(env->GetIsolate());
6664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
6665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<v8::Object> obj = desc->GetFunction()->NewInstance();
6667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env->Global()->Set(v8_str("undetectable"), obj);
6668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectString("undetectable.toString()", "[object Object]");
6670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectString("typeof undetectable", "undefined");
6671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectString("typeof(undetectable)", "undefined");
6672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectBoolean("typeof undetectable == 'undefined'", true);
6673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectBoolean("typeof undetectable == 'object'", false);
6674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectBoolean("if (undetectable) { true; } else { false; }", false);
6675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectBoolean("!undetectable", true);
6676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectObject("true&&undetectable", obj);
6678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectBoolean("false&&undetectable", false);
6679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectBoolean("true||undetectable", true);
6680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectObject("false||undetectable", obj);
6681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectObject("undetectable&&true", obj);
6683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectObject("undetectable&&false", obj);
6684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectBoolean("undetectable||true", true);
6685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectBoolean("undetectable||false", false);
6686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectBoolean("undetectable==null", true);
6688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectBoolean("null==undetectable", true);
6689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectBoolean("undetectable==undefined", true);
6690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectBoolean("undefined==undetectable", true);
6691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectBoolean("undetectable==undetectable", true);
6692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectBoolean("undetectable===null", false);
6695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectBoolean("null===undetectable", false);
6696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectBoolean("undetectable===undefined", false);
6697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectBoolean("undefined===undetectable", false);
6698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectBoolean("undetectable===undetectable", true);
6699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
6700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
67023fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochTHREADED_TEST(VoidLiteral) {
67033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  LocalContext env;
6704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
6705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
67063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
6707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
67083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
67093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
67103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Local<v8::Object> obj = desc->GetFunction()->NewInstance();
67113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  env->Global()->Set(v8_str("undetectable"), obj);
67123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
67133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ExpectBoolean("undefined == void 0", true);
67143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ExpectBoolean("undetectable == void 0", true);
67153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ExpectBoolean("null == void 0", true);
67163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ExpectBoolean("undefined === void 0", true);
67173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ExpectBoolean("undetectable === void 0", false);
67183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ExpectBoolean("null === void 0", false);
67193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
67203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ExpectBoolean("void 0 == undefined", true);
67213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ExpectBoolean("void 0 == undetectable", true);
67223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ExpectBoolean("void 0 == null", true);
67233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ExpectBoolean("void 0 === undefined", true);
67243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ExpectBoolean("void 0 === undetectable", false);
67253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ExpectBoolean("void 0 === null", false);
67263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
67273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ExpectString("(function() {"
67283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch               "  try {"
67293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch               "    return x === void 0;"
67303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch               "  } catch(e) {"
67313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch               "    return e.toString();"
67323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch               "  }"
67333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch               "})()",
67343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch               "ReferenceError: x is not defined");
67353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ExpectString("(function() {"
67363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch               "  try {"
67373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch               "    return void 0 === x;"
67383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch               "  } catch(e) {"
67393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch               "    return e.toString();"
67403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch               "  }"
67413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch               "})()",
67423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch               "ReferenceError: x is not defined");
67433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
67443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
67458defd9ff6930b4e24729971a61cf7469daf119beSteve Block
67468defd9ff6930b4e24729971a61cf7469daf119beSteve BlockTHREADED_TEST(ExtensibleOnUndetectable) {
67478defd9ff6930b4e24729971a61cf7469daf119beSteve Block  LocalContext env;
6748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
6749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
67508defd9ff6930b4e24729971a61cf7469daf119beSteve Block
6751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
67528defd9ff6930b4e24729971a61cf7469daf119beSteve Block  desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
67538defd9ff6930b4e24729971a61cf7469daf119beSteve Block
67548defd9ff6930b4e24729971a61cf7469daf119beSteve Block  Local<v8::Object> obj = desc->GetFunction()->NewInstance();
67558defd9ff6930b4e24729971a61cf7469daf119beSteve Block  env->Global()->Set(v8_str("undetectable"), obj);
67568defd9ff6930b4e24729971a61cf7469daf119beSteve Block
67578defd9ff6930b4e24729971a61cf7469daf119beSteve Block  Local<String> source = v8_str("undetectable.x = 42;"
67588defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                "undetectable.x");
67598defd9ff6930b4e24729971a61cf7469daf119beSteve Block
6760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Script> script = v8_compile(source);
67618defd9ff6930b4e24729971a61cf7469daf119beSteve Block
6762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(v8::Integer::New(isolate, 42), script->Run());
67638defd9ff6930b4e24729971a61cf7469daf119beSteve Block
67648defd9ff6930b4e24729971a61cf7469daf119beSteve Block  ExpectBoolean("Object.isExtensible(undetectable)", true);
67658defd9ff6930b4e24729971a61cf7469daf119beSteve Block
67668defd9ff6930b4e24729971a61cf7469daf119beSteve Block  source = v8_str("Object.preventExtensions(undetectable);");
6767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  script = v8_compile(source);
67688defd9ff6930b4e24729971a61cf7469daf119beSteve Block  script->Run();
67698defd9ff6930b4e24729971a61cf7469daf119beSteve Block  ExpectBoolean("Object.isExtensible(undetectable)", false);
67708defd9ff6930b4e24729971a61cf7469daf119beSteve Block
67718defd9ff6930b4e24729971a61cf7469daf119beSteve Block  source = v8_str("undetectable.y = 2000;");
6772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  script = v8_compile(source);
67733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  script->Run();
677444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ExpectBoolean("undetectable.y == undefined", true);
67758defd9ff6930b4e24729971a61cf7469daf119beSteve Block}
67768defd9ff6930b4e24729971a61cf7469daf119beSteve Block
67778defd9ff6930b4e24729971a61cf7469daf119beSteve Block
67788defd9ff6930b4e24729971a61cf7469daf119beSteve Block
6779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(UndetectableString) {
6780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext env;
6781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
6782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<String> obj = String::NewFromUtf8(env->GetIsolate(), "foo",
6784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                          String::kUndetectableString);
6785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env->Global()->Set(v8_str("undetectable"), obj);
6786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectString("undetectable", "foo");
6788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectString("typeof undetectable", "undefined");
6789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectString("typeof(undetectable)", "undefined");
6790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectBoolean("typeof undetectable == 'undefined'", true);
6791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectBoolean("typeof undetectable == 'string'", false);
6792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectBoolean("if (undetectable) { true; } else { false; }", false);
6793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectBoolean("!undetectable", true);
6794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectObject("true&&undetectable", obj);
6796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectBoolean("false&&undetectable", false);
6797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectBoolean("true||undetectable", true);
6798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectObject("false||undetectable", obj);
6799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectObject("undetectable&&true", obj);
6801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectObject("undetectable&&false", obj);
6802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectBoolean("undetectable||true", true);
6803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectBoolean("undetectable||false", false);
6804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectBoolean("undetectable==null", true);
6806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectBoolean("null==undetectable", true);
6807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectBoolean("undetectable==undefined", true);
6808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectBoolean("undefined==undetectable", true);
6809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectBoolean("undetectable==undetectable", true);
6810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectBoolean("undetectable===null", false);
6813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectBoolean("null===undetectable", false);
6814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectBoolean("undetectable===undefined", false);
6815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectBoolean("undefined===undetectable", false);
6816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectBoolean("undetectable===undetectable", true);
6817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
6818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6820257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochTEST(UndetectableOptimized) {
6821257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  i::FLAG_allow_natives_syntax = true;
6822257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  LocalContext env;
6823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
6824257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<String> obj = String::NewFromUtf8(env->GetIsolate(), "foo",
6826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                          String::kUndetectableString);
6827257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  env->Global()->Set(v8_str("undetectable"), obj);
6828257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  env->Global()->Set(v8_str("detectable"), v8_str("bar"));
6829257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6830257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ExpectString(
6831257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      "function testBranch() {"
6832257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      "  if (!%_IsUndetectableObject(undetectable)) throw 1;"
6833257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      "  if (%_IsUndetectableObject(detectable)) throw 2;"
6834257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      "}\n"
6835257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      "function testBool() {"
6836257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      "  var b1 = !%_IsUndetectableObject(undetectable);"
6837257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      "  var b2 = %_IsUndetectableObject(detectable);"
6838257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      "  if (b1) throw 3;"
6839257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      "  if (b2) throw 4;"
6840257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      "  return b1 == b2;"
6841257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      "}\n"
6842257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      "%OptimizeFunctionOnNextCall(testBranch);"
6843257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      "%OptimizeFunctionOnNextCall(testBool);"
6844257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      "for (var i = 0; i < 10; i++) {"
6845257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      "  testBranch();"
6846257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      "  testBool();"
6847257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      "}\n"
6848257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      "\"PASS\"",
6849257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      "PASS");
6850257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
6851257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6852257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// The point of this test is type checking. We run it only so compilers
6854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// don't complain about an unused function.
6855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(PersistentHandles) {
6856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
6857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
6858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
6859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<String> str = v8_str("foo");
6860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Persistent<String> p_str(isolate, str);
6861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  p_str.Reset();
6862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Script> scr = v8_compile("");
6863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Persistent<Script> p_scr(isolate, scr);
6864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  p_scr.Reset();
6865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Persistent<ObjectTemplate> p_templ(isolate, templ);
6867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  p_templ.Reset();
6868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
6869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void HandleLogDelegator(
6872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::FunctionCallbackInfo<v8::Value>& args) {
6873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
6874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
6875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(GlobalObjectTemplate) {
6878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
6879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(isolate);
6880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
6881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  global_template->Set(v8_str("JSNI_Log"),
6882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       v8::FunctionTemplate::New(isolate, HandleLogDelegator));
6883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<Context> context = Context::New(isolate, 0, global_template);
6884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Context::Scope context_scope(context);
6885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("JSNI_Log('LOG')");
6886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
6887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const char* kSimpleExtensionSource =
6890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "function Foo() {"
6891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "  return 4;"
6892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "}";
6893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(SimpleExtensions) {
6896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(CcTest::isolate());
6897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::RegisterExtension(new Extension("simpletest", kSimpleExtensionSource));
6898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* extension_names[] = { "simpletest" };
6899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::ExtensionConfiguration extensions(1, extension_names);
6900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<Context> context =
6901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Context::New(CcTest::isolate(), &extensions);
6902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Context::Scope lock(context);
6903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<Value> result = CompileRun("Foo()");
6904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 4));
6905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
6906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic const char* kStackTraceFromExtensionSource =
6909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  "function foo() {"
6910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  "  throw new Error();"
6911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  "}"
6912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  "function bar() {"
6913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  "  foo();"
6914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  "}";
6915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(StackTraceInExtension) {
6918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(CcTest::isolate());
6919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::RegisterExtension(new Extension("stacktracetest",
6920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        kStackTraceFromExtensionSource));
6921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* extension_names[] = { "stacktracetest" };
6922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::ExtensionConfiguration extensions(1, extension_names);
6923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<Context> context =
6924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Context::New(CcTest::isolate(), &extensions);
6925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Context::Scope lock(context);
6926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("function user() { bar(); }"
6927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "var error;"
6928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "try{ user(); } catch (e) { error = e; }");
6929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(-1, CompileRun("error.stack.indexOf('foo')")->Int32Value());
6930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(-1, CompileRun("error.stack.indexOf('bar')")->Int32Value());
6931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_NE(-1, CompileRun("error.stack.indexOf('user')")->Int32Value());
6932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
6933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(NullExtensions) {
6936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(CcTest::isolate());
6937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::RegisterExtension(new Extension("nulltest", NULL));
6938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* extension_names[] = { "nulltest" };
6939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::ExtensionConfiguration extensions(1, extension_names);
6940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<Context> context =
6941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Context::New(CcTest::isolate(), &extensions);
6942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Context::Scope lock(context);
6943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<Value> result = CompileRun("1+3");
6944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 4));
6945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
6946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
69483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic const char* kEmbeddedExtensionSource =
69493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    "function Ret54321(){return 54321;}~~@@$"
69503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    "$%% THIS IS A SERIES OF NON-NULL-TERMINATED STRINGS.";
69513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic const int kEmbeddedExtensionSourceValidLen = 34;
69523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
69533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(ExtensionMissingSourceLength) {
6955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(CcTest::isolate());
69563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::RegisterExtension(new Extension("srclentest_fail",
69573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      kEmbeddedExtensionSource));
69583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const char* extension_names[] = { "srclentest_fail" };
69593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::ExtensionConfiguration extensions(1, extension_names);
6960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<Context> context =
6961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Context::New(CcTest::isolate(), &extensions);
69623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(0, *context);
69633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
69643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
69653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(ExtensionWithSourceLength) {
69673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int source_len = kEmbeddedExtensionSourceValidLen - 1;
69683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       source_len <= kEmbeddedExtensionSourceValidLen + 1; ++source_len) {
6969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope handle_scope(CcTest::isolate());
69703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    i::ScopedVector<char> extension_name(32);
6971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    i::SNPrintF(extension_name, "ext #%d", source_len);
69723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    v8::RegisterExtension(new Extension(extension_name.start(),
69733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        kEmbeddedExtensionSource, 0, 0,
69743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        source_len));
69753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    const char* extension_names[1] = { extension_name.start() };
69763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    v8::ExtensionConfiguration extensions(1, extension_names);
6977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Handle<Context> context =
6978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Context::New(CcTest::isolate(), &extensions);
69793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (source_len == kEmbeddedExtensionSourceValidLen) {
69803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Context::Scope lock(context);
6981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Handle<Value> result = CompileRun("Ret54321()");
6982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CHECK_EQ(v8::Integer::New(CcTest::isolate(), 54321), result);
69833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
69843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Anything but exactly the right length should fail to compile.
69853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CHECK_EQ(0, *context);
69863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
69873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
69883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
69893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
69903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const char* kEvalExtensionSource1 =
6992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "function UseEval1() {"
6993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "  var x = 42;"
6994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "  return eval('x');"
6995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "}";
6996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const char* kEvalExtensionSource2 =
6999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "(function() {"
7000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "  var x = 42;"
7001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "  function e() {"
7002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "    return eval('x');"
7003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "  }"
7004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "  this.UseEval2 = e;"
7005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "})()";
7006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(UseEvalFromExtension) {
7009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(CcTest::isolate());
7010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::RegisterExtension(new Extension("evaltest1", kEvalExtensionSource1));
7011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::RegisterExtension(new Extension("evaltest2", kEvalExtensionSource2));
7012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* extension_names[] = { "evaltest1", "evaltest2" };
7013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::ExtensionConfiguration extensions(2, extension_names);
7014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<Context> context =
7015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Context::New(CcTest::isolate(), &extensions);
7016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Context::Scope lock(context);
7017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<Value> result = CompileRun("UseEval1()");
7018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 42));
7019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  result = CompileRun("UseEval2()");
7020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 42));
7021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
7022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const char* kWithExtensionSource1 =
7025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "function UseWith1() {"
7026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "  var x = 42;"
7027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "  with({x:87}) { return x; }"
7028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "}";
7029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const char* kWithExtensionSource2 =
7033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "(function() {"
7034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "  var x = 42;"
7035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "  function e() {"
7036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "    with ({x:87}) { return x; }"
7037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "  }"
7038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "  this.UseWith2 = e;"
7039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "})()";
7040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(UseWithFromExtension) {
7043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(CcTest::isolate());
7044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::RegisterExtension(new Extension("withtest1", kWithExtensionSource1));
7045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::RegisterExtension(new Extension("withtest2", kWithExtensionSource2));
7046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* extension_names[] = { "withtest1", "withtest2" };
7047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::ExtensionConfiguration extensions(2, extension_names);
7048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<Context> context =
7049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Context::New(CcTest::isolate(), &extensions);
7050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Context::Scope lock(context);
7051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<Value> result = CompileRun("UseWith1()");
7052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 87));
7053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  result = CompileRun("UseWith2()");
7054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 87));
7055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
7056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(AutoExtensions) {
7059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(CcTest::isolate());
7060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Extension* extension = new Extension("autotest", kSimpleExtensionSource);
7061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  extension->set_auto_enable(true);
7062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::RegisterExtension(extension);
7063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<Context> context =
7064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Context::New(CcTest::isolate());
7065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Context::Scope lock(context);
7066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<Value> result = CompileRun("Foo()");
7067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 4));
7068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
7069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7071d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockstatic const char* kSyntaxErrorInExtensionSource =
7072d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    "[";
7073d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
7074d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
7075d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// Test that a syntax error in an extension does not cause a fatal
7076d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// error but results in an empty context.
7077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(SyntaxErrorExtensions) {
7078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(CcTest::isolate());
7079d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  v8::RegisterExtension(new Extension("syntaxerror",
7080d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                      kSyntaxErrorInExtensionSource));
7081d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  const char* extension_names[] = { "syntaxerror" };
7082d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  v8::ExtensionConfiguration extensions(1, extension_names);
7083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<Context> context =
7084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Context::New(CcTest::isolate(), &extensions);
7085d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CHECK(context.IsEmpty());
7086d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
7087d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
7088d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
7089d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockstatic const char* kExceptionInExtensionSource =
7090d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    "throw 42";
7091d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
7092d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
7093d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// Test that an exception when installing an extension does not cause
7094d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// a fatal error but results in an empty context.
7095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(ExceptionExtensions) {
7096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(CcTest::isolate());
7097d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  v8::RegisterExtension(new Extension("exception",
7098d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                      kExceptionInExtensionSource));
7099d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  const char* extension_names[] = { "exception" };
7100d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  v8::ExtensionConfiguration extensions(1, extension_names);
7101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<Context> context =
7102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Context::New(CcTest::isolate(), &extensions);
7103d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CHECK(context.IsEmpty());
7104d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
7105d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
7106d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
71079ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrickstatic const char* kNativeCallInExtensionSource =
71089ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    "function call_runtime_last_index_of(x) {"
71099ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    "  return %StringLastIndexOf(x, 'bob', 10);"
71109ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    "}";
71119ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick
71129ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick
71139ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrickstatic const char* kNativeCallTest =
71149ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    "call_runtime_last_index_of('bobbobboellebobboellebobbob');";
71159ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick
71169ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick// Test that a native runtime calls are supported in extensions.
7117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(NativeCallInExtensions) {
7118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(CcTest::isolate());
71199ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  v8::RegisterExtension(new Extension("nativecall",
71209ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick                                      kNativeCallInExtensionSource));
71219ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  const char* extension_names[] = { "nativecall" };
71229ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  v8::ExtensionConfiguration extensions(1, extension_names);
7123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<Context> context =
7124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Context::New(CcTest::isolate(), &extensions);
71259ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  Context::Scope lock(context);
7126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<Value> result = CompileRun(kNativeCallTest);
7127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 3));
71289ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick}
71299ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick
71309ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick
71313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochclass NativeFunctionExtension : public Extension {
71323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch public:
71333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  NativeFunctionExtension(const char* name,
71343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          const char* source,
7135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          v8::FunctionCallback fun = &Echo)
71363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      : Extension(name, source),
71373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        function_(fun) { }
71383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
7139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  virtual v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate(
7140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Isolate* isolate,
71413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      v8::Handle<v8::String> name) {
7142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return v8::FunctionTemplate::New(isolate, function_);
71433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
71443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
7145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static void Echo(const v8::FunctionCallbackInfo<v8::Value>& args) {
7146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (args.Length() >= 1) args.GetReturnValue().Set(args[0]);
71473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
71483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch private:
7149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::FunctionCallback function_;
71503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch};
71513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
71523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
7153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(NativeFunctionDeclaration) {
7154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(CcTest::isolate());
71553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const char* name = "nativedecl";
71563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  v8::RegisterExtension(new NativeFunctionExtension(name,
71573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                    "native function foo();"));
71583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const char* extension_names[] = { name };
71593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  v8::ExtensionConfiguration extensions(1, extension_names);
7160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<Context> context =
7161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Context::New(CcTest::isolate(), &extensions);
71623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Context::Scope lock(context);
7163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<Value> result = CompileRun("foo(42);");
7164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 42));
71653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
71663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
71673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
7168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(NativeFunctionDeclarationError) {
7169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(CcTest::isolate());
71703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const char* name = "nativedeclerr";
71713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Syntax error in extension code.
71723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  v8::RegisterExtension(new NativeFunctionExtension(name,
71733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                    "native\nfunction foo();"));
71743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const char* extension_names[] = { name };
71753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  v8::ExtensionConfiguration extensions(1, extension_names);
7176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<Context> context =
7177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Context::New(CcTest::isolate(), &extensions);
71783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(context.IsEmpty());
71793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
71803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
71813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(NativeFunctionDeclarationErrorEscape) {
7183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(CcTest::isolate());
71843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const char* name = "nativedeclerresc";
71853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Syntax error in extension code - escape code in "native" means that
71863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // it's not treated as a keyword.
71873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  v8::RegisterExtension(new NativeFunctionExtension(
71883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      name,
71893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      "nativ\\u0065 function foo();"));
71903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const char* extension_names[] = { name };
71913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  v8::ExtensionConfiguration extensions(1, extension_names);
7192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<Context> context =
7193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Context::New(CcTest::isolate(), &extensions);
71943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(context.IsEmpty());
71953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
71963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
71973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
7198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void CheckDependencies(const char* name, const char* expected) {
7199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(CcTest::isolate());
7200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::ExtensionConfiguration config(1, &name);
7201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context(&config);
7202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(String::NewFromUtf8(CcTest::isolate(), expected),
7203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           context->Global()->Get(v8_str("loaded")));
7204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
7205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block/*
7208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * Configuration:
7209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *
7210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *     /-- B <--\
7211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * A <-          -- D <-- E
7212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *     \-- C <--/
7213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block */
7214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(ExtensionDependency) {
7215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static const char* kEDeps[] = { "D" };
7216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::RegisterExtension(new Extension("E", "this.loaded += 'E';", 1, kEDeps));
7217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static const char* kDDeps[] = { "B", "C" };
7218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::RegisterExtension(new Extension("D", "this.loaded += 'D';", 2, kDDeps));
7219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static const char* kBCDeps[] = { "A" };
7220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::RegisterExtension(new Extension("B", "this.loaded += 'B';", 1, kBCDeps));
7221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::RegisterExtension(new Extension("C", "this.loaded += 'C';", 1, kBCDeps));
7222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::RegisterExtension(new Extension("A", "this.loaded += 'A';"));
7223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDependencies("A", "undefinedA");
7224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDependencies("B", "undefinedAB");
7225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDependencies("C", "undefinedAC");
7226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDependencies("D", "undefinedABCD");
7227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDependencies("E", "undefinedABCDE");
7228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(CcTest::isolate());
7229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static const char* exts[2] = { "C", "E" };
7230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::ExtensionConfiguration config(2, exts);
7231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context(&config);
7232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(v8_str("undefinedACBDE"), context->Global()->Get(v8_str("loaded")));
7233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
7234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const char* kExtensionTestScript =
7237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "native function A();"
7238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "native function B();"
7239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "native function C();"
7240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "function Foo(i) {"
7241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "  if (i == 0) return A();"
7242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "  if (i == 1) return B();"
7243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "  if (i == 2) return C();"
7244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "}";
7245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void CallFun(const v8::FunctionCallbackInfo<v8::Value>& args) {
7248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
7249e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (args.IsConstructCall()) {
7250e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    args.This()->Set(v8_str("data"), args.Data());
7251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    args.GetReturnValue().SetNull();
7252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
7253e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
7254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  args.GetReturnValue().Set(args.Data());
7255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
7256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass FunctionExtension : public Extension {
7259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
7260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  FunctionExtension() : Extension("functiontest", kExtensionTestScript) { }
7261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  virtual v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate(
7262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Isolate* isolate,
7263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      v8::Handle<String> name);
7264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
7265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic int lookup_count = 0;
7268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochv8::Handle<v8::FunctionTemplate> FunctionExtension::GetNativeFunctionTemplate(
7269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Isolate* isolate, v8::Handle<String> name) {
7270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  lookup_count++;
7271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (name->Equals(v8_str("A"))) {
7272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return v8::FunctionTemplate::New(
7273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        isolate, CallFun, v8::Integer::New(isolate, 8));
7274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (name->Equals(v8_str("B"))) {
7275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return v8::FunctionTemplate::New(
7276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        isolate, CallFun, v8::Integer::New(isolate, 7));
7277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (name->Equals(v8_str("C"))) {
7278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return v8::FunctionTemplate::New(
7279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        isolate, CallFun, v8::Integer::New(isolate, 6));
7280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
7281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return v8::Handle<v8::FunctionTemplate>();
7282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
7283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
7284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(FunctionLookup) {
7287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::RegisterExtension(new FunctionExtension());
7288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(CcTest::isolate());
7289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static const char* exts[1] = { "functiontest" };
7290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::ExtensionConfiguration config(1, exts);
7291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context(&config);
7292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(3, lookup_count);
7293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(v8::Integer::New(CcTest::isolate(), 8),
7294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           CompileRun("Foo(0)"));
7295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(v8::Integer::New(CcTest::isolate(), 7),
7296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           CompileRun("Foo(1)"));
7297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(v8::Integer::New(CcTest::isolate(), 6),
7298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           CompileRun("Foo(2)"));
7299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
7300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7302e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon ClarkeTHREADED_TEST(NativeFunctionConstructCall) {
7303e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  v8::RegisterExtension(new FunctionExtension());
7304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(CcTest::isolate());
7305e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  static const char* exts[1] = { "functiontest" };
7306e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  v8::ExtensionConfiguration config(1, exts);
7307e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  LocalContext context(&config);
7308d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  for (int i = 0; i < 10; i++) {
7309d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // Run a few times to ensure that allocation of objects doesn't
7310d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // change behavior of a constructor function.
7311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(v8::Integer::New(CcTest::isolate(), 8),
7312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             CompileRun("(new A()).data"));
7313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(v8::Integer::New(CcTest::isolate(), 7),
7314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             CompileRun("(new B()).data"));
7315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(v8::Integer::New(CcTest::isolate(), 6),
7316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             CompileRun("(new C()).data"));
7317d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
7318e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
7319e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
7320e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
7321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const char* last_location;
7322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const char* last_message;
7323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StoringErrorCallback(const char* location, const char* message) {
7324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (last_location == NULL) {
7325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    last_location = location;
7326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    last_message = message;
7327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
7328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
7329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ErrorReporting creates a circular extensions configuration and
7332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// tests that the fatal error handler gets called.  This renders V8
7333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// unusable and therefore this test cannot be run in parallel.
7334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(ErrorReporting) {
7335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::V8::SetFatalErrorHandler(StoringErrorCallback);
7336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static const char* aDeps[] = { "B" };
7337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::RegisterExtension(new Extension("A", "", 1, aDeps));
7338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static const char* bDeps[] = { "A" };
7339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::RegisterExtension(new Extension("B", "", 1, bDeps));
7340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  last_location = NULL;
7341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::ExtensionConfiguration config(1, bDeps);
7342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<Context> context =
7343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Context::New(CcTest::isolate(), &config);
7344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(context.IsEmpty());
7345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_NE(last_location, NULL);
7346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
7347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void MissingScriptInfoMessageListener(v8::Handle<v8::Message> message,
7350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             v8::Handle<Value> data) {
7351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(message->GetScriptOrigin().ResourceName()->IsUndefined());
7352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(v8::Undefined(CcTest::isolate()),
7353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      message->GetScriptOrigin().ResourceName());
7354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  message->GetLineNumber();
7355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  message->GetSourceLine();
7356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
7357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(ErrorWithMissingScriptInfo) {
7360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
7361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(context->GetIsolate());
7362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::V8::AddMessageListener(MissingScriptInfoMessageListener);
7363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("throw Error()");
7364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::V8::RemoveMessageListeners(MissingScriptInfoMessageListener);
7365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
7366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstruct FlagAndPersistent {
7369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool flag;
7370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Persistent<v8::Object> handle;
7371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
7372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void DisposeAndSetFlag(
7375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::WeakCallbackData<v8::Object, FlagAndPersistent>& data) {
7376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  data.GetParameter()->handle.Reset();
7377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  data.GetParameter()->flag = true;
7378d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
7379d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
7380d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
7381257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochTHREADED_TEST(IndependentWeakHandle) {
7382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* iso = CcTest::isolate();
7383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(iso);
7384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<Context> context = Context::New(iso);
7385d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Context::Scope context_scope(context);
7386d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
7387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  FlagAndPersistent object_a, object_b;
7388d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
7389d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  {
7390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope handle_scope(iso);
7391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    object_a.handle.Reset(iso, v8::Object::New(iso));
7392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    object_b.handle.Reset(iso, v8::Object::New(iso));
7393d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
7394d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
7395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  object_a.flag = false;
7396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  object_b.flag = false;
7397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  object_a.handle.SetWeak(&object_a, &DisposeAndSetFlag);
7398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  object_b.handle.SetWeak(&object_b, &DisposeAndSetFlag);
7399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!object_b.handle.IsIndependent());
7400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  object_a.handle.MarkIndependent();
7401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  object_b.handle.MarkIndependent();
7402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(object_b.handle.IsIndependent());
7403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectGarbage(i::NEW_SPACE);
7404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(object_a.flag);
7405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(object_b.flag);
7406257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
7407d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
7408257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
7409257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic void InvokeScavenge() {
7410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectGarbage(i::NEW_SPACE);
7411257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
7412257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
7413257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
7414257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic void InvokeMarkSweep() {
7415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
7416257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
7417257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
7418257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
7419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void ForceScavenge(
7420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::WeakCallbackData<v8::Object, FlagAndPersistent>& data) {
7421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  data.GetParameter()->handle.Reset();
7422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  data.GetParameter()->flag = true;
7423257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  InvokeScavenge();
7424257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
7425257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
7426257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
7427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void ForceMarkSweep(
7428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::WeakCallbackData<v8::Object, FlagAndPersistent>& data) {
7429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  data.GetParameter()->handle.Reset();
7430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  data.GetParameter()->flag = true;
7431257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  InvokeMarkSweep();
7432257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
7433257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
7434257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
7435257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochTHREADED_TEST(GCFromWeakCallbacks) {
7436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
7437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
7438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<Context> context = Context::New(isolate);
7439257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Context::Scope context_scope(context);
7440257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
7441257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static const int kNumberOfGCTypes = 2;
7442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  typedef v8::WeakCallbackData<v8::Object, FlagAndPersistent>::Callback
7443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Callback;
7444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Callback gc_forcing_callback[kNumberOfGCTypes] =
7445257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      {&ForceScavenge, &ForceMarkSweep};
7446257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
7447257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  typedef void (*GCInvoker)();
7448257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  GCInvoker invoke_gc[kNumberOfGCTypes] = {&InvokeScavenge, &InvokeMarkSweep};
7449257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
7450257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  for (int outer_gc = 0; outer_gc < kNumberOfGCTypes; outer_gc++) {
7451257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    for (int inner_gc = 0; inner_gc < kNumberOfGCTypes; inner_gc++) {
7452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      FlagAndPersistent object;
7453257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      {
7454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v8::HandleScope handle_scope(isolate);
7455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        object.handle.Reset(isolate, v8::Object::New(isolate));
7456257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      }
7457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      object.flag = false;
7458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      object.handle.SetWeak(&object, gc_forcing_callback[inner_gc]);
7459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      object.handle.MarkIndependent();
7460257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      invoke_gc[outer_gc]();
7461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CHECK(object.flag);
7462257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
7463257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
7464257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
7465257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
7466257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
7467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void RevivingCallback(
7468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::WeakCallbackData<v8::Object, FlagAndPersistent>& data) {
7469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  data.GetParameter()->handle.ClearWeak();
7470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  data.GetParameter()->flag = true;
7471257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
7472257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
7473257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
7474257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochTHREADED_TEST(IndependentHandleRevival) {
7475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
7476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
7477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<Context> context = Context::New(isolate);
7478257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Context::Scope context_scope(context);
7479257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
7480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  FlagAndPersistent object;
7481257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  {
7482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope handle_scope(isolate);
7483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Local<v8::Object> o = v8::Object::New(isolate);
7484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    object.handle.Reset(isolate, o);
7485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    o->Set(v8_str("x"), v8::Integer::New(isolate, 1));
7486257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    v8::Local<String> y_str = v8_str("y");
7487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    o->Set(y_str, y_str);
7488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
7489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  object.flag = false;
7490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  object.handle.SetWeak(&object, &RevivingCallback);
7491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  object.handle.MarkIndependent();
7492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectGarbage(i::NEW_SPACE);
7493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(object.flag);
7494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
7495257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  {
7496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope handle_scope(isolate);
7497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Local<v8::Object> o =
7498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v8::Local<v8::Object>::New(isolate, object.handle);
7499257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    v8::Local<String> y_str = v8_str("y");
7500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(v8::Integer::New(isolate, 1), o->Get(v8_str("x")));
7501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(o->Get(y_str)->Equals(y_str));
7502d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
7503d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
7504d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
7505d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
7506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockv8::Handle<Function> args_fun;
7507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void ArgumentsTestCallback(
7510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::FunctionCallbackInfo<v8::Value>& args) {
7511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
7512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = args.GetIsolate();
7513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(args_fun, args.Callee());
7514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(3, args.Length());
7515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(v8::Integer::New(isolate, 1), args[0]);
7516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(v8::Integer::New(isolate, 2), args[1]);
7517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(v8::Integer::New(isolate, 3), args[2]);
7518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(v8::Undefined(isolate), args[3]);
7519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(args.GetIsolate());
7520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
7521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
7522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(Arguments) {
7525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
7526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
7527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> global = ObjectTemplate::New(isolate);
7528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  global->Set(v8_str("f"),
7529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              v8::FunctionTemplate::New(isolate, ArgumentsTestCallback));
7530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context(NULL, global);
75316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  args_fun = context->Global()->Get(v8_str("f")).As<Function>();
7532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8_compile("f(1, 2, 3)")->Run();
7533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
7534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void NoBlockGetterX(Local<String> name,
7537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           const v8::PropertyCallbackInfo<v8::Value>&) {
7538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
7539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void NoBlockGetterI(uint32_t index,
7542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           const v8::PropertyCallbackInfo<v8::Value>&) {
7543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
7544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void PDeleter(Local<String> name,
7547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     const v8::PropertyCallbackInfo<v8::Boolean>& info) {
7548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!name->Equals(v8_str("foo"))) {
7549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;  // not intercepted
7550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
7551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(false);  // intercepted, don't delete the property
7553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
7554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void IDeleter(uint32_t index,
7557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     const v8::PropertyCallbackInfo<v8::Boolean>& info) {
7558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (index != 2) {
7559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;  // not intercepted
7560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
7561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(false);  // intercepted, don't delete the property
7563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
7564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(Deleter) {
7567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
7568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
7569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
7570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  obj->SetNamedPropertyHandler(NoBlockGetterX, NULL, NULL, PDeleter, NULL);
7571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  obj->SetIndexedPropertyHandler(NoBlockGetterI, NULL, NULL, IDeleter, NULL);
7572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
7573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context->Global()->Set(v8_str("k"), obj->NewInstance());
7574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CompileRun(
7575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "k.foo = 'foo';"
7576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "k.bar = 'bar';"
7577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "k[2] = 2;"
7578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "k[4] = 4;");
7579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(v8_compile("delete k.foo")->Run()->IsFalse());
7580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(v8_compile("delete k.bar")->Run()->IsTrue());
7581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(v8_compile("k.foo")->Run(), v8_str("foo"));
7583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(v8_compile("k.bar")->Run()->IsUndefined());
7584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(v8_compile("delete k[2]")->Run()->IsFalse());
7586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(v8_compile("delete k[4]")->Run()->IsTrue());
7587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(v8_compile("k[2]")->Run(), v8_num(2));
7589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(v8_compile("k[4]")->Run()->IsUndefined());
7590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
7591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void GetK(Local<String> name,
7594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 const v8::PropertyCallbackInfo<v8::Value>& info) {
7595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
7596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (name->Equals(v8_str("foo")) ||
7597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      name->Equals(v8_str("bar")) ||
7598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      name->Equals(v8_str("baz"))) {
7599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    info.GetReturnValue().SetUndefined();
7600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
7601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
7602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void IndexedGetK(uint32_t index,
7605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        const v8::PropertyCallbackInfo<v8::Value>& info) {
7606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
7607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (index == 0 || index == 1) info.GetReturnValue().SetUndefined();
7608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
7609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void NamedEnum(const v8::PropertyCallbackInfo<v8::Array>& info) {
7612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
7613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Array> result = v8::Array::New(info.GetIsolate(), 3);
7614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  result->Set(v8::Integer::New(info.GetIsolate(), 0), v8_str("foo"));
7615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  result->Set(v8::Integer::New(info.GetIsolate(), 1), v8_str("bar"));
7616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  result->Set(v8::Integer::New(info.GetIsolate(), 2), v8_str("baz"));
7617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(result);
7618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
7619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void IndexedEnum(const v8::PropertyCallbackInfo<v8::Array>& info) {
7622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
7623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Array> result = v8::Array::New(info.GetIsolate(), 2);
7624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  result->Set(v8::Integer::New(info.GetIsolate(), 0), v8_str("0"));
7625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  result->Set(v8::Integer::New(info.GetIsolate(), 1), v8_str("1"));
7626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(result);
7627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
7628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(Enumerators) {
7631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
7632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
7633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
7634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  obj->SetNamedPropertyHandler(GetK, NULL, NULL, NULL, NamedEnum);
7635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  obj->SetIndexedPropertyHandler(IndexedGetK, NULL, NULL, NULL, IndexedEnum);
7636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
7637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context->Global()->Set(v8_str("k"), obj->NewInstance());
7638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
7639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "k[10] = 0;"
7640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "k.a = 0;"
7641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "k[5] = 0;"
7642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "k.b = 0;"
7643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "k[4294967295] = 0;"
7644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "k.c = 0;"
7645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "k[4294967296] = 0;"
7646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "k.d = 0;"
7647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "k[140000] = 0;"
7648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "k.e = 0;"
7649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "k[30000000000] = 0;"
7650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "k.f = 0;"
7651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "var result = [];"
7652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "for (var prop in k) {"
7653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  result.push(prop);"
7654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "}"
7655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "result"));
7656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that we get all the property names returned including the
7657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ones from the enumerators in the right order: indexed properties
7658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // in numerical order, indexed interceptor properties, named
7659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // properties in insertion order, named interceptor properties.
7660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // This order is not mandated by the spec, so this test is just
7661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // documenting our behavior.
7662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(17, result->Length());
7663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Indexed properties in numerical order.
7664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(v8_str("5"), result->Get(v8::Integer::New(isolate, 0)));
7665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(v8_str("10"), result->Get(v8::Integer::New(isolate, 1)));
7666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(v8_str("140000"), result->Get(v8::Integer::New(isolate, 2)));
7667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(v8_str("4294967295"), result->Get(v8::Integer::New(isolate, 3)));
7668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Indexed interceptor properties in the order they are returned
7669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // from the enumerator interceptor.
7670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(v8_str("0"), result->Get(v8::Integer::New(isolate, 4)));
7671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(v8_str("1"), result->Get(v8::Integer::New(isolate, 5)));
7672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Named properties in insertion order.
7673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(v8_str("a"), result->Get(v8::Integer::New(isolate, 6)));
7674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(v8_str("b"), result->Get(v8::Integer::New(isolate, 7)));
7675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(v8_str("c"), result->Get(v8::Integer::New(isolate, 8)));
7676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(v8_str("4294967296"), result->Get(v8::Integer::New(isolate, 9)));
7677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(v8_str("d"), result->Get(v8::Integer::New(isolate, 10)));
7678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(v8_str("e"), result->Get(v8::Integer::New(isolate, 11)));
7679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(v8_str("30000000000"), result->Get(v8::Integer::New(isolate, 12)));
7680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(v8_str("f"), result->Get(v8::Integer::New(isolate, 13)));
7681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Named interceptor properties.
7682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(v8_str("foo"), result->Get(v8::Integer::New(isolate, 14)));
7683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(v8_str("bar"), result->Get(v8::Integer::New(isolate, 15)));
7684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(v8_str("baz"), result->Get(v8::Integer::New(isolate, 16)));
7685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
7686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint p_getter_count;
7689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint p_getter_count2;
7690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void PGetter(Local<String> name,
7693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                    const v8::PropertyCallbackInfo<v8::Value>& info) {
7694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
7695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  p_getter_count++;
7696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Object> global =
7697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      info.GetIsolate()->GetCurrentContext()->Global();
7698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(info.Holder(), global->Get(v8_str("o1")));
7699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (name->Equals(v8_str("p1"))) {
7700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(info.This(), global->Get(v8_str("o1")));
7701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (name->Equals(v8_str("p2"))) {
7702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(info.This(), global->Get(v8_str("o2")));
7703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (name->Equals(v8_str("p3"))) {
7704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(info.This(), global->Get(v8_str("o3")));
7705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (name->Equals(v8_str("p4"))) {
7706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(info.This(), global->Get(v8_str("o4")));
7707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
7708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
7709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void RunHolderTest(v8::Handle<v8::ObjectTemplate> obj) {
7712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
7713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
7714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context->Global()->Set(v8_str("o1"), obj->NewInstance());
7715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CompileRun(
7716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "o1.__proto__ = { };"
7717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "var o2 = { __proto__: o1 };"
7718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "var o3 = { __proto__: o2 };"
7719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "var o4 = { __proto__: o3 };"
7720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "for (var i = 0; i < 10; i++) o4.p4;"
7721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "for (var i = 0; i < 10; i++) o3.p3;"
7722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "for (var i = 0; i < 10; i++) o2.p2;"
7723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "for (var i = 0; i < 10; i++) o1.p1;");
7724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
7725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void PGetter2(Local<String> name,
7728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     const v8::PropertyCallbackInfo<v8::Value>& info) {
7729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
7730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  p_getter_count2++;
7731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Object> global =
7732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      info.GetIsolate()->GetCurrentContext()->Global();
7733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(info.Holder(), global->Get(v8_str("o1")));
7734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (name->Equals(v8_str("p1"))) {
7735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(info.This(), global->Get(v8_str("o1")));
7736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (name->Equals(v8_str("p2"))) {
7737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(info.This(), global->Get(v8_str("o2")));
7738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (name->Equals(v8_str("p3"))) {
7739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(info.This(), global->Get(v8_str("o3")));
7740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (name->Equals(v8_str("p4"))) {
7741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(info.This(), global->Get(v8_str("o4")));
7742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
7743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
7744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(GetterHolders) {
7747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
7748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
7749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
7750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  obj->SetAccessor(v8_str("p1"), PGetter);
7751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  obj->SetAccessor(v8_str("p2"), PGetter);
7752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  obj->SetAccessor(v8_str("p3"), PGetter);
7753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  obj->SetAccessor(v8_str("p4"), PGetter);
7754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  p_getter_count = 0;
7755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RunHolderTest(obj);
7756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(40, p_getter_count);
7757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
7758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(PreInterceptorHolders) {
7761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
7762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
7763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
7764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  obj->SetNamedPropertyHandler(PGetter2);
7765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  p_getter_count2 = 0;
7766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RunHolderTest(obj);
7767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(40, p_getter_count2);
7768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
7769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(ObjectInstantiation) {
7772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
7773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
7774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
7775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  templ->SetAccessor(v8_str("t"), PGetter2);
7776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
7777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context->Global()->Set(v8_str("o"), templ->NewInstance());
7778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < 100; i++) {
7779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope inner_scope(CcTest::isolate());
7780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    v8::Handle<v8::Object> obj = templ->NewInstance();
7781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_NE(obj, context->Global()->Get(v8_str("o")));
7782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    context->Global()->Set(v8_str("o2"), obj);
7783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    v8::Handle<Value> value =
7784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        CompileRun("o.__proto__ === o2.__proto__");
7785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(v8::True(isolate), value);
7786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    context->Global()->Set(v8_str("o"), obj);
7787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
7788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
7789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7791b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic int StrCmp16(uint16_t* a, uint16_t* b) {
7792b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (true) {
7793b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (*a == 0 && *b == 0) return 0;
7794b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (*a != *b) return 0 + *a - *b;
7795b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    a++;
7796b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    b++;
7797b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
7798b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7799b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7800b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7801b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic int StrNCmp16(uint16_t* a, uint16_t* b, int n) {
7802b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (true) {
7803b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (n-- == 0) return 0;
7804b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (*a == 0 && *b == 0) return 0;
7805b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (*a != *b) return 0 + *a - *b;
7806b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    a++;
7807b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    b++;
7808b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
7809b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7810b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7811b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
78123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochint GetUtf8Length(Handle<String> str) {
78133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int len = str->Utf8Length();
78143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (len < 0) {
78153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    i::Handle<i::String> istr(v8::Utils::OpenHandle(*str));
7816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    i::String::Flatten(istr);
78173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    len = str->Utf8Length();
78183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
78193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return len;
78203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
78213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
78223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(StringWrite) {
78243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LocalContext context;
7825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(context->GetIsolate());
7826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<String> str = v8_str("abcde");
7827b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // abc<Icelandic eth><Unicode snowman>.
7828b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  v8::Handle<String> str2 = v8_str("abc\303\260\342\230\203");
7829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<String> str3 = v8::String::NewFromUtf8(
7830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      context->GetIsolate(), "abc\0def", v8::String::kNormalString, 7);
7831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // "ab" + lead surrogate + "cd" + trail surrogate + "ef"
7832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  uint16_t orphans[8] = { 0x61, 0x62, 0xd800, 0x63, 0x64, 0xdc00, 0x65, 0x66 };
7833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<String> orphans_str = v8::String::NewFromTwoByte(
7834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      context->GetIsolate(), orphans, v8::String::kNormalString, 8);
7835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // single lead surrogate
7836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  uint16_t lead[1] = { 0xd800 };
7837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<String> lead_str = v8::String::NewFromTwoByte(
7838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      context->GetIsolate(), lead, v8::String::kNormalString, 1);
7839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // single trail surrogate
7840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  uint16_t trail[1] = { 0xdc00 };
7841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<String> trail_str = v8::String::NewFromTwoByte(
7842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      context->GetIsolate(), trail, v8::String::kNormalString, 1);
7843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // surrogate pair
7844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  uint16_t pair[2] = { 0xd800,  0xdc00 };
7845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<String> pair_str = v8::String::NewFromTwoByte(
7846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      context->GetIsolate(), pair, v8::String::kNormalString, 2);
78473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const int kStride = 4;  // Must match stride in for loops in JS below.
78483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileRun(
78493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "var left = '';"
78503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "for (var i = 0; i < 0xd800; i += 4) {"
78513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "  left = left + String.fromCharCode(i);"
78523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "}");
78533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileRun(
78543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "var right = '';"
78553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "for (var i = 0; i < 0xd800; i += 4) {"
78563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "  right = String.fromCharCode(i) + right;"
78573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "}");
7858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Object> global = context->Global();
78593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<String> left_tree = global->Get(v8_str("left")).As<String>();
78603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<String> right_tree = global->Get(v8_str("right")).As<String>();
7861b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7862b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_EQ(5, str2->Length());
78633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(0xd800 / kStride, left_tree->Length());
78643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(0xd800 / kStride, right_tree->Length());
7865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  char buf[100];
78673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  char utf8buf[0xd800 * 3];
7868b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  uint16_t wbuf[100];
7869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int len;
7870b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int charlen;
7871b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
78723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  memset(utf8buf, 0x1, 1000);
7873b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen);
787444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(9, len);
787544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(5, charlen);
787644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
7877b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
78783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  memset(utf8buf, 0x1, 1000);
7879b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  len = str2->WriteUtf8(utf8buf, 8, &charlen);
788044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(8, len);
788144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(5, charlen);
788244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203\1", 9));
7883b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
78843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  memset(utf8buf, 0x1, 1000);
7885b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  len = str2->WriteUtf8(utf8buf, 7, &charlen);
788644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(5, len);
788744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(4, charlen);
788844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
7889b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
78903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  memset(utf8buf, 0x1, 1000);
7891b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  len = str2->WriteUtf8(utf8buf, 6, &charlen);
789244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(5, len);
789344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(4, charlen);
789444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
7895b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
78963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  memset(utf8buf, 0x1, 1000);
7897b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  len = str2->WriteUtf8(utf8buf, 5, &charlen);
789844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(5, len);
789944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(4, charlen);
790044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
7901b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
79023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  memset(utf8buf, 0x1, 1000);
7903b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  len = str2->WriteUtf8(utf8buf, 4, &charlen);
790444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(3, len);
790544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(3, charlen);
790644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
7907b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
79083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  memset(utf8buf, 0x1, 1000);
7909b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  len = str2->WriteUtf8(utf8buf, 3, &charlen);
791044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(3, len);
791144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(3, charlen);
791244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
7913b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
79143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  memset(utf8buf, 0x1, 1000);
7915b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  len = str2->WriteUtf8(utf8buf, 2, &charlen);
791644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(2, len);
791744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(2, charlen);
791844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, strncmp(utf8buf, "ab\1", 3));
7919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // allow orphan surrogates by default
7921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  memset(utf8buf, 0x1, 1000);
7922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  len = orphans_str->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen);
7923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(13, len);
7924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(8, charlen);
7925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, strcmp(utf8buf, "ab\355\240\200cd\355\260\200ef"));
7926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // replace orphan surrogates with unicode replacement character
7928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  memset(utf8buf, 0x1, 1000);
7929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  len = orphans_str->WriteUtf8(utf8buf,
7930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               sizeof(utf8buf),
7931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               &charlen,
7932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               String::REPLACE_INVALID_UTF8);
7933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(13, len);
7934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(8, charlen);
7935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, strcmp(utf8buf, "ab\357\277\275cd\357\277\275ef"));
7936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // replace single lead surrogate with unicode replacement character
7938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  memset(utf8buf, 0x1, 1000);
7939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  len = lead_str->WriteUtf8(utf8buf,
7940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            sizeof(utf8buf),
7941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            &charlen,
7942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            String::REPLACE_INVALID_UTF8);
7943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(4, len);
7944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1, charlen);
7945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, strcmp(utf8buf, "\357\277\275"));
7946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // replace single trail surrogate with unicode replacement character
7948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  memset(utf8buf, 0x1, 1000);
7949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  len = trail_str->WriteUtf8(utf8buf,
7950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             sizeof(utf8buf),
7951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             &charlen,
7952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             String::REPLACE_INVALID_UTF8);
7953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(4, len);
7954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1, charlen);
7955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, strcmp(utf8buf, "\357\277\275"));
7956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // do not replace / write anything if surrogate pair does not fit the buffer
7958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // space
7959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  memset(utf8buf, 0x1, 1000);
7960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  len = pair_str->WriteUtf8(utf8buf,
7961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             3,
7962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             &charlen,
7963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             String::REPLACE_INVALID_UTF8);
7964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, len);
7965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, charlen);
7966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
79673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  memset(utf8buf, 0x1, sizeof(utf8buf));
79683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  len = GetUtf8Length(left_tree);
79693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int utf8_expected =
79703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      (0x80 + (0x800 - 0x80) * 2 + (0xd800 - 0x800) * 3) / kStride;
79713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(utf8_expected, len);
79723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  len = left_tree->WriteUtf8(utf8buf, utf8_expected, &charlen);
79733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(utf8_expected, len);
79743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(0xd800 / kStride, charlen);
79753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[utf8_expected - 3]));
79763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[utf8_expected - 2]));
79773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(0xc0 - kStride,
79783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           static_cast<unsigned char>(utf8buf[utf8_expected - 1]));
79793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(1, utf8buf[utf8_expected]);
79803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
79813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  memset(utf8buf, 0x1, sizeof(utf8buf));
79823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  len = GetUtf8Length(right_tree);
79833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(utf8_expected, len);
79843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  len = right_tree->WriteUtf8(utf8buf, utf8_expected, &charlen);
79853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(utf8_expected, len);
79863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(0xd800 / kStride, charlen);
79873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[0]));
79883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[1]));
79893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(0xc0 - kStride, static_cast<unsigned char>(utf8buf[2]));
79903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(1, utf8buf[utf8_expected]);
79913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  memset(buf, 0x1, sizeof(buf));
7993b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  memset(wbuf, 0x1, sizeof(wbuf));
7994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
799544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(5, len);
7996b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  len = str->Write(wbuf);
799744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(5, len);
799844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, strcmp("abcde", buf));
7999b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  uint16_t answer1[] = {'a', 'b', 'c', 'd', 'e', '\0'};
800044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, StrCmp16(answer1, wbuf));
8001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  memset(buf, 0x1, sizeof(buf));
8003b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  memset(wbuf, 0x1, sizeof(wbuf));
8004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 4);
800544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(4, len);
8006b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  len = str->Write(wbuf, 0, 4);
800744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(4, len);
800844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, strncmp("abcd\1", buf, 5));
8009b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  uint16_t answer2[] = {'a', 'b', 'c', 'd', 0x101};
801044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, StrNCmp16(answer2, wbuf, 5));
8011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  memset(buf, 0x1, sizeof(buf));
8013b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  memset(wbuf, 0x1, sizeof(wbuf));
8014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 5);
801544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(5, len);
8016b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  len = str->Write(wbuf, 0, 5);
801744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(5, len);
801844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, strncmp("abcde\1", buf, 6));
8019b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  uint16_t answer3[] = {'a', 'b', 'c', 'd', 'e', 0x101};
802044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, StrNCmp16(answer3, wbuf, 6));
8021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  memset(buf, 0x1, sizeof(buf));
8023b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  memset(wbuf, 0x1, sizeof(wbuf));
8024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 6);
802544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(5, len);
8026b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  len = str->Write(wbuf, 0, 6);
802744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(5, len);
802844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, strcmp("abcde", buf));
8029b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  uint16_t answer4[] = {'a', 'b', 'c', 'd', 'e', '\0'};
803044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, StrCmp16(answer4, wbuf));
8031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  memset(buf, 0x1, sizeof(buf));
8033b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  memset(wbuf, 0x1, sizeof(wbuf));
8034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, -1);
803544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(1, len);
8036b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  len = str->Write(wbuf, 4, -1);
803744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(1, len);
803844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, strcmp("e", buf));
8039b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  uint16_t answer5[] = {'e', '\0'};
804044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, StrCmp16(answer5, wbuf));
8041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  memset(buf, 0x1, sizeof(buf));
8043b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  memset(wbuf, 0x1, sizeof(wbuf));
8044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, 6);
804544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(1, len);
8046b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  len = str->Write(wbuf, 4, 6);
804744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(1, len);
804844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, strcmp("e", buf));
804944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, StrCmp16(answer5, wbuf));
8050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  memset(buf, 0x1, sizeof(buf));
8052b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  memset(wbuf, 0x1, sizeof(wbuf));
8053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, 1);
805444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(1, len);
8055b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  len = str->Write(wbuf, 4, 1);
805644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(1, len);
805744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, strncmp("e\1", buf, 2));
8058b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  uint16_t answer6[] = {'e', 0x101};
805944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, StrNCmp16(answer6, wbuf, 2));
8060b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
8061b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  memset(buf, 0x1, sizeof(buf));
8062b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  memset(wbuf, 0x1, sizeof(wbuf));
8063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 3, 1);
806444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(1, len);
8065b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  len = str->Write(wbuf, 3, 1);
806644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(1, len);
806744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, strncmp("d\1", buf, 2));
8068b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  uint16_t answer7[] = {'d', 0x101};
806944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, StrNCmp16(answer7, wbuf, 2));
807069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
807169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  memset(wbuf, 0x1, sizeof(wbuf));
807269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  wbuf[5] = 'X';
807369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  len = str->Write(wbuf, 0, 6, String::NO_NULL_TERMINATION);
807469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK_EQ(5, len);
807569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK_EQ('X', wbuf[5]);
807669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  uint16_t answer8a[] = {'a', 'b', 'c', 'd', 'e'};
807769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  uint16_t answer8b[] = {'a', 'b', 'c', 'd', 'e', '\0'};
807869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK_EQ(0, StrNCmp16(answer8a, wbuf, 5));
807969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK_NE(0, StrCmp16(answer8b, wbuf));
808069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  wbuf[5] = '\0';
808169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK_EQ(0, StrCmp16(answer8b, wbuf));
808269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
808369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  memset(buf, 0x1, sizeof(buf));
808469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  buf[5] = 'X';
8085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf),
8086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          0,
8087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          6,
8088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          String::NO_NULL_TERMINATION);
808969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK_EQ(5, len);
809069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK_EQ('X', buf[5]);
809169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK_EQ(0, strncmp("abcde", buf, 5));
809269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK_NE(0, strcmp("abcde", buf));
809369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  buf[5] = '\0';
809469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK_EQ(0, strcmp("abcde", buf));
809569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
809669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  memset(utf8buf, 0x1, sizeof(utf8buf));
809769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  utf8buf[8] = 'X';
809869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen,
809969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                        String::NO_NULL_TERMINATION);
810069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK_EQ(8, len);
810169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK_EQ('X', utf8buf[8]);
810269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK_EQ(5, charlen);
810369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203", 8));
810469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK_NE(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
810569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  utf8buf[8] = '\0';
810669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
8107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  memset(utf8buf, 0x1, sizeof(utf8buf));
8109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  utf8buf[5] = 'X';
8110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  len = str->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen,
8111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        String::NO_NULL_TERMINATION);
8112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(5, len);
8113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ('X', utf8buf[5]);  // Test that the sixth character is untouched.
8114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(5, charlen);
8115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  utf8buf[5] = '\0';
8116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, strcmp(utf8buf, "abcde"));
8117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  memset(buf, 0x1, sizeof(buf));
8119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  len = str3->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
8120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(7, len);
8121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, strcmp("abc", buf));
8122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, buf[3]);
8123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, strcmp("def", buf + 4));
8124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
8125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, str->WriteOneByte(NULL, 0, 0, String::NO_NULL_TERMINATION));
8126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, str->WriteUtf8(NULL, 0, 0, String::NO_NULL_TERMINATION));
8127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, str->Write(NULL, 0, 0, String::NO_NULL_TERMINATION));
8128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
8129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
8130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
8131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void Utf16Helper(
8132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LocalContext& context,  // NOLINT
8133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const char* name,
81343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    const char* lengths_name,
81353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int len) {
81363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Local<v8::Array> a =
81373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Local<v8::Array>::Cast(context->Global()->Get(v8_str(name)));
81383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Local<v8::Array> alens =
81393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Local<v8::Array>::Cast(context->Global()->Get(v8_str(lengths_name)));
81403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < len; i++) {
81413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Local<v8::String> string =
81423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Local<v8::String>::Cast(a->Get(i));
81433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Local<v8::Number> expected_len =
81443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Local<v8::Number>::Cast(alens->Get(i));
81453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int length = GetUtf8Length(string);
81463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CHECK_EQ(static_cast<int>(expected_len->Value()), length);
81473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
81483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
81493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
81503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
81513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic uint16_t StringGet(Handle<String> str, int index) {
81523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  i::Handle<i::String> istring =
81533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      v8::Utils::OpenHandle(String::Cast(*str));
81543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return istring->Get(index);
81553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
81563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
81573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
81583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void WriteUtf8Helper(
8159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LocalContext& context,  // NOLINT
81603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    const char* name,
81613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    const char* lengths_name,
81623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int len) {
81633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Local<v8::Array> b =
81643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Local<v8::Array>::Cast(context->Global()->Get(v8_str(name)));
81653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Local<v8::Array> alens =
81663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Local<v8::Array>::Cast(context->Global()->Get(v8_str(lengths_name)));
81673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  char buffer[1000];
81683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  char buffer2[1000];
81693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < len; i++) {
81703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Local<v8::String> string =
81713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Local<v8::String>::Cast(b->Get(i));
81723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Local<v8::Number> expected_len =
81733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Local<v8::Number>::Cast(alens->Get(i));
81743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int utf8_length = static_cast<int>(expected_len->Value());
81753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    for (int j = utf8_length + 1; j >= 0; j--) {
81763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      memset(reinterpret_cast<void*>(&buffer), 42, sizeof(buffer));
81773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      memset(reinterpret_cast<void*>(&buffer2), 42, sizeof(buffer2));
81783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      int nchars;
81793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      int utf8_written =
81803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          string->WriteUtf8(buffer, j, &nchars, String::NO_OPTIONS);
81813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      int utf8_written2 =
81823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          string->WriteUtf8(buffer2, j, &nchars, String::NO_NULL_TERMINATION);
81833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CHECK_GE(utf8_length + 1, utf8_written);
81843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CHECK_GE(utf8_length, utf8_written2);
81853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      for (int k = 0; k < utf8_written2; k++) {
81863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        CHECK_EQ(buffer[k], buffer2[k]);
81873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
81883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CHECK(nchars * 3 >= utf8_written - 1);
81893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CHECK(nchars <= utf8_written);
81903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (j == utf8_length + 1) {
81913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        CHECK_EQ(utf8_written2, utf8_length);
81923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        CHECK_EQ(utf8_written2 + 1, utf8_written);
81933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
81943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CHECK_EQ(buffer[utf8_written], 42);
81953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (j > utf8_length) {
81963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (utf8_written != 0) CHECK_EQ(buffer[utf8_written - 1], 0);
81973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (utf8_written > 1) CHECK_NE(buffer[utf8_written - 2], 42);
81983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Handle<String> roundtrip = v8_str(buffer);
81993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        CHECK(roundtrip->Equals(string));
82003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
82013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (utf8_written != 0) CHECK_NE(buffer[utf8_written - 1], 42);
82023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
82033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (utf8_written2 != 0) CHECK_NE(buffer[utf8_written - 1], 42);
82043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (nchars >= 2) {
82053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        uint16_t trail = StringGet(string, nchars - 1);
82063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        uint16_t lead = StringGet(string, nchars - 2);
82073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (((lead & 0xfc00) == 0xd800) &&
82083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            ((trail & 0xfc00) == 0xdc00)) {
82093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          unsigned char u1 = buffer2[utf8_written2 - 4];
82103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          unsigned char u2 = buffer2[utf8_written2 - 3];
82113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          unsigned char u3 = buffer2[utf8_written2 - 2];
82123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          unsigned char u4 = buffer2[utf8_written2 - 1];
82133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          CHECK_EQ((u1 & 0xf8), 0xf0);
82143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          CHECK_EQ((u2 & 0xc0), 0x80);
82153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          CHECK_EQ((u3 & 0xc0), 0x80);
82163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          CHECK_EQ((u4 & 0xc0), 0x80);
82173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          uint32_t c = 0x10000 + ((lead & 0x3ff) << 10) + (trail & 0x3ff);
82183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          CHECK_EQ((u4 & 0x3f), (c & 0x3f));
82193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          CHECK_EQ((u3 & 0x3f), ((c >> 6) & 0x3f));
82203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          CHECK_EQ((u2 & 0x3f), ((c >> 12) & 0x3f));
82213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          CHECK_EQ((u1 & 0x3), c >> 18);
82223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
82233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
82243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
82253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
82263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
82273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
82283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
82293ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochTHREADED_TEST(Utf16) {
82303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LocalContext context;
8231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(context->GetIsolate());
82323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileRun(
82333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "var pad = '01234567890123456789';"
82343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "var p = [];"
82353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "var plens = [20, 3, 3];"
82363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "p.push('01234567890123456789');"
82373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "var lead = 0xd800;"
82383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "var trail = 0xdc00;"
82393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "p.push(String.fromCharCode(0xd800));"
82403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "p.push(String.fromCharCode(0xdc00));"
82413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "var a = [];"
82423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "var b = [];"
82433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "var c = [];"
82443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "var alens = [];"
82453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "for (var i = 0; i < 3; i++) {"
82463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "  p[1] = String.fromCharCode(lead++);"
82473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "  for (var j = 0; j < 3; j++) {"
82483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "    p[2] = String.fromCharCode(trail++);"
82493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "    a.push(p[i] + p[j]);"
82503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "    b.push(p[i] + p[j]);"
82513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "    c.push(p[i] + p[j]);"
82523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "    alens.push(plens[i] + plens[j]);"
82533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "  }"
82543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "}"
82553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "alens[5] -= 2;"  // Here the surrogate pairs match up.
82563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "var a2 = [];"
82573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "var b2 = [];"
82583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "var c2 = [];"
82593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "var a2lens = [];"
82603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "for (var m = 0; m < 9; m++) {"
82613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "  for (var n = 0; n < 9; n++) {"
82623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "    a2.push(a[m] + a[n]);"
82633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "    b2.push(b[m] + b[n]);"
82643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "    var newc = 'x' + c[m] + c[n] + 'y';"
82653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "    c2.push(newc.substring(1, newc.length - 1));"
82663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "    var utf = alens[m] + alens[n];"  // And here.
82673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           // The 'n's that start with 0xdc.. are 6-8
82683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           // The 'm's that end with 0xd8.. are 1, 4 and 7
82693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "    if ((m % 3) == 1 && n >= 6) utf -= 2;"
82703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "    a2lens.push(utf);"
82713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "  }"
82723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "}");
82733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Utf16Helper(context, "a", "alens", 9);
82743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Utf16Helper(context, "a2", "a2lens", 81);
82753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  WriteUtf8Helper(context, "b", "alens", 9);
82763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  WriteUtf8Helper(context, "b2", "a2lens", 81);
82773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  WriteUtf8Helper(context, "c2", "a2lens", 81);
82783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
82793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
82803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
82813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic bool SameSymbol(Handle<String> s1, Handle<String> s2) {
82823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  i::Handle<i::String> is1(v8::Utils::OpenHandle(*s1));
82833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  i::Handle<i::String> is2(v8::Utils::OpenHandle(*s2));
82843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return *is1 == *is2;
82853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
82863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void SameSymbolHelper(v8::Isolate* isolate, const char* a,
8288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             const char* b) {
8289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<String> symbol1 =
8290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(isolate, a, v8::String::kInternalizedString);
8291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<String> symbol2 =
8292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(isolate, b, v8::String::kInternalizedString);
82933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(SameSymbol(symbol1, symbol2));
82943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
82953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
82963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
82973ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochTHREADED_TEST(Utf16Symbol) {
82983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LocalContext context;
8299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(context->GetIsolate());
83003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<String> symbol1 = v8::String::NewFromUtf8(
8302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      context->GetIsolate(), "abc", v8::String::kInternalizedString);
8303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<String> symbol2 = v8::String::NewFromUtf8(
8304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      context->GetIsolate(), "abc", v8::String::kInternalizedString);
83053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(SameSymbol(symbol1, symbol2));
83063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SameSymbolHelper(context->GetIsolate(),
8308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   "\360\220\220\205",  // 4 byte encoding.
83093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   "\355\240\201\355\260\205");  // 2 3-byte surrogates.
8310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SameSymbolHelper(context->GetIsolate(),
8311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   "\355\240\201\355\260\206",  // 2 3-byte surrogates.
83123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   "\360\220\220\206");  // 4 byte encoding.
8313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SameSymbolHelper(context->GetIsolate(),
8314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   "x\360\220\220\205",  // 4 byte encoding.
83153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   "x\355\240\201\355\260\205");  // 2 3-byte surrogates.
8316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SameSymbolHelper(context->GetIsolate(),
8317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   "x\355\240\201\355\260\206",  // 2 3-byte surrogates.
83183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   "x\360\220\220\206");  // 4 byte encoding.
83193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileRun(
83203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "var sym0 = 'benedictus';"
83213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "var sym0b = 'S\303\270ren';"
83223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "var sym1 = '\355\240\201\355\260\207';"
83233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "var sym2 = '\360\220\220\210';"
83243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "var sym3 = 'x\355\240\201\355\260\207';"
83253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "var sym4 = 'x\360\220\220\210';"
83263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "if (sym1.length != 2) throw sym1;"
83273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "if (sym1.charCodeAt(1) != 0xdc07) throw sym1.charCodeAt(1);"
83283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "if (sym2.length != 2) throw sym2;"
83293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "if (sym2.charCodeAt(1) != 0xdc08) throw sym2.charCodeAt(2);"
83303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "if (sym3.length != 3) throw sym3;"
83313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "if (sym3.charCodeAt(2) != 0xdc07) throw sym1.charCodeAt(2);"
83323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "if (sym4.length != 3) throw sym4;"
83333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "if (sym4.charCodeAt(2) != 0xdc08) throw sym2.charCodeAt(2);");
8334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<String> sym0 = v8::String::NewFromUtf8(
8335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      context->GetIsolate(), "benedictus", v8::String::kInternalizedString);
8336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<String> sym0b = v8::String::NewFromUtf8(
8337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      context->GetIsolate(), "S\303\270ren", v8::String::kInternalizedString);
8338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<String> sym1 =
8339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(context->GetIsolate(), "\355\240\201\355\260\207",
8340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              v8::String::kInternalizedString);
8341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<String> sym2 =
8342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(context->GetIsolate(), "\360\220\220\210",
8343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              v8::String::kInternalizedString);
8344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<String> sym3 = v8::String::NewFromUtf8(
8345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      context->GetIsolate(), "x\355\240\201\355\260\207",
8346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::kInternalizedString);
8347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<String> sym4 =
8348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(context->GetIsolate(), "x\360\220\220\210",
8349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              v8::String::kInternalizedString);
83503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::Local<v8::Object> global = context->Global();
83513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Local<Value> s0 = global->Get(v8_str("sym0"));
83523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Local<Value> s0b = global->Get(v8_str("sym0b"));
83533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Local<Value> s1 = global->Get(v8_str("sym1"));
83543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Local<Value> s2 = global->Get(v8_str("sym2"));
83553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Local<Value> s3 = global->Get(v8_str("sym3"));
83563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Local<Value> s4 = global->Get(v8_str("sym4"));
8357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(SameSymbol(sym0, Handle<String>::Cast(s0)));
8358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(SameSymbol(sym0b, Handle<String>::Cast(s0b)));
8359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(SameSymbol(sym1, Handle<String>::Cast(s1)));
8360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(SameSymbol(sym2, Handle<String>::Cast(s2)));
8361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(SameSymbol(sym3, Handle<String>::Cast(s3)));
8362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(SameSymbol(sym4, Handle<String>::Cast(s4)));
83633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
83643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
83653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(ToArrayIndex) {
8367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
8368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
8369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
8370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<String> str = v8_str("42");
8372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Uint32> index = str->ToArrayIndex();
8373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(!index.IsEmpty());
8374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(42.0, index->Uint32Value());
8375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  str = v8_str("42asdf");
8376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  index = str->ToArrayIndex();
8377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(index.IsEmpty());
8378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  str = v8_str("-42");
8379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  index = str->ToArrayIndex();
8380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(index.IsEmpty());
8381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  str = v8_str("4294967295");
8382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  index = str->ToArrayIndex();
8383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(!index.IsEmpty());
8384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(4294967295.0, index->Uint32Value());
8385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Number> num = v8::Number::New(isolate, 1);
8386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  index = num->ToArrayIndex();
8387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(!index.IsEmpty());
8388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1.0, index->Uint32Value());
8389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  num = v8::Number::New(isolate, -1);
8390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  index = num->ToArrayIndex();
8391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(index.IsEmpty());
8392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Object> obj = v8::Object::New(isolate);
8393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  index = obj->ToArrayIndex();
8394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(index.IsEmpty());
8395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
8396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(ErrorConstruction) {
8399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
8400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(context->GetIsolate());
8401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<String> foo = v8_str("foo");
8403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<String> message = v8_str("message");
8404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> range_error = v8::Exception::RangeError(foo);
8405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(range_error->IsObject());
84066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(range_error.As<v8::Object>()->Get(message)->Equals(foo));
8407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> reference_error = v8::Exception::ReferenceError(foo);
8408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(reference_error->IsObject());
84096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(reference_error.As<v8::Object>()->Get(message)->Equals(foo));
8410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> syntax_error = v8::Exception::SyntaxError(foo);
8411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(syntax_error->IsObject());
84126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(syntax_error.As<v8::Object>()->Get(message)->Equals(foo));
8413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> type_error = v8::Exception::TypeError(foo);
8414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(type_error->IsObject());
84156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(type_error.As<v8::Object>()->Get(message)->Equals(foo));
8416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> error = v8::Exception::Error(foo);
8417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(error->IsObject());
84186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(error.As<v8::Object>()->Get(message)->Equals(foo));
8419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
8420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void YGetter(Local<String> name,
8423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                    const v8::PropertyCallbackInfo<v8::Value>& info) {
8424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
8425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(v8_num(10));
8426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
8427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void YSetter(Local<String> name,
8430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Local<Value> value,
8431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                    const v8::PropertyCallbackInfo<void>& info) {
8432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Object> this_obj = Local<Object>::Cast(info.This());
8433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (this_obj->Has(name)) this_obj->Delete(name);
8434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  this_obj->Set(name, value);
8435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
8436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(DeleteAccessor) {
8439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
8440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
8441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
8442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  obj->SetAccessor(v8_str("y"), YGetter, YSetter);
8443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
8444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Object> holder = obj->NewInstance();
8445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context->Global()->Set(v8_str("holder"), holder);
8446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> result = CompileRun(
8447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "holder.y = 11; holder.y = 12; holder.y");
8448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(12, result->Uint32Value());
8449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
8450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(TypeSwitch) {
8453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
8454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
8455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::FunctionTemplate> templ1 = v8::FunctionTemplate::New(isolate);
8456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::FunctionTemplate> templ2 = v8::FunctionTemplate::New(isolate);
8457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::FunctionTemplate> templ3 = v8::FunctionTemplate::New(isolate);
8458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::FunctionTemplate> templs[3] = { templ1, templ2, templ3 };
8459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::TypeSwitch> type_switch = v8::TypeSwitch::New(3, templs);
8460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
8461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Object> obj0 = v8::Object::New(isolate);
8462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Object> obj1 = templ1->GetFunction()->NewInstance();
8463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Object> obj2 = templ2->GetFunction()->NewInstance();
8464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Object> obj3 = templ3->GetFunction()->NewInstance();
8465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < 10; i++) {
8466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(0, type_switch->match(obj0));
8467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(1, type_switch->match(obj1));
8468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(2, type_switch->match(obj2));
8469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(3, type_switch->match(obj3));
8470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(3, type_switch->match(obj3));
8471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(2, type_switch->match(obj2));
8472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(1, type_switch->match(obj1));
8473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(0, type_switch->match(obj0));
8474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
8475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
8476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic int trouble_nesting = 0;
8479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void TroubleCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
8480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
8481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  trouble_nesting++;
8482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call a JS function that throws an uncaught exception.
8484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::Object> arg_this =
8485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      args.GetIsolate()->GetCurrentContext()->Global();
8486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Value> trouble_callee = (trouble_nesting == 3) ?
8487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arg_this->Get(v8_str("trouble_callee")) :
8488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arg_this->Get(v8_str("trouble_caller"));
8489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(trouble_callee->IsFunction());
8490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  args.GetReturnValue().Set(
8491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Function::Cast(*trouble_callee)->Call(arg_this, 0, NULL));
8492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
8493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic int report_count = 0;
8496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void ApiUncaughtExceptionTestListener(v8::Handle<v8::Message>,
8497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             v8::Handle<Value>) {
8498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  report_count++;
8499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
8500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Counts uncaught exceptions, but other tests running in parallel
8503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// also have uncaught exceptions.
8504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(ApiUncaughtException) {
8505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  report_count = 0;
8506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext env;
8507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
8508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
8509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::V8::AddMessageListener(ApiUncaughtExceptionTestListener);
8510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::FunctionTemplate> fun =
8512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::FunctionTemplate::New(isolate, TroubleCallback);
8513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Local<v8::Object> global = env->Global();
8514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  global->Set(v8_str("trouble"), fun->GetFunction());
8515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun(
8517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "function trouble_callee() {"
8518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  var x = null;"
8519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  return x.foo;"
8520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "};"
8521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "function trouble_caller() {"
8522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  trouble();"
8523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "};");
8524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Value> trouble = global->Get(v8_str("trouble"));
8525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(trouble->IsFunction());
8526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Value> trouble_callee = global->Get(v8_str("trouble_callee"));
8527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(trouble_callee->IsFunction());
8528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Value> trouble_caller = global->Get(v8_str("trouble_caller"));
8529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(trouble_caller->IsFunction());
8530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Function::Cast(*trouble_caller)->Call(global, 0, NULL);
8531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, report_count);
8532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::V8::RemoveMessageListeners(ApiUncaughtExceptionTestListener);
8533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
8534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
85354515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkestatic const char* script_resource_name = "ExceptionInNativeScript.js";
85364515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkestatic void ExceptionInNativeScriptTestListener(v8::Handle<v8::Message> message,
85374515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke                                                v8::Handle<Value>) {
8538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Value> name_val = message->GetScriptOrigin().ResourceName();
85394515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  CHECK(!name_val.IsEmpty() && name_val->IsString());
8540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::String::Utf8Value name(message->GetScriptOrigin().ResourceName());
85414515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  CHECK_EQ(script_resource_name, *name);
85424515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  CHECK_EQ(3, message->GetLineNumber());
8543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::String::Utf8Value source_line(message->GetSourceLine());
85444515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  CHECK_EQ("  new o.foo();", *source_line);
85454515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke}
85464515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
8547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
85484515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeTEST(ExceptionInNativeScript) {
85494515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  LocalContext env;
8550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
8551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
85524515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  v8::V8::AddMessageListener(ExceptionInNativeScriptTestListener);
85534515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
8554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::FunctionTemplate> fun =
8555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::FunctionTemplate::New(isolate, TroubleCallback);
85564515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  v8::Local<v8::Object> global = env->Global();
85574515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  global->Set(v8_str("trouble"), fun->GetFunction());
85584515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
8559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRunWithOrigin(
8560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "function trouble() {\n"
8561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  var o = {};\n"
8562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  new o.foo();\n"
8563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "};",
8564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      script_resource_name);
85654515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  Local<Value> trouble = global->Get(v8_str("trouble"));
85664515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  CHECK(trouble->IsFunction());
85674515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  Function::Cast(*trouble)->Call(global, 0, NULL);
85684515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  v8::V8::RemoveMessageListeners(ExceptionInNativeScriptTestListener);
85694515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke}
85704515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
8571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(CompilationErrorUsingTryCatchHandler) {
8573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext env;
8574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
8575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::TryCatch try_catch;
8576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8_compile("This doesn't &*&@#$&*^ compile.");
8577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_NE(NULL, *try_catch.Exception());
8578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(try_catch.HasCaught());
8579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
8580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(TryCatchFinallyUsingTryCatchHandler) {
8583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext env;
8584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
8585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::TryCatch try_catch;
8586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("try { throw ''; } catch (e) {}");
8587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(!try_catch.HasCaught());
8588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("try { throw ''; } finally {}");
8589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(try_catch.HasCaught());
8590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  try_catch.Reset();
8591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun(
8592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "(function() {"
8593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "try { throw ''; } finally { return; }"
8594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "})()");
8595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(!try_catch.HasCaught());
8596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun(
8597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "(function()"
8598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  { try { throw ''; } finally { throw 0; }"
8599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "})()");
8600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(try_catch.HasCaught());
8601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
8602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
8603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
8604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CEvaluate(const v8::FunctionCallbackInfo<v8::Value>& args) {
8605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(args.GetIsolate());
8606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun(args[0]->ToString());
8607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
8608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
8609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
8610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(TryCatchFinallyStoresMessageUsingTryCatchHandler) {
8611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
8612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
8613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
8614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  templ->Set(v8_str("CEvaluate"),
8615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             v8::FunctionTemplate::New(isolate, CEvaluate));
8616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context(0, templ);
8617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::TryCatch try_catch;
8618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("try {"
8619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "  CEvaluate('throw 1;');"
8620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "} finally {"
8621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "}");
8622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(try_catch.HasCaught());
8623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!try_catch.Message().IsEmpty());
8624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  String::Utf8Value exception_value(try_catch.Exception());
8625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(*exception_value, "1");
8626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  try_catch.Reset();
8627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("try {"
8628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "  CEvaluate('throw 1;');"
8629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "} finally {"
8630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "  throw 2;"
8631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "}");
8632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(try_catch.HasCaught());
8633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!try_catch.Message().IsEmpty());
8634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  String::Utf8Value finally_exception_value(try_catch.Exception());
8635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(*finally_exception_value, "2");
8636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
8637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
8638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
8639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// For use within the TestSecurityHandler() test.
8640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic bool g_security_callback_result = false;
8641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic bool NamedSecurityTestCallback(Local<v8::Object> global,
8642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                      Local<Value> name,
8643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                      v8::AccessType type,
8644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                      Local<Value> data) {
8645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  printf("a\n");
8646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Always allow read access.
8647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (type == v8::ACCESS_GET)
8648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return true;
8649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
8650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Sometimes allow other access.
8651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return g_security_callback_result;
8652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
8653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
8654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
8655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic bool IndexedSecurityTestCallback(Local<v8::Object> global,
8656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        uint32_t key,
8657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        v8::AccessType type,
8658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        Local<Value> data) {
8659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  printf("b\n");
8660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Always allow read access.
8661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (type == v8::ACCESS_GET)
8662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return true;
8663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
8664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Sometimes allow other access.
8665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return g_security_callback_result;
8666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
8667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SecurityHandler can't be run twice
8670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(SecurityHandler) {
8671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
8672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope0(isolate);
8673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> global_template =
8674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::ObjectTemplate::New(isolate);
8675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  global_template->SetAccessCheckCallbacks(NamedSecurityTestCallback,
8676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           IndexedSecurityTestCallback);
8677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create an environment
8678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<Context> context0 = Context::New(isolate, NULL, global_template);
8679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context0->Enter();
8680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Object> global0 = context0->Global();
8682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Script> script0 = v8_compile("foo = 111");
8683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  script0->Run();
8684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  global0->Set(v8_str("0"), v8_num(999));
8685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> foo0 = global0->Get(v8_str("foo"));
8686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(111, foo0->Int32Value());
8687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> z0 = global0->Get(v8_str("0"));
8688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(999, z0->Int32Value());
8689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create another environment, should fail security checks.
8691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope1(isolate);
8692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<Context> context1 =
8694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Context::New(isolate, NULL, global_template);
8695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context1->Enter();
8696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Object> global1 = context1->Global();
8698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  global1->Set(v8_str("othercontext"), global0);
8699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // This set will fail the security check.
8700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Script> script1 =
8701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    v8_compile("othercontext.foo = 222; othercontext[0] = 888;");
8702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  script1->Run();
8703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // This read will pass the security check.
8704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> foo1 = global0->Get(v8_str("foo"));
8705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(111, foo1->Int32Value());
8706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // This read will pass the security check.
8707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> z1 = global0->Get(v8_str("0"));
8708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(999, z1->Int32Value());
8709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create another environment, should pass security checks.
8711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { g_security_callback_result = true;  // allow security handler to pass.
8712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope2(isolate);
8713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    LocalContext context2;
8714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    v8::Handle<v8::Object> global2 = context2->Global();
8715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    global2->Set(v8_str("othercontext"), global0);
8716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    v8::Handle<Script> script2 =
8717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        v8_compile("othercontext.foo = 333; othercontext[0] = 888;");
8718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    script2->Run();
8719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    v8::Handle<Value> foo2 = global0->Get(v8_str("foo"));
8720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(333, foo2->Int32Value());
8721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    v8::Handle<Value> z2 = global0->Get(v8_str("0"));
8722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(888, z2->Int32Value());
8723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
8724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context1->Exit();
8726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context0->Exit();
8727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
8728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(SecurityChecks) {
8731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext env1;
8732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(env1->GetIsolate());
8733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
8734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Value> foo = v8_str("foo");
8736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Value> bar = v8_str("bar");
8737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set to the same domain.
8739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env1->SetSecurityToken(foo);
8740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create a function in env1.
8742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("spy=function(){return spy;}");
8743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Value> spy = env1->Global()->Get(v8_str("spy"));
8744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(spy->IsFunction());
8745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create another function accessing global objects.
8747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("spy2=function(){return new this.Array();}");
8748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Value> spy2 = env1->Global()->Get(v8_str("spy2"));
8749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(spy2->IsFunction());
8750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Switch to env2 in the same domain and invoke spy on env2.
8752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {
8753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    env2->SetSecurityToken(foo);
8754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Enter env2
8755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Context::Scope scope_env2(env2);
8756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Local<Value> result = Function::Cast(*spy)->Call(env2->Global(), 0, NULL);
8757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK(result->IsFunction());
8758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
8759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {
8761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    env2->SetSecurityToken(bar);
8762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Context::Scope scope_env2(env2);
8763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Call cross_domain_call, it should throw an exception
8765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    v8::TryCatch try_catch;
8766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Function::Cast(*spy2)->Call(env2->Global(), 0, NULL);
8767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK(try_catch.HasCaught());
8768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
8769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
8770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Regression test case for issue 1183439.
8773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(SecurityChecksForPrototypeChain) {
8774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext current;
8775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(current->GetIsolate());
8776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<Context> other = Context::New(current->GetIsolate());
8777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Change context to be able to get to the Object function in the
8779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // other context without hitting the security checks.
8780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Local<Value> other_object;
8781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { Context::Scope scope(other);
8782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    other_object = other->Global()->Get(v8_str("Object"));
8783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    other->Global()->Set(v8_num(42), v8_num(87));
8784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
8785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  current->Global()->Set(v8_str("other"), other->Global());
8787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(v8_compile("other")->Run()->Equals(other->Global()));
8788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make sure the security check fails here and we get an undefined
8790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // result instead of getting the Object function. Repeat in a loop
8791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // to make sure to exercise the IC code.
8792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Local<Script> access_other0 = v8_compile("other.Object");
8793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Local<Script> access_other1 = v8_compile("other[42]");
8794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < 5; i++) {
8795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(access_other0->Run().IsEmpty());
8796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(access_other1->Run().IsEmpty());
8797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
8798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create an object that has 'other' in its prototype chain and make
8800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sure we cannot access the Object function indirectly through
8801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // that. Repeat in a loop to make sure to exercise the IC code.
8802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8_compile("function F() { };"
8803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block             "F.prototype = other;"
8804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block             "var f = new F();")->Run();
8805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Local<Script> access_f0 = v8_compile("f.Object");
8806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Local<Script> access_f1 = v8_compile("f[42]");
8807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int j = 0; j < 5; j++) {
8808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(access_f0->Run().IsEmpty());
8809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(access_f1->Run().IsEmpty());
8810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
8811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Now it gets hairy: Set the prototype for the other global object
8813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // to be the current global object. The prototype chain for 'f' now
8814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // goes through 'other' but ends up in the current global object.
8815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { Context::Scope scope(other);
8816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    other->Global()->Set(v8_str("__proto__"), current->Global());
8817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
8818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set a named and an index property on the current global
8819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // object. To force the lookup to go through the other global object,
8820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the properties must not exist in the other global object.
8821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  current->Global()->Set(v8_str("foo"), v8_num(100));
8822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  current->Global()->Set(v8_num(99), v8_num(101));
8823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Try to read the properties from f and make sure that the access
8824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // gets stopped by the security checks on the other global object.
8825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Script> access_f2 = v8_compile("f.foo");
8826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Script> access_f3 = v8_compile("f[99]");
8827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int k = 0; k < 5; k++) {
8828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(access_f2->Run().IsEmpty());
8829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(access_f3->Run().IsEmpty());
8830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
8831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
8832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
8833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
8834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic bool named_security_check_with_gc_called;
8835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
8836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic bool NamedSecurityCallbackWithGC(Local<v8::Object> global,
8837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        Local<Value> name,
8838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        v8::AccessType type,
8839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        Local<Value> data) {
8840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
8841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  named_security_check_with_gc_called = true;
8842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return true;
8843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
8844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
8845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
8846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic bool indexed_security_check_with_gc_called;
8847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
8848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic bool IndexedSecurityTestCallbackWithGC(Local<v8::Object> global,
8849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              uint32_t key,
8850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              v8::AccessType type,
8851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              Local<Value> data) {
8852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
8853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  indexed_security_check_with_gc_called = true;
8854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return true;
8855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
8856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
8857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
8858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(SecurityTestGCAllowed) {
8859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
8860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(isolate);
8861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> object_template =
8862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::ObjectTemplate::New(isolate);
8863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  object_template->SetAccessCheckCallbacks(NamedSecurityCallbackWithGC,
8864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           IndexedSecurityTestCallbackWithGC);
8865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
8866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<Context> context = Context::New(isolate);
8867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Context::Scope context_scope(context);
8868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
8869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context->Global()->Set(v8_str("obj"), object_template->NewInstance());
8870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
8871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  named_security_check_with_gc_called = false;
8872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("obj.foo = new String(1001);");
8873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(named_security_check_with_gc_called);
8874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
8875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  indexed_security_check_with_gc_called = false;
8876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("obj[0] = new String(1002);");
8877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(indexed_security_check_with_gc_called);
8878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
8879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  named_security_check_with_gc_called = false;
8880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(CompileRun("obj.foo")->ToString()->Equals(v8_str("1001")));
8881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(named_security_check_with_gc_called);
8882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
8883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  indexed_security_check_with_gc_called = false;
8884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(CompileRun("obj[0]")->ToString()->Equals(v8_str("1002")));
8885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(indexed_security_check_with_gc_called);
8886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
8887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(CrossDomainDelete) {
8890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext env1;
8891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(env1->GetIsolate());
8892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
8893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Value> foo = v8_str("foo");
8895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Value> bar = v8_str("bar");
8896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set to the same domain.
8898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env1->SetSecurityToken(foo);
8899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env2->SetSecurityToken(foo);
8900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env1->Global()->Set(v8_str("prop"), v8_num(3));
8902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env2->Global()->Set(v8_str("env1"), env1->Global());
8903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Change env2 to a different domain and delete env1.prop.
8905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env2->SetSecurityToken(bar);
8906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {
8907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Context::Scope scope_env2(env2);
8908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Local<Value> result =
8909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        CompileRun("delete env1.prop");
8910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(result.IsEmpty());
8911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
8912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that env1.prop still exists.
8914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Value> v = env1->Global()->Get(v8_str("prop"));
8915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(v->IsNumber());
8916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(3, v->Int32Value());
8917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
8918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(CrossDomainIsPropertyEnumerable) {
8921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext env1;
8922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(env1->GetIsolate());
8923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
8924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Value> foo = v8_str("foo");
8926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Value> bar = v8_str("bar");
8927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set to the same domain.
8929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env1->SetSecurityToken(foo);
8930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env2->SetSecurityToken(foo);
8931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env1->Global()->Set(v8_str("prop"), v8_num(3));
8933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env2->Global()->Set(v8_str("env1"), env1->Global());
8934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // env1.prop is enumerable in env2.
8936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<String> test = v8_str("propertyIsEnumerable.call(env1, 'prop')");
8937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {
8938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Context::Scope scope_env2(env2);
8939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<Value> result = CompileRun(test);
8940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK(result->IsTrue());
8941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
8942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Change env2 to a different domain and test again.
8944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env2->SetSecurityToken(bar);
8945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {
8946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Context::Scope scope_env2(env2);
8947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<Value> result = CompileRun(test);
8948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(result.IsEmpty());
8949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
8950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
8951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(CrossDomainForIn) {
8954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext env1;
8955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(env1->GetIsolate());
8956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
8957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Value> foo = v8_str("foo");
8959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Value> bar = v8_str("bar");
8960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set to the same domain.
8962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env1->SetSecurityToken(foo);
8963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env2->SetSecurityToken(foo);
8964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env1->Global()->Set(v8_str("prop"), v8_num(3));
8966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env2->Global()->Set(v8_str("env1"), env1->Global());
8967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Change env2 to a different domain and set env1's global object
8969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // as the __proto__ of an object in env2 and enumerate properties
8970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // in for-in. It shouldn't enumerate properties on env1's global
8971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // object.
8972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env2->SetSecurityToken(bar);
8973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {
8974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Context::Scope scope_env2(env2);
8975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<Value> result = CompileRun(
8976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "(function() {"
8977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "  var obj = { '__proto__': env1 };"
8978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "  try {"
8979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "    for (var p in obj) {"
8980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "      if (p == 'prop') return false;"
8981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "    }"
8982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "    return false;"
8983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "  } catch (e) {"
8984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "    return true;"
8985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "  }"
8986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "})()");
8987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK(result->IsTrue());
8988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
8989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
8990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(ContextDetachGlobal) {
8993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext env1;
8994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(env1->GetIsolate());
8995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
8996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<v8::Object> global1 = env1->Global();
8998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Value> foo = v8_str("foo");
9000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set to the same domain.
9002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env1->SetSecurityToken(foo);
9003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env2->SetSecurityToken(foo);
9004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Enter env2
9006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env2->Enter();
9007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
900874b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu  // Create a function in env2 and add a reference to it in env1.
9009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<v8::Object> global2 = env2->Global();
9010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  global2->Set(v8_str("prop"), v8::Integer::New(env2->GetIsolate(), 1));
9011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CompileRun("function getProp() {return prop;}");
9012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env1->Global()->Set(v8_str("getProp"),
9014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      global2->Get(v8_str("getProp")));
9015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
901674b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu  // Detach env2's global, and reuse the global object of env2
9017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env2->Exit();
9018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env2->DetachGlobal();
9019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<Context> env3 = Context::New(env1->GetIsolate(),
9021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                          0,
9022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                          v8::Handle<v8::ObjectTemplate>(),
9023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                          global2);
9024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env3->SetSecurityToken(v8_str("bar"));
9025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env3->Enter();
9026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<v8::Object> global3 = env3->Global();
9028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(global2, global3);
9029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(global3->Get(v8_str("prop"))->IsUndefined());
9030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(global3->Get(v8_str("getProp"))->IsUndefined());
9031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  global3->Set(v8_str("prop"), v8::Integer::New(env3->GetIsolate(), -1));
9032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  global3->Set(v8_str("prop2"), v8::Integer::New(env3->GetIsolate(), 2));
9033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env3->Exit();
9034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call getProp in env1, and it should return the value 1
9036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {
9037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Local<Value> get_prop = global1->Get(v8_str("getProp"));
9038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK(get_prop->IsFunction());
9039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    v8::TryCatch try_catch;
9040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Local<Value> r = Function::Cast(*get_prop)->Call(global1, 0, NULL);
9041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK(!try_catch.HasCaught());
9042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(1, r->Int32Value());
9043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
9044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that env3 is not accessible from env1
9046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {
9047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Local<Value> r = global3->Get(v8_str("prop2"));
9048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(r.IsEmpty());
9049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
9050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
9051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(DetachGlobal) {
905474b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu  LocalContext env1;
9055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env1->GetIsolate());
905674b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu
905774b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu  // Create second environment.
9058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
905974b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu
906074b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu  Local<Value> foo = v8_str("foo");
906174b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu
906274b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu  // Set same security token for env1 and env2.
906374b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu  env1->SetSecurityToken(foo);
906474b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu  env2->SetSecurityToken(foo);
906574b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu
906674b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu  // Create a property on the global object in env2.
906774b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu  {
906874b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu    v8::Context::Scope scope(env2);
9069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    env2->Global()->Set(v8_str("p"), v8::Integer::New(env2->GetIsolate(), 42));
907074b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu  }
907174b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu
907274b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu  // Create a reference to env2 global from env1 global.
907374b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu  env1->Global()->Set(v8_str("other"), env2->Global());
907474b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu
907574b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu  // Check that we have access to other.p in env2 from env1.
907674b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu  Local<Value> result = CompileRun("other.p");
907774b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu  CHECK(result->IsInt32());
907874b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu  CHECK_EQ(42, result->Int32Value());
907974b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu
908074b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu  // Hold on to global from env2 and detach global from env2.
908174b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu  Local<v8::Object> global2 = env2->Global();
908274b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu  env2->DetachGlobal();
908374b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu
908474b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu  // Check that the global has been detached. No other.p property can
908574b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu  // be found.
908674b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu  result = CompileRun("other.p");
9087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(result.IsEmpty());
908874b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu
908974b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu  // Reuse global2 for env3.
9090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<Context> env3 = Context::New(env1->GetIsolate(),
9091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                          0,
9092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                          v8::Handle<v8::ObjectTemplate>(),
9093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                          global2);
909474b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu  CHECK_EQ(global2, env3->Global());
909574b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu
909674b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu  // Start by using the same security token for env3 as for env1 and env2.
909774b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu  env3->SetSecurityToken(foo);
909874b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu
909974b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu  // Create a property on the global object in env3.
910074b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu  {
910174b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu    v8::Context::Scope scope(env3);
9102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    env3->Global()->Set(v8_str("p"), v8::Integer::New(env3->GetIsolate(), 24));
910374b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu  }
910474b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu
910574b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu  // Check that other.p is now the property in env3 and that we have access.
910674b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu  result = CompileRun("other.p");
910774b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu  CHECK(result->IsInt32());
910874b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu  CHECK_EQ(24, result->Int32Value());
910974b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu
911074b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu  // Change security token for env3 to something different from env1 and env2.
911174b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu  env3->SetSecurityToken(v8_str("bar"));
911274b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu
911374b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu  // Check that we do not have access to other.p in env1. |other| is now
911474b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu  // the global object for env3 which has a different security token,
911574b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu  // so access should be blocked.
911674b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu  result = CompileRun("other.p");
9117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(result.IsEmpty());
9118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
911974b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu
912074b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu
9121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid GetThisX(const v8::FunctionCallbackInfo<v8::Value>& info) {
9122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(
9123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      info.GetIsolate()->GetCurrentContext()->Global()->Get(v8_str("x")));
9124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
9125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
9126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
9127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(DetachedAccesses) {
9128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env1;
9129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env1->GetIsolate());
9130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
9131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Create second environment.
9132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> inner_global_template =
9133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      FunctionTemplate::New(env1->GetIsolate())->InstanceTemplate();
9134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inner_global_template ->SetAccessorProperty(
9135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8_str("this_x"), FunctionTemplate::New(env1->GetIsolate(), GetThisX));
9136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<Context> env2 =
9137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Context::New(env1->GetIsolate(), NULL, inner_global_template);
913874b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu
9139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Value> foo = v8_str("foo");
9140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
9141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Set same security token for env1 and env2.
9142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env1->SetSecurityToken(foo);
9143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env2->SetSecurityToken(foo);
9144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
9145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env1->Global()->Set(v8_str("x"), v8_str("env1_x"));
9146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
9147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
9148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Context::Scope scope(env2);
9149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    env2->Global()->Set(v8_str("x"), v8_str("env2_x"));
9150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CompileRun(
9151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "function bound_x() { return x; }"
9152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "function get_x()   { return this.x; }"
9153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "function get_x_w() { return (function() {return this.x;})(); }");
9154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    env1->Global()->Set(v8_str("bound_x"), CompileRun("bound_x"));
9155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    env1->Global()->Set(v8_str("get_x"), CompileRun("get_x"));
9156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    env1->Global()->Set(v8_str("get_x_w"), CompileRun("get_x_w"));
9157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    env1->Global()->Set(
9158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v8_str("this_x"),
9159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        CompileRun("Object.getOwnPropertyDescriptor(this, 'this_x').get"));
9160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
9161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
9162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Object> env2_global = env2->Global();
9163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env2_global->TurnOnAccessCheck();
9164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env2->DetachGlobal();
9165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
9166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Value> result;
9167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  result = CompileRun("bound_x()");
9168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(v8_str("env2_x"), result);
9169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  result = CompileRun("get_x()");
9170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(result.IsEmpty());
9171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  result = CompileRun("get_x_w()");
9172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(result.IsEmpty());
9173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  result = CompileRun("this_x()");
9174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(v8_str("env2_x"), result);
9175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
9176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Reattach env2's proxy
9177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env2 = Context::New(env1->GetIsolate(),
9178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      0,
9179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      v8::Handle<v8::ObjectTemplate>(),
9180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      env2_global);
9181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env2->SetSecurityToken(foo);
9182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
9183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Context::Scope scope(env2);
9184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    env2->Global()->Set(v8_str("x"), v8_str("env3_x"));
9185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    env2->Global()->Set(v8_str("env1"), env1->Global());
9186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    result = CompileRun(
9187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "results = [];"
9188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "for (var i = 0; i < 4; i++ ) {"
9189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "  results.push(env1.bound_x());"
9190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "  results.push(env1.get_x());"
9191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "  results.push(env1.get_x_w());"
9192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "  results.push(env1.this_x());"
9193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "}"
9194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "results");
9195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<v8::Array> results = Local<v8::Array>::Cast(result);
9196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(16, results->Length());
9197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int i = 0; i < 16; i += 4) {
9198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CHECK_EQ(v8_str("env2_x"), results->Get(i + 0));
9199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CHECK_EQ(v8_str("env1_x"), results->Get(i + 1));
9200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CHECK_EQ(v8_str("env3_x"), results->Get(i + 2));
9201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CHECK_EQ(v8_str("env2_x"), results->Get(i + 3));
9202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
9203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
9204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
9205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  result = CompileRun(
9206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "results = [];"
9207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "for (var i = 0; i < 4; i++ ) {"
9208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  results.push(bound_x());"
9209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  results.push(get_x());"
9210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  results.push(get_x_w());"
9211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  results.push(this_x());"
9212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "}"
9213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "results");
9214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::Array> results = Local<v8::Array>::Cast(result);
9215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(16, results->Length());
9216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < 16; i += 4) {
9217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(v8_str("env2_x"), results->Get(i + 0));
9218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(v8_str("env3_x"), results->Get(i + 1));
9219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(v8_str("env3_x"), results->Get(i + 2));
9220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(v8_str("env2_x"), results->Get(i + 3));
9221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
9222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
9223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  result = CompileRun(
9224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "results = [];"
9225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "for (var i = 0; i < 4; i++ ) {"
9226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  results.push(this.bound_x());"
9227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  results.push(this.get_x());"
9228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  results.push(this.get_x_w());"
9229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  results.push(this.this_x());"
9230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "}"
9231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "results");
9232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  results = Local<v8::Array>::Cast(result);
9233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(16, results->Length());
9234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < 16; i += 4) {
9235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(v8_str("env2_x"), results->Get(i + 0));
9236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(v8_str("env1_x"), results->Get(i + 1));
9237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(v8_str("env3_x"), results->Get(i + 2));
9238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(v8_str("env2_x"), results->Get(i + 3));
9239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
924074b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu}
924174b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu
924274b3c146906ea120f97974b0e16aec75c17ebf66Andrei Popescu
92431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockstatic bool allowed_access_type[v8::ACCESS_KEYS + 1] = { false };
9244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic bool NamedAccessBlocker(Local<v8::Object> global,
9245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                               Local<Value> name,
9246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                               v8::AccessType type,
9247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                               Local<Value> data) {
9248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return CcTest::isolate()->GetCurrentContext()->Global()->Equals(global) ||
92491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      allowed_access_type[type];
9250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
9251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic bool IndexedAccessBlocker(Local<v8::Object> global,
9254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 uint32_t key,
9255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 v8::AccessType type,
9256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 Local<Value> data) {
9257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return CcTest::isolate()->GetCurrentContext()->Global()->Equals(global) ||
92581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      allowed_access_type[type];
9259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
9260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic int g_echo_value = -1;
9263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
9264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
9265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void EchoGetter(
9266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<String> name,
9267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Value>& info) {
9268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(v8_num(g_echo_value));
9269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
9270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void EchoSetter(Local<String> name,
9273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       Local<Value> value,
9274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       const v8::PropertyCallbackInfo<void>&) {
9275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (value->IsNumber())
9276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    g_echo_value = value->Int32Value();
9277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
9278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void UnreachableGetter(
9281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<String> name,
9282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Value>& info) {
9283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(false);  // This function should not be called..
9284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
9285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void UnreachableSetter(Local<String>,
9288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Local<Value>,
9289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              const v8::PropertyCallbackInfo<void>&) {
9290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(false);  // This function should nto be called.
9291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
9292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void UnreachableFunction(
9295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::FunctionCallbackInfo<v8::Value>& info) {
9296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(false);  // This function should not be called..
9297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
9298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
9299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
93001e0659c275bb392c045087af4f6b0d7565cb3d77Steve BlockTEST(AccessControl) {
9301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
9302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(isolate);
9303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> global_template =
9304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::ObjectTemplate::New(isolate);
9305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  global_template->SetAccessCheckCallbacks(NamedAccessBlocker,
9307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           IndexedAccessBlocker);
9308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Add an accessor accessible by cross-domain JS code.
9310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  global_template->SetAccessor(
9311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      v8_str("accessible_prop"),
9312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      EchoGetter, EchoSetter,
9313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      v8::Handle<Value>(),
9314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
9315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
9317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Add an accessor that is not accessible by cross-domain JS code.
9318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  global_template->SetAccessor(v8_str("blocked_prop"),
9319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                               UnreachableGetter, UnreachableSetter,
9320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                               v8::Handle<Value>(),
9321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                               v8::DEFAULT);
9322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  global_template->SetAccessorProperty(
9324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8_str("blocked_js_prop"),
9325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::FunctionTemplate::New(isolate, UnreachableFunction),
9326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::FunctionTemplate::New(isolate, UnreachableFunction),
9327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::None,
9328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::DEFAULT);
9329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
9330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create an environment
9331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
9332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context0->Enter();
9333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Object> global0 = context0->Global();
9335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
93361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Define a property with JS getter and setter.
93371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  CompileRun(
93381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      "function getter() { return 'getter'; };\n"
93391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      "function setter() { return 'setter'; }\n"
93401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      "Object.defineProperty(this, 'js_accessor_p', {get:getter, set:setter})");
93411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
93421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Local<Value> getter = global0->Get(v8_str("getter"));
93431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Local<Value> setter = global0->Get(v8_str("setter"));
93441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
93451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // And define normal element.
93461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  global0->Set(239, v8_str("239"));
93471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
93481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Define an element with JS getter and setter.
93491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  CompileRun(
93501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      "function el_getter() { return 'el_getter'; };\n"
93511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      "function el_setter() { return 'el_setter'; };\n"
93521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      "Object.defineProperty(this, '42', {get: el_getter, set: el_setter});");
93531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
93541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Local<Value> el_getter = global0->Get(v8_str("el_getter"));
93551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Local<Value> el_setter = global0->Get(v8_str("el_setter"));
93561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
9357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope1(isolate);
9358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<Context> context1 = Context::New(isolate);
9360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context1->Enter();
9361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Object> global1 = context1->Global();
9363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  global1->Set(v8_str("other"), global0);
9364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
93651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Access blocked property.
93661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  CompileRun("other.blocked_prop = 1");
93671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
9368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(CompileRun("other.blocked_prop").IsEmpty());
9369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, 'blocked_prop')")
9370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            .IsEmpty());
9371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(
9372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CompileRun("propertyIsEnumerable.call(other, 'blocked_prop')").IsEmpty());
93731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
93741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Access blocked element.
9375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(CompileRun("other[239] = 1").IsEmpty());
93761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
9377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(CompileRun("other[239]").IsEmpty());
9378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, '239')").IsEmpty());
9379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(CompileRun("propertyIsEnumerable.call(other, '239')").IsEmpty());
93801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
93811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Enable ACCESS_HAS
93821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  allowed_access_type[v8::ACCESS_HAS] = true;
9383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(CompileRun("other[239]").IsEmpty());
93841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // ... and now we can get the descriptor...
9385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, '239').value")
9386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            .IsEmpty());
93871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // ... and enumerate the property.
93881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ExpectTrue("propertyIsEnumerable.call(other, '239')");
93891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  allowed_access_type[v8::ACCESS_HAS] = false;
93901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
93911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Access a property with JS accessor.
9392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(CompileRun("other.js_accessor_p = 2").IsEmpty());
93931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
9394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(CompileRun("other.js_accessor_p").IsEmpty());
9395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, 'js_accessor_p')")
9396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            .IsEmpty());
93971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
93981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Enable both ACCESS_HAS and ACCESS_GET.
93991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  allowed_access_type[v8::ACCESS_HAS] = true;
94001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  allowed_access_type[v8::ACCESS_GET] = true;
94011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
94021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ExpectString("other.js_accessor_p", "getter");
94031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ExpectObject(
94041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get", getter);
94051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ExpectObject(
94061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set", setter);
94071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ExpectUndefined(
94081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
94091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
94101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  allowed_access_type[v8::ACCESS_HAS] = false;
94111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  allowed_access_type[v8::ACCESS_GET] = false;
94121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
94131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Access an element with JS accessor.
9414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(CompileRun("other[42] = 2").IsEmpty());
94151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
9416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(CompileRun("other[42]").IsEmpty());
9417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, '42')").IsEmpty());
94181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
94191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Enable both ACCESS_HAS and ACCESS_GET.
94201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  allowed_access_type[v8::ACCESS_HAS] = true;
94211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  allowed_access_type[v8::ACCESS_GET] = true;
94221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
94231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ExpectString("other[42]", "el_getter");
94241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ExpectObject("Object.getOwnPropertyDescriptor(other, '42').get", el_getter);
94251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ExpectObject("Object.getOwnPropertyDescriptor(other, '42').set", el_setter);
94261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
94271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
94281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  allowed_access_type[v8::ACCESS_HAS] = false;
94291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  allowed_access_type[v8::ACCESS_GET] = false;
9430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
94311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  v8::Handle<Value> value;
9432b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
9433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Access accessible property
94341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  value = CompileRun("other.accessible_prop = 3");
9435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(value->IsNumber());
9436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(3, value->Int32Value());
94373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  CHECK_EQ(3, g_echo_value);
9438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
94391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  value = CompileRun("other.accessible_prop");
9440103cc40e0c7630e0dada7fcec7f9de7c16ef8844Steve Block  CHECK(value->IsNumber());
9441103cc40e0c7630e0dada7fcec7f9de7c16ef8844Steve Block  CHECK_EQ(3, value->Int32Value());
9442103cc40e0c7630e0dada7fcec7f9de7c16ef8844Steve Block
94431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  value = CompileRun(
94441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      "Object.getOwnPropertyDescriptor(other, 'accessible_prop').value");
94451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  CHECK(value->IsNumber());
94461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  CHECK_EQ(3, value->Int32Value());
94471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
94481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  value = CompileRun("propertyIsEnumerable.call(other, 'accessible_prop')");
9449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(value->IsTrue());
9450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Enumeration doesn't enumerate accessors from inaccessible objects in
9452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the prototype chain even if the accessors are in themselves accessible.
9453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  value = CompileRun(
9454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "(function() {"
9455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  var obj = { '__proto__': other };"
9456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  try {"
9457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "    for (var p in obj) {"
9458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "      if (p == 'accessible_prop' ||"
9459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "          p == 'blocked_js_prop' ||"
9460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "          p == 'blocked_js_prop') {"
9461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "        return false;"
9462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "      }"
9463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "    }"
9464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "    return false;"
9465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  } catch (e) {"
9466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "    return true;"
9467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  }"
9468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "})()");
94691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  CHECK(value->IsTrue());
9470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context1->Exit();
9472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context0->Exit();
9473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
9474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9476e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochTEST(AccessControlES5) {
9477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
9478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(isolate);
9479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> global_template =
9480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::ObjectTemplate::New(isolate);
9481e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
9482e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  global_template->SetAccessCheckCallbacks(NamedAccessBlocker,
9483e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                           IndexedAccessBlocker);
9484e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
948544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Add accessible accessor.
948644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  global_template->SetAccessor(
948744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      v8_str("accessible_prop"),
948844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      EchoGetter, EchoSetter,
948944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      v8::Handle<Value>(),
949044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
949144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
949244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
9493e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Add an accessor that is not accessible by cross-domain JS code.
9494e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  global_template->SetAccessor(v8_str("blocked_prop"),
9495e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                               UnreachableGetter, UnreachableSetter,
9496e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                               v8::Handle<Value>(),
9497e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                               v8::DEFAULT);
9498e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
9499e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Create an environment
9500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
9501e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  context0->Enter();
9502e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
9503e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v8::Handle<v8::Object> global0 = context0->Global();
9504e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
9505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<Context> context1 = Context::New(isolate);
9506e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  context1->Enter();
9507e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v8::Handle<v8::Object> global1 = context1->Global();
9508e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  global1->Set(v8_str("other"), global0);
9509e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
9510e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Regression test for issue 1154.
9511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(CompileRun("Object.keys(other)").IsEmpty());
9512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(CompileRun("other.blocked_prop").IsEmpty());
9513e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
9514e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Regression test for issue 1027.
9515e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  CompileRun("Object.defineProperty(\n"
9516e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch             "  other, 'blocked_prop', {configurable: false})");
9517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(CompileRun("other.blocked_prop").IsEmpty());
9518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, 'blocked_prop')")
9519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            .IsEmpty());
9520e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
9521e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Regression test for issue 1171.
9522e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ExpectTrue("Object.isExtensible(other)");
9523e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  CompileRun("Object.preventExtensions(other)");
9524e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ExpectTrue("Object.isExtensible(other)");
9525e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
9526e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Object.seal and Object.freeze.
9527e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  CompileRun("Object.freeze(other)");
9528e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ExpectTrue("Object.isExtensible(other)");
9529e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
9530e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  CompileRun("Object.seal(other)");
9531e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ExpectTrue("Object.isExtensible(other)");
953244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
953344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Regression test for issue 1250.
953444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Make sure that we can set the accessible accessors value using normal
953544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // assignment.
953644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CompileRun("other.accessible_prop = 42");
953744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(42, g_echo_value);
953844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
953944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::Handle<Value> value;
954044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CompileRun("Object.defineProperty(other, 'accessible_prop', {value: -1})");
954144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  value = CompileRun("other.accessible_prop == 42");
954244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK(value->IsTrue());
9543e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
9544e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
9545e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
9546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic bool BlockEverythingNamed(Local<v8::Object> object, Local<Value> name,
9547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 v8::AccessType type, Local<Value> data) {
95484515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  return false;
95494515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke}
95504515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
95514515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
9552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic bool BlockEverythingIndexed(Local<v8::Object> object, uint32_t key,
9553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   v8::AccessType type, Local<Value> data) {
95544515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  return false;
95554515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke}
95564515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
95574515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
95584515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeTHREADED_TEST(AccessControlGetOwnPropertyNames) {
9559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
9560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(isolate);
9561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> obj_template =
9562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::ObjectTemplate::New(isolate);
95634515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
9564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  obj_template->Set(v8_str("x"), v8::Integer::New(isolate, 42));
9565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  obj_template->SetAccessCheckCallbacks(BlockEverythingNamed,
9566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        BlockEverythingIndexed);
95674515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
95684515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // Create an environment
9569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<Context> context0 = Context::New(isolate, NULL, obj_template);
95704515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  context0->Enter();
95714515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
95724515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  v8::Handle<v8::Object> global0 = context0->Global();
95734515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
9574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope1(CcTest::isolate());
95754515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
9576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<Context> context1 = Context::New(isolate);
95774515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  context1->Enter();
95784515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
95794515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  v8::Handle<v8::Object> global1 = context1->Global();
95804515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  global1->Set(v8_str("other"), global0);
95814515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  global1->Set(v8_str("object"), obj_template->NewInstance());
95824515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
95834515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  v8::Handle<Value> value;
95844515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
95854515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // Attempt to get the property names of the other global object and
95864515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // of an object that requires access checks.  Accessing the other
95874515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // global object should be blocked by access checks on the global
95884515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // proxy object.  Accessing the object that requires access checks
95894515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // is blocked by the access checks on the object itself.
95904515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  value = CompileRun("Object.getOwnPropertyNames(other).length == 0");
9591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(value.IsEmpty());
95924515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
95934515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  value = CompileRun("Object.getOwnPropertyNames(object).length == 0");
9594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(value.IsEmpty());
95954515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
95964515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  context1->Exit();
95974515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  context0->Exit();
95984515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke}
95994515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
96004515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
9601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(SuperAccessControl) {
9602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::FLAG_harmony_classes = true;
9603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
9604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(isolate);
9605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> obj_template =
9606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::ObjectTemplate::New(isolate);
9607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  obj_template->SetAccessCheckCallbacks(BlockEverythingNamed,
9608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        BlockEverythingIndexed);
9609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
9610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->Global()->Set(v8_str("prohibited"), obj_template->NewInstance());
9611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
9612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::TryCatch try_catch;
9613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun(
9614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "function f() { return super.hasOwnProperty; };"
9615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "var m = f.toMethod(prohibited);"
9616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "m();");
9617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(try_catch.HasCaught());
9618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
9619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
9620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
9621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void IndexedPropertyEnumerator(
9622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Array>& info) {
9623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Array> result = v8::Array::New(info.GetIsolate(), 2);
9624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  result->Set(0, v8::Integer::New(info.GetIsolate(), 7));
9625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  result->Set(1, v8::Object::New(info.GetIsolate()));
9626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(result);
9627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
9628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
9629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
9630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void NamedPropertyEnumerator(
9631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Array>& info) {
9632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Array> result = v8::Array::New(info.GetIsolate(), 2);
96338defd9ff6930b4e24729971a61cf7469daf119beSteve Block  result->Set(0, v8_str("x"));
9634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  result->Set(1, v8::Object::New(info.GetIsolate()));
9635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(result);
96368defd9ff6930b4e24729971a61cf7469daf119beSteve Block}
96378defd9ff6930b4e24729971a61cf7469daf119beSteve Block
96388defd9ff6930b4e24729971a61cf7469daf119beSteve Block
96398defd9ff6930b4e24729971a61cf7469daf119beSteve BlockTHREADED_TEST(GetOwnPropertyNamesWithInterceptor) {
9640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
9641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(isolate);
9642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> obj_template =
9643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::ObjectTemplate::New(isolate);
9644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
9645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  obj_template->Set(v8_str("7"), v8::Integer::New(CcTest::isolate(), 7));
9646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  obj_template->Set(v8_str("x"), v8::Integer::New(CcTest::isolate(), 42));
9647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  obj_template->SetIndexedPropertyHandler(NULL, NULL, NULL, NULL,
9648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                          IndexedPropertyEnumerator);
96498defd9ff6930b4e24729971a61cf7469daf119beSteve Block  obj_template->SetNamedPropertyHandler(NULL, NULL, NULL, NULL,
96508defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                        NamedPropertyEnumerator);
96518defd9ff6930b4e24729971a61cf7469daf119beSteve Block
96528defd9ff6930b4e24729971a61cf7469daf119beSteve Block  LocalContext context;
96538defd9ff6930b4e24729971a61cf7469daf119beSteve Block  v8::Handle<v8::Object> global = context->Global();
96548defd9ff6930b4e24729971a61cf7469daf119beSteve Block  global->Set(v8_str("object"), obj_template->NewInstance());
96558defd9ff6930b4e24729971a61cf7469daf119beSteve Block
9656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Value> result =
9657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CompileRun("Object.getOwnPropertyNames(object)");
9658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(result->IsArray());
9659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Array> result_array = v8::Handle<v8::Array>::Cast(result);
9660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(3, result_array->Length());
9661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(result_array->Get(0)->IsString());
9662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(result_array->Get(1)->IsString());
9663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(result_array->Get(2)->IsString());
9664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(v8_str("7"), result_array->Get(0));
9665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(v8_str("[object Object]"), result_array->Get(1));
9666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(v8_str("x"), result_array->Get(2));
96678defd9ff6930b4e24729971a61cf7469daf119beSteve Block}
96688defd9ff6930b4e24729971a61cf7469daf119beSteve Block
96698defd9ff6930b4e24729971a61cf7469daf119beSteve Block
9670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void ConstTenGetter(Local<String> name,
9671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           const v8::PropertyCallbackInfo<v8::Value>& info) {
9672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(v8_num(10));
9673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
9674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(CrossDomainAccessors) {
9677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
9678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(isolate);
9679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::FunctionTemplate> func_template =
9681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::FunctionTemplate::New(isolate);
9682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::ObjectTemplate> global_template =
9684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      func_template->InstanceTemplate();
9685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::ObjectTemplate> proto_template =
9687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      func_template->PrototypeTemplate();
9688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Add an accessor to proto that's accessible by cross-domain JS code.
9690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  proto_template->SetAccessor(v8_str("accessible"),
9691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                              ConstTenGetter, 0,
9692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                              v8::Handle<Value>(),
9693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                              v8::ALL_CAN_READ);
9694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Add an accessor that is not accessible by cross-domain JS code.
9696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  global_template->SetAccessor(v8_str("unreachable"),
9697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                               UnreachableGetter, 0,
9698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                               v8::Handle<Value>(),
9699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                               v8::DEFAULT);
9700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
9702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context0->Enter();
9703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<v8::Object> global = context0->Global();
9705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Add a normal property that shadows 'accessible'
9706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  global->Set(v8_str("accessible"), v8_num(11));
9707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Enter a new context.
9709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope1(CcTest::isolate());
9710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<Context> context1 = Context::New(isolate);
9711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context1->Enter();
9712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Object> global1 = context1->Global();
9714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  global1->Set(v8_str("other"), global);
9715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Should return 10, instead of 11
9717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> value = v8_compile("other.accessible")->Run();
9718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(value->IsNumber());
9719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(10, value->Int32Value());
9720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  value = v8_compile("other.unreachable")->Run();
9722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(value.IsEmpty());
9723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context1->Exit();
9725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context0->Exit();
9726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
9727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic int named_access_count = 0;
9730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic int indexed_access_count = 0;
9731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic bool NamedAccessCounter(Local<v8::Object> global,
9733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                               Local<Value> name,
9734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                               v8::AccessType type,
9735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                               Local<Value> data) {
9736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  named_access_count++;
9737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return true;
9738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
9739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic bool IndexedAccessCounter(Local<v8::Object> global,
9742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 uint32_t key,
9743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 v8::AccessType type,
9744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 Local<Value> data) {
9745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  indexed_access_count++;
9746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return true;
9747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
9748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// This one is too easily disturbed by other tests.
9751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(AccessControlIC) {
9752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  named_access_count = 0;
9753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  indexed_access_count = 0;
9754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
9756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(isolate);
9757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create an environment.
9759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<Context> context0 = Context::New(isolate);
9760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context0->Enter();
9761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create an object that requires access-check functions to be
9763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // called for cross-domain access.
9764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> object_template =
9765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::ObjectTemplate::New(isolate);
9766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  object_template->SetAccessCheckCallbacks(NamedAccessCounter,
9767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           IndexedAccessCounter);
9768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<v8::Object> object = object_template->NewInstance();
9769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope1(isolate);
9771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create another environment.
9773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<Context> context1 = Context::New(isolate);
9774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context1->Enter();
9775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make easy access to the object from the other environment.
9777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Object> global1 = context1->Global();
9778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  global1->Set(v8_str("obj"), object);
9779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> value;
9781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the named access-control function is called every time.
9783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CompileRun("function testProp(obj) {"
9784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block             "  for (var i = 0; i < 10; i++) obj.prop = 1;"
9785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block             "  for (var j = 0; j < 10; j++) obj.prop;"
9786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block             "  return obj.prop"
9787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block             "}");
9788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  value = CompileRun("testProp(obj)");
9789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(value->IsNumber());
9790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, value->Int32Value());
9791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(21, named_access_count);
9792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the named access-control function is called every time.
9794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CompileRun("var p = 'prop';"
9795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block             "function testKeyed(obj) {"
9796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block             "  for (var i = 0; i < 10; i++) obj[p] = 1;"
9797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block             "  for (var j = 0; j < 10; j++) obj[p];"
9798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block             "  return obj[p];"
9799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block             "}");
9800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Use obj which requires access checks.  No inline caching is used
9801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // in that case.
9802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  value = CompileRun("testKeyed(obj)");
9803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(value->IsNumber());
9804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, value->Int32Value());
9805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(42, named_access_count);
9806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Force the inline caches into generic state and try again.
9807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CompileRun("testKeyed({ a: 0 })");
9808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CompileRun("testKeyed({ b: 0 })");
9809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  value = CompileRun("testKeyed(obj)");
9810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(value->IsNumber());
9811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, value->Int32Value());
9812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(63, named_access_count);
9813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the indexed access-control function is called every time.
9815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CompileRun("function testIndexed(obj) {"
9816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block             "  for (var i = 0; i < 10; i++) obj[0] = 1;"
9817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block             "  for (var j = 0; j < 10; j++) obj[0];"
9818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block             "  return obj[0]"
9819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block             "}");
9820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  value = CompileRun("testIndexed(obj)");
9821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(value->IsNumber());
9822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, value->Int32Value());
9823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(21, indexed_access_count);
9824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Force the inline caches into generic state.
9825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CompileRun("testIndexed(new Array(1))");
9826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Test that the indexed access check is called.
9827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  value = CompileRun("testIndexed(obj)");
9828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(value->IsNumber());
9829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, value->Int32Value());
9830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(42, indexed_access_count);
9831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the named access check is called when invoking
9833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // functions on an object that requires access checks.
9834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CompileRun("obj.f = function() {}");
9835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CompileRun("function testCallNormal(obj) {"
9836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block             "  for (var i = 0; i < 10; i++) obj.f();"
9837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block             "}");
9838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CompileRun("testCallNormal(obj)");
9839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(74, named_access_count);
9840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Force obj into slow case.
9842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  value = CompileRun("delete obj.prop");
9843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(value->BooleanValue());
9844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Force inline caches into dictionary probing mode.
9845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CompileRun("var o = { x: 0 }; delete o.x; testProp(o);");
9846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Test that the named access check is called.
9847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  value = CompileRun("testProp(obj);");
9848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(value->IsNumber());
9849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, value->Int32Value());
9850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(96, named_access_count);
9851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Force the call inline cache into dictionary probing mode.
9853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CompileRun("o.f = function() {}; testCallNormal(o)");
9854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Test that the named access check is still called for each
9855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // invocation of the function.
9856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  value = CompileRun("testCallNormal(obj)");
9857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(106, named_access_count);
9858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context1->Exit();
9860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context0->Exit();
9861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
9862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic bool NamedAccessFlatten(Local<v8::Object> global,
9865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                               Local<Value> name,
9866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                               v8::AccessType type,
9867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                               Local<Value> data) {
9868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  char buf[100];
9869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int len;
9870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(name->IsString());
9872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  memset(buf, 0x1, sizeof(buf));
9874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  len = name.As<String>()->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
9875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(4, len);
9876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  uint16_t buf2[100];
9878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  memset(buf, 0x1, sizeof(buf));
98806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  len = name.As<String>()->Write(buf2);
9881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(4, len);
9882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return true;
9884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
9885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic bool IndexedAccessFlatten(Local<v8::Object> global,
9888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 uint32_t key,
9889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 v8::AccessType type,
9890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 Local<Value> data) {
9891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return true;
9892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
9893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Regression test.  In access checks, operations that may cause
9896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// garbage collection are not allowed.  It used to be the case that
9897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// using the Write operation on a string could cause a garbage
9898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// collection due to flattening of the string.  This is no longer the
9899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// case.
9900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(AccessControlFlatten) {
9901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  named_access_count = 0;
9902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  indexed_access_count = 0;
9903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
9905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(isolate);
9906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create an environment.
9908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<Context> context0 = Context::New(isolate);
9909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context0->Enter();
9910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create an object that requires access-check functions to be
9912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // called for cross-domain access.
9913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> object_template =
9914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::ObjectTemplate::New(isolate);
9915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  object_template->SetAccessCheckCallbacks(NamedAccessFlatten,
9916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           IndexedAccessFlatten);
9917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<v8::Object> object = object_template->NewInstance();
9918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope1(isolate);
9920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create another environment.
9922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<Context> context1 = Context::New(isolate);
9923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context1->Enter();
9924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make easy access to the object from the other environment.
9926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Object> global1 = context1->Global();
9927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  global1->Set(v8_str("obj"), object);
9928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> value;
9930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  value = v8_compile("var p = 'as' + 'df';")->Run();
9932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  value = v8_compile("obj[p];")->Run();
9933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context1->Exit();
9935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context0->Exit();
9936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
9937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void AccessControlNamedGetter(
9940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<String>,
9941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Value>& info) {
9942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(42);
9943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
9944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void AccessControlNamedSetter(
9947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<String>,
9948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<Value> value,
9949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Value>& info) {
9950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(value);
9951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
9952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void AccessControlIndexedGetter(
9955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      uint32_t index,
9956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      const v8::PropertyCallbackInfo<v8::Value>& info) {
9957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(v8_num(42));
9958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
9959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void AccessControlIndexedSetter(
9962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t,
9963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<Value> value,
9964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Value>& info) {
9965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(value);
9966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
9967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(AccessControlInterceptorIC) {
9970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  named_access_count = 0;
9971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  indexed_access_count = 0;
9972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
9974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(isolate);
9975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create an environment.
9977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<Context> context0 = Context::New(isolate);
9978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context0->Enter();
9979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create an object that requires access-check functions to be
9981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // called for cross-domain access.  The object also has interceptors
9982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // interceptor.
9983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> object_template =
9984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::ObjectTemplate::New(isolate);
9985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  object_template->SetAccessCheckCallbacks(NamedAccessCounter,
9986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           IndexedAccessCounter);
9987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  object_template->SetNamedPropertyHandler(AccessControlNamedGetter,
9988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           AccessControlNamedSetter);
9989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  object_template->SetIndexedPropertyHandler(AccessControlIndexedGetter,
9990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             AccessControlIndexedSetter);
9991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<v8::Object> object = object_template->NewInstance();
9992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope1(isolate);
9994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create another environment.
9996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<Context> context1 = Context::New(isolate);
9997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context1->Enter();
9998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make easy access to the object from the other environment.
10000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Object> global1 = context1->Global();
10001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  global1->Set(v8_str("obj"), object);
10002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> value;
10004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the named access-control function is called every time
10006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // eventhough there is an interceptor on the object.
10007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  value = v8_compile("for (var i = 0; i < 10; i++) obj.x = 1;")->Run();
10008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  value = v8_compile("for (var i = 0; i < 10; i++) obj.x;"
10009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     "obj.x")->Run();
10010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(value->IsNumber());
10011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(42, value->Int32Value());
10012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(21, named_access_count);
10013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  value = v8_compile("var p = 'x';")->Run();
10015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  value = v8_compile("for (var i = 0; i < 10; i++) obj[p] = 1;")->Run();
10016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  value = v8_compile("for (var i = 0; i < 10; i++) obj[p];"
10017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     "obj[p]")->Run();
10018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(value->IsNumber());
10019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(42, value->Int32Value());
10020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(42, named_access_count);
10021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the indexed access-control function is called every
10023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // time eventhough there is an interceptor on the object.
10024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  value = v8_compile("for (var i = 0; i < 10; i++) obj[0] = 1;")->Run();
10025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  value = v8_compile("for (var i = 0; i < 10; i++) obj[0];"
10026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     "obj[0]")->Run();
10027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(value->IsNumber());
10028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(42, value->Int32Value());
10029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(21, indexed_access_count);
10030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context1->Exit();
10032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context0->Exit();
10033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
10034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(Version) {
10037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::V8::GetVersion();
10038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
10039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void InstanceFunctionCallback(
10042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::FunctionCallbackInfo<v8::Value>& args) {
10043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
10044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  args.GetReturnValue().Set(v8_num(12));
10045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
10046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(InstanceProperties) {
10049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
10050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
10051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(isolate);
10052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
10054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<ObjectTemplate> instance = t->InstanceTemplate();
10055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  instance->Set(v8_str("x"), v8_num(42));
10057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  instance->Set(v8_str("f"),
10058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                v8::FunctionTemplate::New(isolate, InstanceFunctionCallback));
10059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Value> o = t->GetFunction()->NewInstance();
10061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context->Global()->Set(v8_str("i"), o);
10063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Value> value = CompileRun("i.x");
10064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(42, value->Int32Value());
10065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  value = CompileRun("i.f()");
10067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(12, value->Int32Value());
10068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
10069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void GlobalObjectInstancePropertiesGet(
10072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<String> key,
10073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Value>&) {
10074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
10075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
10076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(GlobalObjectInstanceProperties) {
10079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
10080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(isolate);
10081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Value> global_object;
10083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
10085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  t->InstanceTemplate()->SetNamedPropertyHandler(
10086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      GlobalObjectInstancePropertiesGet);
10087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<ObjectTemplate> instance_template = t->InstanceTemplate();
10088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  instance_template->Set(v8_str("x"), v8_num(42));
10089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  instance_template->Set(v8_str("f"),
10090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         v8::FunctionTemplate::New(isolate,
10091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                   InstanceFunctionCallback));
10092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10093b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // The script to check how Crankshaft compiles missing global function
10094b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // invocations.  function g is not defined and should throw on call.
10095b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  const char* script =
10096b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "function wrapper(call) {"
10097b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "  var x = 0, y = 1;"
10098b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "  for (var i = 0; i < 1000; i++) {"
10099b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "    x += i * 100;"
10100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "    y += i * 100;"
10101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "  }"
10102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "  if (call) g();"
10103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "}"
10104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "for (var i = 0; i < 17; i++) wrapper(false);"
10105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "var thrown = 0;"
10106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "try { wrapper(true); } catch (e) { thrown = 1; };"
10107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "thrown";
10108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
10109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {
10110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    LocalContext env(NULL, instance_template);
10111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Hold on to the global object so it can be used again in another
10112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // environment initialization.
10113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    global_object = env->Global();
10114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<Value> value = CompileRun("x");
10116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(42, value->Int32Value());
10117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    value = CompileRun("f()");
10118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(12, value->Int32Value());
10119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    value = CompileRun(script);
10120b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CHECK_EQ(1, value->Int32Value());
10121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
10122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {
10124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Create new environment reusing the global object.
10125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    LocalContext env(NULL, instance_template, global_object);
10126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<Value> value = CompileRun("x");
10127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(42, value->Int32Value());
10128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    value = CompileRun("f()");
10129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(12, value->Int32Value());
10130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    value = CompileRun(script);
10131b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CHECK_EQ(1, value->Int32Value());
10132b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
10133b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
10134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
10135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
10136b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochTHREADED_TEST(CallKnownGlobalReceiver) {
10137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
10138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(isolate);
10139b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
10140b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Local<Value> global_object;
10141b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
10142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
10143b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Local<ObjectTemplate> instance_template = t->InstanceTemplate();
10144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
10145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // The script to check that we leave global object not
10146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // global object proxy on stack when we deoptimize from inside
10147b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // arguments evaluation.
10148b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // To provoke error we need to both force deoptimization
10149b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // from arguments evaluation and to force CallIC to take
10150b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // CallIC_Miss code path that can't cope with global proxy.
10151b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  const char* script =
10152b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "function bar(x, y) { try { } finally { } }"
10153b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "function baz(x) { try { } finally { } }"
10154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "function bom(x) { try { } finally { } }"
10155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "function foo(x) { bar([x], bom(2)); }"
10156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "for (var i = 0; i < 10000; i++) foo(1);"
10157b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "foo";
10158b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
10159b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Local<Value> foo;
10160b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  {
10161b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    LocalContext env(NULL, instance_template);
10162b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Hold on to the global object so it can be used again in another
10163b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // environment initialization.
10164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    global_object = env->Global();
10165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    foo = CompileRun(script);
10166b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
10167b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
10168b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  {
10169b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Create new environment reusing the global object.
10170b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    LocalContext env(NULL, instance_template, global_object);
10171b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    env->Global()->Set(v8_str("foo"), foo);
10172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CompileRun("foo()");
10173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
10174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
10175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void ShadowFunctionCallback(
10178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::FunctionCallbackInfo<v8::Value>& args) {
10179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
10180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  args.GetReturnValue().Set(v8_num(42));
10181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
10182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic int shadow_y;
10185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic int shadow_y_setter_call_count;
10186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic int shadow_y_getter_call_count;
10187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void ShadowYSetter(Local<String>,
10190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          Local<Value>,
10191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          const v8::PropertyCallbackInfo<void>&) {
10192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  shadow_y_setter_call_count++;
10193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  shadow_y = 42;
10194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
10195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void ShadowYGetter(Local<String> name,
10198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          const v8::PropertyCallbackInfo<v8::Value>& info) {
10199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
10200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  shadow_y_getter_call_count++;
10201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(v8_num(shadow_y));
10202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
10203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void ShadowIndexedGet(uint32_t index,
10206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             const v8::PropertyCallbackInfo<v8::Value>&) {
10207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
10208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void ShadowNamedGet(Local<String> key,
10211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           const v8::PropertyCallbackInfo<v8::Value>&) {
10212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
10213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(ShadowObject) {
10216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  shadow_y = shadow_y_setter_call_count = shadow_y_getter_call_count = 0;
10217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
10218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(isolate);
10219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> global_template = v8::ObjectTemplate::New(isolate);
10221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context(NULL, global_template);
10222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
10224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  t->InstanceTemplate()->SetNamedPropertyHandler(ShadowNamedGet);
10225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  t->InstanceTemplate()->SetIndexedPropertyHandler(ShadowIndexedGet);
10226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<ObjectTemplate> proto = t->PrototypeTemplate();
10227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<ObjectTemplate> instance = t->InstanceTemplate();
10228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  proto->Set(v8_str("f"),
10230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             v8::FunctionTemplate::New(isolate,
10231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       ShadowFunctionCallback,
10232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       Local<Value>()));
10233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  proto->Set(v8_str("x"), v8_num(12));
10234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  instance->SetAccessor(v8_str("y"), ShadowYGetter, ShadowYSetter);
10236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Value> o = t->GetFunction()->NewInstance();
10238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context->Global()->Set(v8_str("__proto__"), o);
10239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Value> value =
10241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CompileRun("this.propertyIsEnumerable(0)");
10242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(value->IsBoolean());
10243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(!value->BooleanValue());
10244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  value = CompileRun("x");
10246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(12, value->Int32Value());
10247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  value = CompileRun("f()");
10249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(42, value->Int32Value());
10250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("y = 43");
10252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, shadow_y_setter_call_count);
10253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  value = CompileRun("y");
10254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, shadow_y_getter_call_count);
10255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(42, value->Int32Value());
10256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
10257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(HiddenPrototype) {
10260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
10261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
10262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(isolate);
10263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New(isolate);
10265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
10266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
10267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  t1->SetHiddenPrototype(true);
10268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
10269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
10270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  t2->SetHiddenPrototype(true);
10271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
10272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
10273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
10274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<v8::Object> o0 = t0->GetFunction()->NewInstance();
10276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
10277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
10278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
10279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Setting the prototype on an object skips hidden prototypes.
10281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
10282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  o0->Set(v8_str("__proto__"), o1);
10283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
10284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
10285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  o0->Set(v8_str("__proto__"), o2);
10286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
10287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
10288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
10289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  o0->Set(v8_str("__proto__"), o3);
10290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
10291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
10292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
10293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(3, o0->Get(v8_str("u"))->Int32Value());
10294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Getting the prototype of o0 should get the first visible one
10296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // which is o3.  Therefore, z should not be defined on the prototype
10297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // object.
10298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Value> proto = o0->Get(v8_str("__proto__"));
10299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(proto->IsObject());
103006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(proto.As<v8::Object>()->Get(v8_str("z"))->IsUndefined());
10301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
10302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(HiddenPrototypeSet) {
10305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
10306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
10307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(isolate);
10308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
10309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::FunctionTemplate> ot = v8::FunctionTemplate::New(isolate);
10310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::FunctionTemplate> ht = v8::FunctionTemplate::New(isolate);
10311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ht->SetHiddenPrototype(true);
10312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::FunctionTemplate> pt = v8::FunctionTemplate::New(isolate);
10313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ht->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
10314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
10315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::Object> o = ot->GetFunction()->NewInstance();
10316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::Object> h = ht->GetFunction()->NewInstance();
10317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::Object> p = pt->GetFunction()->NewInstance();
10318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  o->Set(v8_str("__proto__"), h);
10319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  h->Set(v8_str("__proto__"), p);
10320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
10321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Setting a property that exists on the hidden prototype goes there.
10322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  o->Set(v8_str("x"), v8_num(7));
10323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(7, o->Get(v8_str("x"))->Int32Value());
10324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(7, h->Get(v8_str("x"))->Int32Value());
10325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(p->Get(v8_str("x"))->IsUndefined());
10326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
10327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Setting a new property should not be forwarded to the hidden prototype.
10328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  o->Set(v8_str("y"), v8_num(6));
10329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(6, o->Get(v8_str("y"))->Int32Value());
10330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(h->Get(v8_str("y"))->IsUndefined());
10331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(p->Get(v8_str("y"))->IsUndefined());
10332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
10333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Setting a property that only exists on a prototype of the hidden prototype
10334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // is treated normally again.
10335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  p->Set(v8_str("z"), v8_num(8));
10336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(8, o->Get(v8_str("z"))->Int32Value());
10337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(8, h->Get(v8_str("z"))->Int32Value());
10338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(8, p->Get(v8_str("z"))->Int32Value());
10339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  o->Set(v8_str("z"), v8_num(9));
10340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(9, o->Get(v8_str("z"))->Int32Value());
10341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(8, h->Get(v8_str("z"))->Int32Value());
10342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(8, p->Get(v8_str("z"))->Int32Value());
10343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
10344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
10345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
10346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Regression test for issue 2457.
10347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(HiddenPrototypeIdentityHash) {
10348402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  LocalContext context;
10349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(context->GetIsolate());
10350402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
10351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<FunctionTemplate> t = FunctionTemplate::New(context->GetIsolate());
10352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  t->SetHiddenPrototype(true);
10353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  t->InstanceTemplate()->Set(v8_str("foo"), v8_num(75));
10354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Object> p = t->GetFunction()->NewInstance();
10355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Object> o = Object::New(context->GetIsolate());
10356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  o->SetPrototype(p);
10357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
10358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int hash = o->GetIdentityHash();
10359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  USE(hash);
10360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  o->Set(v8_str("foo"), v8_num(42));
10361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(hash, o->GetIdentityHash());
10362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
10363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
10364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
10365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(SetPrototype) {
10366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
10367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
10368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(isolate);
10369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
10370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New(isolate);
10371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
10372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
10373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  t1->SetHiddenPrototype(true);
10374402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
10375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
10376402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  t2->SetHiddenPrototype(true);
10377402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
10378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
10379402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
10380402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
10381402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Local<v8::Object> o0 = t0->GetFunction()->NewInstance();
10382402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
10383402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
10384402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
10385402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
10386402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Setting the prototype on an object does not skip hidden prototypes.
10387402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
10388402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK(o0->SetPrototype(o1));
10389402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
10390402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
10391402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK(o1->SetPrototype(o2));
10392402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
10393402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
10394402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
10395402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK(o2->SetPrototype(o3));
10396402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
10397402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
10398402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
10399402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK_EQ(3, o0->Get(v8_str("u"))->Int32Value());
10400402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
10401402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Getting the prototype of o0 should get the first visible one
10402402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // which is o3.  Therefore, z should not be defined on the prototype
10403402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // object.
10404402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Local<Value> proto = o0->Get(v8_str("__proto__"));
10405402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK(proto->IsObject());
104066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(proto.As<v8::Object>(), o3);
10407402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
10408402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // However, Object::GetPrototype ignores hidden prototype.
10409402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Local<Value> proto0 = o0->GetPrototype();
10410402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK(proto0->IsObject());
104116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(proto0.As<v8::Object>(), o1);
10412402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
10413402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Local<Value> proto1 = o1->GetPrototype();
10414402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK(proto1->IsObject());
104156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(proto1.As<v8::Object>(), o2);
10416402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
10417402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Local<Value> proto2 = o2->GetPrototype();
10418402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK(proto2->IsObject());
104196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(proto2.As<v8::Object>(), o3);
10420402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
10421402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
10422402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
104233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Getting property names of an object with a prototype chain that
10424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// triggers dictionary elements in GetOwnPropertyNames() shouldn't
104253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// crash the runtime.
104263ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochTHREADED_TEST(Regress91517) {
104273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  i::FLAG_allow_natives_syntax = true;
104283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LocalContext context;
10429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
10430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(isolate);
104313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
104333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  t1->SetHiddenPrototype(true);
104343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  t1->InstanceTemplate()->Set(v8_str("foo"), v8_num(1));
10435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
104363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  t2->SetHiddenPrototype(true);
104373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  t2->InstanceTemplate()->Set(v8_str("fuz1"), v8_num(2));
10438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  t2->InstanceTemplate()->Set(v8_str("objects"), v8::Object::New(isolate));
104393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  t2->InstanceTemplate()->Set(v8_str("fuz2"), v8_num(2));
10440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
104413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  t3->SetHiddenPrototype(true);
104423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  t3->InstanceTemplate()->Set(v8_str("boo"), v8_num(3));
10443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::FunctionTemplate> t4 = v8::FunctionTemplate::New(isolate);
104443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  t4->InstanceTemplate()->Set(v8_str("baz"), v8_num(4));
104453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
104463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Force dictionary-based properties.
104473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  i::ScopedVector<char> name_buf(1024);
104483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 1; i <= 1000; i++) {
10449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    i::SNPrintF(name_buf, "sdf%d", i);
104503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    t2->InstanceTemplate()->Set(v8_str(name_buf.start()), v8_num(2));
104513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
104523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
104533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
104543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
104553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
104563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Local<v8::Object> o4 = t4->GetFunction()->NewInstance();
104573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
104583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Create prototype chain of hidden prototypes.
104593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(o4->SetPrototype(o3));
104603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(o3->SetPrototype(o2));
104613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(o2->SetPrototype(o1));
104623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Call the runtime version of GetOwnPropertyNames() on the natively
104643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // created object through JavaScript.
104653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  context->Global()->Set(v8_str("obj"), o4);
10466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // PROPERTY_ATTRIBUTES_NONE = 0
10467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("var names = %GetOwnPropertyNames(obj, 0);");
104683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
104693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExpectInt32("names.length", 1006);
104703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExpectTrue("names.indexOf(\"baz\") >= 0");
104713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExpectTrue("names.indexOf(\"boo\") >= 0");
104723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExpectTrue("names.indexOf(\"foo\") >= 0");
104733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExpectTrue("names.indexOf(\"fuz1\") >= 0");
104743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExpectTrue("names.indexOf(\"fuz2\") >= 0");
104753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExpectFalse("names[1005] == undefined");
104763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
104773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
104783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Getting property names of an object with a hidden and inherited
10480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// prototype should not duplicate the accessor properties inherited.
10481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(Regress269562) {
10482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::FLAG_allow_natives_syntax = true;
10483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
10484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(context->GetIsolate());
10485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
10486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::FunctionTemplate> t1 =
10487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::FunctionTemplate::New(context->GetIsolate());
10488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  t1->SetHiddenPrototype(true);
10489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
10490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::ObjectTemplate> i1 = t1->InstanceTemplate();
10491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i1->SetAccessor(v8_str("foo"),
10492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  SimpleAccessorGetter, SimpleAccessorSetter);
10493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i1->SetAccessor(v8_str("bar"),
10494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  SimpleAccessorGetter, SimpleAccessorSetter);
10495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i1->SetAccessor(v8_str("baz"),
10496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  SimpleAccessorGetter, SimpleAccessorSetter);
10497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i1->Set(v8_str("n1"), v8_num(1));
10498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i1->Set(v8_str("n2"), v8_num(2));
10499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
10500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
10501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::FunctionTemplate> t2 =
10502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::FunctionTemplate::New(context->GetIsolate());
10503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  t2->SetHiddenPrototype(true);
10504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
10505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Inherit from t1 and mark prototype as hidden.
10506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  t2->Inherit(t1);
10507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  t2->InstanceTemplate()->Set(v8_str("mine"), v8_num(4));
10508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
10509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
10510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(o2->SetPrototype(o1));
10511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
10512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Symbol> sym =
10513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Symbol::New(context->GetIsolate(), v8_str("s1"));
10514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  o1->Set(sym, v8_num(3));
10515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  o1->SetHiddenValue(
10516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8_str("h1"), v8::Integer::New(context->GetIsolate(), 2013));
10517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
10518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Call the runtime version of GetOwnPropertyNames() on
10519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the natively created object through JavaScript.
10520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context->Global()->Set(v8_str("obj"), o2);
10521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context->Global()->Set(v8_str("sym"), sym);
10522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // PROPERTY_ATTRIBUTES_NONE = 0
10523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("var names = %GetOwnPropertyNames(obj, 0);");
10524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
10525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExpectInt32("names.length", 7);
10526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExpectTrue("names.indexOf(\"foo\") >= 0");
10527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExpectTrue("names.indexOf(\"bar\") >= 0");
10528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExpectTrue("names.indexOf(\"baz\") >= 0");
10529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExpectTrue("names.indexOf(\"n1\") >= 0");
10530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExpectTrue("names.indexOf(\"n2\") >= 0");
10531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExpectTrue("names.indexOf(sym) >= 0");
10532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExpectTrue("names.indexOf(\"mine\") >= 0");
10533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
10534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
10535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1053669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen MurdochTHREADED_TEST(FunctionReadOnlyPrototype) {
105373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  LocalContext context;
10538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
10539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(isolate);
105403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
10541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
10542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  t1->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(isolate, 42));
1054369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  t1->ReadOnlyPrototype();
105443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  context->Global()->Set(v8_str("func1"), t1->GetFunction());
1054569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Configured value of ReadOnly flag.
105463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK(CompileRun(
105473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      "(function() {"
105483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      "  descriptor = Object.getOwnPropertyDescriptor(func1, 'prototype');"
1054969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      "  return (descriptor['writable'] == false);"
105503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      "})()")->BooleanValue());
1055169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK_EQ(42, CompileRun("func1.prototype.x")->Int32Value());
1055269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK_EQ(42,
1055369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch           CompileRun("func1.prototype = {}; func1.prototype.x")->Int32Value());
105543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
10555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
10556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  t2->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(isolate, 42));
105573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  context->Global()->Set(v8_str("func2"), t2->GetFunction());
1055869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Default value of ReadOnly flag.
105593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK(CompileRun(
105603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      "(function() {"
105613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      "  descriptor = Object.getOwnPropertyDescriptor(func2, 'prototype');"
1056269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      "  return (descriptor['writable'] == true);"
105633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      "})()")->BooleanValue());
1056469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK_EQ(42, CompileRun("func2.prototype.x")->Int32Value());
105653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
105663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
105673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
10568402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei PopescuTHREADED_TEST(SetPrototypeThrows) {
10569402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  LocalContext context;
10570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
10571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(isolate);
10572402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
10573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
10574402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
10575402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Local<v8::Object> o0 = t->GetFunction()->NewInstance();
10576402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Local<v8::Object> o1 = t->GetFunction()->NewInstance();
10577402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
10578402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK(o0->SetPrototype(o1));
10579402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // If setting the prototype leads to the cycle, SetPrototype should
10580402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // return false and keep VM in sane state.
10581402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  v8::TryCatch try_catch;
10582402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK(!o1->SetPrototype(o0));
10583402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK(!try_catch.HasCaught());
10584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!CcTest::i_isolate()->has_pending_exception());
10585402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
10586402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK_EQ(42, CompileRun("function f() { return 42; }; f()")->Int32Value());
10587402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
10588402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
10589402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
10590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(FunctionRemovePrototype) {
10591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
10592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
10593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(isolate);
10594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
10595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
10596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  t1->RemovePrototype();
10597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::Function> fun = t1->GetFunction();
10598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context->Global()->Set(v8_str("fun"), fun);
10599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!CompileRun("'prototype' in fun")->BooleanValue());
10600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
10601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::TryCatch try_catch;
10602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("new fun()");
10603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(try_catch.HasCaught());
10604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
10605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  try_catch.Reset();
10606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fun->NewInstance();
10607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(try_catch.HasCaught());
10608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
10609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
10610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
10611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(GetterSetterExceptions) {
10612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
10613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
10614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(isolate);
10615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CompileRun(
10616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "function Foo() { };"
10617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "function Throw() { throw 5; };"
10618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "var x = { };"
10619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "x.__defineSetter__('set', Throw);"
10620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "x.__defineGetter__('get', Throw);");
10621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<v8::Object> x =
10622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Local<v8::Object>::Cast(context->Global()->Get(v8_str("x")));
10623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::TryCatch try_catch;
10624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  x->Set(v8_str("set"), v8::Integer::New(isolate, 8));
10625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  x->Get(v8_str("get"));
10626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  x->Set(v8_str("set"), v8::Integer::New(isolate, 8));
10627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  x->Get(v8_str("get"));
10628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  x->Set(v8_str("set"), v8::Integer::New(isolate, 8));
10629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  x->Get(v8_str("get"));
10630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  x->Set(v8_str("set"), v8::Integer::New(isolate, 8));
10631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  x->Get(v8_str("get"));
10632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
10633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(Constructor) {
10636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
10637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
10638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(isolate);
10639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
10640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  templ->SetClassName(v8_str("Fun"));
10641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Function> cons = templ->GetFunction();
10642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context->Global()->Set(v8_str("Fun"), cons);
10643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<v8::Object> inst = cons->NewInstance();
106443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  i::Handle<i::JSObject> obj(v8::Utils::OpenHandle(*inst));
106453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(obj->IsJSObject());
10646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Value> value = CompileRun("(new Fun()).constructor === Fun");
10647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(value->BooleanValue());
10648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
10649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10650257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
10651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void ConstructorCallback(
10652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::FunctionCallbackInfo<v8::Value>& args) {
10653257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ApiTestFuzzer::Fuzz();
10654257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Local<Object> This;
10655257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
10656257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (args.IsConstructCall()) {
10657257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Local<Object> Holder = args.Holder();
10658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    This = Object::New(args.GetIsolate());
10659257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Local<Value> proto = Holder->GetPrototype();
10660257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (proto->IsObject()) {
10661257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      This->SetPrototype(proto);
10662257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
10663257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
10664257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    This = args.This();
10665257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
10666257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
10667257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  This->Set(v8_str("a"), args[0]);
10668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  args.GetReturnValue().Set(This);
10669257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
10670257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
10671257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
10672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void FakeConstructorCallback(
10673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::FunctionCallbackInfo<v8::Value>& args) {
10674257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ApiTestFuzzer::Fuzz();
10675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  args.GetReturnValue().Set(args[0]);
10676257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
10677257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
10678257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
10679257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochTHREADED_TEST(ConstructorForObject) {
10680257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  LocalContext context;
10681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
10682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(isolate);
10683257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
10684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  { Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
10685257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    instance_template->SetCallAsFunctionHandler(ConstructorCallback);
10686257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Local<Object> instance = instance_template->NewInstance();
10687257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    context->Global()->Set(v8_str("obj"), instance);
10688257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    v8::TryCatch try_catch;
10689257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Local<Value> value;
10690257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(!try_catch.HasCaught());
10691257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
10692257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Call the Object's constructor with a 32-bit signed integer.
10693257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    value = CompileRun("(function() { var o = new obj(28); return o.a; })()");
10694257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(!try_catch.HasCaught());
10695257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(value->IsInt32());
10696257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_EQ(28, value->Int32Value());
10697257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
10698257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Local<Value> args1[] = { v8_num(28) };
10699257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Local<Value> value_obj1 = instance->CallAsConstructor(1, args1);
10700257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(value_obj1->IsObject());
10701257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Local<Object> object1 = Local<Object>::Cast(value_obj1);
10702257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    value = object1->Get(v8_str("a"));
10703257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(value->IsInt32());
10704257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(!try_catch.HasCaught());
10705257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_EQ(28, value->Int32Value());
10706257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
10707257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Call the Object's constructor with a String.
10708257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    value = CompileRun(
10709257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        "(function() { var o = new obj('tipli'); return o.a; })()");
10710257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(!try_catch.HasCaught());
10711257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(value->IsString());
10712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    String::Utf8Value string_value1(value->ToString());
10713257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_EQ("tipli", *string_value1);
10714257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
10715257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Local<Value> args2[] = { v8_str("tipli") };
10716257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Local<Value> value_obj2 = instance->CallAsConstructor(1, args2);
10717257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(value_obj2->IsObject());
10718257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Local<Object> object2 = Local<Object>::Cast(value_obj2);
10719257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    value = object2->Get(v8_str("a"));
10720257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(!try_catch.HasCaught());
10721257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(value->IsString());
10722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    String::Utf8Value string_value2(value->ToString());
10723257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_EQ("tipli", *string_value2);
10724257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
10725257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Call the Object's constructor with a Boolean.
10726257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    value = CompileRun("(function() { var o = new obj(true); return o.a; })()");
10727257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(!try_catch.HasCaught());
10728257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(value->IsBoolean());
10729257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_EQ(true, value->BooleanValue());
10730257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
10731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<Value> args3[] = { v8::True(isolate) };
10732257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Local<Value> value_obj3 = instance->CallAsConstructor(1, args3);
10733257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(value_obj3->IsObject());
10734257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Local<Object> object3 = Local<Object>::Cast(value_obj3);
10735257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    value = object3->Get(v8_str("a"));
10736257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(!try_catch.HasCaught());
10737257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(value->IsBoolean());
10738257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_EQ(true, value->BooleanValue());
10739257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
10740257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Call the Object's constructor with undefined.
10741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<Value> args4[] = { v8::Undefined(isolate) };
10742257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Local<Value> value_obj4 = instance->CallAsConstructor(1, args4);
10743257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(value_obj4->IsObject());
10744257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Local<Object> object4 = Local<Object>::Cast(value_obj4);
10745257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    value = object4->Get(v8_str("a"));
10746257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(!try_catch.HasCaught());
10747257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(value->IsUndefined());
10748257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
10749257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Call the Object's constructor with null.
10750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<Value> args5[] = { v8::Null(isolate) };
10751257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Local<Value> value_obj5 = instance->CallAsConstructor(1, args5);
10752257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(value_obj5->IsObject());
10753257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Local<Object> object5 = Local<Object>::Cast(value_obj5);
10754257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    value = object5->Get(v8_str("a"));
10755257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(!try_catch.HasCaught());
10756257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(value->IsNull());
10757257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
10758257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
10759257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check exception handling when there is no constructor set for the Object.
10760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  { Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
10761257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Local<Object> instance = instance_template->NewInstance();
10762257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    context->Global()->Set(v8_str("obj2"), instance);
10763257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    v8::TryCatch try_catch;
10764257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Local<Value> value;
10765257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(!try_catch.HasCaught());
10766257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
10767257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    value = CompileRun("new obj2(28)");
10768257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(try_catch.HasCaught());
10769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    String::Utf8Value exception_value1(try_catch.Exception());
10770257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_EQ("TypeError: object is not a function", *exception_value1);
10771257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    try_catch.Reset();
10772257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
10773257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Local<Value> args[] = { v8_num(29) };
10774257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    value = instance->CallAsConstructor(1, args);
10775257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(try_catch.HasCaught());
10776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    String::Utf8Value exception_value2(try_catch.Exception());
10777257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_EQ("TypeError: #<Object> is not a function", *exception_value2);
10778257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    try_catch.Reset();
10779257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
10780257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
10781257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check the case when constructor throws exception.
10782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  { Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
10783257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    instance_template->SetCallAsFunctionHandler(ThrowValue);
10784257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Local<Object> instance = instance_template->NewInstance();
10785257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    context->Global()->Set(v8_str("obj3"), instance);
10786257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    v8::TryCatch try_catch;
10787257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Local<Value> value;
10788257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(!try_catch.HasCaught());
10789257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
10790257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    value = CompileRun("new obj3(22)");
10791257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(try_catch.HasCaught());
10792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    String::Utf8Value exception_value1(try_catch.Exception());
10793257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_EQ("22", *exception_value1);
10794257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    try_catch.Reset();
10795257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
10796257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Local<Value> args[] = { v8_num(23) };
10797257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    value = instance->CallAsConstructor(1, args);
10798257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(try_catch.HasCaught());
10799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    String::Utf8Value exception_value2(try_catch.Exception());
10800257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_EQ("23", *exception_value2);
10801257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    try_catch.Reset();
10802257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
10803257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
10804257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check whether constructor returns with an object or non-object.
10805257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  { Local<FunctionTemplate> function_template =
10806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        FunctionTemplate::New(isolate, FakeConstructorCallback);
10807257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Local<Function> function = function_template->GetFunction();
10808257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Local<Object> instance1 = function;
10809257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    context->Global()->Set(v8_str("obj4"), instance1);
10810257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    v8::TryCatch try_catch;
10811257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Local<Value> value;
10812257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(!try_catch.HasCaught());
10813257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
10814257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(instance1->IsObject());
10815257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(instance1->IsFunction());
10816257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
10817257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    value = CompileRun("new obj4(28)");
10818257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(!try_catch.HasCaught());
10819257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(value->IsObject());
10820257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
10821257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Local<Value> args1[] = { v8_num(28) };
10822257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    value = instance1->CallAsConstructor(1, args1);
10823257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(!try_catch.HasCaught());
10824257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(value->IsObject());
10825257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
10826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
10827257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    instance_template->SetCallAsFunctionHandler(FakeConstructorCallback);
10828257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Local<Object> instance2 = instance_template->NewInstance();
10829257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    context->Global()->Set(v8_str("obj5"), instance2);
10830257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(!try_catch.HasCaught());
10831257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
10832257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(instance2->IsObject());
10833257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(!instance2->IsFunction());
10834257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
10835257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    value = CompileRun("new obj5(28)");
10836257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(!try_catch.HasCaught());
10837257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(!value->IsObject());
10838257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
10839257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Local<Value> args2[] = { v8_num(28) };
10840257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    value = instance2->CallAsConstructor(1, args2);
10841257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(!try_catch.HasCaught());
10842257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(!value->IsObject());
10843257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
10844257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
10845257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
10846257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
10847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(FunctionDescriptorException) {
10848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
10849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
10850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(isolate);
10851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
10852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  templ->SetClassName(v8_str("Fun"));
10853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Function> cons = templ->GetFunction();
10854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context->Global()->Set(v8_str("Fun"), cons);
10855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Value> value = CompileRun(
10856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "function test() {"
10857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  try {"
10858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "    (new Fun()).blah()"
10859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  } catch (e) {"
10860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "    var str = String(e);"
10861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // "    if (str.indexOf('TypeError') == -1) return 1;"
10862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // "    if (str.indexOf('[object Fun]') != -1) return 2;"
10863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // "    if (str.indexOf('#<Fun>') == -1) return 3;"
10864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "    return 0;"
10865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  }"
10866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  return 4;"
10867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "}"
10868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "test();");
10869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, value->Int32Value());
10870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
10871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(EvalAliasedDynamic) {
10874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext current;
10875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(current->GetIsolate());
10876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Tests where aliased eval can only be resolved dynamically.
10878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Script> script = v8_compile(
10879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "function f(x) { "
10880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  var foo = 2;"
10881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  with (x) { return eval('foo'); }"
10882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "}"
10883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "foo = 0;"
10884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "result1 = f(new Object());"
10885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "result2 = f(this);"
10886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "var x = new Object();"
10887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "x.eval = function(x) { return 1; };"
10888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "result3 = f(x);");
10889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  script->Run();
10890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, current->Global()->Get(v8_str("result1"))->Int32Value());
10891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, current->Global()->Get(v8_str("result2"))->Int32Value());
10892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, current->Global()->Get(v8_str("result3"))->Int32Value());
10893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::TryCatch try_catch;
10895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  script = v8_compile(
10896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "function f(x) { "
10897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  var bar = 2;"
10898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  with (x) { return eval('bar'); }"
10899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "}"
10900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "result4 = f(this)");
10901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  script->Run();
109023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(!try_catch.HasCaught());
109033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(2, current->Global()->Get(v8_str("result4"))->Int32Value());
109043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  try_catch.Reset();
10906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
10907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(CrossEval) {
10910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(CcTest::isolate());
10911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext other;
10912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext current;
10913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<String> token = v8_str("<security token>");
10915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  other->SetSecurityToken(token);
10916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  current->SetSecurityToken(token);
10917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
109183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up reference from current to other.
10919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  current->Global()->Set(v8_str("other"), other->Global());
10920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that new variables are introduced in other context.
10922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Script> script = v8_compile("other.eval('var foo = 1234')");
10923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  script->Run();
10924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Value> foo = other->Global()->Get(v8_str("foo"));
10925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1234, foo->Int32Value());
10926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(!current->Global()->Has(v8_str("foo")));
10927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that writing to non-existing properties introduces them in
10929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the other context.
10930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  script = v8_compile("other.eval('na = 1234')");
10931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  script->Run();
10932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1234, other->Global()->Get(v8_str("na"))->Int32Value());
10933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(!current->Global()->Has(v8_str("na")));
10934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that global variables in current context are not visible in other
10936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // context.
10937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::TryCatch try_catch;
10938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  script = v8_compile("var bar = 42; other.eval('bar');");
10939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Value> result = script->Run();
10940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(try_catch.HasCaught());
10941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  try_catch.Reset();
10942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that local variables in current context are not visible in other
10944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // context.
10945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  script = v8_compile(
10946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "(function() { "
10947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  var baz = 87;"
10948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  return other.eval('baz');"
10949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "})();");
10950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  result = script->Run();
10951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(try_catch.HasCaught());
10952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  try_catch.Reset();
10953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that global variables in the other environment are visible
10955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // when evaluting code.
10956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  other->Global()->Set(v8_str("bis"), v8_num(1234));
10957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  script = v8_compile("other.eval('bis')");
10958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1234, script->Run()->Int32Value());
10959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(!try_catch.HasCaught());
10960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the 'this' pointer points to the global object evaluating
10962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // code.
10963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  other->Global()->Set(v8_str("t"), other->Global());
10964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  script = v8_compile("other.eval('this == t')");
10965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  result = script->Run();
10966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(result->IsTrue());
10967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(!try_catch.HasCaught());
10968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that variables introduced in with-statement are not visible in
10970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // other context.
10971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  script = v8_compile("with({x:2}){other.eval('x')}");
10972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  result = script->Run();
10973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(try_catch.HasCaught());
10974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  try_catch.Reset();
10975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that you cannot use 'eval.call' with another object than the
10977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // current global object.
10978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  script = v8_compile("other.y = 1; eval.call(other, 'y')");
10979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  result = script->Run();
10980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(try_catch.HasCaught());
10981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
10982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test that calling eval in a context which has been detached from
10985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// its global throws an exception.  This behavior is consistent with
10986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// other JavaScript implementations.
10987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(EvalInDetachedGlobal) {
10988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
10989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
10990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<Context> context0 = Context::New(isolate);
10992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<Context> context1 = Context::New(isolate);
10993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
109943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up function in context0 that uses eval from context0.
10995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context0->Enter();
10996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Value> fun =
10997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      CompileRun("var x = 42;"
10998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                 "(function() {"
10999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                 "  var e = eval;"
11000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                 "  return function(s) { return e(s); }"
11001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                 "})()");
11002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context0->Exit();
11003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Put the function into context1 and call it before and after
11005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // detaching the global.  Before detaching, the call succeeds and
11006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // after detaching and exception is thrown.
11007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context1->Enter();
11008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context1->Global()->Set(v8_str("fun"), fun);
11009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Value> x_value = CompileRun("fun('x')");
11010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(42, x_value->Int32Value());
11011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context0->DetachGlobal();
11012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::TryCatch catcher;
11013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  x_value = CompileRun("fun('x')");
11014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(x_value.IsEmpty());
11015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(catcher.HasCaught());
11016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context1->Exit();
11017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
11018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(CrossLazyLoad) {
11021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(CcTest::isolate());
11022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext other;
11023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext current;
11024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<String> token = v8_str("<security token>");
11026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  other->SetSecurityToken(token);
11027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  current->SetSecurityToken(token);
11028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
110293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up reference from current to other.
11030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  current->Global()->Set(v8_str("other"), other->Global());
11031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Trigger lazy loading in other context.
11033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Script> script = v8_compile("other.eval('new Date(42)')");
11034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Value> value = script->Run();
11035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(42.0, value->NumberValue());
11036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
11037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void call_as_function(const v8::FunctionCallbackInfo<v8::Value>& args) {
11040402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  ApiTestFuzzer::Fuzz();
11041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (args.IsConstructCall()) {
11042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (args[0]->IsInt32()) {
11043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      args.GetReturnValue().Set(v8_num(-args[0]->Int32Value()));
11044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return;
11045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
11046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
11047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  args.GetReturnValue().Set(args[0]);
11049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
11050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
11051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
11052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void ReturnThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
11053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  args.GetReturnValue().Set(args.This());
11054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
11055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test that a call handler can be set for objects which will allow
11058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// non-function objects created through the API to be called as
11059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// functions.
11060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(CallAsFunction) {
11061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
11062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
11063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
11064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
11066257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Local<ObjectTemplate> instance_template = t->InstanceTemplate();
11067257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    instance_template->SetCallAsFunctionHandler(call_as_function);
11068257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Local<v8::Object> instance = t->GetFunction()->NewInstance();
11069257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    context->Global()->Set(v8_str("obj"), instance);
11070257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    v8::TryCatch try_catch;
11071257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Local<Value> value;
11072257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(!try_catch.HasCaught());
11073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11074257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    value = CompileRun("obj(42)");
11075257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(!try_catch.HasCaught());
11076257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_EQ(42, value->Int32Value());
11077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11078257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    value = CompileRun("(function(o){return o(49)})(obj)");
11079257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(!try_catch.HasCaught());
11080257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_EQ(49, value->Int32Value());
11081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11082257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // test special case of call as function
11083257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    value = CompileRun("[obj]['0'](45)");
11084257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(!try_catch.HasCaught());
11085257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_EQ(45, value->Int32Value());
11086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11087257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    value = CompileRun("obj.call = Function.prototype.call;"
11088257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                       "obj.call(null, 87)");
11089257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(!try_catch.HasCaught());
11090257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_EQ(87, value->Int32Value());
11091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11092257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Regression tests for bug #1116356: Calling call through call/apply
11093257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // must work for non-function receivers.
11094257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    const char* apply_99 = "Function.prototype.call.apply(obj, [this, 99])";
11095257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    value = CompileRun(apply_99);
11096257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(!try_catch.HasCaught());
11097257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_EQ(99, value->Int32Value());
11098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11099257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    const char* call_17 = "Function.prototype.call.call(obj, this, 17)";
11100257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    value = CompileRun(call_17);
11101257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(!try_catch.HasCaught());
11102257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_EQ(17, value->Int32Value());
11103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11104257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Check that the call-as-function handler can be called through
11105257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // new.
11106257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    value = CompileRun("new obj(43)");
11107257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(!try_catch.HasCaught());
11108257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_EQ(-43, value->Int32Value());
11109257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
11110257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Check that the call-as-function handler can be called through
11111257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // the API.
11112257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    v8::Handle<Value> args[] = { v8_num(28) };
11113257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    value = instance->CallAsFunction(instance, 1, args);
11114257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(!try_catch.HasCaught());
11115257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_EQ(28, value->Int32Value());
11116257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
11117257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
11118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
111193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Local<ObjectTemplate> instance_template(t->InstanceTemplate());
111203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    USE(instance_template);
11121257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Local<v8::Object> instance = t->GetFunction()->NewInstance();
11122257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    context->Global()->Set(v8_str("obj2"), instance);
11123257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    v8::TryCatch try_catch;
11124257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Local<Value> value;
11125257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(!try_catch.HasCaught());
11126257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
11127257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Call an object without call-as-function handler through the JS
11128257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    value = CompileRun("obj2(28)");
11129257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(value.IsEmpty());
11130257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(try_catch.HasCaught());
11131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    String::Utf8Value exception_value1(try_catch.Exception());
11132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // TODO(verwaest): Better message
11133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ("TypeError: object is not a function",
11134257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch             *exception_value1);
11135257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    try_catch.Reset();
11136257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
11137257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Call an object without call-as-function handler through the API
11138257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    value = CompileRun("obj2(28)");
11139257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    v8::Handle<Value> args[] = { v8_num(28) };
11140257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    value = instance->CallAsFunction(instance, 1, args);
11141257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(value.IsEmpty());
11142257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(try_catch.HasCaught());
11143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    String::Utf8Value exception_value2(try_catch.Exception());
11144257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_EQ("TypeError: [object Object] is not a function", *exception_value2);
11145257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    try_catch.Reset();
11146257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
11147257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
11148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
11149257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Local<ObjectTemplate> instance_template = t->InstanceTemplate();
11150257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    instance_template->SetCallAsFunctionHandler(ThrowValue);
11151257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Local<v8::Object> instance = t->GetFunction()->NewInstance();
11152257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    context->Global()->Set(v8_str("obj3"), instance);
11153257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    v8::TryCatch try_catch;
11154257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Local<Value> value;
11155257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(!try_catch.HasCaught());
11156257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
11157257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Catch the exception which is thrown by call-as-function handler
11158257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    value = CompileRun("obj3(22)");
11159257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(try_catch.HasCaught());
11160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    String::Utf8Value exception_value1(try_catch.Exception());
11161257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_EQ("22", *exception_value1);
11162257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    try_catch.Reset();
11163257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
11164257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    v8::Handle<Value> args[] = { v8_num(23) };
11165257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    value = instance->CallAsFunction(instance, 1, args);
11166257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(try_catch.HasCaught());
11167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    String::Utf8Value exception_value2(try_catch.Exception());
11168257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_EQ("23", *exception_value2);
11169257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    try_catch.Reset();
11170257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
11171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
11172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
11173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<ObjectTemplate> instance_template = t->InstanceTemplate();
11174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    instance_template->SetCallAsFunctionHandler(ReturnThis);
11175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<v8::Object> instance = t->GetFunction()->NewInstance();
11176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
11177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<v8::Value> a1 =
11178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        instance->CallAsFunction(v8::Undefined(isolate), 0, NULL);
11179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(a1->StrictEquals(instance));
11180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<v8::Value> a2 =
11181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        instance->CallAsFunction(v8::Null(isolate), 0, NULL);
11182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(a2->StrictEquals(instance));
11183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<v8::Value> a3 =
11184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        instance->CallAsFunction(v8_num(42), 0, NULL);
11185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(a3->StrictEquals(instance));
11186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<v8::Value> a4 =
11187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        instance->CallAsFunction(v8_str("hello"), 0, NULL);
11188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(a4->StrictEquals(instance));
11189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<v8::Value> a5 =
11190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        instance->CallAsFunction(v8::True(isolate), 0, NULL);
11191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(a5->StrictEquals(instance));
11192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
11193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
11194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  { CompileRun(
11195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "function ReturnThisSloppy() {"
11196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  return this;"
11197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "}"
11198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "function ReturnThisStrict() {"
11199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  'use strict';"
11200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  return this;"
11201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "}");
11202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<Function> ReturnThisSloppy =
11203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Local<Function>::Cast(
11204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            context->Global()->Get(v8_str("ReturnThisSloppy")));
11205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<Function> ReturnThisStrict =
11206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Local<Function>::Cast(
11207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            context->Global()->Get(v8_str("ReturnThisStrict")));
11208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
11209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<v8::Value> a1 =
11210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ReturnThisSloppy->CallAsFunction(v8::Undefined(isolate), 0, NULL);
11211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(a1->StrictEquals(context->Global()));
11212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<v8::Value> a2 =
11213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ReturnThisSloppy->CallAsFunction(v8::Null(isolate), 0, NULL);
11214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(a2->StrictEquals(context->Global()));
11215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<v8::Value> a3 =
11216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ReturnThisSloppy->CallAsFunction(v8_num(42), 0, NULL);
11217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(a3->IsNumberObject());
11218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(42.0, a3.As<v8::NumberObject>()->ValueOf());
11219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<v8::Value> a4 =
11220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ReturnThisSloppy->CallAsFunction(v8_str("hello"), 0, NULL);
11221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(a4->IsStringObject());
11222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(a4.As<v8::StringObject>()->ValueOf()->StrictEquals(v8_str("hello")));
11223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<v8::Value> a5 =
11224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ReturnThisSloppy->CallAsFunction(v8::True(isolate), 0, NULL);
11225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(a5->IsBooleanObject());
11226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(a5.As<v8::BooleanObject>()->ValueOf());
11227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
11228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<v8::Value> a6 =
11229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ReturnThisStrict->CallAsFunction(v8::Undefined(isolate), 0, NULL);
11230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(a6->IsUndefined());
11231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<v8::Value> a7 =
11232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ReturnThisStrict->CallAsFunction(v8::Null(isolate), 0, NULL);
11233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(a7->IsNull());
11234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<v8::Value> a8 =
11235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ReturnThisStrict->CallAsFunction(v8_num(42), 0, NULL);
11236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(a8->StrictEquals(v8_num(42)));
11237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<v8::Value> a9 =
11238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ReturnThisStrict->CallAsFunction(v8_str("hello"), 0, NULL);
11239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(a9->StrictEquals(v8_str("hello")));
11240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<v8::Value> a10 =
11241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ReturnThisStrict->CallAsFunction(v8::True(isolate), 0, NULL);
11242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(a10->StrictEquals(v8::True(isolate)));
11243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
11244257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
11245257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
11246257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
11247257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Check whether a non-function object is callable.
11248257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochTHREADED_TEST(CallableObject) {
11249257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  LocalContext context;
11250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
11251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
11252257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
11253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  { Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
11254257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    instance_template->SetCallAsFunctionHandler(call_as_function);
11255257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Local<Object> instance = instance_template->NewInstance();
11256257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    v8::TryCatch try_catch;
11257257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
11258257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(instance->IsCallable());
11259257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(!try_catch.HasCaught());
11260257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
11261257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
11262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  { Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
11263257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Local<Object> instance = instance_template->NewInstance();
11264257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    v8::TryCatch try_catch;
11265257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
11266257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(!instance->IsCallable());
11267257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(!try_catch.HasCaught());
11268257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
11269257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
11270257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  { Local<FunctionTemplate> function_template =
11271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        FunctionTemplate::New(isolate, call_as_function);
11272257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Local<Function> function = function_template->GetFunction();
11273257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Local<Object> instance = function;
11274257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    v8::TryCatch try_catch;
11275257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
11276257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(instance->IsCallable());
11277257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(!try_catch.HasCaught());
11278257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
11279257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
11280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  { Local<FunctionTemplate> function_template = FunctionTemplate::New(isolate);
11281257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Local<Function> function = function_template->GetFunction();
11282257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Local<Object> instance = function;
11283257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    v8::TryCatch try_catch;
11284257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
11285257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(instance->IsCallable());
11286257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(!try_catch.HasCaught());
11287257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
11288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
11289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic int Recurse(v8::Isolate* isolate, int depth, int iterations) {
11292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
11293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (depth == 0) return v8::HandleScope::NumberOfHandles(isolate);
11294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < iterations; i++) {
11295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<v8::Number> n(v8::Integer::New(isolate, 42));
11296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
11297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return Recurse(isolate, depth - 1, iterations);
11298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
11299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(HandleIteration) {
11302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static const int kIterations = 500;
11303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static const int kNesting = 200;
11304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
11305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
11306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope0(isolate);
11307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
11308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {
11309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope1(isolate);
11310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
11311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (int i = 0; i < kIterations; i++) {
11312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Local<v8::Number> n(v8::Integer::New(CcTest::isolate(), 42));
11313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CHECK_EQ(i + 1, v8::HandleScope::NumberOfHandles(isolate));
11314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
11315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(kIterations, v8::HandleScope::NumberOfHandles(isolate));
11317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    {
11318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::HandleScope scope2(CcTest::isolate());
11319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      for (int j = 0; j < kIterations; j++) {
11320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Local<v8::Number> n(v8::Integer::New(CcTest::isolate(), 42));
11321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        CHECK_EQ(j + 1 + kIterations,
11322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 v8::HandleScope::NumberOfHandles(isolate));
11323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
11324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
11325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(kIterations, v8::HandleScope::NumberOfHandles(isolate));
11326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
11327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
11328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(kNesting * kIterations, Recurse(isolate, kNesting, kIterations));
11329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
11330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void InterceptorHasOwnPropertyGetter(
11333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Local<String> name,
11334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Value>& info) {
11335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
11336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
11337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(InterceptorHasOwnProperty) {
11340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
11341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
11342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
11343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(isolate);
11344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<v8::ObjectTemplate> instance_templ = fun_templ->InstanceTemplate();
11345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  instance_templ->SetNamedPropertyHandler(InterceptorHasOwnPropertyGetter);
11346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Function> function = fun_templ->GetFunction();
11347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context->Global()->Set(v8_str("constructor"), function);
11348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> value = CompileRun(
11349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "var o = new constructor();"
11350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "o.hasOwnProperty('ostehaps');");
11351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(false, value->BooleanValue());
11352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  value = CompileRun(
11353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "o.ostehaps = 42;"
11354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "o.hasOwnProperty('ostehaps');");
11355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(true, value->BooleanValue());
11356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  value = CompileRun(
11357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "var p = new constructor();"
11358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "p.hasOwnProperty('ostehaps');");
11359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(false, value->BooleanValue());
11360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
11361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void InterceptorHasOwnPropertyGetterGC(
11364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Local<String> name,
11365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Value>& info) {
11366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
11367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
11368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
11369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(InterceptorHasOwnPropertyCausingGC) {
11372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
11373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
11374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
11375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(isolate);
11376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<v8::ObjectTemplate> instance_templ = fun_templ->InstanceTemplate();
11377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  instance_templ->SetNamedPropertyHandler(InterceptorHasOwnPropertyGetterGC);
11378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Function> function = fun_templ->GetFunction();
11379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context->Global()->Set(v8_str("constructor"), function);
11380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Let's first make some stuff so we can be sure to get a good GC.
11381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CompileRun(
11382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "function makestr(size) {"
11383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "  switch (size) {"
11384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "    case 1: return 'f';"
11385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "    case 2: return 'fo';"
11386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "    case 3: return 'foo';"
11387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "  }"
11388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "  return makestr(size >> 1) + makestr((size + 1) >> 1);"
11389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "}"
11390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "var x = makestr(12345);"
11391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "x = makestr(31415);"
11392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "x = makestr(23456);");
11393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> value = CompileRun(
11394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "var o = new constructor();"
11395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "o.__proto__ = new String(x);"
11396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "o.hasOwnProperty('ostehaps');");
11397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(false, value->BooleanValue());
11398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
11399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtypedef void (*NamedPropertyGetter)(
11402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<String> property,
11403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Value>& info);
11404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void CheckInterceptorLoadIC(NamedPropertyGetter getter,
11407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   const char* source,
11408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   int expected) {
11409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
11410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
11411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
114128a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  templ->SetNamedPropertyHandler(getter, 0, 0, 0, 0, v8_str("data"));
11413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
11414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context->Global()->Set(v8_str("o"), templ->NewInstance());
11415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> value = CompileRun(source);
11416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(expected, value->Int32Value());
11417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
11418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void InterceptorLoadICGetter(
11421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<String> name,
11422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Value>& info) {
11423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
11424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
11425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(isolate, info.GetIsolate());
114268a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  CHECK_EQ(v8_str("data"), info.Data());
114278a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  CHECK_EQ(v8_str("x"), name);
11428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(v8::Integer::New(isolate, 42));
11429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
11430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// This test should hit the load IC for the interceptor case.
11433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(InterceptorLoadIC) {
11434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckInterceptorLoadIC(InterceptorLoadICGetter,
11435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "var result = 0;"
11436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "for (var i = 0; i < 1000; i++) {"
11437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  result = o.x;"
11438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "}",
11439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    42);
11440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
11441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Below go several tests which verify that JITing for various
11444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// configurations of interceptor and explicit fields works fine
11445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (those cases are special cased to get better performance).
11446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void InterceptorLoadXICGetter(
11448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<String> name,
11449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Value>& info) {
11450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
11451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(
11452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8_str("x")->Equals(name) ?
11453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          v8::Handle<v8::Value>(v8::Integer::New(info.GetIsolate(), 42)) :
11454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          v8::Handle<v8::Value>());
11455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
11456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(InterceptorLoadICWithFieldOnHolder) {
11459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckInterceptorLoadIC(InterceptorLoadXICGetter,
11460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "var result = 0;"
11461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "o.y = 239;"
11462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "for (var i = 0; i < 1000; i++) {"
11463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  result = o.y;"
11464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "}",
11465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    239);
11466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
11467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(InterceptorLoadICWithSubstitutedProto) {
11470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckInterceptorLoadIC(InterceptorLoadXICGetter,
11471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "var result = 0;"
11472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "o.__proto__ = { 'y': 239 };"
11473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "for (var i = 0; i < 1000; i++) {"
11474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  result = o.y + o.x;"
11475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "}",
11476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    239 + 42);
11477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
11478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(InterceptorLoadICWithPropertyOnProto) {
11481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckInterceptorLoadIC(InterceptorLoadXICGetter,
11482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "var result = 0;"
11483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "o.__proto__.y = 239;"
11484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "for (var i = 0; i < 1000; i++) {"
11485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  result = o.y + o.x;"
11486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "}",
11487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    239 + 42);
11488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
11489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(InterceptorLoadICUndefined) {
11492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckInterceptorLoadIC(InterceptorLoadXICGetter,
11493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "var result = 0;"
11494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "for (var i = 0; i < 1000; i++) {"
11495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  result = (o.y == undefined) ? 239 : 42;"
11496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "}",
11497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    239);
11498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
11499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(InterceptorLoadICWithOverride) {
11502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckInterceptorLoadIC(InterceptorLoadXICGetter,
11503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "fst = new Object();  fst.__proto__ = o;"
11504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "snd = new Object();  snd.__proto__ = fst;"
11505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "var result1 = 0;"
11506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "for (var i = 0; i < 1000;  i++) {"
11507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  result1 = snd.x;"
11508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "}"
11509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "fst.x = 239;"
11510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "var result = 0;"
11511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "for (var i = 0; i < 1000; i++) {"
11512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  result = snd.x;"
11513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "}"
11514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "result + result1",
11515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    239 + 42);
11516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
11517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test the case when we stored field into
11520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// a stub, but interceptor produced value on its own.
11521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(InterceptorLoadICFieldNotNeeded) {
11522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckInterceptorLoadIC(InterceptorLoadXICGetter,
11523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "proto = new Object();"
11524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "o.__proto__ = proto;"
11525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "proto.x = 239;"
11526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "for (var i = 0; i < 1000; i++) {"
11527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  o.x;"
11528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Now it should be ICed and keep a reference to x defined on proto
11529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "}"
11530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "var result = 0;"
11531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "for (var i = 0; i < 1000; i++) {"
11532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  result += o.x;"
11533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "}"
11534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "result;",
11535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    42 * 1000);
11536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
11537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test the case when we stored field into
11540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// a stub, but it got invalidated later on.
11541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(InterceptorLoadICInvalidatedField) {
11542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckInterceptorLoadIC(InterceptorLoadXICGetter,
11543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "proto1 = new Object();"
11544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "proto2 = new Object();"
11545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "o.__proto__ = proto1;"
11546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "proto1.__proto__ = proto2;"
11547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "proto2.y = 239;"
11548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "for (var i = 0; i < 1000; i++) {"
11549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  o.y;"
11550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Now it should be ICed and keep a reference to y defined on proto2
11551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "}"
11552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "proto1.y = 42;"
11553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "var result = 0;"
11554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "for (var i = 0; i < 1000; i++) {"
11555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  result += o.y;"
11556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "}"
11557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "result;",
11558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    42 * 1000);
11559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
11560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
115626ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic int interceptor_load_not_handled_calls = 0;
11563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void InterceptorLoadNotHandled(
11564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<String> name,
11565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Value>& info) {
115666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ++interceptor_load_not_handled_calls;
115676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
115686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
115696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
115706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Test how post-interceptor lookups are done in the non-cacheable
115716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// case: the interceptor should not be invoked during this lookup.
115726ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockTHREADED_TEST(InterceptorLoadICPostInterceptor) {
115736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  interceptor_load_not_handled_calls = 0;
115746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CheckInterceptorLoadIC(InterceptorLoadNotHandled,
115756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    "receiver = new Object();"
115766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    "receiver.__proto__ = o;"
115776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    "proto = new Object();"
115786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    "/* Make proto a slow-case object. */"
115796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    "for (var i = 0; i < 1000; i++) {"
115806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    "  proto[\"xxxxxxxx\" + i] = [];"
115816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    "}"
115826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    "proto.x = 17;"
115836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    "o.__proto__ = proto;"
115846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    "var result = 0;"
115856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    "for (var i = 0; i < 1000; i++) {"
115866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    "  result += receiver.x;"
115876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    "}"
115886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    "result;",
115896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    17 * 1000);
115906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(1000, interceptor_load_not_handled_calls);
115916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
115926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
115936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test the case when we stored field into
11595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// a stub, but it got invalidated later on due to override on
11596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// global object which is between interceptor and fields' holders.
11597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(InterceptorLoadICInvalidatedFieldViaGlobal) {
11598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckInterceptorLoadIC(InterceptorLoadXICGetter,
11599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "o.__proto__ = this;"  // set a global to be a proto of o.
11600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "this.__proto__.y = 239;"
11601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "for (var i = 0; i < 10; i++) {"
11602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  if (o.y != 239) throw 'oops: ' + o.y;"
11603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Now it should be ICed and keep a reference to y defined on field_holder.
11604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "}"
11605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "this.y = 42;"  // Assign on a global.
11606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "var result = 0;"
11607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "for (var i = 0; i < 10; i++) {"
11608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  result += o.y;"
11609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "}"
11610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "result;",
11611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    42 * 10);
11612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
11613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void SetOnThis(Local<String> name,
11616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Local<Value> value,
11617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      const v8::PropertyCallbackInfo<void>& info) {
11618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Object>::Cast(info.This())->ForceSet(name, value);
11619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
11620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(InterceptorLoadICWithCallbackOnHolder) {
11623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
11624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
11625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
11626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  templ->SetNamedPropertyHandler(InterceptorLoadXICGetter);
11627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  templ->SetAccessor(v8_str("y"), Return239Callback);
11628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
11629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context->Global()->Set(v8_str("o"), templ->NewInstance());
116307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
116317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Check the case when receiver and interceptor's holder
116327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // are the same objects.
11633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> value = CompileRun(
11634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "var result = 0;"
11635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "for (var i = 0; i < 7; i++) {"
11636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "  result = o.y;"
11637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "}");
11638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(239, value->Int32Value());
116397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
116407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Check the case when interceptor's holder is in proto chain
116417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // of receiver.
116427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  value = CompileRun(
116437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      "r = { __proto__: o };"
116447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      "var result = 0;"
116457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      "for (var i = 0; i < 7; i++) {"
116467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      "  result = r.y;"
116477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      "}");
116487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  CHECK_EQ(239, value->Int32Value());
11649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
11650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(InterceptorLoadICWithCallbackOnProto) {
11653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
11654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
11655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
11656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
11657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New(isolate);
11658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  templ_p->SetAccessor(v8_str("y"), Return239Callback);
11659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
11661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context->Global()->Set(v8_str("o"), templ_o->NewInstance());
11662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context->Global()->Set(v8_str("p"), templ_p->NewInstance());
11663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
116647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Check the case when receiver and interceptor's holder
116657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // are the same objects.
11666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> value = CompileRun(
11667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "o.__proto__ = p;"
11668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "var result = 0;"
11669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "for (var i = 0; i < 7; i++) {"
11670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "  result = o.x + o.y;"
11671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "}");
11672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(239 + 42, value->Int32Value());
116737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
116747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Check the case when interceptor's holder is in proto chain
116757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // of receiver.
116767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  value = CompileRun(
116777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      "r = { __proto__: o };"
116787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      "var result = 0;"
116797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      "for (var i = 0; i < 7; i++) {"
116807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      "  result = r.x + r.y;"
116817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      "}");
116827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  CHECK_EQ(239 + 42, value->Int32Value());
11683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
11684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(InterceptorLoadICForCallbackWithOverride) {
11687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
11688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
11689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
11690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  templ->SetNamedPropertyHandler(InterceptorLoadXICGetter);
11691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  templ->SetAccessor(v8_str("y"), Return239Callback);
11692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
11694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context->Global()->Set(v8_str("o"), templ->NewInstance());
11695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> value = CompileRun(
11697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "fst = new Object();  fst.__proto__ = o;"
11698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "snd = new Object();  snd.__proto__ = fst;"
11699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "var result1 = 0;"
11700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "for (var i = 0; i < 7;  i++) {"
11701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  result1 = snd.x;"
11702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "}"
11703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "fst.x = 239;"
11704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "var result = 0;"
11705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "for (var i = 0; i < 7; i++) {"
11706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  result = snd.x;"
11707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "}"
11708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "result + result1");
11709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(239 + 42, value->Int32Value());
11710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
11711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test the case when we stored callback into
11714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// a stub, but interceptor produced value on its own.
11715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(InterceptorLoadICCallbackNotNeeded) {
11716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
11717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
11718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
11719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
11720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New(isolate);
11721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  templ_p->SetAccessor(v8_str("y"), Return239Callback);
11722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
11724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context->Global()->Set(v8_str("o"), templ_o->NewInstance());
11725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context->Global()->Set(v8_str("p"), templ_p->NewInstance());
11726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> value = CompileRun(
11728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "o.__proto__ = p;"
11729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "for (var i = 0; i < 7; i++) {"
11730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  o.x;"
11731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Now it should be ICed and keep a reference to x defined on p
11732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "}"
11733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "var result = 0;"
11734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "for (var i = 0; i < 7; i++) {"
11735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  result += o.x;"
11736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "}"
11737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "result");
11738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(42 * 7, value->Int32Value());
11739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
11740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test the case when we stored callback into
11743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// a stub, but it got invalidated later on.
11744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(InterceptorLoadICInvalidatedCallback) {
11745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
11746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
11747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
11748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
11749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New(isolate);
11750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  templ_p->SetAccessor(v8_str("y"), Return239Callback, SetOnThis);
11751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
11753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context->Global()->Set(v8_str("o"), templ_o->NewInstance());
11754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context->Global()->Set(v8_str("p"), templ_p->NewInstance());
11755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> value = CompileRun(
11757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "inbetween = new Object();"
11758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "o.__proto__ = inbetween;"
11759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "inbetween.__proto__ = p;"
11760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "for (var i = 0; i < 10; i++) {"
11761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  o.y;"
11762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Now it should be ICed and keep a reference to y defined on p
11763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "}"
11764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "inbetween.y = 42;"
11765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "var result = 0;"
11766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "for (var i = 0; i < 10; i++) {"
11767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  result += o.y;"
11768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "}"
11769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "result");
11770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(42 * 10, value->Int32Value());
11771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
11772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test the case when we stored callback into
11775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// a stub, but it got invalidated later on due to override on
11776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// global object which is between interceptor and callbacks' holders.
11777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(InterceptorLoadICInvalidatedCallbackViaGlobal) {
11778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
11779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
11780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
11781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
11782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New(isolate);
11783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  templ_p->SetAccessor(v8_str("y"), Return239Callback, SetOnThis);
11784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
11786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context->Global()->Set(v8_str("o"), templ_o->NewInstance());
11787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context->Global()->Set(v8_str("p"), templ_p->NewInstance());
11788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> value = CompileRun(
11790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "o.__proto__ = this;"
11791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "this.__proto__ = p;"
11792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "for (var i = 0; i < 10; i++) {"
11793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  if (o.y != 239) throw 'oops: ' + o.y;"
11794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Now it should be ICed and keep a reference to y defined on p
11795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "}"
11796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "this.y = 42;"
11797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "var result = 0;"
11798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "for (var i = 0; i < 10; i++) {"
11799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  result += o.y;"
11800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "}"
11801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "result");
11802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(42 * 10, value->Int32Value());
11803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
11804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void InterceptorLoadICGetter0(
11807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<String> name,
11808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Value>& info) {
11809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
11810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(v8_str("x")->Equals(name));
11811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(v8::Integer::New(info.GetIsolate(), 0));
11812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
11813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(InterceptorReturningZero) {
11816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckInterceptorLoadIC(InterceptorLoadICGetter0,
11817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     "o.x == undefined ? 1 : 0",
11818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     0);
11819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
11820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void InterceptorStoreICSetter(
11823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<String> key,
11824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<Value> value,
11825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Value>& info) {
11826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(v8_str("x")->Equals(key));
11827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(42, value->Int32Value());
11828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(value);
11829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
11830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// This test should hit the store IC for the interceptor case.
11833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(InterceptorStoreIC) {
11834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
11835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
11836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
11837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  templ->SetNamedPropertyHandler(InterceptorLoadICGetter,
118388a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                                 InterceptorStoreICSetter,
118398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                                 0, 0, 0, v8_str("data"));
11840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
11841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context->Global()->Set(v8_str("o"), templ->NewInstance());
118423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileRun(
118433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "for (var i = 0; i < 1000; i++) {"
118443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "  o.x = 42;"
118453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "}");
11846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
11847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(InterceptorStoreICWithNoSetter) {
11850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
11851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
11852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
11853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  templ->SetNamedPropertyHandler(InterceptorLoadXICGetter);
11854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
11855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context->Global()->Set(v8_str("o"), templ->NewInstance());
11856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> value = CompileRun(
11857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "for (var i = 0; i < 1000; i++) {"
11858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  o.y = 239;"
11859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "}"
11860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "42 + o.y");
11861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(239 + 42, value->Int32Value());
11862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
11863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockv8::Handle<Value> call_ic_function;
11868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockv8::Handle<Value> call_ic_function2;
11869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockv8::Handle<Value> call_ic_function3;
11870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void InterceptorCallICGetter(
11872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<String> name,
11873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Value>& info) {
11874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
11875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(v8_str("x")->Equals(name));
11876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(call_ic_function);
11877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
11878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// This test should hit the call IC for the interceptor case.
11881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(InterceptorCallIC) {
11882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
11883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
11884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
11885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  templ->SetNamedPropertyHandler(InterceptorCallICGetter);
11886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
11887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context->Global()->Set(v8_str("o"), templ->NewInstance());
11888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  call_ic_function =
11889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      v8_compile("function f(x) { return x + 1; }; f")->Run();
11890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> value = CompileRun(
11891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "var result = 0;"
11892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "for (var i = 0; i < 1000; i++) {"
11893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  result = o.x(41);"
11894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "}");
11895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(42, value->Int32Value());
11896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
11897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// This test checks that if interceptor doesn't provide
11900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// a value, we can fetch regular value.
11901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(InterceptorCallICSeesOthers) {
11902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
11903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
11904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
11905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  templ->SetNamedPropertyHandler(NoBlockGetterX);
11906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
11907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context->Global()->Set(v8_str("o"), templ->NewInstance());
11908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> value = CompileRun(
11909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "o.x = function f(x) { return x + 1; };"
11910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "var result = 0;"
11911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "for (var i = 0; i < 7; i++) {"
11912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  result = o.x(41);"
11913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "}");
11914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(42, value->Int32Value());
11915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
11916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic v8::Handle<Value> call_ic_function4;
11919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void InterceptorCallICGetter4(
11920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<String> name,
11921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Value>& info) {
11922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
11923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(v8_str("x")->Equals(name));
11924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(call_ic_function4);
11925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
11926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// This test checks that if interceptor provides a function,
11929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// even if we cached shadowed variant, interceptor's function
11930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// is invoked
11931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(InterceptorCallICCacheableNotNeeded) {
11932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
11933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
11934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
11935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  templ->SetNamedPropertyHandler(InterceptorCallICGetter4);
11936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
11937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context->Global()->Set(v8_str("o"), templ->NewInstance());
11938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  call_ic_function4 =
11939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      v8_compile("function f(x) { return x - 1; }; f")->Run();
11940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> value = CompileRun(
11941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "Object.getPrototypeOf(o).x = function(x) { return x + 1; };"
11942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "var result = 0;"
11943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "for (var i = 0; i < 1000; i++) {"
11944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  result = o.x(42);"
11945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "}");
11946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(41, value->Int32Value());
11947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
11948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test the case when we stored cacheable lookup into
11951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// a stub, but it got invalidated later on
11952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(InterceptorCallICInvalidatedCacheable) {
11953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
11954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
11955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
11956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  templ->SetNamedPropertyHandler(NoBlockGetterX);
11957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
11958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context->Global()->Set(v8_str("o"), templ->NewInstance());
11959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> value = CompileRun(
11960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "proto1 = new Object();"
11961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "proto2 = new Object();"
11962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "o.__proto__ = proto1;"
11963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "proto1.__proto__ = proto2;"
11964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "proto2.y = function(x) { return x + 1; };"
11965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Invoke it many times to compile a stub
11966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "for (var i = 0; i < 7; i++) {"
11967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  o.y(42);"
11968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "}"
11969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "proto1.y = function(x) { return x - 1; };"
11970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "var result = 0;"
11971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "for (var i = 0; i < 7; i++) {"
11972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  result += o.y(42);"
11973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "}");
11974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(41 * 7, value->Int32Value());
11975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
11976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// This test checks that if interceptor doesn't provide a function,
11979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// cached constant function is used
11980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(InterceptorCallICConstantFunctionUsed) {
11981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
11982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
11983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
11984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  templ->SetNamedPropertyHandler(NoBlockGetterX);
11985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
11986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context->Global()->Set(v8_str("o"), templ->NewInstance());
11987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> value = CompileRun(
11988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "function inc(x) { return x + 1; };"
11989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "inc(1);"
11990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "o.x = inc;"
11991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "var result = 0;"
11992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "for (var i = 0; i < 1000; i++) {"
11993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  result = o.x(42);"
11994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "}");
11995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(43, value->Int32Value());
11996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
11997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
119993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic v8::Handle<Value> call_ic_function5;
12000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void InterceptorCallICGetter5(
12001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<String> name,
12002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Value>& info) {
120033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ApiTestFuzzer::Fuzz();
120043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (v8_str("x")->Equals(name))
12005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    info.GetReturnValue().Set(call_ic_function5);
120063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
120073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
120083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// This test checks that if interceptor provides a function,
12010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// even if we cached constant function, interceptor's function
12011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// is invoked
12012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(InterceptorCallICConstantFunctionNotNeeded) {
12013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
12014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
12015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
12016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  templ->SetNamedPropertyHandler(InterceptorCallICGetter5);
12017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
12018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context->Global()->Set(v8_str("o"), templ->NewInstance());
12019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  call_ic_function5 =
12020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      v8_compile("function f(x) { return x - 1; }; f")->Run();
12021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> value = CompileRun(
12022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "function inc(x) { return x + 1; };"
12023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "inc(1);"
12024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "o.x = inc;"
12025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "var result = 0;"
12026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "for (var i = 0; i < 1000; i++) {"
12027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  result = o.x(42);"
12028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "}");
12029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(41, value->Int32Value());
12030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
12031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
12032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
120333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic v8::Handle<Value> call_ic_function6;
12034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void InterceptorCallICGetter6(
12035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<String> name,
12036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Value>& info) {
120373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ApiTestFuzzer::Fuzz();
120383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (v8_str("x")->Equals(name))
12039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    info.GetReturnValue().Set(call_ic_function6);
120403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
120413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
120423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
120433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Same test as above, except the code is wrapped in a function
120443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// to test the optimized compiler.
120453ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochTHREADED_TEST(InterceptorCallICConstantFunctionNotNeededWrapped) {
120463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  i::FLAG_allow_natives_syntax = true;
12047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
12048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
12049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
120503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  templ->SetNamedPropertyHandler(InterceptorCallICGetter6);
120513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LocalContext context;
120523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  context->Global()->Set(v8_str("o"), templ->NewInstance());
120533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  call_ic_function6 =
120543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      v8_compile("function f(x) { return x - 1; }; f")->Run();
120553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::Handle<Value> value = CompileRun(
120563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    "function inc(x) { return x + 1; };"
120573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    "inc(1);"
120583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    "o.x = inc;"
120593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    "function test() {"
120603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    "  var result = 0;"
120613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    "  for (var i = 0; i < 1000; i++) {"
120623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    "    result = o.x(42);"
120633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    "  }"
120643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    "  return result;"
120653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    "};"
120663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    "test();"
120673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    "test();"
120683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    "test();"
120693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    "%OptimizeFunctionOnNextCall(test);"
120703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    "test()");
120713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(41, value->Int32Value());
120723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
120733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
120743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test the case when we stored constant function into
12076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// a stub, but it got invalidated later on
12077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(InterceptorCallICInvalidatedConstantFunction) {
12078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
12079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
12080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
12081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  templ->SetNamedPropertyHandler(NoBlockGetterX);
12082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
12083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context->Global()->Set(v8_str("o"), templ->NewInstance());
12084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> value = CompileRun(
12085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "function inc(x) { return x + 1; };"
12086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "inc(1);"
12087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "proto1 = new Object();"
12088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "proto2 = new Object();"
12089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "o.__proto__ = proto1;"
12090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "proto1.__proto__ = proto2;"
12091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "proto2.y = inc;"
12092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Invoke it many times to compile a stub
12093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "for (var i = 0; i < 7; i++) {"
12094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  o.y(42);"
12095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "}"
12096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "proto1.y = function(x) { return x - 1; };"
12097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "var result = 0;"
12098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "for (var i = 0; i < 7; i++) {"
12099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  result += o.y(42);"
12100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "}");
12101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(41 * 7, value->Int32Value());
12102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
12103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
12104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
12105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test the case when we stored constant function into
12106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// a stub, but it got invalidated later on due to override on
12107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// global object which is between interceptor and constant function' holders.
12108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(InterceptorCallICInvalidatedConstantFunctionViaGlobal) {
12109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
12110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
12111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
12112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  templ->SetNamedPropertyHandler(NoBlockGetterX);
12113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
12114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context->Global()->Set(v8_str("o"), templ->NewInstance());
12115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> value = CompileRun(
12116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "function inc(x) { return x + 1; };"
12117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "inc(1);"
12118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "o.__proto__ = this;"
12119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "this.__proto__.y = inc;"
12120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Invoke it many times to compile a stub
12121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "for (var i = 0; i < 7; i++) {"
12122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  if (o.y(42) != 43) throw 'oops: ' + o.y(42);"
12123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "}"
12124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "this.y = function(x) { return x - 1; };"
12125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "var result = 0;"
12126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "for (var i = 0; i < 7; i++) {"
12127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  result += o.y(42);"
12128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "}");
12129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(41 * 7, value->Int32Value());
12130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
12131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
12132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
121334515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke// Test the case when actual function to call sits on global object.
121344515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeTHREADED_TEST(InterceptorCallICCachedFromGlobal) {
12135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
12136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
12137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
121384515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  templ_o->SetNamedPropertyHandler(NoBlockGetterX);
121394515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
121404515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  LocalContext context;
121414515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  context->Global()->Set(v8_str("o"), templ_o->NewInstance());
121424515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
121434515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  v8::Handle<Value> value = CompileRun(
121444515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    "try {"
121454515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    "  o.__proto__ = this;"
121464515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    "  for (var i = 0; i < 10; i++) {"
121474515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    "    var v = o.parseFloat('239');"
121484515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    "    if (v != 239) throw v;"
121494515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // Now it should be ICed and keep a reference to parseFloat.
121504515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    "  }"
121514515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    "  var result = 0;"
121524515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    "  for (var i = 0; i < 10; i++) {"
121534515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    "    result += o.parseFloat('239');"
121544515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    "  }"
121554515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    "  result"
121564515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    "} catch(e) {"
121574515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    "  e"
121584515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    "};");
121594515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  CHECK_EQ(239 * 10, value->Int32Value());
121604515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke}
121614515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
12162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void InterceptorCallICFastApi(
12163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<String> name,
12164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Value>& info) {
12165402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  ApiTestFuzzer::Fuzz();
12166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckReturnValue(info, FUNCTION_ADDR(InterceptorCallICFastApi));
12167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int* call_count =
12168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      reinterpret_cast<int*>(v8::External::Cast(*info.Data())->Value());
12169402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  ++(*call_count);
12170402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  if ((*call_count) % 20 == 0) {
12171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
12172402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
12173402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
12174402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
12175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void FastApiCallback_TrivialSignature(
12176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::FunctionCallbackInfo<v8::Value>& args) {
12177402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  ApiTestFuzzer::Fuzz();
12178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_TrivialSignature));
12179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
12180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(isolate, args.GetIsolate());
12181402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK_EQ(args.This(), args.Holder());
12182402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK(args.Data()->Equals(v8_str("method_data")));
12183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  args.GetReturnValue().Set(args[0]->Int32Value() + 1);
12184402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
12185402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
12186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void FastApiCallback_SimpleSignature(
12187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::FunctionCallbackInfo<v8::Value>& args) {
12188402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  ApiTestFuzzer::Fuzz();
12189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_SimpleSignature));
12190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
12191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(isolate, args.GetIsolate());
12192402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK_EQ(args.This()->GetPrototype(), args.Holder());
12193402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK(args.Data()->Equals(v8_str("method_data")));
12194402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Note, we're using HasRealNamedProperty instead of Has to avoid
12195402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // invoking the interceptor again.
12196402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK(args.Holder()->HasRealNamedProperty(v8_str("foo")));
12197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  args.GetReturnValue().Set(args[0]->Int32Value() + 1);
12198402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
12199402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
12200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
12201402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// Helper to maximize the odds of object moving.
12202402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescustatic void GenerateSomeGarbage() {
12203402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CompileRun(
12204402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "var garbage;"
12205402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "for (var i = 0; i < 1000; i++) {"
12206402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "  garbage = [1/i, \"garbage\" + i, garbage, {foo: garbage}];"
12207402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "}"
12208402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "garbage = undefined;");
12209402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
12210402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
12211e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
12212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid DirectApiCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
122131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static int count = 0;
122141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (count++ % 3 == 0) {
12215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
12216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // This should move the stub
122171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    GenerateSomeGarbage();  // This should ensure the old stub memory is flushed
122181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
122191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
122201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
122211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
122221e0659c275bb392c045087af4f6b0d7565cb3d77Steve BlockTHREADED_TEST(CallICFastApi_DirectCall_GCMoveStub) {
122231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  LocalContext context;
12224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
12225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
12226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> nativeobject_templ =
12227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::ObjectTemplate::New(isolate);
12228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  nativeobject_templ->Set(isolate, "callback",
12229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          v8::FunctionTemplate::New(isolate,
12230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                    DirectApiCallback));
122311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  v8::Local<v8::Object> nativeobject_obj = nativeobject_templ->NewInstance();
122321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  context->Global()->Set(v8_str("nativeobject"), nativeobject_obj);
122331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // call the api function multiple times to ensure direct call stub creation.
122341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  CompileRun(
122351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        "function f() {"
122361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        "  for (var i = 1; i <= 30; i++) {"
122371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        "    nativeobject.callback();"
122381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        "  }"
122391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        "}"
122401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        "f();");
122411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
122421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
122431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
12244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid ThrowingDirectApiCallback(
12245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::FunctionCallbackInfo<v8::Value>& args) {
12246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  args.GetIsolate()->ThrowException(v8_str("g"));
122471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
122481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
122491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
122501e0659c275bb392c045087af4f6b0d7565cb3d77Steve BlockTHREADED_TEST(CallICFastApi_DirectCall_Throw) {
122511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  LocalContext context;
12252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
12253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
12254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> nativeobject_templ =
12255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::ObjectTemplate::New(isolate);
12256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  nativeobject_templ->Set(isolate, "callback",
12257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          v8::FunctionTemplate::New(isolate,
12258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                    ThrowingDirectApiCallback));
122591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  v8::Local<v8::Object> nativeobject_obj = nativeobject_templ->NewInstance();
122601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  context->Global()->Set(v8_str("nativeobject"), nativeobject_obj);
122611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // call the api function multiple times to ensure direct call stub creation.
122621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  v8::Handle<Value> result = CompileRun(
122631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      "var result = '';"
122641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      "function f() {"
122651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      "  for (var i = 1; i <= 5; i++) {"
122661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      "    try { nativeobject.callback(); } catch (e) { result += e; }"
122671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      "  }"
122681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      "}"
122691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      "f(); result;");
122701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  CHECK_EQ(v8_str("ggggg"), result);
122711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
122721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
122731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
12274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic Handle<Value> DoDirectGetter() {
12275e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (++p_getter_count % 3 == 0) {
12276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
12277e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    GenerateSomeGarbage();
12278e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
12279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return v8_str("Direct Getter Result");
12280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
12281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
12282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void DirectGetterCallback(
12283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<String> name,
12284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Value>& info) {
12285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckReturnValue(info, FUNCTION_ADDR(DirectGetterCallback));
12286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(DoDirectGetter());
12287e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
12288e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
12289e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
12290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<typename Accessor>
12291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void LoadICFastApi_DirectCall_GCMoveStub(Accessor accessor) {
12292e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  LocalContext context;
12293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
12294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
12295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> obj = v8::ObjectTemplate::New(isolate);
12296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  obj->SetAccessor(v8_str("p1"), accessor);
12297e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  context->Global()->Set(v8_str("o1"), obj->NewInstance());
12298e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  p_getter_count = 0;
12299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Value> result = CompileRun(
12300e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      "function f() {"
12301e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      "  for (var i = 0; i < 30; i++) o1.p1;"
12302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  return o1.p1"
12303e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      "}"
12304e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      "f();");
12305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(v8_str("Direct Getter Result"), result);
12306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(31, p_getter_count);
12307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
12308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
12309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
12310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_PROFILED_TEST(LoadICFastApi_DirectCall_GCMoveStub) {
12311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LoadICFastApi_DirectCall_GCMoveStub(DirectGetterCallback);
12312e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
12313e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
12314e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
12315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid ThrowingDirectGetterCallback(
12316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<String> name,
12317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Value>& info) {
12318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetIsolate()->ThrowException(v8_str("g"));
12319e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
12320e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
12321e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
12322e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochTHREADED_TEST(LoadICFastApi_DirectCall_Throw) {
12323e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  LocalContext context;
12324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
12325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
12326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> obj = v8::ObjectTemplate::New(isolate);
12327e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  obj->SetAccessor(v8_str("p1"), ThrowingDirectGetterCallback);
12328e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  context->Global()->Set(v8_str("o1"), obj->NewInstance());
12329e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v8::Handle<Value> result = CompileRun(
12330e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      "var result = '';"
12331e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      "for (var i = 0; i < 5; i++) {"
12332e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      "    try { o1.p1; } catch (e) { result += e; }"
12333e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      "}"
12334e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      "result;");
12335e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  CHECK_EQ(v8_str("ggggg"), result);
12336e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
12337e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
12338e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
12339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_PROFILED_TEST(InterceptorCallICFastApi_TrivialSignature) {
12340402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  int interceptor_call_count = 0;
12341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
12342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
12343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::FunctionTemplate> fun_templ =
12344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::FunctionTemplate::New(isolate);
12345402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  v8::Handle<v8::FunctionTemplate> method_templ =
12346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::FunctionTemplate::New(isolate,
12347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                FastApiCallback_TrivialSignature,
12348402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                v8_str("method_data"),
12349402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                v8::Handle<v8::Signature>());
12350402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12351402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  proto_templ->Set(v8_str("method"), method_templ);
12352402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
12353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  templ->SetNamedPropertyHandler(
12354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
12355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::External::New(isolate, &interceptor_call_count));
12356402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  LocalContext context;
12357402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12358402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  GenerateSomeGarbage();
12359402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  context->Global()->Set(v8_str("o"), fun->NewInstance());
123603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileRun(
12361402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "var result = 0;"
12362402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "for (var i = 0; i < 100; i++) {"
12363402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "  result = o.method(41);"
12364c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      "}");
12365402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
12366402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK_EQ(100, interceptor_call_count);
12367402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
12368402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
12369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
12370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature) {
12371402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  int interceptor_call_count = 0;
12372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
12373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
12374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::FunctionTemplate> fun_templ =
12375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::FunctionTemplate::New(isolate);
12376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
12377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Signature::New(isolate, fun_templ));
12379402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12380402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  proto_templ->Set(v8_str("method"), method_templ);
12381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fun_templ->SetHiddenPrototype(true);
12382402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
12383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  templ->SetNamedPropertyHandler(
12384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
12385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::External::New(isolate, &interceptor_call_count));
12386402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  LocalContext context;
12387402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12388402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  GenerateSomeGarbage();
12389402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  context->Global()->Set(v8_str("o"), fun->NewInstance());
123903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileRun(
12391402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "o.foo = 17;"
12392402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "var receiver = {};"
12393402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "receiver.__proto__ = o;"
12394402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "var result = 0;"
12395402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "for (var i = 0; i < 100; i++) {"
12396402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "  result = receiver.method(41);"
12397c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      "}");
12398402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
12399402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK_EQ(100, interceptor_call_count);
12400402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
12401402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
12402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
12403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss1) {
12404402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  int interceptor_call_count = 0;
12405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
12406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
12407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::FunctionTemplate> fun_templ =
12408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::FunctionTemplate::New(isolate);
12409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
12410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Signature::New(isolate, fun_templ));
12412402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12413402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  proto_templ->Set(v8_str("method"), method_templ);
12414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fun_templ->SetHiddenPrototype(true);
12415402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
12416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  templ->SetNamedPropertyHandler(
12417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
12418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::External::New(isolate, &interceptor_call_count));
12419402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  LocalContext context;
12420402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12421402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  GenerateSomeGarbage();
12422402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  context->Global()->Set(v8_str("o"), fun->NewInstance());
124233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileRun(
12424402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "o.foo = 17;"
12425402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "var receiver = {};"
12426402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "receiver.__proto__ = o;"
12427402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "var result = 0;"
12428402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "var saved_result = 0;"
12429402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "for (var i = 0; i < 100; i++) {"
12430402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "  result = receiver.method(41);"
12431402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "  if (i == 50) {"
12432402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "    saved_result = result;"
12433402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "    receiver = {method: function(x) { return x - 1 }};"
12434402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "  }"
12435c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      "}");
12436402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
12437402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
12438402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK_GE(interceptor_call_count, 50);
12439402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
12440402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
12441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
12442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss2) {
12443402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  int interceptor_call_count = 0;
12444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
12445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
12446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::FunctionTemplate> fun_templ =
12447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::FunctionTemplate::New(isolate);
12448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
12449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Signature::New(isolate, fun_templ));
12451402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12452402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  proto_templ->Set(v8_str("method"), method_templ);
12453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fun_templ->SetHiddenPrototype(true);
12454402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
12455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  templ->SetNamedPropertyHandler(
12456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
12457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::External::New(isolate, &interceptor_call_count));
12458402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  LocalContext context;
12459402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12460402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  GenerateSomeGarbage();
12461402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  context->Global()->Set(v8_str("o"), fun->NewInstance());
124623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileRun(
12463402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "o.foo = 17;"
12464402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "var receiver = {};"
12465402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "receiver.__proto__ = o;"
12466402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "var result = 0;"
12467402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "var saved_result = 0;"
12468402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "for (var i = 0; i < 100; i++) {"
12469402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "  result = receiver.method(41);"
12470402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "  if (i == 50) {"
12471402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "    saved_result = result;"
12472402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "    o.method = function(x) { return x - 1 };"
12473402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "  }"
12474c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      "}");
12475402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
12476402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
12477402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK_GE(interceptor_call_count, 50);
12478402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
12479402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
12480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
12481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss3) {
124826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int interceptor_call_count = 0;
12483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
12484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
12485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::FunctionTemplate> fun_templ =
12486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::FunctionTemplate::New(isolate);
12487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
12488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Signature::New(isolate, fun_templ));
124906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
124916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  proto_templ->Set(v8_str("method"), method_templ);
12492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fun_templ->SetHiddenPrototype(true);
124936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
12494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  templ->SetNamedPropertyHandler(
12495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
12496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::External::New(isolate, &interceptor_call_count));
124976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  LocalContext context;
124986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  v8::Handle<v8::Function> fun = fun_templ->GetFunction();
124996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  GenerateSomeGarbage();
125006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  context->Global()->Set(v8_str("o"), fun->NewInstance());
125016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  v8::TryCatch try_catch;
125023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileRun(
125036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      "o.foo = 17;"
125046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      "var receiver = {};"
125056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      "receiver.__proto__ = o;"
125066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      "var result = 0;"
125076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      "var saved_result = 0;"
125086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      "for (var i = 0; i < 100; i++) {"
125096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      "  result = receiver.method(41);"
125106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      "  if (i == 50) {"
125116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      "    saved_result = result;"
125126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      "    receiver = 333;"
125136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      "  }"
12514c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      "}");
125156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(try_catch.HasCaught());
12516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // TODO(verwaest): Adjust message.
12517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(v8_str("TypeError: undefined is not a function"),
125186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block           try_catch.Exception()->ToString());
125196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
125206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_GE(interceptor_call_count, 50);
125216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
125226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
12524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_TypeError) {
12525402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  int interceptor_call_count = 0;
12526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
12527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
12528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::FunctionTemplate> fun_templ =
12529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::FunctionTemplate::New(isolate);
12530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
12531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Signature::New(isolate, fun_templ));
12533402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12534402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  proto_templ->Set(v8_str("method"), method_templ);
12535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fun_templ->SetHiddenPrototype(true);
12536402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
12537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  templ->SetNamedPropertyHandler(
12538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
12539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::External::New(isolate, &interceptor_call_count));
12540402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  LocalContext context;
12541402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12542402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  GenerateSomeGarbage();
12543402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  context->Global()->Set(v8_str("o"), fun->NewInstance());
12544402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  v8::TryCatch try_catch;
125453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileRun(
12546402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "o.foo = 17;"
12547402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "var receiver = {};"
12548402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "receiver.__proto__ = o;"
12549402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "var result = 0;"
12550402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "var saved_result = 0;"
12551402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "for (var i = 0; i < 100; i++) {"
12552402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "  result = receiver.method(41);"
12553402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "  if (i == 50) {"
12554402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "    saved_result = result;"
12555402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "    receiver = {method: receiver.method};"
12556402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "  }"
12557c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      "}");
12558402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK(try_catch.HasCaught());
12559402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK_EQ(v8_str("TypeError: Illegal invocation"),
12560402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu           try_catch.Exception()->ToString());
12561402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
12562402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK_GE(interceptor_call_count, 50);
12563402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
12564402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
12565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
12566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_PROFILED_TEST(CallICFastApi_TrivialSignature) {
12567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
12568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
12569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::FunctionTemplate> fun_templ =
12570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::FunctionTemplate::New(isolate);
12571402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  v8::Handle<v8::FunctionTemplate> method_templ =
12572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::FunctionTemplate::New(isolate,
12573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                FastApiCallback_TrivialSignature,
12574402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                v8_str("method_data"),
12575402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                v8::Handle<v8::Signature>());
12576402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12577402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  proto_templ->Set(v8_str("method"), method_templ);
125783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
125793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  USE(templ);
12580402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  LocalContext context;
12581402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12582402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  GenerateSomeGarbage();
12583402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  context->Global()->Set(v8_str("o"), fun->NewInstance());
125843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileRun(
12585402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "var result = 0;"
12586402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "for (var i = 0; i < 100; i++) {"
12587402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "  result = o.method(41);"
12588c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      "}");
12589402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
12590402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
12591402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
12592402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
12593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
12594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_PROFILED_TEST(CallICFastApi_SimpleSignature) {
12595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
12596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
12597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::FunctionTemplate> fun_templ =
12598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::FunctionTemplate::New(isolate);
12599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
12600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Signature::New(isolate, fun_templ));
12602402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12603402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  proto_templ->Set(v8_str("method"), method_templ);
12604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fun_templ->SetHiddenPrototype(true);
126053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
126063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(!templ.IsEmpty());
12607402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  LocalContext context;
12608402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12609402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  GenerateSomeGarbage();
12610402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  context->Global()->Set(v8_str("o"), fun->NewInstance());
126113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileRun(
12612402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "o.foo = 17;"
12613402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "var receiver = {};"
12614402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "receiver.__proto__ = o;"
12615402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "var result = 0;"
12616402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "for (var i = 0; i < 100; i++) {"
12617402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "  result = receiver.method(41);"
12618c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      "}");
12619402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
12620402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
12621402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
12622402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
12623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
12624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss1) {
12625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
12626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
12627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::FunctionTemplate> fun_templ =
12628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::FunctionTemplate::New(isolate);
12629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
12630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Signature::New(isolate, fun_templ));
12632402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12633402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  proto_templ->Set(v8_str("method"), method_templ);
12634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fun_templ->SetHiddenPrototype(true);
126353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
126363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(!templ.IsEmpty());
12637402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  LocalContext context;
12638402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12639402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  GenerateSomeGarbage();
12640402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  context->Global()->Set(v8_str("o"), fun->NewInstance());
126413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileRun(
12642402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "o.foo = 17;"
12643402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "var receiver = {};"
12644402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "receiver.__proto__ = o;"
12645402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "var result = 0;"
12646402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "var saved_result = 0;"
12647402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "for (var i = 0; i < 100; i++) {"
12648402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "  result = receiver.method(41);"
12649402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "  if (i == 50) {"
12650402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "    saved_result = result;"
12651402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "    receiver = {method: function(x) { return x - 1 }};"
12652402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "  }"
12653c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      "}");
12654402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
12655402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
12656402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
12657402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
12658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
12659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss2) {
12660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
12661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
12662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::FunctionTemplate> fun_templ =
12663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::FunctionTemplate::New(isolate);
12664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
12665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Signature::New(isolate, fun_templ));
126676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
126686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  proto_templ->Set(v8_str("method"), method_templ);
12669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fun_templ->SetHiddenPrototype(true);
126703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
126713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(!templ.IsEmpty());
126726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  LocalContext context;
126736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  v8::Handle<v8::Function> fun = fun_templ->GetFunction();
126746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  GenerateSomeGarbage();
126756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  context->Global()->Set(v8_str("o"), fun->NewInstance());
126766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  v8::TryCatch try_catch;
126773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileRun(
126786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      "o.foo = 17;"
126796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      "var receiver = {};"
126806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      "receiver.__proto__ = o;"
126816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      "var result = 0;"
126826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      "var saved_result = 0;"
126836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      "for (var i = 0; i < 100; i++) {"
126846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      "  result = receiver.method(41);"
126856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      "  if (i == 50) {"
126866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      "    saved_result = result;"
126876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      "    receiver = 333;"
126886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      "  }"
12689c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      "}");
126906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(try_catch.HasCaught());
12691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // TODO(verwaest): Adjust message.
12692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(v8_str("TypeError: undefined is not a function"),
12693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           try_catch.Exception()->ToString());
12694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
12695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
12696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
12697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
12698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_TypeError) {
12699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
12700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
12701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::FunctionTemplate> fun_templ =
12702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::FunctionTemplate::New(isolate);
12703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
12704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Signature::New(isolate, fun_templ));
12706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  proto_templ->Set(v8_str("method"), method_templ);
12708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fun_templ->SetHiddenPrototype(true);
12709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
12710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!templ.IsEmpty());
12711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
12712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  GenerateSomeGarbage();
12714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context->Global()->Set(v8_str("o"), fun->NewInstance());
12715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::TryCatch try_catch;
12716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun(
12717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "o.foo = 17;"
12718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "var receiver = {};"
12719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "receiver.__proto__ = o;"
12720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "var result = 0;"
12721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "var saved_result = 0;"
12722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "for (var i = 0; i < 100; i++) {"
12723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  result = receiver.method(41);"
12724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  if (i == 50) {"
12725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "    saved_result = result;"
12726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "    receiver = Object.create(receiver);"
12727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  }"
12728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "}");
12729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(try_catch.HasCaught());
12730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(v8_str("TypeError: Illegal invocation"),
127316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block           try_catch.Exception()->ToString());
127326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
127336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
127346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
127354515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
127367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochv8::Handle<Value> keyed_call_ic_function;
127377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
12738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void InterceptorKeyedCallICGetter(
12739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<String> name,
12740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Value>& info) {
127417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ApiTestFuzzer::Fuzz();
127427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  if (v8_str("x")->Equals(name)) {
12743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    info.GetReturnValue().Set(keyed_call_ic_function);
127447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
127457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
127467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
127477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
127487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Test the case when we stored cacheable lookup into
127497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// a stub, but the function name changed (to another cacheable function).
127507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen MurdochTHREADED_TEST(InterceptorKeyedCallICKeyChange1) {
12751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
12752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
12753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
127547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  templ->SetNamedPropertyHandler(NoBlockGetterX);
127557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  LocalContext context;
127567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  context->Global()->Set(v8_str("o"), templ->NewInstance());
127573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileRun(
127587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "proto = new Object();"
127597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "proto.y = function(x) { return x + 1; };"
127607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "proto.z = function(x) { return x - 1; };"
127617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "o.__proto__ = proto;"
127627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "var result = 0;"
127637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "var method = 'y';"
127647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "for (var i = 0; i < 10; i++) {"
127657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "  if (i == 5) { method = 'z'; };"
127667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "  result += o[method](41);"
12767c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    "}");
127687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
127697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
127707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
127717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
127727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Test the case when we stored cacheable lookup into
127737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// a stub, but the function name changed (and the new function is present
127747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// both before and after the interceptor in the prototype chain).
127757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen MurdochTHREADED_TEST(InterceptorKeyedCallICKeyChange2) {
12776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
12777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
12778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
127797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  templ->SetNamedPropertyHandler(InterceptorKeyedCallICGetter);
127807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  LocalContext context;
127817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  context->Global()->Set(v8_str("proto1"), templ->NewInstance());
127827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  keyed_call_ic_function =
127837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      v8_compile("function f(x) { return x - 1; }; f")->Run();
127843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileRun(
127857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "o = new Object();"
127867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "proto2 = new Object();"
127877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "o.y = function(x) { return x + 1; };"
127887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "proto2.y = function(x) { return x + 2; };"
127897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "o.__proto__ = proto1;"
127907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "proto1.__proto__ = proto2;"
127917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "var result = 0;"
127927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "var method = 'x';"
127937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "for (var i = 0; i < 10; i++) {"
127947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "  if (i == 5) { method = 'y'; };"
127957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "  result += o[method](41);"
12796c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    "}");
127977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
127987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
127997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
128007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
128017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Same as InterceptorKeyedCallICKeyChange1 only the cacheable function sit
128027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// on the global object.
128037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen MurdochTHREADED_TEST(InterceptorKeyedCallICKeyChangeOnGlobal) {
12804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
12805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
12806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
128077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  templ->SetNamedPropertyHandler(NoBlockGetterX);
128087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  LocalContext context;
128097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  context->Global()->Set(v8_str("o"), templ->NewInstance());
128103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileRun(
128117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "function inc(x) { return x + 1; };"
128127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "inc(1);"
128137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "function dec(x) { return x - 1; };"
128147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "dec(1);"
128157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "o.__proto__ = this;"
128167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "this.__proto__.x = inc;"
128177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "this.__proto__.y = dec;"
128187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "var result = 0;"
128197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "var method = 'x';"
128207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "for (var i = 0; i < 10; i++) {"
128217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "  if (i == 5) { method = 'y'; };"
128227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "  result += o[method](41);"
12823c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    "}");
128247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
128257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
128267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
128277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
128287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Test the case when actual function to call sits on global object.
128297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen MurdochTHREADED_TEST(InterceptorKeyedCallICFromGlobal) {
12830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
12831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
12832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
128337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  templ_o->SetNamedPropertyHandler(NoBlockGetterX);
128347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  LocalContext context;
128357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  context->Global()->Set(v8_str("o"), templ_o->NewInstance());
128367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
128373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileRun(
128387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "function len(x) { return x.length; };"
128397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "o.__proto__ = this;"
128407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "var m = 'parseFloat';"
128417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "var result = 0;"
128427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "for (var i = 0; i < 10; i++) {"
128437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "  if (i == 5) {"
128447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "    m = 'len';"
128457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "    saved_result = result;"
128467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "  };"
128477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "  result = o[m]('239');"
12848c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    "}");
128497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  CHECK_EQ(3, context->Global()->Get(v8_str("result"))->Int32Value());
128507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  CHECK_EQ(239, context->Global()->Get(v8_str("saved_result"))->Int32Value());
128517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
128527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
12853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
128547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Test the map transition before the interceptor.
128557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen MurdochTHREADED_TEST(InterceptorKeyedCallICMapChangeBefore) {
12856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
12857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
12858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
128597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  templ_o->SetNamedPropertyHandler(NoBlockGetterX);
128607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  LocalContext context;
128617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  context->Global()->Set(v8_str("proto"), templ_o->NewInstance());
128627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
128633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileRun(
128647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "var o = new Object();"
128657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "o.__proto__ = proto;"
128667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "o.method = function(x) { return x + 1; };"
128677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "var m = 'method';"
128687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "var result = 0;"
128697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "for (var i = 0; i < 10; i++) {"
128707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "  if (i == 5) { o.method = function(x) { return x - 1; }; };"
128717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "  result += o[m](41);"
12872c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    "}");
128737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
128747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
128757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
128767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
128777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Test the map transition after the interceptor.
128787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen MurdochTHREADED_TEST(InterceptorKeyedCallICMapChangeAfter) {
12879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
12880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
12881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
128827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  templ_o->SetNamedPropertyHandler(NoBlockGetterX);
128837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  LocalContext context;
128847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  context->Global()->Set(v8_str("o"), templ_o->NewInstance());
128857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
128863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileRun(
128877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "var proto = new Object();"
128887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "o.__proto__ = proto;"
128897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "proto.method = function(x) { return x + 1; };"
128907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "var m = 'method';"
128917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "var result = 0;"
128927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "for (var i = 0; i < 10; i++) {"
128937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "  if (i == 5) { proto.method = function(x) { return x - 1; }; };"
128947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "  result += o[m](41);"
12895c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    "}");
128967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
128977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
128987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
128997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
12900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic int interceptor_call_count = 0;
12901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
12902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void InterceptorICRefErrorGetter(
12903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<String> name,
12904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Value>& info) {
12905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
12906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (v8_str("x")->Equals(name) && interceptor_call_count++ < 20) {
12907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    info.GetReturnValue().Set(call_ic_function2);
12908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
12909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
12910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
12911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
12912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// This test should hit load and call ICs for the interceptor case.
12913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Once in a while, the interceptor will reply that a property was not
12914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// found in which case we should get a reference error.
12915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(InterceptorICReferenceErrors) {
12916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
12917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
12918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
12919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  templ->SetNamedPropertyHandler(InterceptorICRefErrorGetter);
12920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context(0, templ, v8::Handle<Value>());
12921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  call_ic_function2 = v8_compile("function h(x) { return x; }; h")->Run();
12922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> value = CompileRun(
12923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "function f() {"
12924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  for (var i = 0; i < 1000; i++) {"
12925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "    try { x; } catch(e) { return true; }"
12926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  }"
12927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  return false;"
12928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "};"
12929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "f();");
12930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(true, value->BooleanValue());
12931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  interceptor_call_count = 0;
12932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  value = CompileRun(
12933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "function g() {"
12934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  for (var i = 0; i < 1000; i++) {"
12935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "    try { x(42); } catch(e) { return true; }"
12936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  }"
12937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  return false;"
12938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "};"
12939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "g();");
12940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(true, value->BooleanValue());
12941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
12942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
12943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
12944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic int interceptor_ic_exception_get_count = 0;
12945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
12946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void InterceptorICExceptionGetter(
12947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Local<String> name,
12948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Value>& info) {
12949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
12950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (v8_str("x")->Equals(name) && ++interceptor_ic_exception_get_count < 20) {
12951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    info.GetReturnValue().Set(call_ic_function3);
12952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
12953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (interceptor_ic_exception_get_count == 20) {
12954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    info.GetIsolate()->ThrowException(v8_num(42));
12955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
12956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
12957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
12958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
12959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
12960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test interceptor load/call IC where the interceptor throws an
12961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// exception once in a while.
12962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(InterceptorICGetterExceptions) {
12963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  interceptor_ic_exception_get_count = 0;
12964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
12965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
12966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
12967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  templ->SetNamedPropertyHandler(InterceptorICExceptionGetter);
12968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context(0, templ, v8::Handle<Value>());
12969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  call_ic_function3 = v8_compile("function h(x) { return x; }; h")->Run();
12970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> value = CompileRun(
12971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "function f() {"
12972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  for (var i = 0; i < 100; i++) {"
12973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "    try { x; } catch(e) { return true; }"
12974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  }"
12975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  return false;"
12976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "};"
12977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "f();");
12978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(true, value->BooleanValue());
12979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  interceptor_ic_exception_get_count = 0;
12980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  value = CompileRun(
12981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "function f() {"
12982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  for (var i = 0; i < 100; i++) {"
12983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "    try { x(42); } catch(e) { return true; }"
12984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  }"
12985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  return false;"
12986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "};"
12987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "f();");
12988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(true, value->BooleanValue());
12989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
12990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
12991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
12992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic int interceptor_ic_exception_set_count = 0;
12993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
12994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void InterceptorICExceptionSetter(
12995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Local<String> key,
12996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Local<Value> value,
12997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      const v8::PropertyCallbackInfo<v8::Value>& info) {
12998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
12999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (++interceptor_ic_exception_set_count > 20) {
13000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    info.GetIsolate()->ThrowException(v8_num(42));
13001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
13002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
13003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
13005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test interceptor store IC where the interceptor throws an exception
13006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// once in a while.
13007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(InterceptorICSetterExceptions) {
13008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  interceptor_ic_exception_set_count = 0;
13009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
13010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
13011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
13012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  templ->SetNamedPropertyHandler(0, InterceptorICExceptionSetter);
13013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context(0, templ, v8::Handle<Value>());
13014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> value = CompileRun(
13015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "function f() {"
13016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  for (var i = 0; i < 100; i++) {"
13017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "    try { x = 42; } catch(e) { return true; }"
13018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  }"
13019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  return false;"
13020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "};"
13021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "f();");
13022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(true, value->BooleanValue());
13023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
13024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test that we ignore null interceptors.
13027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(NullNamedInterceptor) {
13028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
13029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
13030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
13031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  templ->SetNamedPropertyHandler(
13032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      static_cast<v8::NamedPropertyGetterCallback>(0));
13033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
13034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  templ->Set(CcTest::isolate(), "x", v8_num(42));
13035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Object> obj = templ->NewInstance();
13036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context->Global()->Set(v8_str("obj"), obj);
13037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> value = CompileRun("obj.x");
13038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(value->IsInt32());
13039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(42, value->Int32Value());
13040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
13041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test that we ignore null interceptors.
13044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(NullIndexedInterceptor) {
13045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
13046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
13047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
13048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  templ->SetIndexedPropertyHandler(
13049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      static_cast<v8::IndexedPropertyGetterCallback>(0));
13050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
13051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  templ->Set(CcTest::isolate(), "42", v8_num(42));
13052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Object> obj = templ->NewInstance();
13053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context->Global()->Set(v8_str("obj"), obj);
13054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> value = CompileRun("obj[42]");
13055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(value->IsInt32());
13056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(42, value->Int32Value());
13057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
13058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
130607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen MurdochTHREADED_TEST(NamedPropertyHandlerGetterAttributes) {
13061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
13062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
13063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
130647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  templ->InstanceTemplate()->SetNamedPropertyHandler(InterceptorLoadXICGetter);
130657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  LocalContext env;
130667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  env->Global()->Set(v8_str("obj"),
130677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                     templ->GetFunction()->NewInstance());
130687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ExpectTrue("obj.x === 42");
130697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ExpectTrue("!obj.propertyIsEnumerable('x')");
130707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
130717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
130727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
13073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void ThrowingGetter(Local<String> name,
13074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           const v8::PropertyCallbackInfo<v8::Value>& info) {
130758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ApiTestFuzzer::Fuzz();
13076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetIsolate()->ThrowException(Handle<Value>());
13077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().SetUndefined();
130788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}
130798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
130808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
130818b112d2025046f85ef7f6be087c6129c872ebad2Ben MurdochTHREADED_TEST(VariousGetPropertiesAndThrowingCallbacks) {
130828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  LocalContext context;
13083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HandleScope scope(context->GetIsolate());
130848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
13085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
130868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Local<ObjectTemplate> instance_templ = templ->InstanceTemplate();
130878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  instance_templ->SetAccessor(v8_str("f"), ThrowingGetter);
130888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
130898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Local<Object> instance = templ->GetFunction()->NewInstance();
130908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
13091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Object> another = Object::New(context->GetIsolate());
130928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  another->SetPrototype(instance);
130938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
130948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Local<Object> with_js_getter = CompileRun(
130958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      "o = {};\n"
130968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      "o.__defineGetter__('f', function() { throw undefined; });\n"
130978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      "o\n").As<Object>();
130988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK(!with_js_getter.IsEmpty());
130998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
131008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  TryCatch try_catch;
131018b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
131028b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Local<Value> result = instance->GetRealNamedProperty(v8_str("f"));
131038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK(try_catch.HasCaught());
131048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  try_catch.Reset();
131058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK(result.IsEmpty());
131068b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
131078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  result = another->GetRealNamedProperty(v8_str("f"));
131088b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK(try_catch.HasCaught());
131098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  try_catch.Reset();
131108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK(result.IsEmpty());
131118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
131128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  result = another->GetRealNamedPropertyInPrototypeChain(v8_str("f"));
131138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK(try_catch.HasCaught());
131148b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  try_catch.Reset();
131158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK(result.IsEmpty());
131168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
131178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  result = another->Get(v8_str("f"));
131188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK(try_catch.HasCaught());
131198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  try_catch.Reset();
131208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK(result.IsEmpty());
131218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
131228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  result = with_js_getter->GetRealNamedProperty(v8_str("f"));
131238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK(try_catch.HasCaught());
131248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  try_catch.Reset();
131258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK(result.IsEmpty());
131268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
131278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  result = with_js_getter->Get(v8_str("f"));
131288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK(try_catch.HasCaught());
131298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  try_catch.Reset();
131308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK(result.IsEmpty());
131318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}
131328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
131338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
13134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void ThrowingCallbackWithTryCatch(
13135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::FunctionCallbackInfo<v8::Value>& args) {
131368b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  TryCatch try_catch;
131378b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // Verboseness is important: it triggers message delivery which can call into
131388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // external code.
131398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  try_catch.SetVerbose(true);
131408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CompileRun("throw 'from JS';");
131418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK(try_catch.HasCaught());
13142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!CcTest::i_isolate()->has_pending_exception());
13143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!CcTest::i_isolate()->has_scheduled_exception());
131448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}
131458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
131468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
131478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochstatic int call_depth;
131488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
131498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
131508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochstatic void WithTryCatch(Handle<Message> message, Handle<Value> data) {
131518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  TryCatch try_catch;
131528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}
131538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
131548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
131558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochstatic void ThrowFromJS(Handle<Message> message, Handle<Value> data) {
131568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (--call_depth) CompileRun("throw 'ThrowInJS';");
131578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}
131588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
131598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
131608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochstatic void ThrowViaApi(Handle<Message> message, Handle<Value> data) {
13161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (--call_depth) CcTest::isolate()->ThrowException(v8_str("ThrowViaApi"));
131628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}
131638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
131648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
131658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochstatic void WebKitLike(Handle<Message> message, Handle<Value> data) {
131668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Handle<String> errorMessageString = message->Get();
131678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK(!errorMessageString.IsEmpty());
131688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  message->GetStackTrace();
13169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  message->GetScriptOrigin().ResourceName();
131708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}
131718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
13172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
131738b112d2025046f85ef7f6be087c6129c872ebad2Ben MurdochTHREADED_TEST(ExceptionsDoNotPropagatePastTryCatch) {
131748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  LocalContext context;
13175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
13176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HandleScope scope(isolate);
131778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
131788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Local<Function> func =
13179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      FunctionTemplate::New(isolate,
13180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            ThrowingCallbackWithTryCatch)->GetFunction();
131818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  context->Global()->Set(v8_str("func"), func);
131828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
131838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  MessageCallback callbacks[] =
131848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      { NULL, WebKitLike, ThrowViaApi, ThrowFromJS, WithTryCatch };
131858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  for (unsigned i = 0; i < sizeof(callbacks)/sizeof(callbacks[0]); i++) {
131868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    MessageCallback callback = callbacks[i];
131878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (callback != NULL) {
131888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      V8::AddMessageListener(callback);
131898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    }
13190257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Some small number to control number of times message handler should
13191257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // throw an exception.
131928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    call_depth = 5;
131938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    ExpectFalse(
131948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        "var thrown = false;\n"
131958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        "try { func(); } catch(e) { thrown = true; }\n"
131968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        "thrown\n");
131978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (callback != NULL) {
131988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      V8::RemoveMessageListeners(callback);
131998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    }
132008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
132018b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}
132028b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
132038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
13204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void ParentGetter(Local<String> name,
13205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         const v8::PropertyCallbackInfo<v8::Value>& info) {
13206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
13207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(v8_num(1));
13208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
13209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void ChildGetter(Local<String> name,
13212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        const v8::PropertyCallbackInfo<v8::Value>& info) {
13213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
13214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(v8_num(42));
13215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
13216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(Overriding) {
13219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
13220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
13221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
13222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Parent template.
13224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::FunctionTemplate> parent_templ = v8::FunctionTemplate::New(isolate);
13225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<ObjectTemplate> parent_instance_templ =
13226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      parent_templ->InstanceTemplate();
13227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  parent_instance_templ->SetAccessor(v8_str("f"), ParentGetter);
13228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Template that inherits from the parent template.
13230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::FunctionTemplate> child_templ = v8::FunctionTemplate::New(isolate);
13231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<ObjectTemplate> child_instance_templ =
13232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      child_templ->InstanceTemplate();
13233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  child_templ->Inherit(parent_templ);
13234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Override 'f'.  The child version of 'f' should get called for child
13235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // instances.
13236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  child_instance_templ->SetAccessor(v8_str("f"), ChildGetter);
13237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Add 'g' twice.  The 'g' added last should get called for instances.
13238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  child_instance_templ->SetAccessor(v8_str("g"), ParentGetter);
13239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  child_instance_templ->SetAccessor(v8_str("g"), ChildGetter);
13240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Add 'h' as an accessor to the proto template with ReadOnly attributes
13242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // so 'h' can be shadowed on the instance object.
13243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<ObjectTemplate> child_proto_templ = child_templ->PrototypeTemplate();
13244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  child_proto_templ->SetAccessor(v8_str("h"), ParentGetter, 0,
13245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      v8::Handle<Value>(), v8::DEFAULT, v8::ReadOnly);
13246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Add 'i' as an accessor to the instance template with ReadOnly attributes
13248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // but the attribute does not have effect because it is duplicated with
13249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // NULL setter.
13250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  child_instance_templ->SetAccessor(v8_str("i"), ChildGetter, 0,
13251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      v8::Handle<Value>(), v8::DEFAULT, v8::ReadOnly);
13252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Instantiate the child template.
13256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<v8::Object> instance = child_templ->GetFunction()->NewInstance();
13257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the child function overrides the parent one.
13259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context->Global()->Set(v8_str("o"), instance);
13260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Value> value = v8_compile("o.f")->Run();
13261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the 'g' that was added last is hit.
13262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(42, value->Int32Value());
13263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  value = v8_compile("o.g")->Run();
13264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(42, value->Int32Value());
13265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check that 'h' cannot be shadowed.
13267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  value = v8_compile("o.h = 3; o.h")->Run();
13268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1, value->Int32Value());
13269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check that 'i' cannot be shadowed or changed.
13271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  value = v8_compile("o.i = 3; o.i")->Run();
13272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(42, value->Int32Value());
13273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
13274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void IsConstructHandler(
13277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::FunctionCallbackInfo<v8::Value>& args) {
13278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
13279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  args.GetReturnValue().Set(args.IsConstructCall());
13280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
13281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(IsConstructCall) {
13284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
13285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
13286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Function template with call handler.
13288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
13289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  templ->SetCallHandler(IsConstructHandler);
13290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
13292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context->Global()->Set(v8_str("f"), templ->GetFunction());
13294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Value> value = v8_compile("f()")->Run();
13295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(!value->BooleanValue());
13296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  value = v8_compile("new f()")->Run();
13297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(value->BooleanValue());
13298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
13299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(ObjectProtoToString) {
13302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
13303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
13304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
13305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  templ->SetClassName(v8_str("MyClass"));
13306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
13308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<String> customized_tostring = v8_str("customized toString");
13310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Replace Object.prototype.toString
13312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8_compile("Object.prototype.toString = function() {"
13313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  "  return 'customized toString';"
13314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  "}")->Run();
13315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Normal ToString call should call replaced Object.prototype.toString
13317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<v8::Object> instance = templ->GetFunction()->NewInstance();
13318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<String> value = instance->ToString();
13319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(value->IsString() && value->Equals(customized_tostring));
13320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ObjectProtoToString should not call replace toString function.
13322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  value = instance->ObjectProtoToString();
13323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(value->IsString() && value->Equals(v8_str("[object MyClass]")));
13324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check global
13326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  value = context->Global()->ObjectProtoToString();
13327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(value->IsString() && value->Equals(v8_str("[object global]")));
13328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check ordinary object
13330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Value> object = v8_compile("new Object()")->Run();
133316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  value = object.As<v8::Object>()->ObjectProtoToString();
13332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(value->IsString() && value->Equals(v8_str("[object Object]")));
13333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
13334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
133368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) WangTHREADED_TEST(ObjectGetConstructorName) {
133378a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  LocalContext context;
13338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(context->GetIsolate());
133398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  v8_compile("function Parent() {};"
133408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang             "function Child() {};"
133418a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang             "Child.prototype = new Parent();"
133428a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang             "var outer = { inner: function() { } };"
133438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang             "var p = new Parent();"
133448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang             "var c = new Child();"
133458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang             "var x = new outer.inner();")->Run();
133468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
133478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Local<v8::Value> p = context->Global()->Get(v8_str("p"));
133488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  CHECK(p->IsObject() && p->ToObject()->GetConstructorName()->Equals(
133498a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      v8_str("Parent")));
133508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
133518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Local<v8::Value> c = context->Global()->Get(v8_str("c"));
133528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  CHECK(c->IsObject() && c->ToObject()->GetConstructorName()->Equals(
133538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      v8_str("Child")));
133548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
133558a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Local<v8::Value> x = context->Global()->Get(v8_str("x"));
133568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  CHECK(x->IsObject() && x->ToObject()->GetConstructorName()->Equals(
133578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      v8_str("outer.inner")));
133588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang}
133598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
133608a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
13361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool ApiTestFuzzer::fuzzing_ = false;
13362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochv8::base::Semaphore ApiTestFuzzer::all_tests_done_(0);
13363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint ApiTestFuzzer::active_tests_;
13364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint ApiTestFuzzer::tests_being_run_;
13365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint ApiTestFuzzer::current_;
13366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// We are in a callback and want to switch to another thread (if we
13369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// are currently running the thread fuzzing test).
13370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid ApiTestFuzzer::Fuzz() {
13371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!fuzzing_) return;
13372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer* test = RegisterThreadedTest::nth(current_)->fuzzer_;
13373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  test->ContextSwitch();
13374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
13375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Let the next thread go.  Since it is also waiting on the V8 lock it may
13378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// not start immediately.
13379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool ApiTestFuzzer::NextThread() {
13380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int test_position = GetNextTestNumber();
13381d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  const char* test_name = RegisterThreadedTest::nth(current_)->name();
13382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (test_position == current_) {
13383d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (kLogThreading)
13384d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      printf("Stay with %s\n", test_name);
13385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return false;
13386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
13387d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (kLogThreading) {
13388d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    printf("Switch from %s to %s\n",
13389d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block           test_name,
13390d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block           RegisterThreadedTest::nth(test_position)->name());
13391d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
13392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  current_ = test_position;
13393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RegisterThreadedTest::nth(current_)->fuzzer_->gate_.Signal();
13394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return true;
13395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
13396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid ApiTestFuzzer::Run() {
13399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // When it is our turn...
13400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  gate_.Wait();
13401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {
13402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // ... get the V8 lock and start running the test.
13403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Locker locker(CcTest::isolate());
13404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CallTest();
13405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
13406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // This test finished.
13407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  active_ = false;
13408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  active_tests_--;
13409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If it was the last then signal that fact.
13410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (active_tests_ == 0) {
13411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    all_tests_done_.Signal();
13412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
13413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Otherwise select a new test and start that.
13414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    NextThread();
13415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
13416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
13417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic unsigned linear_congruential_generator;
13420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
134223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid ApiTestFuzzer::SetUp(PartOfTest part) {
13423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  linear_congruential_generator = i::FLAG_testing_prng_seed;
13424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  fuzzing_ = true;
13425257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int count = RegisterThreadedTest::count();
13426257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int start =  count * part / (LAST_PART + 1);
13427257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int end = (count * (part + 1) / (LAST_PART + 1)) - 1;
13428257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  active_tests_ = tests_being_run_ = end - start + 1;
13429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < tests_being_run_; i++) {
134303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    RegisterThreadedTest::nth(i)->fuzzer_ = new ApiTestFuzzer(i + start);
13431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
13432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < active_tests_; i++) {
13433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    RegisterThreadedTest::nth(i)->fuzzer_->Start();
13434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
13435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
13436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void CallTestNumber(int test_number) {
13439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  (RegisterThreadedTest::nth(test_number)->callback())();
13440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
13441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid ApiTestFuzzer::RunAllTests() {
13444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set off the first test.
13445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  current_ = -1;
13446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  NextThread();
13447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Wait till they are all done.
13448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  all_tests_done_.Wait();
13449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
13450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint ApiTestFuzzer::GetNextTestNumber() {
13453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int next_test;
13454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  do {
13455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    next_test = (linear_congruential_generator >> 16) % tests_being_run_;
13456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    linear_congruential_generator *= 1664525u;
13457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    linear_congruential_generator += 1013904223u;
13458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } while (!RegisterThreadedTest::nth(next_test)->fuzzer_->active_);
13459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return next_test;
13460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
13461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid ApiTestFuzzer::ContextSwitch() {
13464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the new thread is the same as the current thread there is nothing to do.
13465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (NextThread()) {
13466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Now it can start.
13467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Unlocker unlocker(CcTest::isolate());
13468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Wait till someone starts us again.
13469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    gate_.Wait();
13470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // And we're off.
13471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
13472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
13473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid ApiTestFuzzer::TearDown() {
13476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  fuzzing_ = false;
13477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < RegisterThreadedTest::count(); i++) {
13478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ApiTestFuzzer *fuzzer = RegisterThreadedTest::nth(i)->fuzzer_;
13479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (fuzzer != NULL) fuzzer->Join();
13480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
13481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
13482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Lets not be needlessly self-referential.
13485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(Threading1) {
134863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ApiTestFuzzer::SetUp(ApiTestFuzzer::FIRST_PART);
13487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::RunAllTests();
13488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::TearDown();
13489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
13490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
13492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(Threading2) {
134933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ApiTestFuzzer::SetUp(ApiTestFuzzer::SECOND_PART);
13494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::RunAllTests();
13495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::TearDown();
13496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
13497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
13499257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochTEST(Threading3) {
135003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ApiTestFuzzer::SetUp(ApiTestFuzzer::THIRD_PART);
13501257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ApiTestFuzzer::RunAllTests();
13502257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ApiTestFuzzer::TearDown();
13503257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
13504257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
13505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
13506257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochTEST(Threading4) {
135073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ApiTestFuzzer::SetUp(ApiTestFuzzer::FOURTH_PART);
13508257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ApiTestFuzzer::RunAllTests();
13509257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ApiTestFuzzer::TearDown();
13510257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
13511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
13513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid ApiTestFuzzer::CallTest() {
13514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate::Scope scope(CcTest::isolate());
13515d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (kLogThreading)
13516d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    printf("Start test %d\n", test_number_);
13517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CallTestNumber(test_number_);
13518d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (kLogThreading)
13519d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    printf("End test %d\n", test_number_);
13520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
13521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void ThrowInJS(const v8::FunctionCallbackInfo<v8::Value>& args) {
13524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = args.GetIsolate();
13525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(v8::Locker::IsLocked(isolate));
13526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
13527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Unlocker unlocker(isolate);
13528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* code = "throw 7;";
13529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {
13530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Locker nested_locker(isolate);
13531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(isolate);
13532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    v8::Handle<Value> exception;
13533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    { v8::TryCatch try_catch;
13534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      v8::Handle<Value> value = CompileRun(code);
13535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      CHECK(value.IsEmpty());
13536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      CHECK(try_catch.HasCaught());
13537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Make sure to wrap the exception in a new handle because
13538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // the handle returned from the TryCatch is destroyed
13539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // when the TryCatch is destroyed.
13540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      exception = Local<Value>::New(isolate, try_catch.Exception());
13541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
13542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    args.GetIsolate()->ThrowException(exception);
13543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
13544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
13545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void ThrowInJSNoCatch(const v8::FunctionCallbackInfo<v8::Value>& args) {
13548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(v8::Locker::IsLocked(CcTest::isolate()));
13549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
13550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Unlocker unlocker(CcTest::isolate());
13551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* code = "throw 7;";
13552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {
13553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Locker nested_locker(CcTest::isolate());
13554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(args.GetIsolate());
13555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    v8::Handle<Value> value = CompileRun(code);
13556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK(value.IsEmpty());
13557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    args.GetReturnValue().Set(v8_str("foo"));
13558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
13559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
13560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// These are locking tests that don't need to be run again
13563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// as part of the locking aggregation tests.
13564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(NestedLockers) {
13565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
13566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Locker locker(isolate);
13567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(v8::Locker::IsLocked(isolate));
13568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext env;
13569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
13570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::FunctionTemplate> fun_templ =
13571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::FunctionTemplate::New(isolate, ThrowInJS);
13572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Function> fun = fun_templ->GetFunction();
13573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env->Global()->Set(v8_str("throw_in_js"), fun);
13574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Script> script = v8_compile("(function () {"
13575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    "  try {"
13576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    "    throw_in_js();"
13577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    "    return 42;"
13578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    "  } catch (e) {"
13579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    "    return e * 13;"
13580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    "  }"
13581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    "})();");
13582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(91, script->Run()->Int32Value());
13583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
13584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// These are locking tests that don't need to be run again
13587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// as part of the locking aggregation tests.
13588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(NestedLockersNoTryCatch) {
13589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Locker locker(CcTest::isolate());
13590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext env;
13591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
13592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<v8::FunctionTemplate> fun_templ =
13593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::FunctionTemplate::New(env->GetIsolate(), ThrowInJSNoCatch);
13594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Function> fun = fun_templ->GetFunction();
13595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env->Global()->Set(v8_str("throw_in_js"), fun);
13596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Script> script = v8_compile("(function () {"
13597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    "  try {"
13598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    "    throw_in_js();"
13599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    "    return 42;"
13600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    "  } catch (e) {"
13601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    "    return e * 13;"
13602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    "  }"
13603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    "})();");
13604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(91, script->Run()->Int32Value());
13605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
13606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(RecursiveLocking) {
13609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Locker locker(CcTest::isolate());
13610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {
13611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Locker locker2(CcTest::isolate());
13612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(v8::Locker::IsLocked(CcTest::isolate()));
13613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
13614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
13615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void UnlockForAMoment(const v8::FunctionCallbackInfo<v8::Value>& args) {
13618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
13619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Unlocker unlocker(CcTest::isolate());
13620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
13621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(LockUnlockLock) {
13624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {
13625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Locker locker(CcTest::isolate());
13626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(CcTest::isolate());
13627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    LocalContext env;
13628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Local<v8::FunctionTemplate> fun_templ =
13629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v8::FunctionTemplate::New(CcTest::isolate(), UnlockForAMoment);
13630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Local<Function> fun = fun_templ->GetFunction();
13631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    env->Global()->Set(v8_str("unlock_for_a_moment"), fun);
13632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Local<Script> script = v8_compile("(function () {"
13633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      "  unlock_for_a_moment();"
13634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      "  return 42;"
13635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      "})();");
13636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(42, script->Run()->Int32Value());
13637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
13638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {
13639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Locker locker(CcTest::isolate());
13640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(CcTest::isolate());
13641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    LocalContext env;
13642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Local<v8::FunctionTemplate> fun_templ =
13643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v8::FunctionTemplate::New(CcTest::isolate(), UnlockForAMoment);
13644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Local<Function> fun = fun_templ->GetFunction();
13645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    env->Global()->Set(v8_str("unlock_for_a_moment"), fun);
13646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Local<Script> script = v8_compile("(function () {"
13647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      "  unlock_for_a_moment();"
13648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      "  return 42;"
13649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      "})();");
13650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(42, script->Run()->Int32Value());
13651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
13652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
13653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13655d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkestatic int GetGlobalObjectsCount() {
13656eab96aab0834f21954b5d6aa6366bcfb348ed811Leon Clarke  int count = 0;
13657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::HeapIterator it(CcTest::heap());
13658d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  for (i::HeapObject* object = it.next(); object != NULL; object = it.next())
13659d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    if (object->IsJSGlobalObject()) count++;
13660d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  return count;
13661d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
13662d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
13663d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
13664f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdochstatic void CheckSurvivingGlobalObjectsCount(int expected) {
13665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // We need to collect all garbage twice to be sure that everything
13666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // has been collected.  This is because inline caches are cleared in
13667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the first garbage collection but some of the maps have already
13668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // been marked at that point.  Therefore some of the maps are not
13669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // collected until the second garbage collection.
13670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
13671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(i::Heap::kMakeHeapIterableMask);
13672d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  int count = GetGlobalObjectsCount();
13673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
13674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (count != expected) CcTest::heap()->TracePathToGlobal();
13675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
13676f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CHECK_EQ(expected, count);
13677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
13678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(DontLeakGlobalObjects) {
13681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Regression test for issues 1139850 and 1174891.
13682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::FLAG_expose_gc = true;
13684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::V8::Initialize();
13685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < 5; i++) {
13687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    { v8::HandleScope scope(CcTest::isolate());
13688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      LocalContext context;
13689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
13690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CcTest::isolate()->ContextDisposedNotification();
13691f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    CheckSurvivingGlobalObjectsCount(0);
13692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    { v8::HandleScope scope(CcTest::isolate());
13694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      LocalContext context;
13695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      v8_compile("Date")->Run();
13696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
13697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CcTest::isolate()->ContextDisposedNotification();
13698f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    CheckSurvivingGlobalObjectsCount(0);
13699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    { v8::HandleScope scope(CcTest::isolate());
13701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      LocalContext context;
13702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      v8_compile("/aaa/")->Run();
13703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
13704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CcTest::isolate()->ContextDisposedNotification();
13705f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    CheckSurvivingGlobalObjectsCount(0);
13706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    { v8::HandleScope scope(CcTest::isolate());
13708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      const char* extension_list[] = { "v8/gc" };
13709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      v8::ExtensionConfiguration extensions(1, extension_list);
13710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      LocalContext context(&extensions);
13711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      v8_compile("gc();")->Run();
13712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
13713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CcTest::isolate()->ContextDisposedNotification();
13714f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    CheckSurvivingGlobalObjectsCount(0);
13715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
13716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
13717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(CopyablePersistent) {
13720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
13721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
13722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::GlobalHandles* globals =
13723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      reinterpret_cast<i::Isolate*>(isolate)->global_handles();
13724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int initial_handles = globals->global_handles_count();
13725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  typedef v8::Persistent<v8::Object, v8::CopyablePersistentTraits<v8::Object> >
13726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CopyableObject;
13727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
13728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CopyableObject handle1;
13729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    {
13730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::HandleScope scope(isolate);
13731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      handle1.Reset(isolate, v8::Object::New(isolate));
13732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
13733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(initial_handles + 1, globals->global_handles_count());
13734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CopyableObject  handle2;
13735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    handle2 = handle1;
13736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(handle1 == handle2);
13737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(initial_handles + 2, globals->global_handles_count());
13738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CopyableObject handle3(handle2);
13739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(handle1 == handle3);
13740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(initial_handles + 3, globals->global_handles_count());
13741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
13742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Verify autodispose
13743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(initial_handles, globals->global_handles_count());
13744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
13745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
13746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
13747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void WeakApiCallback(
13748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::WeakCallbackData<v8::Object, Persistent<v8::Object> >& data) {
13749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Value> value = data.GetValue()->Get(v8_str("key"));
13750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(231, static_cast<int32_t>(Local<v8::Integer>::Cast(value)->Value()));
13751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  data.GetParameter()->Reset();
13752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  delete data.GetParameter();
13753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
13754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
13755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
13756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(WeakCallbackApi) {
13757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
13758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
13759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::GlobalHandles* globals =
13760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      reinterpret_cast<i::Isolate*>(isolate)->global_handles();
13761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int initial_handles = globals->global_handles_count();
13762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
13763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(isolate);
13764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Local<v8::Object> obj = v8::Object::New(isolate);
13765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    obj->Set(v8_str("key"), v8::Integer::New(isolate, 231));
13766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Persistent<v8::Object>* handle =
13767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        new v8::Persistent<v8::Object>(isolate, obj);
13768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    handle->SetWeak<v8::Object, v8::Persistent<v8::Object> >(handle,
13769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                             WeakApiCallback);
13770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
13771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  reinterpret_cast<i::Isolate*>(isolate)->heap()->
13772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CollectAllGarbage(i::Heap::kNoGCFlags);
13773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Verify disposed.
13774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(initial_handles, globals->global_handles_count());
13775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
13776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
13777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
13778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockv8::Persistent<v8::Object> some_object;
13779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockv8::Persistent<v8::Object> bad_handle;
13780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NewPersistentHandleCallback(
13782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::WeakCallbackData<v8::Object, v8::Persistent<v8::Object> >& data) {
13783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(data.GetIsolate());
13784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bad_handle.Reset(data.GetIsolate(), some_object);
13785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  data.GetParameter()->Reset();
13786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
13787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(NewPersistentHandleFromWeakCallback) {
13790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
13791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
13792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Persistent<v8::Object> handle1, handle2;
13794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {
13795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(isolate);
13796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    some_object.Reset(isolate, v8::Object::New(isolate));
13797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    handle1.Reset(isolate, v8::Object::New(isolate));
13798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    handle2.Reset(isolate, v8::Object::New(isolate));
13799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
13800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Note: order is implementation dependent alas: currently
13801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // global handle nodes are processed by PostGarbageCollectionProcessing
13802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // in reverse allocation order, so if second allocated handle is deleted,
13803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // weak callback of the first handle would be able to 'reallocate' it.
13804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  handle1.SetWeak(&handle1, NewPersistentHandleCallback);
13805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  handle2.Reset();
13806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
13807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
13808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockv8::Persistent<v8::Object> to_be_disposed;
13811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid DisposeAndForceGcCallback(
13813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::WeakCallbackData<v8::Object, v8::Persistent<v8::Object> >& data) {
13814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  to_be_disposed.Reset();
13815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
13816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  data.GetParameter()->Reset();
13817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
13818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(DoNotUseDeletedNodesInSecondLevelGc) {
13821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
13822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
13823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Persistent<v8::Object> handle1, handle2;
13825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {
13826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(isolate);
13827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    handle1.Reset(isolate, v8::Object::New(isolate));
13828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    handle2.Reset(isolate, v8::Object::New(isolate));
13829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
13830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  handle1.SetWeak(&handle1, DisposeAndForceGcCallback);
13831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  to_be_disposed.Reset(isolate, handle2);
13832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
13833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
13834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid DisposingCallback(
13836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::WeakCallbackData<v8::Object, v8::Persistent<v8::Object> >& data) {
13837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  data.GetParameter()->Reset();
13838d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
13839d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
13840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HandleCreatingCallback(
13841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::WeakCallbackData<v8::Object, v8::Persistent<v8::Object> >& data) {
13842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(data.GetIsolate());
13843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Persistent<v8::Object>(data.GetIsolate(),
13844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             v8::Object::New(data.GetIsolate()));
13845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  data.GetParameter()->Reset();
13846d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
13847d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
13848d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
13849d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockTHREADED_TEST(NoGlobalHandlesOrphaningDueToWeakCallback) {
13850d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  LocalContext context;
13851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
13852d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
13853d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  v8::Persistent<v8::Object> handle1, handle2, handle3;
13854d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  {
13855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(isolate);
13856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    handle3.Reset(isolate, v8::Object::New(isolate));
13857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    handle2.Reset(isolate, v8::Object::New(isolate));
13858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    handle1.Reset(isolate, v8::Object::New(isolate));
13859d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
13860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  handle2.SetWeak(&handle2, DisposingCallback);
13861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  handle3.SetWeak(&handle3, HandleCreatingCallback);
13862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
13863d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
13864d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
13865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(CheckForCrossContextObjectLiterals) {
13867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::V8::Initialize();
13868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int nof = 2;
13870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* sources[nof] = {
13871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "try { [ 2, 3, 4 ].forEach(5); } catch(e) { e.toString(); }",
13872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "Object()"
13873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  };
13874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < nof; i++) {
13876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    const char* source = sources[i];
13877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    { v8::HandleScope scope(CcTest::isolate());
13878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      LocalContext context;
13879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      CompileRun(source);
13880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
13881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    { v8::HandleScope scope(CcTest::isolate());
13882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      LocalContext context;
13883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      CompileRun(source);
13884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
13885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
13886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
13887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic v8::Handle<Value> NestedScope(v8::Local<Context> env) {
13890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::EscapableHandleScope inner(env->GetIsolate());
13891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env->Enter();
13892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<Value> three = v8_num(3);
13893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<Value> value = inner.Escape(three);
13894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env->Exit();
13895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return value;
13896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
13897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(NestedHandleScopeAndContexts) {
13900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
13901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope outer(isolate);
13902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<Context> env = Context::New(isolate);
13903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env->Enter();
13904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<Value> value = NestedScope(env);
139053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::Handle<String> str(value->ToString());
139063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(!str.IsEmpty());
13907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env->Exit();
13908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
13909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic bool MatchPointers(void* key1, void* key2) {
13912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return key1 == key2;
13913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
13914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstruct SymbolInfo {
13917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  size_t id;
13918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  size_t size;
13919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  std::string name;
13920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
13921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass SetFunctionEntryHookTest {
13924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
13925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SetFunctionEntryHookTest() {
13926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(instance_ == NULL);
13927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    instance_ = this;
13928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
13929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ~SetFunctionEntryHookTest() {
13930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(instance_ == this);
13931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    instance_ = NULL;
13932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
13933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Reset() {
13934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    symbols_.clear();
13935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    symbol_locations_.clear();
13936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    invocations_.clear();
13937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
13938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void RunTest();
13939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void OnJitEvent(const v8::JitCodeEvent* event);
13940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static void JitEvent(const v8::JitCodeEvent* event) {
13941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(instance_ != NULL);
13942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    instance_->OnJitEvent(event);
13943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
13944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void OnEntryHook(uintptr_t function,
13946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   uintptr_t return_addr_location);
13947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static void EntryHook(uintptr_t function,
13948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        uintptr_t return_addr_location) {
13949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(instance_ != NULL);
13950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    instance_->OnEntryHook(function, return_addr_location);
13951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
13952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static void RuntimeCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
13954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(instance_ != NULL);
13955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    args.GetReturnValue().Set(v8_num(42));
13956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
13957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void RunLoopInNewEnv(v8::Isolate* isolate);
13958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Records addr as location of symbol.
13960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void InsertSymbolAt(i::Address addr, SymbolInfo* symbol);
13961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Finds the symbol containing addr
13963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SymbolInfo* FindSymbolForAddr(i::Address addr);
13964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Returns the number of invocations where the caller name contains
13965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // \p caller_name and the function name contains \p function_name.
13966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int CountInvocations(const char* caller_name,
13967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       const char* function_name);
13968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::Handle<i::JSFunction> foo_func_;
13970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::Handle<i::JSFunction> bar_func_;
13971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  typedef std::map<size_t, SymbolInfo> SymbolMap;
13973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  typedef std::map<i::Address, SymbolInfo*> SymbolLocationMap;
13974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  typedef std::map<std::pair<SymbolInfo*, SymbolInfo*>, int> InvocationMap;
13975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SymbolMap symbols_;
13976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SymbolLocationMap symbol_locations_;
13977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InvocationMap invocations_;
13978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static SetFunctionEntryHookTest* instance_;
13980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
13981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochSetFunctionEntryHookTest* SetFunctionEntryHookTest::instance_ = NULL;
13982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Returns true if addr is in the range [start, start+len).
13985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic bool Overlaps(i::Address start, size_t len, i::Address addr) {
13986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (start <= addr && start + len > addr)
13987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return true;
13988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
13989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return false;
13990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
13991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid SetFunctionEntryHookTest::InsertSymbolAt(i::Address addr,
13993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              SymbolInfo* symbol) {
13994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Insert the symbol at the new location.
13995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SymbolLocationMap::iterator it =
13996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      symbol_locations_.insert(std::make_pair(addr, symbol)).first;
13997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Now erase symbols to the left and right that overlap this one.
13998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  while (it != symbol_locations_.begin()) {
13999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SymbolLocationMap::iterator left = it;
14000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    --left;
14001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!Overlaps(left->first, left->second->size, addr))
14002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
14003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    symbol_locations_.erase(left);
14004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
14005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Now erase symbols to the left and right that overlap this one.
14007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  while (true) {
14008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SymbolLocationMap::iterator right = it;
14009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ++right;
14010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (right == symbol_locations_.end())
14011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
14012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!Overlaps(addr, symbol->size, right->first))
14013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
14014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    symbol_locations_.erase(right);
14015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
14016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
14017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid SetFunctionEntryHookTest::OnJitEvent(const v8::JitCodeEvent* event) {
14020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (event->type) {
14021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case v8::JitCodeEvent::CODE_ADDED: {
14022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        CHECK(event->code_start != NULL);
14023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        CHECK_NE(0, static_cast<int>(event->code_len));
14024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        CHECK(event->name.str != NULL);
14025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        size_t symbol_id = symbols_.size();
14026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Record the new symbol.
14028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        SymbolInfo& info = symbols_[symbol_id];
14029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        info.id = symbol_id;
14030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        info.size = event->code_len;
14031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        info.name.assign(event->name.str, event->name.str + event->name.len);
14032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // And record it's location.
14034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        InsertSymbolAt(reinterpret_cast<i::Address>(event->code_start), &info);
14035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
14036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
14037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case v8::JitCodeEvent::CODE_MOVED: {
14039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // We would like to never see code move that we haven't seen before,
14040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // but the code creation event does not happen until the line endings
14041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // have been calculated (this is so that we can report the line in the
14042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // script at which the function source is found, see
14043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Compiler::RecordFunctionCompilation) and the line endings
14044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // calculations can cause a GC, which can move the newly created code
14045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // before its existence can be logged.
14046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        SymbolLocationMap::iterator it(
14047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            symbol_locations_.find(
14048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                reinterpret_cast<i::Address>(event->code_start)));
14049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (it != symbol_locations_.end()) {
14050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          // Found a symbol at this location, move it.
14051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          SymbolInfo* info = it->second;
14052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          symbol_locations_.erase(it);
14053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          InsertSymbolAt(reinterpret_cast<i::Address>(event->new_code_start),
14054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         info);
14055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
14056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
14057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    default:
14058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
14059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
14060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
14061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid SetFunctionEntryHookTest::OnEntryHook(
14063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uintptr_t function, uintptr_t return_addr_location) {
14064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Get the function's code object.
14065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::Code* function_code = i::Code::GetCodeFromTargetAddress(
14066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      reinterpret_cast<i::Address>(function));
14067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(function_code != NULL);
14068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Then try and look up the caller's code object.
14070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::Address caller = *reinterpret_cast<i::Address*>(return_addr_location);
14071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Count the invocation.
14073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SymbolInfo* caller_symbol = FindSymbolForAddr(caller);
14074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SymbolInfo* function_symbol =
14075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      FindSymbolForAddr(reinterpret_cast<i::Address>(function));
14076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ++invocations_[std::make_pair(caller_symbol, function_symbol)];
14077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!bar_func_.is_null() && function_code == bar_func_->code()) {
14079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Check that we have a symbol for the "bar" function at the right location.
14080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SymbolLocationMap::iterator it(
14081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        symbol_locations_.find(function_code->instruction_start()));
14082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(it != symbol_locations_.end());
14083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
14084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!foo_func_.is_null() && function_code == foo_func_->code()) {
14086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Check that we have a symbol for "foo" at the right location.
14087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SymbolLocationMap::iterator it(
14088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        symbol_locations_.find(function_code->instruction_start()));
14089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(it != symbol_locations_.end());
14090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
14091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
14092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochSymbolInfo* SetFunctionEntryHookTest::FindSymbolForAddr(i::Address addr) {
14095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SymbolLocationMap::iterator it(symbol_locations_.lower_bound(addr));
14096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Do we have a direct hit on a symbol?
14097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (it != symbol_locations_.end()) {
14098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (it->first == addr)
14099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return it->second;
14100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
14101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If not a direct hit, it'll have to be the previous symbol.
14103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (it == symbol_locations_.begin())
14104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return NULL;
14105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  --it;
14107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  size_t offs = addr - it->first;
14108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (offs < it->second->size)
14109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return it->second;
14110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return NULL;
14112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
14113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint SetFunctionEntryHookTest::CountInvocations(
14116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const char* caller_name, const char* function_name) {
14117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InvocationMap::iterator it(invocations_.begin());
14118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int invocations = 0;
14119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (; it != invocations_.end(); ++it) {
14120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SymbolInfo* caller = it->first.first;
14121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SymbolInfo* function = it->first.second;
14122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Filter out non-matching functions.
14124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (function_name != NULL) {
14125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (function->name.find(function_name) == std::string::npos)
14126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        continue;
14127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
14128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Filter out non-matching callers.
14130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (caller_name != NULL) {
14131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (caller == NULL)
14132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        continue;
14133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (caller->name.find(caller_name) == std::string::npos)
14134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        continue;
14135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
14136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // It matches add the invocation count to the tally.
14138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    invocations += it->second;
14139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
14140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return invocations;
14142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
14143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid SetFunctionEntryHookTest::RunLoopInNewEnv(v8::Isolate* isolate) {
14146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope outer(isolate);
14147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<Context> env = Context::New(isolate);
14148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->Enter();
14149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> t = ObjectTemplate::New(isolate);
14151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  t->Set(v8_str("asdf"), v8::FunctionTemplate::New(isolate, RuntimeCallback));
14152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->Global()->Set(v8_str("obj"), t->NewInstance());
14153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* script =
14155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "function bar() {\n"
14156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  var sum = 0;\n"
14157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  for (i = 0; i < 100; ++i)\n"
14158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "    sum = foo(i);\n"
14159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  return sum;\n"
14160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "}\n"
14161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "function foo(i) { return i * i; }\n"
14162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "// Invoke on the runtime function.\n"
14163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "obj.asdf()";
14164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun(script);
14165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bar_func_ = i::Handle<i::JSFunction>::cast(
14166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          v8::Utils::OpenHandle(*env->Global()->Get(v8_str("bar"))));
14167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!bar_func_.is_null());
14168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  foo_func_ =
14170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      i::Handle<i::JSFunction>::cast(
14171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           v8::Utils::OpenHandle(*env->Global()->Get(v8_str("foo"))));
14172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!foo_func_.is_null());
14173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Value> value = CompileRun("bar();");
14175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(value->IsNumber());
14176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value());
14177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Test the optimized codegen path.
14179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  value = CompileRun("%OptimizeFunctionOnNextCall(foo);"
14180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     "bar();");
14181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(value->IsNumber());
14182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value());
14183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->Exit();
14185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
14186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid SetFunctionEntryHookTest::RunTest() {
14189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Work in a new isolate throughout.
14190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate::CreateParams create_params;
14191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  create_params.entry_hook = EntryHook;
14192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  create_params.code_event_handler = JitEvent;
14193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = v8::Isolate::New(create_params);
14194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
14196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Isolate::Scope scope(isolate);
14197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    RunLoopInNewEnv(isolate);
14199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Check the exepected invocation counts.
14201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(2, CountInvocations(NULL, "bar"));
14202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(200, CountInvocations("bar", "foo"));
14203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(200, CountInvocations(NULL, "foo"));
14204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Verify that we have an entry hook on some specific stubs.
14206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_NE(0, CountInvocations(NULL, "CEntryStub"));
14207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_NE(0, CountInvocations(NULL, "JSEntryStub"));
14208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_NE(0, CountInvocations(NULL, "JSEntryTrampoline"));
14209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
14210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate->Dispose();
14211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Reset();
14213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Make sure a second isolate is unaffected by the previous entry hook.
14215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate = v8::Isolate::New();
14216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
14217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Isolate::Scope scope(isolate);
14218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Reset the entry count to zero and set the entry hook.
14220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    RunLoopInNewEnv(isolate);
14221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // We should record no invocations in this isolate.
14223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(0, static_cast<int>(invocations_.size()));
14224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
14225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate->Dispose();
14227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
14228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(SetFunctionEntryHook) {
14231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // FunctionEntryHook does not work well with experimental natives.
14232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Experimental natives are compiled during snapshot deserialization.
14233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // This test breaks because InstallGetter (function from snapshot that
14234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // only gets called from experimental natives) is compiled with entry hooks.
14235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::FLAG_allow_natives_syntax = true;
14236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::FLAG_use_inlining = false;
14237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SetFunctionEntryHookTest test;
14239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  test.RunTest();
14240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
14241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic i::HashMap* code_map = NULL;
14244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic i::HashMap* jitcode_line_info = NULL;
14245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic int saw_bar = 0;
14246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic int move_events = 0;
14247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic bool FunctionNameIs(const char* expected,
14250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           const v8::JitCodeEvent* event) {
14251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Log lines for functions are of the general form:
14252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // "LazyCompile:<type><function_name>", where the type is one of
14253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // "*", "~" or "".
14254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const char kPreamble[] = "LazyCompile:";
14255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static size_t kPreambleLen = sizeof(kPreamble) - 1;
14256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (event->name.len < sizeof(kPreamble) - 1 ||
14258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      strncmp(kPreamble, event->name.str, kPreambleLen) != 0) {
14259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return false;
14260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
14261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* tail = event->name.str + kPreambleLen;
14263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  size_t tail_len = event->name.len - kPreambleLen;
14264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  size_t expected_len = strlen(expected);
14265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (tail_len > 1 && (*tail == '*' || *tail == '~')) {
14266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    --tail_len;
14267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ++tail;
14268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
14269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check for tails like 'bar :1'.
14271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (tail_len > expected_len + 2 &&
14272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      tail[expected_len] == ' ' &&
14273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      tail[expected_len + 1] == ':' &&
14274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      tail[expected_len + 2] &&
14275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      !strncmp(tail, expected, expected_len)) {
14276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return true;
14277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
14278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (tail_len != expected_len)
14280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return false;
14281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return strncmp(tail, expected, expected_len) == 0;
14283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
14284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void event_handler(const v8::JitCodeEvent* event) {
14287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(event != NULL);
14288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(code_map != NULL);
14289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(jitcode_line_info != NULL);
14290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  class DummyJitCodeLineInfo {
14292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  };
14293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (event->type) {
14295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case v8::JitCodeEvent::CODE_ADDED: {
14296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        CHECK(event->code_start != NULL);
14297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        CHECK_NE(0, static_cast<int>(event->code_len));
14298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        CHECK(event->name.str != NULL);
14299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        i::HashMap::Entry* entry =
14300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            code_map->Lookup(event->code_start,
14301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             i::ComputePointerHash(event->code_start),
14302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             true);
14303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        entry->value = reinterpret_cast<void*>(event->code_len);
14304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (FunctionNameIs("bar", event)) {
14306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          ++saw_bar;
14307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
14308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
14309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
14310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case v8::JitCodeEvent::CODE_MOVED: {
14312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        uint32_t hash = i::ComputePointerHash(event->code_start);
14313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // We would like to never see code move that we haven't seen before,
14314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // but the code creation event does not happen until the line endings
14315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // have been calculated (this is so that we can report the line in the
14316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // script at which the function source is found, see
14317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Compiler::RecordFunctionCompilation) and the line endings
14318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // calculations can cause a GC, which can move the newly created code
14319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // before its existence can be logged.
14320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        i::HashMap::Entry* entry =
14321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            code_map->Lookup(event->code_start, hash, false);
14322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (entry != NULL) {
14323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          ++move_events;
14324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          CHECK_EQ(reinterpret_cast<void*>(event->code_len), entry->value);
14326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          code_map->Remove(event->code_start, hash);
14327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          entry = code_map->Lookup(event->new_code_start,
14329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   i::ComputePointerHash(event->new_code_start),
14330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   true);
14331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          CHECK(entry != NULL);
14332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          entry->value = reinterpret_cast<void*>(event->code_len);
14333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
14334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
14335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
14336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case v8::JitCodeEvent::CODE_REMOVED:
14338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Object/code removal events are currently not dispatched from the GC.
14339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CHECK(false);
14340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
14341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // For CODE_START_LINE_INFO_RECORDING event, we will create one
14343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // DummyJitCodeLineInfo data structure pointed by event->user_dat. We
14344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // record it in jitcode_line_info.
14345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case v8::JitCodeEvent::CODE_START_LINE_INFO_RECORDING: {
14346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        DummyJitCodeLineInfo* line_info = new DummyJitCodeLineInfo();
14347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v8::JitCodeEvent* temp_event = const_cast<v8::JitCodeEvent*>(event);
14348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        temp_event->user_data = line_info;
14349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        i::HashMap::Entry* entry =
14350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            jitcode_line_info->Lookup(line_info,
14351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                      i::ComputePointerHash(line_info),
14352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                      true);
14353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        entry->value = reinterpret_cast<void*>(line_info);
14354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
14355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
14356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // For these two events, we will check whether the event->user_data
14357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // data structure is created before during CODE_START_LINE_INFO_RECORDING
14358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // event. And delete it in CODE_END_LINE_INFO_RECORDING event handling.
14359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case v8::JitCodeEvent::CODE_END_LINE_INFO_RECORDING: {
14360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        CHECK(event->user_data != NULL);
14361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        uint32_t hash = i::ComputePointerHash(event->user_data);
14362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        i::HashMap::Entry* entry =
14363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            jitcode_line_info->Lookup(event->user_data, hash, false);
14364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        CHECK(entry != NULL);
14365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        delete reinterpret_cast<DummyJitCodeLineInfo*>(event->user_data);
14366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
14367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
14368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case v8::JitCodeEvent::CODE_ADD_LINE_POS_INFO: {
14370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        CHECK(event->user_data != NULL);
14371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        uint32_t hash = i::ComputePointerHash(event->user_data);
14372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        i::HashMap::Entry* entry =
14373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            jitcode_line_info->Lookup(event->user_data, hash, false);
14374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        CHECK(entry != NULL);
14375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
14376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
14377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    default:
14379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Impossible event.
14380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CHECK(false);
14381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
14382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
14383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
14384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochUNINITIALIZED_TEST(SetJitCodeEventHandler) {
14387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::FLAG_stress_compaction = true;
14388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::FLAG_incremental_marking = false;
14389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (i::FLAG_never_compact) return;
14390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* script =
14391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "function bar() {"
14392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "  var sum = 0;"
14393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "  for (i = 0; i < 100; ++i)"
14394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "    sum = foo(i);"
14395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "  return sum;"
14396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "}"
14397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "function foo(i) { return i * i; };"
14398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "bar();";
14399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Run this test in a new isolate to make sure we don't
14401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // have remnants of state from other code.
14402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = v8::Isolate::New();
14403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate->Enter();
14404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
14405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::Heap* heap = i_isolate->heap();
14406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
14408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(isolate);
14409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    i::HashMap code(MatchPointers);
14410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    code_map = &code;
14411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    i::HashMap lineinfo(MatchPointers);
14413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    jitcode_line_info = &lineinfo;
14414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    saw_bar = 0;
14416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    move_events = 0;
14417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, event_handler);
14419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Generate new code objects sparsely distributed across several
14421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // different fragmented code-space pages.
14422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const int kIterations = 10;
14423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int i = 0; i < kIterations; ++i) {
14424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      LocalContext env(isolate);
14425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      i::AlwaysAllocateScope always_allocate(i_isolate);
14426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SimulateFullSpace(heap->code_space());
14427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CompileRun(script);
14428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Keep a strong reference to the code object in the handle scope.
14430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      i::Handle<i::Code> bar_code(i::Handle<i::JSFunction>::cast(
14431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          v8::Utils::OpenHandle(*env->Global()->Get(v8_str("bar"))))->code());
14432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      i::Handle<i::Code> foo_code(i::Handle<i::JSFunction>::cast(
14433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          v8::Utils::OpenHandle(*env->Global()->Get(v8_str("foo"))))->code());
14434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Clear the compilation cache to get more wastage.
14436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      reinterpret_cast<i::Isolate*>(isolate)->compilation_cache()->Clear();
14437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
14438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Force code movement.
14440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    heap->CollectAllAvailableGarbage("TestSetJitCodeEventHandler");
14441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
14443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_LE(kIterations, saw_bar);
14445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_LT(0, move_events);
14446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    code_map = NULL;
14448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    jitcode_line_info = NULL;
14449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
14450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate->Exit();
14452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate->Dispose();
14453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Do this in a new isolate.
14455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate = v8::Isolate::New();
14456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate->Enter();
14457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Verify that we get callbacks for existing code objects when we
14459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // request enumeration of existing code.
14460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
14461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(isolate);
14462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LocalContext env(isolate);
14463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CompileRun(script);
14464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Now get code through initial iteration.
14466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    i::HashMap code(MatchPointers);
14467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    code_map = &code;
14468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    i::HashMap lineinfo(MatchPointers);
14470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    jitcode_line_info = &lineinfo;
14471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    isolate->SetJitCodeEventHandler(v8::kJitCodeEventEnumExisting,
14473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    event_handler);
14474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
14475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    jitcode_line_info = NULL;
14477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // We expect that we got some events. Note that if we could get code removal
14478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // notifications, we could compare two collections, one created by listening
14479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // from the time of creation of an isolate, and the other by subscribing
14480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // with EnumExisting.
14481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_LT(0, code.occupancy());
14482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    code_map = NULL;
14484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
14485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate->Exit();
14487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate->Dispose();
14488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
14489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(ExternalAllocatedMemory) {
14492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
14493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope outer(isolate);
14494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<Context> env(Context::New(isolate));
14495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!env.IsEmpty());
14496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int64_t kSize = 1024*1024;
14497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int64_t baseline = isolate->AdjustAmountOfExternalAllocatedMemory(0);
14498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(baseline + kSize,
14499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           isolate->AdjustAmountOfExternalAllocatedMemory(kSize));
14500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(baseline,
14501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           isolate->AdjustAmountOfExternalAllocatedMemory(-kSize));
14502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
14503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Regression test for issue 54, object templates with internal fields
14506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// but no accessors or interceptors did not get their internal field
14507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// count set on instances.
14508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(Regress54) {
14509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
14510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
14511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope outer(isolate);
14512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static v8::Persistent<v8::ObjectTemplate> templ;
14513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (templ.IsEmpty()) {
14514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::EscapableHandleScope inner(isolate);
14515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Local<v8::ObjectTemplate> local = v8::ObjectTemplate::New(isolate);
14516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    local->SetInternalFieldCount(1);
14517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    templ.Reset(isolate, inner.Escape(local));
14518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
14519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Object> result =
14520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Local<v8::ObjectTemplate>::New(isolate, templ)->NewInstance();
14521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1, result->InternalFieldCount());
14522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
14523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// If part of the threaded tests, this test makes ThreadingTest fail
14526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// on mac.
14527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(CatchStackOverflow) {
14528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
14529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(context->GetIsolate());
14530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::TryCatch try_catch;
14531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Value> result = CompileRun(
14532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "function f() {"
14533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "  return f();"
14534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "}"
14535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ""
14536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "f();");
14537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(result.IsEmpty());
14538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
14539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void CheckTryCatchSourceInfo(v8::Handle<v8::Script> script,
14542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    const char* resource_name,
14543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    int line_offset) {
14544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(CcTest::isolate());
14545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::TryCatch try_catch;
14546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Value> result = script->Run();
14547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(result.IsEmpty());
14548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(try_catch.HasCaught());
14549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Message> message = try_catch.Message();
14550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!message.IsEmpty());
14551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(10 + line_offset, message->GetLineNumber());
14552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(91, message->GetStartPosition());
14553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(92, message->GetEndPosition());
14554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2, message->GetStartColumn());
14555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(3, message->GetEndColumn());
14556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::String::Utf8Value line(message->GetSourceLine());
14557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ("  throw 'nirk';", *line);
14558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::String::Utf8Value name(message->GetScriptOrigin().ResourceName());
14559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(resource_name, *name);
14560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
14561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(TryCatchSourceInfo) {
14564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
14565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(context->GetIsolate());
14566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::String> source = v8_str(
14567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "function Foo() {\n"
14568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  return Bar();\n"
14569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "}\n"
14570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "\n"
14571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "function Bar() {\n"
14572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  return Baz();\n"
14573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "}\n"
14574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "\n"
14575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "function Baz() {\n"
14576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  throw 'nirk';\n"
14577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "}\n"
14578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "\n"
14579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "Foo();\n");
14580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* resource_name;
14582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Script> script;
14583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  resource_name = "test.js";
14584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  script = CompileWithOrigin(source, resource_name);
14585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckTryCatchSourceInfo(script, resource_name, 0);
14586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  resource_name = "test1.js";
14588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::ScriptOrigin origin1(
14589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(context->GetIsolate(), resource_name));
14590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  script = v8::Script::Compile(source, &origin1);
14591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckTryCatchSourceInfo(script, resource_name, 0);
14592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  resource_name = "test2.js";
14594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::ScriptOrigin origin2(
14595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(context->GetIsolate(), resource_name),
14596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Integer::New(context->GetIsolate(), 7));
14597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  script = v8::Script::Compile(source, &origin2);
14598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckTryCatchSourceInfo(script, resource_name, 7);
14599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
14600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(CompilationCache) {
14603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
14604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(context->GetIsolate());
14605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::String> source0 =
14606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(context->GetIsolate(), "1234");
14607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::String> source1 =
14608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(context->GetIsolate(), "1234");
14609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Script> script0 = CompileWithOrigin(source0, "test.js");
14610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Script> script1 = CompileWithOrigin(source1, "test.js");
14611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Script> script2 =
14612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Script::Compile(source0);  // different origin
14613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1234, script0->Run()->Int32Value());
14614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1234, script1->Run()->Int32Value());
14615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1234, script2->Run()->Int32Value());
14616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
14617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void FunctionNameCallback(
14620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::FunctionCallbackInfo<v8::Value>& args) {
14621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ApiTestFuzzer::Fuzz();
14622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  args.GetReturnValue().Set(v8_num(42));
14623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
14624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(CallbackFunctionName) {
14627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
14628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
14629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
14630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> t = ObjectTemplate::New(isolate);
14631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  t->Set(v8_str("asdf"),
14632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         v8::FunctionTemplate::New(isolate, FunctionNameCallback));
14633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context->Global()->Set(v8_str("obj"), t->NewInstance());
14634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Value> value = CompileRun("obj.asdf.name");
14635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(value->IsString());
14636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::String::Utf8Value name(value);
14637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ("asdf", *name);
14638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
14639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(DateAccess) {
14642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
14643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(context->GetIsolate());
14644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Value> date =
14645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Date::New(context->GetIsolate(), 1224744689038.0);
14646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(date->IsDate());
14647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1224744689038.0, date.As<v8::Date>()->ValueOf());
14648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
14649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CheckProperties(v8::Isolate* isolate,
14652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     v8::Handle<v8::Value> val,
14653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     int elmc,
14654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     const char* elmv[]) {
146556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  v8::Handle<v8::Object> obj = val.As<v8::Object>();
14656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Array> props = obj->GetPropertyNames();
14657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(elmc, props->Length());
14658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < elmc; i++) {
14659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::String::Utf8Value elm(props->Get(v8::Integer::New(isolate, i)));
14660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(elmv[i], *elm);
14661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
14662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
14663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CheckOwnProperties(v8::Isolate* isolate,
14666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        v8::Handle<v8::Value> val,
146673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                        int elmc,
146683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                        const char* elmv[]) {
146693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  v8::Handle<v8::Object> obj = val.As<v8::Object>();
146703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  v8::Handle<v8::Array> props = obj->GetOwnPropertyNames();
146713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK_EQ(elmc, props->Length());
146723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  for (int i = 0; i < elmc; i++) {
14673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::String::Utf8Value elm(props->Get(v8::Integer::New(isolate, i)));
146743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    CHECK_EQ(elmv[i], *elm);
146753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
146763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
146773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
146783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
14679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(PropertyEnumeration) {
14680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
14681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
14682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
14683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Value> obj = CompileRun(
14684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "var result = [];"
14685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "result[0] = {};"
14686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "result[1] = {a: 1, b: 2};"
14687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "result[2] = [1, 2, 3];"
14688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "var proto = {x: 1, y: 2, z: 3};"
14689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "var x = { __proto__: proto, w: 0, z: 1 };"
14690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "result[3] = x;"
14691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "result;");
146926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  v8::Handle<v8::Array> elms = obj.As<v8::Array>();
14693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(4, elms->Length());
14694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int elmc0 = 0;
14695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char** elmv0 = NULL;
14696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckProperties(
14697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate, elms->Get(v8::Integer::New(isolate, 0)), elmc0, elmv0);
14698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckOwnProperties(
14699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate, elms->Get(v8::Integer::New(isolate, 0)), elmc0, elmv0);
14700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int elmc1 = 2;
14701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* elmv1[] = {"a", "b"};
14702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckProperties(
14703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate, elms->Get(v8::Integer::New(isolate, 1)), elmc1, elmv1);
14704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckOwnProperties(
14705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate, elms->Get(v8::Integer::New(isolate, 1)), elmc1, elmv1);
14706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int elmc2 = 3;
14707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* elmv2[] = {"0", "1", "2"};
14708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckProperties(
14709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate, elms->Get(v8::Integer::New(isolate, 2)), elmc2, elmv2);
14710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckOwnProperties(
14711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate, elms->Get(v8::Integer::New(isolate, 2)), elmc2, elmv2);
14712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int elmc3 = 4;
14713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* elmv3[] = {"w", "z", "x", "y"};
14714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckProperties(
14715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate, elms->Get(v8::Integer::New(isolate, 3)), elmc3, elmv3);
147163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int elmc4 = 2;
147173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const char* elmv4[] = {"w", "z"};
14718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckOwnProperties(
14719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate, elms->Get(v8::Integer::New(isolate, 3)), elmc4, elmv4);
14720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
14721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1472344f0eee88ff00398ff7f715fab053374d808c90dSteve BlockTHREADED_TEST(PropertyEnumeration2) {
1472444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LocalContext context;
14725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
14726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
14727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Value> obj = CompileRun(
1472844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      "var result = [];"
1472944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      "result[0] = {};"
1473044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      "result[1] = {a: 1, b: 2};"
1473144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      "result[2] = [1, 2, 3];"
1473244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      "var proto = {x: 1, y: 2, z: 3};"
1473344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      "var x = { __proto__: proto, w: 0, z: 1 };"
1473444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      "result[3] = x;"
14735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "result;");
1473644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::Handle<v8::Array> elms = obj.As<v8::Array>();
1473744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(4, elms->Length());
1473844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int elmc0 = 0;
1473944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const char** elmv0 = NULL;
14740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckProperties(isolate,
14741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  elms->Get(v8::Integer::New(isolate, 0)), elmc0, elmv0);
1474244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
14743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Value> val = elms->Get(v8::Integer::New(isolate, 0));
1474444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::Handle<v8::Array> props = val.As<v8::Object>()->GetPropertyNames();
1474544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, props->Length());
1474644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  for (uint32_t i = 0; i < props->Length(); i++) {
1474744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    printf("p[%d]\n", i);
1474844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
1474944f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
14750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic bool NamedSetAccessBlocker(Local<v8::Object> obj,
14752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  Local<Value> name,
14753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  v8::AccessType type,
14754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  Local<Value> data) {
14755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return type != v8::ACCESS_SET;
14756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
14757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic bool IndexedSetAccessBlocker(Local<v8::Object> obj,
14760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    uint32_t key,
14761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    v8::AccessType type,
14762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    Local<Value> data) {
14763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return type != v8::ACCESS_SET;
14764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
14765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(DisableAccessChecksWhileConfiguring) {
14768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
14769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
14770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
14771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
14772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  templ->SetAccessCheckCallbacks(NamedSetAccessBlocker,
14773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 IndexedSetAccessBlocker);
14774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  templ->Set(v8_str("x"), v8::True(isolate));
14775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<v8::Object> instance = templ->NewInstance();
14776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context->Global()->Set(v8_str("obj"), instance);
14777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Value> value = CompileRun("obj.x");
14778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(value->BooleanValue());
14779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
14780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic bool NamedGetAccessBlocker(Local<v8::Object> obj,
14783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  Local<Value> name,
14784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  v8::AccessType type,
14785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  Local<Value> data) {
14786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return false;
14787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
14788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic bool IndexedGetAccessBlocker(Local<v8::Object> obj,
14791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    uint32_t key,
14792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    v8::AccessType type,
14793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    Local<Value> data) {
14794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return false;
14795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
14796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(AccessChecksReenabledCorrectly) {
14800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
14801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
14802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
14803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
14804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  templ->SetAccessCheckCallbacks(NamedGetAccessBlocker,
14805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 IndexedGetAccessBlocker);
14806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  templ->Set(v8_str("a"), v8_str("a"));
14807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Add more than 8 (see kMaxFastProperties) properties
14808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // so that the constructor will force copying map.
14809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Cannot sprintf, gcc complains unsafety.
14810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  char buf[4];
14811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (char i = '0'; i <= '9' ; i++) {
14812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    buf[0] = i;
14813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (char j = '0'; j <= '9'; j++) {
14814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      buf[1] = j;
14815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      for (char k = '0'; k <= '9'; k++) {
14816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        buf[2] = k;
14817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        buf[3] = 0;
14818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        templ->Set(v8_str(buf), v8::Number::New(isolate, k));
14819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
14820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
14821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
14822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<v8::Object> instance_1 = templ->NewInstance();
14824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context->Global()->Set(v8_str("obj_1"), instance_1);
14825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Value> value_1 = CompileRun("obj_1.a");
14827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(value_1.IsEmpty());
14828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<v8::Object> instance_2 = templ->NewInstance();
14830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context->Global()->Set(v8_str("obj_2"), instance_2);
14831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Value> value_2 = CompileRun("obj_2.a");
14833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(value_2.IsEmpty());
14834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
14835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// This tests that access check information remains on the global
14838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// object template when creating contexts.
14839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(AccessControlRepeatedContextCreation) {
14840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
14841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(isolate);
14842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> global_template =
14843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::ObjectTemplate::New(isolate);
14844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  global_template->SetAccessCheckCallbacks(NamedSetAccessBlocker,
14845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           IndexedSetAccessBlocker);
14846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  i::Handle<i::ObjectTemplateInfo> internal_template =
14847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      v8::Utils::OpenHandle(*global_template);
14848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(!internal_template->constructor()->IsUndefined());
14849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  i::Handle<i::FunctionTemplateInfo> constructor(
14850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      i::FunctionTemplateInfo::cast(internal_template->constructor()));
14851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(!constructor->access_check_info()->IsUndefined());
14852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<Context> context0(Context::New(isolate, NULL, global_template));
148533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(!context0.IsEmpty());
14854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(!constructor->access_check_info()->IsUndefined());
14855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
14856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(TurnOnAccessCheck) {
14859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
14860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(isolate);
14861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create an environment with access check to the global object disabled by
14863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // default.
14864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> global_template =
14865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::ObjectTemplate::New(isolate);
14866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  global_template->SetAccessCheckCallbacks(NamedGetAccessBlocker,
14867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           IndexedGetAccessBlocker,
14868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           v8::Handle<v8::Value>(),
14869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           false);
14870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<Context> context = Context::New(isolate, NULL, global_template);
14871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Context::Scope context_scope(context);
14872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set up a property and a number of functions.
14874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context->Global()->Set(v8_str("a"), v8_num(1));
14875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CompileRun("function f1() {return a;}"
14876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block             "function f2() {return a;}"
14877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block             "function g1() {return h();}"
14878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block             "function g2() {return h();}"
14879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block             "function h() {return 1;}");
14880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Function> f1 =
14881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Local<Function>::Cast(context->Global()->Get(v8_str("f1")));
14882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Function> f2 =
14883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Local<Function>::Cast(context->Global()->Get(v8_str("f2")));
14884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Function> g1 =
14885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Local<Function>::Cast(context->Global()->Get(v8_str("g1")));
14886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Function> g2 =
14887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Local<Function>::Cast(context->Global()->Get(v8_str("g2")));
14888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Function> h =
14889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Local<Function>::Cast(context->Global()->Get(v8_str("h")));
14890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the global object.
14892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Object> global = context->Global();
14893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call f1 one time and f2 a number of times. This will ensure that f1 still
14895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // uses the runtime system to retreive property a whereas f2 uses global load
14896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // inline cache.
14897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(f1->Call(global, 0, NULL)->Equals(v8_num(1)));
14898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < 4; i++) {
14899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK(f2->Call(global, 0, NULL)->Equals(v8_num(1)));
14900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
14901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Same for g1 and g2.
14903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(g1->Call(global, 0, NULL)->Equals(v8_num(1)));
14904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < 4; i++) {
14905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK(g2->Call(global, 0, NULL)->Equals(v8_num(1)));
14906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
14907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Detach the global and turn on access check.
14909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Object> hidden_global = Local<Object>::Cast(
14910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      context->Global()->GetPrototype());
14911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context->DetachGlobal();
14912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  hidden_global->TurnOnAccessCheck();
14913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Failing access check results in exception.
14915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(f1->Call(global, 0, NULL).IsEmpty());
14916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(f2->Call(global, 0, NULL).IsEmpty());
14917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(g1->Call(global, 0, NULL).IsEmpty());
14918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(g2->Call(global, 0, NULL).IsEmpty());
14919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // No failing access check when just returning a constant.
14921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(h->Call(global, 0, NULL)->Equals(v8_num(1)));
14922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
14923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
149253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic const char* kPropertyA = "a";
149263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic const char* kPropertyH = "h";
14927b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
14928b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic bool NamedGetAccessBlockAandH(Local<v8::Object> obj,
14929b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                       Local<Value> name,
14930b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                       v8::AccessType type,
14931b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                       Local<Value> data) {
149323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!name->IsString()) return false;
149333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  i::Handle<i::String> name_handle =
149343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      v8::Utils::OpenHandle(String::Cast(*name));
14935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return !name_handle->IsUtf8EqualTo(i::CStrVector(kPropertyA))
14936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      && !name_handle->IsUtf8EqualTo(i::CStrVector(kPropertyH));
14937b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
14938b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
14939b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
14940b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochTHREADED_TEST(TurnOnAccessCheckAndRecompile) {
14941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
14942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(isolate);
14943b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
14944b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Create an environment with access check to the global object disabled by
14945b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // default. When the registered access checker will block access to properties
149463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // a and h.
14947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> global_template =
14948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch     v8::ObjectTemplate::New(isolate);
14949b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  global_template->SetAccessCheckCallbacks(NamedGetAccessBlockAandH,
14950b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                           IndexedGetAccessBlocker,
14951b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                           v8::Handle<v8::Value>(),
14952b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                           false);
14953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<Context> context = Context::New(isolate, NULL, global_template);
14954b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Context::Scope context_scope(context);
14955b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
14956b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Set up a property and a number of functions.
14957b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  context->Global()->Set(v8_str("a"), v8_num(1));
14958b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static const char* source = "function f1() {return a;}"
14959b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                              "function f2() {return a;}"
14960b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                              "function g1() {return h();}"
14961b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                              "function g2() {return h();}"
14962b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                              "function h() {return 1;}";
14963b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
14964b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CompileRun(source);
14965b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Local<Function> f1;
14966b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Local<Function> f2;
14967b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Local<Function> g1;
14968b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Local<Function> g2;
14969b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Local<Function> h;
14970b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  f1 = Local<Function>::Cast(context->Global()->Get(v8_str("f1")));
14971b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  f2 = Local<Function>::Cast(context->Global()->Get(v8_str("f2")));
14972b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  g1 = Local<Function>::Cast(context->Global()->Get(v8_str("g1")));
14973b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  g2 = Local<Function>::Cast(context->Global()->Get(v8_str("g2")));
14974b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  h =  Local<Function>::Cast(context->Global()->Get(v8_str("h")));
14975b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
14976b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Get the global object.
14977b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  v8::Handle<v8::Object> global = context->Global();
14978b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
14979b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Call f1 one time and f2 a number of times. This will ensure that f1 still
14980b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // uses the runtime system to retreive property a whereas f2 uses global load
14981b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // inline cache.
14982b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK(f1->Call(global, 0, NULL)->Equals(v8_num(1)));
14983b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < 4; i++) {
14984b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CHECK(f2->Call(global, 0, NULL)->Equals(v8_num(1)));
14985b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
14986b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
14987b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Same for g1 and g2.
14988b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK(g1->Call(global, 0, NULL)->Equals(v8_num(1)));
14989b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < 4; i++) {
14990b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CHECK(g2->Call(global, 0, NULL)->Equals(v8_num(1)));
14991b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
14992b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
14993b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Detach the global and turn on access check now blocking access to property
14994b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // a and function h.
14995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Object> hidden_global = Local<Object>::Cast(
14996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      context->Global()->GetPrototype());
14997b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  context->DetachGlobal();
14998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  hidden_global->TurnOnAccessCheck();
14999b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
15000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Failing access check results in exception.
15001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(f1->Call(global, 0, NULL).IsEmpty());
15002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(f2->Call(global, 0, NULL).IsEmpty());
15003b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK(g1->Call(global, 0, NULL).IsEmpty());
15004b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK(g2->Call(global, 0, NULL).IsEmpty());
15005b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
15006b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // No failing access check when just returning a constant.
15007b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK(h->Call(global, 0, NULL)->Equals(v8_num(1)));
15008b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
15009b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Now compile the source again. And get the newly compiled functions, except
15010b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // for h for which access is blocked.
15011b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CompileRun(source);
15012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  f1 = Local<Function>::Cast(hidden_global->Get(v8_str("f1")));
15013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  f2 = Local<Function>::Cast(hidden_global->Get(v8_str("f2")));
15014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  g1 = Local<Function>::Cast(hidden_global->Get(v8_str("g1")));
15015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  g2 = Local<Function>::Cast(hidden_global->Get(v8_str("g2")));
15016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(hidden_global->Get(v8_str("h")).IsEmpty());
15017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
15018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Failing access check results in exception.
15019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Value> result = f1->Call(global, 0, NULL);
15020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(result.IsEmpty());
15021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(f1->Call(global, 0, NULL).IsEmpty());
15022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(f2->Call(global, 0, NULL).IsEmpty());
15023b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK(g1->Call(global, 0, NULL).IsEmpty());
15024b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK(g2->Call(global, 0, NULL).IsEmpty());
15025b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
15026b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
15027b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
15028f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke// Tests that ScriptData can be serialized and deserialized.
15029f7060e27768c550ace7ec48ad8c093466db52dfaLeon ClarkeTEST(PreCompileSerialization) {
15030f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  v8::V8::Initialize();
15031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
15032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
15033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HandleScope handle_scope(isolate);
15034f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
15035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::FLAG_min_preparse_length = 0;
15036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* script = "function foo(a) { return a+1; }";
15037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::ScriptCompiler::Source source(v8_str(script));
15038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::ScriptCompiler::Compile(isolate, &source,
15039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              v8::ScriptCompiler::kProduceParserCache);
15040f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Serialize.
15041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const v8::ScriptCompiler::CachedData* cd = source.GetCachedData();
15042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::byte* serialized_data = i::NewArray<i::byte>(cd->length);
15043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::MemCopy(serialized_data, cd->data, cd->length);
15044f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
15045f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Deserialize.
15046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::ScriptData* deserialized = new i::ScriptData(serialized_data, cd->length);
15047f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
15048f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Verify that the original is the same as the deserialized.
15049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(cd->length, deserialized->length());
15050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, memcmp(cd->data, deserialized->data(), cd->length));
15051ac95265630a4e0c317a7a7201d17a57df7d9bcceLeon Clarke
15052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  delete deserialized;
15053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::DeleteArray(serialized_data);
150547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
150557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
150567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
15057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// This tests that we do not allow dictionary load/call inline caches
15058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// to use functions that have not yet been compiled.  The potential
15059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// problem of loading a function that has not yet been compiled can
15060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// arise because we share code between contexts via the compilation
15061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// cache.
15062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(DictionaryICLoadedFunction) {
15063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(CcTest::isolate());
15064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Test LoadIC.
15065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < 2; i++) {
15066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    LocalContext context;
15067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    context->Global()->Set(v8_str("tmp"), v8::True(CcTest::isolate()));
15068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    context->Global()->Delete(v8_str("tmp"));
15069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CompileRun("for (var j = 0; j < 10; j++) new RegExp('');");
15070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
15071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Test CallIC.
15072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < 2; i++) {
15073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    LocalContext context;
15074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    context->Global()->Set(v8_str("tmp"), v8::True(CcTest::isolate()));
15075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    context->Global()->Delete(v8_str("tmp"));
15076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CompileRun("for (var j = 0; j < 10; j++) RegExp('')");
15077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
15078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
15079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test that cross-context new calls use the context of the callee to
15082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// create the new JavaScript object.
15083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(CrossContextNew) {
15084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
15085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
15086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<Context> context0 = Context::New(isolate);
15087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<Context> context1 = Context::New(isolate);
15088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allow cross-domain access.
15090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<String> token = v8_str("<security token>");
15091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context0->SetSecurityToken(token);
15092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context1->SetSecurityToken(token);
15093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set an 'x' property on the Object prototype and define a
15095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // constructor function in context0.
15096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context0->Enter();
15097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CompileRun("Object.prototype.x = 42; function C() {};");
15098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context0->Exit();
15099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call the constructor function from context0 and check that the
15101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // result has the 'x' property.
15102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context1->Enter();
15103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context1->Global()->Set(v8_str("other"), context0->Global());
15104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Value> value = CompileRun("var instance = new other.C(); instance.x");
15105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(value->IsInt32());
15106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(42, value->Int32Value());
15107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context1->Exit();
15108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
15109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Verify that we can clone an object
15112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(ObjectClone) {
15113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext env;
15114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
15115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
15116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* sample =
15118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "var rv = {};"      \
15119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "rv.alpha = 'hello';" \
15120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "rv.beta = 123;"     \
15121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "rv;";
15122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create an object, verify basics.
15124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Value> val = CompileRun(sample);
15125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(val->IsObject());
151266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Local<v8::Object> obj = val.As<v8::Object>();
15127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  obj->Set(v8_str("gamma"), v8_str("cloneme"));
15128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(v8_str("hello"), obj->Get(v8_str("alpha")));
15130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(v8::Integer::New(isolate, 123), obj->Get(v8_str("beta")));
15131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(v8_str("cloneme"), obj->Get(v8_str("gamma")));
15132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Clone it.
15134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<v8::Object> clone = obj->Clone();
15135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(v8_str("hello"), clone->Get(v8_str("alpha")));
15136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(v8::Integer::New(isolate, 123), clone->Get(v8_str("beta")));
15137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(v8_str("cloneme"), clone->Get(v8_str("gamma")));
15138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set a property on the clone, verify each object.
15140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  clone->Set(v8_str("beta"), v8::Integer::New(isolate, 456));
15141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(v8::Integer::New(isolate, 123), obj->Get(v8_str("beta")));
15142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(v8::Integer::New(isolate, 456), clone->Get(v8_str("beta")));
15143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
15144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass OneByteVectorResource : public v8::String::ExternalOneByteStringResource {
15147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
15148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  explicit OneByteVectorResource(i::Vector<const char> vector)
15149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      : data_(vector) {}
15150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  virtual ~OneByteVectorResource() {}
15151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual size_t length() const { return data_.length(); }
15152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual const char* data() const { return data_.start(); }
15153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
15154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  i::Vector<const char> data_;
15155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
15156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass UC16VectorResource : public v8::String::ExternalStringResource {
15159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
15160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  explicit UC16VectorResource(i::Vector<const i::uc16> vector)
15161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      : data_(vector) {}
15162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual ~UC16VectorResource() {}
15163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual size_t length() const { return data_.length(); }
15164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual const i::uc16* data() const { return data_.start(); }
15165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
15166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  i::Vector<const i::uc16> data_;
15167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
15168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void MorphAString(i::String* string,
15171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         OneByteVectorResource* one_byte_resource,
15172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         UC16VectorResource* uc16_resource) {
15173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(i::StringShape(string).IsExternal());
15174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (string->IsOneByteRepresentation()) {
15175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Check old map is not internalized or long.
15176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(string->map() == CcTest::heap()->external_one_byte_string_map());
15177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Morph external string to be TwoByte string.
15178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    string->set_map(CcTest::heap()->external_string_map());
15179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    i::ExternalTwoByteString* morphed =
15180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         i::ExternalTwoByteString::cast(string);
15181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    morphed->set_resource(uc16_resource);
15182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
15183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Check old map is not internalized or long.
15184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(string->map() == CcTest::heap()->external_string_map());
15185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Morph external string to be one-byte string.
15186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    string->set_map(CcTest::heap()->external_one_byte_string_map());
15187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    i::ExternalOneByteString* morphed = i::ExternalOneByteString::cast(string);
15188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    morphed->set_resource(one_byte_resource);
15189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
15190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
15191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test that we can still flatten a string if the components it is built up
15194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// from have been turned into 16 bit strings in the mean time.
15195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(MorphCompositeStringTest) {
151963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  char utf_buffer[129];
15197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* c_string = "Now is the time for all good men"
15198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         " to come to the aid of the party";
15199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  uint16_t* two_byte_string = AsciiToTwoByteString(c_string);
15200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {
15201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    LocalContext env;
15202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    i::Factory* factory = CcTest::i_isolate()->factory();
15203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(env->GetIsolate());
15204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    OneByteVectorResource one_byte_resource(
15205d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        i::Vector<const char>(c_string, i::StrLength(c_string)));
15206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    UC16VectorResource uc16_resource(
15207d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        i::Vector<const uint16_t>(two_byte_string,
15208d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                  i::StrLength(c_string)));
15209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<String> lhs(
15211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v8::Utils::ToLocal(factory->NewExternalStringFromOneByte(
15212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        &one_byte_resource).ToHandleChecked()));
15213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<String> rhs(
15214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v8::Utils::ToLocal(factory->NewExternalStringFromOneByte(
15215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        &one_byte_resource).ToHandleChecked()));
15216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    env->Global()->Set(v8_str("lhs"), lhs);
15218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    env->Global()->Set(v8_str("rhs"), rhs);
15219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CompileRun(
15221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        "var cons = lhs + rhs;"
15222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        "var slice = lhs.substring(1, lhs.length - 1);"
15223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        "var slice_on_cons = (lhs + rhs).substring(1, lhs.length *2 - 1);");
15224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(lhs->IsOneByte());
15226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(rhs->IsOneByte());
152273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MorphAString(*v8::Utils::OpenHandle(*lhs), &one_byte_resource,
15229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 &uc16_resource);
15230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MorphAString(*v8::Utils::OpenHandle(*rhs), &one_byte_resource,
15231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 &uc16_resource);
15232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
152333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // This should UTF-8 without flattening, since everything is ASCII.
152343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> cons = v8_compile("cons")->Run().As<String>();
152353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CHECK_EQ(128, cons->Utf8Length());
152363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int nchars = -1;
152373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CHECK_EQ(129, cons->WriteUtf8(utf_buffer, -1, &nchars));
152383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CHECK_EQ(128, nchars);
152393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CHECK_EQ(0, strcmp(
152403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        utf_buffer,
152413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        "Now is the time for all good men to come to the aid of the party"
152423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        "Now is the time for all good men to come to the aid of the party"));
152433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Now do some stuff to make sure the strings are flattened, etc.
15245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CompileRun(
15246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        "/[^a-z]/.test(cons);"
15247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        "/[^a-z]/.test(slice);"
15248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        "/[^a-z]/.test(slice_on_cons);");
15249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    const char* expected_cons =
15250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        "Now is the time for all good men to come to the aid of the party"
15251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        "Now is the time for all good men to come to the aid of the party";
15252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    const char* expected_slice =
15253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        "ow is the time for all good men to come to the aid of the part";
15254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    const char* expected_slice_on_cons =
15255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        "ow is the time for all good men to come to the aid of the party"
15256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        "Now is the time for all good men to come to the aid of the part";
15257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(String::NewFromUtf8(env->GetIsolate(), expected_cons),
15258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block             env->Global()->Get(v8_str("cons")));
15259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(String::NewFromUtf8(env->GetIsolate(), expected_slice),
15260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block             env->Global()->Get(v8_str("slice")));
15261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(String::NewFromUtf8(env->GetIsolate(), expected_slice_on_cons),
15262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block             env->Global()->Get(v8_str("slice_on_cons")));
15263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
152643bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  i::DeleteArray(two_byte_string);
15265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
15266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(CompileExternalTwoByteSource) {
15269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
15270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(context->GetIsolate());
15271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // This is a very short list of sources, which currently is to check for a
15273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // regression caused by r2703.
15274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* one_byte_sources[] = {
15275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "0.5",
15276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "-0.5",   // This mainly testes PushBack in the Scanner.
15277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "--0.5",  // This mainly testes PushBack in the Scanner.
15278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      NULL};
15279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compile the sources as external two byte strings.
15281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; one_byte_sources[i] != NULL; i++) {
15282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint16_t* two_byte_string = AsciiToTwoByteString(one_byte_sources[i]);
15283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    TestResource* uc16_resource = new TestResource(two_byte_string);
15284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Local<v8::String> source =
15285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v8::String::NewExternal(context->GetIsolate(), uc16_resource);
15286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    v8::Script::Compile(source);
15287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
15288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
15289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifndef V8_INTERPRETED_REGEXP
15292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstruct RegExpInterruptionData {
15294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int loop_count;
15295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  UC16VectorResource* string_resource;
15296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Persistent<v8::String> string;
15297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} regexp_interruption_data;
15298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
15299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
15300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass RegExpInterruptionThread : public v8::base::Thread {
15301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
15302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  explicit RegExpInterruptionThread(v8::Isolate* isolate)
15303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : Thread(Options("TimeoutThread")), isolate_(isolate) {}
15304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
15305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  virtual void Run() {
15306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (regexp_interruption_data.loop_count = 0;
15307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         regexp_interruption_data.loop_count < 7;
15308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         regexp_interruption_data.loop_count++) {
15309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::base::OS::Sleep(50);  // Wait a bit before requesting GC.
15310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      reinterpret_cast<i::Isolate*>(isolate_)->stack_guard()->RequestGC();
15311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
15312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::base::OS::Sleep(50);  // Wait a bit before terminating.
15313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::V8::TerminateExecution(isolate_);
15314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
15315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
153163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch private:
15317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate_;
15318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
15319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid RunBeforeGC(v8::GCType type, v8::GCCallbackFlags flags) {
15322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (regexp_interruption_data.loop_count != 2) return;
15323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(CcTest::isolate());
15324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::String> string = v8::Local<v8::String>::New(
15325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CcTest::isolate(), regexp_interruption_data.string);
15326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  string->MakeExternal(regexp_interruption_data.string_resource);
15327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
15328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Test that RegExp execution can be interrupted.  Specifically, we test
15331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// * interrupting with GC
15332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// * turn the subject string from one-byte internal to two-byte external string
15333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// * force termination
15334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(RegExpInterruption) {
15335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(CcTest::isolate());
15336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
15337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RegExpInterruptionThread timeout_thread(CcTest::isolate());
15339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::V8::AddGCPrologueCallback(RunBeforeGC);
15341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const char* one_byte_content = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
15342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::uc16* uc16_content = AsciiToTwoByteString(one_byte_content);
15343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::String> string = v8_str(one_byte_content);
15344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::global()->Set(v8_str("a"), string);
15346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  regexp_interruption_data.string.Reset(CcTest::isolate(), string);
15347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  regexp_interruption_data.string_resource = new UC16VectorResource(
15348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      i::Vector<const i::uc16>(uc16_content, i::StrLength(one_byte_content)));
15349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::TryCatch try_catch;
15351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  timeout_thread.Start();
15352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
15353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("/((a*)*)*b/.exec(a)");
15354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(try_catch.HasTerminated());
15355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
15356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  timeout_thread.Join();
15357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
15358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  regexp_interruption_data.string.Reset();
15359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::DeleteArray(uc16_content);
15360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
15361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif  // V8_INTERPRETED_REGEXP
15363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
15365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Test that we cannot set a property on the global object if there
15366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// is a read-only property in the prototype chain.
15367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(ReadOnlyPropertyInGlobalProto) {
15368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
15369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
15370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
15371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context(0, templ);
15372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Object> global = context->Global();
15373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Object> global_proto =
15374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      v8::Handle<v8::Object>::Cast(global->Get(v8_str("__proto__")));
15375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  global_proto->ForceSet(v8_str("x"), v8::Integer::New(isolate, 0),
15376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         v8::ReadOnly);
15377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  global_proto->ForceSet(v8_str("y"), v8::Integer::New(isolate, 0),
15378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         v8::ReadOnly);
15379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check without 'eval' or 'with'.
15380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Value> res =
15381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      CompileRun("function f() { x = 42; return x; }; f()");
15382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(v8::Integer::New(isolate, 0), res);
15383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check with 'eval'.
15384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  res = CompileRun("function f() { eval('1'); y = 43; return y; }; f()");
15385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(v8::Integer::New(isolate, 0), res);
15386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check with 'with'.
15387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  res = CompileRun("function f() { with (this) { y = 44 }; return y; }; f()");
15388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(v8::Integer::New(isolate, 0), res);
15389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
15390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic int force_set_set_count = 0;
15392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic int force_set_get_count = 0;
15393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool pass_on_get = false;
15394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void ForceSetGetter(v8::Local<v8::String> name,
15396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           const v8::PropertyCallbackInfo<v8::Value>& info) {
15397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  force_set_get_count++;
15398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (pass_on_get) {
15399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
15400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
15401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(3);
15402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
15403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void ForceSetSetter(v8::Local<v8::String> name,
15405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                           v8::Local<v8::Value> value,
15406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           const v8::PropertyCallbackInfo<void>& info) {
15407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  force_set_set_count++;
15408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
15409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void ForceSetInterceptSetter(
15411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    v8::Local<v8::String> name,
15412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    v8::Local<v8::Value> value,
15413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Value>& info) {
15414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  force_set_set_count++;
15415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().SetUndefined();
15416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
15417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
15419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(ForceSet) {
15420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  force_set_get_count = 0;
15421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  force_set_set_count = 0;
15422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  pass_on_get = false;
15423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
15425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
15426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
15427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::String> access_property =
15428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(isolate, "a");
15429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  templ->SetAccessor(access_property, ForceSetGetter, ForceSetSetter);
15430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context(NULL, templ);
15431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Object> global = context->Global();
15432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Ordinary properties
15434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::String> simple_property =
15435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(isolate, "p");
15436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  global->ForceSet(simple_property, v8::Int32::New(isolate, 4), v8::ReadOnly);
15437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(4, global->Get(simple_property)->Int32Value());
15438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // This should fail because the property is read-only
15439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  global->Set(simple_property, v8::Int32::New(isolate, 5));
15440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(4, global->Get(simple_property)->Int32Value());
15441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // This should succeed even though the property is read-only
15442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  global->ForceSet(simple_property, v8::Int32::New(isolate, 6));
15443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(6, global->Get(simple_property)->Int32Value());
15444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Accessors
15446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, force_set_set_count);
15447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, force_set_get_count);
15448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(3, global->Get(access_property)->Int32Value());
15449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // CHECK_EQ the property shouldn't override it, just call the setter
15450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // which in this case does nothing.
15451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  global->Set(access_property, v8::Int32::New(isolate, 7));
15452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(3, global->Get(access_property)->Int32Value());
15453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, force_set_set_count);
15454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, force_set_get_count);
15455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Forcing the property to be set should override the accessor without
15456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // calling it
15457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  global->ForceSet(access_property, v8::Int32::New(isolate, 8));
15458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(8, global->Get(access_property)->Int32Value());
15459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, force_set_set_count);
15460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, force_set_get_count);
15461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
15462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
15464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(ForceSetWithInterceptor) {
15465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  force_set_get_count = 0;
15466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  force_set_set_count = 0;
15467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  pass_on_get = false;
15468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
15470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
15471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
15472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  templ->SetNamedPropertyHandler(ForceSetGetter, ForceSetInterceptSetter);
15473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context(NULL, templ);
15474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Object> global = context->Global();
15475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::String> some_property =
15477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(isolate, "a");
15478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, force_set_set_count);
15479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, force_set_get_count);
15480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(3, global->Get(some_property)->Int32Value());
15481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Setting the property shouldn't override it, just call the setter
15482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // which in this case does nothing.
15483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  global->Set(some_property, v8::Int32::New(isolate, 7));
15484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(3, global->Get(some_property)->Int32Value());
15485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, force_set_set_count);
15486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, force_set_get_count);
15487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Getting the property when the interceptor returns an empty handle
15488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // should yield undefined, since the property isn't present on the
15489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // object itself yet.
15490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  pass_on_get = true;
15491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(global->Get(some_property)->IsUndefined());
15492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, force_set_set_count);
15493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(3, force_set_get_count);
15494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Forcing the property to be set should cause the value to be
15495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // set locally without calling the interceptor.
15496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  global->ForceSet(some_property, v8::Int32::New(isolate, 8));
15497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(8, global->Get(some_property)->Int32Value());
15498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, force_set_set_count);
15499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(4, force_set_get_count);
15500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Reenabling the interceptor should cause it to take precedence over
15501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the property
15502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  pass_on_get = false;
15503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(3, global->Get(some_property)->Int32Value());
15504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, force_set_set_count);
15505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(5, force_set_get_count);
15506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The interceptor should also work for other properties
15507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(3, global->Get(v8::String::NewFromUtf8(isolate, "b"))
15508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  ->Int32Value());
15509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, force_set_set_count);
15510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(6, force_set_get_count);
15511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
15512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(ForceDelete) {
15515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
15516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
15517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
15518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context(NULL, templ);
15519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Object> global = context->Global();
15520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Ordinary properties
15522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::String> simple_property =
15523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(isolate, "p");
15524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  global->ForceSet(simple_property, v8::Int32::New(isolate, 4), v8::DontDelete);
15525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(4, global->Get(simple_property)->Int32Value());
15526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // This should fail because the property is dont-delete.
15527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(!global->Delete(simple_property));
15528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(4, global->Get(simple_property)->Int32Value());
15529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // This should succeed even though the property is dont-delete.
15530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(global->ForceDelete(simple_property));
15531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(global->Get(simple_property)->IsUndefined());
15532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
15533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic int force_delete_interceptor_count = 0;
15536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic bool pass_on_delete = false;
15537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void ForceDeleteDeleter(
15540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    v8::Local<v8::String> name,
15541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Boolean>& info) {
15542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  force_delete_interceptor_count++;
15543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (pass_on_delete) return;
15544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(true);
15545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
15546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(ForceDeleteWithInterceptor) {
15549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  force_delete_interceptor_count = 0;
15550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  pass_on_delete = false;
15551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
15553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
15554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
15555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  templ->SetNamedPropertyHandler(0, 0, 0, ForceDeleteDeleter);
15556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context(NULL, templ);
15557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Object> global = context->Global();
15558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::String> some_property =
15560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(isolate, "a");
15561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  global->ForceSet(some_property, v8::Integer::New(isolate, 42),
15562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   v8::DontDelete);
15563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Deleting a property should get intercepted and nothing should
15565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // happen.
15566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, force_delete_interceptor_count);
15567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(global->Delete(some_property));
15568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, force_delete_interceptor_count);
15569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(42, global->Get(some_property)->Int32Value());
15570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Deleting the property when the interceptor returns an empty
15571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // handle should not delete the property since it is DontDelete.
15572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  pass_on_delete = true;
15573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(!global->Delete(some_property));
15574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, force_delete_interceptor_count);
15575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(42, global->Get(some_property)->Int32Value());
15576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Forcing the property to be deleted should delete the value
15577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // without calling the interceptor.
15578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(global->ForceDelete(some_property));
15579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(global->Get(some_property)->IsUndefined());
15580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, force_delete_interceptor_count);
15581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
15582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Make sure that forcing a delete invalidates any IC stubs, so we
15585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// don't read the hole value.
15586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(ForceDeleteIC) {
15587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
15588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(context->GetIsolate());
15589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create a DontDelete variable on the global object.
15590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CompileRun("this.__proto__ = { foo: 'horse' };"
15591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block             "var foo = 'fish';"
15592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block             "function f() { return foo.length; }");
15593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Initialize the IC for foo in f.
15594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CompileRun("for (var i = 0; i < 4; i++) f();");
15595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make sure the value of foo is correct before the deletion.
15596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(4, CompileRun("f()")->Int32Value());
15597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Force the deletion of foo.
15598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(context->Global()->ForceDelete(v8_str("foo")));
15599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make sure the value for foo is read from the prototype, and that
15600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // we don't get in trouble with reading the deleted cell value
15601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sentinel.
15602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(5, CompileRun("f()")->Int32Value());
15603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
15604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(InlinedFunctionAcrossContexts) {
15607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::FLAG_allow_natives_syntax = true;
15608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
15609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope outer_scope(isolate);
15610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Context> ctx1 = v8::Context::New(isolate);
15611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Context> ctx2 = v8::Context::New(isolate);
15612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ctx1->Enter();
15613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
15614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
15615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope inner_scope(CcTest::isolate());
15616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CompileRun("var G = 42; function foo() { return G; }");
15617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Local<v8::Value> foo = ctx1->Global()->Get(v8_str("foo"));
15618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ctx2->Enter();
15619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ctx2->Global()->Set(v8_str("o"), foo);
15620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Local<v8::Value> res = CompileRun(
15621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "function f() { return o(); }"
15622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "for (var i = 0; i < 10; ++i) f();"
15623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "%OptimizeFunctionOnNextCall(f);"
15624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "f();");
15625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(42, res->Int32Value());
15626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ctx2->Exit();
15627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Handle<v8::String> G_property =
15628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v8::String::NewFromUtf8(CcTest::isolate(), "G");
15629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(ctx1->Global()->ForceDelete(G_property));
15630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ctx2->Enter();
15631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ExpectString(
15632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "(function() {"
15633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "  try {"
15634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "    return f();"
15635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "  } catch(e) {"
15636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "    return e.toString();"
15637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "  }"
15638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        " })()",
15639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "ReferenceError: G is not defined");
15640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ctx2->Exit();
15641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ctx1->Exit();
15642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
15643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
15644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
15645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
15646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic v8::Local<Context> calling_context0;
15647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic v8::Local<Context> calling_context1;
15648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic v8::Local<Context> calling_context2;
15649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Check that the call to the callback is initiated in
15652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// calling_context2, the directly calling context is calling_context1
15653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// and the callback itself is in calling_context0.
15654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void GetCallingContextCallback(
15655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::FunctionCallbackInfo<v8::Value>& args) {
15656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ApiTestFuzzer::Fuzz();
15657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(args.GetIsolate()->GetCurrentContext() == calling_context0);
15658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(args.GetIsolate()->GetCallingContext() == calling_context1);
15659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(args.GetIsolate()->GetEnteredContext() == calling_context2);
15660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  args.GetReturnValue().Set(42);
15661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
15662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
15663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
15664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(GetCurrentContextWhenNotInContext) {
15665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::Isolate* isolate = CcTest::i_isolate();
15666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(isolate != NULL);
15667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(isolate->context() == NULL);
15668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
15669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(v8_isolate);
15670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The following should not crash, but return an empty handle.
15671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Context> current = v8_isolate->GetCurrentContext();
15672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(current.IsEmpty());
15673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
15674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(GetCallingContext) {
15677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
15678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
15679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Context> calling_context0(Context::New(isolate));
15681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Context> calling_context1(Context::New(isolate));
15682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Context> calling_context2(Context::New(isolate));
15683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ::calling_context0 = calling_context0;
15684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ::calling_context1 = calling_context1;
15685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ::calling_context2 = calling_context2;
15686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allow cross-domain access.
15688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<String> token = v8_str("<security token>");
15689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  calling_context0->SetSecurityToken(token);
15690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  calling_context1->SetSecurityToken(token);
15691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  calling_context2->SetSecurityToken(token);
15692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create an object with a C++ callback in context0.
15694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  calling_context0->Enter();
15695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<v8::FunctionTemplate> callback_templ =
15696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::FunctionTemplate::New(isolate, GetCallingContextCallback);
15697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  calling_context0->Global()->Set(v8_str("callback"),
15698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  callback_templ->GetFunction());
15699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  calling_context0->Exit();
15700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
157013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Expose context0 in context1 and set up a function that calls the
15702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // callback function.
15703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  calling_context1->Enter();
15704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  calling_context1->Global()->Set(v8_str("context0"),
15705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  calling_context0->Global());
15706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CompileRun("function f() { context0.callback() }");
15707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  calling_context1->Exit();
15708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Expose context1 in context2 and call the callback function in
15710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // context0 indirectly through f in context1.
15711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  calling_context2->Enter();
15712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  calling_context2->Global()->Set(v8_str("context1"),
15713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  calling_context1->Global());
15714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CompileRun("context1.f()");
15715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  calling_context2->Exit();
15716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ::calling_context0.Clear();
15717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ::calling_context1.Clear();
15718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ::calling_context2.Clear();
15719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
15720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Check that a variable declaration with no explicit initialization
15723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// value does shadow an existing property in the prototype chain.
15724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(InitGlobalVarInProtoChain) {
15725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
15726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(context->GetIsolate());
15727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Introduce a variable in the prototype chain.
15728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CompileRun("__proto__.x = 42");
15729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Value> result = CompileRun("var x = 43; x");
15730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(!result->IsUndefined());
15731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(43, result->Int32Value());
15732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
15733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Regression test for issue 398.
15736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// If a function is added to an object, creating a constant function
15737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// field, and the result is cloned, replacing the constant function on the
15738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// original should not affect the clone.
15739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// See http://code.google.com/p/v8/issues/detail?id=398
15740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(ReplaceConstantFunction) {
15741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
15742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
15743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
15744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Object> obj = v8::Object::New(isolate);
15745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::FunctionTemplate> func_templ =
15746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::FunctionTemplate::New(isolate);
15747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::String> foo_string =
15748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(isolate, "foo");
15749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  obj->Set(foo_string, func_templ->GetFunction());
15750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Object> obj_clone = obj->Clone();
15751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  obj_clone->Set(foo_string,
15752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 v8::String::NewFromUtf8(isolate, "Hello"));
15753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(!obj->Get(foo_string)->IsUndefined());
15754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
15755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void CheckElementValue(i::Isolate* isolate,
15758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              int expected,
15759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              i::Handle<i::Object> obj,
15760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              int offset) {
15761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::Object* element =
15762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      *i::Object::GetElement(isolate, obj, offset).ToHandleChecked();
15763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(expected, i::Smi::cast(element)->value());
15764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
15765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(PixelArray) {
15768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
15769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::Isolate* isolate = CcTest::i_isolate();
15770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::Factory* factory = isolate->factory();
15771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(context->GetIsolate());
15772d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  const int kElementCount = 260;
15773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(kElementCount));
15774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::Handle<i::ExternalUint8ClampedArray> pixels =
15775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      i::Handle<i::ExternalUint8ClampedArray>::cast(
15776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          factory->NewExternalArray(kElementCount,
15777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    v8::kExternalUint8ClampedArray,
157783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    pixel_data));
157793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Force GC to trigger verification.
15780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
15781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < kElementCount; i++) {
15782d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    pixels->set(i, i % 256);
15783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
157843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Force GC to trigger verification.
15785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
15786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < kElementCount; i++) {
1578769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    CHECK_EQ(i % 256, pixels->get_scalar(i));
15788d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    CHECK_EQ(i % 256, pixel_data[i]);
15789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
15790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Object> obj = v8::Object::New(context->GetIsolate());
15792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
15793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set the elements to be the pixels.
15794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // jsobj->set_elements(*pixels);
15795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  obj->SetIndexedPropertiesToPixelData(pixel_data, kElementCount);
15796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckElementValue(isolate, 1, jsobj, 1);
15797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  obj->Set(v8_str("field"), v8::Int32::New(CcTest::isolate(), 1503));
15798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  context->Global()->Set(v8_str("pixels"), obj);
15799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Value> result = CompileRun("pixels.field");
15800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1503, result->Int32Value());
15801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  result = CompileRun("pixels[1]");
15802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, result->Int32Value());
15803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  result = CompileRun("var sum = 0;"
15805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "for (var i = 0; i < 8; i++) {"
15806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "  sum += pixels[i] = pixels[i] = -i;"
15807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "}"
15808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "sum;");
15809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(-28, result->Int32Value());
15810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  result = CompileRun("var sum = 0;"
15812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "for (var i = 0; i < 8; i++) {"
15813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "  sum += pixels[i] = pixels[i] = 0;"
15814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "}"
15815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "sum;");
15816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, result->Int32Value());
15817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  result = CompileRun("var sum = 0;"
15819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "for (var i = 0; i < 8; i++) {"
15820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "  sum += pixels[i] = pixels[i] = 255;"
15821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "}"
15822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "sum;");
15823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(8 * 255, result->Int32Value());
15824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  result = CompileRun("var sum = 0;"
15826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "for (var i = 0; i < 8; i++) {"
15827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "  sum += pixels[i] = pixels[i] = 256 + i;"
15828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "}"
15829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "sum;");
15830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2076, result->Int32Value());
15831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  result = CompileRun("var sum = 0;"
15833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "for (var i = 0; i < 8; i++) {"
15834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "  sum += pixels[i] = pixels[i] = i;"
15835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "}"
15836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "sum;");
15837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(28, result->Int32Value());
15838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  result = CompileRun("var sum = 0;"
15840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "for (var i = 0; i < 8; i++) {"
15841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "  sum += pixels[i];"
15842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "}"
15843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "sum;");
15844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(28, result->Int32Value());
15845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::Handle<i::Smi> value(i::Smi::FromInt(2),
15847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          reinterpret_cast<i::Isolate*>(context->GetIsolate()));
15848589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  i::Handle<i::Object> no_failure;
15849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  no_failure = i::JSObject::SetElement(
15850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      jsobj, 1, value, NONE, i::SLOPPY).ToHandleChecked();
15851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!no_failure.is_null());
15852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  USE(no_failure);
15853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckElementValue(isolate, 2, jsobj, 1);
15854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  *value.location() = i::Smi::FromInt(256);
15855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  no_failure = i::JSObject::SetElement(
15856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      jsobj, 1, value, NONE, i::SLOPPY).ToHandleChecked();
15857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!no_failure.is_null());
15858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  USE(no_failure);
15859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckElementValue(isolate, 255, jsobj, 1);
15860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  *value.location() = i::Smi::FromInt(-1);
15861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  no_failure = i::JSObject::SetElement(
15862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      jsobj, 1, value, NONE, i::SLOPPY).ToHandleChecked();
15863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!no_failure.is_null());
15864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  USE(no_failure);
15865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckElementValue(isolate, 0, jsobj, 1);
15866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  result = CompileRun("for (var i = 0; i < 8; i++) {"
15868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "  pixels[i] = (i * 65) - 109;"
15869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "}"
15870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "pixels[1] + pixels[6];");
15871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(255, result->Int32Value());
15872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckElementValue(isolate, 0, jsobj, 0);
15873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckElementValue(isolate, 0, jsobj, 1);
15874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckElementValue(isolate, 21, jsobj, 2);
15875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckElementValue(isolate, 86, jsobj, 3);
15876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckElementValue(isolate, 151, jsobj, 4);
15877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckElementValue(isolate, 216, jsobj, 5);
15878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckElementValue(isolate, 255, jsobj, 6);
15879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckElementValue(isolate, 255, jsobj, 7);
15880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  result = CompileRun("var sum = 0;"
15881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "for (var i = 0; i < 8; i++) {"
15882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "  sum += pixels[i];"
15883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "}"
15884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "sum;");
15885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(984, result->Int32Value());
15886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  result = CompileRun("for (var i = 0; i < 8; i++) {"
15888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "  pixels[i] = (i * 1.1);"
15889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "}"
15890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "pixels[1] + pixels[6];");
15891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(8, result->Int32Value());
15892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckElementValue(isolate, 0, jsobj, 0);
15893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckElementValue(isolate, 1, jsobj, 1);
15894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckElementValue(isolate, 2, jsobj, 2);
15895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckElementValue(isolate, 3, jsobj, 3);
15896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckElementValue(isolate, 4, jsobj, 4);
15897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckElementValue(isolate, 6, jsobj, 5);
15898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckElementValue(isolate, 7, jsobj, 6);
15899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckElementValue(isolate, 8, jsobj, 7);
15900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  result = CompileRun("for (var i = 0; i < 8; i++) {"
15902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "  pixels[7] = undefined;"
15903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "}"
15904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "pixels[7];");
15905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, result->Int32Value());
15906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckElementValue(isolate, 0, jsobj, 7);
15907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  result = CompileRun("for (var i = 0; i < 8; i++) {"
15909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "  pixels[6] = '2.3';"
15910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "}"
15911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "pixels[6];");
15912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, result->Int32Value());
15913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckElementValue(isolate, 2, jsobj, 6);
15914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  result = CompileRun("for (var i = 0; i < 8; i++) {"
15916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "  pixels[5] = NaN;"
15917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "}"
15918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "pixels[5];");
15919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, result->Int32Value());
15920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckElementValue(isolate, 0, jsobj, 5);
15921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  result = CompileRun("for (var i = 0; i < 8; i++) {"
15923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "  pixels[8] = Infinity;"
15924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "}"
15925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "pixels[8];");
15926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(255, result->Int32Value());
15927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckElementValue(isolate, 255, jsobj, 8);
15928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  result = CompileRun("for (var i = 0; i < 8; i++) {"
15930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "  pixels[9] = -Infinity;"
15931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "}"
15932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "pixels[9];");
15933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, result->Int32Value());
15934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckElementValue(isolate, 0, jsobj, 9);
15935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  result = CompileRun("pixels[3] = 33;"
15937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "delete pixels[3];"
15938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "pixels[3];");
15939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(33, result->Int32Value());
15940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  result = CompileRun("pixels[0] = 10; pixels[1] = 11;"
15942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "pixels[2] = 12; pixels[3] = 13;"
15943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "pixels.__defineGetter__('2',"
15944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "function() { return 120; });"
15945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "pixels[2];");
15946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(12, result->Int32Value());
15947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  result = CompileRun("var js_array = new Array(40);"
15949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "js_array[0] = 77;"
15950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "js_array;");
15951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
15952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  result = CompileRun("pixels[1] = 23;"
15954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "pixels.__proto__ = [];"
15955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "js_array.__proto__ = pixels;"
15956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "js_array.concat(pixels);");
15957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
15958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(23, v8::Object::Cast(*result)->Get(v8_str("1"))->Int32Value());
15959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  result = CompileRun("pixels[1] = 23;");
15961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(23, result->Int32Value());
15962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15963d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Test for index greater than 255.  Regression test for:
15964d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // http://code.google.com/p/chromium/issues/detail?id=26337.
15965d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  result = CompileRun("pixels[256] = 255;");
15966d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CHECK_EQ(255, result->Int32Value());
15967d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  result = CompileRun("var i = 0;"
15968d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                      "for (var j = 0; j < 8; j++) { i = pixels[256]; }"
15969d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                      "i");
15970d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CHECK_EQ(255, result->Int32Value());
15971d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
159721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Make sure that pixel array ICs recognize when a non-pixel array
159731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // is passed to it.
159741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  result = CompileRun("function pa_load(p) {"
159751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "  var sum = 0;"
159761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "  for (var j = 0; j < 256; j++) { sum += p[j]; }"
159771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "  return sum;"
159781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "}"
159791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
159801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "for (var i = 0; i < 10; ++i) { pa_load(pixels); }"
159811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "just_ints = new Object();"
159821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
159831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "for (var i = 0; i < 10; ++i) {"
159841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "  result = pa_load(just_ints);"
159851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "}"
159861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "result");
159871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  CHECK_EQ(32640, result->Int32Value());
159881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
159891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Make sure that pixel array ICs recognize out-of-bound accesses.
159901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  result = CompileRun("function pa_load(p, start) {"
159911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "  var sum = 0;"
159921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "  for (var j = start; j < 256; j++) { sum += p[j]; }"
159931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "  return sum;"
159941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "}"
159951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
159961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "for (var i = 0; i < 10; ++i) { pa_load(pixels,0); }"
159971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "for (var i = 0; i < 10; ++i) {"
159981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "  result = pa_load(pixels,-10);"
159991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "}"
160001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "result");
160011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  CHECK_EQ(0, result->Int32Value());
160021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
160031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Make sure that generic ICs properly handles a pixel array.
160041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  result = CompileRun("function pa_load(p) {"
160051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "  var sum = 0;"
160061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "  for (var j = 0; j < 256; j++) { sum += p[j]; }"
160071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "  return sum;"
160081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "}"
160091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
160101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "just_ints = new Object();"
160111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
160121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "for (var i = 0; i < 10; ++i) { pa_load(just_ints); }"
160131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "for (var i = 0; i < 10; ++i) {"
160141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "  result = pa_load(pixels);"
160151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "}"
160161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "result");
160171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  CHECK_EQ(32640, result->Int32Value());
160181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
160191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Make sure that generic load ICs recognize out-of-bound accesses in
160201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // pixel arrays.
160211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  result = CompileRun("function pa_load(p, start) {"
160221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "  var sum = 0;"
160231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "  for (var j = start; j < 256; j++) { sum += p[j]; }"
160241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "  return sum;"
160251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "}"
160261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
160271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "just_ints = new Object();"
160281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
160291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "for (var i = 0; i < 10; ++i) { pa_load(just_ints,0); }"
160301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "for (var i = 0; i < 10; ++i) { pa_load(pixels,0); }"
160311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "for (var i = 0; i < 10; ++i) {"
160321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "  result = pa_load(pixels,-10);"
160331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "}"
160341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "result");
160351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  CHECK_EQ(0, result->Int32Value());
160361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
160371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Make sure that generic ICs properly handles other types than pixel
160381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // arrays (that the inlined fast pixel array test leaves the right information
160391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // in the right registers).
160401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  result = CompileRun("function pa_load(p) {"
160411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "  var sum = 0;"
160421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "  for (var j = 0; j < 256; j++) { sum += p[j]; }"
160431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "  return sum;"
160441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "}"
160451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
160461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "just_ints = new Object();"
160471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
160481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "for (var i = 0; i < 10; ++i) { pa_load(just_ints); }"
160491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "for (var i = 0; i < 10; ++i) { pa_load(pixels); }"
160501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "sparse_array = new Object();"
160511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "for (var i = 0; i < 256; ++i) { sparse_array[i] = i; }"
160521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "sparse_array[1000000] = 3;"
160531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "for (var i = 0; i < 10; ++i) {"
160541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "  result = pa_load(sparse_array);"
160551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "}"
160561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "result");
160571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  CHECK_EQ(32640, result->Int32Value());
160581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
16059e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Make sure that pixel array store ICs clamp values correctly.
16060e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  result = CompileRun("function pa_store(p) {"
16061e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      "  for (var j = 0; j < 256; j++) { p[j] = j * 2; }"
16062e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      "}"
16063e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      "pa_store(pixels);"
16064e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      "var sum = 0;"
16065e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
16066e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      "sum");
16067e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  CHECK_EQ(48896, result->Int32Value());
16068e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
16069e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Make sure that pixel array stores correctly handle accesses outside
16070e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // of the pixel array..
16071e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  result = CompileRun("function pa_store(p,start) {"
16072e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      "  for (var j = 0; j < 256; j++) {"
16073e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      "    p[j+start] = j * 2;"
16074e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      "  }"
16075e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      "}"
16076e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      "pa_store(pixels,0);"
16077e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      "pa_store(pixels,-128);"
16078e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      "var sum = 0;"
16079e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
16080e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      "sum");
16081e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  CHECK_EQ(65280, result->Int32Value());
16082e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
16083e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Make sure that the generic store stub correctly handle accesses outside
16084e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // of the pixel array..
16085e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  result = CompileRun("function pa_store(p,start) {"
16086e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      "  for (var j = 0; j < 256; j++) {"
16087e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      "    p[j+start] = j * 2;"
16088e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      "  }"
16089e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      "}"
16090e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      "pa_store(pixels,0);"
16091e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      "just_ints = new Object();"
16092e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
16093e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      "pa_store(just_ints, 0);"
16094e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      "pa_store(pixels,-128);"
16095e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      "var sum = 0;"
16096e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
16097e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      "sum");
16098e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  CHECK_EQ(65280, result->Int32Value());
16099e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
16100e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Make sure that the generic keyed store stub clamps pixel array values
16101e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // correctly.
16102e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  result = CompileRun("function pa_store(p) {"
16103e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      "  for (var j = 0; j < 256; j++) { p[j] = j * 2; }"
16104e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      "}"
16105e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      "pa_store(pixels);"
16106e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      "just_ints = new Object();"
16107e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      "pa_store(just_ints);"
16108e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      "pa_store(pixels);"
16109e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      "var sum = 0;"
16110e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
16111e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      "sum");
16112e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  CHECK_EQ(48896, result->Int32Value());
16113e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
16114e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Make sure that pixel array loads are optimized by crankshaft.
161151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  result = CompileRun("function pa_load(p) {"
161161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "  var sum = 0;"
161171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "  for (var i=0; i<256; ++i) {"
161181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "    sum += p[i];"
161191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "  }"
161201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "  return sum; "
161211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "}"
161221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
1612344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                      "for (var i = 0; i < 5000; ++i) {"
161241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "  result = pa_load(pixels);"
161251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "}"
161261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      "result");
161271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  CHECK_EQ(32640, result->Int32Value());
161281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
16129e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Make sure that pixel array stores are optimized by crankshaft.
16130e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  result = CompileRun("function pa_init(p) {"
16131e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      "for (var i = 0; i < 256; ++i) { p[i] = i; }"
16132e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      "}"
16133e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      "function pa_load(p) {"
16134e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      "  var sum = 0;"
16135e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      "  for (var i=0; i<256; ++i) {"
16136e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      "    sum += p[i];"
16137e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      "  }"
16138e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      "  return sum; "
16139e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      "}"
1614044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                      "for (var i = 0; i < 5000; ++i) {"
16141e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      "  pa_init(pixels);"
16142e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      "}"
16143e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      "result = pa_load(pixels);"
16144e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      "result");
16145e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  CHECK_EQ(32640, result->Int32Value());
16146e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
16147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  free(pixel_data);
16148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
16149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
16150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
161519dcf7e2f83591d471e88bf7d230651900b8e424bKristian MonsenTHREADED_TEST(PixelArrayInfo) {
161523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  LocalContext context;
16153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(context->GetIsolate());
161549dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  for (int size = 0; size < 100; size += 10) {
161559dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(size));
16156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Handle<v8::Object> obj = v8::Object::New(context->GetIsolate());
161579dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    obj->SetIndexedPropertiesToPixelData(pixel_data, size);
161589dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    CHECK(obj->HasIndexedPropertiesInPixelData());
161599dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    CHECK_EQ(pixel_data, obj->GetIndexedPropertiesPixelData());
161609dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    CHECK_EQ(size, obj->GetIndexedPropertiesPixelDataLength());
161619dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    free(pixel_data);
161629dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  }
161639dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
161649dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
161659dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
16166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void NotHandledIndexedPropertyGetter(
16167e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    uint32_t index,
16168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Value>& info) {
16169e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ApiTestFuzzer::Fuzz();
16170e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
16171e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
16172e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
16173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void NotHandledIndexedPropertySetter(
16174e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    uint32_t index,
16175e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Local<Value> value,
16176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Value>& info) {
16177e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ApiTestFuzzer::Fuzz();
16178e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
16179e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
16180e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
16181e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochTHREADED_TEST(PixelArrayWithInterceptor) {
16182e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  LocalContext context;
16183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::Factory* factory = CcTest::i_isolate()->factory();
16184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
16185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
16186e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  const int kElementCount = 260;
16187e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(kElementCount));
16188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::Handle<i::ExternalUint8ClampedArray> pixels =
16189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      i::Handle<i::ExternalUint8ClampedArray>::cast(
16190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          factory->NewExternalArray(kElementCount,
16191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    v8::kExternalUint8ClampedArray,
1619244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                    pixel_data));
16193e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  for (int i = 0; i < kElementCount; i++) {
16194e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    pixels->set(i, i % 256);
16195e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
16196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> templ =
16197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::ObjectTemplate::New(context->GetIsolate());
16198e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  templ->SetIndexedPropertyHandler(NotHandledIndexedPropertyGetter,
16199e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                   NotHandledIndexedPropertySetter);
16200e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v8::Handle<v8::Object> obj = templ->NewInstance();
16201e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  obj->SetIndexedPropertiesToPixelData(pixel_data, kElementCount);
16202e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  context->Global()->Set(v8_str("pixels"), obj);
16203e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v8::Handle<v8::Value> result = CompileRun("pixels[1]");
16204e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  CHECK_EQ(1, result->Int32Value());
16205e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  result = CompileRun("var sum = 0;"
16206e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      "for (var i = 0; i < 8; i++) {"
16207e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      "  sum += pixels[i] = pixels[i] = -i;"
16208e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      "}"
16209e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      "sum;");
16210e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  CHECK_EQ(-28, result->Int32Value());
16211e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  result = CompileRun("pixels.hasOwnProperty('1')");
16212e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  CHECK(result->BooleanValue());
16213e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  free(pixel_data);
16214e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
16215e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
16216e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
162179dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenstatic int ExternalArrayElementSize(v8::ExternalArrayType array_type) {
162183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  switch (array_type) {
16219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case v8::kExternalInt8Array:
16220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case v8::kExternalUint8Array:
16221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case v8::kExternalUint8ClampedArray:
162229dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      return 1;
162233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      break;
16224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case v8::kExternalInt16Array:
16225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case v8::kExternalUint16Array:
162269dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      return 2;
162273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      break;
16228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case v8::kExternalInt32Array:
16229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case v8::kExternalUint32Array:
16230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case v8::kExternalFloat32Array:
162319dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      return 4;
162323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      break;
16233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case v8::kExternalFloat64Array:
16234257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      return 8;
16235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      break;
162363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    default:
162373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      UNREACHABLE();
162389dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      return -1;
162393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
162409dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  UNREACHABLE();
162419dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  return -1;
162429dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
162439dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
162449dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
162459dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsentemplate <class ExternalArrayClass, class ElementType>
16246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void ObjectWithExternalArrayTestHelper(
16247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<Context> context,
16248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Handle<Object> obj,
16249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int element_count,
16250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::ExternalArrayType array_type,
16251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int64_t low, int64_t high) {
162523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
16253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::Isolate* isolate = jsobj->GetIsolate();
16254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  obj->Set(v8_str("field"),
16255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           v8::Int32::New(reinterpret_cast<v8::Isolate*>(isolate), 1503));
162563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  context->Global()->Set(v8_str("ext_array"), obj);
162573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  v8::Handle<v8::Value> result = CompileRun("ext_array.field");
162583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK_EQ(1503, result->Int32Value());
162593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  result = CompileRun("ext_array[1]");
162603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK_EQ(1, result->Int32Value());
162613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
162623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Check assigned smis
162633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  result = CompileRun("for (var i = 0; i < 8; i++) {"
162643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      "  ext_array[i] = i;"
162653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      "}"
162663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      "var sum = 0;"
162673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      "for (var i = 0; i < 8; i++) {"
162683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      "  sum += ext_array[i];"
162693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      "}"
162703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      "sum;");
16271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
162723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK_EQ(28, result->Int32Value());
16273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check pass through of assigned smis
16274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  result = CompileRun("var sum = 0;"
16275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      "for (var i = 0; i < 8; i++) {"
16276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      "  sum += ext_array[i] = ext_array[i] = -i;"
16277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      "}"
16278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      "sum;");
16279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(-28, result->Int32Value());
16280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
162813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
162823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Check assigned smis in reverse order
162833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  result = CompileRun("for (var i = 8; --i >= 0; ) {"
162843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      "  ext_array[i] = i;"
162853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      "}"
162863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      "var sum = 0;"
162873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      "for (var i = 0; i < 8; i++) {"
162883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      "  sum += ext_array[i];"
162893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      "}"
162903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      "sum;");
162913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK_EQ(28, result->Int32Value());
162923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
162933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Check pass through of assigned HeapNumbers
162943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  result = CompileRun("var sum = 0;"
162953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      "for (var i = 0; i < 16; i+=2) {"
162963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      "  sum += ext_array[i] = ext_array[i] = (-i * 0.5);"
162973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      "}"
162983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      "sum;");
162993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK_EQ(-28, result->Int32Value());
163003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
163013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Check assigned HeapNumbers
163023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  result = CompileRun("for (var i = 0; i < 16; i+=2) {"
163033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      "  ext_array[i] = (i * 0.5);"
163043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      "}"
163053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      "var sum = 0;"
163063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      "for (var i = 0; i < 16; i+=2) {"
163073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      "  sum += ext_array[i];"
163083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      "}"
163093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      "sum;");
163103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK_EQ(28, result->Int32Value());
163113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
163123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Check assigned HeapNumbers in reverse order
163133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  result = CompileRun("for (var i = 14; i >= 0; i-=2) {"
163143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      "  ext_array[i] = (i * 0.5);"
163153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      "}"
163163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      "var sum = 0;"
163173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      "for (var i = 0; i < 16; i+=2) {"
163183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      "  sum += ext_array[i];"
163193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      "}"
163203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      "sum;");
163213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK_EQ(28, result->Int32Value());
163223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
163233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  i::ScopedVector<char> test_buf(1024);
163243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
163253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Check legal boundary conditions.
163263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // The repeated loads and stores ensure the ICs are exercised.
163273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  const char* boundary_program =
163283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      "var res = 0;"
163293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      "for (var i = 0; i < 16; i++) {"
163303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      "  ext_array[i] = %lld;"
163313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      "  if (i > 8) {"
163323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      "    res = ext_array[i];"
163333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      "  }"
163343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      "}"
163353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      "res;";
16336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::SNPrintF(test_buf,
16337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              boundary_program,
16338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              low);
163393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  result = CompileRun(test_buf.start());
163403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK_EQ(low, result->IntegerValue());
163413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::SNPrintF(test_buf,
16343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              boundary_program,
16344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              high);
163453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  result = CompileRun(test_buf.start());
163463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK_EQ(high, result->IntegerValue());
163473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
163483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Check misprediction of type in IC.
163493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  result = CompileRun("var tmp_array = ext_array;"
163503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      "var sum = 0;"
163513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      "for (var i = 0; i < 8; i++) {"
163523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      "  tmp_array[i] = i;"
163533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      "  sum += tmp_array[i];"
163543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      "  if (i == 4) {"
163553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      "    tmp_array = {};"
163563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      "  }"
163573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      "}"
163583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      "sum;");
163593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Force GC to trigger verification.
16360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
163613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK_EQ(28, result->Int32Value());
163623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
163633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Make sure out-of-range loads do not throw.
16364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::SNPrintF(test_buf,
16365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              "var caught_exception = false;"
16366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              "try {"
16367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              "  ext_array[%d];"
16368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              "} catch (e) {"
16369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              "  caught_exception = true;"
16370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              "}"
16371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              "caught_exception;",
16372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              element_count);
163733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  result = CompileRun(test_buf.start());
163743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK_EQ(false, result->BooleanValue());
163753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
163763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Make sure out-of-range stores do not throw.
16377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::SNPrintF(test_buf,
16378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              "var caught_exception = false;"
16379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              "try {"
16380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              "  ext_array[%d] = 1;"
16381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              "} catch (e) {"
16382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              "  caught_exception = true;"
16383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              "}"
16384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              "caught_exception;",
16385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              element_count);
163863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  result = CompileRun(test_buf.start());
163873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK_EQ(false, result->BooleanValue());
163883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
163893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Check other boundary conditions, values and operations.
163903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  result = CompileRun("for (var i = 0; i < 8; i++) {"
163913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      "  ext_array[7] = undefined;"
163923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      "}"
163933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      "ext_array[7];");
163943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK_EQ(0, result->Int32Value());
16395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (array_type == v8::kExternalFloat64Array ||
16396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      array_type == v8::kExternalFloat32Array) {
16397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(static_cast<int>(v8::base::OS::nan_value()),
16398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             static_cast<int>(
16399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 i::Object::GetElement(
16400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     isolate, jsobj, 7).ToHandleChecked()->Number()));
164013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
16402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CheckElementValue(isolate, 0, jsobj, 7);
164033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
164043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
164053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  result = CompileRun("for (var i = 0; i < 8; i++) {"
164063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      "  ext_array[6] = '2.3';"
164073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      "}"
164083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      "ext_array[6];");
164093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK_EQ(2, result->Int32Value());
16410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2,
16411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           static_cast<int>(
16412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               i::Object::GetElement(
16413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   isolate, jsobj, 6).ToHandleChecked()->Number()));
164143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (array_type != v8::kExternalFloat32Array &&
16416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      array_type != v8::kExternalFloat64Array) {
164173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Though the specification doesn't state it, be explicit about
164183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // converting NaNs and +/-Infinity to zero.
164193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    result = CompileRun("for (var i = 0; i < 8; i++) {"
164203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                        "  ext_array[i] = 5;"
164213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                        "}"
164223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                        "for (var i = 0; i < 8; i++) {"
164233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                        "  ext_array[i] = NaN;"
164243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                        "}"
164253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                        "ext_array[5];");
164263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    CHECK_EQ(0, result->Int32Value());
16427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CheckElementValue(isolate, 0, jsobj, 5);
164283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
164293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    result = CompileRun("for (var i = 0; i < 8; i++) {"
164303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                        "  ext_array[i] = 5;"
164313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                        "}"
164323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                        "for (var i = 0; i < 8; i++) {"
164333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                        "  ext_array[i] = Infinity;"
164343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                        "}"
164353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                        "ext_array[5];");
1643644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    int expected_value =
16437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        (array_type == v8::kExternalUint8ClampedArray) ? 255 : 0;
1643844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    CHECK_EQ(expected_value, result->Int32Value());
16439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CheckElementValue(isolate, expected_value, jsobj, 5);
164403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
164413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    result = CompileRun("for (var i = 0; i < 8; i++) {"
164423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                        "  ext_array[i] = 5;"
164433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                        "}"
164443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                        "for (var i = 0; i < 8; i++) {"
164453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                        "  ext_array[i] = -Infinity;"
164463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                        "}"
164473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                        "ext_array[5];");
164483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    CHECK_EQ(0, result->Int32Value());
16449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CheckElementValue(isolate, 0, jsobj, 5);
164501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
164511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Check truncation behavior of integral arrays.
164521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    const char* unsigned_data =
164531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        "var source_data = [0.6, 10.6];"
164541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        "var expected_results = [0, 10];";
164551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    const char* signed_data =
164561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        "var source_data = [0.6, 10.6, -0.6, -10.6];"
164571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        "var expected_results = [0, 10, 0, -10];";
1645844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    const char* pixel_data =
1645944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        "var source_data = [0.6, 10.6];"
1646044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        "var expected_results = [1, 11];";
164611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    bool is_unsigned =
16462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        (array_type == v8::kExternalUint8Array ||
16463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         array_type == v8::kExternalUint16Array ||
16464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         array_type == v8::kExternalUint32Array);
16465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bool is_pixel_data = array_type == v8::kExternalUint8ClampedArray;
16466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
16467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    i::SNPrintF(test_buf,
16468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                "%s"
16469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                "var all_passed = true;"
16470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                "for (var i = 0; i < source_data.length; i++) {"
16471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                "  for (var j = 0; j < 8; j++) {"
16472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                "    ext_array[j] = source_data[i];"
16473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                "  }"
16474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                "  all_passed = all_passed &&"
16475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                "               (ext_array[5] == expected_results[i]);"
16476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                "}"
16477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                "all_passed;",
16478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                (is_unsigned ?
16479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     unsigned_data :
16480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     (is_pixel_data ? pixel_data : signed_data)));
164811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    result = CompileRun(test_buf.start());
164821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    CHECK_EQ(true, result->BooleanValue());
164833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
164843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::Handle<ExternalArrayClass> array(
16486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ExternalArrayClass::cast(jsobj->elements()));
16487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < element_count; i++) {
164888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    array->set(i, static_cast<ElementType>(i));
164898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
16490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
164918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // Test complex assignments
164928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  result = CompileRun("function ee_op_test_complex_func(sum) {"
164938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                      " for (var i = 0; i < 40; ++i) {"
164948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                      "   sum += (ext_array[i] += 1);"
164958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                      "   sum += (ext_array[i] -= 1);"
164968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                      " } "
164978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                      " return sum;"
164988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                      "}"
164998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                      "sum=0;"
165008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                      "for (var i=0;i<10000;++i) {"
165018b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                      "  sum=ee_op_test_complex_func(sum);"
165028b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                      "}"
165038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                      "sum;");
165048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK_EQ(16000000, result->Int32Value());
165058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
165068b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // Test count operations
165078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  result = CompileRun("function ee_op_test_count_func(sum) {"
165088b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                      " for (var i = 0; i < 40; ++i) {"
165098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                      "   sum += (++ext_array[i]);"
165108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                      "   sum += (--ext_array[i]);"
165118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                      " } "
165128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                      " return sum;"
165138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                      "}"
165148b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                      "sum=0;"
165158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                      "for (var i=0;i<10000;++i) {"
165168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                      "  sum=ee_op_test_count_func(sum);"
165178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                      "}"
165188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                      "sum;");
165198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK_EQ(16000000, result->Int32Value());
165208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
165213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  result = CompileRun("ext_array[3] = 33;"
165223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      "delete ext_array[3];"
165233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      "ext_array[3];");
165243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK_EQ(33, result->Int32Value());
165253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
165263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  result = CompileRun("ext_array[0] = 10; ext_array[1] = 11;"
165273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      "ext_array[2] = 12; ext_array[3] = 13;"
165283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      "ext_array.__defineGetter__('2',"
165293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      "function() { return 120; });"
165303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      "ext_array[2];");
165313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK_EQ(12, result->Int32Value());
165323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
165333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  result = CompileRun("var js_array = new Array(40);"
165343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      "js_array[0] = 77;"
165353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      "js_array;");
165363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
165373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
165383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  result = CompileRun("ext_array[1] = 23;"
165393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      "ext_array.__proto__ = [];"
165403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      "js_array.__proto__ = ext_array;"
165413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      "js_array.concat(ext_array);");
165423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
165433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK_EQ(23, v8::Object::Cast(*result)->Get(v8_str("1"))->Int32Value());
165443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
165453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  result = CompileRun("ext_array[1] = 23;");
165463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK_EQ(23, result->Int32Value());
16547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
16548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
16549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
16550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate <class FixedTypedArrayClass,
16551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          i::ElementsKind elements_kind,
16552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          class ElementType>
16553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void FixedTypedArrayTestHelper(
16554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::ExternalArrayType array_type,
16555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ElementType low,
16556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ElementType high) {
16557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::FLAG_allow_natives_syntax = true;
16558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
16559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::Isolate* isolate = CcTest::i_isolate();
16560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::Factory* factory = isolate->factory();
16561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(context->GetIsolate());
16562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int kElementCount = 260;
16563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::Handle<FixedTypedArrayClass> fixed_array =
16564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    i::Handle<FixedTypedArrayClass>::cast(
16565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        factory->NewFixedTypedArray(kElementCount, array_type));
16566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(FixedTypedArrayClass::kInstanceType,
16567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           fixed_array->map()->instance_type());
16568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(kElementCount, fixed_array->length());
16569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
16570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < kElementCount; i++) {
16571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    fixed_array->set(i, static_cast<ElementType>(i));
16572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
16573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Force GC to trigger verification.
16574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
16575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < kElementCount; i++) {
16576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(static_cast<int64_t>(static_cast<ElementType>(i)),
16577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             static_cast<int64_t>(fixed_array->get_scalar(i)));
16578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
16579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Object> obj = v8::Object::New(CcTest::isolate());
16580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
16581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::Handle<i::Map> fixed_array_map =
16582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      i::JSObject::GetElementsTransitionMap(jsobj, elements_kind);
16583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  jsobj->set_map(*fixed_array_map);
16584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  jsobj->set_elements(*fixed_array);
16585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
16586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ObjectWithExternalArrayTestHelper<FixedTypedArrayClass, ElementType>(
16587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      context.local(), obj, kElementCount, array_type,
16588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      static_cast<int64_t>(low),
16589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      static_cast<int64_t>(high));
16590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
16591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
16592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
16593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(FixedUint8Array) {
16594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  FixedTypedArrayTestHelper<i::FixedUint8Array, i::UINT8_ELEMENTS, uint8_t>(
16595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::kExternalUint8Array,
16596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    0x0, 0xFF);
16597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
16598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
16599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
16600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(FixedUint8ClampedArray) {
16601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  FixedTypedArrayTestHelper<i::FixedUint8ClampedArray,
16602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            i::UINT8_CLAMPED_ELEMENTS, uint8_t>(
16603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::kExternalUint8ClampedArray,
16604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    0x0, 0xFF);
16605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
16606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
16607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
16608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(FixedInt8Array) {
16609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  FixedTypedArrayTestHelper<i::FixedInt8Array, i::INT8_ELEMENTS, int8_t>(
16610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::kExternalInt8Array,
16611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    -0x80, 0x7F);
16612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
16613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
16614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
16615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(FixedUint16Array) {
16616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  FixedTypedArrayTestHelper<i::FixedUint16Array, i::UINT16_ELEMENTS, uint16_t>(
16617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::kExternalUint16Array,
16618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    0x0, 0xFFFF);
16619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
16620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
16621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
16622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(FixedInt16Array) {
16623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  FixedTypedArrayTestHelper<i::FixedInt16Array, i::INT16_ELEMENTS, int16_t>(
16624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::kExternalInt16Array,
16625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    -0x8000, 0x7FFF);
16626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
16627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
16628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
16629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(FixedUint32Array) {
16630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  FixedTypedArrayTestHelper<i::FixedUint32Array, i::UINT32_ELEMENTS, uint32_t>(
16631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::kExternalUint32Array,
16632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    0x0, UINT_MAX);
16633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
16634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
16635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
16636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(FixedInt32Array) {
16637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  FixedTypedArrayTestHelper<i::FixedInt32Array, i::INT32_ELEMENTS, int32_t>(
16638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::kExternalInt32Array,
16639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    INT_MIN, INT_MAX);
16640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
16641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
16642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
16643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(FixedFloat32Array) {
16644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  FixedTypedArrayTestHelper<i::FixedFloat32Array, i::FLOAT32_ELEMENTS, float>(
16645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::kExternalFloat32Array,
16646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    -500, 500);
16647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
16648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
16649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
16650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(FixedFloat64Array) {
16651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  FixedTypedArrayTestHelper<i::FixedFloat64Array, i::FLOAT64_ELEMENTS, float>(
16652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::kExternalFloat64Array,
16653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    -500, 500);
16654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
16655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
16656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
16657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate <class ExternalArrayClass, class ElementType>
16658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void ExternalArrayTestHelper(v8::ExternalArrayType array_type,
16659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    int64_t low,
16660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    int64_t high) {
16661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
16662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::Isolate* isolate = CcTest::i_isolate();
16663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::Factory* factory = isolate->factory();
16664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(context->GetIsolate());
16665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int kElementCount = 40;
16666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int element_size = ExternalArrayElementSize(array_type);
16667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ElementType* array_data =
16668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      static_cast<ElementType*>(malloc(kElementCount * element_size));
16669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::Handle<ExternalArrayClass> array =
16670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      i::Handle<ExternalArrayClass>::cast(
16671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          factory->NewExternalArray(kElementCount, array_type, array_data));
16672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Force GC to trigger verification.
16673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
16674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < kElementCount; i++) {
16675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    array->set(i, static_cast<ElementType>(i));
16676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
16677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Force GC to trigger verification.
16678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
16679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < kElementCount; i++) {
16680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(static_cast<int64_t>(i),
16681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             static_cast<int64_t>(array->get_scalar(i)));
16682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(static_cast<int64_t>(i), static_cast<int64_t>(array_data[i]));
16683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
16684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
16685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Object> obj = v8::Object::New(context->GetIsolate());
16686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
16687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Set the elements to be the external array.
16688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  obj->SetIndexedPropertiesToExternalArrayData(array_data,
16689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               array_type,
16690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               kElementCount);
16691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1,
16692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           static_cast<int>(
16693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               i::Object::GetElement(
16694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   isolate, jsobj, 1).ToHandleChecked()->Number()));
16695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
16696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ObjectWithExternalArrayTestHelper<ExternalArrayClass, ElementType>(
16697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      context.local(), obj, kElementCount, array_type, low, high);
16698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
16699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Value> result;
167003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16701d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Test more complex manipulations which cause eax to contain values
16702d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // that won't be completely overwritten by loads from the arrays.
16703d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // This catches bugs in the instructions used for the KeyedLoadIC
16704d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // for byte and word types.
16705d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  {
16706d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    const int kXSize = 300;
16707d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    const int kYSize = 300;
16708d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    const int kLargeElementCount = kXSize * kYSize * 4;
16709d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ElementType* large_array_data =
16710d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        static_cast<ElementType*>(malloc(kLargeElementCount * element_size));
16711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Handle<v8::Object> large_obj = v8::Object::New(context->GetIsolate());
16712d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Set the elements to be the external array.
16713d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    large_obj->SetIndexedPropertiesToExternalArrayData(large_array_data,
16714d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                                       array_type,
16715d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                                       kLargeElementCount);
16716d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    context->Global()->Set(v8_str("large_array"), large_obj);
16717d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Initialize contents of a few rows.
16718d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    for (int x = 0; x < 300; x++) {
16719d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      int row = 0;
16720d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      int offset = row * 300 * 4;
16721d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      large_array_data[offset + 4 * x + 0] = (ElementType) 127;
16722d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      large_array_data[offset + 4 * x + 1] = (ElementType) 0;
16723d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      large_array_data[offset + 4 * x + 2] = (ElementType) 0;
16724d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      large_array_data[offset + 4 * x + 3] = (ElementType) 127;
16725d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      row = 150;
16726d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      offset = row * 300 * 4;
16727d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      large_array_data[offset + 4 * x + 0] = (ElementType) 127;
16728d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      large_array_data[offset + 4 * x + 1] = (ElementType) 0;
16729d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      large_array_data[offset + 4 * x + 2] = (ElementType) 0;
16730d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      large_array_data[offset + 4 * x + 3] = (ElementType) 127;
16731d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      row = 298;
16732d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      offset = row * 300 * 4;
16733d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      large_array_data[offset + 4 * x + 0] = (ElementType) 127;
16734d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      large_array_data[offset + 4 * x + 1] = (ElementType) 0;
16735d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      large_array_data[offset + 4 * x + 2] = (ElementType) 0;
16736d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      large_array_data[offset + 4 * x + 3] = (ElementType) 127;
16737d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
16738d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // The goal of the code below is to make "offset" large enough
16739d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // that the computation of the index (which goes into eax) has
16740d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // high bits set which will not be overwritten by a byte or short
16741d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // load.
16742d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    result = CompileRun("var failed = false;"
16743d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                        "var offset = 0;"
16744d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                        "for (var i = 0; i < 300; i++) {"
16745d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                        "  if (large_array[4 * i] != 127 ||"
16746d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                        "      large_array[4 * i + 1] != 0 ||"
16747d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                        "      large_array[4 * i + 2] != 0 ||"
16748d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                        "      large_array[4 * i + 3] != 127) {"
16749d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                        "    failed = true;"
16750d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                        "  }"
16751d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                        "}"
16752d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                        "offset = 150 * 300 * 4;"
16753d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                        "for (var i = 0; i < 300; i++) {"
16754d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                        "  if (large_array[offset + 4 * i] != 127 ||"
16755d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                        "      large_array[offset + 4 * i + 1] != 0 ||"
16756d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                        "      large_array[offset + 4 * i + 2] != 0 ||"
16757d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                        "      large_array[offset + 4 * i + 3] != 127) {"
16758d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                        "    failed = true;"
16759d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                        "  }"
16760d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                        "}"
16761d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                        "offset = 298 * 300 * 4;"
16762d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                        "for (var i = 0; i < 300; i++) {"
16763d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                        "  if (large_array[offset + 4 * i] != 127 ||"
16764d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                        "      large_array[offset + 4 * i + 1] != 0 ||"
16765d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                        "      large_array[offset + 4 * i + 2] != 0 ||"
16766d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                        "      large_array[offset + 4 * i + 3] != 127) {"
16767d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                        "    failed = true;"
16768d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                        "  }"
16769d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                        "}"
16770d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                        "!failed;");
16771d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    CHECK_EQ(true, result->BooleanValue());
16772d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    free(large_array_data);
16773d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
16774d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1677544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // The "" property descriptor is overloaded to store information about
1677644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // the external array. Ensure that setting and accessing the "" property
1677744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // works (it should overwrite the information cached about the external
1677844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // array in the DescriptorArray) in various situations.
1677944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  result = CompileRun("ext_array[''] = 23; ext_array['']");
1678044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(23, result->Int32Value());
1678144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1678244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Property "" set after the external array is associated with the object.
1678344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  {
16784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Handle<v8::Object> obj2 = v8::Object::New(context->GetIsolate());
16785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    obj2->Set(v8_str("ee_test_field"),
16786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              v8::Int32::New(context->GetIsolate(), 256));
16787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    obj2->Set(v8_str(""), v8::Int32::New(context->GetIsolate(), 1503));
1678844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Set the elements to be the external array.
1678944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    obj2->SetIndexedPropertiesToExternalArrayData(array_data,
1679044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                  array_type,
1679144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                  kElementCount);
1679244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    context->Global()->Set(v8_str("ext_array"), obj2);
1679344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    result = CompileRun("ext_array['']");
1679444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    CHECK_EQ(1503, result->Int32Value());
1679544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
1679644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1679744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Property "" set after the external array is associated with the object.
1679844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  {
16799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Handle<v8::Object> obj2 = v8::Object::New(context->GetIsolate());
16800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    obj2->Set(v8_str("ee_test_field_2"),
16801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              v8::Int32::New(context->GetIsolate(), 256));
1680244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Set the elements to be the external array.
1680344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    obj2->SetIndexedPropertiesToExternalArrayData(array_data,
1680444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                  array_type,
1680544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                  kElementCount);
16806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    obj2->Set(v8_str(""), v8::Int32::New(context->GetIsolate(), 1503));
1680744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    context->Global()->Set(v8_str("ext_array"), obj2);
1680844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    result = CompileRun("ext_array['']");
1680944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    CHECK_EQ(1503, result->Int32Value());
1681044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
1681144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1681244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Should reuse the map from previous test.
1681344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  {
16814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Handle<v8::Object> obj2 = v8::Object::New(context->GetIsolate());
16815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    obj2->Set(v8_str("ee_test_field_2"),
16816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              v8::Int32::New(context->GetIsolate(), 256));
1681744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Set the elements to be the external array. Should re-use the map
1681844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // from previous test.
1681944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    obj2->SetIndexedPropertiesToExternalArrayData(array_data,
1682044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                  array_type,
1682144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                  kElementCount);
1682244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    context->Global()->Set(v8_str("ext_array"), obj2);
1682344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    result = CompileRun("ext_array['']");
1682444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
1682544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1682644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Property "" is a constant function that shouldn't not be interfered with
1682744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // when an external array is set.
1682844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  {
16829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Handle<v8::Object> obj2 = v8::Object::New(context->GetIsolate());
1683044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Start
16831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    obj2->Set(v8_str("ee_test_field3"),
16832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              v8::Int32::New(context->GetIsolate(), 256));
1683344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1683444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Add a constant function to an object.
1683544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    context->Global()->Set(v8_str("ext_array"), obj2);
1683644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    result = CompileRun("ext_array[''] = function() {return 1503;};"
1683744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                        "ext_array['']();");
1683844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1683944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Add an external array transition to the same map that
1684044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // has the constant transition.
16841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Handle<v8::Object> obj3 = v8::Object::New(context->GetIsolate());
16842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    obj3->Set(v8_str("ee_test_field3"),
16843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              v8::Int32::New(context->GetIsolate(), 256));
1684444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    obj3->SetIndexedPropertiesToExternalArrayData(array_data,
1684544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                  array_type,
1684644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                  kElementCount);
1684744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    context->Global()->Set(v8_str("ext_array"), obj3);
1684844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
1684944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1685044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // If a external array transition is in the map, it should get clobbered
1685144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // by a constant function.
1685244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  {
1685344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Add an external array transition.
16854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Handle<v8::Object> obj3 = v8::Object::New(context->GetIsolate());
16855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    obj3->Set(v8_str("ee_test_field4"),
16856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              v8::Int32::New(context->GetIsolate(), 256));
1685744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    obj3->SetIndexedPropertiesToExternalArrayData(array_data,
1685844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                  array_type,
1685944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                  kElementCount);
1686044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1686144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Add a constant function to the same map that just got an external array
1686244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // transition.
16863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Handle<v8::Object> obj2 = v8::Object::New(context->GetIsolate());
16864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    obj2->Set(v8_str("ee_test_field4"),
16865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              v8::Int32::New(context->GetIsolate(), 256));
1686644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    context->Global()->Set(v8_str("ext_array"), obj2);
1686744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    result = CompileRun("ext_array[''] = function() {return 1503;};"
1686844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                        "ext_array['']();");
1686944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
1687044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
168713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  free(array_data);
168723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
168733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
168743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(ExternalInt8Array) {
16876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalArrayTestHelper<i::ExternalInt8Array, int8_t>(
16877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::kExternalInt8Array,
168783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      -128,
168793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      127);
168803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
168813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
168823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(ExternalUint8Array) {
16884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalArrayTestHelper<i::ExternalUint8Array, uint8_t>(
16885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::kExternalUint8Array,
168863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      0,
168873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      255);
168883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
168893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
168903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(ExternalUint8ClampedArray) {
16892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalArrayTestHelper<i::ExternalUint8ClampedArray, uint8_t>(
16893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::kExternalUint8ClampedArray,
1689444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      0,
1689544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      255);
1689644f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
1689744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1689844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
16899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(ExternalInt16Array) {
16900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalArrayTestHelper<i::ExternalInt16Array, int16_t>(
16901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::kExternalInt16Array,
169023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      -32768,
169033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      32767);
169043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
169053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
169063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(ExternalUint16Array) {
16908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalArrayTestHelper<i::ExternalUint16Array, uint16_t>(
16909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::kExternalUint16Array,
169103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      0,
169113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      65535);
169123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
169133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
169143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(ExternalInt32Array) {
16916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalArrayTestHelper<i::ExternalInt32Array, int32_t>(
16917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::kExternalInt32Array,
169183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      INT_MIN,   // -2147483648
169193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      INT_MAX);  //  2147483647
169203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
169213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
169223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(ExternalUint32Array) {
16924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalArrayTestHelper<i::ExternalUint32Array, uint32_t>(
16925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::kExternalUint32Array,
169263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      0,
169273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      UINT_MAX);  // 4294967295
169283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
169293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
169303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(ExternalFloat32Array) {
16932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalArrayTestHelper<i::ExternalFloat32Array, float>(
16933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::kExternalFloat32Array,
169343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      -500,
169353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      500);
169363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
169373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
169383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(ExternalFloat64Array) {
16940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalArrayTestHelper<i::ExternalFloat64Array, double>(
16941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::kExternalFloat64Array,
16942257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      -500,
16943257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      500);
16944257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
16945257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
16946257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
169473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockTHREADED_TEST(ExternalArrays) {
16948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TestExternalInt8Array();
16949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TestExternalUint8Array();
16950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TestExternalInt16Array();
16951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TestExternalUint16Array();
16952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TestExternalInt32Array();
16953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TestExternalUint32Array();
16954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TestExternalFloat32Array();
169553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
169563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
169573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
169589dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid ExternalArrayInfoTestHelper(v8::ExternalArrayType array_type) {
169599dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  LocalContext context;
16960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(context->GetIsolate());
169619dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  for (int size = 0; size < 100; size += 10) {
169629dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    int element_size = ExternalArrayElementSize(array_type);
169639dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    void* external_data = malloc(size * element_size);
16964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Handle<v8::Object> obj = v8::Object::New(context->GetIsolate());
169659dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    obj->SetIndexedPropertiesToExternalArrayData(
169669dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        external_data, array_type, size);
169679dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    CHECK(obj->HasIndexedPropertiesInExternalArrayData());
169689dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    CHECK_EQ(external_data, obj->GetIndexedPropertiesExternalArrayData());
169699dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    CHECK_EQ(array_type, obj->GetIndexedPropertiesExternalArrayDataType());
169709dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    CHECK_EQ(size, obj->GetIndexedPropertiesExternalArrayDataLength());
169719dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    free(external_data);
169729dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  }
169739dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
169749dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
169759dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
169769dcf7e2f83591d471e88bf7d230651900b8e424bKristian MonsenTHREADED_TEST(ExternalArrayInfo) {
16977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalArrayInfoTestHelper(v8::kExternalInt8Array);
16978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalArrayInfoTestHelper(v8::kExternalUint8Array);
16979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalArrayInfoTestHelper(v8::kExternalInt16Array);
16980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalArrayInfoTestHelper(v8::kExternalUint16Array);
16981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalArrayInfoTestHelper(v8::kExternalInt32Array);
16982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalArrayInfoTestHelper(v8::kExternalUint32Array);
16983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalArrayInfoTestHelper(v8::kExternalFloat32Array);
16984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalArrayInfoTestHelper(v8::kExternalFloat64Array);
16985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalArrayInfoTestHelper(v8::kExternalUint8ClampedArray);
16986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
16987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
16988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
16989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid ExtArrayLimitsHelper(v8::Isolate* isolate,
16990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          v8::ExternalArrayType array_type,
16991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          int size) {
16992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Object> obj = v8::Object::New(isolate);
16993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::V8::SetFatalErrorHandler(StoringErrorCallback);
16994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  last_location = last_message = NULL;
16995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  obj->SetIndexedPropertiesToExternalArrayData(NULL, array_type, size);
16996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!obj->HasIndexedPropertiesInExternalArrayData());
16997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_NE(NULL, last_location);
16998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_NE(NULL, last_message);
16999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
17000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(ExternalArrayLimits) {
17003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
17004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
17005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
17006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExtArrayLimitsHelper(isolate, v8::kExternalInt8Array, 0x40000000);
17007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExtArrayLimitsHelper(isolate, v8::kExternalInt8Array, 0xffffffff);
17008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExtArrayLimitsHelper(isolate, v8::kExternalUint8Array, 0x40000000);
17009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExtArrayLimitsHelper(isolate, v8::kExternalUint8Array, 0xffffffff);
17010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExtArrayLimitsHelper(isolate, v8::kExternalInt16Array, 0x40000000);
17011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExtArrayLimitsHelper(isolate, v8::kExternalInt16Array, 0xffffffff);
17012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExtArrayLimitsHelper(isolate, v8::kExternalUint16Array, 0x40000000);
17013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExtArrayLimitsHelper(isolate, v8::kExternalUint16Array, 0xffffffff);
17014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExtArrayLimitsHelper(isolate, v8::kExternalInt32Array, 0x40000000);
17015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExtArrayLimitsHelper(isolate, v8::kExternalInt32Array, 0xffffffff);
17016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExtArrayLimitsHelper(isolate, v8::kExternalUint32Array, 0x40000000);
17017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExtArrayLimitsHelper(isolate, v8::kExternalUint32Array, 0xffffffff);
17018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExtArrayLimitsHelper(isolate, v8::kExternalFloat32Array, 0x40000000);
17019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExtArrayLimitsHelper(isolate, v8::kExternalFloat32Array, 0xffffffff);
17020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExtArrayLimitsHelper(isolate, v8::kExternalFloat64Array, 0x40000000);
17021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExtArrayLimitsHelper(isolate, v8::kExternalFloat64Array, 0xffffffff);
17022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExtArrayLimitsHelper(isolate, v8::kExternalUint8ClampedArray, 0x40000000);
17023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExtArrayLimitsHelper(isolate, v8::kExternalUint8ClampedArray, 0xffffffff);
17024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
17025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate <typename ElementType, typename TypedArray,
17028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          class ExternalArrayClass>
17029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid TypedArrayTestHelper(v8::ExternalArrayType array_type,
17030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          int64_t low, int64_t high) {
17031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int kElementCount = 50;
17032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::ScopedVector<ElementType> backing_store(kElementCount+2);
17034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
17036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
17037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(isolate);
17038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::ArrayBuffer> ab =
17040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::ArrayBuffer::New(isolate, backing_store.start(),
17041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           (kElementCount + 2) * sizeof(ElementType));
17042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<TypedArray> ta =
17043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      TypedArray::New(ab, 2*sizeof(ElementType), kElementCount);
17044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
17045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(kElementCount, static_cast<int>(ta->Length()));
17046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2*sizeof(ElementType), static_cast<int>(ta->ByteOffset()));
17047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(kElementCount*sizeof(ElementType),
17048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           static_cast<int>(ta->ByteLength()));
17049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(ab, ta->Buffer());
17050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ElementType* data = backing_store.start() + 2;
17052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < kElementCount; i++) {
17053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    data[i] = static_cast<ElementType>(i);
17054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
17055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ObjectWithExternalArrayTestHelper<ExternalArrayClass, ElementType>(
17057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env.local(), ta, kElementCount, array_type, low, high);
17058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
17059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(Uint8Array) {
17062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::ExternalUint8Array>(
17063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::kExternalUint8Array, 0, 0xFF);
17064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
17065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(Int8Array) {
17068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TypedArrayTestHelper<int8_t, v8::Int8Array, i::ExternalInt8Array>(
17069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::kExternalInt8Array, -0x80, 0x7F);
17070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
17071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(Uint16Array) {
17074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TypedArrayTestHelper<uint16_t,
17075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       v8::Uint16Array,
17076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       i::ExternalUint16Array>(
17077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::kExternalUint16Array, 0, 0xFFFF);
17078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
17079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(Int16Array) {
17082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TypedArrayTestHelper<int16_t, v8::Int16Array, i::ExternalInt16Array>(
17083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::kExternalInt16Array, -0x8000, 0x7FFF);
17084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
17085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(Uint32Array) {
17088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TypedArrayTestHelper<uint32_t, v8::Uint32Array, i::ExternalUint32Array>(
17089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::kExternalUint32Array, 0, UINT_MAX);
17090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
17091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(Int32Array) {
17094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TypedArrayTestHelper<int32_t, v8::Int32Array, i::ExternalInt32Array>(
17095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::kExternalInt32Array, INT_MIN, INT_MAX);
17096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
17097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(Float32Array) {
17100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TypedArrayTestHelper<float, v8::Float32Array, i::ExternalFloat32Array>(
17101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::kExternalFloat32Array, -500, 500);
17102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
17103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(Float64Array) {
17106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TypedArrayTestHelper<double, v8::Float64Array, i::ExternalFloat64Array>(
17107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::kExternalFloat64Array, -500, 500);
17108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
17109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(Uint8ClampedArray) {
17112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TypedArrayTestHelper<uint8_t,
17113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       v8::Uint8ClampedArray, i::ExternalUint8ClampedArray>(
17114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::kExternalUint8ClampedArray, 0, 0xFF);
17115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
17116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(DataView) {
17119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int kSize = 50;
17120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::ScopedVector<uint8_t> backing_store(kSize+2);
17122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
17124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
17125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(isolate);
17126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::ArrayBuffer> ab =
17128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::ArrayBuffer::New(isolate, backing_store.start(), 2 + kSize);
17129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::DataView> dv =
17130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::DataView::New(ab, 2, kSize);
17131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
17132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2, static_cast<int>(dv->ByteOffset()));
17133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(kSize, static_cast<int>(dv->ByteLength()));
17134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(ab, dv->Buffer());
171359dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
171369dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
171379dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
17138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define IS_ARRAY_BUFFER_VIEW_TEST(View)                                       \
17139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  THREADED_TEST(Is##View) {                                                   \
17140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LocalContext env;                                                         \
17141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Isolate* isolate = env->GetIsolate();                                 \
17142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope handle_scope(isolate);                                    \
17143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                                              \
17144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<Value> result = CompileRun(                                        \
17145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "var ab = new ArrayBuffer(128);"                                      \
17146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "new " #View "(ab)");                                                 \
17147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(result->IsArrayBufferView());                                       \
17148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(result->Is##View());                                                \
17149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CheckInternalFieldsAreZero<v8::ArrayBufferView>(result.As<v8::View>());   \
17150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
17151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochIS_ARRAY_BUFFER_VIEW_TEST(Uint8Array)
17153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochIS_ARRAY_BUFFER_VIEW_TEST(Int8Array)
17154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochIS_ARRAY_BUFFER_VIEW_TEST(Uint16Array)
17155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochIS_ARRAY_BUFFER_VIEW_TEST(Int16Array)
17156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochIS_ARRAY_BUFFER_VIEW_TEST(Uint32Array)
17157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochIS_ARRAY_BUFFER_VIEW_TEST(Int32Array)
17158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochIS_ARRAY_BUFFER_VIEW_TEST(Float32Array)
17159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochIS_ARRAY_BUFFER_VIEW_TEST(Float64Array)
17160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochIS_ARRAY_BUFFER_VIEW_TEST(Uint8ClampedArray)
17161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochIS_ARRAY_BUFFER_VIEW_TEST(DataView)
17162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef IS_ARRAY_BUFFER_VIEW_TEST
17164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(ScriptContextDependence) {
17168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext c1;
17169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(c1->GetIsolate());
17170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char *source = "foo";
17171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Script> dep = v8_compile(source);
17172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::ScriptCompiler::Source script_source(v8::String::NewFromUtf8(
17173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      c1->GetIsolate(), source));
17174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::UnboundScript> indep =
17175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::ScriptCompiler::CompileUnbound(c1->GetIsolate(), &script_source);
17176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  c1->Global()->Set(v8::String::NewFromUtf8(c1->GetIsolate(), "foo"),
17177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                    v8::Integer::New(c1->GetIsolate(), 100));
17178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(dep->Run()->Int32Value(), 100);
17179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(indep->BindToCurrentContext()->Run()->Int32Value(), 100);
17180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext c2;
17181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  c2->Global()->Set(v8::String::NewFromUtf8(c2->GetIsolate(), "foo"),
17182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                    v8::Integer::New(c2->GetIsolate(), 101));
17183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(dep->Run()->Int32Value(), 100);
17184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(indep->BindToCurrentContext()->Run()->Int32Value(), 101);
17185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
17186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
17187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
17188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTHREADED_TEST(StackTrace) {
17189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext context;
17190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(context->GetIsolate());
17191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::TryCatch try_catch;
17192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char *source = "function foo() { FAIL.FAIL; }; foo();";
17193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::String> src =
17194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(context->GetIsolate(), source);
17195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::String> origin =
17196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(context->GetIsolate(), "stack-trace-test");
17197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::ScriptCompiler::Source script_source(src, v8::ScriptOrigin(origin));
17198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::ScriptCompiler::CompileUnbound(context->GetIsolate(), &script_source)
17199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ->BindToCurrentContext()
17200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ->Run();
17201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(try_catch.HasCaught());
17202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::String::Utf8Value stack(try_catch.StackTrace());
17203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(strstr(*stack, "at foo (stack-trace-test") != NULL);
17204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
17205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
17206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1720725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen// Checks that a StackFrame has certain expected values.
1720825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsenvoid checkStackFrame(const char* expected_script_name,
1720925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    const char* expected_func_name, int expected_line_number,
1721025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    int expected_column, bool is_eval, bool is_constructor,
1721125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    v8::Handle<v8::StackFrame> frame) {
17212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(CcTest::isolate());
1721325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  v8::String::Utf8Value func_name(frame->GetFunctionName());
1721425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  v8::String::Utf8Value script_name(frame->GetScriptName());
1721525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  if (*script_name == NULL) {
1721625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    // The situation where there is no associated script, like for evals.
1721725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    CHECK(expected_script_name == NULL);
1721825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  } else {
1721925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    CHECK(strstr(*script_name, expected_script_name) != NULL);
1722025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  }
1722125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  CHECK(strstr(*func_name, expected_func_name) != NULL);
1722225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  CHECK_EQ(expected_line_number, frame->GetLineNumber());
1722325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  CHECK_EQ(expected_column, frame->GetColumn());
1722425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  CHECK_EQ(is_eval, frame->IsEval());
1722525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  CHECK_EQ(is_constructor, frame->IsConstructor());
1722625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen}
1722725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
1722825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
17229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid AnalyzeStackInNativeCode(const v8::FunctionCallbackInfo<v8::Value>& args) {
17230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(args.GetIsolate());
1723125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  const char* origin = "capture-stack-trace-test";
1723225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  const int kOverviewTest = 1;
1723325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  const int kDetailedTest = 2;
1723425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
17235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args.Length() == 1);
1723625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
1723725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  int testGroup = args[0]->Int32Value();
1723825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  if (testGroup == kOverviewTest) {
17239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
17240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        args.GetIsolate(), 10, v8::StackTrace::kOverview);
1724125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    CHECK_EQ(4, stackTrace->GetFrameCount());
1724225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    checkStackFrame(origin, "bar", 2, 10, false, false,
1724325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen                    stackTrace->GetFrame(0));
1724425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    checkStackFrame(origin, "foo", 6, 3, false, false,
1724525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen                    stackTrace->GetFrame(1));
172463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // This is the source string inside the eval which has the call to foo.
172473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    checkStackFrame(NULL, "", 1, 5, false, false,
1724825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen                    stackTrace->GetFrame(2));
172493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // The last frame is an anonymous function which has the initial eval call.
1725025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    checkStackFrame(origin, "", 8, 7, false, false,
1725125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen                    stackTrace->GetFrame(3));
1725225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
1725325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    CHECK(stackTrace->AsArray()->IsArray());
1725425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  } else if (testGroup == kDetailedTest) {
17255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
17256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        args.GetIsolate(), 10, v8::StackTrace::kDetailed);
1725725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    CHECK_EQ(4, stackTrace->GetFrameCount());
1725825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    checkStackFrame(origin, "bat", 4, 22, false, false,
1725925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen                    stackTrace->GetFrame(0));
1726025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    checkStackFrame(origin, "baz", 8, 3, false, true,
1726125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen                    stackTrace->GetFrame(1));
172629dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    bool is_eval = true;
172633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // This is the source string inside the eval which has the call to baz.
172643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    checkStackFrame(NULL, "", 1, 5, is_eval, false,
1726525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen                    stackTrace->GetFrame(2));
172663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // The last frame is an anonymous function which has the initial eval call.
1726725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    checkStackFrame(origin, "", 10, 1, false, false,
1726825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen                    stackTrace->GetFrame(3));
1726925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
1727025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    CHECK(stackTrace->AsArray()->IsArray());
1727125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  }
1727225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen}
1727325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
1727425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
1727525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen// Tests the C++ StackTrace API.
17276b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// TODO(3074796): Reenable this as a THREADED_TEST once it passes.
17277b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// THREADED_TEST(CaptureStackTrace) {
17278b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochTEST(CaptureStackTrace) {
17279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
17280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
17281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::String> origin =
17282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(isolate, "capture-stack-trace-test");
17283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
1728425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  templ->Set(v8_str("AnalyzeStackInNativeCode"),
17285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             v8::FunctionTemplate::New(isolate, AnalyzeStackInNativeCode));
1728625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  LocalContext context(0, templ);
1728725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
1728825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  // Test getting OVERVIEW information. Should ignore information that is not
1728925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  // script name, function name, line number, and column offset.
1729025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  const char *overview_source =
1729125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    "function bar() {\n"
1729225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    "  var y; AnalyzeStackInNativeCode(1);\n"
1729325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    "}\n"
1729425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    "function foo() {\n"
1729525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    "\n"
1729625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    "  bar();\n"
1729725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    "}\n"
1729825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    "var x;eval('new foo();');";
17299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::String> overview_src =
17300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(isolate, overview_source);
17301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::ScriptCompiler::Source script_source(overview_src,
17302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           v8::ScriptOrigin(origin));
173033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::Handle<Value> overview_result(
17304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::ScriptCompiler::CompileUnbound(isolate, &script_source)
17305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          ->BindToCurrentContext()
17306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          ->Run());
173073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(!overview_result.IsEmpty());
173083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(overview_result->IsObject());
1730925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
1731025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  // Test getting DETAILED information.
1731125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  const char *detailed_source =
1731225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    "function bat() {AnalyzeStackInNativeCode(2);\n"
1731325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    "}\n"
1731425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    "\n"
1731525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    "function baz() {\n"
1731625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    "  bat();\n"
1731725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    "}\n"
1731825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    "eval('new baz();');";
17319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::String> detailed_src =
17320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(isolate, detailed_source);
1732125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  // Make the script using a non-zero line and column offset.
17322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Integer> line_offset = v8::Integer::New(isolate, 3);
17323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Integer> column_offset = v8::Integer::New(isolate, 5);
1732425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  v8::ScriptOrigin detailed_origin(origin, line_offset, column_offset);
17325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::ScriptCompiler::Source script_source2(detailed_src, detailed_origin);
17326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::UnboundScript> detailed_script(
17327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::ScriptCompiler::CompileUnbound(isolate, &script_source2));
17328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<Value> detailed_result(
17329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      detailed_script->BindToCurrentContext()->Run());
173303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(!detailed_result.IsEmpty());
173313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(detailed_result->IsObject());
1733225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen}
1733325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
1733425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
173353bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdochstatic void StackTraceForUncaughtExceptionListener(
173363bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    v8::Handle<v8::Message> message,
173373bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    v8::Handle<Value>) {
173383bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
173393bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  CHECK_EQ(2, stack_trace->GetFrameCount());
173403bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  checkStackFrame("origin", "foo", 2, 3, false, false,
173413bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                  stack_trace->GetFrame(0));
173423bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  checkStackFrame("origin", "bar", 5, 3, false, false,
173433bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                  stack_trace->GetFrame(1));
173443bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch}
173453bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
17346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
173473bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben MurdochTEST(CaptureStackTraceForUncaughtException) {
173483bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  report_count = 0;
173493bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  LocalContext env;
17350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
173513bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  v8::V8::AddMessageListener(StackTraceForUncaughtExceptionListener);
173523bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
173533bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
17354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRunWithOrigin(
17355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "function foo() {\n"
17356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  throw 1;\n"
17357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "};\n"
17358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "function bar() {\n"
17359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  foo();\n"
17360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "};",
17361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "origin");
173623bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  v8::Local<v8::Object> global = env->Global();
173633bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Local<Value> trouble = global->Get(v8_str("bar"));
173643bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  CHECK(trouble->IsFunction());
173653bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Function::Cast(*trouble)->Call(global, 0, NULL);
173663bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
173673bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  v8::V8::RemoveMessageListeners(StackTraceForUncaughtExceptionListener);
173683bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch}
173693bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
173703bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
173711e0659c275bb392c045087af4f6b0d7565cb3d77Steve BlockTEST(CaptureStackTraceForUncaughtExceptionAndSetters) {
173721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  LocalContext env;
17373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
173741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  v8::V8::SetCaptureStackTraceForUncaughtExceptions(true,
173751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                                    1024,
173761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                                    v8::StackTrace::kDetailed);
173771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
173781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  CompileRun(
173791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      "var setters = ['column', 'lineNumber', 'scriptName',\n"
173801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      "    'scriptNameOrSourceURL', 'functionName', 'isEval',\n"
173811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      "    'isConstructor'];\n"
173821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      "for (var i = 0; i < setters.length; i++) {\n"
173831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      "  var prop = setters[i];\n"
173841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      "  Object.prototype.__defineSetter__(prop, function() { throw prop; });\n"
173851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      "}\n");
173861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  CompileRun("throw 'exception';");
173871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
173881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
173891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
173901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
173913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void RethrowStackTraceHandler(v8::Handle<v8::Message> message,
173923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     v8::Handle<v8::Value> data) {
173933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Use the frame where JavaScript is called from.
173943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
173953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(!stack_trace.IsEmpty());
173963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int frame_count = stack_trace->GetFrameCount();
173973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(3, frame_count);
173983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int line_number[] = {1, 2, 5};
173993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < frame_count; i++) {
174003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
174013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
174023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
174033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
174043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
174053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Test that we only return the stack trace at the site where the exception
174063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// is first thrown (not where it is rethrown).
174073ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochTEST(RethrowStackTrace) {
174083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LocalContext env;
17409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
174103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // We make sure that
174113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // - the stack trace of the ReferenceError in g() is reported.
174123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // - the stack trace is not overwritten when e1 is rethrown by t().
174133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // - the stack trace of e2 does not overwrite that of e1.
174143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const char* source =
174153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "function g() { error; }          \n"
174163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "function f() { g(); }            \n"
174173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "function t(e) { throw e; }       \n"
174183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "try {                            \n"
174193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "  f();                           \n"
174203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "} catch (e1) {                   \n"
174213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "  try {                          \n"
174223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "    error;                       \n"
174233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "  } catch (e2) {                 \n"
174243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "    t(e1);                       \n"
174253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "  }                              \n"
174263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "}                                \n";
174273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::V8::AddMessageListener(RethrowStackTraceHandler);
174283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
174293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileRun(source);
174303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
174313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::V8::RemoveMessageListeners(RethrowStackTraceHandler);
174323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
174333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
174343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
174353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void RethrowPrimitiveStackTraceHandler(v8::Handle<v8::Message> message,
174363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                              v8::Handle<v8::Value> data) {
174373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
174383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(!stack_trace.IsEmpty());
174393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int frame_count = stack_trace->GetFrameCount();
174403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(2, frame_count);
174413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int line_number[] = {3, 7};
174423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < frame_count; i++) {
174433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
174443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
174453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
174463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
174473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
174483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Test that we do not recognize identity for primitive exceptions.
174493ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochTEST(RethrowPrimitiveStackTrace) {
174503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LocalContext env;
17451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
174523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // We do not capture stack trace for non Error objects on creation time.
174533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Instead, we capture the stack trace on last throw.
174543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const char* source =
174553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "function g() { throw 404; }      \n"
174563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "function f() { g(); }            \n"
174573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "function t(e) { throw e; }       \n"
174583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "try {                            \n"
174593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "  f();                           \n"
174603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "} catch (e1) {                   \n"
174613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "  t(e1)                          \n"
174623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "}                                \n";
174633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::V8::AddMessageListener(RethrowPrimitiveStackTraceHandler);
174643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
174653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileRun(source);
174663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
174673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::V8::RemoveMessageListeners(RethrowPrimitiveStackTraceHandler);
174683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
174693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
174703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
174713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void RethrowExistingStackTraceHandler(v8::Handle<v8::Message> message,
174723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                              v8::Handle<v8::Value> data) {
174733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Use the frame where JavaScript is called from.
174743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
174753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(!stack_trace.IsEmpty());
174763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(1, stack_trace->GetFrameCount());
174773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(1, stack_trace->GetFrame(0)->GetLineNumber());
174783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
174793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
174803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
174813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Test that the stack trace is captured when the error object is created and
174823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// not where it is thrown.
174833ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochTEST(RethrowExistingStackTrace) {
174843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LocalContext env;
17485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
174863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const char* source =
174873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "var e = new Error();           \n"
174883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "throw e;                       \n";
174893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::V8::AddMessageListener(RethrowExistingStackTraceHandler);
174903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
174913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileRun(source);
174923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
174933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::V8::RemoveMessageListeners(RethrowExistingStackTraceHandler);
174943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
174953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
174963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
174973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void RethrowBogusErrorStackTraceHandler(v8::Handle<v8::Message> message,
174983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                               v8::Handle<v8::Value> data) {
174993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Use the frame where JavaScript is called from.
175003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
175013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(!stack_trace.IsEmpty());
175023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(1, stack_trace->GetFrameCount());
175033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(2, stack_trace->GetFrame(0)->GetLineNumber());
175043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
175053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
175063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
175073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Test that the stack trace is captured where the bogus Error object is thrown.
175083ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochTEST(RethrowBogusErrorStackTrace) {
175093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LocalContext env;
17510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
175113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const char* source =
175123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "var e = {__proto__: new Error()} \n"
175133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "throw e;                         \n";
175143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::V8::AddMessageListener(RethrowBogusErrorStackTraceHandler);
175153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
175163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileRun(source);
175173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
175183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::V8::RemoveMessageListeners(RethrowBogusErrorStackTraceHandler);
175193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
175203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
175213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
17522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid AnalyzeStackOfEvalWithSourceURL(
17523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::FunctionCallbackInfo<v8::Value>& args) {
17524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(args.GetIsolate());
17525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
17526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      args.GetIsolate(), 10, v8::StackTrace::kDetailed);
17527f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CHECK_EQ(5, stackTrace->GetFrameCount());
17528f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  v8::Handle<v8::String> url = v8_str("eval_url");
17529f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  for (int i = 0; i < 3; i++) {
17530f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    v8::Handle<v8::String> name =
17531f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch        stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
17532f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    CHECK(!name.IsEmpty());
17533f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    CHECK_EQ(url, name);
17534f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  }
17535f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch}
17536f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
17537f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
17538f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochTEST(SourceURLInStackTrace) {
17539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
17540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
17541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
17542f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  templ->Set(v8_str("AnalyzeStackOfEvalWithSourceURL"),
17543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             v8::FunctionTemplate::New(isolate,
17544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       AnalyzeStackOfEvalWithSourceURL));
17545f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  LocalContext context(0, templ);
17546f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
17547f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  const char *source =
17548f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    "function outer() {\n"
17549f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    "function bar() {\n"
17550f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    "  AnalyzeStackOfEvalWithSourceURL();\n"
17551f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    "}\n"
17552f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    "function foo() {\n"
17553f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    "\n"
17554f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    "  bar();\n"
17555f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    "}\n"
17556f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    "foo();\n"
17557f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    "}\n"
17558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "eval('(' + outer +')()%s');";
17559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::ScopedVector<char> code(1024);
17561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::SNPrintF(code, source, "//# sourceURL=eval_url");
17562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(CompileRun(code.start())->IsUndefined());
17563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::SNPrintF(code, source, "//@ sourceURL=eval_url");
17564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(CompileRun(code.start())->IsUndefined());
17565f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch}
17566f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
17567f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
17568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic int scriptIdInStack[2];
17569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid AnalyzeScriptIdInStack(
17571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::FunctionCallbackInfo<v8::Value>& args) {
17572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(args.GetIsolate());
17573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
17574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      args.GetIsolate(), 10, v8::StackTrace::kScriptId);
17575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2, stackTrace->GetFrameCount());
17576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < 2; i++) {
17577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    scriptIdInStack[i] = stackTrace->GetFrame(i)->GetScriptId();
17578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
17579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
17580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(ScriptIdInStackTrace) {
17583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
17584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
17585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
17586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  templ->Set(v8_str("AnalyzeScriptIdInStack"),
17587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             v8::FunctionTemplate::New(isolate, AnalyzeScriptIdInStack));
17588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context(0, templ);
17589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::String> scriptSource = v8::String::NewFromUtf8(
17591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    isolate,
17592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "function foo() {\n"
17593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "  AnalyzeScriptIdInStack();"
17594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "}\n"
17595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "foo();\n");
17596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Script> script = CompileWithOrigin(scriptSource, "test");
17597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  script->Run();
17598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < 2; i++) {
17599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(scriptIdInStack[i] != v8::Message::kNoScriptIdInfo);
17600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(scriptIdInStack[i], script->GetUnboundScript()->GetId());
17601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
17602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
17603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid AnalyzeStackOfInlineScriptWithSourceURL(
17606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::FunctionCallbackInfo<v8::Value>& args) {
17607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(args.GetIsolate());
17608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
17609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      args.GetIsolate(), 10, v8::StackTrace::kDetailed);
17610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(4, stackTrace->GetFrameCount());
17611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::String> url = v8_str("url");
17612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < 3; i++) {
17613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Handle<v8::String> name =
17614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
17615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(!name.IsEmpty());
17616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(url, name);
17617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
17618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
17619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(InlineScriptWithSourceURLInStackTrace) {
17622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
17623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
17624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
17625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  templ->Set(v8_str("AnalyzeStackOfInlineScriptWithSourceURL"),
17626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             v8::FunctionTemplate::New(
17627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 CcTest::isolate(), AnalyzeStackOfInlineScriptWithSourceURL));
17628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context(0, templ);
17629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char *source =
17631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "function outer() {\n"
17632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "function bar() {\n"
17633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "  AnalyzeStackOfInlineScriptWithSourceURL();\n"
17634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "}\n"
17635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "function foo() {\n"
17636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "\n"
17637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "  bar();\n"
17638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "}\n"
17639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "foo();\n"
17640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "}\n"
17641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "outer()\n%s";
17642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::ScopedVector<char> code(1024);
17644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::SNPrintF(code, source, "//# sourceURL=source_url");
17645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
17646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::SNPrintF(code, source, "//@ sourceURL=source_url");
17647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
17648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
17649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid AnalyzeStackOfDynamicScriptWithSourceURL(
17652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::FunctionCallbackInfo<v8::Value>& args) {
17653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(args.GetIsolate());
17654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
17655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      args.GetIsolate(), 10, v8::StackTrace::kDetailed);
17656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(4, stackTrace->GetFrameCount());
17657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::String> url = v8_str("source_url");
17658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < 3; i++) {
17659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Handle<v8::String> name =
17660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
17661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(!name.IsEmpty());
17662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(url, name);
17663c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  }
17664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
17665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(DynamicWithSourceURLInStackTrace) {
17668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
17669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
17670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
17671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  templ->Set(v8_str("AnalyzeStackOfDynamicScriptWithSourceURL"),
17672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             v8::FunctionTemplate::New(
17673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 CcTest::isolate(), AnalyzeStackOfDynamicScriptWithSourceURL));
17674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context(0, templ);
17675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char *source =
17677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "function outer() {\n"
17678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "function bar() {\n"
17679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "  AnalyzeStackOfDynamicScriptWithSourceURL();\n"
17680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "}\n"
17681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "function foo() {\n"
17682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "\n"
17683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "  bar();\n"
17684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "}\n"
17685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "foo();\n"
17686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "}\n"
17687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "outer()\n%s";
17688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::ScopedVector<char> code(1024);
17690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::SNPrintF(code, source, "//# sourceURL=source_url");
17691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
17692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::SNPrintF(code, source, "//@ sourceURL=source_url");
17693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
17694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
17695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(DynamicWithSourceURLInStackTraceString) {
17698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
17699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(context->GetIsolate());
17700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char *source =
17702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "function outer() {\n"
17703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "  function foo() {\n"
17704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "    FAIL.FAIL;\n"
17705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "  }\n"
17706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "  foo();\n"
17707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "}\n"
17708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "outer()\n%s";
17709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::ScopedVector<char> code(1024);
17711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::SNPrintF(code, source, "//# sourceURL=source_url");
17712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::TryCatch try_catch;
17713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRunWithOrigin(code.start(), "", 0, 0);
17714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(try_catch.HasCaught());
17715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::String::Utf8Value stack(try_catch.StackTrace());
17716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(strstr(*stack, "at foo (source_url:3:5)") != NULL);
17717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
17718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(EvalWithSourceURLInMessageScriptResourceNameOrSourceURL) {
17721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
17722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(context->GetIsolate());
17723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char *source =
17725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "function outer() {\n"
17726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "  var scriptContents = \"function foo() { FAIL.FAIL; }\\\n"
17727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "  //# sourceURL=source_url\";\n"
17728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "  eval(scriptContents);\n"
17729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "  foo(); }\n"
17730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "outer();\n"
17731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "//# sourceURL=outer_url";
17732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::TryCatch try_catch;
17734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun(source);
17735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(try_catch.HasCaught());
17736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::Message> message = try_catch.Message();
17738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Value> sourceURL =
17739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    message->GetScriptOrigin().ResourceName();
17740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(*v8::String::Utf8Value(sourceURL), "source_url");
17741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
17742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(RecursionWithSourceURLInMessageScriptResourceNameOrSourceURL) {
17745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
17746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(context->GetIsolate());
17747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char *source =
17749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "function outer() {\n"
17750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "  var scriptContents = \"function boo(){ boo(); }\\\n"
17751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "  //# sourceURL=source_url\";\n"
17752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "  eval(scriptContents);\n"
17753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "  boo(); }\n"
17754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "outer();\n"
17755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "//# sourceURL=outer_url";
17756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::TryCatch try_catch;
17758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun(source);
17759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(try_catch.HasCaught());
17760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::Message> message = try_catch.Message();
17762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Value> sourceURL =
17763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    message->GetScriptOrigin().ResourceName();
17764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(*v8::String::Utf8Value(sourceURL), "source_url");
17765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
17766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void CreateGarbageInOldSpace() {
17769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::Factory* factory = CcTest::i_isolate()->factory();
17770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(CcTest::isolate());
17771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::AlwaysAllocateScope always_allocate(CcTest::i_isolate());
17772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < 1000; i++) {
17773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    factory->NewFixedArray(1000, i::TENURED);
177743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
177753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
177763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
17777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
177783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Test that idle notification can be handled and eventually returns true.
17779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(IdleNotification) {
17780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const intptr_t MB = 1024 * 1024;
17781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int IdlePauseInMs = 1000;
177823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LocalContext env;
17783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
17784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  intptr_t initial_size = CcTest::heap()->SizeOfObjects();
17785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CreateGarbageInOldSpace();
17786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
17787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_GT(size_with_garbage, initial_size + MB);
17788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool finished = false;
17789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < 200 && !finished; i++) {
17790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    finished = env->GetIsolate()->IdleNotification(IdlePauseInMs);
177913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
17792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  intptr_t final_size = CcTest::heap()->SizeOfObjects();
17793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(finished);
17794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_LT(final_size, initial_size + 1);
17795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
17796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Test that idle notification can be handled and eventually collects garbage.
17799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(IdleNotificationWithSmallHint) {
17800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const intptr_t MB = 1024 * 1024;
17801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int IdlePauseInMs = 900;
17802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
17803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
17804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  intptr_t initial_size = CcTest::heap()->SizeOfObjects();
17805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CreateGarbageInOldSpace();
17806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
17807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_GT(size_with_garbage, initial_size + MB);
17808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool finished = false;
17809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < 200 && !finished; i++) {
17810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    finished = env->GetIsolate()->IdleNotification(IdlePauseInMs);
178113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
17812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  intptr_t final_size = CcTest::heap()->SizeOfObjects();
17813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(finished);
17814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_LT(final_size, initial_size + 1);
178153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
178163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
178173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
17818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Test that idle notification can be handled and eventually collects garbage.
178193ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochTEST(IdleNotificationWithLargeHint) {
17820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const intptr_t MB = 1024 * 1024;
17821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int IdlePauseInMs = 900;
178223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LocalContext env;
17823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
17824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  intptr_t initial_size = CcTest::heap()->SizeOfObjects();
17825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CreateGarbageInOldSpace();
17826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
17827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_GT(size_with_garbage, initial_size + MB);
17828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool finished = false;
17829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < 200 && !finished; i++) {
17830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    finished = env->GetIsolate()->IdleNotification(IdlePauseInMs);
17831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
17832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  intptr_t final_size = CcTest::heap()->SizeOfObjects();
17833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(finished);
17834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_LT(final_size, initial_size + 1);
17835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
17836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(Regress2107) {
17839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const intptr_t MB = 1024 * 1024;
17840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int kIdlePauseInMs = 1000;
17841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
17842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
17843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
17844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  intptr_t initial_size = CcTest::heap()->SizeOfObjects();
17845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Send idle notification to start a round of incremental GCs.
17846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->GetIsolate()->IdleNotification(kIdlePauseInMs);
17847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Emulate 7 page reloads.
17848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < 7; i++) {
17849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    {
17850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::HandleScope inner_scope(env->GetIsolate());
17851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Local<v8::Context> ctx = v8::Context::New(isolate);
17852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ctx->Enter();
17853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CreateGarbageInOldSpace();
17854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ctx->Exit();
178553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
17856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    env->GetIsolate()->ContextDisposedNotification();
17857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    env->GetIsolate()->IdleNotification(kIdlePauseInMs);
178583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
17859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Create garbage and check that idle notification still collects it.
17860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CreateGarbageInOldSpace();
17861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
17862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_GT(size_with_garbage, initial_size + MB);
17863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool finished = false;
17864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < 200 && !finished; i++) {
17865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    finished = env->GetIsolate()->IdleNotification(kIdlePauseInMs);
178663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
17867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  intptr_t final_size = CcTest::heap()->SizeOfObjects();
17868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_LT(final_size, initial_size + 1);
17869c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch}
17870c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
17871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
17872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(Regress2333) {
17873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
17874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < 3; i++) {
17875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CcTest::heap()->CollectGarbage(i::NEW_SPACE);
17876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
17877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
17878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic uint32_t* stack_limit;
17880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
17881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void GetStackLimitCallback(
17882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::FunctionCallbackInfo<v8::Value>& args) {
1788344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  stack_limit = reinterpret_cast<uint32_t*>(
17884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CcTest::i_isolate()->stack_guard()->real_climit());
17885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
17886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
17887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
17888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Uses the address of a local variable to determine the stack top now.
17889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Given a size, returns an address that is that far from the current
17890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// top of stack.
17891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic uint32_t* ComputeStackLimit(uint32_t size) {
17892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  uint32_t* answer = &size - (size / sizeof(size));
17893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the size is very large and the stack is very near the bottom of
17894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // memory then the calculation above may wrap around and give an address
17895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // that is above the (downwards-growing) stack.  In that case we return
17896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // a very low address.
17897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (answer > &size) return reinterpret_cast<uint32_t*>(sizeof(size));
17898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return answer;
17899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
17900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
17901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
17902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// We need at least 165kB for an x64 debug build with clang and ASAN.
17903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic const int stack_breathing_room = 256 * i::KB;
17904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(SetStackLimit) {
17907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  uint32_t* set_limit = ComputeStackLimit(stack_breathing_room);
17908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
17909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set stack limit.
17910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::isolate()->SetStackLimit(reinterpret_cast<uintptr_t>(set_limit));
17911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
17912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Execute a script.
17913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LocalContext env;
17914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
17915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<v8::FunctionTemplate> fun_templ =
17916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::FunctionTemplate::New(env->GetIsolate(), GetStackLimitCallback);
17917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Function> fun = fun_templ->GetFunction();
17918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env->Global()->Set(v8_str("get_stack_limit"), fun);
17919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CompileRun("get_stack_limit();");
17920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
17921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(stack_limit == set_limit);
17922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
17923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
17924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
17925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(SetStackLimitInThread) {
17926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  uint32_t* set_limit;
17927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {
17928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Locker locker(CcTest::isolate());
17929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    set_limit = ComputeStackLimit(stack_breathing_room);
17930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
17931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Set stack limit.
17932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CcTest::isolate()->SetStackLimit(reinterpret_cast<uintptr_t>(set_limit));
17933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
17934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Execute a script.
17935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(CcTest::isolate());
17936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    LocalContext env;
17937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Local<v8::FunctionTemplate> fun_templ =
17938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v8::FunctionTemplate::New(CcTest::isolate(), GetStackLimitCallback);
17939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Local<Function> fun = fun_templ->GetFunction();
17940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    env->Global()->Set(v8_str("get_stack_limit"), fun);
17941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CompileRun("get_stack_limit();");
17942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
17943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK(stack_limit == set_limit);
17944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
17945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {
17946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Locker locker(CcTest::isolate());
17947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK(stack_limit == set_limit);
17948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
17949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
179503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
179513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
179523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockTHREADED_TEST(GetHeapStatistics) {
179533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  LocalContext c1;
17954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(c1->GetIsolate());
179553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  v8::HeapStatistics heap_statistics;
17956d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CHECK_EQ(static_cast<int>(heap_statistics.total_heap_size()), 0);
17957d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CHECK_EQ(static_cast<int>(heap_statistics.used_heap_size()), 0);
17958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  c1->GetIsolate()->GetHeapStatistics(&heap_statistics);
17959d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CHECK_NE(static_cast<int>(heap_statistics.total_heap_size()), 0);
17960d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CHECK_NE(static_cast<int>(heap_statistics.used_heap_size()), 0);
17961d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
17962d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
17963d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
179643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochclass VisitorImpl : public v8::ExternalResourceVisitor {
179653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch public:
17966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  explicit VisitorImpl(TestResource** resource) {
17967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int i = 0; i < 4; i++) {
17968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      resource_[i] = resource[i];
17969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      found_resource_[i] = false;
17970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
17971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
179723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  virtual ~VisitorImpl() {}
179733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  virtual void VisitExternalString(v8::Handle<v8::String> string) {
179743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!string->IsExternal()) {
17975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CHECK(string->IsExternalOneByte());
179763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return;
179773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
179783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    v8::String::ExternalStringResource* resource =
179793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        string->GetExternalStringResource();
179803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CHECK(resource);
17981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int i = 0; i < 4; i++) {
17982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (resource_[i] == resource) {
17983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        CHECK(!found_resource_[i]);
17984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        found_resource_[i] = true;
17985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
179863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
179873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
179883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void CheckVisitedResources() {
17989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int i = 0; i < 4; i++) {
17990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CHECK(found_resource_[i]);
17991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
179923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
179933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
179943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch private:
17995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::String::ExternalStringResource* resource_[4];
17996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool found_resource_[4];
179973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch};
179983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
17999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(ExternalizeOldSpaceTwoByteCons) {
18001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
18002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
18003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::String> cons =
18004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CompileRun("'Romeo Montague ' + 'Juliet Capulet'")->ToString();
18005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(v8::Utils::OpenHandle(*cons)->IsConsString());
18006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllAvailableGarbage();
18007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(CcTest::heap()->old_pointer_space()->Contains(
18008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            *v8::Utils::OpenHandle(*cons)));
18009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TestResource* resource = new TestResource(
18011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AsciiToTwoByteString("Romeo Montague Juliet Capulet"));
18012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cons->MakeExternal(resource);
18013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(cons->IsExternal());
18015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(resource, cons->GetExternalStringResource());
18016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  String::Encoding encoding;
18017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(resource, cons->GetExternalStringResourceBase(&encoding));
18018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(String::TWO_BYTE_ENCODING, encoding);
18019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
18020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(ExternalizeOldSpaceOneByteCons) {
18023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
18024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
18025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::String> cons =
18026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CompileRun("'Romeo Montague ' + 'Juliet Capulet'")->ToString();
18027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(v8::Utils::OpenHandle(*cons)->IsConsString());
18028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllAvailableGarbage();
18029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(CcTest::heap()->old_pointer_space()->Contains(
18030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            *v8::Utils::OpenHandle(*cons)));
18031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TestOneByteResource* resource =
18033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      new TestOneByteResource(i::StrDup("Romeo Montague Juliet Capulet"));
18034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cons->MakeExternal(resource);
18035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(cons->IsExternalOneByte());
18037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(resource, cons->GetExternalOneByteStringResource());
18038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  String::Encoding encoding;
18039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(resource, cons->GetExternalStringResourceBase(&encoding));
18040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(String::ONE_BYTE_ENCODING, encoding);
18041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
18042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
180443ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochTEST(VisitExternalStrings) {
180453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LocalContext env;
18046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
180473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const char* string = "Some string";
180483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  uint16_t* two_byte_string = AsciiToTwoByteString(string);
18049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TestResource* resource[4];
18050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  resource[0] = new TestResource(two_byte_string);
18051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::String> string0 =
18052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewExternal(env->GetIsolate(), resource[0]);
18053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  resource[1] = new TestResource(two_byte_string, NULL, false);
18054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::String> string1 =
18055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewExternal(env->GetIsolate(), resource[1]);
18056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Externalized symbol.
18058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  resource[2] = new TestResource(two_byte_string, NULL, false);
18059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::String> string2 = v8::String::NewFromUtf8(
18060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->GetIsolate(), string, v8::String::kInternalizedString);
18061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(string2->MakeExternal(resource[2]));
18062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Symbolized External.
18064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  resource[3] = new TestResource(AsciiToTwoByteString("Some other string"));
18065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::String> string3 =
18066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewExternal(env->GetIsolate(), resource[3]);
18067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllAvailableGarbage();  // Tenure string.
18068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Turn into a symbol.
18069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::Handle<i::String> string3_i = v8::Utils::OpenHandle(*string3);
18070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!CcTest::i_isolate()->factory()->InternalizeString(
18071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      string3_i).is_null());
18072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(string3_i->IsInternalizedString());
18073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // We need to add usages for string* to avoid warnings in GCC 4.7
18075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(string0->IsExternal());
180763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(string1->IsExternal());
180773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(string2->IsExternal());
18078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(string3->IsExternal());
180793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
18080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitorImpl visitor(resource);
180813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::V8::VisitExternalResources(&visitor);
180823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  visitor.CheckVisitedResources();
180833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
180843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
180853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
18086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(ExternalStringCollectedAtTearDown) {
18087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int destroyed = 0;
18088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = v8::Isolate::New();
18089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  { v8::Isolate::Scope isolate_scope(isolate);
18090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope handle_scope(isolate);
18091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const char* s = "One string to test them all, one string to find them.";
18092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    TestOneByteResource* inscription =
18093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        new TestOneByteResource(i::StrDup(s), &destroyed);
18094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Local<v8::String> ring = v8::String::NewExternal(isolate, inscription);
18095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Ring is still alive.  Orcs are roaming freely across our lands.
18096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(0, destroyed);
18097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    USE(ring);
18098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
18099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate->Dispose();
18101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Ring has been destroyed.  Free Peoples of Middle-earth Rejoice.
18102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1, destroyed);
18103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
18104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(ExternalInternalizedStringCollectedAtTearDown) {
18107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int destroyed = 0;
18108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = v8::Isolate::New();
18109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  { v8::Isolate::Scope isolate_scope(isolate);
18110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LocalContext env(isolate);
18111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope handle_scope(isolate);
18112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CompileRun("var ring = 'One string to test them all';");
18113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const char* s = "One string to test them all";
18114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    TestOneByteResource* inscription =
18115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        new TestOneByteResource(i::StrDup(s), &destroyed);
18116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Local<v8::String> ring = CompileRun("ring")->ToString();
18117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(v8::Utils::OpenHandle(*ring)->IsInternalizedString());
18118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ring->MakeExternal(inscription);
18119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Ring is still alive.  Orcs are roaming freely across our lands.
18120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(0, destroyed);
18121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    USE(ring);
18122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
18123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate->Dispose();
18125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Ring has been destroyed.  Free Peoples of Middle-earth Rejoice.
18126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1, destroyed);
18127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
18128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(ExternalInternalizedStringCollectedAtGC) {
18131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int destroyed = 0;
18132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  { LocalContext env;
18133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope handle_scope(env->GetIsolate());
18134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CompileRun("var ring = 'One string to test them all';");
18135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const char* s = "One string to test them all";
18136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    TestOneByteResource* inscription =
18137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        new TestOneByteResource(i::StrDup(s), &destroyed);
18138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Local<v8::String> ring = CompileRun("ring")->ToString();
18139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(v8::Utils::OpenHandle(*ring)->IsInternalizedString());
18140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ring->MakeExternal(inscription);
18141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Ring is still alive.  Orcs are roaming freely across our lands.
18142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(0, destroyed);
18143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    USE(ring);
18144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
18145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Garbage collector deals swift blows to evil.
18147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::i_isolate()->compilation_cache()->Clear();
18148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllAvailableGarbage();
18149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Ring has been destroyed.  Free Peoples of Middle-earth Rejoice.
18151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1, destroyed);
18152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
18153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18155d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockstatic double DoubleFromBits(uint64_t value) {
18156d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  double target;
18157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::MemCopy(&target, &value, sizeof(target));
18158d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  return target;
18159d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
18160d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
18161d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
18162d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockstatic uint64_t DoubleToBits(double value) {
18163d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  uint64_t target;
18164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::MemCopy(&target, &value, sizeof(target));
18165d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  return target;
18166d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
18167d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
18168d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
18169d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockstatic double DoubleToDateTime(double input) {
18170d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  double date_limit = 864e13;
18171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (std::isnan(input) || input < -date_limit || input > date_limit) {
18172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return v8::base::OS::nan_value();
18173d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
18174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return (input < 0) ? -(std::floor(-input)) : std::floor(input);
18175d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
18176d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
18177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18178d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// We don't have a consistent way to write 64-bit constants syntactically, so we
18179d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// split them into two 32-bit constants and combine them programmatically.
18180d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockstatic double DoubleFromBits(uint32_t high_bits, uint32_t low_bits) {
18181d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  return DoubleFromBits((static_cast<uint64_t>(high_bits) << 32) | low_bits);
18182d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
18183d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
18184d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
18185d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockTHREADED_TEST(QuietSignalingNaNs) {
18186d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  LocalContext context;
18187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
18188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
18189d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  v8::TryCatch try_catch;
18190d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
18191d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Special double values.
18192d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  double snan = DoubleFromBits(0x7ff00000, 0x00000001);
18193d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  double qnan = DoubleFromBits(0x7ff80000, 0x00000000);
18194d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  double infinity = DoubleFromBits(0x7ff00000, 0x00000000);
18195d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  double max_normal = DoubleFromBits(0x7fefffff, 0xffffffffu);
18196d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  double min_normal = DoubleFromBits(0x00100000, 0x00000000);
18197d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  double max_denormal = DoubleFromBits(0x000fffff, 0xffffffffu);
18198d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  double min_denormal = DoubleFromBits(0x00000000, 0x00000001);
18199d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
18200d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Date values are capped at +/-100000000 days (times 864e5 ms per day)
18201d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // on either side of the epoch.
18202d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  double date_limit = 864e13;
18203d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
18204d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  double test_values[] = {
18205d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      snan,
18206d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      qnan,
18207d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      infinity,
18208d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      max_normal,
18209d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      date_limit + 1,
18210d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      date_limit,
18211d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      min_normal,
18212d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      max_denormal,
18213d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      min_denormal,
18214d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      0,
18215d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      -0,
18216d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      -min_denormal,
18217d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      -max_denormal,
18218d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      -min_normal,
18219d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      -date_limit,
18220d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      -date_limit - 1,
18221d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      -max_normal,
18222d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      -infinity,
18223d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      -qnan,
18224d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      -snan
18225d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  };
18226d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int num_test_values = 20;
18227d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
18228d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  for (int i = 0; i < num_test_values; i++) {
18229d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    double test_value = test_values[i];
18230d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
18231d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Check that Number::New preserves non-NaNs and quiets SNaNs.
18232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Handle<v8::Value> number = v8::Number::New(isolate, test_value);
18233d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    double stored_number = number->NumberValue();
18234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!std::isnan(test_value)) {
18235d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      CHECK_EQ(test_value, stored_number);
18236d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    } else {
18237d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      uint64_t stored_bits = DoubleToBits(stored_number);
18238d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // Check if quiet nan (bits 51..62 all set).
18239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if (defined(V8_TARGET_ARCH_MIPS) || defined(V8_TARGET_ARCH_MIPS64)) && \
18240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    !defined(_MIPS_ARCH_MIPS64R6) && !defined(USE_SIMULATOR)
182413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Most significant fraction bit for quiet nan is set to 0
182423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // on MIPS architecture. Allowed by IEEE-754.
182433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
182443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#else
18245d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
182463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif
18247d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
18248d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
18249d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Check that Date::New preserves non-NaNs in the date range and
18250d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // quiets SNaNs.
18251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Handle<v8::Value> date =
18252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v8::Date::New(isolate, test_value);
18253d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    double expected_stored_date = DoubleToDateTime(test_value);
18254d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    double stored_date = date->NumberValue();
18255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!std::isnan(expected_stored_date)) {
18256d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      CHECK_EQ(expected_stored_date, stored_date);
18257d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    } else {
18258d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      uint64_t stored_bits = DoubleToBits(stored_date);
18259d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // Check if quiet nan (bits 51..62 all set).
18260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if (defined(V8_TARGET_ARCH_MIPS) || defined(V8_TARGET_ARCH_MIPS64)) && \
18261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    !defined(_MIPS_ARCH_MIPS64R6) && !defined(USE_SIMULATOR)
182623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Most significant fraction bit for quiet nan is set to 0
182633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // on MIPS architecture. Allowed by IEEE-754.
182643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
182653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#else
18266d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
182673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif
18268d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
18269d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
18270d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
18271d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
18272d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
18273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void SpaghettiIncident(
18274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::FunctionCallbackInfo<v8::Value>& args) {
18275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(args.GetIsolate());
18276d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  v8::TryCatch tc;
182773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::Handle<v8::String> str(args[0]->ToString());
182783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  USE(str);
18279d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (tc.HasCaught())
18280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    tc.ReThrow();
18281d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
18282d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
18283d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
18284d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// Test that an exception can be propagated down through a spaghetti
18285d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// stack using ReThrow.
18286d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockTHREADED_TEST(SpaghettiStackReThrow) {
18287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
18288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
18289d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  LocalContext context;
18290d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  context->Global()->Set(
18291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(isolate, "s"),
18292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::FunctionTemplate::New(isolate, SpaghettiIncident)->GetFunction());
18293d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  v8::TryCatch try_catch;
18294d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CompileRun(
18295d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      "var i = 0;"
18296d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      "var o = {"
18297d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      "  toString: function () {"
18298d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      "    if (i == 10) {"
18299d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      "      throw 'Hey!';"
18300d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      "    } else {"
18301d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      "      i++;"
18302d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      "      return s(o);"
18303d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      "    }"
18304d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      "  }"
18305d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      "};"
18306d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      "s(o);");
18307d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CHECK(try_catch.HasCaught());
18308d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  v8::String::Utf8Value value(try_catch.Exception());
18309d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CHECK_EQ(0, strcmp(*value, "Hey!"));
18310d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
18311d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
18312d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
18313d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockTEST(Regress528) {
18314d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  v8::V8::Initialize();
18315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
18316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
18317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<Context> other_context;
18318d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int gc_count;
18319d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
18320d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Create a context used to keep the code from aging in the compilation
18321d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // cache.
18322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  other_context = Context::New(isolate);
18323d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
18324d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Context-dependent context data creates reference from the compilation
18325d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // cache to the global object.
18326d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  const char* source_simple = "1";
18327d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  {
18328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(isolate);
18329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Local<Context> context = Context::New(isolate);
18330d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
18331d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    context->Enter();
18332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<v8::String> obj = v8::String::NewFromUtf8(isolate, "");
18333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    context->SetEmbedderData(0, obj);
18334d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    CompileRun(source_simple);
18335d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    context->Exit();
18336d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
18337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate->ContextDisposedNotification();
18338d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  for (gc_count = 1; gc_count < 10; gc_count++) {
18339d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    other_context->Enter();
18340d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    CompileRun(source_simple);
18341d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    other_context->Exit();
18342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
18343d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (GetGlobalObjectsCount() == 1) break;
18344d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
18345d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CHECK_GE(2, gc_count);
18346d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CHECK_EQ(1, GetGlobalObjectsCount());
18347d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
18348d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Eval in a function creates reference from the compilation cache to the
18349d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // global object.
18350d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  const char* source_eval = "function f(){eval('1')}; f()";
18351d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  {
18352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(isolate);
18353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Local<Context> context = Context::New(isolate);
18354d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
18355d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    context->Enter();
18356d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    CompileRun(source_eval);
18357d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    context->Exit();
18358d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
18359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate->ContextDisposedNotification();
18360d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  for (gc_count = 1; gc_count < 10; gc_count++) {
18361d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    other_context->Enter();
18362d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    CompileRun(source_eval);
18363d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    other_context->Exit();
18364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
18365d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (GetGlobalObjectsCount() == 1) break;
18366d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
18367d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CHECK_GE(2, gc_count);
18368d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CHECK_EQ(1, GetGlobalObjectsCount());
18369d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
18370d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Looking up the line number for an exception creates reference from the
18371d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // compilation cache to the global object.
18372d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  const char* source_exception = "function f(){throw 1;} f()";
18373d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  {
18374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(isolate);
18375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Local<Context> context = Context::New(isolate);
18376d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
18377d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    context->Enter();
18378d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    v8::TryCatch try_catch;
18379d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    CompileRun(source_exception);
18380d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    CHECK(try_catch.HasCaught());
18381d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    v8::Handle<v8::Message> message = try_catch.Message();
18382d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    CHECK(!message.IsEmpty());
18383d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    CHECK_EQ(1, message->GetLineNumber());
18384d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    context->Exit();
18385d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
18386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate->ContextDisposedNotification();
18387d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  for (gc_count = 1; gc_count < 10; gc_count++) {
18388d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    other_context->Enter();
18389d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    CompileRun(source_exception);
18390d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    other_context->Exit();
18391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
18392d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (GetGlobalObjectsCount() == 1) break;
18393d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
18394d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CHECK_GE(2, gc_count);
18395d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CHECK_EQ(1, GetGlobalObjectsCount());
18396d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
18397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate->ContextDisposedNotification();
183983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
18399402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
18400402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
18401402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei PopescuTHREADED_TEST(ScriptOrigin) {
18402402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  LocalContext env;
18403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
18404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::ScriptOrigin origin =
18405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
18406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::String> script = v8::String::NewFromUtf8(
18407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->GetIsolate(), "function f() {}\n\nfunction g() {}");
18408402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  v8::Script::Compile(script, &origin)->Run();
18409402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
18410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
18411402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
18412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
18413402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
18414402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  v8::ScriptOrigin script_origin_f = f->GetScriptOrigin();
18415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ("test", *v8::String::Utf8Value(script_origin_f.ResourceName()));
18416402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK_EQ(0, script_origin_f.ResourceLineOffset()->Int32Value());
18417402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
18418402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  v8::ScriptOrigin script_origin_g = g->GetScriptOrigin();
18419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ("test", *v8::String::Utf8Value(script_origin_g.ResourceName()));
18420402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK_EQ(0, script_origin_g.ResourceLineOffset()->Int32Value());
18421402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
18422402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
18423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
184243ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochTHREADED_TEST(FunctionGetInferredName) {
184253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LocalContext env;
18426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
18427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::ScriptOrigin origin =
18428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
18429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::String> script = v8::String::NewFromUtf8(
18430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->GetIsolate(),
184313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "var foo = { bar : { baz : function() {}}}; var f = foo.bar.baz;");
184323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::Script::Compile(script, &origin)->Run();
184333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
18434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
18435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ("foo.bar.baz", *v8::String::Utf8Value(f->GetInferredName()));
18436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
18437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(FunctionGetDisplayName) {
18440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
18441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
18442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* code = "var error = false;"
18443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     "function a() { this.x = 1; };"
18444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     "a.displayName = 'display_a';"
18445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     "var b = (function() {"
18446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     "  var f = function() { this.x = 2; };"
18447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     "  f.displayName = 'display_b';"
18448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     "  return f;"
18449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     "})();"
18450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     "var c = function() {};"
18451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     "c.__defineGetter__('displayName', function() {"
18452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     "  error = true;"
18453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     "  throw new Error();"
18454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     "});"
18455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     "function d() {};"
18456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     "d.__defineGetter__('displayName', function() {"
18457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     "  error = true;"
18458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     "  return 'wrong_display_name';"
18459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     "});"
18460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     "function e() {};"
18461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     "e.displayName = 'wrong_display_name';"
18462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     "e.__defineSetter__('displayName', function() {"
18463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     "  error = true;"
18464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     "  throw new Error();"
18465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     "});"
18466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     "function f() {};"
18467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     "f.displayName = { 'foo': 6, toString: function() {"
18468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     "  error = true;"
18469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     "  return 'wrong_display_name';"
18470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     "}};"
18471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     "var g = function() {"
18472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     "  arguments.callee.displayName = 'set_in_runtime';"
18473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     "}; g();"
18474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     ;
18475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::ScriptOrigin origin =
18476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
18477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), code), &origin)
18478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ->Run();
18479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Value> error =
18480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "error"));
18481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Function> a = v8::Local<v8::Function>::Cast(
18482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "a")));
18483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Function> b = v8::Local<v8::Function>::Cast(
18484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "b")));
18485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Function> c = v8::Local<v8::Function>::Cast(
18486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "c")));
18487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Function> d = v8::Local<v8::Function>::Cast(
18488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "d")));
18489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Function> e = v8::Local<v8::Function>::Cast(
18490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "e")));
18491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
18492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
18493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
18494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
18495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(false, error->BooleanValue());
18496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ("display_a", *v8::String::Utf8Value(a->GetDisplayName()));
18497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ("display_b", *v8::String::Utf8Value(b->GetDisplayName()));
18498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(c->GetDisplayName()->IsUndefined());
18499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(d->GetDisplayName()->IsUndefined());
18500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(e->GetDisplayName()->IsUndefined());
18501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(f->GetDisplayName()->IsUndefined());
18502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ("set_in_runtime", *v8::String::Utf8Value(g->GetDisplayName()));
185033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
18504402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
18505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18506402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei PopescuTHREADED_TEST(ScriptLineNumber) {
18507402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  LocalContext env;
18508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
18509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::ScriptOrigin origin =
18510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
18511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::String> script = v8::String::NewFromUtf8(
18512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->GetIsolate(), "function f() {}\n\nfunction g() {}");
18513402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  v8::Script::Compile(script, &origin)->Run();
18514402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
18515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
18516402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
18517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
18518402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK_EQ(0, f->GetScriptLineNumber());
18519402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK_EQ(2, g->GetScriptLineNumber());
18520402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
18521402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
18522402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
185233ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochTHREADED_TEST(ScriptColumnNumber) {
185243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LocalContext env;
18525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
18526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
18527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::ScriptOrigin origin =
18528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::ScriptOrigin(v8::String::NewFromUtf8(isolate, "test"),
18529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       v8::Integer::New(isolate, 3),
18530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       v8::Integer::New(isolate, 2));
18531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::String> script = v8::String::NewFromUtf8(
18532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate, "function foo() {}\n\n     function bar() {}");
185333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::Script::Compile(script, &origin)->Run();
185343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
18535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->Global()->Get(v8::String::NewFromUtf8(isolate, "foo")));
185363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
18537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->Global()->Get(v8::String::NewFromUtf8(isolate, "bar")));
185383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(14, foo->GetScriptColumnNumber());
185393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(17, bar->GetScriptColumnNumber());
185403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
185413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
185423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
18543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(FunctionIsBuiltin) {
18544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
18545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
18546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
18547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Function> f;
18548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  f = v8::Local<v8::Function>::Cast(CompileRun("Math.floor"));
18549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(f->IsBuiltin());
18550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  f = v8::Local<v8::Function>::Cast(CompileRun("Object"));
18551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(f->IsBuiltin());
18552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  f = v8::Local<v8::Function>::Cast(CompileRun("Object.__defineSetter__"));
18553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(f->IsBuiltin());
18554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  f = v8::Local<v8::Function>::Cast(CompileRun("Array.prototype.toString"));
18555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(f->IsBuiltin());
18556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  f = v8::Local<v8::Function>::Cast(CompileRun("function a() {}; a;"));
18557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!f->IsBuiltin());
18558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
18559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
185613ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochTHREADED_TEST(FunctionGetScriptId) {
185623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LocalContext env;
18563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
18564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
18565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::ScriptOrigin origin =
18566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::ScriptOrigin(v8::String::NewFromUtf8(isolate, "test"),
18567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       v8::Integer::New(isolate, 3),
18568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       v8::Integer::New(isolate, 2));
18569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::String> scriptSource = v8::String::NewFromUtf8(
18570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate, "function foo() {}\n\n     function bar() {}");
185713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::Local<v8::Script> script(v8::Script::Compile(scriptSource, &origin));
185723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  script->Run();
185733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
18574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->Global()->Get(v8::String::NewFromUtf8(isolate, "foo")));
185753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
18576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->Global()->Get(v8::String::NewFromUtf8(isolate, "bar")));
18577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(script->GetUnboundScript()->GetId(), foo->ScriptId());
18578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(script->GetUnboundScript()->GetId(), bar->ScriptId());
18579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
18580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(FunctionGetBoundFunction) {
18583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
18584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
18585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::NewFromUtf8(
18586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->GetIsolate(), "test"));
18587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::String> script = v8::String::NewFromUtf8(
18588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->GetIsolate(),
18589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "var a = new Object();\n"
18590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "a.x = 1;\n"
18591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "function f () { return this.x };\n"
18592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "var g = f.bind(a);\n"
18593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "var b = g();");
18594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(script, &origin)->Run();
18595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
18596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
18597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
18598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
18599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(g->GetBoundFunction()->IsFunction());
18600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::Function> original_function = Local<v8::Function>::Cast(
18601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      g->GetBoundFunction());
18602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(f->GetName(), original_function->GetName());
18603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(f->GetScriptLineNumber(), original_function->GetScriptLineNumber());
18604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(f->GetScriptColumnNumber(),
18605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           original_function->GetScriptColumnNumber());
18606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
18607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void GetterWhichReturns42(
18610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<String> name,
18611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Value>& info) {
18612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
18613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
18614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(v8_num(42));
186153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
186163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
186173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
18618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void SetterWhichSetsYOnThisTo23(
18619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<String> name,
18620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<Value> value,
18621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<void>& info) {
18622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
18623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
18624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Object>::Cast(info.This())->Set(v8_str("y"), v8_num(23));
18625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
18626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FooGetInterceptor(Local<String> name,
18629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       const v8::PropertyCallbackInfo<v8::Value>& info) {
18630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
18631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
18632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!name->Equals(v8_str("foo"))) return;
18633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(v8_num(42));
18634402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
18635402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
18636402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
18637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FooSetInterceptor(Local<String> name,
18638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       Local<Value> value,
18639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       const v8::PropertyCallbackInfo<v8::Value>& info) {
18640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
18641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
18642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!name->Equals(v8_str("foo"))) return;
18643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Object>::Cast(info.This())->Set(v8_str("y"), v8_num(23));
18644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(v8_num(23));
18645402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
18646402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
18647402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
186486ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockTEST(SetterOnConstructorPrototype) {
18649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
18650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
18651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
18652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  templ->SetAccessor(v8_str("x"), GetterWhichReturns42,
18653402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                     SetterWhichSetsYOnThisTo23);
18654402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  LocalContext context;
18655402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  context->Global()->Set(v8_str("P"), templ->NewInstance());
18656402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CompileRun("function C1() {"
18657402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu             "  this.x = 23;"
18658402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu             "};"
18659402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu             "C1.prototype = P;"
18660402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu             "function C2() {"
18661402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu             "  this.x = 23"
18662402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu             "};"
18663402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu             "C2.prototype = { };"
18664402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu             "C2.prototype.__proto__ = P;");
18665402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
18666402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  v8::Local<v8::Script> script;
18667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  script = v8_compile("new C1();");
18668402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  for (int i = 0; i < 10; i++) {
18669402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
18670402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    CHECK_EQ(42, c1->Get(v8_str("x"))->Int32Value());
18671402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    CHECK_EQ(23, c1->Get(v8_str("y"))->Int32Value());
18672402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
18673402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
18674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochscript = v8_compile("new C2();");
18675402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  for (int i = 0; i < 10; i++) {
18676402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    v8::Handle<v8::Object> c2 = v8::Handle<v8::Object>::Cast(script->Run());
18677402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    CHECK_EQ(42, c2->Get(v8_str("x"))->Int32Value());
18678402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    CHECK_EQ(23, c2->Get(v8_str("y"))->Int32Value());
18679402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
18680402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
18681402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
18682402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
18683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void NamedPropertyGetterWhichReturns42(
18684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<String> name,
18685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Value>& info) {
18686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(v8_num(42));
18687402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
18688402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
18689402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
18690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void NamedPropertySetterWhichSetsYOnThisTo23(
18691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<String> name,
18692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<Value> value,
18693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Value>& info) {
18694402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  if (name->Equals(v8_str("x"))) {
18695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<Object>::Cast(info.This())->Set(v8_str("y"), v8_num(23));
18696402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
18697402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
18698402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
18699402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
18700402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei PopescuTHREADED_TEST(InterceptorOnConstructorPrototype) {
18701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
18702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
18703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
18704402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  templ->SetNamedPropertyHandler(NamedPropertyGetterWhichReturns42,
18705402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                 NamedPropertySetterWhichSetsYOnThisTo23);
18706402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  LocalContext context;
18707402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  context->Global()->Set(v8_str("P"), templ->NewInstance());
18708402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CompileRun("function C1() {"
18709402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu             "  this.x = 23;"
18710402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu             "};"
18711402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu             "C1.prototype = P;"
18712402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu             "function C2() {"
18713402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu             "  this.x = 23"
18714402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu             "};"
18715402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu             "C2.prototype = { };"
18716402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu             "C2.prototype.__proto__ = P;");
18717402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
18718402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  v8::Local<v8::Script> script;
18719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  script = v8_compile("new C1();");
18720402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  for (int i = 0; i < 10; i++) {
18721402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
18722402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    CHECK_EQ(23, c1->Get(v8_str("x"))->Int32Value());
18723402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    CHECK_EQ(42, c1->Get(v8_str("y"))->Int32Value());
18724402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
18725402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
18726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  script = v8_compile("new C2();");
18727402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  for (int i = 0; i < 10; i++) {
18728402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    v8::Handle<v8::Object> c2 = v8::Handle<v8::Object>::Cast(script->Run());
18729402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    CHECK_EQ(23, c2->Get(v8_str("x"))->Int32Value());
18730402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    CHECK_EQ(42, c2->Get(v8_str("y"))->Int32Value());
18731402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
18732402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
187336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
187346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(Regress618) {
187366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const char* source = "function C1() {"
187376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                       "  this.x = 23;"
187386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                       "};"
187396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                       "C1.prototype = P;";
187406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
187416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  LocalContext context;
18742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
18743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
187446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  v8::Local<v8::Script> script;
187456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
187466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Use a simple object as prototype.
18747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Object> prototype = v8::Object::New(isolate);
187486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  prototype->Set(v8_str("y"), v8_num(42));
187496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  context->Global()->Set(v8_str("P"), prototype);
187506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
187516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // This compile will add the code to the compilation cache.
187526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CompileRun(source);
187536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  script = v8_compile("new C1();");
187550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Allow enough iterations for the inobject slack tracking logic
187560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // to finalize instance size and install the fast construct stub.
187570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  for (int i = 0; i < 256; i++) {
187586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
187596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    CHECK_EQ(23, c1->Get(v8_str("x"))->Int32Value());
187606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    CHECK_EQ(42, c1->Get(v8_str("y"))->Int32Value());
187616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
187626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
187636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Use an API object with accessors as prototype.
18764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
18765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  templ->SetAccessor(v8_str("x"), GetterWhichReturns42,
187666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                     SetterWhichSetsYOnThisTo23);
187676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  context->Global()->Set(v8_str("P"), templ->NewInstance());
187686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
187696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // This compile will get the code from the compilation cache.
187706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CompileRun(source);
187716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  script = v8_compile("new C1();");
187736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (int i = 0; i < 10; i++) {
187746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
187756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    CHECK_EQ(42, c1->Get(v8_str("x"))->Int32Value());
187766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    CHECK_EQ(23, c1->Get(v8_str("y"))->Int32Value());
187776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
187786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
187796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochv8::Isolate* gc_callbacks_isolate = NULL;
187816ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockint prologue_call_count = 0;
187826ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockint epilogue_call_count = 0;
187836ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockint prologue_call_count_second = 0;
187846ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockint epilogue_call_count_second = 0;
18785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint prologue_call_count_alloc = 0;
18786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint epilogue_call_count_alloc = 0;
18787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid PrologueCallback(v8::GCType, v8::GCCallbackFlags flags) {
18789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(flags, v8::kNoGCCallbackFlags);
18790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ++prologue_call_count;
18791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
187926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid PrologueCallback(v8::Isolate* isolate,
18795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      v8::GCType,
18796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      v8::GCCallbackFlags flags) {
18797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(flags, v8::kNoGCCallbackFlags);
18798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(gc_callbacks_isolate, isolate);
187996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ++prologue_call_count;
188006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
188016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid EpilogueCallback(v8::GCType, v8::GCCallbackFlags flags) {
18804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(flags, v8::kNoGCCallbackFlags);
18805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ++epilogue_call_count;
18806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
18807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid EpilogueCallback(v8::Isolate* isolate,
18810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      v8::GCType,
18811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      v8::GCCallbackFlags flags) {
18812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(flags, v8::kNoGCCallbackFlags);
18813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(gc_callbacks_isolate, isolate);
188146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ++epilogue_call_count;
188156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
188166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid PrologueCallbackSecond(v8::GCType, v8::GCCallbackFlags flags) {
18819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(flags, v8::kNoGCCallbackFlags);
18820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ++prologue_call_count_second;
18821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
18822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid PrologueCallbackSecond(v8::Isolate* isolate,
18825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            v8::GCType,
18826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            v8::GCCallbackFlags flags) {
18827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(flags, v8::kNoGCCallbackFlags);
18828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(gc_callbacks_isolate, isolate);
188296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ++prologue_call_count_second;
188306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
188316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid EpilogueCallbackSecond(v8::GCType, v8::GCCallbackFlags flags) {
18834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(flags, v8::kNoGCCallbackFlags);
188356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ++epilogue_call_count_second;
188366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
188376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid EpilogueCallbackSecond(v8::Isolate* isolate,
18840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            v8::GCType,
18841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            v8::GCCallbackFlags flags) {
18842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(flags, v8::kNoGCCallbackFlags);
18843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(gc_callbacks_isolate, isolate);
18844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ++epilogue_call_count_second;
18845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
18846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid PrologueCallbackAlloc(v8::Isolate* isolate,
18849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           v8::GCType,
18850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           v8::GCCallbackFlags flags) {
18851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
18852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(flags, v8::kNoGCCallbackFlags);
18854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(gc_callbacks_isolate, isolate);
18855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ++prologue_call_count_alloc;
18856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Simulate full heap to see if we will reenter this callback
18858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SimulateFullSpace(CcTest::heap()->new_space());
18859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Object> obj = Object::New(isolate);
18861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!obj.IsEmpty());
18862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(
18864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      i::Heap::kAbortIncrementalMarkingMask);
18865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
18866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid EpilogueCallbackAlloc(v8::Isolate* isolate,
18869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           v8::GCType,
18870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           v8::GCCallbackFlags flags) {
18871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
18872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(flags, v8::kNoGCCallbackFlags);
18874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(gc_callbacks_isolate, isolate);
18875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ++epilogue_call_count_alloc;
18876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Simulate full heap to see if we will reenter this callback
18878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SimulateFullSpace(CcTest::heap()->new_space());
18879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Object> obj = Object::New(isolate);
18881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!obj.IsEmpty());
18882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(
18884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      i::Heap::kAbortIncrementalMarkingMask);
18885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
18886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(GCCallbacksOld) {
188896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  LocalContext context;
188906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
188916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  v8::V8::AddGCPrologueCallback(PrologueCallback);
188926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  v8::V8::AddGCEpilogueCallback(EpilogueCallback);
188936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(0, prologue_call_count);
188946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(0, epilogue_call_count);
18895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
188966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(1, prologue_call_count);
188976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(1, epilogue_call_count);
188986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  v8::V8::AddGCPrologueCallback(PrologueCallbackSecond);
188996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  v8::V8::AddGCEpilogueCallback(EpilogueCallbackSecond);
18900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
189016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(2, prologue_call_count);
189026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(2, epilogue_call_count);
189036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(1, prologue_call_count_second);
189046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(1, epilogue_call_count_second);
189056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  v8::V8::RemoveGCPrologueCallback(PrologueCallback);
189066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  v8::V8::RemoveGCEpilogueCallback(EpilogueCallback);
18907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
189086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(2, prologue_call_count);
189096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(2, epilogue_call_count);
189106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(2, prologue_call_count_second);
189116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(2, epilogue_call_count_second);
189126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  v8::V8::RemoveGCPrologueCallback(PrologueCallbackSecond);
189136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  v8::V8::RemoveGCEpilogueCallback(EpilogueCallbackSecond);
18914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
18915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2, prologue_call_count);
18916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2, epilogue_call_count);
18917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2, prologue_call_count_second);
18918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2, epilogue_call_count_second);
18919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
18920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(GCCallbacks) {
18923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
18924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
18925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  gc_callbacks_isolate = isolate;
18926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate->AddGCPrologueCallback(PrologueCallback);
18927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate->AddGCEpilogueCallback(EpilogueCallback);
18928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, prologue_call_count);
18929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, epilogue_call_count);
18930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
18931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1, prologue_call_count);
18932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1, epilogue_call_count);
18933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate->AddGCPrologueCallback(PrologueCallbackSecond);
18934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate->AddGCEpilogueCallback(EpilogueCallbackSecond);
18935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
18936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2, prologue_call_count);
18937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2, epilogue_call_count);
18938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1, prologue_call_count_second);
18939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1, epilogue_call_count_second);
18940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate->RemoveGCPrologueCallback(PrologueCallback);
18941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate->RemoveGCEpilogueCallback(EpilogueCallback);
18942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
18943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2, prologue_call_count);
18944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2, epilogue_call_count);
18945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2, prologue_call_count_second);
18946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2, epilogue_call_count_second);
18947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate->RemoveGCPrologueCallback(PrologueCallbackSecond);
18948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate->RemoveGCEpilogueCallback(EpilogueCallbackSecond);
18949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
189506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(2, prologue_call_count);
189516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(2, epilogue_call_count);
189526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(2, prologue_call_count_second);
189536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(2, epilogue_call_count_second);
18954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, prologue_call_count_alloc);
18956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, epilogue_call_count_alloc);
18957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate->AddGCPrologueCallback(PrologueCallbackAlloc);
18958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate->AddGCEpilogueCallback(EpilogueCallbackAlloc);
18959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(
18960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      i::Heap::kAbortIncrementalMarkingMask);
18961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1, prologue_call_count_alloc);
18962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1, epilogue_call_count_alloc);
18963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate->RemoveGCPrologueCallback(PrologueCallbackAlloc);
18964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate->RemoveGCEpilogueCallback(EpilogueCallbackAlloc);
189656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
1896625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
1896725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
1896825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian MonsenTHREADED_TEST(AddToJSFunctionResultCache) {
18969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::FLAG_stress_compaction = false;
1897025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  i::FLAG_allow_natives_syntax = true;
18971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(CcTest::isolate());
1897225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
1897325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  LocalContext context;
1897425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
1897525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  const char* code =
1897625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      "(function() {"
1897725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      "  var key0 = 'a';"
1897825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      "  var key1 = 'b';"
1897925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      "  var r0 = %_GetFromCache(0, key0);"
1898025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      "  var r1 = %_GetFromCache(0, key1);"
1898125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      "  var r0_ = %_GetFromCache(0, key0);"
1898225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      "  if (r0 !== r0_)"
1898325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      "    return 'Different results for ' + key0 + ': ' + r0 + ' vs. ' + r0_;"
1898425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      "  var r1_ = %_GetFromCache(0, key1);"
1898525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      "  if (r1 !== r1_)"
1898625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      "    return 'Different results for ' + key1 + ': ' + r1 + ' vs. ' + r1_;"
1898725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      "  return 'PASSED';"
1898825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      "})()";
18989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->ClearJSFunctionResultCaches();
1899025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  ExpectString(code, "PASSED");
1899125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen}
1899225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
1899325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
1899425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian MonsenTHREADED_TEST(FillJSFunctionResultCache) {
1899525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  i::FLAG_allow_natives_syntax = true;
1899625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  LocalContext context;
18997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(context->GetIsolate());
1899825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
1899925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  const char* code =
1900025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      "(function() {"
1900125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      "  var k = 'a';"
1900225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      "  var r = %_GetFromCache(0, k);"
1900325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      "  for (var i = 0; i < 16; i++) {"
1900425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      "    %_GetFromCache(0, 'a' + i);"
1900525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      "  };"
1900625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      "  if (r === %_GetFromCache(0, k))"
1900725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      "    return 'FAILED: k0CacheSize is too small';"
1900825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      "  return 'PASSED';"
1900925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      "})()";
19010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->ClearJSFunctionResultCaches();
1901125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  ExpectString(code, "PASSED");
1901225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen}
1901325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
1901425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
1901525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian MonsenTHREADED_TEST(RoundRobinGetFromCache) {
1901625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  i::FLAG_allow_natives_syntax = true;
1901725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  LocalContext context;
19018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(context->GetIsolate());
1901925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
1902025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  const char* code =
1902125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      "(function() {"
1902225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      "  var keys = [];"
1902325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      "  for (var i = 0; i < 16; i++) keys.push(i);"
1902425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      "  var values = [];"
1902525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      "  for (var i = 0; i < 16; i++) values[i] = %_GetFromCache(0, keys[i]);"
1902625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      "  for (var i = 0; i < 16; i++) {"
1902725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      "    var v = %_GetFromCache(0, keys[i]);"
190283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "    if (v.toString() !== values[i].toString())"
1902925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      "      return 'Wrong value for ' + "
1903025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      "          keys[i] + ': ' + v + ' vs. ' + values[i];"
1903125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      "  };"
1903225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      "  return 'PASSED';"
1903325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      "})()";
19034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->ClearJSFunctionResultCaches();
1903525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  ExpectString(code, "PASSED");
1903625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen}
1903725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
1903825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
1903925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian MonsenTHREADED_TEST(ReverseGetFromCache) {
1904025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  i::FLAG_allow_natives_syntax = true;
1904125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  LocalContext context;
19042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(context->GetIsolate());
1904325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
1904425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  const char* code =
1904525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      "(function() {"
1904625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      "  var keys = [];"
1904725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      "  for (var i = 0; i < 16; i++) keys.push(i);"
1904825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      "  var values = [];"
1904925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      "  for (var i = 0; i < 16; i++) values[i] = %_GetFromCache(0, keys[i]);"
1905025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      "  for (var i = 15; i >= 16; i--) {"
1905125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      "    var v = %_GetFromCache(0, keys[i]);"
1905225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      "    if (v !== values[i])"
1905325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      "      return 'Wrong value for ' + "
1905425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      "          keys[i] + ': ' + v + ' vs. ' + values[i];"
1905525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      "  };"
1905625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      "  return 'PASSED';"
1905725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      "})()";
19058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->ClearJSFunctionResultCaches();
1905925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  ExpectString(code, "PASSED");
1906025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen}
1906125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
1906225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
1906325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian MonsenTHREADED_TEST(TestEviction) {
1906425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  i::FLAG_allow_natives_syntax = true;
1906525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  LocalContext context;
19066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(context->GetIsolate());
1906725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
1906825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  const char* code =
1906925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      "(function() {"
1907025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      "  for (var i = 0; i < 2*16; i++) {"
1907125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      "    %_GetFromCache(0, 'a' + i);"
1907225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      "  };"
1907325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      "  return 'PASSED';"
1907425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      "})()";
19075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->ClearJSFunctionResultCaches();
1907625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  ExpectString(code, "PASSED");
1907725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen}
190788defd9ff6930b4e24729971a61cf7469daf119beSteve Block
190798defd9ff6930b4e24729971a61cf7469daf119beSteve Block
19080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(TwoByteStringInOneByteCons) {
190818defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // See Chromium issue 47824.
190828defd9ff6930b4e24729971a61cf7469daf119beSteve Block  LocalContext context;
19083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(context->GetIsolate());
19084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
190858defd9ff6930b4e24729971a61cf7469daf119beSteve Block  const char* init_code =
190868defd9ff6930b4e24729971a61cf7469daf119beSteve Block      "var str1 = 'abelspendabel';"
190878defd9ff6930b4e24729971a61cf7469daf119beSteve Block      "var str2 = str1 + str1 + str1;"
190888defd9ff6930b4e24729971a61cf7469daf119beSteve Block      "str2;";
190898defd9ff6930b4e24729971a61cf7469daf119beSteve Block  Local<Value> result = CompileRun(init_code);
190908defd9ff6930b4e24729971a61cf7469daf119beSteve Block
1909169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Local<Value> indexof = CompileRun("str2.indexOf('els')");
1909269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Local<Value> lastindexof = CompileRun("str2.lastIndexOf('dab')");
1909369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
190948defd9ff6930b4e24729971a61cf7469daf119beSteve Block  CHECK(result->IsString());
190958defd9ff6930b4e24729971a61cf7469daf119beSteve Block  i::Handle<i::String> string = v8::Utils::OpenHandle(String::Cast(*result));
190968defd9ff6930b4e24729971a61cf7469daf119beSteve Block  int length = string->length();
19097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(string->IsOneByteRepresentation());
190988defd9ff6930b4e24729971a61cf7469daf119beSteve Block
19099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::Handle<i::String> flat_string = i::String::Flatten(string);
191008defd9ff6930b4e24729971a61cf7469daf119beSteve Block
19101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(string->IsOneByteRepresentation());
19102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(flat_string->IsOneByteRepresentation());
191038defd9ff6930b4e24729971a61cf7469daf119beSteve Block
191048defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Create external resource.
191058defd9ff6930b4e24729971a61cf7469daf119beSteve Block  uint16_t* uc16_buffer = new uint16_t[length + 1];
191068defd9ff6930b4e24729971a61cf7469daf119beSteve Block
191078defd9ff6930b4e24729971a61cf7469daf119beSteve Block  i::String::WriteToFlat(*flat_string, uc16_buffer, 0, length);
191088defd9ff6930b4e24729971a61cf7469daf119beSteve Block  uc16_buffer[length] = 0;
191098defd9ff6930b4e24729971a61cf7469daf119beSteve Block
191108defd9ff6930b4e24729971a61cf7469daf119beSteve Block  TestResource resource(uc16_buffer);
191118defd9ff6930b4e24729971a61cf7469daf119beSteve Block
191128defd9ff6930b4e24729971a61cf7469daf119beSteve Block  flat_string->MakeExternal(&resource);
191138defd9ff6930b4e24729971a61cf7469daf119beSteve Block
191148defd9ff6930b4e24729971a61cf7469daf119beSteve Block  CHECK(flat_string->IsTwoByteRepresentation());
191158defd9ff6930b4e24729971a61cf7469daf119beSteve Block
19116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If the cons string has been short-circuited, skip the following checks.
19117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!string.is_identical_to(flat_string)) {
19118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // At this point, we should have a Cons string which is flat and one-byte,
19119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // with a first half that is a two-byte string (although it only contains
19120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // one-byte characters). This is a valid sequence of steps, and it can
19121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // happen in real pages.
19122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(string->IsOneByteRepresentation());
19123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    i::ConsString* cons = i::ConsString::cast(*string);
19124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(0, cons->second()->length());
19125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(cons->first()->IsTwoByteRepresentation());
19126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
191278defd9ff6930b4e24729971a61cf7469daf119beSteve Block
191288defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Check that some string operations work.
191298defd9ff6930b4e24729971a61cf7469daf119beSteve Block
191308defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Atom RegExp.
191318defd9ff6930b4e24729971a61cf7469daf119beSteve Block  Local<Value> reresult = CompileRun("str2.match(/abel/g).length;");
191328defd9ff6930b4e24729971a61cf7469daf119beSteve Block  CHECK_EQ(6, reresult->Int32Value());
191338defd9ff6930b4e24729971a61cf7469daf119beSteve Block
191348defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Nonatom RegExp.
191358defd9ff6930b4e24729971a61cf7469daf119beSteve Block  reresult = CompileRun("str2.match(/abe./g).length;");
191368defd9ff6930b4e24729971a61cf7469daf119beSteve Block  CHECK_EQ(6, reresult->Int32Value());
191378defd9ff6930b4e24729971a61cf7469daf119beSteve Block
191388defd9ff6930b4e24729971a61cf7469daf119beSteve Block  reresult = CompileRun("str2.search(/bel/g);");
191398defd9ff6930b4e24729971a61cf7469daf119beSteve Block  CHECK_EQ(1, reresult->Int32Value());
191408defd9ff6930b4e24729971a61cf7469daf119beSteve Block
191418defd9ff6930b4e24729971a61cf7469daf119beSteve Block  reresult = CompileRun("str2.search(/be./g);");
191428defd9ff6930b4e24729971a61cf7469daf119beSteve Block  CHECK_EQ(1, reresult->Int32Value());
191438defd9ff6930b4e24729971a61cf7469daf119beSteve Block
191448defd9ff6930b4e24729971a61cf7469daf119beSteve Block  ExpectTrue("/bel/g.test(str2);");
191458defd9ff6930b4e24729971a61cf7469daf119beSteve Block
191468defd9ff6930b4e24729971a61cf7469daf119beSteve Block  ExpectTrue("/be./g.test(str2);");
191478defd9ff6930b4e24729971a61cf7469daf119beSteve Block
191488defd9ff6930b4e24729971a61cf7469daf119beSteve Block  reresult = CompileRun("/bel/g.exec(str2);");
191498defd9ff6930b4e24729971a61cf7469daf119beSteve Block  CHECK(!reresult->IsNull());
191508defd9ff6930b4e24729971a61cf7469daf119beSteve Block
191518defd9ff6930b4e24729971a61cf7469daf119beSteve Block  reresult = CompileRun("/be./g.exec(str2);");
191528defd9ff6930b4e24729971a61cf7469daf119beSteve Block  CHECK(!reresult->IsNull());
191538defd9ff6930b4e24729971a61cf7469daf119beSteve Block
191548defd9ff6930b4e24729971a61cf7469daf119beSteve Block  ExpectString("str2.substring(2, 10);", "elspenda");
191558defd9ff6930b4e24729971a61cf7469daf119beSteve Block
191568defd9ff6930b4e24729971a61cf7469daf119beSteve Block  ExpectString("str2.substring(2, 20);", "elspendabelabelspe");
191578defd9ff6930b4e24729971a61cf7469daf119beSteve Block
191588defd9ff6930b4e24729971a61cf7469daf119beSteve Block  ExpectString("str2.charAt(2);", "e");
191598defd9ff6930b4e24729971a61cf7469daf119beSteve Block
1916069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  ExpectObject("str2.indexOf('els');", indexof);
1916169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
1916269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  ExpectObject("str2.lastIndexOf('dab');", lastindexof);
1916369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
191648defd9ff6930b4e24729971a61cf7469daf119beSteve Block  reresult = CompileRun("str2.charCodeAt(2);");
191658defd9ff6930b4e24729971a61cf7469daf119beSteve Block  CHECK_EQ(static_cast<int32_t>('e'), reresult->Int32Value());
191668defd9ff6930b4e24729971a61cf7469daf119beSteve Block}
19167756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
19168756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
19169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(ContainsOnlyOneByte) {
19170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::V8::Initialize();
19171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
19172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
19173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Make a buffer long enough that it won't automatically be converted.
19174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int length = 512;
19175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Ensure word aligned assignment.
19176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int aligned_length = length*sizeof(uintptr_t)/sizeof(uint16_t);
19177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::SmartArrayPointer<uintptr_t>
19178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  aligned_contents(new uintptr_t[aligned_length]);
19179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  uint16_t* string_contents =
19180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      reinterpret_cast<uint16_t*>(aligned_contents.get());
19181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Set to contain only one byte.
19182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < length-1; i++) {
19183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    string_contents[i] = 0x41;
19184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
19185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  string_contents[length-1] = 0;
19186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Simple case.
19187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<String> string =
19188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      String::NewExternal(isolate,
19189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          new TestResource(string_contents, NULL, false));
19190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
19191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Counter example.
19192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  string = String::NewFromTwoByte(isolate, string_contents);
19193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
19194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Test left right and balanced cons strings.
19195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<String> base = String::NewFromUtf8(isolate, "a");
19196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<String> left = base;
19197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<String> right = base;
19198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < 1000; i++) {
19199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    left = String::Concat(base, left);
19200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    right = String::Concat(right, base);
19201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
19202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<String> balanced = String::Concat(left, base);
19203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  balanced = String::Concat(balanced, right);
19204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<String> cons_strings[] = {left, balanced, right};
19205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<String> two_byte =
19206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      String::NewExternal(isolate,
19207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          new TestResource(string_contents, NULL, false));
19208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  USE(two_byte); USE(cons_strings);
19209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (size_t i = 0; i < arraysize(cons_strings); i++) {
19210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Base assumptions.
19211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    string = cons_strings[i];
19212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
19213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Test left and right concatentation.
19214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    string = String::Concat(two_byte, cons_strings[i]);
19215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
19216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    string = String::Concat(cons_strings[i], two_byte);
19217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
19218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
19219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Set bits in different positions
19220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // for strings of different lengths and alignments.
19221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int alignment = 0; alignment < 7; alignment++) {
19222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int size = 2; alignment + size < length; size *= 2) {
19223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      int zero_offset = size + alignment;
19224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      string_contents[zero_offset] = 0;
19225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      for (int i = 0; i < size; i++) {
19226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        int shift = 8 + (i % 7);
19227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        string_contents[alignment + i] = 1 << shift;
19228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        string = String::NewExternal(
19229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            isolate,
19230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            new TestResource(string_contents + alignment, NULL, false));
19231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        CHECK_EQ(size, string->Length());
19232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        CHECK(!string->ContainsOnlyOneByte());
19233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        string_contents[alignment + i] = 0x41;
19234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
19235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      string_contents[zero_offset] = 0x41;
19236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
19237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
19238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
19239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
19240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
19241756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick// Failed access check callback that performs a GC on each invocation.
19242756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid FailedAccessCheckCallbackGC(Local<v8::Object> target,
19243756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                                 v8::AccessType type,
19244756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                                 Local<v8::Value> data) {
19245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
19246756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
19247756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
19248756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
19249756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain MerrickTEST(GCInFailedAccessCheckCallback) {
19250756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Install a failed access check callback that performs a GC on each
19251756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // invocation. Then force the callback to be called from va
19252756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
19253756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  v8::V8::Initialize();
19254756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  v8::V8::SetFailedAccessCheckCallbackFunction(&FailedAccessCheckCallbackGC);
19255756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
19256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
19257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
19258756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
19259756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Create an ObjectTemplate for global objects and install access
19260756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // check callbacks that will block access.
19261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> global_template =
19262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::ObjectTemplate::New(isolate);
19263756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  global_template->SetAccessCheckCallbacks(NamedGetAccessBlocker,
19264756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                                           IndexedGetAccessBlocker,
19265756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                                           v8::Handle<v8::Value>(),
19266756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                                           false);
19267756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
19268756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Create a context and set an x property on it's global object.
19269756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  LocalContext context0(NULL, global_template);
19270756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  context0->Global()->Set(v8_str("x"), v8_num(42));
19271756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  v8::Handle<v8::Object> global0 = context0->Global();
19272756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
19273756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Create a context with a different security token so that the
19274756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // failed access check callback will be called on each access.
19275756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  LocalContext context1(NULL, global_template);
19276756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  context1->Global()->Set(v8_str("other"), global0);
19277756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
19278756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Get property with failed access check.
19279756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  ExpectUndefined("other.x");
19280756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
19281756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Get element with failed access check.
19282756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  ExpectUndefined("other[0]");
19283756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
19284756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Set property with failed access check.
19285756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  v8::Handle<v8::Value> result = CompileRun("other.x = new Object()");
19286756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  CHECK(result->IsObject());
19287756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
19288756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Set element with failed access check.
19289756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  result = CompileRun("other[0] = new Object()");
19290756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  CHECK(result->IsObject());
19291756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
19292756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Get property attribute with failed access check.
19293756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  ExpectFalse("\'x\' in other");
19294756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
19295756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Get property attribute for element with failed access check.
19296756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  ExpectFalse("0 in other");
19297756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
19298756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Delete property.
19299756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  ExpectFalse("delete other.x");
19300756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
19301756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Delete element.
19302756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  CHECK_EQ(false, global0->Delete(0));
19303756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
19304756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // DefineAccessor.
19305756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  CHECK_EQ(false,
19306756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick           global0->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("x")));
19307756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
19308756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Define JavaScript accessor.
19309756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  ExpectUndefined("Object.prototype.__defineGetter__.call("
19310756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                  "    other, \'x\', function() { return 42; })");
19311756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
19312756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // LookupAccessor.
19313756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  ExpectUndefined("Object.prototype.__lookupGetter__.call("
19314756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                  "    other, \'x\')");
19315756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
19316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // HasOwnElement.
19317756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  ExpectFalse("Object.prototype.hasOwnProperty.call(other, \'0\')");
19318756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
19319756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  CHECK_EQ(false, global0->HasRealIndexedProperty(0));
19320756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  CHECK_EQ(false, global0->HasRealNamedProperty(v8_str("x")));
19321756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  CHECK_EQ(false, global0->HasRealNamedCallbackProperty(v8_str("x")));
19322756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
19323756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Reset the failed access check callback so it does not influence
19324756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // the other tests.
19325756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  v8::V8::SetFailedAccessCheckCallbackFunction(NULL);
19326756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
193270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
1932844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1932944f0eee88ff00398ff7f715fab053374d808c90dSteve BlockTEST(IsolateNewDispose) {
19330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* current_isolate = CcTest::isolate();
1933144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::Isolate* isolate = v8::Isolate::New();
1933244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK(isolate != NULL);
1933344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK(current_isolate != isolate);
19334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(current_isolate == CcTest::isolate());
1933544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1933644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::V8::SetFatalErrorHandler(StoringErrorCallback);
1933744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  last_location = last_message = NULL;
1933844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  isolate->Dispose();
1933944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(last_location, NULL);
1934044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(last_message, NULL);
1934144f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
1934244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1934344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
19344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochUNINITIALIZED_TEST(DisposeIsolateWhenInUse) {
1934544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::Isolate* isolate = v8::Isolate::New();
19346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
19347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Isolate::Scope i_scope(isolate);
19348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(isolate);
19349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LocalContext context(isolate);
19350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Run something in this isolate.
19351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ExpectTrue("true");
19352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::V8::SetFatalErrorHandler(StoringErrorCallback);
19353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    last_location = last_message = NULL;
19354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Still entered, should fail.
19355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    isolate->Dispose();
19356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_NE(last_location, NULL);
19357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_NE(last_message, NULL);
1935844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
1935944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  isolate->Dispose();
1936044f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
1936144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1936244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1936344f0eee88ff00398ff7f715fab053374d808c90dSteve BlockTEST(RunTwoIsolatesOnSingleThread) {
1936444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Run isolate 1.
1936544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::Isolate* isolate1 = v8::Isolate::New();
1936644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  isolate1->Enter();
19367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Persistent<v8::Context> context1;
19368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
19369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(isolate1);
19370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    context1.Reset(isolate1, Context::New(isolate1));
19371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1937244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1937344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  {
19374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(isolate1);
19375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Local<v8::Context> context =
19376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v8::Local<v8::Context>::New(isolate1, context1);
19377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Context::Scope context_scope(context);
1937844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Run something in new isolate.
1937944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    CompileRun("var foo = 'isolate 1';");
1938044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ExpectString("function f() { return foo; }; f()", "isolate 1");
1938144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
1938244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1938344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Run isolate 2.
1938444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::Isolate* isolate2 = v8::Isolate::New();
1938544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::Persistent<v8::Context> context2;
1938644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1938744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  {
1938844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    v8::Isolate::Scope iscope(isolate2);
19389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(isolate2);
19390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    context2.Reset(isolate2, Context::New(isolate2));
19391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Local<v8::Context> context =
19392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v8::Local<v8::Context>::New(isolate2, context2);
19393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Context::Scope context_scope(context);
1939444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1939544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Run something in new isolate.
1939644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    CompileRun("var foo = 'isolate 2';");
1939744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ExpectString("function f() { return foo; }; f()", "isolate 2");
1939844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
1939944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1940044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  {
19401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(isolate1);
19402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Local<v8::Context> context =
19403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v8::Local<v8::Context>::New(isolate1, context1);
19404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Context::Scope context_scope(context);
1940544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Now again in isolate 1
1940644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ExpectString("function f() { return foo; }; f()", "isolate 1");
1940744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
1940844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1940944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  isolate1->Exit();
1941044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1941144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Run some stuff in default isolate.
19412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Persistent<v8::Context> context_default;
19413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
19414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Isolate* isolate = CcTest::isolate();
19415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Isolate::Scope iscope(isolate);
19416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(isolate);
19417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    context_default.Reset(isolate, Context::New(isolate));
19418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1941944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1942044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  {
19421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(CcTest::isolate());
19422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Local<v8::Context> context =
19423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v8::Local<v8::Context>::New(CcTest::isolate(), context_default);
19424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Context::Scope context_scope(context);
1942544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Variables in other isolates should be not available, verify there
1942644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // is an exception.
1942744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ExpectTrue("function f() {"
1942844f0eee88ff00398ff7f715fab053374d808c90dSteve Block               "  try {"
1942944f0eee88ff00398ff7f715fab053374d808c90dSteve Block               "    foo;"
1943044f0eee88ff00398ff7f715fab053374d808c90dSteve Block               "    return false;"
1943144f0eee88ff00398ff7f715fab053374d808c90dSteve Block               "  } catch(e) {"
1943244f0eee88ff00398ff7f715fab053374d808c90dSteve Block               "    return true;"
1943344f0eee88ff00398ff7f715fab053374d808c90dSteve Block               "  }"
1943444f0eee88ff00398ff7f715fab053374d808c90dSteve Block               "};"
1943544f0eee88ff00398ff7f715fab053374d808c90dSteve Block               "var isDefaultIsolate = true;"
1943644f0eee88ff00398ff7f715fab053374d808c90dSteve Block               "f()");
1943744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
1943844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1943944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  isolate1->Enter();
1944044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1944144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  {
1944244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    v8::Isolate::Scope iscope(isolate2);
19443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(isolate2);
19444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Local<v8::Context> context =
19445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v8::Local<v8::Context>::New(isolate2, context2);
19446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Context::Scope context_scope(context);
1944744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ExpectString("function f() { return foo; }; f()", "isolate 2");
1944844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
1944944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1945044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  {
19451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(v8::Isolate::GetCurrent());
19452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Local<v8::Context> context =
19453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v8::Local<v8::Context>::New(v8::Isolate::GetCurrent(), context1);
19454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Context::Scope context_scope(context);
1945544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ExpectString("function f() { return foo; }; f()", "isolate 1");
1945644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
1945744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1945844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  {
1945944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    v8::Isolate::Scope iscope(isolate2);
19460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    context2.Reset();
1946144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
1946244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
19463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context1.Reset();
1946444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  isolate1->Exit();
1946544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1946644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::V8::SetFatalErrorHandler(StoringErrorCallback);
1946744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  last_location = last_message = NULL;
1946844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1946944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  isolate1->Dispose();
1947044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(last_location, NULL);
1947144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(last_message, NULL);
1947244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1947344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  isolate2->Dispose();
1947444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(last_location, NULL);
1947544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(last_message, NULL);
1947644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1947744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check that default isolate still runs.
1947844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  {
19479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(CcTest::isolate());
19480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Local<v8::Context> context =
19481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v8::Local<v8::Context>::New(CcTest::isolate(), context_default);
19482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Context::Scope context_scope(context);
1948344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ExpectTrue("function f() { return isDefaultIsolate; }; f()");
1948444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
1948544f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
1948644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
19487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1948844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic int CalcFibonacci(v8::Isolate* isolate, int limit) {
1948944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::Isolate::Scope isolate_scope(isolate);
19490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
19491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context(isolate);
1949244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  i::ScopedVector<char> code(1024);
19493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::SNPrintF(code, "function fib(n) {"
19494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                    "  if (n <= 2) return 1;"
19495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                    "  return fib(n-1) + fib(n-2);"
19496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                    "}"
19497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                    "fib(%d)", limit);
1949844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Local<Value> value = CompileRun(code.start());
1949944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK(value->IsNumber());
1950044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return static_cast<int>(value->NumberValue());
1950144f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
1950244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
19503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass IsolateThread : public v8::base::Thread {
1950444f0eee88ff00398ff7f715fab053374d808c90dSteve Block public:
19505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  explicit IsolateThread(int fib_limit)
19506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : Thread(Options("IsolateThread")), fib_limit_(fib_limit), result_(0) {}
1950744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1950844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void Run() {
19509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Isolate* isolate = v8::Isolate::New();
19510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    result_ = CalcFibonacci(isolate, fib_limit_);
19511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    isolate->Dispose();
1951244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
1951344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1951444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int result() { return result_; }
1951544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1951644f0eee88ff00398ff7f715fab053374d808c90dSteve Block private:
1951744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int fib_limit_;
1951844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int result_;
1951944f0eee88ff00398ff7f715fab053374d808c90dSteve Block};
1952044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1952144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
19522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(MultipleIsolatesOnIndividualThreads) {
19523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  IsolateThread thread1(21);
19524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  IsolateThread thread2(12);
1952544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1952644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Compute some fibonacci numbers on 3 threads in 3 isolates.
1952744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  thread1.Start();
1952844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  thread2.Start();
1952944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
19530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int result1 = CalcFibonacci(CcTest::isolate(), 21);
19531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int result2 = CalcFibonacci(CcTest::isolate(), 12);
1953244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1953344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  thread1.Join();
1953444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  thread2.Join();
1953544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1953644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Compare results. The actual fibonacci numbers for 12 and 21 are taken
1953744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // (I'm lazy!) from http://en.wikipedia.org/wiki/Fibonacci_number
1953844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(result1, 10946);
1953944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(result2, 144);
1954044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(result1, thread1.result());
1954144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(result2, thread2.result());
1954244f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
1954344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
19544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
19545257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochTEST(IsolateDifferentContexts) {
19546257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  v8::Isolate* isolate = v8::Isolate::New();
19547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::Context> context;
19548257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  {
19549257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    v8::Isolate::Scope isolate_scope(isolate);
19550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope handle_scope(isolate);
19551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    context = v8::Context::New(isolate);
19552257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    v8::Context::Scope context_scope(context);
19553257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Local<Value> v = CompileRun("2");
19554257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(v->IsNumber());
19555257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_EQ(2, static_cast<int>(v->NumberValue()));
19556257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
19557257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  {
19558257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    v8::Isolate::Scope isolate_scope(isolate);
19559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope handle_scope(isolate);
19560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    context = v8::Context::New(isolate);
19561257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    v8::Context::Scope context_scope(context);
19562257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Local<Value> v = CompileRun("22");
19563257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(v->IsNumber());
19564257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_EQ(22, static_cast<int>(v->NumberValue()));
19565257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
19566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate->Dispose();
19567257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1956844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
19569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass InitDefaultIsolateThread : public v8::base::Thread {
1957044f0eee88ff00398ff7f715fab053374d808c90dSteve Block public:
1957144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  enum TestCase {
1957244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    SetResourceConstraints,
1957344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    SetFatalHandler,
1957444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    SetCounterFunction,
1957544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    SetCreateHistogramFunction,
1957644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    SetAddHistogramSampleFunction
1957744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  };
1957844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1957944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  explicit InitDefaultIsolateThread(TestCase testCase)
19580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : Thread(Options("InitDefaultIsolateThread")),
1958144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        testCase_(testCase),
19582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        result_(false) {}
1958344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1958444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void Run() {
19585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Isolate::CreateParams create_params;
1958644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    switch (testCase_) {
19587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case SetResourceConstraints: {
19588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        create_params.constraints.set_max_semi_space_size(1);
19589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        create_params.constraints.set_max_old_space_size(4);
19590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
19591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
19592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      default:
19593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
1959444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
19595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Isolate* isolate = v8::Isolate::New(create_params);
19596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    isolate->Enter();
19597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    switch (testCase_) {
19598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case SetResourceConstraints:
19599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Already handled in pre-Isolate-creation block.
19600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
1960144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
19602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case SetFatalHandler:
19603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v8::V8::SetFatalErrorHandler(NULL);
19604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
1960544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
19606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case SetCounterFunction:
19607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        CcTest::isolate()->SetCounterFunction(NULL);
19608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
1960944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
19610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case SetCreateHistogramFunction:
19611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        CcTest::isolate()->SetCreateHistogramFunction(NULL);
19612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
1961344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
19614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case SetAddHistogramSampleFunction:
19615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        CcTest::isolate()->SetAddHistogramSampleFunction(NULL);
19616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
1961744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
19618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    isolate->Exit();
19619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    isolate->Dispose();
1962044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    result_ = true;
1962144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
1962244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1962344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bool result() { return result_; }
1962444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1962544f0eee88ff00398ff7f715fab053374d808c90dSteve Block private:
1962644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  TestCase testCase_;
1962744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bool result_;
1962844f0eee88ff00398ff7f715fab053374d808c90dSteve Block};
1962944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1963044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1963144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic void InitializeTestHelper(InitDefaultIsolateThread::TestCase testCase) {
1963244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  InitDefaultIsolateThread thread(testCase);
1963344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  thread.Start();
1963444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  thread.Join();
1963544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(thread.result(), true);
1963644f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
1963744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1963844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
19639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(InitializeDefaultIsolateOnSecondaryThread1) {
1964044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  InitializeTestHelper(InitDefaultIsolateThread::SetResourceConstraints);
1964144f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
1964244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
19643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
19644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(InitializeDefaultIsolateOnSecondaryThread2) {
1964544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  InitializeTestHelper(InitDefaultIsolateThread::SetFatalHandler);
1964644f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
1964744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
19648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
19649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(InitializeDefaultIsolateOnSecondaryThread3) {
1965044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  InitializeTestHelper(InitDefaultIsolateThread::SetCounterFunction);
1965144f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
1965244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
19653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
19654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(InitializeDefaultIsolateOnSecondaryThread4) {
1965544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  InitializeTestHelper(InitDefaultIsolateThread::SetCreateHistogramFunction);
1965644f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
1965744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
19658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
19659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(InitializeDefaultIsolateOnSecondaryThread5) {
1966044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  InitializeTestHelper(InitDefaultIsolateThread::SetAddHistogramSampleFunction);
1966144f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
1966244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
196630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
196640d5e116f6aee03185f237311a943491bb079a768Kristian MonsenTEST(StringCheckMultipleContexts) {
196650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  const char* code =
196660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "(function() { return \"a\".charAt(0); })()";
196670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
196680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  {
196690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    // Run the code twice in the first context to initialize the call IC.
196700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    LocalContext context1;
19671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(context1->GetIsolate());
196720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    ExpectString(code, "a");
196730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    ExpectString(code, "a");
196740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  }
196750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
196760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  {
196770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    // Change the String.prototype in the second context and check
196780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    // that the right function gets called.
196790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    LocalContext context2;
19680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(context2->GetIsolate());
196810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    CompileRun("String.prototype.charAt = function() { return \"not a\"; }");
196820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    ExpectString(code, "not a");
196830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  }
196840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
196850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
196860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
196870d5e116f6aee03185f237311a943491bb079a768Kristian MonsenTEST(NumberCheckMultipleContexts) {
196880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  const char* code =
196890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "(function() { return (42).toString(); })()";
196900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
196910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  {
196920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    // Run the code twice in the first context to initialize the call IC.
196930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    LocalContext context1;
19694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(context1->GetIsolate());
196950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    ExpectString(code, "42");
196960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    ExpectString(code, "42");
196970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  }
196980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
196990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  {
197000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    // Change the Number.prototype in the second context and check
197010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    // that the right function gets called.
197020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    LocalContext context2;
19703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(context2->GetIsolate());
197040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    CompileRun("Number.prototype.toString = function() { return \"not 42\"; }");
197050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    ExpectString(code, "not 42");
197060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  }
197070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
197080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
197090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
197100d5e116f6aee03185f237311a943491bb079a768Kristian MonsenTEST(BooleanCheckMultipleContexts) {
197110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  const char* code =
197120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "(function() { return true.toString(); })()";
197130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
197140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  {
197150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    // Run the code twice in the first context to initialize the call IC.
197160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    LocalContext context1;
19717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(context1->GetIsolate());
197180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    ExpectString(code, "true");
197190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    ExpectString(code, "true");
197200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  }
197210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
197220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  {
197230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    // Change the Boolean.prototype in the second context and check
197240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    // that the right function gets called.
197250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    LocalContext context2;
19726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(context2->GetIsolate());
197270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    CompileRun("Boolean.prototype.toString = function() { return \"\"; }");
197280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    ExpectString(code, "");
197290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  }
197300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
19731f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
19732f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
19733f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochTEST(DontDeleteCellLoadIC) {
19734f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  const char* function_code =
19735f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      "function readCell() { while (true) { return cell; } }";
19736f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
19737f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  {
19738f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    // Run the code twice in the first context to initialize the load
19739f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    // IC for a don't delete cell.
19740f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    LocalContext context1;
19741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(context1->GetIsolate());
19742f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    CompileRun("var cell = \"first\";");
19743f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    ExpectBoolean("delete cell", false);
19744f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    CompileRun(function_code);
19745f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    ExpectString("readCell()", "first");
19746f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    ExpectString("readCell()", "first");
19747f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  }
19748f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
19749f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  {
19750f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    // Use a deletable cell in the second context.
19751f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    LocalContext context2;
19752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(context2->GetIsolate());
19753f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    CompileRun("cell = \"second\";");
19754f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    CompileRun(function_code);
19755f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    ExpectString("readCell()", "second");
19756f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    ExpectBoolean("delete cell", true);
19757f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    ExpectString("(function() {"
19758f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch                 "  try {"
19759f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch                 "    return readCell();"
19760f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch                 "  } catch(e) {"
19761f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch                 "    return e.toString();"
19762f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch                 "  }"
19763f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch                 "})()",
19764f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch                 "ReferenceError: cell is not defined");
19765f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    CompileRun("cell = \"new_second\";");
19766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
19767f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    ExpectString("readCell()", "new_second");
19768f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    ExpectString("readCell()", "new_second");
19769f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  }
19770f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch}
19771f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
19772f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
19773f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochTEST(DontDeleteCellLoadICForceDelete) {
19774f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  const char* function_code =
19775f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      "function readCell() { while (true) { return cell; } }";
19776f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
19777f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Run the code twice to initialize the load IC for a don't delete
19778f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // cell.
19779f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  LocalContext context;
19780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(context->GetIsolate());
19781f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CompileRun("var cell = \"value\";");
19782f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  ExpectBoolean("delete cell", false);
19783f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CompileRun(function_code);
19784f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  ExpectString("readCell()", "value");
19785f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  ExpectString("readCell()", "value");
19786f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
19787f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Delete the cell using the API and check the inlined code works
19788f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // correctly.
19789f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CHECK(context->Global()->ForceDelete(v8_str("cell")));
19790f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  ExpectString("(function() {"
19791f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch               "  try {"
19792f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch               "    return readCell();"
19793f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch               "  } catch(e) {"
19794f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch               "    return e.toString();"
19795f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch               "  }"
19796f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch               "})()",
19797f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch               "ReferenceError: cell is not defined");
19798f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch}
19799f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
19800f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
19801f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochTEST(DontDeleteCellLoadICAPI) {
19802f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  const char* function_code =
19803f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      "function readCell() { while (true) { return cell; } }";
19804f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
19805f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Run the code twice to initialize the load IC for a don't delete
19806f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // cell created using the API.
19807f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  LocalContext context;
19808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(context->GetIsolate());
19809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context->Global()->ForceSet(v8_str("cell"), v8_str("value"), v8::DontDelete);
19810f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  ExpectBoolean("delete cell", false);
19811f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CompileRun(function_code);
19812f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  ExpectString("readCell()", "value");
19813f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  ExpectString("readCell()", "value");
19814f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
19815f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Delete the cell using the API and check the inlined code works
19816f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // correctly.
19817f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CHECK(context->Global()->ForceDelete(v8_str("cell")));
19818f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  ExpectString("(function() {"
19819f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch               "  try {"
19820f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch               "    return readCell();"
19821f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch               "  } catch(e) {"
19822f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch               "    return e.toString();"
19823f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch               "  }"
19824f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch               "})()",
19825f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch               "ReferenceError: cell is not defined");
19826f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch}
19827f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
19828f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
19829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass Visitor42 : public v8::PersistentHandleVisitor {
19830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
19831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  explicit Visitor42(v8::Persistent<v8::Object>* object)
19832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : counter_(0), object_(object) { }
19833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
19834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  virtual void VisitPersistentHandle(Persistent<Value>* value,
19835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                     uint16_t class_id) {
19836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (class_id != 42) return;
19837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(42, value->WrapperClassId());
19838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Isolate* isolate = CcTest::isolate();
19839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope handle_scope(isolate);
19840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Handle<v8::Value> handle = v8::Local<v8::Value>::New(isolate, *value);
19841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Handle<v8::Value> object =
19842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v8::Local<v8::Object>::New(isolate, *object_);
19843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(handle->IsObject());
19844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(Handle<Object>::Cast(handle), object);
19845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ++counter_;
19846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
19847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
19848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int counter_;
19849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Persistent<v8::Object>* object_;
19850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
19851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
19852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
19853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(PersistentHandleVisitor) {
19854f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  LocalContext context;
19855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
19856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
19857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Persistent<v8::Object> object(isolate, v8::Object::New(isolate));
19858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, object.WrapperClassId());
19859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  object.SetWrapperClassId(42);
19860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(42, object.WrapperClassId());
19861f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
19862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Visitor42 visitor(&object);
19863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::V8::VisitHandlesWithClassIds(&visitor);
19864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1, visitor.counter_);
19865f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
19866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  object.Reset();
19867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
19868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
19869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
19870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(WrapperClassId) {
19871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
19872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
19873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
19874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Persistent<v8::Object> object(isolate, v8::Object::New(isolate));
19875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, object.WrapperClassId());
19876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  object.SetWrapperClassId(65535);
19877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(65535, object.WrapperClassId());
19878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  object.Reset();
19879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
19880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
19881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
19882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(PersistentHandleInNewSpaceVisitor) {
19883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
19884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
19885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
19886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Persistent<v8::Object> object1(isolate, v8::Object::New(isolate));
19887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, object1.WrapperClassId());
19888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  object1.SetWrapperClassId(42);
19889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(42, object1.WrapperClassId());
19890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
19891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
19892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
19893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
19894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Persistent<v8::Object> object2(isolate, v8::Object::New(isolate));
19895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, object2.WrapperClassId());
19896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  object2.SetWrapperClassId(42);
19897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(42, object2.WrapperClassId());
19898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
19899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Visitor42 visitor(&object2);
19900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::V8::VisitHandlesForPartialDependence(isolate, &visitor);
19901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1, visitor.counter_);
19902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
19903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  object1.Reset();
19904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  object2.Reset();
19905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
19906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
19907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
19908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(RegExp) {
19909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
19910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(context->GetIsolate());
19911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
19912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::RegExp> re = v8::RegExp::New(v8_str("foo"), v8::RegExp::kNone);
19913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(re->IsRegExp());
19914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(re->GetSource()->Equals(v8_str("foo")));
19915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
19916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
19917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  re = v8::RegExp::New(v8_str("bar"),
19918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
19919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                      v8::RegExp::kGlobal));
19920f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CHECK(re->IsRegExp());
19921f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CHECK(re->GetSource()->Equals(v8_str("bar")));
1992269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kGlobal,
1992369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch           static_cast<int>(re->GetFlags()));
19924f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
19925f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  re = v8::RegExp::New(v8_str("baz"),
19926f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch                       static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
19927f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch                                                      v8::RegExp::kMultiline));
19928f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CHECK(re->IsRegExp());
19929f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CHECK(re->GetSource()->Equals(v8_str("baz")));
1993069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
1993169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch           static_cast<int>(re->GetFlags()));
19932f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
19933f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  re = CompileRun("/quux/").As<v8::RegExp>();
19934f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CHECK(re->IsRegExp());
19935f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CHECK(re->GetSource()->Equals(v8_str("quux")));
1993669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
19937f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
19938f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  re = CompileRun("/quux/gm").As<v8::RegExp>();
19939f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CHECK(re->IsRegExp());
19940f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CHECK(re->GetSource()->Equals(v8_str("quux")));
1994169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK_EQ(v8::RegExp::kGlobal | v8::RegExp::kMultiline,
1994269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch           static_cast<int>(re->GetFlags()));
19943f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
19944f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Override the RegExp constructor and check the API constructor
19945f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // still works.
19946f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CompileRun("RegExp = function() {}");
19947f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
19948f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  re = v8::RegExp::New(v8_str("foobar"), v8::RegExp::kNone);
19949f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CHECK(re->IsRegExp());
19950f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CHECK(re->GetSource()->Equals(v8_str("foobar")));
1995169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
19952f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
19953f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  re = v8::RegExp::New(v8_str("foobarbaz"),
19954f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch                       static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
19955f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch                                                      v8::RegExp::kMultiline));
19956f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CHECK(re->IsRegExp());
19957f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CHECK(re->GetSource()->Equals(v8_str("foobarbaz")));
1995869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
1995969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch           static_cast<int>(re->GetFlags()));
19960f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
19961f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  context->Global()->Set(v8_str("re"), re);
19962f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  ExpectTrue("re.test('FoobarbaZ')");
19963f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
19964257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // RegExps are objects on which you can set properties.
19965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  re->Set(v8_str("property"), v8::Integer::New(context->GetIsolate(), 32));
199663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::Handle<v8::Value> value(CompileRun("re.property"));
199673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(32, value->Int32Value());
19968257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
19969f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  v8::TryCatch try_catch;
19970f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  re = v8::RegExp::New(v8_str("foo["), v8::RegExp::kNone);
19971f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CHECK(re.IsEmpty());
19972f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CHECK(try_catch.HasCaught());
19973f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  context->Global()->Set(v8_str("ex"), try_catch.Exception());
19974f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  ExpectTrue("ex instanceof SyntaxError");
19975f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch}
19976f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
19977f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
199781e0659c275bb392c045087af4f6b0d7565cb3d77Steve BlockTHREADED_TEST(Equals) {
199791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  LocalContext localContext;
19980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handleScope(localContext->GetIsolate());
199811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
199821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  v8::Handle<v8::Object> globalProxy = localContext->Global();
199831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  v8::Handle<Value> global = globalProxy->GetPrototype();
199841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
199851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  CHECK(global->StrictEquals(global));
199861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  CHECK(!global->StrictEquals(globalProxy));
199871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  CHECK(!globalProxy->StrictEquals(global));
199881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  CHECK(globalProxy->StrictEquals(globalProxy));
199891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
199901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  CHECK(global->Equals(global));
199911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  CHECK(!global->Equals(globalProxy));
199921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  CHECK(!globalProxy->Equals(global));
199931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  CHECK(globalProxy->Equals(globalProxy));
199941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
199951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
199961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
19997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void Getter(v8::Local<v8::String> property,
19998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   const v8::PropertyCallbackInfo<v8::Value>& info ) {
19999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(v8_str("42!"));
20000f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch}
20001f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
20002f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
20003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void Enumerator(const v8::PropertyCallbackInfo<v8::Array>& info) {
20004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Array> result = v8::Array::New(info.GetIsolate());
20005f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  result->Set(0, v8_str("universalAnswer"));
20006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(result);
20007f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch}
20008f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
20009f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
20010f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochTEST(NamedEnumeratorAndForIn) {
20011f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  LocalContext context;
20012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
20013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(isolate);
20014f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  v8::Context::Scope context_scope(context.local());
20015f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
20016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> tmpl = v8::ObjectTemplate::New(isolate);
20017f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  tmpl->SetNamedPropertyHandler(Getter, NULL, NULL, NULL, Enumerator);
20018f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  context->Global()->Set(v8_str("o"), tmpl->NewInstance());
20019f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
20020f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch        "var result = []; for (var k in o) result.push(k); result"));
20021f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CHECK_EQ(1, result->Length());
20022f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CHECK_EQ(v8_str("universalAnswer"), result->Get(0));
20023f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch}
200241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
200251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
200261e0659c275bb392c045087af4f6b0d7565cb3d77Steve BlockTEST(DefinePropertyPostDetach) {
200271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  LocalContext context;
20028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(context->GetIsolate());
200291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  v8::Handle<v8::Object> proxy = context->Global();
200301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  v8::Handle<v8::Function> define_property =
200311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      CompileRun("(function() {"
200321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                 "  Object.defineProperty("
200331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                 "    this,"
200341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                 "    1,"
200351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                 "    { configurable: true, enumerable: true, value: 3 });"
200361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                 "})").As<Function>();
200371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  context->DetachGlobal();
200381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  define_property->Call(proxy, 0, NULL);
200391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
200408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
200418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
200428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochstatic void InstallContextId(v8::Handle<Context> context, int id) {
200438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Context::Scope scope(context);
200448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CompileRun("Object.prototype").As<Object>()->
20045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Set(v8_str("context_id"), v8::Integer::New(context->GetIsolate(), id));
200468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}
200478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
200488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
200498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochstatic void CheckContextId(v8::Handle<Object> object, int expected) {
200508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK_EQ(expected, object->Get(v8_str("context_id"))->Int32Value());
200518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}
200528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
200538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
200548b112d2025046f85ef7f6be087c6129c872ebad2Ben MurdochTHREADED_TEST(CreationContext) {
20055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
20056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HandleScope handle_scope(isolate);
20057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Context> context1 = Context::New(isolate);
200588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  InstallContextId(context1, 1);
20059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Context> context2 = Context::New(isolate);
200608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  InstallContextId(context2, 2);
20061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Context> context3 = Context::New(isolate);
200628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  InstallContextId(context3, 3);
200638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
20064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::FunctionTemplate> tmpl = v8::FunctionTemplate::New(isolate);
200658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
200668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Local<Object> object1;
200678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Local<Function> func1;
200688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  {
200698b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    Context::Scope scope(context1);
20070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    object1 = Object::New(isolate);
200718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    func1 = tmpl->GetFunction();
200728b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
200738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
200748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Local<Object> object2;
200758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Local<Function> func2;
200768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  {
200778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    Context::Scope scope(context2);
20078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    object2 = Object::New(isolate);
200798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    func2 = tmpl->GetFunction();
200808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
200818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
200828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Local<Object> instance1;
200838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Local<Object> instance2;
200848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
200858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  {
200868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    Context::Scope scope(context3);
200878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    instance1 = func1->NewInstance();
200888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    instance2 = func2->NewInstance();
200898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
200908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
200918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK(object1->CreationContext() == context1);
200928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CheckContextId(object1, 1);
200938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK(func1->CreationContext() == context1);
200948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CheckContextId(func1, 1);
200958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK(instance1->CreationContext() == context1);
200968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CheckContextId(instance1, 1);
200978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK(object2->CreationContext() == context2);
200988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CheckContextId(object2, 2);
200998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK(func2->CreationContext() == context2);
201008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CheckContextId(func2, 2);
201018b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK(instance2->CreationContext() == context2);
201028b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CheckContextId(instance2, 2);
201038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
201048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  {
201058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    Context::Scope scope(context1);
201068b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CHECK(object1->CreationContext() == context1);
201078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CheckContextId(object1, 1);
201088b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CHECK(func1->CreationContext() == context1);
201098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CheckContextId(func1, 1);
201108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CHECK(instance1->CreationContext() == context1);
201118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CheckContextId(instance1, 1);
201128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CHECK(object2->CreationContext() == context2);
201138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CheckContextId(object2, 2);
201148b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CHECK(func2->CreationContext() == context2);
201158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CheckContextId(func2, 2);
201168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CHECK(instance2->CreationContext() == context2);
201178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CheckContextId(instance2, 2);
201188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
201198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
201208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  {
201218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    Context::Scope scope(context2);
201228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CHECK(object1->CreationContext() == context1);
201238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CheckContextId(object1, 1);
201248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CHECK(func1->CreationContext() == context1);
201258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CheckContextId(func1, 1);
201268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CHECK(instance1->CreationContext() == context1);
201278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CheckContextId(instance1, 1);
201288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CHECK(object2->CreationContext() == context2);
201298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CheckContextId(object2, 2);
201308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CHECK(func2->CreationContext() == context2);
201318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CheckContextId(func2, 2);
201328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CHECK(instance2->CreationContext() == context2);
201338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CheckContextId(instance2, 2);
201348b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
201358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}
20136257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
20137257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2013869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen MurdochTHREADED_TEST(CreationContextOfJsFunction) {
20139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HandleScope handle_scope(CcTest::isolate());
20140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Context> context = Context::New(CcTest::isolate());
2014169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  InstallContextId(context, 1);
2014269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
2014369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Local<Object> function;
2014469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  {
2014569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    Context::Scope scope(context);
2014669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    function = CompileRun("function foo() {}; foo").As<Object>();
2014769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
2014869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
2014969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK(function->CreationContext() == context);
2015069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CheckContextId(function, 1);
2015169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch}
2015269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
2015369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
20154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HasOwnPropertyIndexedPropertyGetter(
20155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t index,
20156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Value>& info) {
20157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (index == 42) info.GetReturnValue().Set(v8_str("yes"));
20158257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
20159257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
20160257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
20161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HasOwnPropertyNamedPropertyGetter(
20162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<String> property,
20163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Value>& info) {
20164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (property->Equals(v8_str("foo"))) info.GetReturnValue().Set(v8_str("yes"));
20165257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
20166257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
20167257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
20168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HasOwnPropertyIndexedPropertyQuery(
20169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t index, const v8::PropertyCallbackInfo<v8::Integer>& info) {
20170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (index == 42) info.GetReturnValue().Set(1);
20171257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
20172257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
20173257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
20174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HasOwnPropertyNamedPropertyQuery(
20175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<String> property,
20176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Integer>& info) {
20177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (property->Equals(v8_str("foo"))) info.GetReturnValue().Set(1);
20178257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
20179257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
20180257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
20181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HasOwnPropertyNamedPropertyQuery2(
20182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<String> property,
20183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Integer>& info) {
20184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (property->Equals(v8_str("bar"))) info.GetReturnValue().Set(1);
20185257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
20186257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
20187257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
20188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HasOwnPropertyAccessorGetter(
20189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<String> property,
20190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Value>& info) {
20191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(v8_str("yes"));
20192257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
20193257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
20194257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
20195257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochTEST(HasOwnProperty) {
20196257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  LocalContext env;
20197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
20198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
20199257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  { // Check normal properties and defined getters.
20200257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Handle<Value> value = CompileRun(
20201257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        "function Foo() {"
20202257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        "    this.foo = 11;"
20203257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        "    this.__defineGetter__('baz', function() { return 1; });"
20204257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        "};"
20205257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        "function Bar() { "
20206257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        "    this.bar = 13;"
20207257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        "    this.__defineGetter__('bla', function() { return 2; });"
20208257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        "};"
20209257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        "Bar.prototype = new Foo();"
20210257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        "new Bar();");
20211257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(value->IsObject());
20212257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Handle<Object> object = value->ToObject();
20213257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(object->Has(v8_str("foo")));
20214257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(!object->HasOwnProperty(v8_str("foo")));
20215257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(object->HasOwnProperty(v8_str("bar")));
20216257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(object->Has(v8_str("baz")));
20217257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(!object->HasOwnProperty(v8_str("baz")));
20218257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(object->HasOwnProperty(v8_str("bla")));
20219257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
20220257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  { // Check named getter interceptors.
20221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
20222257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    templ->SetNamedPropertyHandler(HasOwnPropertyNamedPropertyGetter);
20223257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Handle<Object> instance = templ->NewInstance();
20224257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(!instance->HasOwnProperty(v8_str("42")));
20225257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(instance->HasOwnProperty(v8_str("foo")));
20226257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(!instance->HasOwnProperty(v8_str("bar")));
20227257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
20228257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  { // Check indexed getter interceptors.
20229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
20230257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    templ->SetIndexedPropertyHandler(HasOwnPropertyIndexedPropertyGetter);
20231257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Handle<Object> instance = templ->NewInstance();
20232257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(instance->HasOwnProperty(v8_str("42")));
20233257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(!instance->HasOwnProperty(v8_str("43")));
20234257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(!instance->HasOwnProperty(v8_str("foo")));
20235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
20236257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  { // Check named query interceptors.
20237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
20238257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    templ->SetNamedPropertyHandler(0, 0, HasOwnPropertyNamedPropertyQuery);
20239257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Handle<Object> instance = templ->NewInstance();
20240257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(instance->HasOwnProperty(v8_str("foo")));
20241257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(!instance->HasOwnProperty(v8_str("bar")));
20242257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
20243257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  { // Check indexed query interceptors.
20244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
20245257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    templ->SetIndexedPropertyHandler(0, 0, HasOwnPropertyIndexedPropertyQuery);
20246257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Handle<Object> instance = templ->NewInstance();
20247257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(instance->HasOwnProperty(v8_str("42")));
20248257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(!instance->HasOwnProperty(v8_str("41")));
20249257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
20250257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  { // Check callbacks.
20251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
20252257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    templ->SetAccessor(v8_str("foo"), HasOwnPropertyAccessorGetter);
20253257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Handle<Object> instance = templ->NewInstance();
20254257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(instance->HasOwnProperty(v8_str("foo")));
20255257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(!instance->HasOwnProperty(v8_str("bar")));
20256257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
20257257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  { // Check that query wins on disagreement.
20258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
20259257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    templ->SetNamedPropertyHandler(HasOwnPropertyNamedPropertyGetter,
20260257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                   0,
20261257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                   HasOwnPropertyNamedPropertyQuery2);
20262257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Handle<Object> instance = templ->NewInstance();
20263257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(!instance->HasOwnProperty(v8_str("foo")));
20264257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK(instance->HasOwnProperty(v8_str("bar")));
20265257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
20266257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
20267257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
20268257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
20269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(IndexedInterceptorWithStringProto) {
20270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
20271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
20272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
20273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  templ->SetIndexedPropertyHandler(NULL,
20274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   NULL,
20275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   HasOwnPropertyIndexedPropertyQuery);
20276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
20277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context->Global()->Set(v8_str("obj"), templ->NewInstance());
20278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("var s = new String('foobar'); obj.__proto__ = s;");
20279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // These should be intercepted.
20280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(CompileRun("42 in obj")->BooleanValue());
20281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(CompileRun("'42' in obj")->BooleanValue());
20282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // These should fall through to the String prototype.
20283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(CompileRun("0 in obj")->BooleanValue());
20284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(CompileRun("'0' in obj")->BooleanValue());
20285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // And these should both fail.
20286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!CompileRun("32 in obj")->BooleanValue());
20287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!CompileRun("'32' in obj")->BooleanValue());
20288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
20289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
20290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
20291257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid CheckCodeGenerationAllowed() {
20292257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Value> result = CompileRun("eval('42')");
20293257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_EQ(42, result->Int32Value());
20294257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  result = CompileRun("(function(e) { return e('42'); })(eval)");
20295257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_EQ(42, result->Int32Value());
20296257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  result = CompileRun("var f = new Function('return 42'); f()");
20297257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_EQ(42, result->Int32Value());
20298257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
20299257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
20300257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
20301257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid CheckCodeGenerationDisallowed() {
20302257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  TryCatch try_catch;
20303257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
20304257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Value> result = CompileRun("eval('42')");
20305257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK(result.IsEmpty());
20306257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK(try_catch.HasCaught());
20307257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  try_catch.Reset();
20308257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
20309257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  result = CompileRun("(function(e) { return e('42'); })(eval)");
20310257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK(result.IsEmpty());
20311257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK(try_catch.HasCaught());
20312257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  try_catch.Reset();
20313257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
20314257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  result = CompileRun("var f = new Function('return 42'); f()");
20315257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK(result.IsEmpty());
20316257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK(try_catch.HasCaught());
20317257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
20318257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
20319257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
20320257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochbool CodeGenerationAllowed(Local<Context> context) {
20321257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ApiTestFuzzer::Fuzz();
20322257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return true;
20323257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
20324257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
20325257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
20326257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochbool CodeGenerationDisallowed(Local<Context> context) {
20327257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ApiTestFuzzer::Fuzz();
20328257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return false;
20329257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
20330257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
20331257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
20332257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochTHREADED_TEST(AllowCodeGenFromStrings) {
20333257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  LocalContext context;
20334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(context->GetIsolate());
20335257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
20336257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // eval and the Function constructor allowed by default.
203373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(context->IsCodeGenerationFromStringsAllowed());
20338257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CheckCodeGenerationAllowed();
20339257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
20340257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Disallow eval and the Function constructor.
20341257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  context->AllowCodeGenerationFromStrings(false);
203423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(!context->IsCodeGenerationFromStringsAllowed());
20343257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CheckCodeGenerationDisallowed();
20344257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
20345257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Allow again.
20346257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  context->AllowCodeGenerationFromStrings(true);
20347257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CheckCodeGenerationAllowed();
20348257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
20349257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Disallow but setting a global callback that will allow the calls.
20350257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  context->AllowCodeGenerationFromStrings(false);
20351257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationAllowed);
203523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(!context->IsCodeGenerationFromStringsAllowed());
20353257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CheckCodeGenerationAllowed();
20354257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
20355257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Set a callback that disallows the code generation.
20356257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationDisallowed);
203573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(!context->IsCodeGenerationFromStringsAllowed());
20358257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CheckCodeGenerationDisallowed();
20359257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
20360257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
20361257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
20362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(SetErrorMessageForCodeGenFromStrings) {
20363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
20364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(context->GetIsolate());
20365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TryCatch try_catch;
20366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
20367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<String> message = v8_str("Message") ;
20368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<String> expected_message = v8_str("Uncaught EvalError: Message");
20369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationDisallowed);
20370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context->AllowCodeGenerationFromStrings(false);
20371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context->SetErrorMessageForCodeGenerationFromStrings(message);
20372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Value> result = CompileRun("eval('42')");
20373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(result.IsEmpty());
20374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(try_catch.HasCaught());
20375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<String> actual_message = try_catch.Message()->Get();
20376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(expected_message->Equals(actual_message));
20377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
20378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
20379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
20380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void NonObjectThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
20381257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
20382257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
20383257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
20384257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochTHREADED_TEST(CallAPIFunctionOnNonObject) {
20385257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  LocalContext context;
20386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
20387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
20388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<FunctionTemplate> templ =
20389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::FunctionTemplate::New(isolate, NonObjectThis);
20390257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Function> function = templ->GetFunction();
20391257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  context->Global()->Set(v8_str("f"), function);
20392257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  TryCatch try_catch;
20393257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CompileRun("f.call(2)");
20394257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
203953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
203963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
203973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch// Regression test for issue 1470.
203983fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochTHREADED_TEST(ReadOnlyIndexedProperties) {
20399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
20400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
20401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
204023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
204033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  LocalContext context;
204043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Local<v8::Object> obj = templ->NewInstance();
204053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  context->Global()->Set(v8_str("obj"), obj);
20406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  obj->ForceSet(v8_str("1"), v8_str("DONT_CHANGE"), v8::ReadOnly);
204073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  obj->Set(v8_str("1"), v8_str("foobar"));
204083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK_EQ(v8_str("DONT_CHANGE"), obj->Get(v8_str("1")));
20409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  obj->ForceSet(v8_num(2), v8_str("DONT_CHANGE"), v8::ReadOnly);
204103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  obj->Set(v8_num(2), v8_str("foobar"));
204113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK_EQ(v8_str("DONT_CHANGE"), obj->Get(v8_num(2)));
204123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
204133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Test non-smi case.
20414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  obj->ForceSet(v8_str("2000000000"), v8_str("DONT_CHANGE"), v8::ReadOnly);
204153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  obj->Set(v8_str("2000000000"), v8_str("foobar"));
204163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK_EQ(v8_str("DONT_CHANGE"), obj->Get(v8_str("2000000000")));
204173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
204183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
204193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
204203fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochTHREADED_TEST(Regress1516) {
204213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  LocalContext context;
20422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(context->GetIsolate());
20423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
20424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  { v8::HandleScope temp_scope(context->GetIsolate());
204253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    CompileRun("({'a': 0})");
204263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
204273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
204283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int elements;
204293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  { i::MapCache* map_cache =
20430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        i::MapCache::cast(CcTest::i_isolate()->context()->map_cache());
204313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    elements = map_cache->NumberOfElements();
204323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    CHECK_LE(1, elements);
204333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
204343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
20435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(
20436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      i::Heap::kAbortIncrementalMarkingMask);
20437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  { i::Object* raw_map_cache = CcTest::i_isolate()->context()->map_cache();
20438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (raw_map_cache != CcTest::heap()->undefined_value()) {
204393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      i::MapCache* map_cache = i::MapCache::cast(raw_map_cache);
204403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      CHECK_GT(elements, map_cache->NumberOfElements());
204413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
204423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
204433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
204443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
204453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
204463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochstatic bool BlockProtoNamedSecurityTestCallback(Local<v8::Object> global,
204473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                Local<Value> name,
204483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                v8::AccessType type,
204493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                Local<Value> data) {
204503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Only block read access to __proto__.
204513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (type == v8::ACCESS_GET &&
204523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      name->IsString() &&
204533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      name->ToString()->Length() == 9 &&
204543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      name->ToString()->Utf8Length() == 9) {
204553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    char buffer[10];
204563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    CHECK_EQ(10, name->ToString()->WriteUtf8(buffer));
204573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return strncmp(buffer, "__proto__", 9) != 0;
204583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
204593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
204603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return true;
204613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
204623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
204633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
204643fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochTHREADED_TEST(Regress93759) {
20465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
20466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HandleScope scope(isolate);
204673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
204683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Template for object with security check.
20469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> no_proto_template = v8::ObjectTemplate::New(isolate);
204703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // We don't do indexing, so any callback can be used for that.
204713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  no_proto_template->SetAccessCheckCallbacks(
204723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      BlockProtoNamedSecurityTestCallback,
204733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      IndexedSecurityTestCallback);
204743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
204753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Templates for objects with hidden prototypes and possibly security check.
20476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<FunctionTemplate> hidden_proto_template =
20477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::FunctionTemplate::New(isolate);
204783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  hidden_proto_template->SetHiddenPrototype(true);
204793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
204803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Local<FunctionTemplate> protected_hidden_proto_template =
20481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::FunctionTemplate::New(isolate);
204823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  protected_hidden_proto_template->InstanceTemplate()->SetAccessCheckCallbacks(
204833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      BlockProtoNamedSecurityTestCallback,
204843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      IndexedSecurityTestCallback);
204853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  protected_hidden_proto_template->SetHiddenPrototype(true);
204863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
204873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Context for "foreign" objects used in test.
20488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Context> context = v8::Context::New(isolate);
204893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  context->Enter();
204903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
204913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Plain object, no security check.
20492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Object> simple_object = Object::New(isolate);
204933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
204943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Object with explicit security check.
204953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Local<Object> protected_object =
204963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      no_proto_template->NewInstance();
204973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
204983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // JSGlobalProxy object, always have security check.
204993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Local<Object> proxy_object =
205003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      context->Global();
205013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
205023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Global object, the  prototype of proxy_object. No security checks.
205033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Local<Object> global_object =
205043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      proxy_object->GetPrototype()->ToObject();
205053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
205063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Hidden prototype without security check.
205073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Local<Object> hidden_prototype =
205083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      hidden_proto_template->GetFunction()->NewInstance();
205093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Local<Object> object_with_hidden =
20510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Object::New(isolate);
205113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  object_with_hidden->SetPrototype(hidden_prototype);
205123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
205133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Hidden prototype with security check on the hidden prototype.
205143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Local<Object> protected_hidden_prototype =
205153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      protected_hidden_proto_template->GetFunction()->NewInstance();
205163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Local<Object> object_with_protected_hidden =
20517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Object::New(isolate);
205183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  object_with_protected_hidden->SetPrototype(protected_hidden_prototype);
205193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
205203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  context->Exit();
205213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
205223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Template for object for second context. Values to test are put on it as
205233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // properties.
20524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
205253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  global_template->Set(v8_str("simple"), simple_object);
205263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  global_template->Set(v8_str("protected"), protected_object);
205273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  global_template->Set(v8_str("global"), global_object);
205283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  global_template->Set(v8_str("proxy"), proxy_object);
205293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  global_template->Set(v8_str("hidden"), object_with_hidden);
205303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  global_template->Set(v8_str("phidden"), object_with_protected_hidden);
205313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
205323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  LocalContext context2(NULL, global_template);
205333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
205343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Local<Value> result1 = CompileRun("Object.getPrototypeOf(simple)");
205353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK(result1->Equals(simple_object->GetPrototype()));
205363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
205373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Local<Value> result2 = CompileRun("Object.getPrototypeOf(protected)");
20538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(result2.IsEmpty());
205393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
205403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Local<Value> result3 = CompileRun("Object.getPrototypeOf(global)");
205413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK(result3->Equals(global_object->GetPrototype()));
205423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
205433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Local<Value> result4 = CompileRun("Object.getPrototypeOf(proxy)");
20544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(result4.IsEmpty());
205453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
205463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Local<Value> result5 = CompileRun("Object.getPrototypeOf(hidden)");
205473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK(result5->Equals(
205483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      object_with_hidden->GetPrototype()->ToObject()->GetPrototype()));
205493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
205503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Local<Value> result6 = CompileRun("Object.getPrototypeOf(phidden)");
20551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(result6.IsEmpty());
205523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
2055369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
2055469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
205555710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben MurdochTHREADED_TEST(Regress125988) {
20556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(CcTest::isolate());
20557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<FunctionTemplate> intercept = FunctionTemplate::New(CcTest::isolate());
205585710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch  AddInterceptor(intercept, EmptyInterceptorGetter, EmptyInterceptorSetter);
205595710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch  LocalContext env;
205605710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch  env->Global()->Set(v8_str("Intercept"), intercept->GetFunction());
205615710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch  CompileRun("var a = new Object();"
205625710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch             "var b = new Intercept();"
205635710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch             "var c = new Object();"
205645710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch             "c.__proto__ = b;"
205655710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch             "b.__proto__ = a;"
205665710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch             "a.x = 23;"
205675710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch             "for (var i = 0; i < 3; i++) c.x;");
205685710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch  ExpectBoolean("c.hasOwnProperty('x')", false);
205695710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch  ExpectInt32("c.x", 23);
205705710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch  CompileRun("a.y = 42;"
205715710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch             "for (var i = 0; i < 3; i++) c.x;");
205725710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch  ExpectBoolean("c.hasOwnProperty('x')", false);
205735710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch  ExpectInt32("c.x", 23);
205745710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch  ExpectBoolean("c.hasOwnProperty('y')", false);
205755710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch  ExpectInt32("c.y", 42);
205765710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch}
205775710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch
205785710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch
2057969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochstatic void TestReceiver(Local<Value> expected_result,
2058069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                         Local<Value> expected_receiver,
2058169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                         const char* code) {
2058269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Local<Value> result = CompileRun(code);
2058369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK(result->IsObject());
2058469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK(expected_receiver->Equals(result->ToObject()->Get(1)));
2058569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK(expected_result->Equals(result->ToObject()->Get(0)));
2058669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch}
2058769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
2058869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
2058969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen MurdochTHREADED_TEST(ForeignFunctionReceiver) {
20590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
20591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HandleScope scope(isolate);
2059269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
2059369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Create two contexts with different "id" properties ('i' and 'o').
2059469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Call a function both from its own context and from a the foreign
2059569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // context, and see what "this" is bound to (returning both "this"
2059669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // and "this.id" for comparison).
2059769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
20598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Context> foreign_context = v8::Context::New(isolate);
2059969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  foreign_context->Enter();
2060069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Local<Value> foreign_function =
2060169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    CompileRun("function func() { return { 0: this.id, "
2060269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch               "                           1: this, "
2060369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch               "                           toString: function() { "
2060469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch               "                               return this[0];"
2060569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch               "                           }"
2060669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch               "                         };"
2060769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch               "}"
2060869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch               "var id = 'i';"
2060969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch               "func;");
2061069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK(foreign_function->IsFunction());
2061169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  foreign_context->Exit();
2061269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
2061369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  LocalContext context;
2061469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
2061569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Local<String> password = v8_str("Password");
2061669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Don't get hit by security checks when accessing foreign_context's
2061769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // global receiver (aka. global proxy).
2061869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  context->SetSecurityToken(password);
2061969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  foreign_context->SetSecurityToken(password);
2062069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
2062169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Local<String> i = v8_str("i");
2062269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Local<String> o = v8_str("o");
2062369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Local<String> id = v8_str("id");
2062469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
2062569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CompileRun("function ownfunc() { return { 0: this.id, "
2062669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch             "                              1: this, "
2062769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch             "                              toString: function() { "
2062869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch             "                                  return this[0];"
2062969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch             "                              }"
2063069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch             "                             };"
2063169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch             "}"
2063269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch             "var id = 'o';"
2063369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch             "ownfunc");
2063469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  context->Global()->Set(v8_str("func"), foreign_function);
2063569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
2063669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Sanity check the contexts.
2063769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK(i->Equals(foreign_context->Global()->Get(id)));
2063869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK(o->Equals(context->Global()->Get(id)));
2063969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
2064069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Checking local function's receiver.
2064169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Calling function using its call/apply methods.
2064269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  TestReceiver(o, context->Global(), "ownfunc.call()");
2064369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  TestReceiver(o, context->Global(), "ownfunc.apply()");
2064469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Making calls through built-in functions.
2064569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  TestReceiver(o, context->Global(), "[1].map(ownfunc)[0]");
2064669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/,ownfunc)[1]")));
2064769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/g,ownfunc)[1]")));
2064869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/g,ownfunc)[3]")));
2064969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Calling with environment record as base.
2065069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  TestReceiver(o, context->Global(), "ownfunc()");
2065169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Calling with no base.
2065269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  TestReceiver(o, context->Global(), "(1,ownfunc)()");
2065369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
2065469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Checking foreign function return value.
2065569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Calling function using its call/apply methods.
2065669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  TestReceiver(i, foreign_context->Global(), "func.call()");
2065769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  TestReceiver(i, foreign_context->Global(), "func.apply()");
2065869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Calling function using another context's call/apply methods.
2065969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  TestReceiver(i, foreign_context->Global(),
2066069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch               "Function.prototype.call.call(func)");
2066169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  TestReceiver(i, foreign_context->Global(),
2066269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch               "Function.prototype.call.apply(func)");
2066369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  TestReceiver(i, foreign_context->Global(),
2066469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch               "Function.prototype.apply.call(func)");
2066569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  TestReceiver(i, foreign_context->Global(),
2066669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch               "Function.prototype.apply.apply(func)");
2066769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Making calls through built-in functions.
2066869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  TestReceiver(i, foreign_context->Global(), "[1].map(func)[0]");
2066969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // ToString(func()) is func()[0], i.e., the returned this.id.
2067069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/,func)[1]")));
2067169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/g,func)[1]")));
2067269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/g,func)[3]")));
2067369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
2067469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Calling with environment record as base.
20675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TestReceiver(i, foreign_context->Global(), "func()");
2067669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Calling with no base.
20677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TestReceiver(i, foreign_context->Global(), "(1,func)()");
2067869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch}
206793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
206803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
206813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochuint8_t callback_fired = 0;
206823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
206833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
206843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallCompletedCallback1() {
20685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::base::OS::Print("Firing callback 1.\n");
206863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  callback_fired ^= 1;  // Toggle first bit.
206873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
206883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
206893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
206903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallCompletedCallback2() {
20691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::base::OS::Print("Firing callback 2.\n");
206923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  callback_fired ^= 2;  // Toggle second bit.
206933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
206943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
206953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
20696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid RecursiveCall(const v8::FunctionCallbackInfo<v8::Value>& args) {
206973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int32_t level = args[0]->Int32Value();
206983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (level < 3) {
206993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    level++;
20700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::base::OS::Print("Entering recursion level %d.\n", level);
207013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    char script[64];
207023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    i::Vector<char> script_vector(script, sizeof(script));
20703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    i::SNPrintF(script_vector, "recursion(%d)", level);
207043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CompileRun(script_vector.start());
20705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::base::OS::Print("Leaving recursion level %d.\n", level);
207063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CHECK_EQ(0, callback_fired);
207073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
20708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::base::OS::Print("Recursion ends.\n");
207093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CHECK_EQ(0, callback_fired);
207103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
207113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
207123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
207133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
207143ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochTEST(CallCompletedCallback) {
207153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LocalContext env;
20716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
207173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::Handle<v8::FunctionTemplate> recursive_runtime =
20718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::FunctionTemplate::New(env->GetIsolate(), RecursiveCall);
207193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  env->Global()->Set(v8_str("recursion"),
207203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     recursive_runtime->GetFunction());
207213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Adding the same callback a second time has no effect.
20722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback1);
20723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback1);
20724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback2);
20725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::base::OS::Print("--- Script (1) ---\n");
20726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Script> script = v8::Script::Compile(
20727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(env->GetIsolate(), "recursion(0)"));
207283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  script->Run();
207293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(3, callback_fired);
207303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
20731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::base::OS::Print("\n--- Script (2) ---\n");
207323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  callback_fired = 0;
20733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->GetIsolate()->RemoveCallCompletedCallback(CallCompletedCallback1);
207343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  script->Run();
207353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(2, callback_fired);
207363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
20737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::base::OS::Print("\n--- Function ---\n");
207383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  callback_fired = 0;
207393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Local<Function> recursive_function =
207403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Local<Function>::Cast(env->Global()->Get(v8_str("recursion")));
207413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::Handle<Value> args[] = { v8_num(0) };
207423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  recursive_function->Call(env->Global(), 1, args);
207433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(2, callback_fired);
207443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
207453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
207463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
207473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallCompletedCallbackNoException() {
20748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(CcTest::isolate());
207493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileRun("1+1;");
207503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
207513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
207523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
207533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallCompletedCallbackException() {
20754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(CcTest::isolate());
207553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileRun("throw 'second exception';");
207563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
207573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
207583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
207593ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochTEST(CallCompletedCallbackOneException) {
207603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LocalContext env;
20761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
20762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallbackNoException);
207633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileRun("throw 'exception';");
207643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
207653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
207663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
207673ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochTEST(CallCompletedCallbackTwoExceptions) {
207683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LocalContext env;
20769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
20770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallbackException);
207713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileRun("throw 'first exception';");
207723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
207733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
207743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
20775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void MicrotaskOne(const v8::FunctionCallbackInfo<Value>& info) {
20776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(info.GetIsolate());
20777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("ext1Calls++;");
20778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
20779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
20780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
20781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void MicrotaskTwo(const v8::FunctionCallbackInfo<Value>& info) {
20782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(info.GetIsolate());
20783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("ext2Calls++;");
20784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
20785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
20786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
20787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid* g_passed_to_three = NULL;
20788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
20789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
20790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void MicrotaskThree(void* data) {
20791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  g_passed_to_three = data;
20792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
20793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
20794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
20795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(EnqueueMicrotask) {
20796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
20797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
20798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun(
20799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "var ext1Calls = 0;"
20800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "var ext2Calls = 0;");
20801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("1+1;");
20802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value());
20803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value());
20804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
20805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->GetIsolate()->EnqueueMicrotask(
20806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Function::New(env->GetIsolate(), MicrotaskOne));
20807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("1+1;");
20808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value());
20809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value());
20810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
20811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->GetIsolate()->EnqueueMicrotask(
20812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Function::New(env->GetIsolate(), MicrotaskOne));
20813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->GetIsolate()->EnqueueMicrotask(
20814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Function::New(env->GetIsolate(), MicrotaskTwo));
20815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("1+1;");
20816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
20817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value());
20818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
20819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->GetIsolate()->EnqueueMicrotask(
20820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Function::New(env->GetIsolate(), MicrotaskTwo));
20821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("1+1;");
20822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
20823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value());
20824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
20825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("1+1;");
20826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
20827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value());
20828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
20829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  g_passed_to_three = NULL;
20830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->GetIsolate()->EnqueueMicrotask(MicrotaskThree);
20831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("1+1;");
20832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(NULL, g_passed_to_three);
20833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
20834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value());
20835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
20836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int dummy;
20837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->GetIsolate()->EnqueueMicrotask(
20838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Function::New(env->GetIsolate(), MicrotaskOne));
20839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->GetIsolate()->EnqueueMicrotask(MicrotaskThree, &dummy);
20840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->GetIsolate()->EnqueueMicrotask(
20841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Function::New(env->GetIsolate(), MicrotaskTwo));
20842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("1+1;");
20843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(&dummy, g_passed_to_three);
20844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(3, CompileRun("ext1Calls")->Int32Value());
20845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value());
20846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  g_passed_to_three = NULL;
20847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
20848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
20849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
20850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void MicrotaskExceptionOne(
20851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::FunctionCallbackInfo<Value>& info) {
20852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(info.GetIsolate());
20853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("exception1Calls++;");
20854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetIsolate()->ThrowException(
20855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Exception::Error(v8_str("first")));
20856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
20857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
20858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
20859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void MicrotaskExceptionTwo(
20860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::FunctionCallbackInfo<Value>& info) {
20861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(info.GetIsolate());
20862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("exception2Calls++;");
20863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetIsolate()->ThrowException(
20864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Exception::Error(v8_str("second")));
20865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
20866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
20867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
20868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(RunMicrotasksIgnoresThrownExceptions) {
20869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
20870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
20871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
20872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun(
20873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "var exception1Calls = 0;"
20874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "var exception2Calls = 0;");
20875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate->EnqueueMicrotask(
20876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Function::New(isolate, MicrotaskExceptionOne));
20877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate->EnqueueMicrotask(
20878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Function::New(isolate, MicrotaskExceptionTwo));
20879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TryCatch try_catch;
20880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("1+1;");
20881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!try_catch.HasCaught());
20882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1, CompileRun("exception1Calls")->Int32Value());
20883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1, CompileRun("exception2Calls")->Int32Value());
20884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
20885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
20886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
20887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(SetAutorunMicrotasks) {
20888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
20889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
20890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun(
20891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "var ext1Calls = 0;"
20892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "var ext2Calls = 0;");
20893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("1+1;");
20894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value());
20895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value());
20896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
20897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->GetIsolate()->EnqueueMicrotask(
20898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Function::New(env->GetIsolate(), MicrotaskOne));
20899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("1+1;");
20900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value());
20901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value());
20902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
20903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->GetIsolate()->SetAutorunMicrotasks(false);
20904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->GetIsolate()->EnqueueMicrotask(
20905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Function::New(env->GetIsolate(), MicrotaskOne));
20906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->GetIsolate()->EnqueueMicrotask(
20907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Function::New(env->GetIsolate(), MicrotaskTwo));
20908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("1+1;");
20909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value());
20910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value());
20911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
20912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->GetIsolate()->RunMicrotasks();
20913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
20914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value());
20915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
20916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->GetIsolate()->EnqueueMicrotask(
20917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Function::New(env->GetIsolate(), MicrotaskTwo));
20918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("1+1;");
20919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
20920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value());
20921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
20922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->GetIsolate()->RunMicrotasks();
20923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
20924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value());
20925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
20926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->GetIsolate()->SetAutorunMicrotasks(true);
20927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->GetIsolate()->EnqueueMicrotask(
20928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Function::New(env->GetIsolate(), MicrotaskTwo));
20929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("1+1;");
20930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
20931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value());
20932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
20933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->GetIsolate()->EnqueueMicrotask(
20934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Function::New(env->GetIsolate(), MicrotaskTwo));
20935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
20936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Isolate::SuppressMicrotaskExecutionScope scope(env->GetIsolate());
20937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CompileRun("1+1;");
20938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
20939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value());
20940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
20941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
20942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("1+1;");
20943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
20944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(4, CompileRun("ext2Calls")->Int32Value());
20945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
20946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
20947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
20948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(RunMicrotasksWithoutEnteringContext) {
20949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
20950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HandleScope handle_scope(isolate);
20951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate->SetAutorunMicrotasks(false);
20952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Context> context = Context::New(isolate);
20953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
20954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Context::Scope context_scope(context);
20955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CompileRun("var ext1Calls = 0;");
20956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    isolate->EnqueueMicrotask(Function::New(isolate, MicrotaskOne));
20957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
20958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate->RunMicrotasks();
20959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
20960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Context::Scope context_scope(context);
20961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value());
20962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
20963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate->SetAutorunMicrotasks(true);
20964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
20965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
20966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
20967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void DebugEventInObserver(const v8::Debug::EventDetails& event_details) {
20968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::DebugEvent event = event_details.GetEvent();
20969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (event != v8::Break) return;
20970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Object> exec_state = event_details.GetExecutionState();
20971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Value> break_id = exec_state->Get(v8_str("break_id"));
20972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("function f(id) { new FrameDetails(id, 0); }");
20973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Function> fun = Handle<Function>::Cast(
20974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CcTest::global()->Get(v8_str("f"))->ToObject());
20975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fun->Call(CcTest::global(), 1, &break_id);
20976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
20977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
20978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
20979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(Regress385349) {
20980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::FLAG_allow_natives_syntax = true;
20981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
20982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HandleScope handle_scope(isolate);
20983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate->SetAutorunMicrotasks(false);
20984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Context> context = Context::New(isolate);
20985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetDebugEventListener(DebugEventInObserver);
20986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
20987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Context::Scope context_scope(context);
20988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CompileRun("var obj = {};"
20989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               "Object.observe(obj, function(changes) { debugger; });"
20990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               "obj.a = 0;");
20991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
20992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate->RunMicrotasks();
20993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate->SetAutorunMicrotasks(true);
20994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetDebugEventListener(NULL);
20995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
20996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
20997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
20998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG
209993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic int probes_counter = 0;
210003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic int misses_counter = 0;
210013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic int updates_counter = 0;
210023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
210033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
210043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic int* LookupCounter(const char* name) {
210053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (strcmp(name, "c:V8.MegamorphicStubCacheProbes") == 0) {
210063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return &probes_counter;
210073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (strcmp(name, "c:V8.MegamorphicStubCacheMisses") == 0) {
210083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return &misses_counter;
210093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (strcmp(name, "c:V8.MegamorphicStubCacheUpdates") == 0) {
210103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return &updates_counter;
210113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
210123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return NULL;
210133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
210143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
210153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
210163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic const char* kMegamorphicTestProgram =
210173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    "function ClassA() { };"
210183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    "function ClassB() { };"
210193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    "ClassA.prototype.foo = function() { };"
210203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    "ClassB.prototype.foo = function() { };"
210213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    "function fooify(obj) { obj.foo(); };"
210223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    "var a = new ClassA();"
210233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    "var b = new ClassB();"
210243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    "for (var i = 0; i < 10000; i++) {"
210253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    "  fooify(a);"
210263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    "  fooify(b);"
210273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    "}";
21028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
210293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
210303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
210313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void StubCacheHelper(bool primary) {
210323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef DEBUG
210333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  i::FLAG_native_code_counters = true;
210343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (primary) {
210353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    i::FLAG_test_primary_stub_cache = true;
210363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
210373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    i::FLAG_test_secondary_stub_cache = true;
210383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
210393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  i::FLAG_crankshaft = false;
210403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LocalContext env;
21041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->GetIsolate()->SetCounterFunction(LookupCounter);
21042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
210433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int initial_probes = probes_counter;
210443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int initial_misses = misses_counter;
210453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int initial_updates = updates_counter;
210463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileRun(kMegamorphicTestProgram);
210473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int probes = probes_counter - initial_probes;
210483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int misses = misses_counter - initial_misses;
210493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int updates = updates_counter - initial_updates;
210503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_LT(updates, 10);
210513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_LT(misses, 10);
21052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // TODO(verwaest): Update this test to overflow the degree of polymorphism
21053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // before megamorphism. The number of probes will only work once we teach the
21054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // serializer to embed references to counters in the stubs, given that the
21055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // megamorphic_stub_cache_probes is updated in a snapshot-generated stub.
21056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_GE(probes, 0);
210573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif
210583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
210593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
210603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
210613ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochTEST(SecondaryStubCache) {
210623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  StubCacheHelper(true);
210633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
210643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
210653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
210663ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochTEST(PrimaryStubCache) {
210673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  StubCacheHelper(false);
210683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
210693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
21070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG
21072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic int cow_arrays_created_runtime = 0;
21073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic int* LookupCounterCOWArrays(const char* name) {
21076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (strcmp(name, "c:V8.COWArraysCreatedRuntime") == 0) {
21077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return &cow_arrays_created_runtime;
21078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
21079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return NULL;
21080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
21081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
21082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(CheckCOWArraysCreatedRuntimeCounter) {
21085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG
21086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::FLAG_native_code_counters = true;
21087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
21088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->GetIsolate()->SetCounterFunction(LookupCounterCOWArrays);
21089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
21090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int initial_cow_arrays = cow_arrays_created_runtime;
21091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("var o = [1, 2, 3];");
21092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1, cow_arrays_created_runtime - initial_cow_arrays);
21093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("var o = {foo: [4, 5, 6], bar: [3, 0]};");
21094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(3, cow_arrays_created_runtime - initial_cow_arrays);
21095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("var o = {foo: [1, 2, 3, [4, 5, 6]], bar: 'hi'};");
21096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(4, cow_arrays_created_runtime - initial_cow_arrays);
21097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
21098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
21099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(StaticGetters) {
21102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
21103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::Factory* factory = CcTest::i_isolate()->factory();
21104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
21105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
21106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::Handle<i::Object> undefined_value = factory->undefined_value();
21107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(*v8::Utils::OpenHandle(*v8::Undefined(isolate)) == *undefined_value);
21108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::Handle<i::Object> null_value = factory->null_value();
21109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(*v8::Utils::OpenHandle(*v8::Null(isolate)) == *null_value);
21110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::Handle<i::Object> true_value = factory->true_value();
21111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(*v8::Utils::OpenHandle(*v8::True(isolate)) == *true_value);
21112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::Handle<i::Object> false_value = factory->false_value();
21113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(*v8::Utils::OpenHandle(*v8::False(isolate)) == *false_value);
21114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
21115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochUNINITIALIZED_TEST(IsolateEmbedderData) {
21118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::DisableAutomaticDispose();
21119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = v8::Isolate::New();
21120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate->Enter();
21121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
21122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
21123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(NULL, isolate->GetData(slot));
21124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(NULL, i_isolate->GetData(slot));
21125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
21126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
21127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    void* data = reinterpret_cast<void*>(0xacce55ed + slot);
21128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    isolate->SetData(slot, data);
21129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
21130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
21131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    void* data = reinterpret_cast<void*>(0xacce55ed + slot);
21132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(data, isolate->GetData(slot));
21133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(data, i_isolate->GetData(slot));
21134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
21135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
21136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    void* data = reinterpret_cast<void*>(0xdecea5ed + slot);
21137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    isolate->SetData(slot, data);
21138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
21139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
21140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    void* data = reinterpret_cast<void*>(0xdecea5ed + slot);
21141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(data, isolate->GetData(slot));
21142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(data, i_isolate->GetData(slot));
21143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
21144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate->Exit();
21145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate->Dispose();
21146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
21147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(StringEmpty) {
21150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
21151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::Factory* factory = CcTest::i_isolate()->factory();
21152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
21153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
21154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::Handle<i::Object> empty_string = factory->empty_string();
21155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(*v8::Utils::OpenHandle(*v8::String::Empty(isolate)) == *empty_string);
21156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
21157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic int instance_checked_getter_count = 0;
21160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void InstanceCheckedGetter(
21161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<String> name,
21162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Value>& info) {
21163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(name, v8_str("foo"));
21164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  instance_checked_getter_count++;
21165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(v8_num(11));
21166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
21167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic int instance_checked_setter_count = 0;
21170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void InstanceCheckedSetter(Local<String> name,
21171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      Local<Value> value,
21172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      const v8::PropertyCallbackInfo<void>& info) {
21173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(name, v8_str("foo"));
21174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(value, v8_num(23));
21175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  instance_checked_setter_count++;
21176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
21177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void CheckInstanceCheckedResult(int getters, int setters,
21180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       bool expects_callbacks,
21181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       TryCatch* try_catch) {
21182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (expects_callbacks) {
21183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(!try_catch->HasCaught());
21184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(getters, instance_checked_getter_count);
21185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(setters, instance_checked_setter_count);
21186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
21187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(try_catch->HasCaught());
21188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(0, instance_checked_getter_count);
21189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(0, instance_checked_setter_count);
21190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
21191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  try_catch->Reset();
21192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
21193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void CheckInstanceCheckedAccessors(bool expects_callbacks) {
21196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  instance_checked_getter_count = 0;
21197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  instance_checked_setter_count = 0;
21198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TryCatch try_catch;
21199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Test path through generic runtime code.
21201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("obj.foo");
21202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckInstanceCheckedResult(1, 0, expects_callbacks, &try_catch);
21203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("obj.foo = 23");
21204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckInstanceCheckedResult(1, 1, expects_callbacks, &try_catch);
21205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Test path through generated LoadIC and StoredIC.
21207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("function test_get(o) { o.foo; }"
21208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "test_get(obj);");
21209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckInstanceCheckedResult(2, 1, expects_callbacks, &try_catch);
21210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("test_get(obj);");
21211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckInstanceCheckedResult(3, 1, expects_callbacks, &try_catch);
21212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("test_get(obj);");
21213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckInstanceCheckedResult(4, 1, expects_callbacks, &try_catch);
21214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("function test_set(o) { o.foo = 23; }"
21215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "test_set(obj);");
21216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckInstanceCheckedResult(4, 2, expects_callbacks, &try_catch);
21217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("test_set(obj);");
21218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckInstanceCheckedResult(4, 3, expects_callbacks, &try_catch);
21219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("test_set(obj);");
21220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckInstanceCheckedResult(4, 4, expects_callbacks, &try_catch);
21221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Test path through optimized code.
21223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("%OptimizeFunctionOnNextCall(test_get);"
21224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "test_get(obj);");
21225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckInstanceCheckedResult(5, 4, expects_callbacks, &try_catch);
21226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("%OptimizeFunctionOnNextCall(test_set);"
21227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "test_set(obj);");
21228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckInstanceCheckedResult(5, 5, expects_callbacks, &try_catch);
21229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Cleanup so that closures start out fresh in next check.
21231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("%DeoptimizeFunction(test_get);"
21232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "%ClearFunctionTypeFeedback(test_get);"
21233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "%DeoptimizeFunction(test_set);"
21234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "%ClearFunctionTypeFeedback(test_set);");
21235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
21236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(InstanceCheckOnInstanceAccessor) {
21239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::internal::FLAG_allow_natives_syntax = true;
21240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
21241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(context->GetIsolate());
21242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
21244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> inst = templ->InstanceTemplate();
21245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inst->SetAccessor(v8_str("foo"),
21246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                    InstanceCheckedGetter, InstanceCheckedSetter,
21247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                    Handle<Value>(),
21248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                    v8::DEFAULT,
21249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                    v8::None,
21250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                    v8::AccessorSignature::New(context->GetIsolate(), templ));
21251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context->Global()->Set(v8_str("f"), templ->GetFunction());
21252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  printf("Testing positive ...\n");
21254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("var obj = new f();");
21255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
21256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckInstanceCheckedAccessors(true);
21257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  printf("Testing negative ...\n");
21259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("var obj = {};"
21260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "obj.__proto__ = new f();");
21261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
21262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckInstanceCheckedAccessors(false);
21263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
21264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(InstanceCheckOnInstanceAccessorWithInterceptor) {
21267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::internal::FLAG_allow_natives_syntax = true;
21268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
21269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(context->GetIsolate());
21270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
21272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> inst = templ->InstanceTemplate();
21273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter);
21274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inst->SetAccessor(v8_str("foo"),
21275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                    InstanceCheckedGetter, InstanceCheckedSetter,
21276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                    Handle<Value>(),
21277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                    v8::DEFAULT,
21278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                    v8::None,
21279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                    v8::AccessorSignature::New(context->GetIsolate(), templ));
21280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context->Global()->Set(v8_str("f"), templ->GetFunction());
21281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  printf("Testing positive ...\n");
21283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("var obj = new f();");
21284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
21285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckInstanceCheckedAccessors(true);
21286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  printf("Testing negative ...\n");
21288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("var obj = {};"
21289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "obj.__proto__ = new f();");
21290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
21291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckInstanceCheckedAccessors(false);
21292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
21293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(InstanceCheckOnPrototypeAccessor) {
21296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::internal::FLAG_allow_natives_syntax = true;
21297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
21298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(context->GetIsolate());
21299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
21301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> proto = templ->PrototypeTemplate();
21302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  proto->SetAccessor(v8_str("foo"), InstanceCheckedGetter,
21303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     InstanceCheckedSetter, Handle<Value>(), v8::DEFAULT,
21304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     v8::None,
21305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     v8::AccessorSignature::New(context->GetIsolate(), templ));
21306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context->Global()->Set(v8_str("f"), templ->GetFunction());
21307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  printf("Testing positive ...\n");
21309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("var obj = new f();");
21310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
21311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckInstanceCheckedAccessors(true);
21312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  printf("Testing negative ...\n");
21314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("var obj = {};"
21315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "obj.__proto__ = new f();");
21316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
21317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckInstanceCheckedAccessors(false);
21318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  printf("Testing positive with modified prototype chain ...\n");
21320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("var obj = new f();"
21321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "var pro = {};"
21322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "pro.__proto__ = obj.__proto__;"
21323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "obj.__proto__ = pro;");
21324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
21325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckInstanceCheckedAccessors(true);
21326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
21327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(TryFinallyMessage) {
21330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
21331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(context->GetIsolate());
21332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
21333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Test that the original error message is not lost if there is a
21334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // recursive call into Javascript is done in the finally block, e.g. to
21335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // initialize an IC. (crbug.com/129171)
21336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    TryCatch try_catch;
21337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const char* trigger_ic =
21338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "try {                      \n"
21339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "  throw new Error('test'); \n"
21340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "} finally {                \n"
21341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "  var x = 0;               \n"
21342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "  x++;                     \n"  // Trigger an IC initialization here.
21343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "}                          \n";
21344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CompileRun(trigger_ic);
21345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(try_catch.HasCaught());
21346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<Message> message = try_catch.Message();
21347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(!message.IsEmpty());
21348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(2, message->GetLineNumber());
21349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
21350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
21352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Test that the original exception message is indeed overwritten if
21353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // a new error is thrown in the finally block.
21354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    TryCatch try_catch;
21355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const char* throw_again =
21356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "try {                       \n"
21357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "  throw new Error('test');  \n"
21358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "} finally {                 \n"
21359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "  var x = 0;                \n"
21360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "  x++;                      \n"
21361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "  throw new Error('again'); \n"  // This is the new uncaught error.
21362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "}                           \n";
21363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CompileRun(throw_again);
21364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(try_catch.HasCaught());
21365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<Message> message = try_catch.Message();
21366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(!message.IsEmpty());
21367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(6, message->GetLineNumber());
21368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
21369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
21370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void Helper137002(bool do_store,
21373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         bool polymorphic,
21374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         bool remove_accessor,
21375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         bool interceptor) {
21376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
21377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> templ = ObjectTemplate::New(context->GetIsolate());
21378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (interceptor) {
21379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    templ->SetNamedPropertyHandler(FooGetInterceptor, FooSetInterceptor);
21380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
21381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    templ->SetAccessor(v8_str("foo"),
21382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       GetterWhichReturns42,
21383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       SetterWhichSetsYOnThisTo23);
21384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
21385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context->Global()->Set(v8_str("obj"), templ->NewInstance());
21386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Turn monomorphic on slow object with native accessor, then turn
21388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // polymorphic, finally optimize to create negative lookup and fail.
21389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun(do_store ?
21390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "function f(x) { x.foo = void 0; }" :
21391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "function f(x) { return x.foo; }");
21392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("obj.y = void 0;");
21393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!interceptor) {
21394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CompileRun("%OptimizeObjectForAddingMultipleProperties(obj, 1);");
21395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
21396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("obj.__proto__ = null;"
21397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "f(obj); f(obj); f(obj);");
21398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (polymorphic) {
21399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CompileRun("f({});");
21400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
21401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("obj.y = void 0;"
21402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "%OptimizeFunctionOnNextCall(f);");
21403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (remove_accessor) {
21404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CompileRun("delete obj.foo;");
21405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
21406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("var result = f(obj);");
21407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (do_store) {
21408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CompileRun("result = obj.y;");
21409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
21410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (remove_accessor && !interceptor) {
21411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(context->Global()->Get(v8_str("result"))->IsUndefined());
21412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
21413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(do_store ? 23 : 42,
21414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             context->Global()->Get(v8_str("result"))->Int32Value());
21415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
21416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
21417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(Regress137002a) {
21420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::FLAG_allow_natives_syntax = true;
21421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::FLAG_compilation_cache = false;
21422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(CcTest::isolate());
21423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < 16; i++) {
21424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Helper137002(i & 8, i & 4, i & 2, i & 1);
21425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
21426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
21427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(Regress137002b) {
21430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::FLAG_allow_natives_syntax = true;
21431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
21432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
21433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
21434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
21435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  templ->SetAccessor(v8_str("foo"),
21436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     GetterWhichReturns42,
21437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     SetterWhichSetsYOnThisTo23);
21438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context->Global()->Set(v8_str("obj"), templ->NewInstance());
21439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Turn monomorphic on slow object with native accessor, then just
21441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // delete the property and fail.
21442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("function load(x) { return x.foo; }"
21443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "function store(x) { x.foo = void 0; }"
21444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "function keyed_load(x, key) { return x[key]; }"
21445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             // Second version of function has a different source (add void 0)
21446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             // so that it does not share code with the first version.  This
21447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             // ensures that the ICs are monomorphic.
21448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "function load2(x) { void 0; return x.foo; }"
21449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "function store2(x) { void 0; x.foo = void 0; }"
21450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "function keyed_load2(x, key) { void 0; return x[key]; }"
21451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "obj.y = void 0;"
21453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "obj.__proto__ = null;"
21454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "var subobj = {};"
21455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "subobj.y = void 0;"
21456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "subobj.__proto__ = obj;"
21457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
21458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             // Make the ICs monomorphic.
21460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "load(obj); load(obj);"
21461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "load2(subobj); load2(subobj);"
21462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "store(obj); store(obj);"
21463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "store2(subobj); store2(subobj);"
21464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "keyed_load(obj, 'foo'); keyed_load(obj, 'foo');"
21465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "keyed_load2(subobj, 'foo'); keyed_load2(subobj, 'foo');"
21466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             // Actually test the shiny new ICs and better not crash. This
21468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             // serves as a regression test for issue 142088 as well.
21469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "load(obj);"
21470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "load2(subobj);"
21471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "store(obj);"
21472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "store2(subobj);"
21473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "keyed_load(obj, 'foo');"
21474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "keyed_load2(subobj, 'foo');"
21475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             // Delete the accessor.  It better not be called any more now.
21477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "delete obj.foo;"
21478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "obj.y = void 0;"
21479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "subobj.y = void 0;"
21480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "var load_result = load(obj);"
21482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "var load_result2 = load2(subobj);"
21483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "var keyed_load_result = keyed_load(obj, 'foo');"
21484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "var keyed_load_result2 = keyed_load2(subobj, 'foo');"
21485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "store(obj);"
21486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "store2(subobj);"
21487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "var y_from_obj = obj.y;"
21488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "var y_from_subobj = subobj.y;");
21489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(context->Global()->Get(v8_str("load_result"))->IsUndefined());
21490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(context->Global()->Get(v8_str("load_result2"))->IsUndefined());
21491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(context->Global()->Get(v8_str("keyed_load_result"))->IsUndefined());
21492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(context->Global()->Get(v8_str("keyed_load_result2"))->IsUndefined());
21493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(context->Global()->Get(v8_str("y_from_obj"))->IsUndefined());
21494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(context->Global()->Get(v8_str("y_from_subobj"))->IsUndefined());
21495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
21496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(Regress142088) {
21499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::FLAG_allow_natives_syntax = true;
21500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
21501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
21502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
21503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
21504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  templ->SetAccessor(v8_str("foo"),
21505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     GetterWhichReturns42,
21506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     SetterWhichSetsYOnThisTo23);
21507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context->Global()->Set(v8_str("obj"), templ->NewInstance());
21508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("function load(x) { return x.foo; }"
21510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "var o = Object.create(obj);"
21511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
21512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "load(o); load(o); load(o); load(o);");
21513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
21514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(Regress3337) {
21517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
21518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
21519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
21520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::Object> o1 = Object::New(isolate);
21521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<v8::Object> o2 = Object::New(isolate);
21522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::Handle<i::JSObject> io1 = v8::Utils::OpenHandle(*o1);
21523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::Handle<i::JSObject> io2 = v8::Utils::OpenHandle(*o2);
21524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(io1->map() == io2->map());
21525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  o1->SetIndexedPropertiesToExternalArrayData(
21526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      NULL, v8::kExternalUint32Array, 0);
21527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  o2->SetIndexedPropertiesToExternalArrayData(
21528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      NULL, v8::kExternalUint32Array, 0);
21529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(io1->map() == io2->map());
21530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
21531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(Regress137496) {
21534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::FLAG_expose_gc = true;
21535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
21536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(context->GetIsolate());
21537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Compile a try-finally clause where the finally block causes a GC
21539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // while there still is a message pending for external reporting.
21540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TryCatch try_catch;
21541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  try_catch.SetVerbose(true);
21542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("try { throw new Error(); } finally { gc(); }");
21543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(try_catch.HasCaught());
21544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
21545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(Regress149912) {
21548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
21549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(context->GetIsolate());
21550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
21551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter);
21552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context->Global()->Set(v8_str("Bug"), templ->GetFunction());
21553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("Number.prototype.__proto__ = new Bug; var x = 0; x.foo();");
21554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
21555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(Regress157124) {
21558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
21559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
21560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
21561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
21562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Object> obj = templ->NewInstance();
21563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  obj->GetIdentityHash();
21564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  obj->DeleteHiddenValue(v8_str("Bug"));
21565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
21566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(Regress2535) {
21569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
21570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(context->GetIsolate());
21571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Value> set_value = CompileRun("new Set();");
21572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Object> set_object(Local<Object>::Cast(set_value));
21573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, set_object->InternalFieldCount());
21574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Value> map_value = CompileRun("new Map();");
21575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Object> map_object(Local<Object>::Cast(map_value));
21576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, map_object->InternalFieldCount());
21577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
21578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(Regress2746) {
21581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
21582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
21583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
21584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Object> obj = Object::New(isolate);
21585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<String> key = String::NewFromUtf8(context->GetIsolate(), "key");
21586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  obj->SetHiddenValue(key, v8::Undefined(isolate));
21587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Value> value = obj->GetHiddenValue(key);
21588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!value.IsEmpty());
21589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(value->IsUndefined());
21590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
21591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(Regress260106) {
21594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
21595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
21596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
21597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<FunctionTemplate> templ = FunctionTemplate::New(isolate,
21598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                        DummyCallHandler);
21599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("for (var i = 0; i < 128; i++) Object.prototype[i] = 0;");
21600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Function> function = templ->GetFunction();
21601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!function.IsEmpty());
21602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(function->IsFunction());
21603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
21604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(JSONParseObject) {
21607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
21608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HandleScope scope(context->GetIsolate());
21609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Value> obj = v8::JSON::Parse(v8_str("{\"x\":42}"));
21610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Object> global = context->Global();
21611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  global->Set(v8_str("obj"), obj);
21612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExpectString("JSON.stringify(obj)", "{\"x\":42}");
21613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
21614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(JSONParseNumber) {
21617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
21618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HandleScope scope(context->GetIsolate());
21619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Value> obj = v8::JSON::Parse(v8_str("42"));
21620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Object> global = context->Global();
21621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  global->Set(v8_str("obj"), obj);
21622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExpectString("JSON.stringify(obj)", "42");
21623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
21624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_OS_POSIX && !V8_OS_NACL
21627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass ThreadInterruptTest {
21628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
21629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ThreadInterruptTest() : sem_(0), sem_value_(0) { }
21630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ~ThreadInterruptTest() {}
21631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void RunTest() {
21633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    InterruptThread i_thread(this);
21634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    i_thread.Start();
21635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    sem_.Wait();
21637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(kExpectedValue, sem_value_);
21638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
21639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
21641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const int kExpectedValue = 1;
21642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  class InterruptThread : public v8::base::Thread {
21644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch   public:
21645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    explicit InterruptThread(ThreadInterruptTest* test)
21646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        : Thread(Options("InterruptThread")), test_(test) {}
21647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    virtual void Run() {
21649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      struct sigaction action;
21650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Ensure that we'll enter waiting condition
21652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::base::OS::Sleep(100);
21653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Setup signal handler
21655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      memset(&action, 0, sizeof(action));
21656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      action.sa_handler = SignalHandler;
21657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      sigaction(SIGCHLD, &action, NULL);
21658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Send signal
21660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      kill(getpid(), SIGCHLD);
21661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Ensure that if wait has returned because of error
21663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::base::OS::Sleep(100);
21664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Set value and signal semaphore
21666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      test_->sem_value_ = 1;
21667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      test_->sem_.Signal();
21668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
21669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    static void SignalHandler(int signal) {
21671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
21672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch   private:
21674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch     ThreadInterruptTest* test_;
21675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  };
21676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::base::Semaphore sem_;
21678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  volatile int sem_value_;
21679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
21680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(SemaphoreInterruption) {
21683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ThreadInterruptTest().RunTest();
21684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
21685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif  // V8_OS_POSIX
21688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic bool NamedAccessAlwaysBlocked(Local<v8::Object> global,
21691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                     Local<Value> name,
21692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                     v8::AccessType type,
21693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                     Local<Value> data) {
21694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::PrintF("Named access blocked.\n");
21695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return false;
21696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
21697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic bool IndexAccessAlwaysBlocked(Local<v8::Object> global,
21700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                     uint32_t key,
21701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                     v8::AccessType type,
21702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                     Local<Value> data) {
21703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::PrintF("Indexed access blocked.\n");
21704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return false;
21705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
21706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid UnreachableCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
21709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(false);
21710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
21711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(JSONStringifyAccessCheck) {
21714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::V8::Initialize();
21715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
21716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
21717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Create an ObjectTemplate for global objects and install access
21719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // check callbacks that will block access.
21720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> global_template =
21721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::ObjectTemplate::New(isolate);
21722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  global_template->SetAccessCheckCallbacks(NamedAccessAlwaysBlocked,
21723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           IndexAccessAlwaysBlocked);
21724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Create a context and set an x property on it's global object.
21726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context0(NULL, global_template);
21727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Object> global0 = context0->Global();
21728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  global0->Set(v8_str("x"), v8_num(42));
21729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExpectString("JSON.stringify(this)", "{\"x\":42}");
21730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < 2; i++) {
21732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (i == 1) {
21733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Install a toJSON function on the second run.
21734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Handle<v8::FunctionTemplate> toJSON =
21735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          v8::FunctionTemplate::New(isolate, UnreachableCallback);
21736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      global0->Set(v8_str("toJSON"), toJSON->GetFunction());
21738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
21739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Create a context with a different security token so that the
21740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // failed access check callback will be called on each access.
21741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LocalContext context1(NULL, global_template);
21742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    context1->Global()->Set(v8_str("other"), global0);
21743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(CompileRun("JSON.stringify(other)").IsEmpty());
21745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(CompileRun("JSON.stringify({ 'a' : other, 'b' : ['c'] })").IsEmpty());
21746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(CompileRun("JSON.stringify([other, 'b', 'c'])").IsEmpty());
21747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Handle<v8::Array> array = v8::Array::New(isolate, 2);
21749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    array->Set(0, v8_str("a"));
21750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    array->Set(1, v8_str("b"));
21751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    context1->Global()->Set(v8_str("array"), array);
21752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ExpectString("JSON.stringify(array)", "[\"a\",\"b\"]");
21753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    array->TurnOnAccessCheck();
21754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(CompileRun("JSON.stringify(array)").IsEmpty());
21755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(CompileRun("JSON.stringify([array])").IsEmpty());
21756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(CompileRun("JSON.stringify({'a' : array})").IsEmpty());
21757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
21758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
21759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool access_check_fail_thrown = false;
21762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool catch_callback_called = false;
21763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Failed access check callback that performs a GC on each invocation.
21766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FailedAccessCheckThrows(Local<v8::Object> target,
21767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             v8::AccessType type,
21768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             Local<v8::Value> data) {
21769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  access_check_fail_thrown = true;
21770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::PrintF("Access check failed. Error thrown.\n");
21771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::isolate()->ThrowException(
21772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Exception::Error(v8_str("cross context")));
21773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
21774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CatcherCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
21777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < args.Length(); i++) {
21778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    i::PrintF("%s\n", *String::Utf8Value(args[i]));
21779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
21780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  catch_callback_called = true;
21781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
21782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HasOwnPropertyCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
21785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  args[0]->ToObject()->HasOwnProperty(args[1]->ToString());
21786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
21787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CheckCorrectThrow(const char* script) {
21790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Test that the script, when wrapped into a try-catch, triggers the catch
21791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // clause due to failed access check throwing an exception.
21792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The subsequent try-catch should run without any exception.
21793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  access_check_fail_thrown = false;
21794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  catch_callback_called = false;
21795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::ScopedVector<char> source(1024);
21796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::SNPrintF(source, "try { %s; } catch (e) { catcher(e); }", script);
21797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun(source.start());
21798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(access_check_fail_thrown);
21799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(catch_callback_called);
21800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  access_check_fail_thrown = false;
21802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  catch_callback_called = false;
21803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("try { [1, 2, 3].sort(); } catch (e) { catcher(e) };");
21804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!access_check_fail_thrown);
21805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!catch_callback_called);
21806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
21807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(AccessCheckThrows) {
21810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::FLAG_allow_natives_syntax = true;
21811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::V8::Initialize();
21812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::V8::SetFailedAccessCheckCallbackFunction(&FailedAccessCheckThrows);
21813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
21814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
21815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Create an ObjectTemplate for global objects and install access
21817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // check callbacks that will block access.
21818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> global_template =
21819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::ObjectTemplate::New(isolate);
21820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  global_template->SetAccessCheckCallbacks(NamedAccessAlwaysBlocked,
21821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           IndexAccessAlwaysBlocked);
21822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Create a context and set an x property on it's global object.
21824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context0(NULL, global_template);
21825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Object> global0 = context0->Global();
21826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Create a context with a different security token so that the
21828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // failed access check callback will be called on each access.
21829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context1(NULL, global_template);
21830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context1->Global()->Set(v8_str("other"), global0);
21831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::FunctionTemplate> catcher_fun =
21833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::FunctionTemplate::New(isolate, CatcherCallback);
21834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context1->Global()->Set(v8_str("catcher"), catcher_fun->GetFunction());
21835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::FunctionTemplate> has_own_property_fun =
21837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::FunctionTemplate::New(isolate, HasOwnPropertyCallback);
21838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context1->Global()->Set(v8_str("has_own_property"),
21839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          has_own_property_fun->GetFunction());
21840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  { v8::TryCatch try_catch;
21842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    access_check_fail_thrown = false;
21843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CompileRun("other.x;");
21844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(access_check_fail_thrown);
21845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(try_catch.HasCaught());
21846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
21847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckCorrectThrow("other.x");
21849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckCorrectThrow("other[1]");
21850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckCorrectThrow("JSON.stringify(other)");
21851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckCorrectThrow("has_own_property(other, 'x')");
21852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckCorrectThrow("%GetProperty(other, 'x')");
21853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckCorrectThrow("%SetProperty(other, 'x', 'foo', 0)");
21854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckCorrectThrow("%AddNamedProperty(other, 'x', 'foo', 1)");
21855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckCorrectThrow("%DeleteProperty(other, 'x', 0)");
21856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckCorrectThrow("%DeleteProperty(other, '1', 0)");
21857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckCorrectThrow("%HasOwnProperty(other, 'x')");
21858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckCorrectThrow("%HasProperty(other, 'x')");
21859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckCorrectThrow("%HasElement(other, 1)");
21860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckCorrectThrow("%IsPropertyEnumerable(other, 'x')");
21861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckCorrectThrow("%GetPropertyNames(other)");
21862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // PROPERTY_ATTRIBUTES_NONE = 0
21863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckCorrectThrow("%GetOwnPropertyNames(other, 0)");
21864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckCorrectThrow("%DefineAccessorPropertyUnchecked("
21865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        "other, 'x', null, null, 1)");
21866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Reset the failed access check callback so it does not influence
21868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the other tests.
21869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::V8::SetFailedAccessCheckCallbackFunction(NULL);
21870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
21871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(Regress256330) {
21874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::FLAG_allow_natives_syntax = true;
21875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
21876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(context->GetIsolate());
21877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
21878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter);
21879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context->Global()->Set(v8_str("Bug"), templ->GetFunction());
21880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("\"use strict\"; var o = new Bug;"
21881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "function f(o) { o.x = 10; };"
21882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "f(o); f(o); f(o);"
21883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "%OptimizeFunctionOnNextCall(f);"
21884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "f(o);");
21885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExpectBoolean("%GetOptimizationStatus(f) != 2", true);
21886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
21887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(CrankshaftInterceptorSetter) {
21890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::FLAG_allow_natives_syntax = true;
21891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(CcTest::isolate());
21892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
21893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
21894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
21895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->Global()->Set(v8_str("Obj"), templ->GetFunction());
21896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("var obj = new Obj;"
21897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             // Initialize fields to avoid transitions later.
21898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "obj.age = 0;"
21899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "obj.accessor_age = 42;"
21900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "function setter(i) { this.accessor_age = i; };"
21901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "function getter() { return this.accessor_age; };"
21902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "function setAge(i) { obj.age = i; };"
21903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "Object.defineProperty(obj, 'age', { get:getter, set:setter });"
21904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "setAge(1);"
21905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "setAge(2);"
21906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "setAge(3);"
21907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "%OptimizeFunctionOnNextCall(setAge);"
21908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "setAge(4);");
21909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // All stores went through the interceptor.
21910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExpectInt32("obj.interceptor_age", 4);
21911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExpectInt32("obj.accessor_age", 42);
21912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
21913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(CrankshaftInterceptorGetter) {
21916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::FLAG_allow_natives_syntax = true;
21917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(CcTest::isolate());
21918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
21919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
21920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
21921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->Global()->Set(v8_str("Obj"), templ->GetFunction());
21922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("var obj = new Obj;"
21923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             // Initialize fields to avoid transitions later.
21924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "obj.age = 1;"
21925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "obj.accessor_age = 42;"
21926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "function getter() { return this.accessor_age; };"
21927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "function getAge() { return obj.interceptor_age; };"
21928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "Object.defineProperty(obj, 'interceptor_age', { get:getter });"
21929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "getAge();"
21930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "getAge();"
21931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "getAge();"
21932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "%OptimizeFunctionOnNextCall(getAge);");
21933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Access through interceptor.
21934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExpectInt32("getAge()", 1);
21935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
21936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(CrankshaftInterceptorFieldRead) {
21939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::FLAG_allow_natives_syntax = true;
21940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(CcTest::isolate());
21941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
21942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
21943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
21944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->Global()->Set(v8_str("Obj"), templ->GetFunction());
21945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("var obj = new Obj;"
21946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "obj.__proto__.interceptor_age = 42;"
21947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "obj.age = 100;"
21948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "function getAge() { return obj.interceptor_age; };");
21949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExpectInt32("getAge();", 100);
21950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExpectInt32("getAge();", 100);
21951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExpectInt32("getAge();", 100);
21952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("%OptimizeFunctionOnNextCall(getAge);");
21953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Access through interceptor.
21954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExpectInt32("getAge();", 100);
21955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
21956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(CrankshaftInterceptorFieldWrite) {
21959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::FLAG_allow_natives_syntax = true;
21960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(CcTest::isolate());
21961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
21962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
21963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
21964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->Global()->Set(v8_str("Obj"), templ->GetFunction());
21965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("var obj = new Obj;"
21966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "obj.age = 100000;"
21967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "function setAge(i) { obj.age = i };"
21968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "setAge(100);"
21969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "setAge(101);"
21970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "setAge(102);"
21971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "%OptimizeFunctionOnNextCall(setAge);"
21972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "setAge(103);");
21973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExpectInt32("obj.age", 100000);
21974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExpectInt32("obj.interceptor_age", 103);
21975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
21976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass RequestInterruptTestBase {
21979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
21980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RequestInterruptTestBase()
21981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : env_(),
21982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        isolate_(env_->GetIsolate()),
21983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        sem_(0),
21984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        warmup_(20000),
21985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        should_continue_(true) {
21986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
21987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  virtual ~RequestInterruptTestBase() { }
21989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  virtual void StartInterruptThread() = 0;
21991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  virtual void TestBody() = 0;
21993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void RunTest() {
21995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    StartInterruptThread();
21996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope handle_scope(isolate_);
21998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    TestBody();
22000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    isolate_->ClearInterrupt();
22002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Verify we arrived here because interruptor was called
22004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // not due to a bug causing us to exit the loop too early.
22005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(!should_continue());
22006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
22007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void WakeUpInterruptor() {
22009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    sem_.Signal();
22010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
22011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool should_continue() const { return should_continue_; }
22013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool ShouldContinue() {
22015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (warmup_ > 0) {
22016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (--warmup_ == 0) {
22017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        WakeUpInterruptor();
22018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
22019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
22020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return should_continue_;
22022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
22023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static void ShouldContinueCallback(
22025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      const v8::FunctionCallbackInfo<Value>& info) {
22026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    RequestInterruptTestBase* test =
22027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        reinterpret_cast<RequestInterruptTestBase*>(
22028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            info.Data().As<v8::External>()->Value());
22029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    info.GetReturnValue().Set(test->ShouldContinue());
22030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
22031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env_;
22033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate_;
22034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::base::Semaphore sem_;
22035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int warmup_;
22036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool should_continue_;
22037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
22038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass RequestInterruptTestBaseWithSimpleInterrupt
22041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    : public RequestInterruptTestBase {
22042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
22043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RequestInterruptTestBaseWithSimpleInterrupt() : i_thread(this) { }
22044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  virtual void StartInterruptThread() {
22046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    i_thread.Start();
22047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
22048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
22050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  class InterruptThread : public v8::base::Thread {
22051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch   public:
22052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    explicit InterruptThread(RequestInterruptTestBase* test)
22053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        : Thread(Options("RequestInterruptTest")), test_(test) {}
22054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    virtual void Run() {
22056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      test_->sem_.Wait();
22057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      test_->isolate_->RequestInterrupt(&OnInterrupt, test_);
22058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
22059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    static void OnInterrupt(v8::Isolate* isolate, void* data) {
22061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      reinterpret_cast<RequestInterruptTestBase*>(data)->
22062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          should_continue_ = false;
22063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
22064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch   private:
22066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch     RequestInterruptTestBase* test_;
22067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  };
22068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InterruptThread i_thread;
22070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
22071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass RequestInterruptTestWithFunctionCall
22074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    : public RequestInterruptTestBaseWithSimpleInterrupt {
22075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
22076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  virtual void TestBody() {
22077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<Function> func = Function::New(
22078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        isolate_, ShouldContinueCallback, v8::External::New(isolate_, this));
22079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    env_->Global()->Set(v8_str("ShouldContinue"), func);
22080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CompileRun("while (ShouldContinue()) { }");
22082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
22083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
22084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass RequestInterruptTestWithMethodCall
22087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    : public RequestInterruptTestBaseWithSimpleInterrupt {
22088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
22089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  virtual void TestBody() {
22090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
22091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Local<v8::Template> proto = t->PrototypeTemplate();
22092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    proto->Set(v8_str("shouldContinue"), Function::New(
22093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
22094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    env_->Global()->Set(v8_str("Klass"), t->GetFunction());
22095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CompileRun("var obj = new Klass; while (obj.shouldContinue()) { }");
22097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
22098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
22099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass RequestInterruptTestWithAccessor
22102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    : public RequestInterruptTestBaseWithSimpleInterrupt {
22103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
22104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  virtual void TestBody() {
22105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
22106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Local<v8::Template> proto = t->PrototypeTemplate();
22107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    proto->SetAccessorProperty(v8_str("shouldContinue"), FunctionTemplate::New(
22108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
22109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    env_->Global()->Set(v8_str("Klass"), t->GetFunction());
22110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CompileRun("var obj = new Klass; while (obj.shouldContinue) { }");
22112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
22113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
22114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass RequestInterruptTestWithNativeAccessor
22117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    : public RequestInterruptTestBaseWithSimpleInterrupt {
22118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
22119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  virtual void TestBody() {
22120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
22121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    t->InstanceTemplate()->SetNativeDataProperty(
22122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v8_str("shouldContinue"),
22123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        &ShouldContinueNativeGetter,
22124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        NULL,
22125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v8::External::New(isolate_, this));
22126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    env_->Global()->Set(v8_str("Klass"), t->GetFunction());
22127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CompileRun("var obj = new Klass; while (obj.shouldContinue) { }");
22129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
22130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
22132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static void ShouldContinueNativeGetter(
22133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Local<String> property,
22134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      const v8::PropertyCallbackInfo<v8::Value>& info) {
22135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    RequestInterruptTestBase* test =
22136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        reinterpret_cast<RequestInterruptTestBase*>(
22137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            info.Data().As<v8::External>()->Value());
22138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    info.GetReturnValue().Set(test->ShouldContinue());
22139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
22140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
22141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass RequestInterruptTestWithMethodCallAndInterceptor
22144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    : public RequestInterruptTestBaseWithSimpleInterrupt {
22145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
22146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  virtual void TestBody() {
22147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
22148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Local<v8::Template> proto = t->PrototypeTemplate();
22149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    proto->Set(v8_str("shouldContinue"), Function::New(
22150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
22151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Local<v8::ObjectTemplate> instance_template = t->InstanceTemplate();
22152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    instance_template->SetNamedPropertyHandler(EmptyInterceptor);
22153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    env_->Global()->Set(v8_str("Klass"), t->GetFunction());
22155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CompileRun("var obj = new Klass; while (obj.shouldContinue()) { }");
22157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
22158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
22160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static void EmptyInterceptor(
22161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Local<String> property,
22162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      const v8::PropertyCallbackInfo<v8::Value>& info) {
22163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
22164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
22165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass RequestInterruptTestWithMathAbs
22168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    : public RequestInterruptTestBaseWithSimpleInterrupt {
22169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
22170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  virtual void TestBody() {
22171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    env_->Global()->Set(v8_str("WakeUpInterruptor"), Function::New(
22172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        isolate_,
22173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        WakeUpInterruptorCallback,
22174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v8::External::New(isolate_, this)));
22175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    env_->Global()->Set(v8_str("ShouldContinue"), Function::New(
22177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        isolate_,
22178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ShouldContinueCallback,
22179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v8::External::New(isolate_, this)));
22180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    i::FLAG_allow_natives_syntax = true;
22182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CompileRun("function loopish(o) {"
22183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               "  var pre = 10;"
22184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               "  while (o.abs(1) > 0) {"
22185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               "    if (o.abs(1) >= 0 && !ShouldContinue()) break;"
22186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               "    if (pre > 0) {"
22187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               "      if (--pre === 0) WakeUpInterruptor(o === Math);"
22188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               "    }"
22189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               "  }"
22190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               "}"
22191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               "var i = 50;"
22192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               "var obj = {abs: function () { return i-- }, x: null};"
22193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               "delete obj.x;"
22194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               "loopish(obj);"
22195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               "%OptimizeFunctionOnNextCall(loopish);"
22196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               "loopish(Math);");
22197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    i::FLAG_allow_natives_syntax = false;
22199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
22200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
22202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static void WakeUpInterruptorCallback(
22203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      const v8::FunctionCallbackInfo<Value>& info) {
22204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!info[0]->BooleanValue()) return;
22205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    RequestInterruptTestBase* test =
22207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        reinterpret_cast<RequestInterruptTestBase*>(
22208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            info.Data().As<v8::External>()->Value());
22209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    test->WakeUpInterruptor();
22210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
22211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static void ShouldContinueCallback(
22213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      const v8::FunctionCallbackInfo<Value>& info) {
22214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    RequestInterruptTestBase* test =
22215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        reinterpret_cast<RequestInterruptTestBase*>(
22216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            info.Data().As<v8::External>()->Value());
22217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    info.GetReturnValue().Set(test->should_continue());
22218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
22219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
22220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(RequestInterruptTestWithFunctionCall) {
22223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RequestInterruptTestWithFunctionCall().RunTest();
22224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
22225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(RequestInterruptTestWithMethodCall) {
22228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RequestInterruptTestWithMethodCall().RunTest();
22229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
22230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(RequestInterruptTestWithAccessor) {
22233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RequestInterruptTestWithAccessor().RunTest();
22234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
22235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(RequestInterruptTestWithNativeAccessor) {
22238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RequestInterruptTestWithNativeAccessor().RunTest();
22239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
22240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(RequestInterruptTestWithMethodCallAndInterceptor) {
22243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RequestInterruptTestWithMethodCallAndInterceptor().RunTest();
22244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
22245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(RequestInterruptTestWithMathAbs) {
22248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RequestInterruptTestWithMathAbs().RunTest();
22249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
22250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass ClearInterruptFromAnotherThread
22253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    : public RequestInterruptTestBase {
22254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
22255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ClearInterruptFromAnotherThread() : i_thread(this), sem2_(0) { }
22256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  virtual void StartInterruptThread() {
22258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    i_thread.Start();
22259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
22260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  virtual void TestBody() {
22262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<Function> func = Function::New(
22263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        isolate_, ShouldContinueCallback, v8::External::New(isolate_, this));
22264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    env_->Global()->Set(v8_str("ShouldContinue"), func);
22265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CompileRun("while (ShouldContinue()) { }");
22267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
22268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
22270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  class InterruptThread : public v8::base::Thread {
22271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch   public:
22272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    explicit InterruptThread(ClearInterruptFromAnotherThread* test)
22273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        : Thread(Options("RequestInterruptTest")), test_(test) {}
22274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    virtual void Run() {
22276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      test_->sem_.Wait();
22277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      test_->isolate_->RequestInterrupt(&OnInterrupt, test_);
22278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      test_->sem_.Wait();
22279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      test_->isolate_->ClearInterrupt();
22280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      test_->sem2_.Signal();
22281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
22282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    static void OnInterrupt(v8::Isolate* isolate, void* data) {
22284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ClearInterruptFromAnotherThread* test =
22285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          reinterpret_cast<ClearInterruptFromAnotherThread*>(data);
22286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      test->sem_.Signal();
22287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      bool success = test->sem2_.WaitFor(v8::base::TimeDelta::FromSeconds(2));
22288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Crash instead of timeout to make this failure more prominent.
22289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CHECK(success);
22290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      test->should_continue_ = false;
22291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
22292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch   private:
22294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch     ClearInterruptFromAnotherThread* test_;
22295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  };
22296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InterruptThread i_thread;
22298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::base::Semaphore sem2_;
22299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
22300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(ClearInterruptFromAnotherThread) {
22303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ClearInterruptFromAnotherThread().RunTest();
22304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
22305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic Local<Value> function_new_expected_env;
22308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void FunctionNewCallback(const v8::FunctionCallbackInfo<Value>& info) {
22309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(function_new_expected_env, info.Data());
22310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(17);
22311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
22312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTHREADED_TEST(FunctionNew) {
22315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
22316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
22317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
22318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Object> data = v8::Object::New(isolate);
22319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  function_new_expected_env = data;
22320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Function> func = Function::New(isolate, FunctionNewCallback, data);
22321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->Global()->Set(v8_str("func"), func);
22322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Value> result = CompileRun("func();");
22323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(v8::Integer::New(isolate, 17), result);
22324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Verify function not cached
22325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int serial_number =
22326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      i::Smi::cast(v8::Utils::OpenHandle(*func)
22327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          ->shared()->get_api_func_data()->serial_number())->value();
22328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
22329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::Handle<i::JSObject> cache(i_isolate->native_context()->function_cache());
22330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::Handle<i::Object> elm =
22331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      i::Object::GetElement(i_isolate, cache, serial_number).ToHandleChecked();
22332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(elm->IsUndefined());
22333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Verify that each Function::New creates a new function instance
22334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Object> data2 = v8::Object::New(isolate);
22335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  function_new_expected_env = data2;
22336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Function> func2 = Function::New(isolate, FunctionNewCallback, data2);
22337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!func2->IsNull());
22338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_NE(func, func2);
22339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->Global()->Set(v8_str("func2"), func2);
22340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Value> result2 = CompileRun("func2();");
22341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(v8::Integer::New(isolate, 17), result2);
22342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
22343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(EscapeableHandleScope) {
22346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HandleScope outer_scope(CcTest::isolate());
22347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
22348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int runs = 10;
22349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<String> values[runs];
22350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < runs; i++) {
22351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::EscapableHandleScope inner_scope(CcTest::isolate());
22352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<String> value;
22353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (i != 0) value = v8_str("escape value");
22354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    values[i] = inner_scope.Escape(value);
22355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
22356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < runs; i++) {
22357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<String> expected;
22358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (i != 0) {
22359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CHECK_EQ(v8_str("escape value"), values[i]);
22360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
22361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CHECK(values[i].IsEmpty());
22362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
22363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
22364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
22365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void SetterWhichExpectsThisAndHolderToDiffer(
22368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<String>, Local<Value>, const v8::PropertyCallbackInfo<void>& info) {
22369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(info.Holder() != info.This());
22370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
22371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(Regress239669) {
22374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
22375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
22376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
22377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
22378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  templ->SetAccessor(v8_str("x"), 0, SetterWhichExpectsThisAndHolderToDiffer);
22379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context->Global()->Set(v8_str("P"), templ->NewInstance());
22380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun(
22381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "function C1() {"
22382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  this.x = 23;"
22383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "};"
22384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "C1.prototype = P;"
22385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "for (var i = 0; i < 4; i++ ) {"
22386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  new C1();"
22387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "}");
22388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
22389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass ApiCallOptimizationChecker {
22392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
22393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static Local<Object> data;
22394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static Local<Object> receiver;
22395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static Local<Object> holder;
22396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static Local<Object> callee;
22397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static int count;
22398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static void OptimizationCallback(
22400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      const v8::FunctionCallbackInfo<v8::Value>& info) {
22401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(callee == info.Callee());
22402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(data == info.Data());
22403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(receiver == info.This());
22404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (info.Length() == 1) {
22405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CHECK_EQ(v8_num(1), info[0]);
22406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
22407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(holder == info.Holder());
22408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    count++;
22409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    info.GetReturnValue().Set(v8_str("returned"));
22410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
22411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
22413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  enum SignatureType {
22414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    kNoSignature,
22415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    kSignatureOnReceiver,
22416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    kSignatureOnPrototype
22417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  };
22418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void RunAll() {
22420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SignatureType signature_types[] =
22421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      {kNoSignature, kSignatureOnReceiver, kSignatureOnPrototype};
22422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (unsigned i = 0; i < arraysize(signature_types); i++) {
22423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SignatureType signature_type = signature_types[i];
22424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      for (int j = 0; j < 2; j++) {
22425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        bool global = j == 0;
22426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        int key = signature_type +
22427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            arraysize(signature_types) * (global ? 1 : 0);
22428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Run(signature_type, global, key);
22429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
22430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
22431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
22432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Run(SignatureType signature_type, bool global, int key) {
22434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Isolate* isolate = CcTest::isolate();
22435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(isolate);
22436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Build a template for signature checks.
22437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<v8::ObjectTemplate> signature_template;
22438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<v8::Signature> signature;
22439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    {
22440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Local<v8::FunctionTemplate> parent_template =
22441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        FunctionTemplate::New(isolate);
22442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      parent_template->SetHiddenPrototype(true);
22443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Local<v8::FunctionTemplate> function_template
22444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          = FunctionTemplate::New(isolate);
22445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      function_template->Inherit(parent_template);
22446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      switch (signature_type) {
22447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case kNoSignature:
22448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          break;
22449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case kSignatureOnReceiver:
22450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          signature = v8::Signature::New(isolate, function_template);
22451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          break;
22452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case kSignatureOnPrototype:
22453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          signature = v8::Signature::New(isolate, parent_template);
22454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          break;
22455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
22456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      signature_template = function_template->InstanceTemplate();
22457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
22458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Global object must pass checks.
22459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<v8::Context> context =
22460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v8::Context::New(isolate, NULL, signature_template);
22461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Context::Scope context_scope(context);
22462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Install regular object that can pass signature checks.
22463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<Object> function_receiver = signature_template->NewInstance();
22464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    context->Global()->Set(v8_str("function_receiver"), function_receiver);
22465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Get the holder objects.
22466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<Object> inner_global =
22467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Local<Object>::Cast(context->Global()->GetPrototype());
22468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Install functions on hidden prototype object if there is one.
22469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    data = Object::New(isolate);
22470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<FunctionTemplate> function_template = FunctionTemplate::New(
22471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        isolate, OptimizationCallback, data, signature);
22472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<Function> function = function_template->GetFunction();
22473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<Object> global_holder = inner_global;
22474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<Object> function_holder = function_receiver;
22475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (signature_type == kSignatureOnPrototype) {
22476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      function_holder = Local<Object>::Cast(function_holder->GetPrototype());
22477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      global_holder = Local<Object>::Cast(global_holder->GetPrototype());
22478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
22479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    global_holder->Set(v8_str("g_f"), function);
22480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    global_holder->SetAccessorProperty(v8_str("g_acc"), function, function);
22481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    function_holder->Set(v8_str("f"), function);
22482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    function_holder->SetAccessorProperty(v8_str("acc"), function, function);
22483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Initialize expected values.
22484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    callee = function;
22485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    count = 0;
22486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (global) {
22487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      receiver = context->Global();
22488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      holder = inner_global;
22489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
22490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      holder = function_receiver;
22491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // If not using a signature, add something else to the prototype chain
22492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // to test the case that holder != receiver
22493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (signature_type == kNoSignature) {
22494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        receiver = Local<Object>::Cast(CompileRun(
22495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            "var receiver_subclass = {};\n"
22496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            "receiver_subclass.__proto__ = function_receiver;\n"
22497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            "receiver_subclass"));
22498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
22499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        receiver = Local<Object>::Cast(CompileRun(
22500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          "var receiver_subclass = function_receiver;\n"
22501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          "receiver_subclass"));
22502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
22503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
22504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // With no signature, the holder is not set.
22505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (signature_type == kNoSignature) holder = receiver;
22506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // build wrap_function
22507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    i::ScopedVector<char> wrap_function(200);
22508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (global) {
22509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      i::SNPrintF(
22510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          wrap_function,
22511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          "function wrap_f_%d() { var f = g_f; return f(); }\n"
22512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          "function wrap_get_%d() { return this.g_acc; }\n"
22513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          "function wrap_set_%d() { return this.g_acc = 1; }\n",
22514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          key, key, key);
22515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
22516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      i::SNPrintF(
22517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          wrap_function,
22518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          "function wrap_f_%d() { return receiver_subclass.f(); }\n"
22519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          "function wrap_get_%d() { return receiver_subclass.acc; }\n"
22520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          "function wrap_set_%d() { return receiver_subclass.acc = 1; }\n",
22521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          key, key, key);
22522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
22523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // build source string
22524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    i::ScopedVector<char> source(1000);
22525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    i::SNPrintF(
22526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        source,
22527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "%s\n"  // wrap functions
22528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "function wrap_f() { return wrap_f_%d(); }\n"
22529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "function wrap_get() { return wrap_get_%d(); }\n"
22530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "function wrap_set() { return wrap_set_%d(); }\n"
22531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "check = function(returned) {\n"
22532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "  if (returned !== 'returned') { throw returned; }\n"
22533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "}\n"
22534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "\n"
22535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "check(wrap_f());\n"
22536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "check(wrap_f());\n"
22537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "%%OptimizeFunctionOnNextCall(wrap_f_%d);\n"
22538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "check(wrap_f());\n"
22539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "\n"
22540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "check(wrap_get());\n"
22541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "check(wrap_get());\n"
22542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "%%OptimizeFunctionOnNextCall(wrap_get_%d);\n"
22543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "check(wrap_get());\n"
22544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "\n"
22545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "check = function(returned) {\n"
22546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "  if (returned !== 1) { throw returned; }\n"
22547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "}\n"
22548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "check(wrap_set());\n"
22549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "check(wrap_set());\n"
22550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "%%OptimizeFunctionOnNextCall(wrap_set_%d);\n"
22551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "check(wrap_set());\n",
22552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        wrap_function.start(), key, key, key, key, key, key);
22553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::TryCatch try_catch;
22554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CompileRun(source.start());
22555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!try_catch.HasCaught());
22556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(9, count);
22557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
22558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
22559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochLocal<Object> ApiCallOptimizationChecker::data;
22562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochLocal<Object> ApiCallOptimizationChecker::receiver;
22563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochLocal<Object> ApiCallOptimizationChecker::holder;
22564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochLocal<Object> ApiCallOptimizationChecker::callee;
22565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint ApiCallOptimizationChecker::count = 0;
22566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(TestFunctionCallOptimization) {
22569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::FLAG_allow_natives_syntax = true;
22570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ApiCallOptimizationChecker checker;
22571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  checker.RunAll();
22572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
22573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic const char* last_event_message;
22576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic int last_event_status;
22577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid StoringEventLoggerCallback(const char* message, int status) {
22578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    last_event_message = message;
22579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    last_event_status = status;
22580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
22581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(EventLogging) {
22584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
22585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate->SetEventLogger(StoringEventLoggerCallback);
22586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::internal::HistogramTimer histogramTimer(
22587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "V8.Test", 0, 10000, 50,
22588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      reinterpret_cast<v8::internal::Isolate*>(isolate));
22589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  histogramTimer.Start();
22590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ("V8.Test", last_event_message);
22591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, last_event_status);
22592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  histogramTimer.Stop();
22593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ("V8.Test", last_event_message);
22594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1, last_event_status);
22595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
22596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(Promises) {
22599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
22600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
22601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
22602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Object> global = context->Global();
22603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Creation.
22605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<v8::Promise::Resolver> pr = v8::Promise::Resolver::New(isolate);
22606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<v8::Promise::Resolver> rr = v8::Promise::Resolver::New(isolate);
22607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<v8::Promise> p = pr->GetPromise();
22608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<v8::Promise> r = rr->GetPromise();
22609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // IsPromise predicate.
22611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(p->IsPromise());
22612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(r->IsPromise());
22613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Value> o = v8::Object::New(isolate);
22614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!o->IsPromise());
22615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Resolution and rejection.
22617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  pr->Resolve(v8::Integer::New(isolate, 1));
22618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(p->IsPromise());
22619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  rr->Reject(v8::Integer::New(isolate, 2));
22620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(r->IsPromise());
22621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Chaining non-pending promises.
22623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun(
22624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "var x1 = 0;\n"
22625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "var x2 = 0;\n"
22626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "function f1(x) { x1 = x; return x+1 };\n"
22627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "function f2(x) { x2 = x; return x+1 };\n");
22628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Function> f1 = Handle<Function>::Cast(global->Get(v8_str("f1")));
22629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Function> f2 = Handle<Function>::Cast(global->Get(v8_str("f2")));
22630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  p->Chain(f1);
22632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
22633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate->RunMicrotasks();
22634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1, global->Get(v8_str("x1"))->Int32Value());
22635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  p->Catch(f2);
22637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate->RunMicrotasks();
22638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
22639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  r->Catch(f2);
22641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
22642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate->RunMicrotasks();
22643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2, global->Get(v8_str("x2"))->Int32Value());
22644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  r->Chain(f1);
22646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate->RunMicrotasks();
22647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1, global->Get(v8_str("x1"))->Int32Value());
22648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Chaining pending promises.
22650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("x1 = x2 = 0;");
22651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  pr = v8::Promise::Resolver::New(isolate);
22652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  rr = v8::Promise::Resolver::New(isolate);
22653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  pr->GetPromise()->Chain(f1);
22655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  rr->GetPromise()->Catch(f2);
22656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate->RunMicrotasks();
22657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
22658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
22659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  pr->Resolve(v8::Integer::New(isolate, 1));
22661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  rr->Reject(v8::Integer::New(isolate, 2));
22662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
22663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
22664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate->RunMicrotasks();
22666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1, global->Get(v8_str("x1"))->Int32Value());
22667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2, global->Get(v8_str("x2"))->Int32Value());
22668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Multi-chaining.
22670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("x1 = x2 = 0;");
22671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  pr = v8::Promise::Resolver::New(isolate);
22672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  pr->GetPromise()->Chain(f1)->Chain(f2);
22673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  pr->Resolve(v8::Integer::New(isolate, 3));
22674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
22675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
22676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate->RunMicrotasks();
22677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(3, global->Get(v8_str("x1"))->Int32Value());
22678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(4, global->Get(v8_str("x2"))->Int32Value());
22679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("x1 = x2 = 0;");
22681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  rr = v8::Promise::Resolver::New(isolate);
22682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  rr->GetPromise()->Catch(f1)->Chain(f2);
22683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  rr->Reject(v8::Integer::New(isolate, 3));
22684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
22685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
22686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate->RunMicrotasks();
22687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(3, global->Get(v8_str("x1"))->Int32Value());
22688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(4, global->Get(v8_str("x2"))->Int32Value());
22689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
22690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(PromiseThen) {
22693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
22694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
22695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
22696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Object> global = context->Global();
22697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Creation.
22699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<v8::Promise::Resolver> pr = v8::Promise::Resolver::New(isolate);
22700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<v8::Promise::Resolver> qr = v8::Promise::Resolver::New(isolate);
22701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<v8::Promise> p = pr->GetPromise();
22702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<v8::Promise> q = qr->GetPromise();
22703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(p->IsPromise());
22705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(q->IsPromise());
22706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  pr->Resolve(v8::Integer::New(isolate, 1));
22708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  qr->Resolve(p);
22709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Chaining non-pending promises.
22711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun(
22712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "var x1 = 0;\n"
22713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "var x2 = 0;\n"
22714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "function f1(x) { x1 = x; return x+1 };\n"
22715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "function f2(x) { x2 = x; return x+1 };\n");
22716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Function> f1 = Handle<Function>::Cast(global->Get(v8_str("f1")));
22717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Function> f2 = Handle<Function>::Cast(global->Get(v8_str("f2")));
22718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Chain
22720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  q->Chain(f1);
22721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(global->Get(v8_str("x1"))->IsNumber());
22722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
22723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate->RunMicrotasks();
22724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!global->Get(v8_str("x1"))->IsNumber());
22725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(p, global->Get(v8_str("x1")));
22726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Then
22728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("x1 = x2 = 0;");
22729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  q->Then(f1);
22730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
22731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate->RunMicrotasks();
22732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1, global->Get(v8_str("x1"))->Int32Value());
22733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Then
22735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("x1 = x2 = 0;");
22736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  pr = v8::Promise::Resolver::New(isolate);
22737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  qr = v8::Promise::Resolver::New(isolate);
22738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  qr->Resolve(pr);
22740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  qr->GetPromise()->Then(f1)->Then(f2);
22741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
22743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
22744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate->RunMicrotasks();
22745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
22746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
22747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  pr->Resolve(v8::Integer::New(isolate, 3));
22749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
22751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
22752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate->RunMicrotasks();
22753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(3, global->Get(v8_str("x1"))->Int32Value());
22754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(4, global->Get(v8_str("x2"))->Int32Value());
22755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
22756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(DisallowJavascriptExecutionScope) {
22759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
22760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
22761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
22762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate::DisallowJavascriptExecutionScope no_js(
22763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate, v8::Isolate::DisallowJavascriptExecutionScope::CRASH_ON_FAILURE);
22764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("2+2");
22765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
22766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(AllowJavascriptExecutionScope) {
22769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
22770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
22771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
22772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate::DisallowJavascriptExecutionScope no_js(
22773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate, v8::Isolate::DisallowJavascriptExecutionScope::CRASH_ON_FAILURE);
22774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate::DisallowJavascriptExecutionScope throw_js(
22775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate, v8::Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE);
22776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  { v8::Isolate::AllowJavascriptExecutionScope yes_js(isolate);
22777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CompileRun("1+1");
22778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
22779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
22780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(ThrowOnJavascriptExecution) {
22783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
22784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = context->GetIsolate();
22785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
22786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::TryCatch try_catch;
22787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate::DisallowJavascriptExecutionScope throw_js(
22788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate, v8::Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE);
22789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("1+1");
22790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(try_catch.HasCaught());
22791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
22792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(Regress354123) {
22795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext current;
22796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = current->GetIsolate();
22797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
22798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
22800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  templ->SetAccessCheckCallbacks(NamedAccessCounter, IndexedAccessCounter);
22801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  current->Global()->Set(v8_str("friend"), templ->NewInstance());
22802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Test access using __proto__ from the prototype chain.
22804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  named_access_count = 0;
22805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("friend.__proto__ = {};");
22806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2, named_access_count);
22807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("friend.__proto__;");
22808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(4, named_access_count);
22809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Test access using __proto__ as a hijacked function (A).
22811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  named_access_count = 0;
22812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("var p = Object.prototype;"
22813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "var f = Object.getOwnPropertyDescriptor(p, '__proto__').set;"
22814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "f.call(friend, {});");
22815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1, named_access_count);
22816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("var p = Object.prototype;"
22817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "var f = Object.getOwnPropertyDescriptor(p, '__proto__').get;"
22818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "f.call(friend);");
22819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2, named_access_count);
22820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Test access using __proto__ as a hijacked function (B).
22822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  named_access_count = 0;
22823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("var f = Object.prototype.__lookupSetter__('__proto__');"
22824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "f.call(friend, {});");
22825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1, named_access_count);
22826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("var f = Object.prototype.__lookupGetter__('__proto__');"
22827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "f.call(friend);");
22828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2, named_access_count);
22829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Test access using Object.setPrototypeOf reflective method.
22831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  named_access_count = 0;
22832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("Object.setPrototypeOf(friend, {});");
22833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1, named_access_count);
22834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("Object.getPrototypeOf(friend);");
22835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2, named_access_count);
22836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
22837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(CaptureStackTraceForStackOverflow) {
22840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::internal::FLAG_stack_size = 150;
22841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext current;
22842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = current->GetIsolate();
22843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
22844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  V8::SetCaptureStackTraceForUncaughtExceptions(
22845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      true, 10, v8::StackTrace::kDetailed);
22846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::TryCatch try_catch;
22847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("(function f(x) { f(x+1); })(0)");
22848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(try_catch.HasCaught());
22849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
22850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(ScriptNameAndLineNumber) {
22853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
22854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
22855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
22856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* url = "http://www.foo.com/foo.js";
22857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::ScriptOrigin origin(v8_str(url), v8::Integer::New(isolate, 13));
22858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::ScriptCompiler::Source script_source(v8_str("var foo;"), origin);
22859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Script> script = v8::ScriptCompiler::Compile(
22860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate, &script_source);
22861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Value> script_name = script->GetUnboundScript()->GetScriptName();
22862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!script_name.IsEmpty());
22863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(script_name->IsString());
22864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  String::Utf8Value utf8_name(script_name);
22865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(url, *utf8_name);
22866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int line_number = script->GetUnboundScript()->GetLineNumber(0);
22867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(13, line_number);
22868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
22869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid SourceURLHelper(const char* source, const char* expected_source_url,
22872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     const char* expected_source_mapping_url) {
22873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Script> script = v8_compile(source);
22874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (expected_source_url != NULL) {
22875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::String::Utf8Value url(script->GetUnboundScript()->GetSourceURL());
22876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(expected_source_url, *url);
22877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
22878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(script->GetUnboundScript()->GetSourceURL()->IsUndefined());
22879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
22880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (expected_source_mapping_url != NULL) {
22881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::String::Utf8Value url(
22882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        script->GetUnboundScript()->GetSourceMappingURL());
22883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(expected_source_mapping_url, *url);
22884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
22885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(script->GetUnboundScript()->GetSourceMappingURL()->IsUndefined());
22886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
22887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
22888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(ScriptSourceURLAndSourceMappingURL) {
22891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
22892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
22893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
22894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SourceURLHelper("function foo() {}\n"
22895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  "//# sourceURL=bar1.js\n", "bar1.js", NULL);
22896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SourceURLHelper("function foo() {}\n"
22897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  "//# sourceMappingURL=bar2.js\n", NULL, "bar2.js");
22898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Both sourceURL and sourceMappingURL.
22900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SourceURLHelper("function foo() {}\n"
22901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  "//# sourceURL=bar3.js\n"
22902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  "//# sourceMappingURL=bar4.js\n", "bar3.js", "bar4.js");
22903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Two source URLs; the first one is ignored.
22905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SourceURLHelper("function foo() {}\n"
22906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  "//# sourceURL=ignoreme.js\n"
22907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  "//# sourceURL=bar5.js\n", "bar5.js", NULL);
22908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SourceURLHelper("function foo() {}\n"
22909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  "//# sourceMappingURL=ignoreme.js\n"
22910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  "//# sourceMappingURL=bar6.js\n", NULL, "bar6.js");
22911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // SourceURL or sourceMappingURL in the middle of the script.
22913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SourceURLHelper("function foo() {}\n"
22914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  "//# sourceURL=bar7.js\n"
22915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  "function baz() {}\n", "bar7.js", NULL);
22916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SourceURLHelper("function foo() {}\n"
22917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  "//# sourceMappingURL=bar8.js\n"
22918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  "function baz() {}\n", NULL, "bar8.js");
22919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Too much whitespace.
22921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SourceURLHelper("function foo() {}\n"
22922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  "//#  sourceURL=bar9.js\n"
22923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  "//#  sourceMappingURL=bar10.js\n", NULL, NULL);
22924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SourceURLHelper("function foo() {}\n"
22925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  "//# sourceURL =bar11.js\n"
22926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  "//# sourceMappingURL =bar12.js\n", NULL, NULL);
22927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Disallowed characters in value.
22929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SourceURLHelper("function foo() {}\n"
22930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  "//# sourceURL=bar13 .js   \n"
22931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  "//# sourceMappingURL=bar14 .js \n",
22932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  NULL, NULL);
22933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SourceURLHelper("function foo() {}\n"
22934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  "//# sourceURL=bar15\t.js   \n"
22935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  "//# sourceMappingURL=bar16\t.js \n",
22936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  NULL, NULL);
22937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SourceURLHelper("function foo() {}\n"
22938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  "//# sourceURL=bar17'.js   \n"
22939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  "//# sourceMappingURL=bar18'.js \n",
22940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  NULL, NULL);
22941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SourceURLHelper("function foo() {}\n"
22942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  "//# sourceURL=bar19\".js   \n"
22943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  "//# sourceMappingURL=bar20\".js \n",
22944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  NULL, NULL);
22945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Not too much whitespace.
22947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SourceURLHelper("function foo() {}\n"
22948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  "//# sourceURL=  bar21.js   \n"
22949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  "//# sourceMappingURL=  bar22.js \n", "bar21.js", "bar22.js");
22950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
22951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(GetOwnPropertyDescriptor) {
22954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
22955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
22956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
22957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun(
22958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "var x = { value : 13};"
22959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "Object.defineProperty(x, 'p0', {value : 12});"
22960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "Object.defineProperty(x, 'p1', {"
22961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "  set : function(value) { this.value = value; },"
22962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "  get : function() { return this.value; },"
22963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "});");
22964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Object> x = Local<Object>::Cast(env->Global()->Get(v8_str("x")));
22965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Value> desc = x->GetOwnPropertyDescriptor(v8_str("no_prop"));
22966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(desc->IsUndefined());
22967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  desc = x->GetOwnPropertyDescriptor(v8_str("p0"));
22968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(v8_num(12), Local<Object>::Cast(desc)->Get(v8_str("value")));
22969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  desc = x->GetOwnPropertyDescriptor(v8_str("p1"));
22970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Function> set =
22971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<Function>::Cast(Local<Object>::Cast(desc)->Get(v8_str("set")));
22972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Local<Function> get =
22973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Local<Function>::Cast(Local<Object>::Cast(desc)->Get(v8_str("get")));
22974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(v8_num(13), get->Call(x, 0, NULL));
22975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Value> args[] = { v8_num(14) };
22976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set->Call(x, 1, args);
22977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(v8_num(14), get->Call(x, 0, NULL));
22978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
22979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(Regress411877) {
22982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
22983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(isolate);
22984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> object_template =
22985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::ObjectTemplate::New(isolate);
22986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  object_template->SetAccessCheckCallbacks(NamedAccessCounter,
22987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           IndexedAccessCounter);
22988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<Context> context = Context::New(isolate);
22990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Context::Scope context_scope(context);
22991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context->Global()->Set(v8_str("o"), object_template->NewInstance());
22993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("Object.getOwnPropertyNames(o)");
22994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
22995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(GetHiddenPropertyTableAfterAccessCheck) {
22998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
22999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(isolate);
23000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> object_template =
23001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::ObjectTemplate::New(isolate);
23002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  object_template->SetAccessCheckCallbacks(NamedAccessCounter,
23003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           IndexedAccessCounter);
23004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
23005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<Context> context = Context::New(isolate);
23006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Context::Scope context_scope(context);
23007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
23008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Object> obj = object_template->NewInstance();
23009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  obj->Set(v8_str("key"), v8_str("value"));
23010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  obj->Delete(v8_str("key"));
23011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
23012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  obj->SetHiddenValue(v8_str("hidden key 2"), v8_str("hidden value 2"));
23013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
23014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
23015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
23016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(Regress411793) {
23017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
23018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope handle_scope(isolate);
23019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> object_template =
23020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::ObjectTemplate::New(isolate);
23021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  object_template->SetAccessCheckCallbacks(NamedAccessCounter,
23022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           IndexedAccessCounter);
23023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
23024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<Context> context = Context::New(isolate);
23025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Context::Scope context_scope(context);
23026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
23027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context->Global()->Set(v8_str("o"), object_template->NewInstance());
23028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun(
23029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "Object.defineProperty(o, 'key', "
23030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "    { get: function() {}, set: function() {} });");
23031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
23032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
23033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass TestSourceStream : public v8::ScriptCompiler::ExternalSourceStream {
23034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
23035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  explicit TestSourceStream(const char** chunks) : chunks_(chunks), index_(0) {}
23036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
23037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  virtual size_t GetMoreData(const uint8_t** src) {
23038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Unlike in real use cases, this function will never block.
23039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (chunks_[index_] == NULL) {
23040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return 0;
23041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
23042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Copy the data, since the caller takes ownership of it.
23043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    size_t len = strlen(chunks_[index_]);
23044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // We don't need to zero-terminate since we return the length.
23045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint8_t* copy = new uint8_t[len];
23046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    memcpy(copy, chunks_[index_], len);
23047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    *src = copy;
23048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ++index_;
23049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return len;
23050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
23051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
23052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Helper for constructing a string from chunks (the compilation needs it
23053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // too).
23054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static char* FullSourceString(const char** chunks) {
23055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    size_t total_len = 0;
23056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (size_t i = 0; chunks[i] != NULL; ++i) {
23057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      total_len += strlen(chunks[i]);
23058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
23059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    char* full_string = new char[total_len + 1];
23060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    size_t offset = 0;
23061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (size_t i = 0; chunks[i] != NULL; ++i) {
23062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      size_t len = strlen(chunks[i]);
23063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      memcpy(full_string + offset, chunks[i], len);
23064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      offset += len;
23065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
23066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    full_string[total_len] = 0;
23067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return full_string;
23068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
23069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
23070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
23071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char** chunks_;
23072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  unsigned index_;
23073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
23074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
23075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
23076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Helper function for running streaming tests.
23077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid RunStreamingTest(const char** chunks,
23078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      v8::ScriptCompiler::StreamedSource::Encoding encoding =
23079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          v8::ScriptCompiler::StreamedSource::ONE_BYTE,
23080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      bool expected_success = true) {
23081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
23082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
23083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
23084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::TryCatch try_catch;
23085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
23086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::ScriptCompiler::StreamedSource source(new TestSourceStream(chunks),
23087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                            encoding);
23088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::ScriptCompiler::ScriptStreamingTask* task =
23089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::ScriptCompiler::StartStreamingScript(isolate, &source);
23090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
23091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // TestSourceStream::GetMoreData won't block, so it's OK to just run the
23092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // task here in the main thread.
23093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  task->Run();
23094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  delete task;
23095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
23096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::ScriptOrigin origin(v8_str("http://foo.com"));
23097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  char* full_source = TestSourceStream::FullSourceString(chunks);
23098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
23099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The possible errors are only produced while compiling.
23100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(false, try_catch.HasCaught());
23101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
23102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<Script> script = v8::ScriptCompiler::Compile(
23103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate, &source, v8_str(full_source), origin);
23104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (expected_success) {
23105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(!script.IsEmpty());
23106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Handle<Value> result(script->Run());
23107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // All scripts are supposed to return the fixed value 13 when ran.
23108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(13, result->Int32Value());
23109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
23110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(script.IsEmpty());
23111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(try_catch.HasCaught());
23112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
23113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  delete[] full_source;
23114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
23115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
23116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
23117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(StreamingSimpleScript) {
23118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // This script is unrealistically small, since no one chunk is enough to fill
23119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the backing buffer of Scanner, let alone overflow it.
23120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo(); ",
23121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          NULL};
23122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RunStreamingTest(chunks);
23123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
23124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
23125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
23126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(StreamingBiggerScript) {
23127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* chunk1 =
23128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "function foo() {\n"
23129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  // Make this chunk sufficiently long so that it will overflow the\n"
23130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  // backing buffer of the Scanner.\n"
23131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  var i = 0;\n"
23132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  var result = 0;\n"
23133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  for (i = 0; i < 13; ++i) { result = result + 1; }\n"
23134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  result = 0;\n"
23135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  for (i = 0; i < 13; ++i) { result = result + 1; }\n"
23136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  result = 0;\n"
23137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  for (i = 0; i < 13; ++i) { result = result + 1; }\n"
23138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  result = 0;\n"
23139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  for (i = 0; i < 13; ++i) { result = result + 1; }\n"
23140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  return result;\n"
23141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "}\n";
23142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* chunks[] = {chunk1, "foo(); ", NULL};
23143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RunStreamingTest(chunks);
23144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
23145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
23146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
23147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(StreamingScriptWithParseError) {
23148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Test that parse errors from streamed scripts are propagated correctly.
23149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
23150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    char chunk1[] =
23151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "  // This will result in a parse error.\n"
23152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "  var if else then foo";
23153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    char chunk2[] = "  13\n";
23154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
23155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
23156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::ONE_BYTE,
23157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     false);
23158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
23159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Test that the next script succeeds normally.
23160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
23161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    char chunk1[] =
23162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "  // This will be parsed successfully.\n"
23163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "  function foo() { return ";
23164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    char chunk2[] = "  13; }\n";
23165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
23166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
23167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    RunStreamingTest(chunks);
23168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
23169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
23170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
23171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
23172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(StreamingUtf8Script) {
23173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // We'd want to write \uc481 instead of \xeb\x91\x80, but Windows compilers
23174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // don't like it.
23175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* chunk1 =
23176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "function foo() {\n"
23177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  // This function will contain an UTF-8 character which is not in\n"
23178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  // ASCII.\n"
23179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  var foob\xeb\x91\x80r = 13;\n"
23180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  return foob\xeb\x91\x80r;\n"
23181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "}\n";
23182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* chunks[] = {chunk1, "foo(); ", NULL};
23183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
23184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
23185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
23186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
23187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(StreamingUtf8ScriptWithSplitCharactersSanityCheck) {
23188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // A sanity check to prove that the approach of splitting UTF-8
23189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // characters is correct. Here is an UTF-8 character which will take three
23190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // bytes.
23191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* reference = "\xeb\x91\x80";
23192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(3u == strlen(reference));  // NOLINT - no CHECK_EQ for unsigned.
23193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
23194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  char chunk1[] =
23195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "function foo() {\n"
23196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  // This function will contain an UTF-8 character which is not in\n"
23197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  // ASCII.\n"
23198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  var foob";
23199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  char chunk2[] =
23200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "XXXr = 13;\n"
23201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  return foob\xeb\x91\x80r;\n"
23202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "}\n";
23203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < 3; ++i) {
23204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    chunk2[i] = reference[i];
23205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
23206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
23207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
23208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
23209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
23210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
23211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(StreamingUtf8ScriptWithSplitCharacters) {
23212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Stream data where a multi-byte UTF-8 character is split between two data
23213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // chunks.
23214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* reference = "\xeb\x91\x80";
23215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  char chunk1[] =
23216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "function foo() {\n"
23217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  // This function will contain an UTF-8 character which is not in\n"
23218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  // ASCII.\n"
23219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  var foobX";
23220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  char chunk2[] =
23221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "XXr = 13;\n"
23222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  return foob\xeb\x91\x80r;\n"
23223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "}\n";
23224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  chunk1[strlen(chunk1) - 1] = reference[0];
23225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  chunk2[0] = reference[1];
23226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  chunk2[1] = reference[2];
23227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
23228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
23229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
23230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
23231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
23232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(StreamingUtf8ScriptWithSplitCharactersValidEdgeCases) {
23233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Tests edge cases which should still be decoded correctly.
23234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
23235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Case 1: a chunk contains only bytes for a split character (and no other
23236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // data). This kind of a chunk would be exceptionally small, but we should
23237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // still decode it correctly.
23238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* reference = "\xeb\x91\x80";
23239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The small chunk is at the beginning of the split character
23240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
23241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    char chunk1[] =
23242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "function foo() {\n"
23243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "  // This function will contain an UTF-8 character which is not in\n"
23244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "  // ASCII.\n"
23245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "  var foob";
23246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    char chunk2[] = "XX";
23247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    char chunk3[] =
23248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "Xr = 13;\n"
23249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "  return foob\xeb\x91\x80r;\n"
23250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "}\n";
23251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    chunk2[0] = reference[0];
23252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    chunk2[1] = reference[1];
23253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    chunk3[0] = reference[2];
23254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", NULL};
23255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
23256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
23257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The small chunk is at the end of a character
23258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
23259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    char chunk1[] =
23260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "function foo() {\n"
23261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "  // This function will contain an UTF-8 character which is not in\n"
23262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "  // ASCII.\n"
23263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "  var foobX";
23264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    char chunk2[] = "XX";
23265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    char chunk3[] =
23266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "r = 13;\n"
23267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "  return foob\xeb\x91\x80r;\n"
23268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "}\n";
23269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    chunk1[strlen(chunk1) - 1] = reference[0];
23270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    chunk2[0] = reference[1];
23271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    chunk2[1] = reference[2];
23272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", NULL};
23273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
23274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
23275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Case 2: the script ends with a multi-byte character. Make sure that it's
23276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // decoded correctly and not just ignored.
23277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
23278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    char chunk1[] =
23279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "var foob\xeb\x91\x80 = 13;\n"
23280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "foob\xeb\x91\x80";
23281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const char* chunks[] = {chunk1, NULL};
23282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
23283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
23284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
23285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
23286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
23287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(StreamingUtf8ScriptWithSplitCharactersInvalidEdgeCases) {
23288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Test cases where a UTF-8 character is split over several chunks. Those
23289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // cases are not supported (the embedder should give the data in big enough
23290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // chunks), but we shouldn't crash, just produce a parse error.
23291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* reference = "\xeb\x91\x80";
23292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  char chunk1[] =
23293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "function foo() {\n"
23294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  // This function will contain an UTF-8 character which is not in\n"
23295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  // ASCII.\n"
23296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  var foobX";
23297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  char chunk2[] = "X";
23298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  char chunk3[] =
23299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "Xr = 13;\n"
23300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  return foob\xeb\x91\x80r;\n"
23301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "}\n";
23302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  chunk1[strlen(chunk1) - 1] = reference[0];
23303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  chunk2[0] = reference[1];
23304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  chunk3[0] = reference[2];
23305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", NULL};
23306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
23307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, false);
23308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
23309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
23310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
23311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(StreamingProducesParserCache) {
23312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::FLAG_min_preparse_length = 0;
23313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo(); ",
23314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          NULL};
23315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
23316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
23317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
23318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
23319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
23320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::ScriptCompiler::StreamedSource source(
23321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      new TestSourceStream(chunks),
23322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::ScriptCompiler::StreamedSource::ONE_BYTE);
23323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::ScriptCompiler::ScriptStreamingTask* task =
23324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::ScriptCompiler::StartStreamingScript(
23325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          isolate, &source, v8::ScriptCompiler::kProduceParserCache);
23326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
23327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // TestSourceStream::GetMoreData won't block, so it's OK to just run the
23328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // task here in the main thread.
23329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  task->Run();
23330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  delete task;
23331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
23332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const v8::ScriptCompiler::CachedData* cached_data = source.GetCachedData();
23333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(cached_data != NULL);
23334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(cached_data->data != NULL);
23335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_GT(cached_data->length, 0);
23336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
23337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
23338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
23339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(StreamingScriptWithInvalidUtf8) {
23340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Regression test for a crash: test that invalid UTF-8 bytes in the end of a
23341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // chunk don't produce a crash.
23342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* reference = "\xeb\x91\x80\x80\x80";
23343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  char chunk1[] =
23344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "function foo() {\n"
23345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  // This function will contain an UTF-8 character which is not in\n"
23346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  // ASCII.\n"
23347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  var foobXXXXX";  // Too many bytes which look like incomplete chars!
23348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  char chunk2[] =
23349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "r = 13;\n"
23350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  return foob\xeb\x91\x80\x80\x80r;\n"
23351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "}\n";
23352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < 5; ++i) chunk1[strlen(chunk1) - 5 + i] = reference[i];
23353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
23354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
23355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, false);
23356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
23357