1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "src/api.h"
6 
7 #include <string.h>  // For memcpy, strlen.
8 #ifdef V8_USE_ADDRESS_SANITIZER
9 #include <sanitizer/asan_interface.h>
10 #endif  // V8_USE_ADDRESS_SANITIZER
11 #include <cmath>  // For isnan.
12 #include "include/v8-debug.h"
13 #include "include/v8-profiler.h"
14 #include "include/v8-testing.h"
15 #include "src/assert-scope.h"
16 #include "src/background-parsing-task.h"
17 #include "src/base/platform/platform.h"
18 #include "src/base/platform/time.h"
19 #include "src/base/utils/random-number-generator.h"
20 #include "src/bootstrapper.h"
21 #include "src/code-stubs.h"
22 #include "src/compiler.h"
23 #include "src/conversions-inl.h"
24 #include "src/counters.h"
25 #include "src/cpu-profiler.h"
26 #include "src/debug.h"
27 #include "src/deoptimizer.h"
28 #include "src/execution.h"
29 #include "src/global-handles.h"
30 #include "src/heap-profiler.h"
31 #include "src/heap-snapshot-generator-inl.h"
32 #include "src/icu_util.h"
33 #include "src/json-parser.h"
34 #include "src/messages.h"
35 #include "src/natives.h"
36 #include "src/parser.h"
37 #include "src/profile-generator-inl.h"
38 #include "src/property.h"
39 #include "src/property-details.h"
40 #include "src/prototype.h"
41 #include "src/runtime.h"
42 #include "src/runtime-profiler.h"
43 #include "src/scanner-character-streams.h"
44 #include "src/simulator.h"
45 #include "src/snapshot.h"
46 #include "src/unicode-inl.h"
47 #include "src/v8threads.h"
48 #include "src/version.h"
49 #include "src/vm-state-inl.h"
50 
51 
52 #define LOG_API(isolate, expr) LOG(isolate, ApiEntryCall(expr))
53 
54 #define ENTER_V8(isolate)                                          \
55   DCHECK((isolate)->IsInitialized());                              \
56   i::VMState<i::OTHER> __state__((isolate))
57 
58 namespace v8 {
59 
60 #define ON_BAILOUT(isolate, location, code)                        \
61   if (IsExecutionTerminatingCheck(isolate)) {                      \
62     code;                                                          \
63     UNREACHABLE();                                                 \
64   }
65 
66 
67 #define EXCEPTION_PREAMBLE(isolate)                                         \
68   (isolate)->handle_scope_implementer()->IncrementCallDepth();              \
69   DCHECK(!(isolate)->external_caught_exception());                          \
70   bool has_pending_exception = false
71 
72 
73 #define EXCEPTION_BAILOUT_CHECK_GENERIC(isolate, value, do_callback)           \
74   do {                                                                         \
75     i::HandleScopeImplementer* handle_scope_implementer =                      \
76         (isolate)->handle_scope_implementer();                                 \
77     handle_scope_implementer->DecrementCallDepth();                            \
78     if (has_pending_exception) {                                               \
79       bool call_depth_is_zero = handle_scope_implementer->CallDepthIsZero();   \
80       (isolate)->OptionalRescheduleException(call_depth_is_zero);              \
81       do_callback                                                              \
82       return value;                                                            \
83     }                                                                          \
84     do_callback                                                                \
85   } while (false)
86 
87 
88 #define EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, value)                    \
89   EXCEPTION_BAILOUT_CHECK_GENERIC(                                             \
90       isolate, value, isolate->FireCallCompletedCallback();)
91 
92 
93 #define EXCEPTION_BAILOUT_CHECK(isolate, value)                                \
94   EXCEPTION_BAILOUT_CHECK_GENERIC(isolate, value, ;)
95 
96 
97 // --- E x c e p t i o n   B e h a v i o r ---
98 
99 
FatalProcessOutOfMemory(const char * location)100 void i::FatalProcessOutOfMemory(const char* location) {
101   i::V8::FatalProcessOutOfMemory(location, false);
102 }
103 
104 
105 // When V8 cannot allocated memory FatalProcessOutOfMemory is called.
106 // The default fatal error handler is called and execution is stopped.
FatalProcessOutOfMemory(const char * location,bool take_snapshot)107 void i::V8::FatalProcessOutOfMemory(const char* location, bool take_snapshot) {
108   i::HeapStats heap_stats;
109   int start_marker;
110   heap_stats.start_marker = &start_marker;
111   int new_space_size;
112   heap_stats.new_space_size = &new_space_size;
113   int new_space_capacity;
114   heap_stats.new_space_capacity = &new_space_capacity;
115   intptr_t old_pointer_space_size;
116   heap_stats.old_pointer_space_size = &old_pointer_space_size;
117   intptr_t old_pointer_space_capacity;
118   heap_stats.old_pointer_space_capacity = &old_pointer_space_capacity;
119   intptr_t old_data_space_size;
120   heap_stats.old_data_space_size = &old_data_space_size;
121   intptr_t old_data_space_capacity;
122   heap_stats.old_data_space_capacity = &old_data_space_capacity;
123   intptr_t code_space_size;
124   heap_stats.code_space_size = &code_space_size;
125   intptr_t code_space_capacity;
126   heap_stats.code_space_capacity = &code_space_capacity;
127   intptr_t map_space_size;
128   heap_stats.map_space_size = &map_space_size;
129   intptr_t map_space_capacity;
130   heap_stats.map_space_capacity = &map_space_capacity;
131   intptr_t cell_space_size;
132   heap_stats.cell_space_size = &cell_space_size;
133   intptr_t cell_space_capacity;
134   heap_stats.cell_space_capacity = &cell_space_capacity;
135   intptr_t property_cell_space_size;
136   heap_stats.property_cell_space_size = &property_cell_space_size;
137   intptr_t property_cell_space_capacity;
138   heap_stats.property_cell_space_capacity = &property_cell_space_capacity;
139   intptr_t lo_space_size;
140   heap_stats.lo_space_size = &lo_space_size;
141   int global_handle_count;
142   heap_stats.global_handle_count = &global_handle_count;
143   int weak_global_handle_count;
144   heap_stats.weak_global_handle_count = &weak_global_handle_count;
145   int pending_global_handle_count;
146   heap_stats.pending_global_handle_count = &pending_global_handle_count;
147   int near_death_global_handle_count;
148   heap_stats.near_death_global_handle_count = &near_death_global_handle_count;
149   int free_global_handle_count;
150   heap_stats.free_global_handle_count = &free_global_handle_count;
151   intptr_t memory_allocator_size;
152   heap_stats.memory_allocator_size = &memory_allocator_size;
153   intptr_t memory_allocator_capacity;
154   heap_stats.memory_allocator_capacity = &memory_allocator_capacity;
155   int objects_per_type[LAST_TYPE + 1] = {0};
156   heap_stats.objects_per_type = objects_per_type;
157   int size_per_type[LAST_TYPE + 1] = {0};
158   heap_stats.size_per_type = size_per_type;
159   int os_error;
160   heap_stats.os_error = &os_error;
161   int end_marker;
162   heap_stats.end_marker = &end_marker;
163   i::Isolate* isolate = i::Isolate::Current();
164   if (isolate->heap()->HasBeenSetUp()) {
165     // BUG(1718): Don't use the take_snapshot since we don't support
166     // HeapIterator here without doing a special GC.
167     isolate->heap()->RecordStats(&heap_stats, false);
168   }
169   Utils::ApiCheck(false, location, "Allocation failed - process out of memory");
170   // If the fatal error handler returns, we stop execution.
171   FATAL("API fatal error handler returned after process out of memory");
172 }
173 
174 
ReportApiFailure(const char * location,const char * message)175 void Utils::ReportApiFailure(const char* location, const char* message) {
176   i::Isolate* isolate = i::Isolate::Current();
177   FatalErrorCallback callback = isolate->exception_behavior();
178   if (callback == NULL) {
179     base::OS::PrintError("\n#\n# Fatal error in %s\n# %s\n#\n\n", location,
180                          message);
181     base::OS::Abort();
182   } else {
183     callback(location, message);
184   }
185   isolate->SignalFatalError();
186 }
187 
188 
IsDead()189 bool V8::IsDead() {
190   i::Isolate* isolate = i::Isolate::Current();
191   return isolate->IsDead();
192 }
193 
194 
IsExecutionTerminatingCheck(i::Isolate * isolate)195 static inline bool IsExecutionTerminatingCheck(i::Isolate* isolate) {
196   if (!isolate->IsInitialized()) return false;
197   if (isolate->has_scheduled_exception()) {
198     return isolate->scheduled_exception() ==
199         isolate->heap()->termination_exception();
200   }
201   return false;
202 }
203 
204 
StartupDataDecompressor()205 StartupDataDecompressor::StartupDataDecompressor()
206     : raw_data(i::NewArray<char*>(V8::GetCompressedStartupDataCount())) {
207   for (int i = 0; i < V8::GetCompressedStartupDataCount(); ++i) {
208     raw_data[i] = NULL;
209   }
210 }
211 
212 
~StartupDataDecompressor()213 StartupDataDecompressor::~StartupDataDecompressor() {
214   for (int i = 0; i < V8::GetCompressedStartupDataCount(); ++i) {
215     i::DeleteArray(raw_data[i]);
216   }
217   i::DeleteArray(raw_data);
218 }
219 
220 
Decompress()221 int StartupDataDecompressor::Decompress() {
222   int compressed_data_count = V8::GetCompressedStartupDataCount();
223   StartupData* compressed_data =
224       i::NewArray<StartupData>(compressed_data_count);
225   V8::GetCompressedStartupData(compressed_data);
226   for (int i = 0; i < compressed_data_count; ++i) {
227     char* decompressed = raw_data[i] =
228         i::NewArray<char>(compressed_data[i].raw_size);
229     if (compressed_data[i].compressed_size != 0) {
230       int result = DecompressData(decompressed,
231                                   &compressed_data[i].raw_size,
232                                   compressed_data[i].data,
233                                   compressed_data[i].compressed_size);
234       if (result != 0) return result;
235     } else {
236       DCHECK_EQ(0, compressed_data[i].raw_size);
237     }
238     compressed_data[i].data = decompressed;
239   }
240   V8::SetDecompressedStartupData(compressed_data);
241   i::DeleteArray(compressed_data);
242   return 0;
243 }
244 
245 
GetCompressedStartupDataAlgorithm()246 StartupData::CompressionAlgorithm V8::GetCompressedStartupDataAlgorithm() {
247 #ifdef COMPRESS_STARTUP_DATA_BZ2
248   return StartupData::kBZip2;
249 #else
250   return StartupData::kUncompressed;
251 #endif
252 }
253 
254 
255 enum CompressedStartupDataItems {
256   kSnapshot = 0,
257   kSnapshotContext,
258   kLibraries,
259   kExperimentalLibraries,
260   kCompressedStartupDataCount
261 };
262 
263 
GetCompressedStartupDataCount()264 int V8::GetCompressedStartupDataCount() {
265 #ifdef COMPRESS_STARTUP_DATA_BZ2
266   return kCompressedStartupDataCount;
267 #else
268   return 0;
269 #endif
270 }
271 
272 
GetCompressedStartupData(StartupData * compressed_data)273 void V8::GetCompressedStartupData(StartupData* compressed_data) {
274 #ifdef COMPRESS_STARTUP_DATA_BZ2
275   compressed_data[kSnapshot].data =
276       reinterpret_cast<const char*>(i::Snapshot::data());
277   compressed_data[kSnapshot].compressed_size = i::Snapshot::size();
278   compressed_data[kSnapshot].raw_size = i::Snapshot::raw_size();
279 
280   compressed_data[kSnapshotContext].data =
281       reinterpret_cast<const char*>(i::Snapshot::context_data());
282   compressed_data[kSnapshotContext].compressed_size =
283       i::Snapshot::context_size();
284   compressed_data[kSnapshotContext].raw_size = i::Snapshot::context_raw_size();
285 
286   i::Vector<const i::byte> libraries_source = i::Natives::GetScriptsSource();
287   compressed_data[kLibraries].data =
288       reinterpret_cast<const char*>(libraries_source.start());
289   compressed_data[kLibraries].compressed_size = libraries_source.length();
290   compressed_data[kLibraries].raw_size = i::Natives::GetRawScriptsSize();
291 
292   i::Vector<const i::byte> exp_libraries_source =
293       i::ExperimentalNatives::GetScriptsSource();
294   compressed_data[kExperimentalLibraries].data =
295       reinterpret_cast<const char*>(exp_libraries_source.start());
296   compressed_data[kExperimentalLibraries].compressed_size =
297       exp_libraries_source.length();
298   compressed_data[kExperimentalLibraries].raw_size =
299       i::ExperimentalNatives::GetRawScriptsSize();
300 #endif
301 }
302 
303 
SetDecompressedStartupData(StartupData * decompressed_data)304 void V8::SetDecompressedStartupData(StartupData* decompressed_data) {
305 #ifdef COMPRESS_STARTUP_DATA_BZ2
306   DCHECK_EQ(i::Snapshot::raw_size(), decompressed_data[kSnapshot].raw_size);
307   i::Snapshot::set_raw_data(
308       reinterpret_cast<const i::byte*>(decompressed_data[kSnapshot].data));
309 
310   DCHECK_EQ(i::Snapshot::context_raw_size(),
311             decompressed_data[kSnapshotContext].raw_size);
312   i::Snapshot::set_context_raw_data(
313       reinterpret_cast<const i::byte*>(
314           decompressed_data[kSnapshotContext].data));
315 
316   DCHECK_EQ(i::Natives::GetRawScriptsSize(),
317             decompressed_data[kLibraries].raw_size);
318   i::Vector<const char> libraries_source(
319       decompressed_data[kLibraries].data,
320       decompressed_data[kLibraries].raw_size);
321   i::Natives::SetRawScriptsSource(libraries_source);
322 
323   DCHECK_EQ(i::ExperimentalNatives::GetRawScriptsSize(),
324             decompressed_data[kExperimentalLibraries].raw_size);
325   i::Vector<const char> exp_libraries_source(
326       decompressed_data[kExperimentalLibraries].data,
327       decompressed_data[kExperimentalLibraries].raw_size);
328   i::ExperimentalNatives::SetRawScriptsSource(exp_libraries_source);
329 #endif
330 }
331 
332 
SetNativesDataBlob(StartupData * natives_blob)333 void V8::SetNativesDataBlob(StartupData* natives_blob) {
334 #ifdef V8_USE_EXTERNAL_STARTUP_DATA
335   i::SetNativesFromFile(natives_blob);
336 #else
337   CHECK(false);
338 #endif
339 }
340 
341 
SetSnapshotDataBlob(StartupData * snapshot_blob)342 void V8::SetSnapshotDataBlob(StartupData* snapshot_blob) {
343 #ifdef V8_USE_EXTERNAL_STARTUP_DATA
344   i::SetSnapshotFromFile(snapshot_blob);
345 #else
346   CHECK(false);
347 #endif
348 }
349 
350 
SetFatalErrorHandler(FatalErrorCallback that)351 void V8::SetFatalErrorHandler(FatalErrorCallback that) {
352   i::Isolate* isolate = i::Isolate::Current();
353   isolate->set_exception_behavior(that);
354 }
355 
356 
SetAllowCodeGenerationFromStringsCallback(AllowCodeGenerationFromStringsCallback callback)357 void V8::SetAllowCodeGenerationFromStringsCallback(
358     AllowCodeGenerationFromStringsCallback callback) {
359   i::Isolate* isolate = i::Isolate::Current();
360   isolate->set_allow_code_gen_callback(callback);
361 }
362 
363 
SetFlagsFromString(const char * str,int length)364 void V8::SetFlagsFromString(const char* str, int length) {
365   i::FlagList::SetFlagsFromString(str, length);
366 }
367 
368 
SetFlagsFromCommandLine(int * argc,char ** argv,bool remove_flags)369 void V8::SetFlagsFromCommandLine(int* argc, char** argv, bool remove_flags) {
370   i::FlagList::SetFlagsFromCommandLine(argc, argv, remove_flags);
371 }
372 
373 
374 RegisteredExtension* RegisteredExtension::first_extension_ = NULL;
375 
376 
RegisteredExtension(Extension * extension)377 RegisteredExtension::RegisteredExtension(Extension* extension)
378     : extension_(extension) { }
379 
380 
Register(RegisteredExtension * that)381 void RegisteredExtension::Register(RegisteredExtension* that) {
382   that->next_ = first_extension_;
383   first_extension_ = that;
384 }
385 
386 
UnregisterAll()387 void RegisteredExtension::UnregisterAll() {
388   RegisteredExtension* re = first_extension_;
389   while (re != NULL) {
390     RegisteredExtension* next = re->next();
391     delete re;
392     re = next;
393   }
394   first_extension_ = NULL;
395 }
396 
397 
RegisterExtension(Extension * that)398 void RegisterExtension(Extension* that) {
399   RegisteredExtension* extension = new RegisteredExtension(that);
400   RegisteredExtension::Register(extension);
401 }
402 
403 
Extension(const char * name,const char * source,int dep_count,const char ** deps,int source_length)404 Extension::Extension(const char* name,
405                      const char* source,
406                      int dep_count,
407                      const char** deps,
408                      int source_length)
409     : name_(name),
410       source_length_(source_length >= 0 ?
411                      source_length :
412                      (source ? static_cast<int>(strlen(source)) : 0)),
413       source_(source, source_length_),
414       dep_count_(dep_count),
415       deps_(deps),
416       auto_enable_(false) {
417   CHECK(source != NULL || source_length_ == 0);
418 }
419 
420 
ResourceConstraints()421 ResourceConstraints::ResourceConstraints()
422     : max_semi_space_size_(0),
423       max_old_space_size_(0),
424       max_executable_size_(0),
425       stack_limit_(NULL),
426       max_available_threads_(0),
427       code_range_size_(0) { }
428 
ConfigureDefaults(uint64_t physical_memory,uint64_t virtual_memory_limit,uint32_t number_of_processors)429 void ResourceConstraints::ConfigureDefaults(uint64_t physical_memory,
430                                             uint64_t virtual_memory_limit,
431                                             uint32_t number_of_processors) {
432 #if V8_OS_ANDROID
433   // Android has higher physical memory requirements before raising the maximum
434   // heap size limits since it has no swap space.
435   const uint64_t low_limit = 512ul * i::MB;
436   const uint64_t medium_limit = 1ul * i::GB;
437   const uint64_t high_limit = 2ul * i::GB;
438 #else
439   const uint64_t low_limit = 512ul * i::MB;
440   const uint64_t medium_limit = 768ul * i::MB;
441   const uint64_t high_limit = 1ul  * i::GB;
442 #endif
443 
444   if (physical_memory <= low_limit) {
445     set_max_semi_space_size(i::Heap::kMaxSemiSpaceSizeLowMemoryDevice);
446     set_max_old_space_size(i::Heap::kMaxOldSpaceSizeLowMemoryDevice);
447     set_max_executable_size(i::Heap::kMaxExecutableSizeLowMemoryDevice);
448   } else if (physical_memory <= medium_limit) {
449     set_max_semi_space_size(i::Heap::kMaxSemiSpaceSizeMediumMemoryDevice);
450     set_max_old_space_size(i::Heap::kMaxOldSpaceSizeMediumMemoryDevice);
451     set_max_executable_size(i::Heap::kMaxExecutableSizeMediumMemoryDevice);
452   } else if (physical_memory <= high_limit) {
453     set_max_semi_space_size(i::Heap::kMaxSemiSpaceSizeHighMemoryDevice);
454     set_max_old_space_size(i::Heap::kMaxOldSpaceSizeHighMemoryDevice);
455     set_max_executable_size(i::Heap::kMaxExecutableSizeHighMemoryDevice);
456   } else {
457     set_max_semi_space_size(i::Heap::kMaxSemiSpaceSizeHugeMemoryDevice);
458     set_max_old_space_size(i::Heap::kMaxOldSpaceSizeHugeMemoryDevice);
459     set_max_executable_size(i::Heap::kMaxExecutableSizeHugeMemoryDevice);
460   }
461 
462   set_max_available_threads(i::Max(i::Min(number_of_processors, 4u), 1u));
463 
464   if (virtual_memory_limit > 0 && i::kRequiresCodeRange) {
465     // Reserve no more than 1/8 of the memory for the code range, but at most
466     // kMaximalCodeRangeSize.
467     set_code_range_size(
468         i::Min(i::kMaximalCodeRangeSize / i::MB,
469                static_cast<size_t>((virtual_memory_limit >> 3) / i::MB)));
470   }
471 }
472 
473 
SetResourceConstraints(i::Isolate * isolate,const ResourceConstraints & constraints)474 void SetResourceConstraints(i::Isolate* isolate,
475                             const ResourceConstraints& constraints) {
476   int semi_space_size = constraints.max_semi_space_size();
477   int old_space_size = constraints.max_old_space_size();
478   int max_executable_size = constraints.max_executable_size();
479   size_t code_range_size = constraints.code_range_size();
480   if (semi_space_size != 0 || old_space_size != 0 ||
481       max_executable_size != 0 || code_range_size != 0) {
482     isolate->heap()->ConfigureHeap(semi_space_size, old_space_size,
483                                    max_executable_size, code_range_size);
484   }
485   if (constraints.stack_limit() != NULL) {
486     uintptr_t limit = reinterpret_cast<uintptr_t>(constraints.stack_limit());
487     isolate->stack_guard()->SetStackLimit(limit);
488   }
489 
490   isolate->set_max_available_threads(constraints.max_available_threads());
491 }
492 
493 
GlobalizeReference(i::Isolate * isolate,i::Object ** obj)494 i::Object** V8::GlobalizeReference(i::Isolate* isolate, i::Object** obj) {
495   LOG_API(isolate, "Persistent::New");
496   i::Handle<i::Object> result = isolate->global_handles()->Create(*obj);
497 #ifdef DEBUG
498   (*obj)->ObjectVerify();
499 #endif  // DEBUG
500   return result.location();
501 }
502 
503 
CopyPersistent(i::Object ** obj)504 i::Object** V8::CopyPersistent(i::Object** obj) {
505   i::Handle<i::Object> result = i::GlobalHandles::CopyGlobal(obj);
506 #ifdef DEBUG
507   (*obj)->ObjectVerify();
508 #endif  // DEBUG
509   return result.location();
510 }
511 
512 
MakeWeak(i::Object ** object,void * parameters,WeakCallback weak_callback)513 void V8::MakeWeak(i::Object** object,
514                   void* parameters,
515                   WeakCallback weak_callback) {
516   i::GlobalHandles::MakeWeak(object, parameters, weak_callback);
517 }
518 
519 
ClearWeak(i::Object ** obj)520 void* V8::ClearWeak(i::Object** obj) {
521   return i::GlobalHandles::ClearWeakness(obj);
522 }
523 
524 
DisposeGlobal(i::Object ** obj)525 void V8::DisposeGlobal(i::Object** obj) {
526   i::GlobalHandles::Destroy(obj);
527 }
528 
529 
Eternalize(Isolate * v8_isolate,Value * value,int * index)530 void V8::Eternalize(Isolate* v8_isolate, Value* value, int* index) {
531   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
532   i::Object* object = *Utils::OpenHandle(value);
533   isolate->eternal_handles()->Create(isolate, object, index);
534 }
535 
536 
GetEternal(Isolate * v8_isolate,int index)537 Local<Value> V8::GetEternal(Isolate* v8_isolate, int index) {
538   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
539   return Utils::ToLocal(isolate->eternal_handles()->Get(index));
540 }
541 
542 
543 // --- H a n d l e s ---
544 
545 
HandleScope(Isolate * isolate)546 HandleScope::HandleScope(Isolate* isolate) {
547   Initialize(isolate);
548 }
549 
550 
Initialize(Isolate * isolate)551 void HandleScope::Initialize(Isolate* isolate) {
552   i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
553   // We do not want to check the correct usage of the Locker class all over the
554   // place, so we do it only here: Without a HandleScope, an embedder can do
555   // almost nothing, so it is enough to check in this central place.
556   Utils::ApiCheck(!v8::Locker::IsActive() ||
557                   internal_isolate->thread_manager()->IsLockedByCurrentThread(),
558                   "HandleScope::HandleScope",
559                   "Entering the V8 API without proper locking in place");
560   i::HandleScopeData* current = internal_isolate->handle_scope_data();
561   isolate_ = internal_isolate;
562   prev_next_ = current->next;
563   prev_limit_ = current->limit;
564   current->level++;
565 }
566 
567 
~HandleScope()568 HandleScope::~HandleScope() {
569   i::HandleScope::CloseScope(isolate_, prev_next_, prev_limit_);
570 }
571 
572 
NumberOfHandles(Isolate * isolate)573 int HandleScope::NumberOfHandles(Isolate* isolate) {
574   return i::HandleScope::NumberOfHandles(
575       reinterpret_cast<i::Isolate*>(isolate));
576 }
577 
578 
CreateHandle(i::Isolate * isolate,i::Object * value)579 i::Object** HandleScope::CreateHandle(i::Isolate* isolate, i::Object* value) {
580   return i::HandleScope::CreateHandle(isolate, value);
581 }
582 
583 
CreateHandle(i::HeapObject * heap_object,i::Object * value)584 i::Object** HandleScope::CreateHandle(i::HeapObject* heap_object,
585                                       i::Object* value) {
586   DCHECK(heap_object->IsHeapObject());
587   return i::HandleScope::CreateHandle(heap_object->GetIsolate(), value);
588 }
589 
590 
EscapableHandleScope(Isolate * v8_isolate)591 EscapableHandleScope::EscapableHandleScope(Isolate* v8_isolate) {
592   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
593   escape_slot_ = CreateHandle(isolate, isolate->heap()->the_hole_value());
594   Initialize(v8_isolate);
595 }
596 
597 
Escape(i::Object ** escape_value)598 i::Object** EscapableHandleScope::Escape(i::Object** escape_value) {
599   i::Heap* heap = reinterpret_cast<i::Isolate*>(GetIsolate())->heap();
600   Utils::ApiCheck(*escape_slot_ == heap->the_hole_value(),
601                   "EscapeableHandleScope::Escape",
602                   "Escape value set twice");
603   if (escape_value == NULL) {
604     *escape_slot_ = heap->undefined_value();
605     return NULL;
606   }
607   *escape_slot_ = *escape_value;
608   return escape_slot_;
609 }
610 
611 
Enter()612 void Context::Enter() {
613   i::Handle<i::Context> env = Utils::OpenHandle(this);
614   i::Isolate* isolate = env->GetIsolate();
615   ENTER_V8(isolate);
616   i::HandleScopeImplementer* impl = isolate->handle_scope_implementer();
617   impl->EnterContext(env);
618   impl->SaveContext(isolate->context());
619   isolate->set_context(*env);
620 }
621 
622 
Exit()623 void Context::Exit() {
624   i::Handle<i::Context> env = Utils::OpenHandle(this);
625   i::Isolate* isolate = env->GetIsolate();
626   ENTER_V8(isolate);
627   i::HandleScopeImplementer* impl = isolate->handle_scope_implementer();
628   if (!Utils::ApiCheck(impl->LastEnteredContextWas(env),
629                        "v8::Context::Exit()",
630                        "Cannot exit non-entered context")) {
631     return;
632   }
633   impl->LeaveContext();
634   isolate->set_context(impl->RestoreContext());
635 }
636 
637 
DecodeSmiToAligned(i::Object * value,const char * location)638 static void* DecodeSmiToAligned(i::Object* value, const char* location) {
639   Utils::ApiCheck(value->IsSmi(), location, "Not a Smi");
640   return reinterpret_cast<void*>(value);
641 }
642 
643 
EncodeAlignedAsSmi(void * value,const char * location)644 static i::Smi* EncodeAlignedAsSmi(void* value, const char* location) {
645   i::Smi* smi = reinterpret_cast<i::Smi*>(value);
646   Utils::ApiCheck(smi->IsSmi(), location, "Pointer is not aligned");
647   return smi;
648 }
649 
650 
EmbedderDataFor(Context * context,int index,bool can_grow,const char * location)651 static i::Handle<i::FixedArray> EmbedderDataFor(Context* context,
652                                                 int index,
653                                                 bool can_grow,
654                                                 const char* location) {
655   i::Handle<i::Context> env = Utils::OpenHandle(context);
656   bool ok =
657       Utils::ApiCheck(env->IsNativeContext(),
658                       location,
659                       "Not a native context") &&
660       Utils::ApiCheck(index >= 0, location, "Negative index");
661   if (!ok) return i::Handle<i::FixedArray>();
662   i::Handle<i::FixedArray> data(env->embedder_data());
663   if (index < data->length()) return data;
664   if (!Utils::ApiCheck(can_grow, location, "Index too large")) {
665     return i::Handle<i::FixedArray>();
666   }
667   int new_size = i::Max(index, data->length() << 1) + 1;
668   data = i::FixedArray::CopySize(data, new_size);
669   env->set_embedder_data(*data);
670   return data;
671 }
672 
673 
SlowGetEmbedderData(int index)674 v8::Local<v8::Value> Context::SlowGetEmbedderData(int index) {
675   const char* location = "v8::Context::GetEmbedderData()";
676   i::Handle<i::FixedArray> data = EmbedderDataFor(this, index, false, location);
677   if (data.is_null()) return Local<Value>();
678   i::Handle<i::Object> result(data->get(index), data->GetIsolate());
679   return Utils::ToLocal(result);
680 }
681 
682 
SetEmbedderData(int index,v8::Handle<Value> value)683 void Context::SetEmbedderData(int index, v8::Handle<Value> value) {
684   const char* location = "v8::Context::SetEmbedderData()";
685   i::Handle<i::FixedArray> data = EmbedderDataFor(this, index, true, location);
686   if (data.is_null()) return;
687   i::Handle<i::Object> val = Utils::OpenHandle(*value);
688   data->set(index, *val);
689   DCHECK_EQ(*Utils::OpenHandle(*value),
690             *Utils::OpenHandle(*GetEmbedderData(index)));
691 }
692 
693 
SlowGetAlignedPointerFromEmbedderData(int index)694 void* Context::SlowGetAlignedPointerFromEmbedderData(int index) {
695   const char* location = "v8::Context::GetAlignedPointerFromEmbedderData()";
696   i::Handle<i::FixedArray> data = EmbedderDataFor(this, index, false, location);
697   if (data.is_null()) return NULL;
698   return DecodeSmiToAligned(data->get(index), location);
699 }
700 
701 
SetAlignedPointerInEmbedderData(int index,void * value)702 void Context::SetAlignedPointerInEmbedderData(int index, void* value) {
703   const char* location = "v8::Context::SetAlignedPointerInEmbedderData()";
704   i::Handle<i::FixedArray> data = EmbedderDataFor(this, index, true, location);
705   data->set(index, EncodeAlignedAsSmi(value, location));
706   DCHECK_EQ(value, GetAlignedPointerFromEmbedderData(index));
707 }
708 
709 
710 // --- N e a n d e r ---
711 
712 
713 // A constructor cannot easily return an error value, therefore it is necessary
714 // to check for a dead VM with ON_BAILOUT before constructing any Neander
715 // objects.  To remind you about this there is no HandleScope in the
716 // NeanderObject constructor.  When you add one to the site calling the
717 // constructor you should check that you ensured the VM was not dead first.
NeanderObject(v8::internal::Isolate * isolate,int size)718 NeanderObject::NeanderObject(v8::internal::Isolate* isolate, int size) {
719   ENTER_V8(isolate);
720   value_ = isolate->factory()->NewNeanderObject();
721   i::Handle<i::FixedArray> elements = isolate->factory()->NewFixedArray(size);
722   value_->set_elements(*elements);
723 }
724 
725 
size()726 int NeanderObject::size() {
727   return i::FixedArray::cast(value_->elements())->length();
728 }
729 
730 
NeanderArray(v8::internal::Isolate * isolate)731 NeanderArray::NeanderArray(v8::internal::Isolate* isolate) : obj_(isolate, 2) {
732   obj_.set(0, i::Smi::FromInt(0));
733 }
734 
735 
length()736 int NeanderArray::length() {
737   return i::Smi::cast(obj_.get(0))->value();
738 }
739 
740 
get(int offset)741 i::Object* NeanderArray::get(int offset) {
742   DCHECK(0 <= offset);
743   DCHECK(offset < length());
744   return obj_.get(offset + 1);
745 }
746 
747 
748 // This method cannot easily return an error value, therefore it is necessary
749 // to check for a dead VM with ON_BAILOUT before calling it.  To remind you
750 // about this there is no HandleScope in this method.  When you add one to the
751 // site calling this method you should check that you ensured the VM was not
752 // dead first.
add(i::Handle<i::Object> value)753 void NeanderArray::add(i::Handle<i::Object> value) {
754   int length = this->length();
755   int size = obj_.size();
756   if (length == size - 1) {
757     i::Factory* factory = i::Isolate::Current()->factory();
758     i::Handle<i::FixedArray> new_elms = factory->NewFixedArray(2 * size);
759     for (int i = 0; i < length; i++)
760       new_elms->set(i + 1, get(i));
761     obj_.value()->set_elements(*new_elms);
762   }
763   obj_.set(length + 1, *value);
764   obj_.set(0, i::Smi::FromInt(length + 1));
765 }
766 
767 
set(int index,i::Object * value)768 void NeanderArray::set(int index, i::Object* value) {
769   if (index < 0 || index >= this->length()) return;
770   obj_.set(index + 1, value);
771 }
772 
773 
774 // --- T e m p l a t e ---
775 
776 
InitializeTemplate(i::Handle<i::TemplateInfo> that,int type)777 static void InitializeTemplate(i::Handle<i::TemplateInfo> that, int type) {
778   that->set_tag(i::Smi::FromInt(type));
779 }
780 
781 
TemplateSet(i::Isolate * isolate,v8::Template * templ,int length,v8::Handle<v8::Data> * data)782 static void TemplateSet(i::Isolate* isolate,
783                         v8::Template* templ,
784                         int length,
785                         v8::Handle<v8::Data>* data) {
786   i::Handle<i::Object> list(Utils::OpenHandle(templ)->property_list(), isolate);
787   if (list->IsUndefined()) {
788     list = NeanderArray(isolate).value();
789     Utils::OpenHandle(templ)->set_property_list(*list);
790   }
791   NeanderArray array(list);
792   array.add(isolate->factory()->NewNumberFromInt(length));
793   for (int i = 0; i < length; i++) {
794     i::Handle<i::Object> value = data[i].IsEmpty() ?
795         i::Handle<i::Object>(isolate->factory()->undefined_value()) :
796         Utils::OpenHandle(*data[i]);
797     array.add(value);
798   }
799 }
800 
801 
Set(v8::Handle<Name> name,v8::Handle<Data> value,v8::PropertyAttribute attribute)802 void Template::Set(v8::Handle<Name> name,
803                    v8::Handle<Data> value,
804                    v8::PropertyAttribute attribute) {
805   i::Isolate* isolate = i::Isolate::Current();
806   ENTER_V8(isolate);
807   i::HandleScope scope(isolate);
808   const int kSize = 3;
809   v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
810   v8::Handle<v8::Data> data[kSize] = {
811     name,
812     value,
813     v8::Integer::New(v8_isolate, attribute)};
814   TemplateSet(isolate, this, kSize, data);
815 }
816 
817 
SetAccessorProperty(v8::Local<v8::Name> name,v8::Local<FunctionTemplate> getter,v8::Local<FunctionTemplate> setter,v8::PropertyAttribute attribute,v8::AccessControl access_control)818 void Template::SetAccessorProperty(
819     v8::Local<v8::Name> name,
820     v8::Local<FunctionTemplate> getter,
821     v8::Local<FunctionTemplate> setter,
822     v8::PropertyAttribute attribute,
823     v8::AccessControl access_control) {
824   // TODO(verwaest): Remove |access_control|.
825   DCHECK_EQ(v8::DEFAULT, access_control);
826   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
827   ENTER_V8(isolate);
828   DCHECK(!name.IsEmpty());
829   DCHECK(!getter.IsEmpty() || !setter.IsEmpty());
830   i::HandleScope scope(isolate);
831   const int kSize = 5;
832   v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
833   v8::Handle<v8::Data> data[kSize] = {
834     name,
835     getter,
836     setter,
837     v8::Integer::New(v8_isolate, attribute)};
838   TemplateSet(isolate, this, kSize, data);
839 }
840 
841 
842 // --- F u n c t i o n   T e m p l a t e ---
InitializeFunctionTemplate(i::Handle<i::FunctionTemplateInfo> info)843 static void InitializeFunctionTemplate(
844     i::Handle<i::FunctionTemplateInfo> info) {
845   info->set_tag(i::Smi::FromInt(Consts::FUNCTION_TEMPLATE));
846   info->set_flag(0);
847 }
848 
849 
PrototypeTemplate()850 Local<ObjectTemplate> FunctionTemplate::PrototypeTemplate() {
851   i::Isolate* i_isolate = Utils::OpenHandle(this)->GetIsolate();
852   ENTER_V8(i_isolate);
853   i::Handle<i::Object> result(Utils::OpenHandle(this)->prototype_template(),
854                               i_isolate);
855   if (result->IsUndefined()) {
856     v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(i_isolate);
857     result = Utils::OpenHandle(*ObjectTemplate::New(isolate));
858     Utils::OpenHandle(this)->set_prototype_template(*result);
859   }
860   return ToApiHandle<ObjectTemplate>(result);
861 }
862 
863 
Inherit(v8::Handle<FunctionTemplate> value)864 void FunctionTemplate::Inherit(v8::Handle<FunctionTemplate> value) {
865   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
866   ENTER_V8(isolate);
867   Utils::OpenHandle(this)->set_parent_template(*Utils::OpenHandle(*value));
868 }
869 
870 
FunctionTemplateNew(i::Isolate * isolate,FunctionCallback callback,v8::Handle<Value> data,v8::Handle<Signature> signature,int length,bool do_not_cache)871 static Local<FunctionTemplate> FunctionTemplateNew(
872     i::Isolate* isolate,
873     FunctionCallback callback,
874     v8::Handle<Value> data,
875     v8::Handle<Signature> signature,
876     int length,
877     bool do_not_cache) {
878   i::Handle<i::Struct> struct_obj =
879       isolate->factory()->NewStruct(i::FUNCTION_TEMPLATE_INFO_TYPE);
880   i::Handle<i::FunctionTemplateInfo> obj =
881       i::Handle<i::FunctionTemplateInfo>::cast(struct_obj);
882   InitializeFunctionTemplate(obj);
883   obj->set_do_not_cache(do_not_cache);
884   int next_serial_number = 0;
885   if (!do_not_cache) {
886     next_serial_number = isolate->next_serial_number() + 1;
887     isolate->set_next_serial_number(next_serial_number);
888   }
889   obj->set_serial_number(i::Smi::FromInt(next_serial_number));
890   if (callback != 0) {
891     if (data.IsEmpty()) {
892       data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
893     }
894     Utils::ToLocal(obj)->SetCallHandler(callback, data);
895   }
896   obj->set_length(length);
897   obj->set_undetectable(false);
898   obj->set_needs_access_check(false);
899   if (!signature.IsEmpty())
900     obj->set_signature(*Utils::OpenHandle(*signature));
901   return Utils::ToLocal(obj);
902 }
903 
New(Isolate * isolate,FunctionCallback callback,v8::Handle<Value> data,v8::Handle<Signature> signature,int length)904 Local<FunctionTemplate> FunctionTemplate::New(
905     Isolate* isolate,
906     FunctionCallback callback,
907     v8::Handle<Value> data,
908     v8::Handle<Signature> signature,
909     int length) {
910   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
911   LOG_API(i_isolate, "FunctionTemplate::New");
912   ENTER_V8(i_isolate);
913   return FunctionTemplateNew(
914       i_isolate, callback, data, signature, length, false);
915 }
916 
917 
New(Isolate * isolate,Handle<FunctionTemplate> receiver,int argc,Handle<FunctionTemplate> argv[])918 Local<Signature> Signature::New(Isolate* isolate,
919                                 Handle<FunctionTemplate> receiver, int argc,
920                                 Handle<FunctionTemplate> argv[]) {
921   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
922   LOG_API(i_isolate, "Signature::New");
923   ENTER_V8(i_isolate);
924   i::Handle<i::Struct> struct_obj =
925       i_isolate->factory()->NewStruct(i::SIGNATURE_INFO_TYPE);
926   i::Handle<i::SignatureInfo> obj =
927       i::Handle<i::SignatureInfo>::cast(struct_obj);
928   if (!receiver.IsEmpty()) obj->set_receiver(*Utils::OpenHandle(*receiver));
929   if (argc > 0) {
930     i::Handle<i::FixedArray> args = i_isolate->factory()->NewFixedArray(argc);
931     for (int i = 0; i < argc; i++) {
932       if (!argv[i].IsEmpty())
933         args->set(i, *Utils::OpenHandle(*argv[i]));
934     }
935     obj->set_args(*args);
936   }
937   return Utils::ToLocal(obj);
938 }
939 
940 
New(Isolate * isolate,Handle<FunctionTemplate> receiver)941 Local<AccessorSignature> AccessorSignature::New(
942     Isolate* isolate,
943     Handle<FunctionTemplate> receiver) {
944   return Utils::AccessorSignatureToLocal(Utils::OpenHandle(*receiver));
945 }
946 
947 
948 template<typename Operation>
NewDescriptor(Isolate * isolate,const i::DeclaredAccessorDescriptorData & data,Data * previous_descriptor)949 static Local<Operation> NewDescriptor(
950     Isolate* isolate,
951     const i::DeclaredAccessorDescriptorData& data,
952     Data* previous_descriptor) {
953   i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
954   i::Handle<i::DeclaredAccessorDescriptor> previous =
955       i::Handle<i::DeclaredAccessorDescriptor>();
956   if (previous_descriptor != NULL) {
957     previous = Utils::OpenHandle(
958         static_cast<DeclaredAccessorDescriptor*>(previous_descriptor));
959   }
960   i::Handle<i::DeclaredAccessorDescriptor> descriptor =
961       i::DeclaredAccessorDescriptor::Create(internal_isolate, data, previous);
962   return Utils::Convert<i::DeclaredAccessorDescriptor, Operation>(descriptor);
963 }
964 
965 
966 Local<RawOperationDescriptor>
NewInternalFieldDereference(Isolate * isolate,int internal_field)967 ObjectOperationDescriptor::NewInternalFieldDereference(
968     Isolate* isolate,
969     int internal_field) {
970   i::DeclaredAccessorDescriptorData data;
971   data.type = i::kDescriptorObjectDereference;
972   data.object_dereference_descriptor.internal_field = internal_field;
973   return NewDescriptor<RawOperationDescriptor>(isolate, data, NULL);
974 }
975 
976 
NewRawShift(Isolate * isolate,int16_t byte_offset)977 Local<RawOperationDescriptor> RawOperationDescriptor::NewRawShift(
978     Isolate* isolate,
979     int16_t byte_offset) {
980   i::DeclaredAccessorDescriptorData data;
981   data.type = i::kDescriptorPointerShift;
982   data.pointer_shift_descriptor.byte_offset = byte_offset;
983   return NewDescriptor<RawOperationDescriptor>(isolate, data, this);
984 }
985 
986 
NewHandleDereference(Isolate * isolate)987 Local<DeclaredAccessorDescriptor> RawOperationDescriptor::NewHandleDereference(
988     Isolate* isolate) {
989   i::DeclaredAccessorDescriptorData data;
990   data.type = i::kDescriptorReturnObject;
991   return NewDescriptor<DeclaredAccessorDescriptor>(isolate, data, this);
992 }
993 
994 
NewRawDereference(Isolate * isolate)995 Local<RawOperationDescriptor> RawOperationDescriptor::NewRawDereference(
996     Isolate* isolate) {
997   i::DeclaredAccessorDescriptorData data;
998   data.type = i::kDescriptorPointerDereference;
999   return NewDescriptor<RawOperationDescriptor>(isolate, data, this);
1000 }
1001 
1002 
NewPointerCompare(Isolate * isolate,void * compare_value)1003 Local<DeclaredAccessorDescriptor> RawOperationDescriptor::NewPointerCompare(
1004     Isolate* isolate,
1005     void* compare_value) {
1006   i::DeclaredAccessorDescriptorData data;
1007   data.type = i::kDescriptorPointerCompare;
1008   data.pointer_compare_descriptor.compare_value = compare_value;
1009   return NewDescriptor<DeclaredAccessorDescriptor>(isolate, data, this);
1010 }
1011 
1012 
NewPrimitiveValue(Isolate * isolate,DeclaredAccessorDescriptorDataType data_type,uint8_t bool_offset)1013 Local<DeclaredAccessorDescriptor> RawOperationDescriptor::NewPrimitiveValue(
1014     Isolate* isolate,
1015     DeclaredAccessorDescriptorDataType data_type,
1016     uint8_t bool_offset) {
1017   i::DeclaredAccessorDescriptorData data;
1018   data.type = i::kDescriptorPrimitiveValue;
1019   data.primitive_value_descriptor.data_type = data_type;
1020   data.primitive_value_descriptor.bool_offset = bool_offset;
1021   return NewDescriptor<DeclaredAccessorDescriptor>(isolate, data, this);
1022 }
1023 
1024 
1025 template<typename T>
NewBitmaskCompare(Isolate * isolate,T bitmask,T compare_value,RawOperationDescriptor * operation)1026 static Local<DeclaredAccessorDescriptor> NewBitmaskCompare(
1027     Isolate* isolate,
1028     T bitmask,
1029     T compare_value,
1030     RawOperationDescriptor* operation) {
1031   i::DeclaredAccessorDescriptorData data;
1032   data.type = i::kDescriptorBitmaskCompare;
1033   data.bitmask_compare_descriptor.bitmask = bitmask;
1034   data.bitmask_compare_descriptor.compare_value = compare_value;
1035   data.bitmask_compare_descriptor.size = sizeof(T);
1036   return NewDescriptor<DeclaredAccessorDescriptor>(isolate, data, operation);
1037 }
1038 
1039 
NewBitmaskCompare8(Isolate * isolate,uint8_t bitmask,uint8_t compare_value)1040 Local<DeclaredAccessorDescriptor> RawOperationDescriptor::NewBitmaskCompare8(
1041     Isolate* isolate,
1042     uint8_t bitmask,
1043     uint8_t compare_value) {
1044   return NewBitmaskCompare(isolate, bitmask, compare_value, this);
1045 }
1046 
1047 
NewBitmaskCompare16(Isolate * isolate,uint16_t bitmask,uint16_t compare_value)1048 Local<DeclaredAccessorDescriptor> RawOperationDescriptor::NewBitmaskCompare16(
1049     Isolate* isolate,
1050     uint16_t bitmask,
1051     uint16_t compare_value) {
1052   return NewBitmaskCompare(isolate, bitmask, compare_value, this);
1053 }
1054 
1055 
NewBitmaskCompare32(Isolate * isolate,uint32_t bitmask,uint32_t compare_value)1056 Local<DeclaredAccessorDescriptor> RawOperationDescriptor::NewBitmaskCompare32(
1057     Isolate* isolate,
1058     uint32_t bitmask,
1059     uint32_t compare_value) {
1060   return NewBitmaskCompare(isolate, bitmask, compare_value, this);
1061 }
1062 
1063 
New(Handle<FunctionTemplate> type)1064 Local<TypeSwitch> TypeSwitch::New(Handle<FunctionTemplate> type) {
1065   Handle<FunctionTemplate> types[1] = { type };
1066   return TypeSwitch::New(1, types);
1067 }
1068 
1069 
New(int argc,Handle<FunctionTemplate> types[])1070 Local<TypeSwitch> TypeSwitch::New(int argc, Handle<FunctionTemplate> types[]) {
1071   i::Isolate* isolate = i::Isolate::Current();
1072   LOG_API(isolate, "TypeSwitch::New");
1073   ENTER_V8(isolate);
1074   i::Handle<i::FixedArray> vector = isolate->factory()->NewFixedArray(argc);
1075   for (int i = 0; i < argc; i++)
1076     vector->set(i, *Utils::OpenHandle(*types[i]));
1077   i::Handle<i::Struct> struct_obj =
1078       isolate->factory()->NewStruct(i::TYPE_SWITCH_INFO_TYPE);
1079   i::Handle<i::TypeSwitchInfo> obj =
1080       i::Handle<i::TypeSwitchInfo>::cast(struct_obj);
1081   obj->set_types(*vector);
1082   return Utils::ToLocal(obj);
1083 }
1084 
1085 
match(v8::Handle<Value> value)1086 int TypeSwitch::match(v8::Handle<Value> value) {
1087   i::Isolate* isolate = i::Isolate::Current();
1088   LOG_API(isolate, "TypeSwitch::match");
1089   USE(isolate);
1090   i::Handle<i::Object> obj = Utils::OpenHandle(*value);
1091   i::Handle<i::TypeSwitchInfo> info = Utils::OpenHandle(this);
1092   i::FixedArray* types = i::FixedArray::cast(info->types());
1093   for (int i = 0; i < types->length(); i++) {
1094     if (i::FunctionTemplateInfo::cast(types->get(i))->IsTemplateFor(*obj))
1095       return i + 1;
1096   }
1097   return 0;
1098 }
1099 
1100 
1101 #define SET_FIELD_WRAPPED(obj, setter, cdata) do {                      \
1102     i::Handle<i::Object> foreign = FromCData(obj->GetIsolate(), cdata); \
1103     (obj)->setter(*foreign);                                            \
1104   } while (false)
1105 
1106 
SetCallHandler(FunctionCallback callback,v8::Handle<Value> data)1107 void FunctionTemplate::SetCallHandler(FunctionCallback callback,
1108                                       v8::Handle<Value> data) {
1109   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1110   ENTER_V8(isolate);
1111   i::HandleScope scope(isolate);
1112   i::Handle<i::Struct> struct_obj =
1113       isolate->factory()->NewStruct(i::CALL_HANDLER_INFO_TYPE);
1114   i::Handle<i::CallHandlerInfo> obj =
1115       i::Handle<i::CallHandlerInfo>::cast(struct_obj);
1116   SET_FIELD_WRAPPED(obj, set_callback, callback);
1117   if (data.IsEmpty()) {
1118     data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
1119   }
1120   obj->set_data(*Utils::OpenHandle(*data));
1121   Utils::OpenHandle(this)->set_call_code(*obj);
1122 }
1123 
1124 
SetAccessorInfoProperties(i::Handle<i::AccessorInfo> obj,v8::Handle<Name> name,v8::AccessControl settings,v8::PropertyAttribute attributes,v8::Handle<AccessorSignature> signature)1125 static i::Handle<i::AccessorInfo> SetAccessorInfoProperties(
1126     i::Handle<i::AccessorInfo> obj,
1127     v8::Handle<Name> name,
1128     v8::AccessControl settings,
1129     v8::PropertyAttribute attributes,
1130     v8::Handle<AccessorSignature> signature) {
1131   obj->set_name(*Utils::OpenHandle(*name));
1132   if (settings & ALL_CAN_READ) obj->set_all_can_read(true);
1133   if (settings & ALL_CAN_WRITE) obj->set_all_can_write(true);
1134   obj->set_property_attributes(static_cast<PropertyAttributes>(attributes));
1135   if (!signature.IsEmpty()) {
1136     obj->set_expected_receiver_type(*Utils::OpenHandle(*signature));
1137   }
1138   return obj;
1139 }
1140 
1141 
1142 template<typename Getter, typename Setter>
MakeAccessorInfo(v8::Handle<Name> name,Getter getter,Setter setter,v8::Handle<Value> data,v8::AccessControl settings,v8::PropertyAttribute attributes,v8::Handle<AccessorSignature> signature)1143 static i::Handle<i::AccessorInfo> MakeAccessorInfo(
1144     v8::Handle<Name> name,
1145     Getter getter,
1146     Setter setter,
1147     v8::Handle<Value> data,
1148     v8::AccessControl settings,
1149     v8::PropertyAttribute attributes,
1150     v8::Handle<AccessorSignature> signature) {
1151   i::Isolate* isolate = Utils::OpenHandle(*name)->GetIsolate();
1152   i::Handle<i::ExecutableAccessorInfo> obj =
1153       isolate->factory()->NewExecutableAccessorInfo();
1154   SET_FIELD_WRAPPED(obj, set_getter, getter);
1155   SET_FIELD_WRAPPED(obj, set_setter, setter);
1156   if (data.IsEmpty()) {
1157     data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
1158   }
1159   obj->set_data(*Utils::OpenHandle(*data));
1160   return SetAccessorInfoProperties(obj, name, settings, attributes, signature);
1161 }
1162 
1163 
MakeAccessorInfo(v8::Handle<Name> name,v8::Handle<v8::DeclaredAccessorDescriptor> descriptor,void * setter_ignored,void * data_ignored,v8::AccessControl settings,v8::PropertyAttribute attributes,v8::Handle<AccessorSignature> signature)1164 static i::Handle<i::AccessorInfo> MakeAccessorInfo(
1165     v8::Handle<Name> name,
1166     v8::Handle<v8::DeclaredAccessorDescriptor> descriptor,
1167     void* setter_ignored,
1168     void* data_ignored,
1169     v8::AccessControl settings,
1170     v8::PropertyAttribute attributes,
1171     v8::Handle<AccessorSignature> signature) {
1172   i::Isolate* isolate = Utils::OpenHandle(*name)->GetIsolate();
1173   if (descriptor.IsEmpty()) return i::Handle<i::DeclaredAccessorInfo>();
1174   i::Handle<i::DeclaredAccessorInfo> obj =
1175       isolate->factory()->NewDeclaredAccessorInfo();
1176   obj->set_descriptor(*Utils::OpenHandle(*descriptor));
1177   return SetAccessorInfoProperties(obj, name, settings, attributes, signature);
1178 }
1179 
1180 
InstanceTemplate()1181 Local<ObjectTemplate> FunctionTemplate::InstanceTemplate() {
1182   i::Handle<i::FunctionTemplateInfo> handle = Utils::OpenHandle(this, true);
1183   if (!Utils::ApiCheck(!handle.is_null(),
1184                        "v8::FunctionTemplate::InstanceTemplate()",
1185                        "Reading from empty handle")) {
1186     return Local<ObjectTemplate>();
1187   }
1188   i::Isolate* isolate = handle->GetIsolate();
1189   ENTER_V8(isolate);
1190   if (handle->instance_template()->IsUndefined()) {
1191     Local<ObjectTemplate> templ =
1192         ObjectTemplate::New(isolate, ToApiHandle<FunctionTemplate>(handle));
1193     handle->set_instance_template(*Utils::OpenHandle(*templ));
1194   }
1195   i::Handle<i::ObjectTemplateInfo> result(
1196       i::ObjectTemplateInfo::cast(handle->instance_template()));
1197   return Utils::ToLocal(result);
1198 }
1199 
1200 
SetLength(int length)1201 void FunctionTemplate::SetLength(int length) {
1202   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1203   ENTER_V8(isolate);
1204   Utils::OpenHandle(this)->set_length(length);
1205 }
1206 
1207 
SetClassName(Handle<String> name)1208 void FunctionTemplate::SetClassName(Handle<String> name) {
1209   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1210   ENTER_V8(isolate);
1211   Utils::OpenHandle(this)->set_class_name(*Utils::OpenHandle(*name));
1212 }
1213 
1214 
SetHiddenPrototype(bool value)1215 void FunctionTemplate::SetHiddenPrototype(bool value) {
1216   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1217   ENTER_V8(isolate);
1218   Utils::OpenHandle(this)->set_hidden_prototype(value);
1219 }
1220 
1221 
ReadOnlyPrototype()1222 void FunctionTemplate::ReadOnlyPrototype() {
1223   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1224   ENTER_V8(isolate);
1225   Utils::OpenHandle(this)->set_read_only_prototype(true);
1226 }
1227 
1228 
RemovePrototype()1229 void FunctionTemplate::RemovePrototype() {
1230   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1231   ENTER_V8(isolate);
1232   Utils::OpenHandle(this)->set_remove_prototype(true);
1233 }
1234 
1235 
1236 // --- O b j e c t T e m p l a t e ---
1237 
1238 
New(Isolate * isolate)1239 Local<ObjectTemplate> ObjectTemplate::New(Isolate* isolate) {
1240   return New(reinterpret_cast<i::Isolate*>(isolate), Local<FunctionTemplate>());
1241 }
1242 
1243 
New()1244 Local<ObjectTemplate> ObjectTemplate::New() {
1245   return New(i::Isolate::Current(), Local<FunctionTemplate>());
1246 }
1247 
1248 
New(i::Isolate * isolate,v8::Handle<FunctionTemplate> constructor)1249 Local<ObjectTemplate> ObjectTemplate::New(
1250     i::Isolate* isolate,
1251     v8::Handle<FunctionTemplate> constructor) {
1252   LOG_API(isolate, "ObjectTemplate::New");
1253   ENTER_V8(isolate);
1254   i::Handle<i::Struct> struct_obj =
1255       isolate->factory()->NewStruct(i::OBJECT_TEMPLATE_INFO_TYPE);
1256   i::Handle<i::ObjectTemplateInfo> obj =
1257       i::Handle<i::ObjectTemplateInfo>::cast(struct_obj);
1258   InitializeTemplate(obj, Consts::OBJECT_TEMPLATE);
1259   if (!constructor.IsEmpty())
1260     obj->set_constructor(*Utils::OpenHandle(*constructor));
1261   obj->set_internal_field_count(i::Smi::FromInt(0));
1262   return Utils::ToLocal(obj);
1263 }
1264 
1265 
1266 // Ensure that the object template has a constructor.  If no
1267 // constructor is available we create one.
EnsureConstructor(i::Isolate * isolate,ObjectTemplate * object_template)1268 static i::Handle<i::FunctionTemplateInfo> EnsureConstructor(
1269     i::Isolate* isolate,
1270     ObjectTemplate* object_template) {
1271   i::Object* obj = Utils::OpenHandle(object_template)->constructor();
1272   if (!obj ->IsUndefined()) {
1273     i::FunctionTemplateInfo* info = i::FunctionTemplateInfo::cast(obj);
1274     return i::Handle<i::FunctionTemplateInfo>(info, isolate);
1275   }
1276   Local<FunctionTemplate> templ =
1277       FunctionTemplate::New(reinterpret_cast<Isolate*>(isolate));
1278   i::Handle<i::FunctionTemplateInfo> constructor = Utils::OpenHandle(*templ);
1279   constructor->set_instance_template(*Utils::OpenHandle(object_template));
1280   Utils::OpenHandle(object_template)->set_constructor(*constructor);
1281   return constructor;
1282 }
1283 
1284 
AddPropertyToTemplate(i::Handle<i::TemplateInfo> info,i::Handle<i::AccessorInfo> obj)1285 static inline void AddPropertyToTemplate(
1286     i::Handle<i::TemplateInfo> info,
1287     i::Handle<i::AccessorInfo> obj) {
1288   i::Isolate* isolate = info->GetIsolate();
1289   i::Handle<i::Object> list(info->property_accessors(), isolate);
1290   if (list->IsUndefined()) {
1291     list = NeanderArray(isolate).value();
1292     info->set_property_accessors(*list);
1293   }
1294   NeanderArray array(list);
1295   array.add(obj);
1296 }
1297 
1298 
GetTemplateInfo(i::Isolate * isolate,Template * template_obj)1299 static inline i::Handle<i::TemplateInfo> GetTemplateInfo(
1300     i::Isolate* isolate,
1301     Template* template_obj) {
1302   return Utils::OpenHandle(template_obj);
1303 }
1304 
1305 
1306 // TODO(dcarney): remove this with ObjectTemplate::SetAccessor
GetTemplateInfo(i::Isolate * isolate,ObjectTemplate * object_template)1307 static inline i::Handle<i::TemplateInfo> GetTemplateInfo(
1308     i::Isolate* isolate,
1309     ObjectTemplate* object_template) {
1310   EnsureConstructor(isolate, object_template);
1311   return Utils::OpenHandle(object_template);
1312 }
1313 
1314 
1315 template<typename Getter, typename Setter, typename Data, typename Template>
TemplateSetAccessor(Template * template_obj,v8::Local<Name> name,Getter getter,Setter setter,Data data,AccessControl settings,PropertyAttribute attribute,v8::Local<AccessorSignature> signature)1316 static bool TemplateSetAccessor(
1317     Template* template_obj,
1318     v8::Local<Name> name,
1319     Getter getter,
1320     Setter setter,
1321     Data data,
1322     AccessControl settings,
1323     PropertyAttribute attribute,
1324     v8::Local<AccessorSignature> signature) {
1325   i::Isolate* isolate = Utils::OpenHandle(template_obj)->GetIsolate();
1326   ENTER_V8(isolate);
1327   i::HandleScope scope(isolate);
1328   i::Handle<i::AccessorInfo> obj = MakeAccessorInfo(
1329       name, getter, setter, data, settings, attribute, signature);
1330   if (obj.is_null()) return false;
1331   i::Handle<i::TemplateInfo> info = GetTemplateInfo(isolate, template_obj);
1332   AddPropertyToTemplate(info, obj);
1333   return true;
1334 }
1335 
1336 
SetDeclaredAccessor(Local<Name> name,Local<DeclaredAccessorDescriptor> descriptor,PropertyAttribute attribute,Local<AccessorSignature> signature,AccessControl settings)1337 bool Template::SetDeclaredAccessor(
1338     Local<Name> name,
1339     Local<DeclaredAccessorDescriptor> descriptor,
1340     PropertyAttribute attribute,
1341     Local<AccessorSignature> signature,
1342     AccessControl settings) {
1343   void* null = NULL;
1344   return TemplateSetAccessor(
1345       this, name, descriptor, null, null, settings, attribute, signature);
1346 }
1347 
1348 
SetNativeDataProperty(v8::Local<String> name,AccessorGetterCallback getter,AccessorSetterCallback setter,v8::Handle<Value> data,PropertyAttribute attribute,v8::Local<AccessorSignature> signature,AccessControl settings)1349 void Template::SetNativeDataProperty(v8::Local<String> name,
1350                                      AccessorGetterCallback getter,
1351                                      AccessorSetterCallback setter,
1352                                      v8::Handle<Value> data,
1353                                      PropertyAttribute attribute,
1354                                      v8::Local<AccessorSignature> signature,
1355                                      AccessControl settings) {
1356   TemplateSetAccessor(
1357       this, name, getter, setter, data, settings, attribute, signature);
1358 }
1359 
1360 
SetNativeDataProperty(v8::Local<Name> name,AccessorNameGetterCallback getter,AccessorNameSetterCallback setter,v8::Handle<Value> data,PropertyAttribute attribute,v8::Local<AccessorSignature> signature,AccessControl settings)1361 void Template::SetNativeDataProperty(v8::Local<Name> name,
1362                                      AccessorNameGetterCallback getter,
1363                                      AccessorNameSetterCallback setter,
1364                                      v8::Handle<Value> data,
1365                                      PropertyAttribute attribute,
1366                                      v8::Local<AccessorSignature> signature,
1367                                      AccessControl settings) {
1368   TemplateSetAccessor(
1369       this, name, getter, setter, data, settings, attribute, signature);
1370 }
1371 
1372 
SetAccessor(v8::Handle<String> name,AccessorGetterCallback getter,AccessorSetterCallback setter,v8::Handle<Value> data,AccessControl settings,PropertyAttribute attribute,v8::Handle<AccessorSignature> signature)1373 void ObjectTemplate::SetAccessor(v8::Handle<String> name,
1374                                  AccessorGetterCallback getter,
1375                                  AccessorSetterCallback setter,
1376                                  v8::Handle<Value> data,
1377                                  AccessControl settings,
1378                                  PropertyAttribute attribute,
1379                                  v8::Handle<AccessorSignature> signature) {
1380   TemplateSetAccessor(
1381       this, name, getter, setter, data, settings, attribute, signature);
1382 }
1383 
1384 
SetAccessor(v8::Handle<Name> name,AccessorNameGetterCallback getter,AccessorNameSetterCallback setter,v8::Handle<Value> data,AccessControl settings,PropertyAttribute attribute,v8::Handle<AccessorSignature> signature)1385 void ObjectTemplate::SetAccessor(v8::Handle<Name> name,
1386                                  AccessorNameGetterCallback getter,
1387                                  AccessorNameSetterCallback setter,
1388                                  v8::Handle<Value> data,
1389                                  AccessControl settings,
1390                                  PropertyAttribute attribute,
1391                                  v8::Handle<AccessorSignature> signature) {
1392   TemplateSetAccessor(
1393       this, name, getter, setter, data, settings, attribute, signature);
1394 }
1395 
1396 
SetNamedPropertyHandler(NamedPropertyGetterCallback getter,NamedPropertySetterCallback setter,NamedPropertyQueryCallback query,NamedPropertyDeleterCallback remover,NamedPropertyEnumeratorCallback enumerator,Handle<Value> data)1397 void ObjectTemplate::SetNamedPropertyHandler(
1398     NamedPropertyGetterCallback getter,
1399     NamedPropertySetterCallback setter,
1400     NamedPropertyQueryCallback query,
1401     NamedPropertyDeleterCallback remover,
1402     NamedPropertyEnumeratorCallback enumerator,
1403     Handle<Value> data) {
1404   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1405   ENTER_V8(isolate);
1406   i::HandleScope scope(isolate);
1407   EnsureConstructor(isolate, this);
1408   i::FunctionTemplateInfo* constructor = i::FunctionTemplateInfo::cast(
1409       Utils::OpenHandle(this)->constructor());
1410   i::Handle<i::FunctionTemplateInfo> cons(constructor);
1411   i::Handle<i::Struct> struct_obj =
1412       isolate->factory()->NewStruct(i::INTERCEPTOR_INFO_TYPE);
1413   i::Handle<i::InterceptorInfo> obj =
1414       i::Handle<i::InterceptorInfo>::cast(struct_obj);
1415 
1416   if (getter != 0) SET_FIELD_WRAPPED(obj, set_getter, getter);
1417   if (setter != 0) SET_FIELD_WRAPPED(obj, set_setter, setter);
1418   if (query != 0) SET_FIELD_WRAPPED(obj, set_query, query);
1419   if (remover != 0) SET_FIELD_WRAPPED(obj, set_deleter, remover);
1420   if (enumerator != 0) SET_FIELD_WRAPPED(obj, set_enumerator, enumerator);
1421 
1422   if (data.IsEmpty()) {
1423     data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
1424   }
1425   obj->set_data(*Utils::OpenHandle(*data));
1426   cons->set_named_property_handler(*obj);
1427 }
1428 
1429 
MarkAsUndetectable()1430 void ObjectTemplate::MarkAsUndetectable() {
1431   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1432   ENTER_V8(isolate);
1433   i::HandleScope scope(isolate);
1434   EnsureConstructor(isolate, this);
1435   i::FunctionTemplateInfo* constructor =
1436       i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1437   i::Handle<i::FunctionTemplateInfo> cons(constructor);
1438   cons->set_undetectable(true);
1439 }
1440 
1441 
SetAccessCheckCallbacks(NamedSecurityCallback named_callback,IndexedSecurityCallback indexed_callback,Handle<Value> data,bool turned_on_by_default)1442 void ObjectTemplate::SetAccessCheckCallbacks(
1443     NamedSecurityCallback named_callback,
1444     IndexedSecurityCallback indexed_callback,
1445     Handle<Value> data,
1446     bool turned_on_by_default) {
1447   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1448   ENTER_V8(isolate);
1449   i::HandleScope scope(isolate);
1450   EnsureConstructor(isolate, this);
1451 
1452   i::Handle<i::Struct> struct_info =
1453       isolate->factory()->NewStruct(i::ACCESS_CHECK_INFO_TYPE);
1454   i::Handle<i::AccessCheckInfo> info =
1455       i::Handle<i::AccessCheckInfo>::cast(struct_info);
1456 
1457   SET_FIELD_WRAPPED(info, set_named_callback, named_callback);
1458   SET_FIELD_WRAPPED(info, set_indexed_callback, indexed_callback);
1459 
1460   if (data.IsEmpty()) {
1461     data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
1462   }
1463   info->set_data(*Utils::OpenHandle(*data));
1464 
1465   i::FunctionTemplateInfo* constructor =
1466       i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1467   i::Handle<i::FunctionTemplateInfo> cons(constructor);
1468   cons->set_access_check_info(*info);
1469   cons->set_needs_access_check(turned_on_by_default);
1470 }
1471 
1472 
SetIndexedPropertyHandler(IndexedPropertyGetterCallback getter,IndexedPropertySetterCallback setter,IndexedPropertyQueryCallback query,IndexedPropertyDeleterCallback remover,IndexedPropertyEnumeratorCallback enumerator,Handle<Value> data)1473 void ObjectTemplate::SetIndexedPropertyHandler(
1474     IndexedPropertyGetterCallback getter,
1475     IndexedPropertySetterCallback setter,
1476     IndexedPropertyQueryCallback query,
1477     IndexedPropertyDeleterCallback remover,
1478     IndexedPropertyEnumeratorCallback enumerator,
1479     Handle<Value> data) {
1480   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1481   ENTER_V8(isolate);
1482   i::HandleScope scope(isolate);
1483   EnsureConstructor(isolate, this);
1484   i::FunctionTemplateInfo* constructor = i::FunctionTemplateInfo::cast(
1485       Utils::OpenHandle(this)->constructor());
1486   i::Handle<i::FunctionTemplateInfo> cons(constructor);
1487   i::Handle<i::Struct> struct_obj =
1488       isolate->factory()->NewStruct(i::INTERCEPTOR_INFO_TYPE);
1489   i::Handle<i::InterceptorInfo> obj =
1490       i::Handle<i::InterceptorInfo>::cast(struct_obj);
1491 
1492   if (getter != 0) SET_FIELD_WRAPPED(obj, set_getter, getter);
1493   if (setter != 0) SET_FIELD_WRAPPED(obj, set_setter, setter);
1494   if (query != 0) SET_FIELD_WRAPPED(obj, set_query, query);
1495   if (remover != 0) SET_FIELD_WRAPPED(obj, set_deleter, remover);
1496   if (enumerator != 0) SET_FIELD_WRAPPED(obj, set_enumerator, enumerator);
1497 
1498   if (data.IsEmpty()) {
1499     data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
1500   }
1501   obj->set_data(*Utils::OpenHandle(*data));
1502   cons->set_indexed_property_handler(*obj);
1503 }
1504 
1505 
SetCallAsFunctionHandler(FunctionCallback callback,Handle<Value> data)1506 void ObjectTemplate::SetCallAsFunctionHandler(FunctionCallback callback,
1507                                               Handle<Value> data) {
1508   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1509   ENTER_V8(isolate);
1510   i::HandleScope scope(isolate);
1511   EnsureConstructor(isolate, this);
1512   i::FunctionTemplateInfo* constructor = i::FunctionTemplateInfo::cast(
1513       Utils::OpenHandle(this)->constructor());
1514   i::Handle<i::FunctionTemplateInfo> cons(constructor);
1515   i::Handle<i::Struct> struct_obj =
1516       isolate->factory()->NewStruct(i::CALL_HANDLER_INFO_TYPE);
1517   i::Handle<i::CallHandlerInfo> obj =
1518       i::Handle<i::CallHandlerInfo>::cast(struct_obj);
1519   SET_FIELD_WRAPPED(obj, set_callback, callback);
1520   if (data.IsEmpty()) {
1521     data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
1522   }
1523   obj->set_data(*Utils::OpenHandle(*data));
1524   cons->set_instance_call_handler(*obj);
1525 }
1526 
1527 
InternalFieldCount()1528 int ObjectTemplate::InternalFieldCount() {
1529   return i::Smi::cast(Utils::OpenHandle(this)->internal_field_count())->value();
1530 }
1531 
1532 
SetInternalFieldCount(int value)1533 void ObjectTemplate::SetInternalFieldCount(int value) {
1534   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1535   if (!Utils::ApiCheck(i::Smi::IsValid(value),
1536                        "v8::ObjectTemplate::SetInternalFieldCount()",
1537                        "Invalid internal field count")) {
1538     return;
1539   }
1540   ENTER_V8(isolate);
1541   if (value > 0) {
1542     // The internal field count is set by the constructor function's
1543     // construct code, so we ensure that there is a constructor
1544     // function to do the setting.
1545     EnsureConstructor(isolate, this);
1546   }
1547   Utils::OpenHandle(this)->set_internal_field_count(i::Smi::FromInt(value));
1548 }
1549 
1550 
1551 // --- S c r i p t s ---
1552 
1553 
1554 // Internally, UnboundScript is a SharedFunctionInfo, and Script is a
1555 // JSFunction.
1556 
CachedData(const uint8_t * data_,int length_,BufferPolicy buffer_policy_)1557 ScriptCompiler::CachedData::CachedData(const uint8_t* data_, int length_,
1558                                        BufferPolicy buffer_policy_)
1559     : data(data_), length(length_), buffer_policy(buffer_policy_) {}
1560 
1561 
~CachedData()1562 ScriptCompiler::CachedData::~CachedData() {
1563   if (buffer_policy == BufferOwned) {
1564     delete[] data;
1565   }
1566 }
1567 
1568 
StreamedSource(ExternalSourceStream * stream,Encoding encoding)1569 ScriptCompiler::StreamedSource::StreamedSource(ExternalSourceStream* stream,
1570                                                Encoding encoding)
1571     : impl_(new i::StreamedSource(stream, encoding)) {}
1572 
1573 
~StreamedSource()1574 ScriptCompiler::StreamedSource::~StreamedSource() { delete impl_; }
1575 
1576 
1577 const ScriptCompiler::CachedData*
GetCachedData() const1578 ScriptCompiler::StreamedSource::GetCachedData() const {
1579   return impl_->cached_data.get();
1580 }
1581 
1582 
BindToCurrentContext()1583 Local<Script> UnboundScript::BindToCurrentContext() {
1584   i::Handle<i::HeapObject> obj =
1585       i::Handle<i::HeapObject>::cast(Utils::OpenHandle(this));
1586   i::Handle<i::SharedFunctionInfo>
1587       function_info(i::SharedFunctionInfo::cast(*obj), obj->GetIsolate());
1588   i::Handle<i::JSFunction> function =
1589       obj->GetIsolate()->factory()->NewFunctionFromSharedFunctionInfo(
1590           function_info, obj->GetIsolate()->global_context());
1591   return ToApiHandle<Script>(function);
1592 }
1593 
1594 
GetId()1595 int UnboundScript::GetId() {
1596   i::Handle<i::HeapObject> obj =
1597       i::Handle<i::HeapObject>::cast(Utils::OpenHandle(this));
1598   i::Isolate* isolate = obj->GetIsolate();
1599   ON_BAILOUT(isolate, "v8::UnboundScript::GetId()", return -1);
1600   LOG_API(isolate, "v8::UnboundScript::GetId");
1601   {
1602     i::HandleScope scope(isolate);
1603     i::Handle<i::SharedFunctionInfo> function_info(
1604         i::SharedFunctionInfo::cast(*obj));
1605     i::Handle<i::Script> script(i::Script::cast(function_info->script()));
1606     return script->id()->value();
1607   }
1608 }
1609 
1610 
GetLineNumber(int code_pos)1611 int UnboundScript::GetLineNumber(int code_pos) {
1612   i::Handle<i::SharedFunctionInfo> obj =
1613       i::Handle<i::SharedFunctionInfo>::cast(Utils::OpenHandle(this));
1614   i::Isolate* isolate = obj->GetIsolate();
1615   ON_BAILOUT(isolate, "v8::UnboundScript::GetLineNumber()", return -1);
1616   LOG_API(isolate, "UnboundScript::GetLineNumber");
1617   if (obj->script()->IsScript()) {
1618     i::Handle<i::Script> script(i::Script::cast(obj->script()));
1619     return i::Script::GetLineNumber(script, code_pos);
1620   } else {
1621     return -1;
1622   }
1623 }
1624 
1625 
GetScriptName()1626 Handle<Value> UnboundScript::GetScriptName() {
1627   i::Handle<i::SharedFunctionInfo> obj =
1628       i::Handle<i::SharedFunctionInfo>::cast(Utils::OpenHandle(this));
1629   i::Isolate* isolate = obj->GetIsolate();
1630   ON_BAILOUT(isolate, "v8::UnboundScript::GetName()",
1631              return Handle<String>());
1632   LOG_API(isolate, "UnboundScript::GetName");
1633   if (obj->script()->IsScript()) {
1634     i::Object* name = i::Script::cast(obj->script())->name();
1635     return Utils::ToLocal(i::Handle<i::Object>(name, isolate));
1636   } else {
1637     return Handle<String>();
1638   }
1639 }
1640 
1641 
GetSourceURL()1642 Handle<Value> UnboundScript::GetSourceURL() {
1643   i::Handle<i::SharedFunctionInfo> obj =
1644       i::Handle<i::SharedFunctionInfo>::cast(Utils::OpenHandle(this));
1645   i::Isolate* isolate = obj->GetIsolate();
1646   ON_BAILOUT(isolate, "v8::UnboundScript::GetSourceURL()",
1647              return Handle<String>());
1648   LOG_API(isolate, "UnboundScript::GetSourceURL");
1649   if (obj->script()->IsScript()) {
1650     i::Object* url = i::Script::cast(obj->script())->source_url();
1651     return Utils::ToLocal(i::Handle<i::Object>(url, isolate));
1652   } else {
1653     return Handle<String>();
1654   }
1655 }
1656 
1657 
GetSourceMappingURL()1658 Handle<Value> UnboundScript::GetSourceMappingURL() {
1659   i::Handle<i::SharedFunctionInfo> obj =
1660       i::Handle<i::SharedFunctionInfo>::cast(Utils::OpenHandle(this));
1661   i::Isolate* isolate = obj->GetIsolate();
1662   ON_BAILOUT(isolate, "v8::UnboundScript::GetSourceMappingURL()",
1663              return Handle<String>());
1664   LOG_API(isolate, "UnboundScript::GetSourceMappingURL");
1665   if (obj->script()->IsScript()) {
1666     i::Object* url = i::Script::cast(obj->script())->source_mapping_url();
1667     return Utils::ToLocal(i::Handle<i::Object>(url, isolate));
1668   } else {
1669     return Handle<String>();
1670   }
1671 }
1672 
1673 
Run()1674 Local<Value> Script::Run() {
1675   i::Handle<i::Object> obj = Utils::OpenHandle(this, true);
1676   // If execution is terminating, Compile(..)->Run() requires this
1677   // check.
1678   if (obj.is_null()) return Local<Value>();
1679   i::Isolate* isolate = i::Handle<i::HeapObject>::cast(obj)->GetIsolate();
1680   ON_BAILOUT(isolate, "v8::Script::Run()", return Local<Value>());
1681   LOG_API(isolate, "Script::Run");
1682   ENTER_V8(isolate);
1683   i::TimerEventScope<i::TimerEventExecute> timer_scope(isolate);
1684   i::HandleScope scope(isolate);
1685   i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(obj);
1686   EXCEPTION_PREAMBLE(isolate);
1687   i::Handle<i::Object> receiver(isolate->global_proxy(), isolate);
1688   i::Handle<i::Object> result;
1689   has_pending_exception = !i::Execution::Call(
1690       isolate, fun, receiver, 0, NULL).ToHandle(&result);
1691   EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<Value>());
1692   return Utils::ToLocal(scope.CloseAndEscape(result));
1693 }
1694 
1695 
GetUnboundScript()1696 Local<UnboundScript> Script::GetUnboundScript() {
1697   i::Handle<i::Object> obj = Utils::OpenHandle(this);
1698   return ToApiHandle<UnboundScript>(
1699       i::Handle<i::SharedFunctionInfo>(i::JSFunction::cast(*obj)->shared()));
1700 }
1701 
1702 
CompileUnbound(Isolate * v8_isolate,Source * source,CompileOptions options)1703 Local<UnboundScript> ScriptCompiler::CompileUnbound(
1704     Isolate* v8_isolate,
1705     Source* source,
1706     CompileOptions options) {
1707   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
1708   ON_BAILOUT(isolate, "v8::ScriptCompiler::CompileUnbound()",
1709              return Local<UnboundScript>());
1710 
1711   // Support the old API for a transition period:
1712   // - kProduceToCache -> kProduceParserCache
1713   // - kNoCompileOptions + cached_data != NULL -> kConsumeParserCache
1714   if (options == kProduceDataToCache) {
1715     options = kProduceParserCache;
1716   } else if (options == kNoCompileOptions && source->cached_data) {
1717     options = kConsumeParserCache;
1718   }
1719 
1720   i::ScriptData* script_data = NULL;
1721   if (options == kConsumeParserCache || options == kConsumeCodeCache) {
1722     DCHECK(source->cached_data);
1723     // ScriptData takes care of pointer-aligning the data.
1724     script_data = new i::ScriptData(source->cached_data->data,
1725                                     source->cached_data->length);
1726   }
1727 
1728   i::Handle<i::String> str = Utils::OpenHandle(*(source->source_string));
1729   LOG_API(isolate, "ScriptCompiler::CompileUnbound");
1730   ENTER_V8(isolate);
1731   i::SharedFunctionInfo* raw_result = NULL;
1732   { i::HandleScope scope(isolate);
1733     i::Handle<i::Object> name_obj;
1734     int line_offset = 0;
1735     int column_offset = 0;
1736     bool is_shared_cross_origin = false;
1737     if (!source->resource_name.IsEmpty()) {
1738       name_obj = Utils::OpenHandle(*(source->resource_name));
1739     }
1740     if (!source->resource_line_offset.IsEmpty()) {
1741       line_offset = static_cast<int>(source->resource_line_offset->Value());
1742     }
1743     if (!source->resource_column_offset.IsEmpty()) {
1744       column_offset =
1745           static_cast<int>(source->resource_column_offset->Value());
1746     }
1747     if (!source->resource_is_shared_cross_origin.IsEmpty()) {
1748       v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
1749       is_shared_cross_origin =
1750           source->resource_is_shared_cross_origin == v8::True(v8_isolate);
1751     }
1752     EXCEPTION_PREAMBLE(isolate);
1753     i::Handle<i::SharedFunctionInfo> result = i::Compiler::CompileScript(
1754         str, name_obj, line_offset, column_offset, is_shared_cross_origin,
1755         isolate->global_context(), NULL, &script_data, options,
1756         i::NOT_NATIVES_CODE);
1757     has_pending_exception = result.is_null();
1758     if (has_pending_exception && script_data != NULL) {
1759       // This case won't happen during normal operation; we have compiled
1760       // successfully and produced cached data, and but the second compilation
1761       // of the same source code fails.
1762       delete script_data;
1763       script_data = NULL;
1764     }
1765     EXCEPTION_BAILOUT_CHECK(isolate, Local<UnboundScript>());
1766     raw_result = *result;
1767 
1768     if ((options == kProduceParserCache || options == kProduceCodeCache) &&
1769         script_data != NULL) {
1770       // script_data now contains the data that was generated. source will
1771       // take the ownership.
1772       source->cached_data = new CachedData(
1773           script_data->data(), script_data->length(), CachedData::BufferOwned);
1774       script_data->ReleaseDataOwnership();
1775     }
1776     delete script_data;
1777   }
1778   i::Handle<i::SharedFunctionInfo> result(raw_result, isolate);
1779   return ToApiHandle<UnboundScript>(result);
1780 }
1781 
1782 
Compile(Isolate * v8_isolate,Source * source,CompileOptions options)1783 Local<Script> ScriptCompiler::Compile(
1784     Isolate* v8_isolate,
1785     Source* source,
1786     CompileOptions options) {
1787   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
1788   ON_BAILOUT(isolate, "v8::ScriptCompiler::Compile()", return Local<Script>());
1789   LOG_API(isolate, "ScriptCompiler::CompiletBound()");
1790   ENTER_V8(isolate);
1791   Local<UnboundScript> generic = CompileUnbound(v8_isolate, source, options);
1792   if (generic.IsEmpty()) return Local<Script>();
1793   return generic->BindToCurrentContext();
1794 }
1795 
1796 
StartStreamingScript(Isolate * v8_isolate,StreamedSource * source,CompileOptions options)1797 ScriptCompiler::ScriptStreamingTask* ScriptCompiler::StartStreamingScript(
1798     Isolate* v8_isolate, StreamedSource* source, CompileOptions options) {
1799   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
1800   if (!isolate->global_context().is_null() &&
1801       !isolate->global_context()->IsNativeContext()) {
1802     // The context chain is non-trivial, and constructing the corresponding
1803     // non-trivial Scope chain outside the V8 heap is not implemented. Don't
1804     // stream the script. This will only occur if Harmony scoping is enabled and
1805     // a previous script has introduced "let" or "const" variables. TODO(marja):
1806     // Implement externalizing ScopeInfos and constructing non-trivial Scope
1807     // chains independent of the V8 heap so that we can stream also in this
1808     // case.
1809     return NULL;
1810   }
1811   return new i::BackgroundParsingTask(source->impl(), options,
1812                                       i::FLAG_stack_size, isolate);
1813 }
1814 
1815 
Compile(Isolate * v8_isolate,StreamedSource * v8_source,Handle<String> full_source_string,const ScriptOrigin & origin)1816 Local<Script> ScriptCompiler::Compile(Isolate* v8_isolate,
1817                                       StreamedSource* v8_source,
1818                                       Handle<String> full_source_string,
1819                                       const ScriptOrigin& origin) {
1820   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
1821   i::StreamedSource* source = v8_source->impl();
1822   ON_BAILOUT(isolate, "v8::ScriptCompiler::Compile()", return Local<Script>());
1823   LOG_API(isolate, "ScriptCompiler::Compile()");
1824   ENTER_V8(isolate);
1825   i::SharedFunctionInfo* raw_result = NULL;
1826 
1827   {
1828     i::HandleScope scope(isolate);
1829     i::Handle<i::String> str = Utils::OpenHandle(*(full_source_string));
1830     i::Handle<i::Script> script = isolate->factory()->NewScript(str);
1831     if (!origin.ResourceName().IsEmpty()) {
1832       script->set_name(*Utils::OpenHandle(*(origin.ResourceName())));
1833     }
1834     if (!origin.ResourceLineOffset().IsEmpty()) {
1835       script->set_line_offset(i::Smi::FromInt(
1836           static_cast<int>(origin.ResourceLineOffset()->Value())));
1837     }
1838     if (!origin.ResourceColumnOffset().IsEmpty()) {
1839       script->set_column_offset(i::Smi::FromInt(
1840           static_cast<int>(origin.ResourceColumnOffset()->Value())));
1841     }
1842     if (!origin.ResourceIsSharedCrossOrigin().IsEmpty()) {
1843       script->set_is_shared_cross_origin(origin.ResourceIsSharedCrossOrigin() ==
1844                                          v8::True(v8_isolate));
1845     }
1846     source->info->set_script(script);
1847     source->info->SetContext(isolate->global_context());
1848 
1849     EXCEPTION_PREAMBLE(isolate);
1850 
1851     // Do the parsing tasks which need to be done on the main thread. This will
1852     // also handle parse errors.
1853     source->parser->Internalize();
1854 
1855     i::Handle<i::SharedFunctionInfo> result =
1856         i::Handle<i::SharedFunctionInfo>::null();
1857     if (source->info->function() != NULL) {
1858       // Parsing has succeeded.
1859       result =
1860           i::Compiler::CompileStreamedScript(source->info.get(), str->length());
1861     }
1862     has_pending_exception = result.is_null();
1863     if (has_pending_exception) isolate->ReportPendingMessages();
1864     EXCEPTION_BAILOUT_CHECK(isolate, Local<Script>());
1865 
1866     raw_result = *result;
1867     // The Handle<Script> will go out of scope soon; make sure CompilationInfo
1868     // doesn't point to it.
1869     source->info->set_script(i::Handle<i::Script>());
1870   }  // HandleScope goes out of scope.
1871   i::Handle<i::SharedFunctionInfo> result(raw_result, isolate);
1872   Local<UnboundScript> generic = ToApiHandle<UnboundScript>(result);
1873   if (generic.IsEmpty()) {
1874     return Local<Script>();
1875   }
1876   return generic->BindToCurrentContext();
1877 }
1878 
1879 
Compile(v8::Handle<String> source,v8::ScriptOrigin * origin)1880 Local<Script> Script::Compile(v8::Handle<String> source,
1881                               v8::ScriptOrigin* origin) {
1882   i::Handle<i::String> str = Utils::OpenHandle(*source);
1883   if (origin) {
1884     ScriptCompiler::Source script_source(source, *origin);
1885     return ScriptCompiler::Compile(
1886         reinterpret_cast<v8::Isolate*>(str->GetIsolate()),
1887         &script_source);
1888   }
1889   ScriptCompiler::Source script_source(source);
1890   return ScriptCompiler::Compile(
1891       reinterpret_cast<v8::Isolate*>(str->GetIsolate()),
1892       &script_source);
1893 }
1894 
1895 
Compile(v8::Handle<String> source,v8::Handle<String> file_name)1896 Local<Script> Script::Compile(v8::Handle<String> source,
1897                               v8::Handle<String> file_name) {
1898   ScriptOrigin origin(file_name);
1899   return Compile(source, &origin);
1900 }
1901 
1902 
1903 // --- E x c e p t i o n s ---
1904 
1905 
TryCatch()1906 v8::TryCatch::TryCatch()
1907     : isolate_(i::Isolate::Current()),
1908       next_(isolate_->try_catch_handler()),
1909       is_verbose_(false),
1910       can_continue_(true),
1911       capture_message_(true),
1912       rethrow_(false),
1913       has_terminated_(false) {
1914   ResetInternal();
1915   // Special handling for simulators which have a separate JS stack.
1916   js_stack_comparable_address_ =
1917       reinterpret_cast<void*>(v8::internal::SimulatorStack::RegisterCTryCatch(
1918           v8::internal::GetCurrentStackPosition()));
1919   isolate_->RegisterTryCatchHandler(this);
1920 }
1921 
1922 
~TryCatch()1923 v8::TryCatch::~TryCatch() {
1924   DCHECK(isolate_ == i::Isolate::Current());
1925   if (rethrow_) {
1926     v8::Isolate* isolate = reinterpret_cast<Isolate*>(isolate_);
1927     v8::HandleScope scope(isolate);
1928     v8::Local<v8::Value> exc = v8::Local<v8::Value>::New(isolate, Exception());
1929     if (HasCaught() && capture_message_) {
1930       // If an exception was caught and rethrow_ is indicated, the saved
1931       // message, script, and location need to be restored to Isolate TLS
1932       // for reuse.  capture_message_ needs to be disabled so that DoThrow()
1933       // does not create a new message.
1934       isolate_->thread_local_top()->rethrowing_message_ = true;
1935       isolate_->RestorePendingMessageFromTryCatch(this);
1936     }
1937     isolate_->UnregisterTryCatchHandler(this);
1938     v8::internal::SimulatorStack::UnregisterCTryCatch();
1939     reinterpret_cast<Isolate*>(isolate_)->ThrowException(exc);
1940     DCHECK(!isolate_->thread_local_top()->rethrowing_message_);
1941   } else {
1942     if (HasCaught() && isolate_->has_scheduled_exception()) {
1943       // If an exception was caught but is still scheduled because no API call
1944       // promoted it, then it is canceled to prevent it from being propagated.
1945       // Note that this will not cancel termination exceptions.
1946       isolate_->CancelScheduledExceptionFromTryCatch(this);
1947     }
1948     isolate_->UnregisterTryCatchHandler(this);
1949     v8::internal::SimulatorStack::UnregisterCTryCatch();
1950   }
1951 }
1952 
1953 
HasCaught() const1954 bool v8::TryCatch::HasCaught() const {
1955   return !reinterpret_cast<i::Object*>(exception_)->IsTheHole();
1956 }
1957 
1958 
CanContinue() const1959 bool v8::TryCatch::CanContinue() const {
1960   return can_continue_;
1961 }
1962 
1963 
HasTerminated() const1964 bool v8::TryCatch::HasTerminated() const {
1965   return has_terminated_;
1966 }
1967 
1968 
ReThrow()1969 v8::Handle<v8::Value> v8::TryCatch::ReThrow() {
1970   if (!HasCaught()) return v8::Local<v8::Value>();
1971   rethrow_ = true;
1972   return v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate_));
1973 }
1974 
1975 
Exception() const1976 v8::Local<Value> v8::TryCatch::Exception() const {
1977   DCHECK(isolate_ == i::Isolate::Current());
1978   if (HasCaught()) {
1979     // Check for out of memory exception.
1980     i::Object* exception = reinterpret_cast<i::Object*>(exception_);
1981     return v8::Utils::ToLocal(i::Handle<i::Object>(exception, isolate_));
1982   } else {
1983     return v8::Local<Value>();
1984   }
1985 }
1986 
1987 
StackTrace() const1988 v8::Local<Value> v8::TryCatch::StackTrace() const {
1989   DCHECK(isolate_ == i::Isolate::Current());
1990   if (HasCaught()) {
1991     i::Object* raw_obj = reinterpret_cast<i::Object*>(exception_);
1992     if (!raw_obj->IsJSObject()) return v8::Local<Value>();
1993     i::HandleScope scope(isolate_);
1994     i::Handle<i::JSObject> obj(i::JSObject::cast(raw_obj), isolate_);
1995     i::Handle<i::String> name = isolate_->factory()->stack_string();
1996     EXCEPTION_PREAMBLE(isolate_);
1997     Maybe<bool> maybe = i::JSReceiver::HasProperty(obj, name);
1998     has_pending_exception = !maybe.has_value;
1999     EXCEPTION_BAILOUT_CHECK(isolate_, v8::Local<Value>());
2000     if (!maybe.value) return v8::Local<Value>();
2001     i::Handle<i::Object> value;
2002     if (!i::Object::GetProperty(obj, name).ToHandle(&value)) {
2003       return v8::Local<Value>();
2004     }
2005     return v8::Utils::ToLocal(scope.CloseAndEscape(value));
2006   } else {
2007     return v8::Local<Value>();
2008   }
2009 }
2010 
2011 
Message() const2012 v8::Local<v8::Message> v8::TryCatch::Message() const {
2013   DCHECK(isolate_ == i::Isolate::Current());
2014   i::Object* message = reinterpret_cast<i::Object*>(message_obj_);
2015   DCHECK(message->IsJSMessageObject() || message->IsTheHole());
2016   if (HasCaught() && !message->IsTheHole()) {
2017     return v8::Utils::MessageToLocal(i::Handle<i::Object>(message, isolate_));
2018   } else {
2019     return v8::Local<v8::Message>();
2020   }
2021 }
2022 
2023 
Reset()2024 void v8::TryCatch::Reset() {
2025   DCHECK(isolate_ == i::Isolate::Current());
2026   if (!rethrow_ && HasCaught() && isolate_->has_scheduled_exception()) {
2027     // If an exception was caught but is still scheduled because no API call
2028     // promoted it, then it is canceled to prevent it from being propagated.
2029     // Note that this will not cancel termination exceptions.
2030     isolate_->CancelScheduledExceptionFromTryCatch(this);
2031   }
2032   ResetInternal();
2033 }
2034 
2035 
ResetInternal()2036 void v8::TryCatch::ResetInternal() {
2037   i::Object* the_hole = isolate_->heap()->the_hole_value();
2038   exception_ = the_hole;
2039   message_obj_ = the_hole;
2040   message_script_ = the_hole;
2041   message_start_pos_ = 0;
2042   message_end_pos_ = 0;
2043 }
2044 
2045 
SetVerbose(bool value)2046 void v8::TryCatch::SetVerbose(bool value) {
2047   is_verbose_ = value;
2048 }
2049 
2050 
SetCaptureMessage(bool value)2051 void v8::TryCatch::SetCaptureMessage(bool value) {
2052   capture_message_ = value;
2053 }
2054 
2055 
2056 // --- M e s s a g e ---
2057 
2058 
Get() const2059 Local<String> Message::Get() const {
2060   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2061   ON_BAILOUT(isolate, "v8::Message::Get()", return Local<String>());
2062   ENTER_V8(isolate);
2063   EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate));
2064   i::Handle<i::Object> obj = Utils::OpenHandle(this);
2065   i::Handle<i::String> raw_result = i::MessageHandler::GetMessage(isolate, obj);
2066   Local<String> result = Utils::ToLocal(raw_result);
2067   return scope.Escape(result);
2068 }
2069 
2070 
GetScriptOrigin() const2071 ScriptOrigin Message::GetScriptOrigin() const {
2072   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2073   i::Handle<i::JSMessageObject> message =
2074       i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
2075   i::Handle<i::Object> script_wraper =
2076       i::Handle<i::Object>(message->script(), isolate);
2077   i::Handle<i::JSValue> script_value =
2078       i::Handle<i::JSValue>::cast(script_wraper);
2079   i::Handle<i::Script> script(i::Script::cast(script_value->value()));
2080   i::Handle<i::Object> scriptName(i::Script::GetNameOrSourceURL(script));
2081   v8::Isolate* v8_isolate =
2082       reinterpret_cast<v8::Isolate*>(script->GetIsolate());
2083   v8::ScriptOrigin origin(
2084       Utils::ToLocal(scriptName),
2085       v8::Integer::New(v8_isolate, script->line_offset()->value()),
2086       v8::Integer::New(v8_isolate, script->column_offset()->value()),
2087       Handle<Boolean>(),
2088       v8::Integer::New(v8_isolate, script->id()->value()));
2089   return origin;
2090 }
2091 
2092 
GetScriptResourceName() const2093 v8::Handle<Value> Message::GetScriptResourceName() const {
2094   return GetScriptOrigin().ResourceName();
2095 }
2096 
2097 
GetStackTrace() const2098 v8::Handle<v8::StackTrace> Message::GetStackTrace() const {
2099   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2100   ENTER_V8(isolate);
2101   EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate));
2102   i::Handle<i::JSMessageObject> message =
2103       i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
2104   i::Handle<i::Object> stackFramesObj(message->stack_frames(), isolate);
2105   if (!stackFramesObj->IsJSArray()) return v8::Handle<v8::StackTrace>();
2106   i::Handle<i::JSArray> stackTrace =
2107       i::Handle<i::JSArray>::cast(stackFramesObj);
2108   return scope.Escape(Utils::StackTraceToLocal(stackTrace));
2109 }
2110 
2111 
CallV8HeapFunction(const char * name,i::Handle<i::Object> recv,int argc,i::Handle<i::Object> argv[])2112 MUST_USE_RESULT static i::MaybeHandle<i::Object> CallV8HeapFunction(
2113     const char* name,
2114     i::Handle<i::Object> recv,
2115     int argc,
2116     i::Handle<i::Object> argv[]) {
2117   i::Isolate* isolate = i::Isolate::Current();
2118   i::Handle<i::Object> object_fun =
2119       i::Object::GetProperty(
2120           isolate, isolate->js_builtins_object(), name).ToHandleChecked();
2121   i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(object_fun);
2122   return i::Execution::Call(isolate, fun, recv, argc, argv);
2123 }
2124 
2125 
CallV8HeapFunction(const char * name,i::Handle<i::Object> data)2126 MUST_USE_RESULT static i::MaybeHandle<i::Object> CallV8HeapFunction(
2127     const char* name,
2128     i::Handle<i::Object> data) {
2129   i::Handle<i::Object> argv[] = { data };
2130   return CallV8HeapFunction(name,
2131                             i::Isolate::Current()->js_builtins_object(),
2132                             arraysize(argv),
2133                             argv);
2134 }
2135 
2136 
GetLineNumber() const2137 int Message::GetLineNumber() const {
2138   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2139   ON_BAILOUT(isolate, "v8::Message::GetLineNumber()", return kNoLineNumberInfo);
2140   ENTER_V8(isolate);
2141   i::HandleScope scope(isolate);
2142 
2143   EXCEPTION_PREAMBLE(isolate);
2144   i::Handle<i::Object> result;
2145   has_pending_exception = !CallV8HeapFunction(
2146       "GetLineNumber", Utils::OpenHandle(this)).ToHandle(&result);
2147   EXCEPTION_BAILOUT_CHECK(isolate, 0);
2148   return static_cast<int>(result->Number());
2149 }
2150 
2151 
GetStartPosition() const2152 int Message::GetStartPosition() const {
2153   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2154   ENTER_V8(isolate);
2155   i::HandleScope scope(isolate);
2156   i::Handle<i::JSMessageObject> message =
2157       i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
2158   return message->start_position();
2159 }
2160 
2161 
GetEndPosition() const2162 int Message::GetEndPosition() const {
2163   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2164   ENTER_V8(isolate);
2165   i::HandleScope scope(isolate);
2166   i::Handle<i::JSMessageObject> message =
2167       i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
2168   return message->end_position();
2169 }
2170 
2171 
GetStartColumn() const2172 int Message::GetStartColumn() const {
2173   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2174   ON_BAILOUT(isolate, "v8::Message::GetStartColumn()", return kNoColumnInfo);
2175   ENTER_V8(isolate);
2176   i::HandleScope scope(isolate);
2177   i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
2178   EXCEPTION_PREAMBLE(isolate);
2179   i::Handle<i::Object> start_col_obj;
2180   has_pending_exception = !CallV8HeapFunction(
2181       "GetPositionInLine", data_obj).ToHandle(&start_col_obj);
2182   EXCEPTION_BAILOUT_CHECK(isolate, 0);
2183   return static_cast<int>(start_col_obj->Number());
2184 }
2185 
2186 
GetEndColumn() const2187 int Message::GetEndColumn() const {
2188   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2189   ON_BAILOUT(isolate, "v8::Message::GetEndColumn()", return kNoColumnInfo);
2190   ENTER_V8(isolate);
2191   i::HandleScope scope(isolate);
2192   i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
2193   EXCEPTION_PREAMBLE(isolate);
2194   i::Handle<i::Object> start_col_obj;
2195   has_pending_exception = !CallV8HeapFunction(
2196       "GetPositionInLine", data_obj).ToHandle(&start_col_obj);
2197   EXCEPTION_BAILOUT_CHECK(isolate, 0);
2198   i::Handle<i::JSMessageObject> message =
2199       i::Handle<i::JSMessageObject>::cast(data_obj);
2200   int start = message->start_position();
2201   int end = message->end_position();
2202   return static_cast<int>(start_col_obj->Number()) + (end - start);
2203 }
2204 
2205 
IsSharedCrossOrigin() const2206 bool Message::IsSharedCrossOrigin() const {
2207   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2208   ENTER_V8(isolate);
2209   i::HandleScope scope(isolate);
2210   i::Handle<i::JSMessageObject> message =
2211       i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
2212   i::Handle<i::JSValue> script =
2213       i::Handle<i::JSValue>::cast(i::Handle<i::Object>(message->script(),
2214                                                        isolate));
2215   return i::Script::cast(script->value())->is_shared_cross_origin();
2216 }
2217 
2218 
GetSourceLine() const2219 Local<String> Message::GetSourceLine() const {
2220   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2221   ON_BAILOUT(isolate, "v8::Message::GetSourceLine()", return Local<String>());
2222   ENTER_V8(isolate);
2223   EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate));
2224   EXCEPTION_PREAMBLE(isolate);
2225   i::Handle<i::Object> result;
2226   has_pending_exception = !CallV8HeapFunction(
2227       "GetSourceLine", Utils::OpenHandle(this)).ToHandle(&result);
2228   EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::String>());
2229   if (result->IsString()) {
2230     return scope.Escape(Utils::ToLocal(i::Handle<i::String>::cast(result)));
2231   } else {
2232     return Local<String>();
2233   }
2234 }
2235 
2236 
PrintCurrentStackTrace(Isolate * isolate,FILE * out)2237 void Message::PrintCurrentStackTrace(Isolate* isolate, FILE* out) {
2238   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
2239   ENTER_V8(i_isolate);
2240   i_isolate->PrintCurrentStackTrace(out);
2241 }
2242 
2243 
2244 // --- S t a c k T r a c e ---
2245 
GetFrame(uint32_t index) const2246 Local<StackFrame> StackTrace::GetFrame(uint32_t index) const {
2247   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2248   ENTER_V8(isolate);
2249   EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate));
2250   i::Handle<i::JSArray> self = Utils::OpenHandle(this);
2251   i::Handle<i::Object> obj =
2252       i::Object::GetElement(isolate, self, index).ToHandleChecked();
2253   i::Handle<i::JSObject> jsobj = i::Handle<i::JSObject>::cast(obj);
2254   return scope.Escape(Utils::StackFrameToLocal(jsobj));
2255 }
2256 
2257 
GetFrameCount() const2258 int StackTrace::GetFrameCount() const {
2259   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2260   ENTER_V8(isolate);
2261   return i::Smi::cast(Utils::OpenHandle(this)->length())->value();
2262 }
2263 
2264 
AsArray()2265 Local<Array> StackTrace::AsArray() {
2266   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2267   ENTER_V8(isolate);
2268   return Utils::ToLocal(Utils::OpenHandle(this));
2269 }
2270 
2271 
CurrentStackTrace(Isolate * isolate,int frame_limit,StackTraceOptions options)2272 Local<StackTrace> StackTrace::CurrentStackTrace(
2273     Isolate* isolate,
2274     int frame_limit,
2275     StackTraceOptions options) {
2276   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
2277   ENTER_V8(i_isolate);
2278   // TODO(dcarney): remove when ScriptDebugServer is fixed.
2279   options = static_cast<StackTraceOptions>(
2280       static_cast<int>(options) | kExposeFramesAcrossSecurityOrigins);
2281   i::Handle<i::JSArray> stackTrace =
2282       i_isolate->CaptureCurrentStackTrace(frame_limit, options);
2283   return Utils::StackTraceToLocal(stackTrace);
2284 }
2285 
2286 
2287 // --- S t a c k F r a m e ---
2288 
getIntProperty(const StackFrame * f,const char * propertyName,int defaultValue)2289 static int getIntProperty(const StackFrame* f, const char* propertyName,
2290                           int defaultValue) {
2291   i::Isolate* isolate = Utils::OpenHandle(f)->GetIsolate();
2292   ENTER_V8(isolate);
2293   i::HandleScope scope(isolate);
2294   i::Handle<i::JSObject> self = Utils::OpenHandle(f);
2295   i::Handle<i::Object> obj =
2296       i::Object::GetProperty(isolate, self, propertyName).ToHandleChecked();
2297   return obj->IsSmi() ? i::Smi::cast(*obj)->value() : defaultValue;
2298 }
2299 
2300 
GetLineNumber() const2301 int StackFrame::GetLineNumber() const {
2302   return getIntProperty(this, "lineNumber", Message::kNoLineNumberInfo);
2303 }
2304 
2305 
GetColumn() const2306 int StackFrame::GetColumn() const {
2307   return getIntProperty(this, "column", Message::kNoColumnInfo);
2308 }
2309 
2310 
GetScriptId() const2311 int StackFrame::GetScriptId() const {
2312   return getIntProperty(this, "scriptId", Message::kNoScriptIdInfo);
2313 }
2314 
2315 
getStringProperty(const StackFrame * f,const char * propertyName)2316 static Local<String> getStringProperty(const StackFrame* f,
2317                                        const char* propertyName) {
2318   i::Isolate* isolate = Utils::OpenHandle(f)->GetIsolate();
2319   ENTER_V8(isolate);
2320   EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate));
2321   i::Handle<i::JSObject> self = Utils::OpenHandle(f);
2322   i::Handle<i::Object> obj =
2323       i::Object::GetProperty(isolate, self, propertyName).ToHandleChecked();
2324   return obj->IsString()
2325              ? scope.Escape(Local<String>::Cast(Utils::ToLocal(obj)))
2326              : Local<String>();
2327 }
2328 
2329 
GetScriptName() const2330 Local<String> StackFrame::GetScriptName() const {
2331   return getStringProperty(this, "scriptName");
2332 }
2333 
2334 
GetScriptNameOrSourceURL() const2335 Local<String> StackFrame::GetScriptNameOrSourceURL() const {
2336   return getStringProperty(this, "scriptNameOrSourceURL");
2337 }
2338 
2339 
GetFunctionName() const2340 Local<String> StackFrame::GetFunctionName() const {
2341   return getStringProperty(this, "functionName");
2342 }
2343 
2344 
getBoolProperty(const StackFrame * f,const char * propertyName)2345 static bool getBoolProperty(const StackFrame* f, const char* propertyName) {
2346   i::Isolate* isolate = Utils::OpenHandle(f)->GetIsolate();
2347   ENTER_V8(isolate);
2348   i::HandleScope scope(isolate);
2349   i::Handle<i::JSObject> self = Utils::OpenHandle(f);
2350   i::Handle<i::Object> obj =
2351       i::Object::GetProperty(isolate, self, propertyName).ToHandleChecked();
2352   return obj->IsTrue();
2353 }
2354 
IsEval() const2355 bool StackFrame::IsEval() const { return getBoolProperty(this, "isEval"); }
2356 
2357 
IsConstructor() const2358 bool StackFrame::IsConstructor() const {
2359   return getBoolProperty(this, "isConstructor");
2360 }
2361 
2362 
2363 // --- J S O N ---
2364 
Parse(Local<String> json_string)2365 Local<Value> JSON::Parse(Local<String> json_string) {
2366   i::Handle<i::String> string = Utils::OpenHandle(*json_string);
2367   i::Isolate* isolate = string->GetIsolate();
2368   ENTER_V8(isolate);
2369   i::HandleScope scope(isolate);
2370   i::Handle<i::String> source = i::String::Flatten(string);
2371   EXCEPTION_PREAMBLE(isolate);
2372   i::MaybeHandle<i::Object> maybe_result =
2373       source->IsSeqOneByteString() ? i::JsonParser<true>::Parse(source)
2374                                    : i::JsonParser<false>::Parse(source);
2375   i::Handle<i::Object> result;
2376   has_pending_exception = !maybe_result.ToHandle(&result);
2377   EXCEPTION_BAILOUT_CHECK(isolate, Local<Object>());
2378   return Utils::ToLocal(
2379       i::Handle<i::Object>::cast(scope.CloseAndEscape(result)));
2380 }
2381 
2382 
2383 // --- D a t a ---
2384 
FullIsUndefined() const2385 bool Value::FullIsUndefined() const {
2386   bool result = Utils::OpenHandle(this)->IsUndefined();
2387   DCHECK_EQ(result, QuickIsUndefined());
2388   return result;
2389 }
2390 
2391 
FullIsNull() const2392 bool Value::FullIsNull() const {
2393   bool result = Utils::OpenHandle(this)->IsNull();
2394   DCHECK_EQ(result, QuickIsNull());
2395   return result;
2396 }
2397 
2398 
IsTrue() const2399 bool Value::IsTrue() const {
2400   return Utils::OpenHandle(this)->IsTrue();
2401 }
2402 
2403 
IsFalse() const2404 bool Value::IsFalse() const {
2405   return Utils::OpenHandle(this)->IsFalse();
2406 }
2407 
2408 
IsFunction() const2409 bool Value::IsFunction() const {
2410   return Utils::OpenHandle(this)->IsJSFunction();
2411 }
2412 
2413 
IsName() const2414 bool Value::IsName() const {
2415   return Utils::OpenHandle(this)->IsName();
2416 }
2417 
2418 
FullIsString() const2419 bool Value::FullIsString() const {
2420   bool result = Utils::OpenHandle(this)->IsString();
2421   DCHECK_EQ(result, QuickIsString());
2422   return result;
2423 }
2424 
2425 
IsSymbol() const2426 bool Value::IsSymbol() const {
2427   return Utils::OpenHandle(this)->IsSymbol();
2428 }
2429 
2430 
IsArray() const2431 bool Value::IsArray() const {
2432   return Utils::OpenHandle(this)->IsJSArray();
2433 }
2434 
2435 
IsArrayBuffer() const2436 bool Value::IsArrayBuffer() const {
2437   return Utils::OpenHandle(this)->IsJSArrayBuffer();
2438 }
2439 
2440 
IsArrayBufferView() const2441 bool Value::IsArrayBufferView() const {
2442   return Utils::OpenHandle(this)->IsJSArrayBufferView();
2443 }
2444 
2445 
IsTypedArray() const2446 bool Value::IsTypedArray() const {
2447   return Utils::OpenHandle(this)->IsJSTypedArray();
2448 }
2449 
2450 
2451 #define VALUE_IS_TYPED_ARRAY(Type, typeName, TYPE, ctype, size)            \
2452   bool Value::Is##Type##Array() const {                                    \
2453     i::Handle<i::Object> obj = Utils::OpenHandle(this);                    \
2454     return obj->IsJSTypedArray() &&                                        \
2455            i::JSTypedArray::cast(*obj)->type() == kExternal##Type##Array;  \
2456   }
2457 
TYPED_ARRAYS(VALUE_IS_TYPED_ARRAY)2458 TYPED_ARRAYS(VALUE_IS_TYPED_ARRAY)
2459 
2460 #undef VALUE_IS_TYPED_ARRAY
2461 
2462 
2463 bool Value::IsDataView() const {
2464   return Utils::OpenHandle(this)->IsJSDataView();
2465 }
2466 
2467 
IsObject() const2468 bool Value::IsObject() const {
2469   return Utils::OpenHandle(this)->IsJSObject();
2470 }
2471 
2472 
IsNumber() const2473 bool Value::IsNumber() const {
2474   return Utils::OpenHandle(this)->IsNumber();
2475 }
2476 
2477 
2478 #define VALUE_IS_SPECIFIC_TYPE(Type, Class)                            \
2479   bool Value::Is##Type() const {                                       \
2480     i::Handle<i::Object> obj = Utils::OpenHandle(this);                \
2481     if (!obj->IsHeapObject()) return false;                            \
2482     i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();     \
2483     return obj->HasSpecificClassOf(isolate->heap()->Class##_string()); \
2484   }
2485 
VALUE_IS_SPECIFIC_TYPE(ArgumentsObject,Arguments)2486 VALUE_IS_SPECIFIC_TYPE(ArgumentsObject, Arguments)
2487 VALUE_IS_SPECIFIC_TYPE(BooleanObject, Boolean)
2488 VALUE_IS_SPECIFIC_TYPE(NumberObject, Number)
2489 VALUE_IS_SPECIFIC_TYPE(StringObject, String)
2490 VALUE_IS_SPECIFIC_TYPE(SymbolObject, Symbol)
2491 VALUE_IS_SPECIFIC_TYPE(Date, Date)
2492 VALUE_IS_SPECIFIC_TYPE(Map, Map)
2493 VALUE_IS_SPECIFIC_TYPE(Set, Set)
2494 VALUE_IS_SPECIFIC_TYPE(WeakMap, WeakMap)
2495 VALUE_IS_SPECIFIC_TYPE(WeakSet, WeakSet)
2496 
2497 #undef VALUE_IS_SPECIFIC_TYPE
2498 
2499 
2500 bool Value::IsBoolean() const {
2501   return Utils::OpenHandle(this)->IsBoolean();
2502 }
2503 
2504 
IsExternal() const2505 bool Value::IsExternal() const {
2506   return Utils::OpenHandle(this)->IsExternal();
2507 }
2508 
2509 
IsInt32() const2510 bool Value::IsInt32() const {
2511   i::Handle<i::Object> obj = Utils::OpenHandle(this);
2512   if (obj->IsSmi()) return true;
2513   if (obj->IsNumber()) {
2514     return i::IsInt32Double(obj->Number());
2515   }
2516   return false;
2517 }
2518 
2519 
IsUint32() const2520 bool Value::IsUint32() const {
2521   i::Handle<i::Object> obj = Utils::OpenHandle(this);
2522   if (obj->IsSmi()) return i::Smi::cast(*obj)->value() >= 0;
2523   if (obj->IsNumber()) {
2524     double value = obj->Number();
2525     return !i::IsMinusZero(value) &&
2526         value >= 0 &&
2527         value <= i::kMaxUInt32 &&
2528         value == i::FastUI2D(i::FastD2UI(value));
2529   }
2530   return false;
2531 }
2532 
2533 
CheckConstructor(i::Isolate * isolate,i::Handle<i::JSObject> obj,const char * class_name)2534 static bool CheckConstructor(i::Isolate* isolate,
2535                              i::Handle<i::JSObject> obj,
2536                              const char* class_name) {
2537   i::Handle<i::Object> constr(obj->map()->constructor(), isolate);
2538   if (!constr->IsJSFunction()) return false;
2539   i::Handle<i::JSFunction> func = i::Handle<i::JSFunction>::cast(constr);
2540   return func->shared()->native() && constr.is_identical_to(
2541       i::Object::GetProperty(isolate,
2542                              isolate->js_builtins_object(),
2543                              class_name).ToHandleChecked());
2544 }
2545 
2546 
IsNativeError() const2547 bool Value::IsNativeError() const {
2548   i::Handle<i::Object> obj = Utils::OpenHandle(this);
2549   if (obj->IsJSObject()) {
2550     i::Handle<i::JSObject> js_obj(i::JSObject::cast(*obj));
2551     i::Isolate* isolate = js_obj->GetIsolate();
2552     return CheckConstructor(isolate, js_obj, "$Error") ||
2553         CheckConstructor(isolate, js_obj, "$EvalError") ||
2554         CheckConstructor(isolate, js_obj, "$RangeError") ||
2555         CheckConstructor(isolate, js_obj, "$ReferenceError") ||
2556         CheckConstructor(isolate, js_obj, "$SyntaxError") ||
2557         CheckConstructor(isolate, js_obj, "$TypeError") ||
2558         CheckConstructor(isolate, js_obj, "$URIError");
2559   } else {
2560     return false;
2561   }
2562 }
2563 
2564 
IsRegExp() const2565 bool Value::IsRegExp() const {
2566   i::Handle<i::Object> obj = Utils::OpenHandle(this);
2567   return obj->IsJSRegExp();
2568 }
2569 
2570 
ToString() const2571 Local<String> Value::ToString() const {
2572   i::Handle<i::Object> obj = Utils::OpenHandle(this);
2573   i::Handle<i::Object> str;
2574   if (obj->IsString()) {
2575     str = obj;
2576   } else {
2577     i::Isolate* isolate = i::Isolate::Current();
2578     LOG_API(isolate, "ToString");
2579     ENTER_V8(isolate);
2580     EXCEPTION_PREAMBLE(isolate);
2581     has_pending_exception = !i::Execution::ToString(
2582         isolate, obj).ToHandle(&str);
2583     EXCEPTION_BAILOUT_CHECK(isolate, Local<String>());
2584   }
2585   return ToApiHandle<String>(str);
2586 }
2587 
2588 
ToDetailString() const2589 Local<String> Value::ToDetailString() const {
2590   i::Handle<i::Object> obj = Utils::OpenHandle(this);
2591   i::Handle<i::Object> str;
2592   if (obj->IsString()) {
2593     str = obj;
2594   } else {
2595     i::Isolate* isolate = i::Isolate::Current();
2596     LOG_API(isolate, "ToDetailString");
2597     ENTER_V8(isolate);
2598     EXCEPTION_PREAMBLE(isolate);
2599     has_pending_exception = !i::Execution::ToDetailString(
2600         isolate, obj).ToHandle(&str);
2601     EXCEPTION_BAILOUT_CHECK(isolate, Local<String>());
2602   }
2603   return ToApiHandle<String>(str);
2604 }
2605 
2606 
ToObject() const2607 Local<v8::Object> Value::ToObject() const {
2608   i::Handle<i::Object> obj = Utils::OpenHandle(this);
2609   i::Handle<i::Object> val;
2610   if (obj->IsJSObject()) {
2611     val = obj;
2612   } else {
2613     i::Isolate* isolate = i::Isolate::Current();
2614     LOG_API(isolate, "ToObject");
2615     ENTER_V8(isolate);
2616     EXCEPTION_PREAMBLE(isolate);
2617     has_pending_exception = !i::Execution::ToObject(
2618         isolate, obj).ToHandle(&val);
2619     EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Object>());
2620   }
2621   return ToApiHandle<Object>(val);
2622 }
2623 
2624 
ToBoolean() const2625 Local<Boolean> Value::ToBoolean() const {
2626   i::Handle<i::Object> obj = Utils::OpenHandle(this);
2627   if (obj->IsBoolean()) {
2628     return ToApiHandle<Boolean>(obj);
2629   } else {
2630     i::Isolate* isolate = i::Isolate::Current();
2631     LOG_API(isolate, "ToBoolean");
2632     ENTER_V8(isolate);
2633     i::Handle<i::Object> val =
2634         isolate->factory()->ToBoolean(obj->BooleanValue());
2635     return ToApiHandle<Boolean>(val);
2636   }
2637 }
2638 
2639 
ToNumber() const2640 Local<Number> Value::ToNumber() const {
2641   i::Handle<i::Object> obj = Utils::OpenHandle(this);
2642   i::Handle<i::Object> num;
2643   if (obj->IsNumber()) {
2644     num = obj;
2645   } else {
2646     i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
2647     LOG_API(isolate, "ToNumber");
2648     ENTER_V8(isolate);
2649     EXCEPTION_PREAMBLE(isolate);
2650     has_pending_exception = !i::Execution::ToNumber(
2651         isolate, obj).ToHandle(&num);
2652     EXCEPTION_BAILOUT_CHECK(isolate, Local<Number>());
2653   }
2654   return ToApiHandle<Number>(num);
2655 }
2656 
2657 
ToInteger() const2658 Local<Integer> Value::ToInteger() const {
2659   i::Handle<i::Object> obj = Utils::OpenHandle(this);
2660   i::Handle<i::Object> num;
2661   if (obj->IsSmi()) {
2662     num = obj;
2663   } else {
2664     i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
2665     LOG_API(isolate, "ToInteger");
2666     ENTER_V8(isolate);
2667     EXCEPTION_PREAMBLE(isolate);
2668     has_pending_exception = !i::Execution::ToInteger(
2669         isolate, obj).ToHandle(&num);
2670     EXCEPTION_BAILOUT_CHECK(isolate, Local<Integer>());
2671   }
2672   return ToApiHandle<Integer>(num);
2673 }
2674 
2675 
CheckInitializedImpl(v8::Isolate * external_isolate)2676 void i::Internals::CheckInitializedImpl(v8::Isolate* external_isolate) {
2677   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(external_isolate);
2678   Utils::ApiCheck(isolate != NULL &&
2679                   isolate->IsInitialized() &&
2680                   !isolate->IsDead(),
2681                   "v8::internal::Internals::CheckInitialized()",
2682                   "Isolate is not initialized or V8 has died");
2683 }
2684 
2685 
CheckCast(v8::Value * that)2686 void External::CheckCast(v8::Value* that) {
2687   Utils::ApiCheck(Utils::OpenHandle(that)->IsExternal(),
2688                   "v8::External::Cast()",
2689                   "Could not convert to external");
2690 }
2691 
2692 
CheckCast(Value * that)2693 void v8::Object::CheckCast(Value* that) {
2694   i::Handle<i::Object> obj = Utils::OpenHandle(that);
2695   Utils::ApiCheck(obj->IsJSObject(),
2696                   "v8::Object::Cast()",
2697                   "Could not convert to object");
2698 }
2699 
2700 
CheckCast(Value * that)2701 void v8::Function::CheckCast(Value* that) {
2702   i::Handle<i::Object> obj = Utils::OpenHandle(that);
2703   Utils::ApiCheck(obj->IsJSFunction(),
2704                   "v8::Function::Cast()",
2705                   "Could not convert to function");
2706 }
2707 
2708 
CheckCast(v8::Value * that)2709 void v8::Name::CheckCast(v8::Value* that) {
2710   i::Handle<i::Object> obj = Utils::OpenHandle(that);
2711   Utils::ApiCheck(obj->IsName(),
2712                   "v8::Name::Cast()",
2713                   "Could not convert to name");
2714 }
2715 
2716 
CheckCast(v8::Value * that)2717 void v8::String::CheckCast(v8::Value* that) {
2718   i::Handle<i::Object> obj = Utils::OpenHandle(that);
2719   Utils::ApiCheck(obj->IsString(),
2720                   "v8::String::Cast()",
2721                   "Could not convert to string");
2722 }
2723 
2724 
CheckCast(v8::Value * that)2725 void v8::Symbol::CheckCast(v8::Value* that) {
2726   i::Handle<i::Object> obj = Utils::OpenHandle(that);
2727   Utils::ApiCheck(obj->IsSymbol(),
2728                   "v8::Symbol::Cast()",
2729                   "Could not convert to symbol");
2730 }
2731 
2732 
CheckCast(v8::Value * that)2733 void v8::Number::CheckCast(v8::Value* that) {
2734   i::Handle<i::Object> obj = Utils::OpenHandle(that);
2735   Utils::ApiCheck(obj->IsNumber(),
2736                   "v8::Number::Cast()",
2737                   "Could not convert to number");
2738 }
2739 
2740 
CheckCast(v8::Value * that)2741 void v8::Integer::CheckCast(v8::Value* that) {
2742   i::Handle<i::Object> obj = Utils::OpenHandle(that);
2743   Utils::ApiCheck(obj->IsNumber(),
2744                   "v8::Integer::Cast()",
2745                   "Could not convert to number");
2746 }
2747 
2748 
CheckCast(Value * that)2749 void v8::Array::CheckCast(Value* that) {
2750   i::Handle<i::Object> obj = Utils::OpenHandle(that);
2751   Utils::ApiCheck(obj->IsJSArray(),
2752                   "v8::Array::Cast()",
2753                   "Could not convert to array");
2754 }
2755 
2756 
CheckCast(Value * that)2757 void v8::Promise::CheckCast(Value* that) {
2758   Utils::ApiCheck(that->IsPromise(),
2759                   "v8::Promise::Cast()",
2760                   "Could not convert to promise");
2761 }
2762 
2763 
CheckCast(Value * that)2764 void v8::Promise::Resolver::CheckCast(Value* that) {
2765   Utils::ApiCheck(that->IsPromise(),
2766                   "v8::Promise::Resolver::Cast()",
2767                   "Could not convert to promise resolver");
2768 }
2769 
2770 
CheckCast(Value * that)2771 void v8::ArrayBuffer::CheckCast(Value* that) {
2772   i::Handle<i::Object> obj = Utils::OpenHandle(that);
2773   Utils::ApiCheck(obj->IsJSArrayBuffer(),
2774                   "v8::ArrayBuffer::Cast()",
2775                   "Could not convert to ArrayBuffer");
2776 }
2777 
2778 
CheckCast(Value * that)2779 void v8::ArrayBufferView::CheckCast(Value* that) {
2780   i::Handle<i::Object> obj = Utils::OpenHandle(that);
2781   Utils::ApiCheck(obj->IsJSArrayBufferView(),
2782                   "v8::ArrayBufferView::Cast()",
2783                   "Could not convert to ArrayBufferView");
2784 }
2785 
2786 
CheckCast(Value * that)2787 void v8::TypedArray::CheckCast(Value* that) {
2788   i::Handle<i::Object> obj = Utils::OpenHandle(that);
2789   Utils::ApiCheck(obj->IsJSTypedArray(),
2790                   "v8::TypedArray::Cast()",
2791                   "Could not convert to TypedArray");
2792 }
2793 
2794 
2795 #define CHECK_TYPED_ARRAY_CAST(Type, typeName, TYPE, ctype, size)             \
2796   void v8::Type##Array::CheckCast(Value* that) {                              \
2797     i::Handle<i::Object> obj = Utils::OpenHandle(that);                       \
2798     Utils::ApiCheck(obj->IsJSTypedArray() &&                                  \
2799                     i::JSTypedArray::cast(*obj)->type() ==                    \
2800                         kExternal##Type##Array,                               \
2801                     "v8::" #Type "Array::Cast()",                             \
2802                     "Could not convert to " #Type "Array");                   \
2803   }
2804 
2805 
TYPED_ARRAYS(CHECK_TYPED_ARRAY_CAST)2806 TYPED_ARRAYS(CHECK_TYPED_ARRAY_CAST)
2807 
2808 #undef CHECK_TYPED_ARRAY_CAST
2809 
2810 
2811 void v8::DataView::CheckCast(Value* that) {
2812   i::Handle<i::Object> obj = Utils::OpenHandle(that);
2813   Utils::ApiCheck(obj->IsJSDataView(),
2814                   "v8::DataView::Cast()",
2815                   "Could not convert to DataView");
2816 }
2817 
2818 
CheckCast(v8::Value * that)2819 void v8::Date::CheckCast(v8::Value* that) {
2820   i::Handle<i::Object> obj = Utils::OpenHandle(that);
2821   i::Isolate* isolate = NULL;
2822   if (obj->IsHeapObject()) isolate = i::HeapObject::cast(*obj)->GetIsolate();
2823   Utils::ApiCheck(isolate != NULL &&
2824                   obj->HasSpecificClassOf(isolate->heap()->Date_string()),
2825                   "v8::Date::Cast()",
2826                   "Could not convert to date");
2827 }
2828 
2829 
CheckCast(v8::Value * that)2830 void v8::StringObject::CheckCast(v8::Value* that) {
2831   i::Handle<i::Object> obj = Utils::OpenHandle(that);
2832   i::Isolate* isolate = NULL;
2833   if (obj->IsHeapObject()) isolate = i::HeapObject::cast(*obj)->GetIsolate();
2834   Utils::ApiCheck(isolate != NULL &&
2835                   obj->HasSpecificClassOf(isolate->heap()->String_string()),
2836                   "v8::StringObject::Cast()",
2837                   "Could not convert to StringObject");
2838 }
2839 
2840 
CheckCast(v8::Value * that)2841 void v8::SymbolObject::CheckCast(v8::Value* that) {
2842   i::Handle<i::Object> obj = Utils::OpenHandle(that);
2843   i::Isolate* isolate = NULL;
2844   if (obj->IsHeapObject()) isolate = i::HeapObject::cast(*obj)->GetIsolate();
2845   Utils::ApiCheck(isolate != NULL &&
2846                   obj->HasSpecificClassOf(isolate->heap()->Symbol_string()),
2847                   "v8::SymbolObject::Cast()",
2848                   "Could not convert to SymbolObject");
2849 }
2850 
2851 
CheckCast(v8::Value * that)2852 void v8::NumberObject::CheckCast(v8::Value* that) {
2853   i::Handle<i::Object> obj = Utils::OpenHandle(that);
2854   i::Isolate* isolate = NULL;
2855   if (obj->IsHeapObject()) isolate = i::HeapObject::cast(*obj)->GetIsolate();
2856   Utils::ApiCheck(isolate != NULL &&
2857                   obj->HasSpecificClassOf(isolate->heap()->Number_string()),
2858                   "v8::NumberObject::Cast()",
2859                   "Could not convert to NumberObject");
2860 }
2861 
2862 
CheckCast(v8::Value * that)2863 void v8::BooleanObject::CheckCast(v8::Value* that) {
2864   i::Handle<i::Object> obj = Utils::OpenHandle(that);
2865   i::Isolate* isolate = NULL;
2866   if (obj->IsHeapObject()) isolate = i::HeapObject::cast(*obj)->GetIsolate();
2867   Utils::ApiCheck(isolate != NULL &&
2868                   obj->HasSpecificClassOf(isolate->heap()->Boolean_string()),
2869                   "v8::BooleanObject::Cast()",
2870                   "Could not convert to BooleanObject");
2871 }
2872 
2873 
CheckCast(v8::Value * that)2874 void v8::RegExp::CheckCast(v8::Value* that) {
2875   i::Handle<i::Object> obj = Utils::OpenHandle(that);
2876   Utils::ApiCheck(obj->IsJSRegExp(),
2877                   "v8::RegExp::Cast()",
2878                   "Could not convert to regular expression");
2879 }
2880 
2881 
BooleanValue() const2882 bool Value::BooleanValue() const {
2883   return Utils::OpenHandle(this)->BooleanValue();
2884 }
2885 
2886 
NumberValue() const2887 double Value::NumberValue() const {
2888   i::Handle<i::Object> obj = Utils::OpenHandle(this);
2889   i::Handle<i::Object> num;
2890   if (obj->IsNumber()) {
2891     num = obj;
2892   } else {
2893     i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
2894     LOG_API(isolate, "NumberValue");
2895     ENTER_V8(isolate);
2896     EXCEPTION_PREAMBLE(isolate);
2897     has_pending_exception = !i::Execution::ToNumber(
2898         isolate, obj).ToHandle(&num);
2899     EXCEPTION_BAILOUT_CHECK(isolate, base::OS::nan_value());
2900   }
2901   return num->Number();
2902 }
2903 
2904 
IntegerValue() const2905 int64_t Value::IntegerValue() const {
2906   i::Handle<i::Object> obj = Utils::OpenHandle(this);
2907   i::Handle<i::Object> num;
2908   if (obj->IsNumber()) {
2909     num = obj;
2910   } else {
2911     i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
2912     LOG_API(isolate, "IntegerValue");
2913     ENTER_V8(isolate);
2914     EXCEPTION_PREAMBLE(isolate);
2915     has_pending_exception = !i::Execution::ToInteger(
2916         isolate, obj).ToHandle(&num);
2917     EXCEPTION_BAILOUT_CHECK(isolate, 0);
2918   }
2919   if (num->IsSmi()) {
2920     return i::Smi::cast(*num)->value();
2921   } else {
2922     return static_cast<int64_t>(num->Number());
2923   }
2924 }
2925 
2926 
ToInt32() const2927 Local<Int32> Value::ToInt32() const {
2928   i::Handle<i::Object> obj = Utils::OpenHandle(this);
2929   i::Handle<i::Object> num;
2930   if (obj->IsSmi()) {
2931     num = obj;
2932   } else {
2933     i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
2934     LOG_API(isolate, "ToInt32");
2935     ENTER_V8(isolate);
2936     EXCEPTION_PREAMBLE(isolate);
2937     has_pending_exception = !i::Execution::ToInt32(isolate, obj).ToHandle(&num);
2938     EXCEPTION_BAILOUT_CHECK(isolate, Local<Int32>());
2939   }
2940   return ToApiHandle<Int32>(num);
2941 }
2942 
2943 
ToUint32() const2944 Local<Uint32> Value::ToUint32() const {
2945   i::Handle<i::Object> obj = Utils::OpenHandle(this);
2946   i::Handle<i::Object> num;
2947   if (obj->IsSmi()) {
2948     num = obj;
2949   } else {
2950     i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
2951     LOG_API(isolate, "ToUInt32");
2952     ENTER_V8(isolate);
2953     EXCEPTION_PREAMBLE(isolate);
2954     has_pending_exception = !i::Execution::ToUint32(
2955         isolate, obj).ToHandle(&num);
2956     EXCEPTION_BAILOUT_CHECK(isolate, Local<Uint32>());
2957   }
2958   return ToApiHandle<Uint32>(num);
2959 }
2960 
2961 
ToArrayIndex() const2962 Local<Uint32> Value::ToArrayIndex() const {
2963   i::Handle<i::Object> obj = Utils::OpenHandle(this);
2964   if (obj->IsSmi()) {
2965     if (i::Smi::cast(*obj)->value() >= 0) return Utils::Uint32ToLocal(obj);
2966     return Local<Uint32>();
2967   }
2968   i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
2969   LOG_API(isolate, "ToArrayIndex");
2970   ENTER_V8(isolate);
2971   EXCEPTION_PREAMBLE(isolate);
2972   i::Handle<i::Object> string_obj;
2973   has_pending_exception = !i::Execution::ToString(
2974       isolate, obj).ToHandle(&string_obj);
2975   EXCEPTION_BAILOUT_CHECK(isolate, Local<Uint32>());
2976   i::Handle<i::String> str = i::Handle<i::String>::cast(string_obj);
2977   uint32_t index;
2978   if (str->AsArrayIndex(&index)) {
2979     i::Handle<i::Object> value;
2980     if (index <= static_cast<uint32_t>(i::Smi::kMaxValue)) {
2981       value = i::Handle<i::Object>(i::Smi::FromInt(index), isolate);
2982     } else {
2983       value = isolate->factory()->NewNumber(index);
2984     }
2985     return Utils::Uint32ToLocal(value);
2986   }
2987   return Local<Uint32>();
2988 }
2989 
2990 
Int32Value() const2991 int32_t Value::Int32Value() const {
2992   i::Handle<i::Object> obj = Utils::OpenHandle(this);
2993   if (obj->IsSmi()) {
2994     return i::Smi::cast(*obj)->value();
2995   } else {
2996     i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
2997     LOG_API(isolate, "Int32Value (slow)");
2998     ENTER_V8(isolate);
2999     EXCEPTION_PREAMBLE(isolate);
3000     i::Handle<i::Object> num;
3001     has_pending_exception = !i::Execution::ToInt32(isolate, obj).ToHandle(&num);
3002     EXCEPTION_BAILOUT_CHECK(isolate, 0);
3003     if (num->IsSmi()) {
3004       return i::Smi::cast(*num)->value();
3005     } else {
3006       return static_cast<int32_t>(num->Number());
3007     }
3008   }
3009 }
3010 
3011 
Equals(Handle<Value> that) const3012 bool Value::Equals(Handle<Value> that) const {
3013   i::Isolate* isolate = i::Isolate::Current();
3014   i::Handle<i::Object> obj = Utils::OpenHandle(this, true);
3015   if (!Utils::ApiCheck(!obj.is_null() && !that.IsEmpty(),
3016                        "v8::Value::Equals()",
3017                        "Reading from empty handle")) {
3018     return false;
3019   }
3020   LOG_API(isolate, "Equals");
3021   ENTER_V8(isolate);
3022   i::Handle<i::Object> other = Utils::OpenHandle(*that);
3023   // If both obj and other are JSObjects, we'd better compare by identity
3024   // immediately when going into JS builtin.  The reason is Invoke
3025   // would overwrite global object receiver with global proxy.
3026   if (obj->IsJSObject() && other->IsJSObject()) {
3027     return *obj == *other;
3028   }
3029   i::Handle<i::Object> args[] = { other };
3030   EXCEPTION_PREAMBLE(isolate);
3031   i::Handle<i::Object> result;
3032   has_pending_exception = !CallV8HeapFunction(
3033       "EQUALS", obj, arraysize(args), args).ToHandle(&result);
3034   EXCEPTION_BAILOUT_CHECK(isolate, false);
3035   return *result == i::Smi::FromInt(i::EQUAL);
3036 }
3037 
3038 
StrictEquals(Handle<Value> that) const3039 bool Value::StrictEquals(Handle<Value> that) const {
3040   i::Isolate* isolate = i::Isolate::Current();
3041   i::Handle<i::Object> obj = Utils::OpenHandle(this, true);
3042   if (!Utils::ApiCheck(!obj.is_null() && !that.IsEmpty(),
3043                        "v8::Value::StrictEquals()",
3044                        "Reading from empty handle")) {
3045     return false;
3046   }
3047   LOG_API(isolate, "StrictEquals");
3048   i::Handle<i::Object> other = Utils::OpenHandle(*that);
3049   // Must check HeapNumber first, since NaN !== NaN.
3050   if (obj->IsHeapNumber()) {
3051     if (!other->IsNumber()) return false;
3052     double x = obj->Number();
3053     double y = other->Number();
3054     // Must check explicitly for NaN:s on Windows, but -0 works fine.
3055     return x == y && !std::isnan(x) && !std::isnan(y);
3056   } else if (*obj == *other) {  // Also covers Booleans.
3057     return true;
3058   } else if (obj->IsSmi()) {
3059     return other->IsNumber() && obj->Number() == other->Number();
3060   } else if (obj->IsString()) {
3061     return other->IsString() &&
3062         i::String::Equals(i::Handle<i::String>::cast(obj),
3063                           i::Handle<i::String>::cast(other));
3064   } else if (obj->IsUndefined() || obj->IsUndetectableObject()) {
3065     return other->IsUndefined() || other->IsUndetectableObject();
3066   } else {
3067     return false;
3068   }
3069 }
3070 
3071 
SameValue(Handle<Value> that) const3072 bool Value::SameValue(Handle<Value> that) const {
3073   i::Handle<i::Object> obj = Utils::OpenHandle(this, true);
3074   if (!Utils::ApiCheck(!obj.is_null() && !that.IsEmpty(),
3075                        "v8::Value::SameValue()",
3076                        "Reading from empty handle")) {
3077     return false;
3078   }
3079   i::Handle<i::Object> other = Utils::OpenHandle(*that);
3080   return obj->SameValue(*other);
3081 }
3082 
3083 
Uint32Value() const3084 uint32_t Value::Uint32Value() const {
3085   i::Handle<i::Object> obj = Utils::OpenHandle(this);
3086   if (obj->IsSmi()) {
3087     return i::Smi::cast(*obj)->value();
3088   } else {
3089     i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
3090     LOG_API(isolate, "Uint32Value");
3091     ENTER_V8(isolate);
3092     EXCEPTION_PREAMBLE(isolate);
3093     i::Handle<i::Object> num;
3094     has_pending_exception = !i::Execution::ToUint32(
3095         isolate, obj).ToHandle(&num);
3096     EXCEPTION_BAILOUT_CHECK(isolate, 0);
3097     if (num->IsSmi()) {
3098       return i::Smi::cast(*num)->value();
3099     } else {
3100       return static_cast<uint32_t>(num->Number());
3101     }
3102   }
3103 }
3104 
3105 
Set(v8::Handle<Value> key,v8::Handle<Value> value)3106 bool v8::Object::Set(v8::Handle<Value> key, v8::Handle<Value> value) {
3107   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3108   ON_BAILOUT(isolate, "v8::Object::Set()", return false);
3109   ENTER_V8(isolate);
3110   i::HandleScope scope(isolate);
3111   i::Handle<i::Object> self = Utils::OpenHandle(this);
3112   i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
3113   i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
3114   EXCEPTION_PREAMBLE(isolate);
3115   has_pending_exception =
3116       i::Runtime::SetObjectProperty(isolate, self, key_obj, value_obj,
3117                                     i::SLOPPY).is_null();
3118   EXCEPTION_BAILOUT_CHECK(isolate, false);
3119   return true;
3120 }
3121 
3122 
Set(uint32_t index,v8::Handle<Value> value)3123 bool v8::Object::Set(uint32_t index, v8::Handle<Value> value) {
3124   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3125   ON_BAILOUT(isolate, "v8::Object::Set()", return false);
3126   ENTER_V8(isolate);
3127   i::HandleScope scope(isolate);
3128   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3129   i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
3130   EXCEPTION_PREAMBLE(isolate);
3131   has_pending_exception = i::JSObject::SetElement(
3132       self, index, value_obj, NONE, i::SLOPPY).is_null();
3133   EXCEPTION_BAILOUT_CHECK(isolate, false);
3134   return true;
3135 }
3136 
3137 
ForceSet(v8::Handle<Value> key,v8::Handle<Value> value,v8::PropertyAttribute attribs)3138 bool v8::Object::ForceSet(v8::Handle<Value> key,
3139                           v8::Handle<Value> value,
3140                           v8::PropertyAttribute attribs) {
3141   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3142   ON_BAILOUT(isolate, "v8::Object::ForceSet()", return false);
3143   ENTER_V8(isolate);
3144   i::HandleScope scope(isolate);
3145   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3146   i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
3147   i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
3148   EXCEPTION_PREAMBLE(isolate);
3149   has_pending_exception = i::Runtime::DefineObjectProperty(
3150       self,
3151       key_obj,
3152       value_obj,
3153       static_cast<PropertyAttributes>(attribs)).is_null();
3154   EXCEPTION_BAILOUT_CHECK(isolate, false);
3155   return true;
3156 }
3157 
3158 
SetPrivate(v8::Handle<Private> key,v8::Handle<Value> value)3159 bool v8::Object::SetPrivate(v8::Handle<Private> key, v8::Handle<Value> value) {
3160   return ForceSet(v8::Handle<Value>(reinterpret_cast<Value*>(*key)),
3161                   value, DontEnum);
3162 }
3163 
3164 
ForceDelete(v8::Handle<Value> key)3165 bool v8::Object::ForceDelete(v8::Handle<Value> key) {
3166   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3167   ON_BAILOUT(isolate, "v8::Object::ForceDelete()", return false);
3168   ENTER_V8(isolate);
3169   i::HandleScope scope(isolate);
3170   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3171   i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
3172 
3173   // When deleting a property on the global object using ForceDelete
3174   // deoptimize all functions as optimized code does not check for the hole
3175   // value with DontDelete properties.  We have to deoptimize all contexts
3176   // because of possible cross-context inlined functions.
3177   if (self->IsJSGlobalProxy() || self->IsGlobalObject()) {
3178     i::Deoptimizer::DeoptimizeAll(isolate);
3179   }
3180 
3181   EXCEPTION_PREAMBLE(isolate);
3182   i::Handle<i::Object> obj;
3183   has_pending_exception = !i::Runtime::DeleteObjectProperty(
3184       isolate, self, key_obj, i::JSReceiver::FORCE_DELETION).ToHandle(&obj);
3185   EXCEPTION_BAILOUT_CHECK(isolate, false);
3186   return obj->IsTrue();
3187 }
3188 
3189 
Get(v8::Handle<Value> key)3190 Local<Value> v8::Object::Get(v8::Handle<Value> key) {
3191   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3192   ON_BAILOUT(isolate, "v8::Object::Get()", return Local<v8::Value>());
3193   ENTER_V8(isolate);
3194   i::Handle<i::Object> self = Utils::OpenHandle(this);
3195   i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
3196   EXCEPTION_PREAMBLE(isolate);
3197   i::Handle<i::Object> result;
3198   has_pending_exception =
3199       !i::Runtime::GetObjectProperty(isolate, self, key_obj).ToHandle(&result);
3200   EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
3201   return Utils::ToLocal(result);
3202 }
3203 
3204 
Get(uint32_t index)3205 Local<Value> v8::Object::Get(uint32_t index) {
3206   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3207   ON_BAILOUT(isolate, "v8::Object::Get()", return Local<v8::Value>());
3208   ENTER_V8(isolate);
3209   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3210   EXCEPTION_PREAMBLE(isolate);
3211   i::Handle<i::Object> result;
3212   has_pending_exception =
3213       !i::Object::GetElement(isolate, self, index).ToHandle(&result);
3214   EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
3215   return Utils::ToLocal(result);
3216 }
3217 
3218 
GetPrivate(v8::Handle<Private> key)3219 Local<Value> v8::Object::GetPrivate(v8::Handle<Private> key) {
3220   return Get(v8::Handle<Value>(reinterpret_cast<Value*>(*key)));
3221 }
3222 
3223 
GetPropertyAttributes(v8::Handle<Value> key)3224 PropertyAttribute v8::Object::GetPropertyAttributes(v8::Handle<Value> key) {
3225   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3226   ON_BAILOUT(isolate, "v8::Object::GetPropertyAttributes()",
3227              return static_cast<PropertyAttribute>(NONE));
3228   ENTER_V8(isolate);
3229   i::HandleScope scope(isolate);
3230   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3231   i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
3232   if (!key_obj->IsName()) {
3233     EXCEPTION_PREAMBLE(isolate);
3234     has_pending_exception = !i::Execution::ToString(
3235         isolate, key_obj).ToHandle(&key_obj);
3236     EXCEPTION_BAILOUT_CHECK(isolate, static_cast<PropertyAttribute>(NONE));
3237   }
3238   i::Handle<i::Name> key_name = i::Handle<i::Name>::cast(key_obj);
3239   EXCEPTION_PREAMBLE(isolate);
3240   Maybe<PropertyAttributes> result =
3241       i::JSReceiver::GetPropertyAttributes(self, key_name);
3242   has_pending_exception = !result.has_value;
3243   EXCEPTION_BAILOUT_CHECK(isolate, static_cast<PropertyAttribute>(NONE));
3244   if (result.value == ABSENT) return static_cast<PropertyAttribute>(NONE);
3245   return static_cast<PropertyAttribute>(result.value);
3246 }
3247 
3248 
GetOwnPropertyDescriptor(Local<String> key)3249 Local<Value> v8::Object::GetOwnPropertyDescriptor(Local<String> key) {
3250   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3251   ON_BAILOUT(isolate, "v8::Object::GetOwnPropertyDescriptor()",
3252              return Local<Value>());
3253   ENTER_V8(isolate);
3254   i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3255   i::Handle<i::Name> key_name = Utils::OpenHandle(*key);
3256   i::Handle<i::Object> args[] = { obj, key_name };
3257   EXCEPTION_PREAMBLE(isolate);
3258   i::Handle<i::Object> result;
3259   has_pending_exception = !CallV8HeapFunction(
3260       "ObjectGetOwnPropertyDescriptor",
3261       isolate->factory()->undefined_value(),
3262       arraysize(args),
3263       args).ToHandle(&result);
3264   EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
3265   return Utils::ToLocal(result);
3266 }
3267 
3268 
GetPrototype()3269 Local<Value> v8::Object::GetPrototype() {
3270   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3271   ON_BAILOUT(isolate, "v8::Object::GetPrototype()", return Local<v8::Value>());
3272   ENTER_V8(isolate);
3273   i::Handle<i::Object> self = Utils::OpenHandle(this);
3274   i::PrototypeIterator iter(isolate, self);
3275   return Utils::ToLocal(i::PrototypeIterator::GetCurrent(iter));
3276 }
3277 
3278 
SetPrototype(Handle<Value> value)3279 bool v8::Object::SetPrototype(Handle<Value> value) {
3280   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3281   ON_BAILOUT(isolate, "v8::Object::SetPrototype()", return false);
3282   ENTER_V8(isolate);
3283   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3284   i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
3285   // We do not allow exceptions thrown while setting the prototype
3286   // to propagate outside.
3287   TryCatch try_catch;
3288   EXCEPTION_PREAMBLE(isolate);
3289   i::MaybeHandle<i::Object> result =
3290       i::JSObject::SetPrototype(self, value_obj, false);
3291   has_pending_exception = result.is_null();
3292   EXCEPTION_BAILOUT_CHECK(isolate, false);
3293   return true;
3294 }
3295 
3296 
FindInstanceInPrototypeChain(v8::Handle<FunctionTemplate> tmpl)3297 Local<Object> v8::Object::FindInstanceInPrototypeChain(
3298     v8::Handle<FunctionTemplate> tmpl) {
3299   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3300   ON_BAILOUT(isolate,
3301              "v8::Object::FindInstanceInPrototypeChain()",
3302              return Local<v8::Object>());
3303   ENTER_V8(isolate);
3304   i::PrototypeIterator iter(isolate, *Utils::OpenHandle(this),
3305                             i::PrototypeIterator::START_AT_RECEIVER);
3306   i::FunctionTemplateInfo* tmpl_info = *Utils::OpenHandle(*tmpl);
3307   while (!tmpl_info->IsTemplateFor(iter.GetCurrent())) {
3308     iter.Advance();
3309     if (iter.IsAtEnd()) {
3310       return Local<Object>();
3311     }
3312   }
3313   return Utils::ToLocal(
3314       i::handle(i::JSObject::cast(iter.GetCurrent()), isolate));
3315 }
3316 
3317 
GetPropertyNames()3318 Local<Array> v8::Object::GetPropertyNames() {
3319   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3320   ON_BAILOUT(isolate, "v8::Object::GetPropertyNames()",
3321              return Local<v8::Array>());
3322   ENTER_V8(isolate);
3323   i::HandleScope scope(isolate);
3324   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3325   EXCEPTION_PREAMBLE(isolate);
3326   i::Handle<i::FixedArray> value;
3327   has_pending_exception = !i::JSReceiver::GetKeys(
3328       self, i::JSReceiver::INCLUDE_PROTOS).ToHandle(&value);
3329   EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Array>());
3330   // Because we use caching to speed up enumeration it is important
3331   // to never change the result of the basic enumeration function so
3332   // we clone the result.
3333   i::Handle<i::FixedArray> elms = isolate->factory()->CopyFixedArray(value);
3334   i::Handle<i::JSArray> result =
3335       isolate->factory()->NewJSArrayWithElements(elms);
3336   return Utils::ToLocal(scope.CloseAndEscape(result));
3337 }
3338 
3339 
GetOwnPropertyNames()3340 Local<Array> v8::Object::GetOwnPropertyNames() {
3341   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3342   ON_BAILOUT(isolate, "v8::Object::GetOwnPropertyNames()",
3343              return Local<v8::Array>());
3344   ENTER_V8(isolate);
3345   i::HandleScope scope(isolate);
3346   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3347   EXCEPTION_PREAMBLE(isolate);
3348   i::Handle<i::FixedArray> value;
3349   has_pending_exception = !i::JSReceiver::GetKeys(
3350       self, i::JSReceiver::OWN_ONLY).ToHandle(&value);
3351   EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Array>());
3352   // Because we use caching to speed up enumeration it is important
3353   // to never change the result of the basic enumeration function so
3354   // we clone the result.
3355   i::Handle<i::FixedArray> elms = isolate->factory()->CopyFixedArray(value);
3356   i::Handle<i::JSArray> result =
3357       isolate->factory()->NewJSArrayWithElements(elms);
3358   return Utils::ToLocal(scope.CloseAndEscape(result));
3359 }
3360 
3361 
ObjectProtoToString()3362 Local<String> v8::Object::ObjectProtoToString() {
3363   i::Isolate* i_isolate = Utils::OpenHandle(this)->GetIsolate();
3364   Isolate* isolate = reinterpret_cast<Isolate*>(i_isolate);
3365   ON_BAILOUT(i_isolate, "v8::Object::ObjectProtoToString()",
3366              return Local<v8::String>());
3367   ENTER_V8(i_isolate);
3368   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3369 
3370   i::Handle<i::Object> name(self->class_name(), i_isolate);
3371 
3372   // Native implementation of Object.prototype.toString (v8natives.js):
3373   //   var c = %_ClassOf(this);
3374   //   if (c === 'Arguments') c  = 'Object';
3375   //   return "[object " + c + "]";
3376 
3377   if (!name->IsString()) {
3378     return v8::String::NewFromUtf8(isolate, "[object ]");
3379   } else {
3380     i::Handle<i::String> class_name = i::Handle<i::String>::cast(name);
3381     if (i::String::Equals(class_name,
3382                           i_isolate->factory()->Arguments_string())) {
3383       return v8::String::NewFromUtf8(isolate, "[object Object]");
3384     } else {
3385       const char* prefix = "[object ";
3386       Local<String> str = Utils::ToLocal(class_name);
3387       const char* postfix = "]";
3388 
3389       int prefix_len = i::StrLength(prefix);
3390       int str_len = str->Utf8Length();
3391       int postfix_len = i::StrLength(postfix);
3392 
3393       int buf_len = prefix_len + str_len + postfix_len;
3394       i::ScopedVector<char> buf(buf_len);
3395 
3396       // Write prefix.
3397       char* ptr = buf.start();
3398       i::MemCopy(ptr, prefix, prefix_len * v8::internal::kCharSize);
3399       ptr += prefix_len;
3400 
3401       // Write real content.
3402       str->WriteUtf8(ptr, str_len);
3403       ptr += str_len;
3404 
3405       // Write postfix.
3406       i::MemCopy(ptr, postfix, postfix_len * v8::internal::kCharSize);
3407 
3408       // Copy the buffer into a heap-allocated string and return it.
3409       Local<String> result = v8::String::NewFromUtf8(
3410           isolate, buf.start(), String::kNormalString, buf_len);
3411       return result;
3412     }
3413   }
3414 }
3415 
3416 
GetConstructorName()3417 Local<String> v8::Object::GetConstructorName() {
3418   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3419   ON_BAILOUT(isolate, "v8::Object::GetConstructorName()",
3420              return Local<v8::String>());
3421   ENTER_V8(isolate);
3422   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3423   i::Handle<i::String> name(self->constructor_name());
3424   return Utils::ToLocal(name);
3425 }
3426 
3427 
Delete(v8::Handle<Value> key)3428 bool v8::Object::Delete(v8::Handle<Value> key) {
3429   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3430   ON_BAILOUT(isolate, "v8::Object::Delete()", return false);
3431   ENTER_V8(isolate);
3432   i::HandleScope scope(isolate);
3433   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3434   i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
3435   EXCEPTION_PREAMBLE(isolate);
3436   i::Handle<i::Object> obj;
3437   has_pending_exception = !i::Runtime::DeleteObjectProperty(
3438       isolate, self, key_obj, i::JSReceiver::NORMAL_DELETION).ToHandle(&obj);
3439   EXCEPTION_BAILOUT_CHECK(isolate, false);
3440   return obj->IsTrue();
3441 }
3442 
3443 
DeletePrivate(v8::Handle<Private> key)3444 bool v8::Object::DeletePrivate(v8::Handle<Private> key) {
3445   return Delete(v8::Handle<Value>(reinterpret_cast<Value*>(*key)));
3446 }
3447 
3448 
Has(v8::Handle<Value> key)3449 bool v8::Object::Has(v8::Handle<Value> key) {
3450   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3451   ON_BAILOUT(isolate, "v8::Object::Has()", return false);
3452   ENTER_V8(isolate);
3453   i::Handle<i::JSReceiver> self = Utils::OpenHandle(this);
3454   i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
3455   EXCEPTION_PREAMBLE(isolate);
3456   i::Handle<i::Object> obj;
3457   has_pending_exception = !i::Runtime::HasObjectProperty(
3458       isolate, self, key_obj).ToHandle(&obj);
3459   EXCEPTION_BAILOUT_CHECK(isolate, false);
3460   return obj->IsTrue();
3461 }
3462 
3463 
HasPrivate(v8::Handle<Private> key)3464 bool v8::Object::HasPrivate(v8::Handle<Private> key) {
3465   // TODO(rossberg): this should use HasOwnProperty, but we'd need to
3466   // generalise that to a (noy yet existant) Name argument first.
3467   return Has(v8::Handle<Value>(reinterpret_cast<Value*>(*key)));
3468 }
3469 
3470 
Delete(uint32_t index)3471 bool v8::Object::Delete(uint32_t index) {
3472   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3473   ON_BAILOUT(isolate, "v8::Object::DeleteProperty()",
3474              return false);
3475   ENTER_V8(isolate);
3476   HandleScope scope(reinterpret_cast<Isolate*>(isolate));
3477   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3478 
3479   EXCEPTION_PREAMBLE(isolate);
3480   i::Handle<i::Object> obj;
3481   has_pending_exception =
3482       !i::JSReceiver::DeleteElement(self, index).ToHandle(&obj);
3483   EXCEPTION_BAILOUT_CHECK(isolate, false);
3484   return obj->IsTrue();
3485 }
3486 
3487 
Has(uint32_t index)3488 bool v8::Object::Has(uint32_t index) {
3489   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3490   ON_BAILOUT(isolate, "v8::Object::HasProperty()", return false);
3491   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3492   EXCEPTION_PREAMBLE(isolate);
3493   Maybe<bool> maybe = i::JSReceiver::HasElement(self, index);
3494   has_pending_exception = !maybe.has_value;
3495   EXCEPTION_BAILOUT_CHECK(isolate, false);
3496   return maybe.value;
3497 }
3498 
3499 
3500 template<typename Getter, typename Setter, typename Data>
ObjectSetAccessor(Object * obj,Handle<Name> name,Getter getter,Setter setter,Data data,AccessControl settings,PropertyAttribute attributes)3501 static inline bool ObjectSetAccessor(Object* obj,
3502                                      Handle<Name> name,
3503                                      Getter getter,
3504                                      Setter setter,
3505                                      Data data,
3506                                      AccessControl settings,
3507                                      PropertyAttribute attributes) {
3508   i::Isolate* isolate = Utils::OpenHandle(obj)->GetIsolate();
3509   ON_BAILOUT(isolate, "v8::Object::SetAccessor()", return false);
3510   ENTER_V8(isolate);
3511   i::HandleScope scope(isolate);
3512   v8::Handle<AccessorSignature> signature;
3513   i::Handle<i::AccessorInfo> info = MakeAccessorInfo(
3514       name, getter, setter, data, settings, attributes, signature);
3515   if (info.is_null()) return false;
3516   bool fast = Utils::OpenHandle(obj)->HasFastProperties();
3517   i::Handle<i::Object> result;
3518   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3519       isolate, result,
3520       i::JSObject::SetAccessor(Utils::OpenHandle(obj), info),
3521       false);
3522   if (result->IsUndefined()) return false;
3523   if (fast) i::JSObject::MigrateSlowToFast(Utils::OpenHandle(obj), 0);
3524   return true;
3525 }
3526 
3527 
SetAccessor(Handle<String> name,AccessorGetterCallback getter,AccessorSetterCallback setter,v8::Handle<Value> data,AccessControl settings,PropertyAttribute attributes)3528 bool Object::SetAccessor(Handle<String> name,
3529                          AccessorGetterCallback getter,
3530                          AccessorSetterCallback setter,
3531                          v8::Handle<Value> data,
3532                          AccessControl settings,
3533                          PropertyAttribute attributes) {
3534   return ObjectSetAccessor(
3535       this, name, getter, setter, data, settings, attributes);
3536 }
3537 
3538 
SetAccessor(Handle<Name> name,AccessorNameGetterCallback getter,AccessorNameSetterCallback setter,v8::Handle<Value> data,AccessControl settings,PropertyAttribute attributes)3539 bool Object::SetAccessor(Handle<Name> name,
3540                          AccessorNameGetterCallback getter,
3541                          AccessorNameSetterCallback setter,
3542                          v8::Handle<Value> data,
3543                          AccessControl settings,
3544                          PropertyAttribute attributes) {
3545   return ObjectSetAccessor(
3546       this, name, getter, setter, data, settings, attributes);
3547 }
3548 
3549 
SetDeclaredAccessor(Local<Name> name,Local<DeclaredAccessorDescriptor> descriptor,PropertyAttribute attributes,AccessControl settings)3550 bool Object::SetDeclaredAccessor(Local<Name> name,
3551                                  Local<DeclaredAccessorDescriptor> descriptor,
3552                                  PropertyAttribute attributes,
3553                                  AccessControl settings) {
3554   void* null = NULL;
3555   return ObjectSetAccessor(
3556       this, name, descriptor, null, null, settings, attributes);
3557 }
3558 
3559 
SetAccessorProperty(Local<Name> name,Local<Function> getter,Handle<Function> setter,PropertyAttribute attribute,AccessControl settings)3560 void Object::SetAccessorProperty(Local<Name> name,
3561                                  Local<Function> getter,
3562                                  Handle<Function> setter,
3563                                  PropertyAttribute attribute,
3564                                  AccessControl settings) {
3565   // TODO(verwaest): Remove |settings|.
3566   DCHECK_EQ(v8::DEFAULT, settings);
3567   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3568   ON_BAILOUT(isolate, "v8::Object::SetAccessorProperty()", return);
3569   ENTER_V8(isolate);
3570   i::HandleScope scope(isolate);
3571   i::Handle<i::Object> getter_i = v8::Utils::OpenHandle(*getter);
3572   i::Handle<i::Object> setter_i = v8::Utils::OpenHandle(*setter, true);
3573   if (setter_i.is_null()) setter_i = isolate->factory()->null_value();
3574   i::JSObject::DefineAccessor(v8::Utils::OpenHandle(this),
3575                               v8::Utils::OpenHandle(*name),
3576                               getter_i,
3577                               setter_i,
3578                               static_cast<PropertyAttributes>(attribute));
3579 }
3580 
3581 
HasOwnProperty(Handle<String> key)3582 bool v8::Object::HasOwnProperty(Handle<String> key) {
3583   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3584   ON_BAILOUT(isolate, "v8::Object::HasOwnProperty()",
3585              return false);
3586   EXCEPTION_PREAMBLE(isolate);
3587   Maybe<bool> maybe = i::JSReceiver::HasOwnProperty(Utils::OpenHandle(this),
3588                                                     Utils::OpenHandle(*key));
3589   has_pending_exception = !maybe.has_value;
3590   EXCEPTION_BAILOUT_CHECK(isolate, false);
3591   return maybe.value;
3592 }
3593 
3594 
HasRealNamedProperty(Handle<String> key)3595 bool v8::Object::HasRealNamedProperty(Handle<String> key) {
3596   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3597   ON_BAILOUT(isolate, "v8::Object::HasRealNamedProperty()",
3598              return false);
3599   EXCEPTION_PREAMBLE(isolate);
3600   Maybe<bool> maybe = i::JSObject::HasRealNamedProperty(
3601       Utils::OpenHandle(this), Utils::OpenHandle(*key));
3602   has_pending_exception = !maybe.has_value;
3603   EXCEPTION_BAILOUT_CHECK(isolate, false);
3604   return maybe.value;
3605 }
3606 
3607 
HasRealIndexedProperty(uint32_t index)3608 bool v8::Object::HasRealIndexedProperty(uint32_t index) {
3609   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3610   ON_BAILOUT(isolate, "v8::Object::HasRealIndexedProperty()",
3611              return false);
3612   EXCEPTION_PREAMBLE(isolate);
3613   Maybe<bool> maybe =
3614       i::JSObject::HasRealElementProperty(Utils::OpenHandle(this), index);
3615   has_pending_exception = !maybe.has_value;
3616   EXCEPTION_BAILOUT_CHECK(isolate, false);
3617   return maybe.value;
3618 }
3619 
3620 
HasRealNamedCallbackProperty(Handle<String> key)3621 bool v8::Object::HasRealNamedCallbackProperty(Handle<String> key) {
3622   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3623   ON_BAILOUT(isolate,
3624              "v8::Object::HasRealNamedCallbackProperty()",
3625              return false);
3626   ENTER_V8(isolate);
3627   EXCEPTION_PREAMBLE(isolate);
3628   Maybe<bool> maybe = i::JSObject::HasRealNamedCallbackProperty(
3629       Utils::OpenHandle(this), Utils::OpenHandle(*key));
3630   has_pending_exception = !maybe.has_value;
3631   EXCEPTION_BAILOUT_CHECK(isolate, false);
3632   return maybe.value;
3633 }
3634 
3635 
HasNamedLookupInterceptor()3636 bool v8::Object::HasNamedLookupInterceptor() {
3637   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3638   ON_BAILOUT(isolate, "v8::Object::HasNamedLookupInterceptor()",
3639              return false);
3640   return Utils::OpenHandle(this)->HasNamedInterceptor();
3641 }
3642 
3643 
HasIndexedLookupInterceptor()3644 bool v8::Object::HasIndexedLookupInterceptor() {
3645   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3646   ON_BAILOUT(isolate, "v8::Object::HasIndexedLookupInterceptor()",
3647              return false);
3648   return Utils::OpenHandle(this)->HasIndexedInterceptor();
3649 }
3650 
3651 
GetPropertyByLookup(i::LookupIterator * it)3652 static Local<Value> GetPropertyByLookup(i::LookupIterator* it) {
3653   // If the property being looked up is a callback, it can throw an exception.
3654   EXCEPTION_PREAMBLE(it->isolate());
3655   i::Handle<i::Object> result;
3656   has_pending_exception = !i::Object::GetProperty(it).ToHandle(&result);
3657   EXCEPTION_BAILOUT_CHECK(it->isolate(), Local<Value>());
3658 
3659   if (it->IsFound()) return Utils::ToLocal(result);
3660   return Local<Value>();
3661 }
3662 
3663 
GetRealNamedPropertyInPrototypeChain(Handle<String> key)3664 Local<Value> v8::Object::GetRealNamedPropertyInPrototypeChain(
3665     Handle<String> key) {
3666   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3667   ON_BAILOUT(isolate,
3668              "v8::Object::GetRealNamedPropertyInPrototypeChain()",
3669              return Local<Value>());
3670   ENTER_V8(isolate);
3671   i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this);
3672   i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
3673   i::PrototypeIterator iter(isolate, self_obj);
3674   if (iter.IsAtEnd()) return Local<Value>();
3675   i::Handle<i::Object> proto = i::PrototypeIterator::GetCurrent(iter);
3676   i::LookupIterator it(self_obj, key_obj, i::Handle<i::JSReceiver>::cast(proto),
3677                        i::LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
3678   return GetPropertyByLookup(&it);
3679 }
3680 
3681 
GetRealNamedProperty(Handle<String> key)3682 Local<Value> v8::Object::GetRealNamedProperty(Handle<String> key) {
3683   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3684   ON_BAILOUT(isolate, "v8::Object::GetRealNamedProperty()",
3685              return Local<Value>());
3686   ENTER_V8(isolate);
3687   i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this);
3688   i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
3689   i::LookupIterator it(self_obj, key_obj,
3690                        i::LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
3691   return GetPropertyByLookup(&it);
3692 }
3693 
3694 
3695 // Turns on access checks by copying the map and setting the check flag.
3696 // Because the object gets a new map, existing inline cache caching
3697 // the old map of this object will fail.
TurnOnAccessCheck()3698 void v8::Object::TurnOnAccessCheck() {
3699   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3700   ON_BAILOUT(isolate, "v8::Object::TurnOnAccessCheck()", return);
3701   ENTER_V8(isolate);
3702   i::HandleScope scope(isolate);
3703   i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3704 
3705   // When turning on access checks for a global object deoptimize all functions
3706   // as optimized code does not always handle access checks.
3707   i::Deoptimizer::DeoptimizeGlobalObject(*obj);
3708 
3709   i::Handle<i::Map> new_map = i::Map::Copy(i::Handle<i::Map>(obj->map()));
3710   new_map->set_is_access_check_needed(true);
3711   i::JSObject::MigrateToMap(obj, new_map);
3712 }
3713 
3714 
IsDirty()3715 bool v8::Object::IsDirty() {
3716   return Utils::OpenHandle(this)->IsDirty();
3717 }
3718 
3719 
Clone()3720 Local<v8::Object> v8::Object::Clone() {
3721   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3722   ON_BAILOUT(isolate, "v8::Object::Clone()", return Local<Object>());
3723   ENTER_V8(isolate);
3724   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3725   EXCEPTION_PREAMBLE(isolate);
3726   i::Handle<i::JSObject> result = isolate->factory()->CopyJSObject(self);
3727   has_pending_exception = result.is_null();
3728   EXCEPTION_BAILOUT_CHECK(isolate, Local<Object>());
3729   return Utils::ToLocal(result);
3730 }
3731 
3732 
CreationContext()3733 Local<v8::Context> v8::Object::CreationContext() {
3734   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3735   ON_BAILOUT(isolate,
3736              "v8::Object::CreationContext()", return Local<v8::Context>());
3737   ENTER_V8(isolate);
3738   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3739   i::Context* context = self->GetCreationContext();
3740   return Utils::ToLocal(i::Handle<i::Context>(context));
3741 }
3742 
3743 
GetIdentityHash()3744 int v8::Object::GetIdentityHash() {
3745   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3746   ON_BAILOUT(isolate, "v8::Object::GetIdentityHash()", return 0);
3747   ENTER_V8(isolate);
3748   i::HandleScope scope(isolate);
3749   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3750   return i::JSReceiver::GetOrCreateIdentityHash(self)->value();
3751 }
3752 
3753 
SetHiddenValue(v8::Handle<v8::String> key,v8::Handle<v8::Value> value)3754 bool v8::Object::SetHiddenValue(v8::Handle<v8::String> key,
3755                                 v8::Handle<v8::Value> value) {
3756   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3757   ON_BAILOUT(isolate, "v8::Object::SetHiddenValue()", return false);
3758   if (value.IsEmpty()) return DeleteHiddenValue(key);
3759   ENTER_V8(isolate);
3760   i::HandleScope scope(isolate);
3761   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3762   i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
3763   i::Handle<i::String> key_string =
3764       isolate->factory()->InternalizeString(key_obj);
3765   i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
3766   i::Handle<i::Object> result =
3767       i::JSObject::SetHiddenProperty(self, key_string, value_obj);
3768   return *result == *self;
3769 }
3770 
3771 
GetHiddenValue(v8::Handle<v8::String> key)3772 v8::Local<v8::Value> v8::Object::GetHiddenValue(v8::Handle<v8::String> key) {
3773   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3774   ON_BAILOUT(isolate, "v8::Object::GetHiddenValue()",
3775              return Local<v8::Value>());
3776   ENTER_V8(isolate);
3777   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3778   i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
3779   i::Handle<i::String> key_string =
3780       isolate->factory()->InternalizeString(key_obj);
3781   i::Handle<i::Object> result(self->GetHiddenProperty(key_string), isolate);
3782   if (result->IsTheHole()) return v8::Local<v8::Value>();
3783   return Utils::ToLocal(result);
3784 }
3785 
3786 
DeleteHiddenValue(v8::Handle<v8::String> key)3787 bool v8::Object::DeleteHiddenValue(v8::Handle<v8::String> key) {
3788   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3789   ON_BAILOUT(isolate, "v8::DeleteHiddenValue()", return false);
3790   ENTER_V8(isolate);
3791   i::HandleScope scope(isolate);
3792   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3793   i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
3794   i::Handle<i::String> key_string =
3795       isolate->factory()->InternalizeString(key_obj);
3796   i::JSObject::DeleteHiddenProperty(self, key_string);
3797   return true;
3798 }
3799 
3800 
3801 namespace {
3802 
GetElementsKindFromExternalArrayType(ExternalArrayType array_type)3803 static i::ElementsKind GetElementsKindFromExternalArrayType(
3804     ExternalArrayType array_type) {
3805   switch (array_type) {
3806 #define ARRAY_TYPE_TO_ELEMENTS_KIND(Type, type, TYPE, ctype, size)            \
3807     case kExternal##Type##Array:                                              \
3808       return i::EXTERNAL_##TYPE##_ELEMENTS;
3809 
3810     TYPED_ARRAYS(ARRAY_TYPE_TO_ELEMENTS_KIND)
3811 #undef ARRAY_TYPE_TO_ELEMENTS_KIND
3812   }
3813   UNREACHABLE();
3814   return i::DICTIONARY_ELEMENTS;
3815 }
3816 
3817 
PrepareExternalArrayElements(i::Handle<i::JSObject> object,void * data,ExternalArrayType array_type,int length)3818 void PrepareExternalArrayElements(i::Handle<i::JSObject> object,
3819                                   void* data,
3820                                   ExternalArrayType array_type,
3821                                   int length) {
3822   i::Isolate* isolate = object->GetIsolate();
3823   i::Handle<i::ExternalArray> array =
3824       isolate->factory()->NewExternalArray(length, array_type, data);
3825 
3826   i::Handle<i::Map> external_array_map =
3827       i::JSObject::GetElementsTransitionMap(
3828           object,
3829           GetElementsKindFromExternalArrayType(array_type));
3830 
3831   i::JSObject::SetMapAndElements(object, external_array_map, array);
3832 }
3833 
3834 }  // namespace
3835 
3836 
SetIndexedPropertiesToPixelData(uint8_t * data,int length)3837 void v8::Object::SetIndexedPropertiesToPixelData(uint8_t* data, int length) {
3838   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3839   ON_BAILOUT(isolate, "v8::SetElementsToPixelData()", return);
3840   ENTER_V8(isolate);
3841   i::HandleScope scope(isolate);
3842   if (!Utils::ApiCheck(length >= 0 &&
3843                        length <= i::ExternalUint8ClampedArray::kMaxLength,
3844                        "v8::Object::SetIndexedPropertiesToPixelData()",
3845                        "length exceeds max acceptable value")) {
3846     return;
3847   }
3848   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3849   if (!Utils::ApiCheck(!self->IsJSArray(),
3850                        "v8::Object::SetIndexedPropertiesToPixelData()",
3851                        "JSArray is not supported")) {
3852     return;
3853   }
3854   PrepareExternalArrayElements(self, data, kExternalUint8ClampedArray, length);
3855 }
3856 
3857 
HasIndexedPropertiesInPixelData()3858 bool v8::Object::HasIndexedPropertiesInPixelData() {
3859   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3860   ON_BAILOUT(self->GetIsolate(), "v8::HasIndexedPropertiesInPixelData()",
3861              return false);
3862   return self->HasExternalUint8ClampedElements();
3863 }
3864 
3865 
GetIndexedPropertiesPixelData()3866 uint8_t* v8::Object::GetIndexedPropertiesPixelData() {
3867   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3868   ON_BAILOUT(self->GetIsolate(), "v8::GetIndexedPropertiesPixelData()",
3869              return NULL);
3870   if (self->HasExternalUint8ClampedElements()) {
3871     return i::ExternalUint8ClampedArray::cast(self->elements())->
3872         external_uint8_clamped_pointer();
3873   } else {
3874     return NULL;
3875   }
3876 }
3877 
3878 
GetIndexedPropertiesPixelDataLength()3879 int v8::Object::GetIndexedPropertiesPixelDataLength() {
3880   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3881   ON_BAILOUT(self->GetIsolate(), "v8::GetIndexedPropertiesPixelDataLength()",
3882              return -1);
3883   if (self->HasExternalUint8ClampedElements()) {
3884     return i::ExternalUint8ClampedArray::cast(self->elements())->length();
3885   } else {
3886     return -1;
3887   }
3888 }
3889 
3890 
SetIndexedPropertiesToExternalArrayData(void * data,ExternalArrayType array_type,int length)3891 void v8::Object::SetIndexedPropertiesToExternalArrayData(
3892     void* data,
3893     ExternalArrayType array_type,
3894     int length) {
3895   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3896   ON_BAILOUT(isolate, "v8::SetIndexedPropertiesToExternalArrayData()", return);
3897   ENTER_V8(isolate);
3898   i::HandleScope scope(isolate);
3899   if (!Utils::ApiCheck(length >= 0 && length <= i::ExternalArray::kMaxLength,
3900                        "v8::Object::SetIndexedPropertiesToExternalArrayData()",
3901                        "length exceeds max acceptable value")) {
3902     return;
3903   }
3904   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3905   if (!Utils::ApiCheck(!self->IsJSArray(),
3906                        "v8::Object::SetIndexedPropertiesToExternalArrayData()",
3907                        "JSArray is not supported")) {
3908     return;
3909   }
3910   PrepareExternalArrayElements(self, data, array_type, length);
3911 }
3912 
3913 
HasIndexedPropertiesInExternalArrayData()3914 bool v8::Object::HasIndexedPropertiesInExternalArrayData() {
3915   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3916   ON_BAILOUT(self->GetIsolate(),
3917              "v8::HasIndexedPropertiesInExternalArrayData()",
3918              return false);
3919   return self->HasExternalArrayElements();
3920 }
3921 
3922 
GetIndexedPropertiesExternalArrayData()3923 void* v8::Object::GetIndexedPropertiesExternalArrayData() {
3924   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3925   ON_BAILOUT(self->GetIsolate(),
3926              "v8::GetIndexedPropertiesExternalArrayData()",
3927              return NULL);
3928   if (self->HasExternalArrayElements()) {
3929     return i::ExternalArray::cast(self->elements())->external_pointer();
3930   } else {
3931     return NULL;
3932   }
3933 }
3934 
3935 
GetIndexedPropertiesExternalArrayDataType()3936 ExternalArrayType v8::Object::GetIndexedPropertiesExternalArrayDataType() {
3937   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3938   ON_BAILOUT(self->GetIsolate(),
3939              "v8::GetIndexedPropertiesExternalArrayDataType()",
3940              return static_cast<ExternalArrayType>(-1));
3941   switch (self->elements()->map()->instance_type()) {
3942 #define INSTANCE_TYPE_TO_ARRAY_TYPE(Type, type, TYPE, ctype, size)            \
3943     case i::EXTERNAL_##TYPE##_ARRAY_TYPE:                                     \
3944       return kExternal##Type##Array;
3945     TYPED_ARRAYS(INSTANCE_TYPE_TO_ARRAY_TYPE)
3946 #undef INSTANCE_TYPE_TO_ARRAY_TYPE
3947     default:
3948       return static_cast<ExternalArrayType>(-1);
3949   }
3950 }
3951 
3952 
GetIndexedPropertiesExternalArrayDataLength()3953 int v8::Object::GetIndexedPropertiesExternalArrayDataLength() {
3954   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3955   ON_BAILOUT(self->GetIsolate(),
3956              "v8::GetIndexedPropertiesExternalArrayDataLength()",
3957              return 0);
3958   if (self->HasExternalArrayElements()) {
3959     return i::ExternalArray::cast(self->elements())->length();
3960   } else {
3961     return -1;
3962   }
3963 }
3964 
3965 
IsCallable()3966 bool v8::Object::IsCallable() {
3967   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3968   ON_BAILOUT(isolate, "v8::Object::IsCallable()", return false);
3969   ENTER_V8(isolate);
3970   i::HandleScope scope(isolate);
3971   i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3972   return obj->IsCallable();
3973 }
3974 
3975 
CallAsFunction(v8::Handle<v8::Value> recv,int argc,v8::Handle<v8::Value> argv[])3976 Local<v8::Value> Object::CallAsFunction(v8::Handle<v8::Value> recv,
3977                                         int argc,
3978                                         v8::Handle<v8::Value> argv[]) {
3979   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3980   ON_BAILOUT(isolate, "v8::Object::CallAsFunction()",
3981              return Local<v8::Value>());
3982   LOG_API(isolate, "Object::CallAsFunction");
3983   ENTER_V8(isolate);
3984   i::TimerEventScope<i::TimerEventExecute> timer_scope(isolate);
3985   i::HandleScope scope(isolate);
3986   i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3987   i::Handle<i::Object> recv_obj = Utils::OpenHandle(*recv);
3988   STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
3989   i::Handle<i::Object>* args = reinterpret_cast<i::Handle<i::Object>*>(argv);
3990   i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>();
3991   if (obj->IsJSFunction()) {
3992     fun = i::Handle<i::JSFunction>::cast(obj);
3993   } else {
3994     EXCEPTION_PREAMBLE(isolate);
3995     i::Handle<i::Object> delegate;
3996     has_pending_exception = !i::Execution::TryGetFunctionDelegate(
3997         isolate, obj).ToHandle(&delegate);
3998     EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
3999     fun = i::Handle<i::JSFunction>::cast(delegate);
4000     recv_obj = obj;
4001   }
4002   EXCEPTION_PREAMBLE(isolate);
4003   i::Handle<i::Object> returned;
4004   has_pending_exception = !i::Execution::Call(
4005       isolate, fun, recv_obj, argc, args, true).ToHandle(&returned);
4006   EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<Value>());
4007   return Utils::ToLocal(scope.CloseAndEscape(returned));
4008 }
4009 
4010 
CallAsConstructor(int argc,v8::Handle<v8::Value> argv[])4011 Local<v8::Value> Object::CallAsConstructor(int argc,
4012                                            v8::Handle<v8::Value> argv[]) {
4013   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
4014   ON_BAILOUT(isolate, "v8::Object::CallAsConstructor()",
4015              return Local<v8::Object>());
4016   LOG_API(isolate, "Object::CallAsConstructor");
4017   ENTER_V8(isolate);
4018   i::TimerEventScope<i::TimerEventExecute> timer_scope(isolate);
4019   i::HandleScope scope(isolate);
4020   i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
4021   STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
4022   i::Handle<i::Object>* args = reinterpret_cast<i::Handle<i::Object>*>(argv);
4023   if (obj->IsJSFunction()) {
4024     i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(obj);
4025     EXCEPTION_PREAMBLE(isolate);
4026     i::Handle<i::Object> returned;
4027     has_pending_exception = !i::Execution::New(
4028         fun, argc, args).ToHandle(&returned);
4029     EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<v8::Object>());
4030     return Utils::ToLocal(scope.CloseAndEscape(
4031         i::Handle<i::JSObject>::cast(returned)));
4032   }
4033   EXCEPTION_PREAMBLE(isolate);
4034   i::Handle<i::Object> delegate;
4035   has_pending_exception = !i::Execution::TryGetConstructorDelegate(
4036       isolate, obj).ToHandle(&delegate);
4037   EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Object>());
4038   if (!delegate->IsUndefined()) {
4039     i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(delegate);
4040     EXCEPTION_PREAMBLE(isolate);
4041     i::Handle<i::Object> returned;
4042     has_pending_exception = !i::Execution::Call(
4043         isolate, fun, obj, argc, args).ToHandle(&returned);
4044     EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<v8::Object>());
4045     DCHECK(!delegate->IsUndefined());
4046     return Utils::ToLocal(scope.CloseAndEscape(returned));
4047   }
4048   return Local<v8::Object>();
4049 }
4050 
4051 
New(Isolate * v8_isolate,FunctionCallback callback,Local<Value> data,int length)4052 Local<Function> Function::New(Isolate* v8_isolate,
4053                               FunctionCallback callback,
4054                               Local<Value> data,
4055                               int length) {
4056   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
4057   LOG_API(isolate, "Function::New");
4058   ENTER_V8(isolate);
4059   return FunctionTemplateNew(
4060       isolate, callback, data, Local<Signature>(), length, true)->
4061       GetFunction();
4062 }
4063 
4064 
NewInstance() const4065 Local<v8::Object> Function::NewInstance() const {
4066   return NewInstance(0, NULL);
4067 }
4068 
4069 
NewInstance(int argc,v8::Handle<v8::Value> argv[]) const4070 Local<v8::Object> Function::NewInstance(int argc,
4071                                         v8::Handle<v8::Value> argv[]) const {
4072   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
4073   ON_BAILOUT(isolate, "v8::Function::NewInstance()",
4074              return Local<v8::Object>());
4075   LOG_API(isolate, "Function::NewInstance");
4076   ENTER_V8(isolate);
4077   i::TimerEventScope<i::TimerEventExecute> timer_scope(isolate);
4078   EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate));
4079   i::Handle<i::JSFunction> function = Utils::OpenHandle(this);
4080   STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
4081   i::Handle<i::Object>* args = reinterpret_cast<i::Handle<i::Object>*>(argv);
4082   EXCEPTION_PREAMBLE(isolate);
4083   i::Handle<i::Object> returned;
4084   has_pending_exception = !i::Execution::New(
4085       function, argc, args).ToHandle(&returned);
4086   EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<v8::Object>());
4087   return scope.Escape(Utils::ToLocal(i::Handle<i::JSObject>::cast(returned)));
4088 }
4089 
4090 
Call(v8::Handle<v8::Value> recv,int argc,v8::Handle<v8::Value> argv[])4091 Local<v8::Value> Function::Call(v8::Handle<v8::Value> recv, int argc,
4092                                 v8::Handle<v8::Value> argv[]) {
4093   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
4094   ON_BAILOUT(isolate, "v8::Function::Call()", return Local<v8::Value>());
4095   LOG_API(isolate, "Function::Call");
4096   ENTER_V8(isolate);
4097   i::TimerEventScope<i::TimerEventExecute> timer_scope(isolate);
4098   i::HandleScope scope(isolate);
4099   i::Handle<i::JSFunction> fun = Utils::OpenHandle(this);
4100   i::Handle<i::Object> recv_obj = Utils::OpenHandle(*recv);
4101   STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
4102   i::Handle<i::Object>* args = reinterpret_cast<i::Handle<i::Object>*>(argv);
4103   EXCEPTION_PREAMBLE(isolate);
4104   i::Handle<i::Object> returned;
4105   has_pending_exception = !i::Execution::Call(
4106       isolate, fun, recv_obj, argc, args, true).ToHandle(&returned);
4107   EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<Object>());
4108   return Utils::ToLocal(scope.CloseAndEscape(returned));
4109 }
4110 
4111 
SetName(v8::Handle<v8::String> name)4112 void Function::SetName(v8::Handle<v8::String> name) {
4113   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
4114   ENTER_V8(isolate);
4115   USE(isolate);
4116   i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
4117   func->shared()->set_name(*Utils::OpenHandle(*name));
4118 }
4119 
4120 
GetName() const4121 Handle<Value> Function::GetName() const {
4122   i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
4123   return Utils::ToLocal(i::Handle<i::Object>(func->shared()->name(),
4124                                              func->GetIsolate()));
4125 }
4126 
4127 
GetInferredName() const4128 Handle<Value> Function::GetInferredName() const {
4129   i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
4130   return Utils::ToLocal(i::Handle<i::Object>(func->shared()->inferred_name(),
4131                                              func->GetIsolate()));
4132 }
4133 
4134 
GetDisplayName() const4135 Handle<Value> Function::GetDisplayName() const {
4136   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
4137   ON_BAILOUT(isolate, "v8::Function::GetDisplayName()",
4138              return ToApiHandle<Primitive>(
4139                  isolate->factory()->undefined_value()));
4140   ENTER_V8(isolate);
4141   i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
4142   i::Handle<i::String> property_name =
4143       isolate->factory()->InternalizeOneByteString(
4144           STATIC_CHAR_VECTOR("displayName"));
4145 
4146   i::Handle<i::Object> value =
4147       i::JSObject::GetDataProperty(func, property_name);
4148   if (value->IsString()) {
4149     i::Handle<i::String> name = i::Handle<i::String>::cast(value);
4150     if (name->length() > 0) return Utils::ToLocal(name);
4151   }
4152 
4153   return ToApiHandle<Primitive>(isolate->factory()->undefined_value());
4154 }
4155 
4156 
GetScriptOrigin() const4157 ScriptOrigin Function::GetScriptOrigin() const {
4158   i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
4159   if (func->shared()->script()->IsScript()) {
4160     i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
4161     i::Handle<i::Object> scriptName = i::Script::GetNameOrSourceURL(script);
4162     v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(func->GetIsolate());
4163     v8::ScriptOrigin origin(
4164         Utils::ToLocal(scriptName),
4165         v8::Integer::New(isolate, script->line_offset()->value()),
4166         v8::Integer::New(isolate, script->column_offset()->value()));
4167     return origin;
4168   }
4169   return v8::ScriptOrigin(Handle<Value>());
4170 }
4171 
4172 
4173 const int Function::kLineOffsetNotFound = -1;
4174 
4175 
GetScriptLineNumber() const4176 int Function::GetScriptLineNumber() const {
4177   i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
4178   if (func->shared()->script()->IsScript()) {
4179     i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
4180     return i::Script::GetLineNumber(script, func->shared()->start_position());
4181   }
4182   return kLineOffsetNotFound;
4183 }
4184 
4185 
GetScriptColumnNumber() const4186 int Function::GetScriptColumnNumber() const {
4187   i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
4188   if (func->shared()->script()->IsScript()) {
4189     i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
4190     return i::Script::GetColumnNumber(script, func->shared()->start_position());
4191   }
4192   return kLineOffsetNotFound;
4193 }
4194 
4195 
IsBuiltin() const4196 bool Function::IsBuiltin() const {
4197   i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
4198   return func->IsBuiltin();
4199 }
4200 
4201 
ScriptId() const4202 int Function::ScriptId() const {
4203   i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
4204   if (!func->shared()->script()->IsScript()) {
4205     return v8::UnboundScript::kNoScriptId;
4206   }
4207   i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
4208   return script->id()->value();
4209 }
4210 
4211 
GetBoundFunction() const4212 Local<v8::Value> Function::GetBoundFunction() const {
4213   i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
4214   if (!func->shared()->bound()) {
4215     return v8::Undefined(reinterpret_cast<v8::Isolate*>(func->GetIsolate()));
4216   }
4217   i::Handle<i::FixedArray> bound_args = i::Handle<i::FixedArray>(
4218       i::FixedArray::cast(func->function_bindings()));
4219   i::Handle<i::Object> original(
4220       bound_args->get(i::JSFunction::kBoundFunctionIndex),
4221       func->GetIsolate());
4222   return Utils::ToLocal(i::Handle<i::JSFunction>::cast(original));
4223 }
4224 
4225 
Length() const4226 int String::Length() const {
4227   i::Handle<i::String> str = Utils::OpenHandle(this);
4228   return str->length();
4229 }
4230 
4231 
IsOneByte() const4232 bool String::IsOneByte() const {
4233   i::Handle<i::String> str = Utils::OpenHandle(this);
4234   return str->HasOnlyOneByteChars();
4235 }
4236 
4237 
4238 // Helpers for ContainsOnlyOneByteHelper
4239 template<size_t size> struct OneByteMask;
4240 template<> struct OneByteMask<4> {
4241   static const uint32_t value = 0xFF00FF00;
4242 };
4243 template<> struct OneByteMask<8> {
4244   static const uint64_t value = V8_2PART_UINT64_C(0xFF00FF00, FF00FF00);
4245 };
4246 static const uintptr_t kOneByteMask = OneByteMask<sizeof(uintptr_t)>::value;
4247 static const uintptr_t kAlignmentMask = sizeof(uintptr_t) - 1;
Unaligned(const uint16_t * chars)4248 static inline bool Unaligned(const uint16_t* chars) {
4249   return reinterpret_cast<const uintptr_t>(chars) & kAlignmentMask;
4250 }
4251 
4252 
Align(const uint16_t * chars)4253 static inline const uint16_t* Align(const uint16_t* chars) {
4254   return reinterpret_cast<uint16_t*>(
4255       reinterpret_cast<uintptr_t>(chars) & ~kAlignmentMask);
4256 }
4257 
4258 class ContainsOnlyOneByteHelper {
4259  public:
ContainsOnlyOneByteHelper()4260   ContainsOnlyOneByteHelper() : is_one_byte_(true) {}
Check(i::String * string)4261   bool Check(i::String* string) {
4262     i::ConsString* cons_string = i::String::VisitFlat(this, string, 0);
4263     if (cons_string == NULL) return is_one_byte_;
4264     return CheckCons(cons_string);
4265   }
VisitOneByteString(const uint8_t * chars,int length)4266   void VisitOneByteString(const uint8_t* chars, int length) {
4267     // Nothing to do.
4268   }
VisitTwoByteString(const uint16_t * chars,int length)4269   void VisitTwoByteString(const uint16_t* chars, int length) {
4270     // Accumulated bits.
4271     uintptr_t acc = 0;
4272     // Align to uintptr_t.
4273     const uint16_t* end = chars + length;
4274     while (Unaligned(chars) && chars != end) {
4275       acc |= *chars++;
4276     }
4277     // Read word aligned in blocks,
4278     // checking the return value at the end of each block.
4279     const uint16_t* aligned_end = Align(end);
4280     const int increment = sizeof(uintptr_t)/sizeof(uint16_t);
4281     const int inner_loops = 16;
4282     while (chars + inner_loops*increment < aligned_end) {
4283       for (int i = 0; i < inner_loops; i++) {
4284         acc |= *reinterpret_cast<const uintptr_t*>(chars);
4285         chars += increment;
4286       }
4287       // Check for early return.
4288       if ((acc & kOneByteMask) != 0) {
4289         is_one_byte_ = false;
4290         return;
4291       }
4292     }
4293     // Read the rest.
4294     while (chars != end) {
4295       acc |= *chars++;
4296     }
4297     // Check result.
4298     if ((acc & kOneByteMask) != 0) is_one_byte_ = false;
4299   }
4300 
4301  private:
CheckCons(i::ConsString * cons_string)4302   bool CheckCons(i::ConsString* cons_string) {
4303     while (true) {
4304       // Check left side if flat.
4305       i::String* left = cons_string->first();
4306       i::ConsString* left_as_cons =
4307           i::String::VisitFlat(this, left, 0);
4308       if (!is_one_byte_) return false;
4309       // Check right side if flat.
4310       i::String* right = cons_string->second();
4311       i::ConsString* right_as_cons =
4312           i::String::VisitFlat(this, right, 0);
4313       if (!is_one_byte_) return false;
4314       // Standard recurse/iterate trick.
4315       if (left_as_cons != NULL && right_as_cons != NULL) {
4316         if (left->length() < right->length()) {
4317           CheckCons(left_as_cons);
4318           cons_string = right_as_cons;
4319         } else {
4320           CheckCons(right_as_cons);
4321           cons_string = left_as_cons;
4322         }
4323         // Check fast return.
4324         if (!is_one_byte_) return false;
4325         continue;
4326       }
4327       // Descend left in place.
4328       if (left_as_cons != NULL) {
4329         cons_string = left_as_cons;
4330         continue;
4331       }
4332       // Descend right in place.
4333       if (right_as_cons != NULL) {
4334         cons_string = right_as_cons;
4335         continue;
4336       }
4337       // Terminate.
4338       break;
4339     }
4340     return is_one_byte_;
4341   }
4342   bool is_one_byte_;
4343   DISALLOW_COPY_AND_ASSIGN(ContainsOnlyOneByteHelper);
4344 };
4345 
4346 
ContainsOnlyOneByte() const4347 bool String::ContainsOnlyOneByte() const {
4348   i::Handle<i::String> str = Utils::OpenHandle(this);
4349   if (str->HasOnlyOneByteChars()) return true;
4350   ContainsOnlyOneByteHelper helper;
4351   return helper.Check(*str);
4352 }
4353 
4354 
4355 class Utf8LengthHelper : public i::AllStatic {
4356  public:
4357   enum State {
4358     kEndsWithLeadingSurrogate = 1 << 0,
4359     kStartsWithTrailingSurrogate = 1 << 1,
4360     kLeftmostEdgeIsCalculated = 1 << 2,
4361     kRightmostEdgeIsCalculated = 1 << 3,
4362     kLeftmostEdgeIsSurrogate = 1 << 4,
4363     kRightmostEdgeIsSurrogate = 1 << 5
4364   };
4365 
4366   static const uint8_t kInitialState = 0;
4367 
EndsWithSurrogate(uint8_t state)4368   static inline bool EndsWithSurrogate(uint8_t state) {
4369     return state & kEndsWithLeadingSurrogate;
4370   }
4371 
StartsWithSurrogate(uint8_t state)4372   static inline bool StartsWithSurrogate(uint8_t state) {
4373     return state & kStartsWithTrailingSurrogate;
4374   }
4375 
4376   class Visitor {
4377    public:
Visitor()4378     Visitor() : utf8_length_(0), state_(kInitialState) {}
4379 
VisitOneByteString(const uint8_t * chars,int length)4380     void VisitOneByteString(const uint8_t* chars, int length) {
4381       int utf8_length = 0;
4382       // Add in length 1 for each non-Latin1 character.
4383       for (int i = 0; i < length; i++) {
4384         utf8_length += *chars++ >> 7;
4385       }
4386       // Add in length 1 for each character.
4387       utf8_length_ = utf8_length + length;
4388       state_ = kInitialState;
4389     }
4390 
VisitTwoByteString(const uint16_t * chars,int length)4391     void VisitTwoByteString(const uint16_t* chars, int length) {
4392       int utf8_length = 0;
4393       int last_character = unibrow::Utf16::kNoPreviousCharacter;
4394       for (int i = 0; i < length; i++) {
4395         uint16_t c = chars[i];
4396         utf8_length += unibrow::Utf8::Length(c, last_character);
4397         last_character = c;
4398       }
4399       utf8_length_ = utf8_length;
4400       uint8_t state = 0;
4401       if (unibrow::Utf16::IsTrailSurrogate(chars[0])) {
4402         state |= kStartsWithTrailingSurrogate;
4403       }
4404       if (unibrow::Utf16::IsLeadSurrogate(chars[length-1])) {
4405         state |= kEndsWithLeadingSurrogate;
4406       }
4407       state_ = state;
4408     }
4409 
VisitFlat(i::String * string,int * length,uint8_t * state)4410     static i::ConsString* VisitFlat(i::String* string,
4411                                     int* length,
4412                                     uint8_t* state) {
4413       Visitor visitor;
4414       i::ConsString* cons_string = i::String::VisitFlat(&visitor, string);
4415       *length = visitor.utf8_length_;
4416       *state = visitor.state_;
4417       return cons_string;
4418     }
4419 
4420    private:
4421     int utf8_length_;
4422     uint8_t state_;
4423     DISALLOW_COPY_AND_ASSIGN(Visitor);
4424   };
4425 
MergeLeafLeft(int * length,uint8_t * state,uint8_t leaf_state)4426   static inline void MergeLeafLeft(int* length,
4427                                    uint8_t* state,
4428                                    uint8_t leaf_state) {
4429     bool edge_surrogate = StartsWithSurrogate(leaf_state);
4430     if (!(*state & kLeftmostEdgeIsCalculated)) {
4431       DCHECK(!(*state & kLeftmostEdgeIsSurrogate));
4432       *state |= kLeftmostEdgeIsCalculated
4433           | (edge_surrogate ? kLeftmostEdgeIsSurrogate : 0);
4434     } else if (EndsWithSurrogate(*state) && edge_surrogate) {
4435       *length -= unibrow::Utf8::kBytesSavedByCombiningSurrogates;
4436     }
4437     if (EndsWithSurrogate(leaf_state)) {
4438       *state |= kEndsWithLeadingSurrogate;
4439     } else {
4440       *state &= ~kEndsWithLeadingSurrogate;
4441     }
4442   }
4443 
MergeLeafRight(int * length,uint8_t * state,uint8_t leaf_state)4444   static inline void MergeLeafRight(int* length,
4445                                     uint8_t* state,
4446                                     uint8_t leaf_state) {
4447     bool edge_surrogate = EndsWithSurrogate(leaf_state);
4448     if (!(*state & kRightmostEdgeIsCalculated)) {
4449       DCHECK(!(*state & kRightmostEdgeIsSurrogate));
4450       *state |= (kRightmostEdgeIsCalculated
4451                  | (edge_surrogate ? kRightmostEdgeIsSurrogate : 0));
4452     } else if (edge_surrogate && StartsWithSurrogate(*state)) {
4453       *length -= unibrow::Utf8::kBytesSavedByCombiningSurrogates;
4454     }
4455     if (StartsWithSurrogate(leaf_state)) {
4456       *state |= kStartsWithTrailingSurrogate;
4457     } else {
4458       *state &= ~kStartsWithTrailingSurrogate;
4459     }
4460   }
4461 
MergeTerminal(int * length,uint8_t state,uint8_t * state_out)4462   static inline void MergeTerminal(int* length,
4463                                    uint8_t state,
4464                                    uint8_t* state_out) {
4465     DCHECK((state & kLeftmostEdgeIsCalculated) &&
4466            (state & kRightmostEdgeIsCalculated));
4467     if (EndsWithSurrogate(state) && StartsWithSurrogate(state)) {
4468       *length -= unibrow::Utf8::kBytesSavedByCombiningSurrogates;
4469     }
4470     *state_out = kInitialState |
4471         (state & kLeftmostEdgeIsSurrogate ? kStartsWithTrailingSurrogate : 0) |
4472         (state & kRightmostEdgeIsSurrogate ? kEndsWithLeadingSurrogate : 0);
4473   }
4474 
Calculate(i::ConsString * current,uint8_t * state_out)4475   static int Calculate(i::ConsString* current, uint8_t* state_out) {
4476     using namespace internal;
4477     int total_length = 0;
4478     uint8_t state = kInitialState;
4479     while (true) {
4480       i::String* left = current->first();
4481       i::String* right = current->second();
4482       uint8_t right_leaf_state;
4483       uint8_t left_leaf_state;
4484       int leaf_length;
4485       ConsString* left_as_cons =
4486           Visitor::VisitFlat(left, &leaf_length, &left_leaf_state);
4487       if (left_as_cons == NULL) {
4488         total_length += leaf_length;
4489         MergeLeafLeft(&total_length, &state, left_leaf_state);
4490       }
4491       ConsString* right_as_cons =
4492           Visitor::VisitFlat(right, &leaf_length, &right_leaf_state);
4493       if (right_as_cons == NULL) {
4494         total_length += leaf_length;
4495         MergeLeafRight(&total_length, &state, right_leaf_state);
4496         if (left_as_cons != NULL) {
4497           // 1 Leaf node. Descend in place.
4498           current = left_as_cons;
4499           continue;
4500         } else {
4501           // Terminal node.
4502           MergeTerminal(&total_length, state, state_out);
4503           return total_length;
4504         }
4505       } else if (left_as_cons == NULL) {
4506         // 1 Leaf node. Descend in place.
4507         current = right_as_cons;
4508         continue;
4509       }
4510       // Both strings are ConsStrings.
4511       // Recurse on smallest.
4512       if (left->length() < right->length()) {
4513         total_length += Calculate(left_as_cons, &left_leaf_state);
4514         MergeLeafLeft(&total_length, &state, left_leaf_state);
4515         current = right_as_cons;
4516       } else {
4517         total_length += Calculate(right_as_cons, &right_leaf_state);
4518         MergeLeafRight(&total_length, &state, right_leaf_state);
4519         current = left_as_cons;
4520       }
4521     }
4522     UNREACHABLE();
4523     return 0;
4524   }
4525 
Calculate(i::ConsString * current)4526   static inline int Calculate(i::ConsString* current) {
4527     uint8_t state = kInitialState;
4528     return Calculate(current, &state);
4529   }
4530 
4531  private:
4532   DISALLOW_IMPLICIT_CONSTRUCTORS(Utf8LengthHelper);
4533 };
4534 
4535 
Utf8Length(i::String * str,i::Isolate * isolate)4536 static int Utf8Length(i::String* str, i::Isolate* isolate) {
4537   int length = str->length();
4538   if (length == 0) return 0;
4539   uint8_t state;
4540   i::ConsString* cons_string =
4541       Utf8LengthHelper::Visitor::VisitFlat(str, &length, &state);
4542   if (cons_string == NULL) return length;
4543   return Utf8LengthHelper::Calculate(cons_string);
4544 }
4545 
4546 
Utf8Length() const4547 int String::Utf8Length() const {
4548   i::Handle<i::String> str = Utils::OpenHandle(this);
4549   i::Isolate* isolate = str->GetIsolate();
4550   return v8::Utf8Length(*str, isolate);
4551 }
4552 
4553 
4554 class Utf8WriterVisitor {
4555  public:
Utf8WriterVisitor(char * buffer,int capacity,bool skip_capacity_check,bool replace_invalid_utf8)4556   Utf8WriterVisitor(
4557       char* buffer,
4558       int capacity,
4559       bool skip_capacity_check,
4560       bool replace_invalid_utf8)
4561     : early_termination_(false),
4562       last_character_(unibrow::Utf16::kNoPreviousCharacter),
4563       buffer_(buffer),
4564       start_(buffer),
4565       capacity_(capacity),
4566       skip_capacity_check_(capacity == -1 || skip_capacity_check),
4567       replace_invalid_utf8_(replace_invalid_utf8),
4568       utf16_chars_read_(0) {
4569   }
4570 
WriteEndCharacter(uint16_t character,int last_character,int remaining,char * const buffer,bool replace_invalid_utf8)4571   static int WriteEndCharacter(uint16_t character,
4572                                int last_character,
4573                                int remaining,
4574                                char* const buffer,
4575                                bool replace_invalid_utf8) {
4576     using namespace unibrow;
4577     DCHECK(remaining > 0);
4578     // We can't use a local buffer here because Encode needs to modify
4579     // previous characters in the stream.  We know, however, that
4580     // exactly one character will be advanced.
4581     if (Utf16::IsSurrogatePair(last_character, character)) {
4582       int written = Utf8::Encode(buffer,
4583                                  character,
4584                                  last_character,
4585                                  replace_invalid_utf8);
4586       DCHECK(written == 1);
4587       return written;
4588     }
4589     // Use a scratch buffer to check the required characters.
4590     char temp_buffer[Utf8::kMaxEncodedSize];
4591     // Can't encode using last_character as gcc has array bounds issues.
4592     int written = Utf8::Encode(temp_buffer,
4593                                character,
4594                                Utf16::kNoPreviousCharacter,
4595                                replace_invalid_utf8);
4596     // Won't fit.
4597     if (written > remaining) return 0;
4598     // Copy over the character from temp_buffer.
4599     for (int j = 0; j < written; j++) {
4600       buffer[j] = temp_buffer[j];
4601     }
4602     return written;
4603   }
4604 
4605   // Visit writes out a group of code units (chars) of a v8::String to the
4606   // internal buffer_. This is done in two phases. The first phase calculates a
4607   // pesimistic estimate (writable_length) on how many code units can be safely
4608   // written without exceeding the buffer capacity and without writing the last
4609   // code unit (it could be a lead surrogate). The estimated number of code
4610   // units is then written out in one go, and the reported byte usage is used
4611   // to correct the estimate. This is repeated until the estimate becomes <= 0
4612   // or all code units have been written out. The second phase writes out code
4613   // units until the buffer capacity is reached, would be exceeded by the next
4614   // unit, or all units have been written out.
4615   template<typename Char>
Visit(const Char * chars,const int length)4616   void Visit(const Char* chars, const int length) {
4617     using namespace unibrow;
4618     DCHECK(!early_termination_);
4619     if (length == 0) return;
4620     // Copy state to stack.
4621     char* buffer = buffer_;
4622     int last_character =
4623         sizeof(Char) == 1 ? Utf16::kNoPreviousCharacter : last_character_;
4624     int i = 0;
4625     // Do a fast loop where there is no exit capacity check.
4626     while (true) {
4627       int fast_length;
4628       if (skip_capacity_check_) {
4629         fast_length = length;
4630       } else {
4631         int remaining_capacity = capacity_ - static_cast<int>(buffer - start_);
4632         // Need enough space to write everything but one character.
4633         STATIC_ASSERT(Utf16::kMaxExtraUtf8BytesForOneUtf16CodeUnit == 3);
4634         int max_size_per_char =  sizeof(Char) == 1 ? 2 : 3;
4635         int writable_length =
4636             (remaining_capacity - max_size_per_char)/max_size_per_char;
4637         // Need to drop into slow loop.
4638         if (writable_length <= 0) break;
4639         fast_length = i + writable_length;
4640         if (fast_length > length) fast_length = length;
4641       }
4642       // Write the characters to the stream.
4643       if (sizeof(Char) == 1) {
4644         for (; i < fast_length; i++) {
4645           buffer +=
4646               Utf8::EncodeOneByte(buffer, static_cast<uint8_t>(*chars++));
4647           DCHECK(capacity_ == -1 || (buffer - start_) <= capacity_);
4648         }
4649       } else {
4650         for (; i < fast_length; i++) {
4651           uint16_t character = *chars++;
4652           buffer += Utf8::Encode(buffer,
4653                                  character,
4654                                  last_character,
4655                                  replace_invalid_utf8_);
4656           last_character = character;
4657           DCHECK(capacity_ == -1 || (buffer - start_) <= capacity_);
4658         }
4659       }
4660       // Array is fully written. Exit.
4661       if (fast_length == length) {
4662         // Write state back out to object.
4663         last_character_ = last_character;
4664         buffer_ = buffer;
4665         utf16_chars_read_ += length;
4666         return;
4667       }
4668     }
4669     DCHECK(!skip_capacity_check_);
4670     // Slow loop. Must check capacity on each iteration.
4671     int remaining_capacity = capacity_ - static_cast<int>(buffer - start_);
4672     DCHECK(remaining_capacity >= 0);
4673     for (; i < length && remaining_capacity > 0; i++) {
4674       uint16_t character = *chars++;
4675       // remaining_capacity is <= 3 bytes at this point, so we do not write out
4676       // an umatched lead surrogate.
4677       if (replace_invalid_utf8_ && Utf16::IsLeadSurrogate(character)) {
4678         early_termination_ = true;
4679         break;
4680       }
4681       int written = WriteEndCharacter(character,
4682                                       last_character,
4683                                       remaining_capacity,
4684                                       buffer,
4685                                       replace_invalid_utf8_);
4686       if (written == 0) {
4687         early_termination_ = true;
4688         break;
4689       }
4690       buffer += written;
4691       remaining_capacity -= written;
4692       last_character = character;
4693     }
4694     // Write state back out to object.
4695     last_character_ = last_character;
4696     buffer_ = buffer;
4697     utf16_chars_read_ += i;
4698   }
4699 
IsDone()4700   inline bool IsDone() {
4701     return early_termination_;
4702   }
4703 
VisitOneByteString(const uint8_t * chars,int length)4704   inline void VisitOneByteString(const uint8_t* chars, int length) {
4705     Visit(chars, length);
4706   }
4707 
VisitTwoByteString(const uint16_t * chars,int length)4708   inline void VisitTwoByteString(const uint16_t* chars, int length) {
4709     Visit(chars, length);
4710   }
4711 
CompleteWrite(bool write_null,int * utf16_chars_read_out)4712   int CompleteWrite(bool write_null, int* utf16_chars_read_out) {
4713     // Write out number of utf16 characters written to the stream.
4714     if (utf16_chars_read_out != NULL) {
4715       *utf16_chars_read_out = utf16_chars_read_;
4716     }
4717     // Only null terminate if all of the string was written and there's space.
4718     if (write_null &&
4719         !early_termination_ &&
4720         (capacity_ == -1 || (buffer_ - start_) < capacity_)) {
4721       *buffer_++ = '\0';
4722     }
4723     return static_cast<int>(buffer_ - start_);
4724   }
4725 
4726  private:
4727   bool early_termination_;
4728   int last_character_;
4729   char* buffer_;
4730   char* const start_;
4731   int capacity_;
4732   bool const skip_capacity_check_;
4733   bool const replace_invalid_utf8_;
4734   int utf16_chars_read_;
4735   DISALLOW_IMPLICIT_CONSTRUCTORS(Utf8WriterVisitor);
4736 };
4737 
4738 
RecursivelySerializeToUtf8(i::String * current,Utf8WriterVisitor * writer,int recursion_budget)4739 static bool RecursivelySerializeToUtf8(i::String* current,
4740                                        Utf8WriterVisitor* writer,
4741                                        int recursion_budget) {
4742   while (!writer->IsDone()) {
4743     i::ConsString* cons_string = i::String::VisitFlat(writer, current);
4744     if (cons_string == NULL) return true;  // Leaf node.
4745     if (recursion_budget <= 0) return false;
4746     // Must write the left branch first.
4747     i::String* first = cons_string->first();
4748     bool success = RecursivelySerializeToUtf8(first,
4749                                               writer,
4750                                               recursion_budget - 1);
4751     if (!success) return false;
4752     // Inline tail recurse for right branch.
4753     current = cons_string->second();
4754   }
4755   return true;
4756 }
4757 
4758 
WriteUtf8(char * buffer,int capacity,int * nchars_ref,int options) const4759 int String::WriteUtf8(char* buffer,
4760                       int capacity,
4761                       int* nchars_ref,
4762                       int options) const {
4763   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
4764   LOG_API(isolate, "String::WriteUtf8");
4765   ENTER_V8(isolate);
4766   i::Handle<i::String> str = Utils::OpenHandle(this);
4767   if (options & HINT_MANY_WRITES_EXPECTED) {
4768     str = i::String::Flatten(str);  // Flatten the string for efficiency.
4769   }
4770   const int string_length = str->length();
4771   bool write_null = !(options & NO_NULL_TERMINATION);
4772   bool replace_invalid_utf8 = (options & REPLACE_INVALID_UTF8);
4773   int max16BitCodeUnitSize = unibrow::Utf8::kMax16BitCodeUnitSize;
4774   // First check if we can just write the string without checking capacity.
4775   if (capacity == -1 || capacity / max16BitCodeUnitSize >= string_length) {
4776     Utf8WriterVisitor writer(buffer, capacity, true, replace_invalid_utf8);
4777     const int kMaxRecursion = 100;
4778     bool success = RecursivelySerializeToUtf8(*str, &writer, kMaxRecursion);
4779     if (success) return writer.CompleteWrite(write_null, nchars_ref);
4780   } else if (capacity >= string_length) {
4781     // First check that the buffer is large enough.
4782     int utf8_bytes = v8::Utf8Length(*str, str->GetIsolate());
4783     if (utf8_bytes <= capacity) {
4784       // one-byte fast path.
4785       if (utf8_bytes == string_length) {
4786         WriteOneByte(reinterpret_cast<uint8_t*>(buffer), 0, capacity, options);
4787         if (nchars_ref != NULL) *nchars_ref = string_length;
4788         if (write_null && (utf8_bytes+1 <= capacity)) {
4789           return string_length + 1;
4790         }
4791         return string_length;
4792       }
4793       if (write_null && (utf8_bytes+1 > capacity)) {
4794         options |= NO_NULL_TERMINATION;
4795       }
4796       // Recurse once without a capacity limit.
4797       // This will get into the first branch above.
4798       // TODO(dcarney) Check max left rec. in Utf8Length and fall through.
4799       return WriteUtf8(buffer, -1, nchars_ref, options);
4800     }
4801   }
4802   // Recursive slow path can potentially be unreasonable slow. Flatten.
4803   str = i::String::Flatten(str);
4804   Utf8WriterVisitor writer(buffer, capacity, false, replace_invalid_utf8);
4805   i::String::VisitFlat(&writer, *str);
4806   return writer.CompleteWrite(write_null, nchars_ref);
4807 }
4808 
4809 
4810 template<typename CharType>
WriteHelper(const String * string,CharType * buffer,int start,int length,int options)4811 static inline int WriteHelper(const String* string,
4812                               CharType* buffer,
4813                               int start,
4814                               int length,
4815                               int options) {
4816   i::Isolate* isolate = Utils::OpenHandle(string)->GetIsolate();
4817   LOG_API(isolate, "String::Write");
4818   ENTER_V8(isolate);
4819   DCHECK(start >= 0 && length >= -1);
4820   i::Handle<i::String> str = Utils::OpenHandle(string);
4821   isolate->string_tracker()->RecordWrite(str);
4822   if (options & String::HINT_MANY_WRITES_EXPECTED) {
4823     // Flatten the string for efficiency.  This applies whether we are
4824     // using StringCharacterStream or Get(i) to access the characters.
4825     str = i::String::Flatten(str);
4826   }
4827   int end = start + length;
4828   if ((length == -1) || (length > str->length() - start) )
4829     end = str->length();
4830   if (end < 0) return 0;
4831   i::String::WriteToFlat(*str, buffer, start, end);
4832   if (!(options & String::NO_NULL_TERMINATION) &&
4833       (length == -1 || end - start < length)) {
4834     buffer[end - start] = '\0';
4835   }
4836   return end - start;
4837 }
4838 
4839 
WriteOneByte(uint8_t * buffer,int start,int length,int options) const4840 int String::WriteOneByte(uint8_t* buffer,
4841                          int start,
4842                          int length,
4843                          int options) const {
4844   return WriteHelper(this, buffer, start, length, options);
4845 }
4846 
4847 
Write(uint16_t * buffer,int start,int length,int options) const4848 int String::Write(uint16_t* buffer,
4849                   int start,
4850                   int length,
4851                   int options) const {
4852   return WriteHelper(this, buffer, start, length, options);
4853 }
4854 
4855 
IsExternal() const4856 bool v8::String::IsExternal() const {
4857   i::Handle<i::String> str = Utils::OpenHandle(this);
4858   return i::StringShape(*str).IsExternalTwoByte();
4859 }
4860 
4861 
IsExternalOneByte() const4862 bool v8::String::IsExternalOneByte() const {
4863   i::Handle<i::String> str = Utils::OpenHandle(this);
4864   return i::StringShape(*str).IsExternalOneByte();
4865 }
4866 
4867 
VerifyExternalStringResource(v8::String::ExternalStringResource * value) const4868 void v8::String::VerifyExternalStringResource(
4869     v8::String::ExternalStringResource* value) const {
4870   i::Handle<i::String> str = Utils::OpenHandle(this);
4871   const v8::String::ExternalStringResource* expected;
4872   if (i::StringShape(*str).IsExternalTwoByte()) {
4873     const void* resource =
4874         i::Handle<i::ExternalTwoByteString>::cast(str)->resource();
4875     expected = reinterpret_cast<const ExternalStringResource*>(resource);
4876   } else {
4877     expected = NULL;
4878   }
4879   CHECK_EQ(expected, value);
4880 }
4881 
VerifyExternalStringResourceBase(v8::String::ExternalStringResourceBase * value,Encoding encoding) const4882 void v8::String::VerifyExternalStringResourceBase(
4883     v8::String::ExternalStringResourceBase* value, Encoding encoding) const {
4884   i::Handle<i::String> str = Utils::OpenHandle(this);
4885   const v8::String::ExternalStringResourceBase* expected;
4886   Encoding expectedEncoding;
4887   if (i::StringShape(*str).IsExternalOneByte()) {
4888     const void* resource =
4889         i::Handle<i::ExternalOneByteString>::cast(str)->resource();
4890     expected = reinterpret_cast<const ExternalStringResourceBase*>(resource);
4891     expectedEncoding = ONE_BYTE_ENCODING;
4892   } else if (i::StringShape(*str).IsExternalTwoByte()) {
4893     const void* resource =
4894         i::Handle<i::ExternalTwoByteString>::cast(str)->resource();
4895     expected = reinterpret_cast<const ExternalStringResourceBase*>(resource);
4896     expectedEncoding = TWO_BYTE_ENCODING;
4897   } else {
4898     expected = NULL;
4899     expectedEncoding =
4900         str->IsOneByteRepresentation() ? ONE_BYTE_ENCODING : TWO_BYTE_ENCODING;
4901   }
4902   CHECK_EQ(expected, value);
4903   CHECK_EQ(expectedEncoding, encoding);
4904 }
4905 
4906 const v8::String::ExternalOneByteStringResource*
GetExternalOneByteStringResource() const4907 v8::String::GetExternalOneByteStringResource() const {
4908   i::Handle<i::String> str = Utils::OpenHandle(this);
4909   if (i::StringShape(*str).IsExternalOneByte()) {
4910     const void* resource =
4911         i::Handle<i::ExternalOneByteString>::cast(str)->resource();
4912     return reinterpret_cast<const ExternalOneByteStringResource*>(resource);
4913   } else {
4914     return NULL;
4915   }
4916 }
4917 
4918 
Name() const4919 Local<Value> Symbol::Name() const {
4920   i::Handle<i::Symbol> sym = Utils::OpenHandle(this);
4921   i::Handle<i::Object> name(sym->name(), sym->GetIsolate());
4922   return Utils::ToLocal(name);
4923 }
4924 
4925 
Name() const4926 Local<Value> Private::Name() const {
4927   return reinterpret_cast<const Symbol*>(this)->Name();
4928 }
4929 
4930 
Value() const4931 double Number::Value() const {
4932   i::Handle<i::Object> obj = Utils::OpenHandle(this);
4933   return obj->Number();
4934 }
4935 
4936 
Value() const4937 bool Boolean::Value() const {
4938   i::Handle<i::Object> obj = Utils::OpenHandle(this);
4939   return obj->IsTrue();
4940 }
4941 
4942 
Value() const4943 int64_t Integer::Value() const {
4944   i::Handle<i::Object> obj = Utils::OpenHandle(this);
4945   if (obj->IsSmi()) {
4946     return i::Smi::cast(*obj)->value();
4947   } else {
4948     return static_cast<int64_t>(obj->Number());
4949   }
4950 }
4951 
4952 
Value() const4953 int32_t Int32::Value() const {
4954   i::Handle<i::Object> obj = Utils::OpenHandle(this);
4955   if (obj->IsSmi()) {
4956     return i::Smi::cast(*obj)->value();
4957   } else {
4958     return static_cast<int32_t>(obj->Number());
4959   }
4960 }
4961 
4962 
Value() const4963 uint32_t Uint32::Value() const {
4964   i::Handle<i::Object> obj = Utils::OpenHandle(this);
4965   if (obj->IsSmi()) {
4966     return i::Smi::cast(*obj)->value();
4967   } else {
4968     return static_cast<uint32_t>(obj->Number());
4969   }
4970 }
4971 
4972 
InternalFieldCount()4973 int v8::Object::InternalFieldCount() {
4974   i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
4975   return obj->GetInternalFieldCount();
4976 }
4977 
4978 
InternalFieldOK(i::Handle<i::JSObject> obj,int index,const char * location)4979 static bool InternalFieldOK(i::Handle<i::JSObject> obj,
4980                             int index,
4981                             const char* location) {
4982   return Utils::ApiCheck(index < obj->GetInternalFieldCount(),
4983                          location,
4984                          "Internal field out of bounds");
4985 }
4986 
4987 
SlowGetInternalField(int index)4988 Local<Value> v8::Object::SlowGetInternalField(int index) {
4989   i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
4990   const char* location = "v8::Object::GetInternalField()";
4991   if (!InternalFieldOK(obj, index, location)) return Local<Value>();
4992   i::Handle<i::Object> value(obj->GetInternalField(index), obj->GetIsolate());
4993   return Utils::ToLocal(value);
4994 }
4995 
4996 
SetInternalField(int index,v8::Handle<Value> value)4997 void v8::Object::SetInternalField(int index, v8::Handle<Value> value) {
4998   i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
4999   const char* location = "v8::Object::SetInternalField()";
5000   if (!InternalFieldOK(obj, index, location)) return;
5001   i::Handle<i::Object> val = Utils::OpenHandle(*value);
5002   obj->SetInternalField(index, *val);
5003   DCHECK_EQ(value, GetInternalField(index));
5004 }
5005 
5006 
SlowGetAlignedPointerFromInternalField(int index)5007 void* v8::Object::SlowGetAlignedPointerFromInternalField(int index) {
5008   i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
5009   const char* location = "v8::Object::GetAlignedPointerFromInternalField()";
5010   if (!InternalFieldOK(obj, index, location)) return NULL;
5011   return DecodeSmiToAligned(obj->GetInternalField(index), location);
5012 }
5013 
5014 
SetAlignedPointerInInternalField(int index,void * value)5015 void v8::Object::SetAlignedPointerInInternalField(int index, void* value) {
5016   i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
5017   const char* location = "v8::Object::SetAlignedPointerInInternalField()";
5018   if (!InternalFieldOK(obj, index, location)) return;
5019   obj->SetInternalField(index, EncodeAlignedAsSmi(value, location));
5020   DCHECK_EQ(value, GetAlignedPointerFromInternalField(index));
5021 }
5022 
5023 
ExternalValue(i::Object * obj)5024 static void* ExternalValue(i::Object* obj) {
5025   // Obscure semantics for undefined, but somehow checked in our unit tests...
5026   if (obj->IsUndefined()) return NULL;
5027   i::Object* foreign = i::JSObject::cast(obj)->GetInternalField(0);
5028   return i::Foreign::cast(foreign)->foreign_address();
5029 }
5030 
5031 
5032 // --- E n v i r o n m e n t ---
5033 
5034 
InitializePlatform(Platform * platform)5035 void v8::V8::InitializePlatform(Platform* platform) {
5036   i::V8::InitializePlatform(platform);
5037 }
5038 
5039 
ShutdownPlatform()5040 void v8::V8::ShutdownPlatform() {
5041   i::V8::ShutdownPlatform();
5042 }
5043 
5044 
Initialize()5045 bool v8::V8::Initialize() {
5046   i::V8::Initialize();
5047   return true;
5048 }
5049 
5050 
SetEntropySource(EntropySource entropy_source)5051 void v8::V8::SetEntropySource(EntropySource entropy_source) {
5052   base::RandomNumberGenerator::SetEntropySource(entropy_source);
5053 }
5054 
5055 
SetReturnAddressLocationResolver(ReturnAddressLocationResolver return_address_resolver)5056 void v8::V8::SetReturnAddressLocationResolver(
5057     ReturnAddressLocationResolver return_address_resolver) {
5058   i::V8::SetReturnAddressLocationResolver(return_address_resolver);
5059 }
5060 
SetArrayBufferAllocator(ArrayBuffer::Allocator * allocator)5061 void v8::V8::SetArrayBufferAllocator(
5062     ArrayBuffer::Allocator* allocator) {
5063   if (!Utils::ApiCheck(i::V8::ArrayBufferAllocator() == NULL,
5064                        "v8::V8::SetArrayBufferAllocator",
5065                        "ArrayBufferAllocator might only be set once"))
5066     return;
5067   i::V8::SetArrayBufferAllocator(allocator);
5068 }
5069 
5070 
Dispose()5071 bool v8::V8::Dispose() {
5072   i::V8::TearDown();
5073   return true;
5074 }
5075 
5076 
HeapStatistics()5077 HeapStatistics::HeapStatistics(): total_heap_size_(0),
5078                                   total_heap_size_executable_(0),
5079                                   total_physical_size_(0),
5080                                   used_heap_size_(0),
5081                                   heap_size_limit_(0) { }
5082 
5083 
VisitExternalResources(ExternalResourceVisitor * visitor)5084 void v8::V8::VisitExternalResources(ExternalResourceVisitor* visitor) {
5085   i::Isolate* isolate = i::Isolate::Current();
5086   isolate->heap()->VisitExternalResources(visitor);
5087 }
5088 
5089 
5090 class VisitorAdapter : public i::ObjectVisitor {
5091  public:
VisitorAdapter(PersistentHandleVisitor * visitor)5092   explicit VisitorAdapter(PersistentHandleVisitor* visitor)
5093       : visitor_(visitor) {}
VisitPointers(i::Object ** start,i::Object ** end)5094   virtual void VisitPointers(i::Object** start, i::Object** end) {
5095     UNREACHABLE();
5096   }
VisitEmbedderReference(i::Object ** p,uint16_t class_id)5097   virtual void VisitEmbedderReference(i::Object** p, uint16_t class_id) {
5098     Value* value = ToApi<Value>(i::Handle<i::Object>(p));
5099     visitor_->VisitPersistentHandle(
5100         reinterpret_cast<Persistent<Value>*>(&value), class_id);
5101   }
5102  private:
5103   PersistentHandleVisitor* visitor_;
5104 };
5105 
5106 
VisitHandlesWithClassIds(PersistentHandleVisitor * visitor)5107 void v8::V8::VisitHandlesWithClassIds(PersistentHandleVisitor* visitor) {
5108   i::Isolate* isolate = i::Isolate::Current();
5109   i::DisallowHeapAllocation no_allocation;
5110 
5111   VisitorAdapter visitor_adapter(visitor);
5112   isolate->global_handles()->IterateAllRootsWithClassIds(&visitor_adapter);
5113 }
5114 
5115 
VisitHandlesForPartialDependence(Isolate * exported_isolate,PersistentHandleVisitor * visitor)5116 void v8::V8::VisitHandlesForPartialDependence(
5117     Isolate* exported_isolate, PersistentHandleVisitor* visitor) {
5118   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(exported_isolate);
5119   DCHECK(isolate == i::Isolate::Current());
5120   i::DisallowHeapAllocation no_allocation;
5121 
5122   VisitorAdapter visitor_adapter(visitor);
5123   isolate->global_handles()->IterateAllRootsInNewSpaceWithClassIds(
5124       &visitor_adapter);
5125 }
5126 
5127 
InitializeICU(const char * icu_data_file)5128 bool v8::V8::InitializeICU(const char* icu_data_file) {
5129   return i::InitializeICU(icu_data_file);
5130 }
5131 
5132 
GetVersion()5133 const char* v8::V8::GetVersion() {
5134   return i::Version::GetVersion();
5135 }
5136 
5137 
CreateEnvironment(i::Isolate * isolate,v8::ExtensionConfiguration * extensions,v8::Handle<ObjectTemplate> global_template,v8::Handle<Value> maybe_global_proxy)5138 static i::Handle<i::Context> CreateEnvironment(
5139     i::Isolate* isolate,
5140     v8::ExtensionConfiguration* extensions,
5141     v8::Handle<ObjectTemplate> global_template,
5142     v8::Handle<Value> maybe_global_proxy) {
5143   i::Handle<i::Context> env;
5144 
5145   // Enter V8 via an ENTER_V8 scope.
5146   {
5147     ENTER_V8(isolate);
5148     v8::Handle<ObjectTemplate> proxy_template = global_template;
5149     i::Handle<i::FunctionTemplateInfo> proxy_constructor;
5150     i::Handle<i::FunctionTemplateInfo> global_constructor;
5151 
5152     if (!global_template.IsEmpty()) {
5153       // Make sure that the global_template has a constructor.
5154       global_constructor = EnsureConstructor(isolate, *global_template);
5155 
5156       // Create a fresh template for the global proxy object.
5157       proxy_template = ObjectTemplate::New(
5158           reinterpret_cast<v8::Isolate*>(isolate));
5159       proxy_constructor = EnsureConstructor(isolate, *proxy_template);
5160 
5161       // Set the global template to be the prototype template of
5162       // global proxy template.
5163       proxy_constructor->set_prototype_template(
5164           *Utils::OpenHandle(*global_template));
5165 
5166       // Migrate security handlers from global_template to
5167       // proxy_template.  Temporarily removing access check
5168       // information from the global template.
5169       if (!global_constructor->access_check_info()->IsUndefined()) {
5170         proxy_constructor->set_access_check_info(
5171             global_constructor->access_check_info());
5172         proxy_constructor->set_needs_access_check(
5173             global_constructor->needs_access_check());
5174         global_constructor->set_needs_access_check(false);
5175         global_constructor->set_access_check_info(
5176             isolate->heap()->undefined_value());
5177       }
5178     }
5179 
5180     i::Handle<i::Object> proxy = Utils::OpenHandle(*maybe_global_proxy, true);
5181     i::MaybeHandle<i::JSGlobalProxy> maybe_proxy;
5182     if (!proxy.is_null()) {
5183       maybe_proxy = i::Handle<i::JSGlobalProxy>::cast(proxy);
5184     }
5185     // Create the environment.
5186     env = isolate->bootstrapper()->CreateEnvironment(
5187         maybe_proxy, proxy_template, extensions);
5188 
5189     // Restore the access check info on the global template.
5190     if (!global_template.IsEmpty()) {
5191       DCHECK(!global_constructor.is_null());
5192       DCHECK(!proxy_constructor.is_null());
5193       global_constructor->set_access_check_info(
5194           proxy_constructor->access_check_info());
5195       global_constructor->set_needs_access_check(
5196           proxy_constructor->needs_access_check());
5197     }
5198   }
5199   // Leave V8.
5200 
5201   return env;
5202 }
5203 
New(v8::Isolate * external_isolate,v8::ExtensionConfiguration * extensions,v8::Handle<ObjectTemplate> global_template,v8::Handle<Value> global_object)5204 Local<Context> v8::Context::New(
5205     v8::Isolate* external_isolate,
5206     v8::ExtensionConfiguration* extensions,
5207     v8::Handle<ObjectTemplate> global_template,
5208     v8::Handle<Value> global_object) {
5209   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(external_isolate);
5210   LOG_API(isolate, "Context::New");
5211   ON_BAILOUT(isolate, "v8::Context::New()", return Local<Context>());
5212   i::HandleScope scope(isolate);
5213   ExtensionConfiguration no_extensions;
5214   if (extensions == NULL) extensions = &no_extensions;
5215   i::Handle<i::Context> env =
5216       CreateEnvironment(isolate, extensions, global_template, global_object);
5217   if (env.is_null()) return Local<Context>();
5218   return Utils::ToLocal(scope.CloseAndEscape(env));
5219 }
5220 
5221 
SetSecurityToken(Handle<Value> token)5222 void v8::Context::SetSecurityToken(Handle<Value> token) {
5223   i::Isolate* isolate = i::Isolate::Current();
5224   ENTER_V8(isolate);
5225   i::Handle<i::Context> env = Utils::OpenHandle(this);
5226   i::Handle<i::Object> token_handle = Utils::OpenHandle(*token);
5227   env->set_security_token(*token_handle);
5228 }
5229 
5230 
UseDefaultSecurityToken()5231 void v8::Context::UseDefaultSecurityToken() {
5232   i::Isolate* isolate = i::Isolate::Current();
5233   ENTER_V8(isolate);
5234   i::Handle<i::Context> env = Utils::OpenHandle(this);
5235   env->set_security_token(env->global_object());
5236 }
5237 
5238 
GetSecurityToken()5239 Handle<Value> v8::Context::GetSecurityToken() {
5240   i::Isolate* isolate = i::Isolate::Current();
5241   i::Handle<i::Context> env = Utils::OpenHandle(this);
5242   i::Object* security_token = env->security_token();
5243   i::Handle<i::Object> token_handle(security_token, isolate);
5244   return Utils::ToLocal(token_handle);
5245 }
5246 
5247 
GetIsolate()5248 v8::Isolate* Context::GetIsolate() {
5249   i::Handle<i::Context> env = Utils::OpenHandle(this);
5250   return reinterpret_cast<Isolate*>(env->GetIsolate());
5251 }
5252 
5253 
Global()5254 v8::Local<v8::Object> Context::Global() {
5255   i::Handle<i::Context> context = Utils::OpenHandle(this);
5256   i::Isolate* isolate = context->GetIsolate();
5257   i::Handle<i::Object> global(context->global_proxy(), isolate);
5258   // TODO(dcarney): This should always return the global proxy
5259   // but can't presently as calls to GetProtoype will return the wrong result.
5260   if (i::Handle<i::JSGlobalProxy>::cast(
5261           global)->IsDetachedFrom(context->global_object())) {
5262     global = i::Handle<i::Object>(context->global_object(), isolate);
5263   }
5264   return Utils::ToLocal(i::Handle<i::JSObject>::cast(global));
5265 }
5266 
5267 
DetachGlobal()5268 void Context::DetachGlobal() {
5269   i::Handle<i::Context> context = Utils::OpenHandle(this);
5270   i::Isolate* isolate = context->GetIsolate();
5271   ENTER_V8(isolate);
5272   isolate->bootstrapper()->DetachGlobal(context);
5273 }
5274 
5275 
AllowCodeGenerationFromStrings(bool allow)5276 void Context::AllowCodeGenerationFromStrings(bool allow) {
5277   i::Handle<i::Context> context = Utils::OpenHandle(this);
5278   i::Isolate* isolate = context->GetIsolate();
5279   ENTER_V8(isolate);
5280   context->set_allow_code_gen_from_strings(
5281       allow ? isolate->heap()->true_value() : isolate->heap()->false_value());
5282 }
5283 
5284 
IsCodeGenerationFromStringsAllowed()5285 bool Context::IsCodeGenerationFromStringsAllowed() {
5286   i::Handle<i::Context> context = Utils::OpenHandle(this);
5287   return !context->allow_code_gen_from_strings()->IsFalse();
5288 }
5289 
5290 
SetErrorMessageForCodeGenerationFromStrings(Handle<String> error)5291 void Context::SetErrorMessageForCodeGenerationFromStrings(
5292     Handle<String> error) {
5293   i::Handle<i::Context> context = Utils::OpenHandle(this);
5294   i::Handle<i::String> error_handle = Utils::OpenHandle(*error);
5295   context->set_error_message_for_code_gen_from_strings(*error_handle);
5296 }
5297 
5298 
NewInstance()5299 Local<v8::Object> ObjectTemplate::NewInstance() {
5300   i::Isolate* isolate = i::Isolate::Current();
5301   ON_BAILOUT(isolate, "v8::ObjectTemplate::NewInstance()",
5302              return Local<v8::Object>());
5303   LOG_API(isolate, "ObjectTemplate::NewInstance");
5304   ENTER_V8(isolate);
5305   EXCEPTION_PREAMBLE(isolate);
5306   i::Handle<i::Object> obj;
5307   has_pending_exception = !i::Execution::InstantiateObject(
5308       Utils::OpenHandle(this)).ToHandle(&obj);
5309   EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Object>());
5310   return Utils::ToLocal(i::Handle<i::JSObject>::cast(obj));
5311 }
5312 
5313 
GetFunction()5314 Local<v8::Function> FunctionTemplate::GetFunction() {
5315   i::Isolate* isolate = i::Isolate::Current();
5316   ON_BAILOUT(isolate, "v8::FunctionTemplate::GetFunction()",
5317              return Local<v8::Function>());
5318   LOG_API(isolate, "FunctionTemplate::GetFunction");
5319   ENTER_V8(isolate);
5320   EXCEPTION_PREAMBLE(isolate);
5321   i::Handle<i::Object> obj;
5322   has_pending_exception = !i::Execution::InstantiateFunction(
5323       Utils::OpenHandle(this)).ToHandle(&obj);
5324   EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Function>());
5325   return Utils::ToLocal(i::Handle<i::JSFunction>::cast(obj));
5326 }
5327 
5328 
HasInstance(v8::Handle<v8::Value> value)5329 bool FunctionTemplate::HasInstance(v8::Handle<v8::Value> value) {
5330   ON_BAILOUT(i::Isolate::Current(), "v8::FunctionTemplate::HasInstanceOf()",
5331              return false);
5332   i::Object* obj = *Utils::OpenHandle(*value);
5333   return Utils::OpenHandle(this)->IsTemplateFor(obj);
5334 }
5335 
5336 
New(Isolate * isolate,void * value)5337 Local<External> v8::External::New(Isolate* isolate, void* value) {
5338   STATIC_ASSERT(sizeof(value) == sizeof(i::Address));
5339   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
5340   LOG_API(i_isolate, "External::New");
5341   ENTER_V8(i_isolate);
5342   i::Handle<i::JSObject> external = i_isolate->factory()->NewExternal(value);
5343   return Utils::ExternalToLocal(external);
5344 }
5345 
5346 
Value() const5347 void* External::Value() const {
5348   return ExternalValue(*Utils::OpenHandle(this));
5349 }
5350 
5351 
5352 // anonymous namespace for string creation helper functions
5353 namespace {
5354 
StringLength(const char * string)5355 inline int StringLength(const char* string) {
5356   return i::StrLength(string);
5357 }
5358 
5359 
StringLength(const uint8_t * string)5360 inline int StringLength(const uint8_t* string) {
5361   return i::StrLength(reinterpret_cast<const char*>(string));
5362 }
5363 
5364 
StringLength(const uint16_t * string)5365 inline int StringLength(const uint16_t* string) {
5366   int length = 0;
5367   while (string[length] != '\0')
5368     length++;
5369   return length;
5370 }
5371 
5372 
5373 MUST_USE_RESULT
NewString(i::Factory * factory,String::NewStringType type,i::Vector<const char> string)5374 inline i::MaybeHandle<i::String> NewString(i::Factory* factory,
5375                                            String::NewStringType type,
5376                                            i::Vector<const char> string) {
5377   if (type == String::kInternalizedString) {
5378     return factory->InternalizeUtf8String(string);
5379   }
5380   return factory->NewStringFromUtf8(string);
5381 }
5382 
5383 
5384 MUST_USE_RESULT
NewString(i::Factory * factory,String::NewStringType type,i::Vector<const uint8_t> string)5385 inline i::MaybeHandle<i::String> NewString(i::Factory* factory,
5386                                            String::NewStringType type,
5387                                            i::Vector<const uint8_t> string) {
5388   if (type == String::kInternalizedString) {
5389     return factory->InternalizeOneByteString(string);
5390   }
5391   return factory->NewStringFromOneByte(string);
5392 }
5393 
5394 
5395 MUST_USE_RESULT
NewString(i::Factory * factory,String::NewStringType type,i::Vector<const uint16_t> string)5396 inline i::MaybeHandle<i::String> NewString(i::Factory* factory,
5397                                            String::NewStringType type,
5398                                            i::Vector<const uint16_t> string) {
5399   if (type == String::kInternalizedString) {
5400     return factory->InternalizeTwoByteString(string);
5401   }
5402   return factory->NewStringFromTwoByte(string);
5403 }
5404 
5405 
5406 template<typename Char>
NewString(Isolate * v8_isolate,const char * location,const char * env,const Char * data,String::NewStringType type,int length)5407 inline Local<String> NewString(Isolate* v8_isolate,
5408                                const char* location,
5409                                const char* env,
5410                                const Char* data,
5411                                String::NewStringType type,
5412                                int length) {
5413   i::Isolate* isolate = reinterpret_cast<internal::Isolate*>(v8_isolate);
5414   LOG_API(isolate, env);
5415   if (length == 0 && type != String::kUndetectableString) {
5416     return String::Empty(v8_isolate);
5417   }
5418   ENTER_V8(isolate);
5419   if (length == -1) length = StringLength(data);
5420   // We do not expect this to fail. Change this if it does.
5421   i::Handle<i::String> result = NewString(
5422       isolate->factory(),
5423       type,
5424       i::Vector<const Char>(data, length)).ToHandleChecked();
5425   if (type == String::kUndetectableString) {
5426     result->MarkAsUndetectable();
5427   }
5428   return Utils::ToLocal(result);
5429 }
5430 
5431 }  // anonymous namespace
5432 
5433 
NewFromUtf8(Isolate * isolate,const char * data,NewStringType type,int length)5434 Local<String> String::NewFromUtf8(Isolate* isolate,
5435                                   const char* data,
5436                                   NewStringType type,
5437                                   int length) {
5438   return NewString(isolate,
5439                    "v8::String::NewFromUtf8()",
5440                    "String::NewFromUtf8",
5441                    data,
5442                    type,
5443                    length);
5444 }
5445 
5446 
NewFromOneByte(Isolate * isolate,const uint8_t * data,NewStringType type,int length)5447 Local<String> String::NewFromOneByte(Isolate* isolate,
5448                                      const uint8_t* data,
5449                                      NewStringType type,
5450                                      int length) {
5451   return NewString(isolate,
5452                    "v8::String::NewFromOneByte()",
5453                    "String::NewFromOneByte",
5454                    data,
5455                    type,
5456                    length);
5457 }
5458 
5459 
NewFromTwoByte(Isolate * isolate,const uint16_t * data,NewStringType type,int length)5460 Local<String> String::NewFromTwoByte(Isolate* isolate,
5461                                      const uint16_t* data,
5462                                      NewStringType type,
5463                                      int length) {
5464   return NewString(isolate,
5465                    "v8::String::NewFromTwoByte()",
5466                    "String::NewFromTwoByte",
5467                    data,
5468                    type,
5469                    length);
5470 }
5471 
5472 
Concat(Handle<String> left,Handle<String> right)5473 Local<String> v8::String::Concat(Handle<String> left, Handle<String> right) {
5474   i::Handle<i::String> left_string = Utils::OpenHandle(*left);
5475   i::Isolate* isolate = left_string->GetIsolate();
5476   LOG_API(isolate, "String::New(char)");
5477   ENTER_V8(isolate);
5478   i::Handle<i::String> right_string = Utils::OpenHandle(*right);
5479   // We do not expect this to fail. Change this if it does.
5480   i::Handle<i::String> result = isolate->factory()->NewConsString(
5481       left_string, right_string).ToHandleChecked();
5482   return Utils::ToLocal(result);
5483 }
5484 
5485 
NewExternalStringHandle(i::Isolate * isolate,v8::String::ExternalStringResource * resource)5486 static i::Handle<i::String> NewExternalStringHandle(
5487     i::Isolate* isolate,
5488     v8::String::ExternalStringResource* resource) {
5489   // We do not expect this to fail. Change this if it does.
5490   return isolate->factory()->NewExternalStringFromTwoByte(
5491       resource).ToHandleChecked();
5492 }
5493 
5494 
NewExternalOneByteStringHandle(i::Isolate * isolate,v8::String::ExternalOneByteStringResource * resource)5495 static i::Handle<i::String> NewExternalOneByteStringHandle(
5496     i::Isolate* isolate, v8::String::ExternalOneByteStringResource* resource) {
5497   // We do not expect this to fail. Change this if it does.
5498   return isolate->factory()
5499       ->NewExternalStringFromOneByte(resource)
5500       .ToHandleChecked();
5501 }
5502 
5503 
NewExternal(Isolate * isolate,v8::String::ExternalStringResource * resource)5504 Local<String> v8::String::NewExternal(
5505     Isolate* isolate,
5506     v8::String::ExternalStringResource* resource) {
5507   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
5508   LOG_API(i_isolate, "String::NewExternal");
5509   ENTER_V8(i_isolate);
5510   CHECK(resource && resource->data());
5511   i::Handle<i::String> result = NewExternalStringHandle(i_isolate, resource);
5512   i_isolate->heap()->external_string_table()->AddString(*result);
5513   return Utils::ToLocal(result);
5514 }
5515 
5516 
MakeExternal(v8::String::ExternalStringResource * resource)5517 bool v8::String::MakeExternal(v8::String::ExternalStringResource* resource) {
5518   i::Handle<i::String> obj = Utils::OpenHandle(this);
5519   i::Isolate* isolate = obj->GetIsolate();
5520   if (i::StringShape(*obj).IsExternal()) {
5521     return false;  // Already an external string.
5522   }
5523   ENTER_V8(isolate);
5524   if (isolate->string_tracker()->IsFreshUnusedString(obj)) {
5525     return false;
5526   }
5527   if (isolate->heap()->IsInGCPostProcessing()) {
5528     return false;
5529   }
5530   CHECK(resource && resource->data());
5531 
5532   bool result = obj->MakeExternal(resource);
5533   // Assert that if CanMakeExternal(), then externalizing actually succeeds.
5534   DCHECK(!CanMakeExternal() || result);
5535   if (result) {
5536     DCHECK(obj->IsExternalString());
5537     isolate->heap()->external_string_table()->AddString(*obj);
5538   }
5539   return result;
5540 }
5541 
5542 
NewExternal(Isolate * isolate,v8::String::ExternalOneByteStringResource * resource)5543 Local<String> v8::String::NewExternal(
5544     Isolate* isolate, v8::String::ExternalOneByteStringResource* resource) {
5545   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
5546   LOG_API(i_isolate, "String::NewExternal");
5547   ENTER_V8(i_isolate);
5548   CHECK(resource && resource->data());
5549   i::Handle<i::String> result =
5550       NewExternalOneByteStringHandle(i_isolate, resource);
5551   i_isolate->heap()->external_string_table()->AddString(*result);
5552   return Utils::ToLocal(result);
5553 }
5554 
5555 
MakeExternal(v8::String::ExternalOneByteStringResource * resource)5556 bool v8::String::MakeExternal(
5557     v8::String::ExternalOneByteStringResource* resource) {
5558   i::Handle<i::String> obj = Utils::OpenHandle(this);
5559   i::Isolate* isolate = obj->GetIsolate();
5560   if (i::StringShape(*obj).IsExternal()) {
5561     return false;  // Already an external string.
5562   }
5563   ENTER_V8(isolate);
5564   if (isolate->string_tracker()->IsFreshUnusedString(obj)) {
5565     return false;
5566   }
5567   if (isolate->heap()->IsInGCPostProcessing()) {
5568     return false;
5569   }
5570   CHECK(resource && resource->data());
5571 
5572   bool result = obj->MakeExternal(resource);
5573   // Assert that if CanMakeExternal(), then externalizing actually succeeds.
5574   DCHECK(!CanMakeExternal() || result);
5575   if (result) {
5576     DCHECK(obj->IsExternalString());
5577     isolate->heap()->external_string_table()->AddString(*obj);
5578   }
5579   return result;
5580 }
5581 
5582 
CanMakeExternal()5583 bool v8::String::CanMakeExternal() {
5584   if (!internal::FLAG_clever_optimizations) return false;
5585   i::Handle<i::String> obj = Utils::OpenHandle(this);
5586   i::Isolate* isolate = obj->GetIsolate();
5587 
5588   if (isolate->string_tracker()->IsFreshUnusedString(obj)) return false;
5589   int size = obj->Size();  // Byte size of the original string.
5590   if (size < i::ExternalString::kShortSize) return false;
5591   i::StringShape shape(*obj);
5592   return !shape.IsExternal();
5593 }
5594 
5595 
New(Isolate * isolate)5596 Local<v8::Object> v8::Object::New(Isolate* isolate) {
5597   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
5598   LOG_API(i_isolate, "Object::New");
5599   ENTER_V8(i_isolate);
5600   i::Handle<i::JSObject> obj =
5601       i_isolate->factory()->NewJSObject(i_isolate->object_function());
5602   return Utils::ToLocal(obj);
5603 }
5604 
5605 
New(Isolate * isolate,double value)5606 Local<v8::Value> v8::NumberObject::New(Isolate* isolate, double value) {
5607   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
5608   LOG_API(i_isolate, "NumberObject::New");
5609   ENTER_V8(i_isolate);
5610   i::Handle<i::Object> number = i_isolate->factory()->NewNumber(value);
5611   i::Handle<i::Object> obj =
5612       i::Object::ToObject(i_isolate, number).ToHandleChecked();
5613   return Utils::ToLocal(obj);
5614 }
5615 
5616 
ValueOf() const5617 double v8::NumberObject::ValueOf() const {
5618   i::Handle<i::Object> obj = Utils::OpenHandle(this);
5619   i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
5620   i::Isolate* isolate = jsvalue->GetIsolate();
5621   LOG_API(isolate, "NumberObject::NumberValue");
5622   return jsvalue->value()->Number();
5623 }
5624 
5625 
New(bool value)5626 Local<v8::Value> v8::BooleanObject::New(bool value) {
5627   i::Isolate* isolate = i::Isolate::Current();
5628   LOG_API(isolate, "BooleanObject::New");
5629   ENTER_V8(isolate);
5630   i::Handle<i::Object> boolean(value
5631                                ? isolate->heap()->true_value()
5632                                : isolate->heap()->false_value(),
5633                                isolate);
5634   i::Handle<i::Object> obj =
5635       i::Object::ToObject(isolate, boolean).ToHandleChecked();
5636   return Utils::ToLocal(obj);
5637 }
5638 
5639 
ValueOf() const5640 bool v8::BooleanObject::ValueOf() const {
5641   i::Handle<i::Object> obj = Utils::OpenHandle(this);
5642   i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
5643   i::Isolate* isolate = jsvalue->GetIsolate();
5644   LOG_API(isolate, "BooleanObject::BooleanValue");
5645   return jsvalue->value()->IsTrue();
5646 }
5647 
5648 
New(Handle<String> value)5649 Local<v8::Value> v8::StringObject::New(Handle<String> value) {
5650   i::Handle<i::String> string = Utils::OpenHandle(*value);
5651   i::Isolate* isolate = string->GetIsolate();
5652   LOG_API(isolate, "StringObject::New");
5653   ENTER_V8(isolate);
5654   i::Handle<i::Object> obj =
5655       i::Object::ToObject(isolate, string).ToHandleChecked();
5656   return Utils::ToLocal(obj);
5657 }
5658 
5659 
ValueOf() const5660 Local<v8::String> v8::StringObject::ValueOf() const {
5661   i::Handle<i::Object> obj = Utils::OpenHandle(this);
5662   i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
5663   i::Isolate* isolate = jsvalue->GetIsolate();
5664   LOG_API(isolate, "StringObject::StringValue");
5665   return Utils::ToLocal(
5666       i::Handle<i::String>(i::String::cast(jsvalue->value())));
5667 }
5668 
5669 
New(Isolate * isolate,Handle<Symbol> value)5670 Local<v8::Value> v8::SymbolObject::New(Isolate* isolate, Handle<Symbol> value) {
5671   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
5672   LOG_API(i_isolate, "SymbolObject::New");
5673   ENTER_V8(i_isolate);
5674   i::Handle<i::Object> obj = i::Object::ToObject(
5675       i_isolate, Utils::OpenHandle(*value)).ToHandleChecked();
5676   return Utils::ToLocal(obj);
5677 }
5678 
5679 
ValueOf() const5680 Local<v8::Symbol> v8::SymbolObject::ValueOf() const {
5681   i::Handle<i::Object> obj = Utils::OpenHandle(this);
5682   i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
5683   i::Isolate* isolate = jsvalue->GetIsolate();
5684   LOG_API(isolate, "SymbolObject::SymbolValue");
5685   return Utils::ToLocal(
5686       i::Handle<i::Symbol>(i::Symbol::cast(jsvalue->value())));
5687 }
5688 
5689 
New(Isolate * isolate,double time)5690 Local<v8::Value> v8::Date::New(Isolate* isolate, double time) {
5691   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
5692   LOG_API(i_isolate, "Date::New");
5693   if (std::isnan(time)) {
5694     // Introduce only canonical NaN value into the VM, to avoid signaling NaNs.
5695     time = base::OS::nan_value();
5696   }
5697   ENTER_V8(i_isolate);
5698   EXCEPTION_PREAMBLE(i_isolate);
5699   i::Handle<i::Object> obj;
5700   has_pending_exception = !i::Execution::NewDate(
5701       i_isolate, time).ToHandle(&obj);
5702   EXCEPTION_BAILOUT_CHECK(i_isolate, Local<v8::Value>());
5703   return Utils::ToLocal(obj);
5704 }
5705 
5706 
ValueOf() const5707 double v8::Date::ValueOf() const {
5708   i::Handle<i::Object> obj = Utils::OpenHandle(this);
5709   i::Handle<i::JSDate> jsdate = i::Handle<i::JSDate>::cast(obj);
5710   i::Isolate* isolate = jsdate->GetIsolate();
5711   LOG_API(isolate, "Date::NumberValue");
5712   return jsdate->value()->Number();
5713 }
5714 
5715 
DateTimeConfigurationChangeNotification(Isolate * isolate)5716 void v8::Date::DateTimeConfigurationChangeNotification(Isolate* isolate) {
5717   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
5718   if (!i_isolate->IsInitialized()) return;
5719   ON_BAILOUT(i_isolate, "v8::Date::DateTimeConfigurationChangeNotification()",
5720              return);
5721   LOG_API(i_isolate, "Date::DateTimeConfigurationChangeNotification");
5722   ENTER_V8(i_isolate);
5723 
5724   i_isolate->date_cache()->ResetDateCache();
5725 
5726   if (!i_isolate->eternal_handles()->Exists(
5727           i::EternalHandles::DATE_CACHE_VERSION)) {
5728     return;
5729   }
5730   i::Handle<i::FixedArray> date_cache_version =
5731       i::Handle<i::FixedArray>::cast(i_isolate->eternal_handles()->GetSingleton(
5732           i::EternalHandles::DATE_CACHE_VERSION));
5733   DCHECK_EQ(1, date_cache_version->length());
5734   CHECK(date_cache_version->get(0)->IsSmi());
5735   date_cache_version->set(
5736       0,
5737       i::Smi::FromInt(i::Smi::cast(date_cache_version->get(0))->value() + 1));
5738 }
5739 
5740 
RegExpFlagsToString(RegExp::Flags flags)5741 static i::Handle<i::String> RegExpFlagsToString(RegExp::Flags flags) {
5742   i::Isolate* isolate = i::Isolate::Current();
5743   uint8_t flags_buf[3];
5744   int num_flags = 0;
5745   if ((flags & RegExp::kGlobal) != 0) flags_buf[num_flags++] = 'g';
5746   if ((flags & RegExp::kMultiline) != 0) flags_buf[num_flags++] = 'm';
5747   if ((flags & RegExp::kIgnoreCase) != 0) flags_buf[num_flags++] = 'i';
5748   DCHECK(num_flags <= static_cast<int>(arraysize(flags_buf)));
5749   return isolate->factory()->InternalizeOneByteString(
5750       i::Vector<const uint8_t>(flags_buf, num_flags));
5751 }
5752 
5753 
New(Handle<String> pattern,Flags flags)5754 Local<v8::RegExp> v8::RegExp::New(Handle<String> pattern,
5755                                   Flags flags) {
5756   i::Isolate* isolate = Utils::OpenHandle(*pattern)->GetIsolate();
5757   LOG_API(isolate, "RegExp::New");
5758   ENTER_V8(isolate);
5759   EXCEPTION_PREAMBLE(isolate);
5760   i::Handle<i::JSRegExp> obj;
5761   has_pending_exception = !i::Execution::NewJSRegExp(
5762       Utils::OpenHandle(*pattern),
5763       RegExpFlagsToString(flags)).ToHandle(&obj);
5764   EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::RegExp>());
5765   return Utils::ToLocal(i::Handle<i::JSRegExp>::cast(obj));
5766 }
5767 
5768 
GetSource() const5769 Local<v8::String> v8::RegExp::GetSource() const {
5770   i::Handle<i::JSRegExp> obj = Utils::OpenHandle(this);
5771   return Utils::ToLocal(i::Handle<i::String>(obj->Pattern()));
5772 }
5773 
5774 
5775 // Assert that the static flags cast in GetFlags is valid.
5776 #define REGEXP_FLAG_ASSERT_EQ(api_flag, internal_flag)          \
5777   STATIC_ASSERT(static_cast<int>(v8::RegExp::api_flag) ==       \
5778                 static_cast<int>(i::JSRegExp::internal_flag))
5779 REGEXP_FLAG_ASSERT_EQ(kNone, NONE);
5780 REGEXP_FLAG_ASSERT_EQ(kGlobal, GLOBAL);
5781 REGEXP_FLAG_ASSERT_EQ(kIgnoreCase, IGNORE_CASE);
5782 REGEXP_FLAG_ASSERT_EQ(kMultiline, MULTILINE);
5783 #undef REGEXP_FLAG_ASSERT_EQ
5784 
GetFlags() const5785 v8::RegExp::Flags v8::RegExp::GetFlags() const {
5786   i::Handle<i::JSRegExp> obj = Utils::OpenHandle(this);
5787   return static_cast<RegExp::Flags>(obj->GetFlags().value());
5788 }
5789 
5790 
New(Isolate * isolate,int length)5791 Local<v8::Array> v8::Array::New(Isolate* isolate, int length) {
5792   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
5793   LOG_API(i_isolate, "Array::New");
5794   ENTER_V8(i_isolate);
5795   int real_length = length > 0 ? length : 0;
5796   i::Handle<i::JSArray> obj = i_isolate->factory()->NewJSArray(real_length);
5797   i::Handle<i::Object> length_obj =
5798       i_isolate->factory()->NewNumberFromInt(real_length);
5799   obj->set_length(*length_obj);
5800   return Utils::ToLocal(obj);
5801 }
5802 
5803 
Length() const5804 uint32_t v8::Array::Length() const {
5805   i::Handle<i::JSArray> obj = Utils::OpenHandle(this);
5806   i::Object* length = obj->length();
5807   if (length->IsSmi()) {
5808     return i::Smi::cast(length)->value();
5809   } else {
5810     return static_cast<uint32_t>(length->Number());
5811   }
5812 }
5813 
5814 
CloneElementAt(uint32_t index)5815 Local<Object> Array::CloneElementAt(uint32_t index) {
5816   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
5817   ON_BAILOUT(isolate, "v8::Array::CloneElementAt()", return Local<Object>());
5818   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
5819   if (!self->HasFastObjectElements()) {
5820     return Local<Object>();
5821   }
5822   i::FixedArray* elms = i::FixedArray::cast(self->elements());
5823   i::Object* paragon = elms->get(index);
5824   if (!paragon->IsJSObject()) {
5825     return Local<Object>();
5826   }
5827   i::Handle<i::JSObject> paragon_handle(i::JSObject::cast(paragon));
5828   EXCEPTION_PREAMBLE(isolate);
5829   ENTER_V8(isolate);
5830   i::Handle<i::JSObject> result =
5831       isolate->factory()->CopyJSObject(paragon_handle);
5832   has_pending_exception = result.is_null();
5833   EXCEPTION_BAILOUT_CHECK(isolate, Local<Object>());
5834   return Utils::ToLocal(result);
5835 }
5836 
5837 
IsPromise() const5838 bool Value::IsPromise() const {
5839   i::Handle<i::Object> val = Utils::OpenHandle(this);
5840   if (!val->IsJSObject()) return false;
5841   i::Handle<i::JSObject> obj = i::Handle<i::JSObject>::cast(val);
5842   i::Isolate* isolate = obj->GetIsolate();
5843   LOG_API(isolate, "IsPromise");
5844   ENTER_V8(isolate);
5845   EXCEPTION_PREAMBLE(isolate);
5846   i::Handle<i::Object> argv[] = { obj };
5847   i::Handle<i::Object> b;
5848   has_pending_exception = !i::Execution::Call(
5849       isolate,
5850       isolate->is_promise(),
5851       isolate->factory()->undefined_value(),
5852       arraysize(argv), argv,
5853       false).ToHandle(&b);
5854   EXCEPTION_BAILOUT_CHECK(isolate, false);
5855   return b->BooleanValue();
5856 }
5857 
5858 
New(Isolate * v8_isolate)5859 Local<Promise::Resolver> Promise::Resolver::New(Isolate* v8_isolate) {
5860   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
5861   LOG_API(isolate, "Promise::Resolver::New");
5862   ENTER_V8(isolate);
5863   EXCEPTION_PREAMBLE(isolate);
5864   i::Handle<i::Object> result;
5865   has_pending_exception = !i::Execution::Call(
5866       isolate,
5867       isolate->promise_create(),
5868       isolate->factory()->undefined_value(),
5869       0, NULL,
5870       false).ToHandle(&result);
5871   EXCEPTION_BAILOUT_CHECK(isolate, Local<Promise::Resolver>());
5872   return Local<Promise::Resolver>::Cast(Utils::ToLocal(result));
5873 }
5874 
5875 
GetPromise()5876 Local<Promise> Promise::Resolver::GetPromise() {
5877   i::Handle<i::JSObject> promise = Utils::OpenHandle(this);
5878   return Local<Promise>::Cast(Utils::ToLocal(promise));
5879 }
5880 
5881 
Resolve(Handle<Value> value)5882 void Promise::Resolver::Resolve(Handle<Value> value) {
5883   i::Handle<i::JSObject> promise = Utils::OpenHandle(this);
5884   i::Isolate* isolate = promise->GetIsolate();
5885   LOG_API(isolate, "Promise::Resolver::Resolve");
5886   ENTER_V8(isolate);
5887   EXCEPTION_PREAMBLE(isolate);
5888   i::Handle<i::Object> argv[] = { promise, Utils::OpenHandle(*value) };
5889   has_pending_exception = i::Execution::Call(
5890       isolate,
5891       isolate->promise_resolve(),
5892       isolate->factory()->undefined_value(),
5893       arraysize(argv), argv,
5894       false).is_null();
5895   EXCEPTION_BAILOUT_CHECK(isolate, /* void */ ;);
5896 }
5897 
5898 
Reject(Handle<Value> value)5899 void Promise::Resolver::Reject(Handle<Value> value) {
5900   i::Handle<i::JSObject> promise = Utils::OpenHandle(this);
5901   i::Isolate* isolate = promise->GetIsolate();
5902   LOG_API(isolate, "Promise::Resolver::Reject");
5903   ENTER_V8(isolate);
5904   EXCEPTION_PREAMBLE(isolate);
5905   i::Handle<i::Object> argv[] = { promise, Utils::OpenHandle(*value) };
5906   has_pending_exception = i::Execution::Call(
5907       isolate,
5908       isolate->promise_reject(),
5909       isolate->factory()->undefined_value(),
5910       arraysize(argv), argv,
5911       false).is_null();
5912   EXCEPTION_BAILOUT_CHECK(isolate, /* void */ ;);
5913 }
5914 
5915 
Chain(Handle<Function> handler)5916 Local<Promise> Promise::Chain(Handle<Function> handler) {
5917   i::Handle<i::JSObject> promise = Utils::OpenHandle(this);
5918   i::Isolate* isolate = promise->GetIsolate();
5919   LOG_API(isolate, "Promise::Chain");
5920   ENTER_V8(isolate);
5921   EXCEPTION_PREAMBLE(isolate);
5922   i::Handle<i::Object> argv[] = { Utils::OpenHandle(*handler) };
5923   i::Handle<i::Object> result;
5924   has_pending_exception = !i::Execution::Call(
5925       isolate,
5926       isolate->promise_chain(),
5927       promise,
5928       arraysize(argv), argv,
5929       false).ToHandle(&result);
5930   EXCEPTION_BAILOUT_CHECK(isolate, Local<Promise>());
5931   return Local<Promise>::Cast(Utils::ToLocal(result));
5932 }
5933 
5934 
Catch(Handle<Function> handler)5935 Local<Promise> Promise::Catch(Handle<Function> handler) {
5936   i::Handle<i::JSObject> promise = Utils::OpenHandle(this);
5937   i::Isolate* isolate = promise->GetIsolate();
5938   LOG_API(isolate, "Promise::Catch");
5939   ENTER_V8(isolate);
5940   EXCEPTION_PREAMBLE(isolate);
5941   i::Handle<i::Object> argv[] = { Utils::OpenHandle(*handler) };
5942   i::Handle<i::Object> result;
5943   has_pending_exception = !i::Execution::Call(
5944       isolate,
5945       isolate->promise_catch(),
5946       promise,
5947       arraysize(argv), argv,
5948       false).ToHandle(&result);
5949   EXCEPTION_BAILOUT_CHECK(isolate, Local<Promise>());
5950   return Local<Promise>::Cast(Utils::ToLocal(result));
5951 }
5952 
5953 
Then(Handle<Function> handler)5954 Local<Promise> Promise::Then(Handle<Function> handler) {
5955   i::Handle<i::JSObject> promise = Utils::OpenHandle(this);
5956   i::Isolate* isolate = promise->GetIsolate();
5957   LOG_API(isolate, "Promise::Then");
5958   ENTER_V8(isolate);
5959   EXCEPTION_PREAMBLE(isolate);
5960   i::Handle<i::Object> argv[] = { Utils::OpenHandle(*handler) };
5961   i::Handle<i::Object> result;
5962   has_pending_exception = !i::Execution::Call(
5963       isolate,
5964       isolate->promise_then(),
5965       promise,
5966       arraysize(argv), argv,
5967       false).ToHandle(&result);
5968   EXCEPTION_BAILOUT_CHECK(isolate, Local<Promise>());
5969   return Local<Promise>::Cast(Utils::ToLocal(result));
5970 }
5971 
5972 
IsExternal() const5973 bool v8::ArrayBuffer::IsExternal() const {
5974   return Utils::OpenHandle(this)->is_external();
5975 }
5976 
5977 
Externalize()5978 v8::ArrayBuffer::Contents v8::ArrayBuffer::Externalize() {
5979   i::Handle<i::JSArrayBuffer> obj = Utils::OpenHandle(this);
5980   Utils::ApiCheck(!obj->is_external(),
5981                   "v8::ArrayBuffer::Externalize",
5982                   "ArrayBuffer already externalized");
5983   obj->set_is_external(true);
5984   size_t byte_length = static_cast<size_t>(obj->byte_length()->Number());
5985   Contents contents;
5986   contents.data_ = obj->backing_store();
5987   contents.byte_length_ = byte_length;
5988   return contents;
5989 }
5990 
5991 
Neuter()5992 void v8::ArrayBuffer::Neuter() {
5993   i::Handle<i::JSArrayBuffer> obj = Utils::OpenHandle(this);
5994   i::Isolate* isolate = obj->GetIsolate();
5995   Utils::ApiCheck(obj->is_external(),
5996                   "v8::ArrayBuffer::Neuter",
5997                   "Only externalized ArrayBuffers can be neutered");
5998   LOG_API(obj->GetIsolate(), "v8::ArrayBuffer::Neuter()");
5999   ENTER_V8(isolate);
6000   i::Runtime::NeuterArrayBuffer(obj);
6001 }
6002 
6003 
ByteLength() const6004 size_t v8::ArrayBuffer::ByteLength() const {
6005   i::Handle<i::JSArrayBuffer> obj = Utils::OpenHandle(this);
6006   return static_cast<size_t>(obj->byte_length()->Number());
6007 }
6008 
6009 
New(Isolate * isolate,size_t byte_length)6010 Local<ArrayBuffer> v8::ArrayBuffer::New(Isolate* isolate, size_t byte_length) {
6011   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
6012   LOG_API(i_isolate, "v8::ArrayBuffer::New(size_t)");
6013   ENTER_V8(i_isolate);
6014   i::Handle<i::JSArrayBuffer> obj =
6015       i_isolate->factory()->NewJSArrayBuffer();
6016   i::Runtime::SetupArrayBufferAllocatingData(i_isolate, obj, byte_length);
6017   return Utils::ToLocal(obj);
6018 }
6019 
6020 
New(Isolate * isolate,void * data,size_t byte_length)6021 Local<ArrayBuffer> v8::ArrayBuffer::New(Isolate* isolate, void* data,
6022                                         size_t byte_length) {
6023   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
6024   LOG_API(i_isolate, "v8::ArrayBuffer::New(void*, size_t)");
6025   ENTER_V8(i_isolate);
6026   i::Handle<i::JSArrayBuffer> obj =
6027       i_isolate->factory()->NewJSArrayBuffer();
6028   i::Runtime::SetupArrayBuffer(i_isolate, obj, true, data, byte_length);
6029   return Utils::ToLocal(obj);
6030 }
6031 
6032 
Buffer()6033 Local<ArrayBuffer> v8::ArrayBufferView::Buffer() {
6034   i::Handle<i::JSArrayBufferView> obj = Utils::OpenHandle(this);
6035   i::Handle<i::JSArrayBuffer> buffer;
6036   if (obj->IsJSDataView()) {
6037     i::Handle<i::JSDataView> data_view(i::JSDataView::cast(*obj));
6038     DCHECK(data_view->buffer()->IsJSArrayBuffer());
6039     buffer = i::handle(i::JSArrayBuffer::cast(data_view->buffer()));
6040   } else {
6041     DCHECK(obj->IsJSTypedArray());
6042     buffer = i::JSTypedArray::cast(*obj)->GetBuffer();
6043   }
6044   return Utils::ToLocal(buffer);
6045 }
6046 
6047 
ByteOffset()6048 size_t v8::ArrayBufferView::ByteOffset() {
6049   i::Handle<i::JSArrayBufferView> obj = Utils::OpenHandle(this);
6050   return static_cast<size_t>(obj->byte_offset()->Number());
6051 }
6052 
6053 
ByteLength()6054 size_t v8::ArrayBufferView::ByteLength() {
6055   i::Handle<i::JSArrayBufferView> obj = Utils::OpenHandle(this);
6056   return static_cast<size_t>(obj->byte_length()->Number());
6057 }
6058 
6059 
Length()6060 size_t v8::TypedArray::Length() {
6061   i::Handle<i::JSTypedArray> obj = Utils::OpenHandle(this);
6062   return static_cast<size_t>(obj->length()->Number());
6063 }
6064 
6065 
SetupArrayBufferView(i::Isolate * isolate,i::Handle<i::JSArrayBufferView> obj,i::Handle<i::JSArrayBuffer> buffer,size_t byte_offset,size_t byte_length)6066 static inline void SetupArrayBufferView(
6067     i::Isolate* isolate,
6068     i::Handle<i::JSArrayBufferView> obj,
6069     i::Handle<i::JSArrayBuffer> buffer,
6070     size_t byte_offset,
6071     size_t byte_length) {
6072   DCHECK(byte_offset + byte_length <=
6073          static_cast<size_t>(buffer->byte_length()->Number()));
6074 
6075   obj->set_buffer(*buffer);
6076 
6077   obj->set_weak_next(buffer->weak_first_view());
6078   buffer->set_weak_first_view(*obj);
6079 
6080   i::Handle<i::Object> byte_offset_object =
6081       isolate->factory()->NewNumberFromSize(byte_offset);
6082   obj->set_byte_offset(*byte_offset_object);
6083 
6084   i::Handle<i::Object> byte_length_object =
6085       isolate->factory()->NewNumberFromSize(byte_length);
6086   obj->set_byte_length(*byte_length_object);
6087 }
6088 
6089 template<typename ElementType,
6090          ExternalArrayType array_type,
6091          i::ElementsKind elements_kind>
NewTypedArray(i::Isolate * isolate,Handle<ArrayBuffer> array_buffer,size_t byte_offset,size_t length)6092 i::Handle<i::JSTypedArray> NewTypedArray(
6093     i::Isolate* isolate,
6094     Handle<ArrayBuffer> array_buffer, size_t byte_offset, size_t length) {
6095   i::Handle<i::JSTypedArray> obj =
6096       isolate->factory()->NewJSTypedArray(array_type);
6097   i::Handle<i::JSArrayBuffer> buffer = Utils::OpenHandle(*array_buffer);
6098 
6099   DCHECK(byte_offset % sizeof(ElementType) == 0);
6100 
6101   CHECK(length <= (std::numeric_limits<size_t>::max() / sizeof(ElementType)));
6102   CHECK(length <= static_cast<size_t>(i::Smi::kMaxValue));
6103   size_t byte_length = length * sizeof(ElementType);
6104   SetupArrayBufferView(
6105       isolate, obj, buffer, byte_offset, byte_length);
6106 
6107   i::Handle<i::Object> length_object =
6108       isolate->factory()->NewNumberFromSize(length);
6109   obj->set_length(*length_object);
6110 
6111   i::Handle<i::ExternalArray> elements =
6112       isolate->factory()->NewExternalArray(
6113           static_cast<int>(length), array_type,
6114           static_cast<uint8_t*>(buffer->backing_store()) + byte_offset);
6115   i::Handle<i::Map> map =
6116       i::JSObject::GetElementsTransitionMap(obj, elements_kind);
6117   i::JSObject::SetMapAndElements(obj, map, elements);
6118   return obj;
6119 }
6120 
6121 
6122 #define TYPED_ARRAY_NEW(Type, type, TYPE, ctype, size)                       \
6123   Local<Type##Array> Type##Array::New(Handle<ArrayBuffer> array_buffer,      \
6124                                     size_t byte_offset, size_t length) {     \
6125     i::Isolate* isolate = Utils::OpenHandle(*array_buffer)->GetIsolate();    \
6126     LOG_API(isolate,                                                         \
6127         "v8::" #Type "Array::New(Handle<ArrayBuffer>, size_t, size_t)");     \
6128     ENTER_V8(isolate);                                                       \
6129     if (!Utils::ApiCheck(length <= static_cast<size_t>(i::Smi::kMaxValue),   \
6130             "v8::" #Type "Array::New(Handle<ArrayBuffer>, size_t, size_t)",  \
6131             "length exceeds max allowed value")) {                           \
6132       return Local<Type##Array>();                                          \
6133     }                                                                        \
6134     i::Handle<i::JSTypedArray> obj =                                         \
6135         NewTypedArray<ctype, v8::kExternal##Type##Array,                     \
6136                       i::EXTERNAL_##TYPE##_ELEMENTS>(                        \
6137             isolate, array_buffer, byte_offset, length);                     \
6138     return Utils::ToLocal##Type##Array(obj);                                 \
6139   }
6140 
6141 
TYPED_ARRAYS(TYPED_ARRAY_NEW)6142 TYPED_ARRAYS(TYPED_ARRAY_NEW)
6143 #undef TYPED_ARRAY_NEW
6144 
6145 Local<DataView> DataView::New(Handle<ArrayBuffer> array_buffer,
6146                               size_t byte_offset, size_t byte_length) {
6147   i::Handle<i::JSArrayBuffer> buffer = Utils::OpenHandle(*array_buffer);
6148   i::Isolate* isolate = buffer->GetIsolate();
6149   LOG_API(isolate, "v8::DataView::New(void*, size_t, size_t)");
6150   ENTER_V8(isolate);
6151   i::Handle<i::JSDataView> obj = isolate->factory()->NewJSDataView();
6152   SetupArrayBufferView(
6153       isolate, obj, buffer, byte_offset, byte_length);
6154   return Utils::ToLocal(obj);
6155 }
6156 
6157 
New(Isolate * isolate,Local<String> name)6158 Local<Symbol> v8::Symbol::New(Isolate* isolate, Local<String> name) {
6159   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
6160   LOG_API(i_isolate, "Symbol::New()");
6161   ENTER_V8(i_isolate);
6162   i::Handle<i::Symbol> result = i_isolate->factory()->NewSymbol();
6163   if (!name.IsEmpty()) result->set_name(*Utils::OpenHandle(*name));
6164   return Utils::ToLocal(result);
6165 }
6166 
6167 
SymbolFor(i::Isolate * isolate,i::Handle<i::String> name,i::Handle<i::String> part)6168 static i::Handle<i::Symbol> SymbolFor(i::Isolate* isolate,
6169                                       i::Handle<i::String> name,
6170                                       i::Handle<i::String> part) {
6171   i::Handle<i::JSObject> registry = isolate->GetSymbolRegistry();
6172   i::Handle<i::JSObject> symbols =
6173       i::Handle<i::JSObject>::cast(
6174           i::Object::GetPropertyOrElement(registry, part).ToHandleChecked());
6175   i::Handle<i::Object> symbol =
6176       i::Object::GetPropertyOrElement(symbols, name).ToHandleChecked();
6177   if (!symbol->IsSymbol()) {
6178     DCHECK(symbol->IsUndefined());
6179     symbol = isolate->factory()->NewSymbol();
6180     i::Handle<i::Symbol>::cast(symbol)->set_name(*name);
6181     i::JSObject::SetProperty(symbols, name, symbol, i::STRICT).Assert();
6182   }
6183   return i::Handle<i::Symbol>::cast(symbol);
6184 }
6185 
6186 
For(Isolate * isolate,Local<String> name)6187 Local<Symbol> v8::Symbol::For(Isolate* isolate, Local<String> name) {
6188   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
6189   i::Handle<i::String> i_name = Utils::OpenHandle(*name);
6190   i::Handle<i::String> part = i_isolate->factory()->for_string();
6191   return Utils::ToLocal(SymbolFor(i_isolate, i_name, part));
6192 }
6193 
6194 
ForApi(Isolate * isolate,Local<String> name)6195 Local<Symbol> v8::Symbol::ForApi(Isolate* isolate, Local<String> name) {
6196   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
6197   i::Handle<i::String> i_name = Utils::OpenHandle(*name);
6198   i::Handle<i::String> part = i_isolate->factory()->for_api_string();
6199   return Utils::ToLocal(SymbolFor(i_isolate, i_name, part));
6200 }
6201 
6202 
GetWellKnownSymbol(Isolate * isolate,const char * name)6203 static Local<Symbol> GetWellKnownSymbol(Isolate* isolate, const char* name) {
6204   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
6205   i::Handle<i::String> i_name =
6206       Utils::OpenHandle(*String::NewFromUtf8(isolate, name));
6207   i::Handle<i::String> part = i_isolate->factory()->for_intern_string();
6208   return Utils::ToLocal(SymbolFor(i_isolate, i_name, part));
6209 }
6210 
6211 
GetIterator(Isolate * isolate)6212 Local<Symbol> v8::Symbol::GetIterator(Isolate* isolate) {
6213   return GetWellKnownSymbol(isolate, "Symbol.iterator");
6214 }
6215 
6216 
GetUnscopables(Isolate * isolate)6217 Local<Symbol> v8::Symbol::GetUnscopables(Isolate* isolate) {
6218   return GetWellKnownSymbol(isolate, "Symbol.unscopables");
6219 }
6220 
6221 
New(Isolate * isolate,Local<String> name)6222 Local<Private> v8::Private::New(Isolate* isolate, Local<String> name) {
6223   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
6224   LOG_API(i_isolate, "Private::New()");
6225   ENTER_V8(i_isolate);
6226   i::Handle<i::Symbol> symbol = i_isolate->factory()->NewPrivateSymbol();
6227   if (!name.IsEmpty()) symbol->set_name(*Utils::OpenHandle(*name));
6228   Local<Symbol> result = Utils::ToLocal(symbol);
6229   return v8::Handle<Private>(reinterpret_cast<Private*>(*result));
6230 }
6231 
6232 
ForApi(Isolate * isolate,Local<String> name)6233 Local<Private> v8::Private::ForApi(Isolate* isolate, Local<String> name) {
6234   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
6235   i::Handle<i::String> i_name = Utils::OpenHandle(*name);
6236   i::Handle<i::JSObject> registry = i_isolate->GetSymbolRegistry();
6237   i::Handle<i::String> part = i_isolate->factory()->private_api_string();
6238   i::Handle<i::JSObject> privates =
6239       i::Handle<i::JSObject>::cast(
6240           i::Object::GetPropertyOrElement(registry, part).ToHandleChecked());
6241   i::Handle<i::Object> symbol =
6242       i::Object::GetPropertyOrElement(privates, i_name).ToHandleChecked();
6243   if (!symbol->IsSymbol()) {
6244     DCHECK(symbol->IsUndefined());
6245     symbol = i_isolate->factory()->NewPrivateSymbol();
6246     i::Handle<i::Symbol>::cast(symbol)->set_name(*i_name);
6247     i::JSObject::SetProperty(privates, i_name, symbol, i::STRICT).Assert();
6248   }
6249   Local<Symbol> result = Utils::ToLocal(i::Handle<i::Symbol>::cast(symbol));
6250   return v8::Handle<Private>(reinterpret_cast<Private*>(*result));
6251 }
6252 
6253 
New(Isolate * isolate,double value)6254 Local<Number> v8::Number::New(Isolate* isolate, double value) {
6255   i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
6256   DCHECK(internal_isolate->IsInitialized());
6257   if (std::isnan(value)) {
6258     // Introduce only canonical NaN value into the VM, to avoid signaling NaNs.
6259     value = base::OS::nan_value();
6260   }
6261   ENTER_V8(internal_isolate);
6262   i::Handle<i::Object> result = internal_isolate->factory()->NewNumber(value);
6263   return Utils::NumberToLocal(result);
6264 }
6265 
6266 
New(Isolate * isolate,int32_t value)6267 Local<Integer> v8::Integer::New(Isolate* isolate, int32_t value) {
6268   i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
6269   DCHECK(internal_isolate->IsInitialized());
6270   if (i::Smi::IsValid(value)) {
6271     return Utils::IntegerToLocal(i::Handle<i::Object>(i::Smi::FromInt(value),
6272                                                       internal_isolate));
6273   }
6274   ENTER_V8(internal_isolate);
6275   i::Handle<i::Object> result = internal_isolate->factory()->NewNumber(value);
6276   return Utils::IntegerToLocal(result);
6277 }
6278 
6279 
NewFromUnsigned(Isolate * isolate,uint32_t value)6280 Local<Integer> v8::Integer::NewFromUnsigned(Isolate* isolate, uint32_t value) {
6281   i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
6282   DCHECK(internal_isolate->IsInitialized());
6283   bool fits_into_int32_t = (value & (1 << 31)) == 0;
6284   if (fits_into_int32_t) {
6285     return Integer::New(isolate, static_cast<int32_t>(value));
6286   }
6287   ENTER_V8(internal_isolate);
6288   i::Handle<i::Object> result = internal_isolate->factory()->NewNumber(value);
6289   return Utils::IntegerToLocal(result);
6290 }
6291 
6292 
AddMessageListener(MessageCallback that,Handle<Value> data)6293 bool V8::AddMessageListener(MessageCallback that, Handle<Value> data) {
6294   i::Isolate* isolate = i::Isolate::Current();
6295   ON_BAILOUT(isolate, "v8::V8::AddMessageListener()", return false);
6296   ENTER_V8(isolate);
6297   i::HandleScope scope(isolate);
6298   NeanderArray listeners(isolate->factory()->message_listeners());
6299   NeanderObject obj(isolate, 2);
6300   obj.set(0, *isolate->factory()->NewForeign(FUNCTION_ADDR(that)));
6301   obj.set(1, data.IsEmpty() ? isolate->heap()->undefined_value()
6302           : *Utils::OpenHandle(*data));
6303   listeners.add(obj.value());
6304   return true;
6305 }
6306 
6307 
RemoveMessageListeners(MessageCallback that)6308 void V8::RemoveMessageListeners(MessageCallback that) {
6309   i::Isolate* isolate = i::Isolate::Current();
6310   ON_BAILOUT(isolate, "v8::V8::RemoveMessageListeners()", return);
6311   ENTER_V8(isolate);
6312   i::HandleScope scope(isolate);
6313   NeanderArray listeners(isolate->factory()->message_listeners());
6314   for (int i = 0; i < listeners.length(); i++) {
6315     if (listeners.get(i)->IsUndefined()) continue;  // skip deleted ones
6316 
6317     NeanderObject listener(i::JSObject::cast(listeners.get(i)));
6318     i::Handle<i::Foreign> callback_obj(i::Foreign::cast(listener.get(0)));
6319     if (callback_obj->foreign_address() == FUNCTION_ADDR(that)) {
6320       listeners.set(i, isolate->heap()->undefined_value());
6321     }
6322   }
6323 }
6324 
6325 
SetCaptureStackTraceForUncaughtExceptions(bool capture,int frame_limit,StackTrace::StackTraceOptions options)6326 void V8::SetCaptureStackTraceForUncaughtExceptions(
6327     bool capture,
6328     int frame_limit,
6329     StackTrace::StackTraceOptions options) {
6330   i::Isolate::Current()->SetCaptureStackTraceForUncaughtExceptions(
6331       capture,
6332       frame_limit,
6333       options);
6334 }
6335 
6336 
SetFailedAccessCheckCallbackFunction(FailedAccessCheckCallback callback)6337 void V8::SetFailedAccessCheckCallbackFunction(
6338     FailedAccessCheckCallback callback) {
6339   i::Isolate* isolate = i::Isolate::Current();
6340   isolate->SetFailedAccessCheckCallback(callback);
6341 }
6342 
6343 
CollectAllGarbage(const char * gc_reason)6344 void Isolate::CollectAllGarbage(const char* gc_reason) {
6345   reinterpret_cast<i::Isolate*>(this)->heap()->CollectAllGarbage(
6346       i::Heap::kNoGCFlags, gc_reason);
6347 }
6348 
6349 
GetHeapProfiler()6350 HeapProfiler* Isolate::GetHeapProfiler() {
6351   i::HeapProfiler* heap_profiler =
6352       reinterpret_cast<i::Isolate*>(this)->heap_profiler();
6353   return reinterpret_cast<HeapProfiler*>(heap_profiler);
6354 }
6355 
6356 
GetCpuProfiler()6357 CpuProfiler* Isolate::GetCpuProfiler() {
6358   i::CpuProfiler* cpu_profiler =
6359       reinterpret_cast<i::Isolate*>(this)->cpu_profiler();
6360   return reinterpret_cast<CpuProfiler*>(cpu_profiler);
6361 }
6362 
6363 
InContext()6364 bool Isolate::InContext() {
6365   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6366   return isolate->context() != NULL;
6367 }
6368 
6369 
GetCurrentContext()6370 v8::Local<v8::Context> Isolate::GetCurrentContext() {
6371   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6372   i::Context* context = isolate->context();
6373   if (context == NULL) return Local<Context>();
6374   i::Context* native_context = context->native_context();
6375   if (native_context == NULL) return Local<Context>();
6376   return Utils::ToLocal(i::Handle<i::Context>(native_context));
6377 }
6378 
6379 
GetCallingContext()6380 v8::Local<v8::Context> Isolate::GetCallingContext() {
6381   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6382   i::Handle<i::Object> calling = isolate->GetCallingNativeContext();
6383   if (calling.is_null()) return Local<Context>();
6384   return Utils::ToLocal(i::Handle<i::Context>::cast(calling));
6385 }
6386 
6387 
GetEnteredContext()6388 v8::Local<v8::Context> Isolate::GetEnteredContext() {
6389   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6390   i::Handle<i::Object> last =
6391       isolate->handle_scope_implementer()->LastEnteredContext();
6392   if (last.is_null()) return Local<Context>();
6393   return Utils::ToLocal(i::Handle<i::Context>::cast(last));
6394 }
6395 
6396 
ThrowException(v8::Local<v8::Value> value)6397 v8::Local<Value> Isolate::ThrowException(v8::Local<v8::Value> value) {
6398   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6399   ENTER_V8(isolate);
6400   // If we're passed an empty handle, we throw an undefined exception
6401   // to deal more gracefully with out of memory situations.
6402   if (value.IsEmpty()) {
6403     isolate->ScheduleThrow(isolate->heap()->undefined_value());
6404   } else {
6405     isolate->ScheduleThrow(*Utils::OpenHandle(*value));
6406   }
6407   return v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
6408 }
6409 
6410 
SetObjectGroupId(internal::Object ** object,UniqueId id)6411 void Isolate::SetObjectGroupId(internal::Object** object, UniqueId id) {
6412   i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(this);
6413   internal_isolate->global_handles()->SetObjectGroupId(
6414       v8::internal::Handle<v8::internal::Object>(object).location(),
6415       id);
6416 }
6417 
6418 
SetReferenceFromGroup(UniqueId id,internal::Object ** object)6419 void Isolate::SetReferenceFromGroup(UniqueId id, internal::Object** object) {
6420   i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(this);
6421   internal_isolate->global_handles()->SetReferenceFromGroup(
6422       id,
6423       v8::internal::Handle<v8::internal::Object>(object).location());
6424 }
6425 
6426 
SetReference(internal::Object ** parent,internal::Object ** child)6427 void Isolate::SetReference(internal::Object** parent,
6428                            internal::Object** child) {
6429   i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(this);
6430   i::Object** parent_location =
6431       v8::internal::Handle<v8::internal::Object>(parent).location();
6432   internal_isolate->global_handles()->SetReference(
6433       reinterpret_cast<i::HeapObject**>(parent_location),
6434       v8::internal::Handle<v8::internal::Object>(child).location());
6435 }
6436 
6437 
AddGCPrologueCallback(GCPrologueCallback callback,GCType gc_type)6438 void Isolate::AddGCPrologueCallback(GCPrologueCallback callback,
6439                                     GCType gc_type) {
6440   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6441   isolate->heap()->AddGCPrologueCallback(callback, gc_type);
6442 }
6443 
6444 
RemoveGCPrologueCallback(GCPrologueCallback callback)6445 void Isolate::RemoveGCPrologueCallback(GCPrologueCallback callback) {
6446   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6447   isolate->heap()->RemoveGCPrologueCallback(callback);
6448 }
6449 
6450 
AddGCEpilogueCallback(GCEpilogueCallback callback,GCType gc_type)6451 void Isolate::AddGCEpilogueCallback(GCEpilogueCallback callback,
6452                                     GCType gc_type) {
6453   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6454   isolate->heap()->AddGCEpilogueCallback(callback, gc_type);
6455 }
6456 
6457 
RemoveGCEpilogueCallback(GCEpilogueCallback callback)6458 void Isolate::RemoveGCEpilogueCallback(GCEpilogueCallback callback) {
6459   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6460   isolate->heap()->RemoveGCEpilogueCallback(callback);
6461 }
6462 
6463 
AddGCPrologueCallback(GCPrologueCallback callback,GCType gc_type)6464 void V8::AddGCPrologueCallback(GCPrologueCallback callback, GCType gc_type) {
6465   i::Isolate* isolate = i::Isolate::Current();
6466   isolate->heap()->AddGCPrologueCallback(
6467       reinterpret_cast<v8::Isolate::GCPrologueCallback>(callback),
6468       gc_type,
6469       false);
6470 }
6471 
6472 
RemoveGCPrologueCallback(GCPrologueCallback callback)6473 void V8::RemoveGCPrologueCallback(GCPrologueCallback callback) {
6474   i::Isolate* isolate = i::Isolate::Current();
6475   isolate->heap()->RemoveGCPrologueCallback(
6476       reinterpret_cast<v8::Isolate::GCPrologueCallback>(callback));
6477 }
6478 
6479 
AddGCEpilogueCallback(GCEpilogueCallback callback,GCType gc_type)6480 void V8::AddGCEpilogueCallback(GCEpilogueCallback callback, GCType gc_type) {
6481   i::Isolate* isolate = i::Isolate::Current();
6482   isolate->heap()->AddGCEpilogueCallback(
6483       reinterpret_cast<v8::Isolate::GCEpilogueCallback>(callback),
6484       gc_type,
6485       false);
6486 }
6487 
6488 
RemoveGCEpilogueCallback(GCEpilogueCallback callback)6489 void V8::RemoveGCEpilogueCallback(GCEpilogueCallback callback) {
6490   i::Isolate* isolate = i::Isolate::Current();
6491   isolate->heap()->RemoveGCEpilogueCallback(
6492       reinterpret_cast<v8::Isolate::GCEpilogueCallback>(callback));
6493 }
6494 
6495 
AddMemoryAllocationCallback(MemoryAllocationCallback callback,ObjectSpace space,AllocationAction action)6496 void V8::AddMemoryAllocationCallback(MemoryAllocationCallback callback,
6497                                      ObjectSpace space,
6498                                      AllocationAction action) {
6499   i::Isolate* isolate = i::Isolate::Current();
6500   isolate->memory_allocator()->AddMemoryAllocationCallback(
6501       callback, space, action);
6502 }
6503 
6504 
RemoveMemoryAllocationCallback(MemoryAllocationCallback callback)6505 void V8::RemoveMemoryAllocationCallback(MemoryAllocationCallback callback) {
6506   i::Isolate* isolate = i::Isolate::Current();
6507   isolate->memory_allocator()->RemoveMemoryAllocationCallback(
6508       callback);
6509 }
6510 
6511 
TerminateExecution(Isolate * isolate)6512 void V8::TerminateExecution(Isolate* isolate) {
6513   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
6514   i_isolate->stack_guard()->RequestTerminateExecution();
6515 }
6516 
6517 
IsExecutionTerminating(Isolate * isolate)6518 bool V8::IsExecutionTerminating(Isolate* isolate) {
6519   i::Isolate* i_isolate = isolate != NULL ?
6520       reinterpret_cast<i::Isolate*>(isolate) : i::Isolate::Current();
6521   return IsExecutionTerminatingCheck(i_isolate);
6522 }
6523 
6524 
CancelTerminateExecution(Isolate * isolate)6525 void V8::CancelTerminateExecution(Isolate* isolate) {
6526   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
6527   i_isolate->stack_guard()->ClearTerminateExecution();
6528   i_isolate->CancelTerminateExecution();
6529 }
6530 
6531 
RequestInterrupt(InterruptCallback callback,void * data)6532 void Isolate::RequestInterrupt(InterruptCallback callback, void* data) {
6533   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(this);
6534   i_isolate->set_api_interrupt_callback(callback);
6535   i_isolate->set_api_interrupt_callback_data(data);
6536   i_isolate->stack_guard()->RequestApiInterrupt();
6537 }
6538 
6539 
ClearInterrupt()6540 void Isolate::ClearInterrupt() {
6541   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(this);
6542   i_isolate->stack_guard()->ClearApiInterrupt();
6543   i_isolate->set_api_interrupt_callback(NULL);
6544   i_isolate->set_api_interrupt_callback_data(NULL);
6545 }
6546 
6547 
RequestGarbageCollectionForTesting(GarbageCollectionType type)6548 void Isolate::RequestGarbageCollectionForTesting(GarbageCollectionType type) {
6549   CHECK(i::FLAG_expose_gc);
6550   if (type == kMinorGarbageCollection) {
6551     reinterpret_cast<i::Isolate*>(this)->heap()->CollectGarbage(
6552         i::NEW_SPACE, "Isolate::RequestGarbageCollection",
6553         kGCCallbackFlagForced);
6554   } else {
6555     DCHECK_EQ(kFullGarbageCollection, type);
6556     reinterpret_cast<i::Isolate*>(this)->heap()->CollectAllGarbage(
6557         i::Heap::kAbortIncrementalMarkingMask,
6558         "Isolate::RequestGarbageCollection", kGCCallbackFlagForced);
6559   }
6560 }
6561 
6562 
GetCurrent()6563 Isolate* Isolate::GetCurrent() {
6564   i::Isolate* isolate = i::Isolate::Current();
6565   return reinterpret_cast<Isolate*>(isolate);
6566 }
6567 
6568 
New(const Isolate::CreateParams & params)6569 Isolate* Isolate::New(const Isolate::CreateParams& params) {
6570   i::Isolate* isolate = new i::Isolate();
6571   Isolate* v8_isolate = reinterpret_cast<Isolate*>(isolate);
6572   if (params.entry_hook) {
6573     isolate->set_function_entry_hook(params.entry_hook);
6574   }
6575   if (params.code_event_handler) {
6576     isolate->InitializeLoggingAndCounters();
6577     isolate->logger()->SetCodeEventHandler(kJitCodeEventDefault,
6578                                            params.code_event_handler);
6579   }
6580   SetResourceConstraints(isolate, params.constraints);
6581   if (params.enable_serializer) {
6582     isolate->enable_serializer();
6583   }
6584   // TODO(jochen): Once we got rid of Isolate::Current(), we can remove this.
6585   Isolate::Scope isolate_scope(v8_isolate);
6586   if (params.entry_hook || !i::Snapshot::Initialize(isolate)) {
6587     // If the isolate has a function entry hook, it needs to re-build all its
6588     // code stubs with entry hooks embedded, so don't deserialize a snapshot.
6589     isolate->Init(NULL);
6590   }
6591   return v8_isolate;
6592 }
6593 
6594 
Dispose()6595 void Isolate::Dispose() {
6596   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6597   if (!Utils::ApiCheck(!isolate->IsInUse(),
6598                        "v8::Isolate::Dispose()",
6599                        "Disposing the isolate that is entered by a thread.")) {
6600     return;
6601   }
6602   isolate->TearDown();
6603 }
6604 
6605 
Enter()6606 void Isolate::Enter() {
6607   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6608   isolate->Enter();
6609 }
6610 
6611 
Exit()6612 void Isolate::Exit() {
6613   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6614   isolate->Exit();
6615 }
6616 
6617 
DisallowJavascriptExecutionScope(Isolate * isolate,Isolate::DisallowJavascriptExecutionScope::OnFailure on_failure)6618 Isolate::DisallowJavascriptExecutionScope::DisallowJavascriptExecutionScope(
6619     Isolate* isolate,
6620     Isolate::DisallowJavascriptExecutionScope::OnFailure on_failure)
6621     : on_failure_(on_failure) {
6622   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
6623   if (on_failure_ == CRASH_ON_FAILURE) {
6624     internal_ = reinterpret_cast<void*>(
6625         new i::DisallowJavascriptExecution(i_isolate));
6626   } else {
6627     DCHECK_EQ(THROW_ON_FAILURE, on_failure);
6628     internal_ = reinterpret_cast<void*>(
6629         new i::ThrowOnJavascriptExecution(i_isolate));
6630   }
6631 }
6632 
6633 
~DisallowJavascriptExecutionScope()6634 Isolate::DisallowJavascriptExecutionScope::~DisallowJavascriptExecutionScope() {
6635   if (on_failure_ == CRASH_ON_FAILURE) {
6636     delete reinterpret_cast<i::DisallowJavascriptExecution*>(internal_);
6637   } else {
6638     delete reinterpret_cast<i::ThrowOnJavascriptExecution*>(internal_);
6639   }
6640 }
6641 
6642 
AllowJavascriptExecutionScope(Isolate * isolate)6643 Isolate::AllowJavascriptExecutionScope::AllowJavascriptExecutionScope(
6644     Isolate* isolate) {
6645   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
6646   internal_assert_ = reinterpret_cast<void*>(
6647       new i::AllowJavascriptExecution(i_isolate));
6648   internal_throws_ = reinterpret_cast<void*>(
6649       new i::NoThrowOnJavascriptExecution(i_isolate));
6650 }
6651 
6652 
~AllowJavascriptExecutionScope()6653 Isolate::AllowJavascriptExecutionScope::~AllowJavascriptExecutionScope() {
6654   delete reinterpret_cast<i::AllowJavascriptExecution*>(internal_assert_);
6655   delete reinterpret_cast<i::NoThrowOnJavascriptExecution*>(internal_throws_);
6656 }
6657 
6658 
SuppressMicrotaskExecutionScope(Isolate * isolate)6659 Isolate::SuppressMicrotaskExecutionScope::SuppressMicrotaskExecutionScope(
6660     Isolate* isolate)
6661     : isolate_(reinterpret_cast<i::Isolate*>(isolate)) {
6662   isolate_->handle_scope_implementer()->IncrementCallDepth();
6663 }
6664 
6665 
~SuppressMicrotaskExecutionScope()6666 Isolate::SuppressMicrotaskExecutionScope::~SuppressMicrotaskExecutionScope() {
6667   isolate_->handle_scope_implementer()->DecrementCallDepth();
6668 }
6669 
6670 
GetHeapStatistics(HeapStatistics * heap_statistics)6671 void Isolate::GetHeapStatistics(HeapStatistics* heap_statistics) {
6672   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6673   if (!isolate->IsInitialized()) {
6674     heap_statistics->total_heap_size_ = 0;
6675     heap_statistics->total_heap_size_executable_ = 0;
6676     heap_statistics->total_physical_size_ = 0;
6677     heap_statistics->used_heap_size_ = 0;
6678     heap_statistics->heap_size_limit_ = 0;
6679     return;
6680   }
6681   i::Heap* heap = isolate->heap();
6682   heap_statistics->total_heap_size_ = heap->CommittedMemory();
6683   heap_statistics->total_heap_size_executable_ =
6684       heap->CommittedMemoryExecutable();
6685   heap_statistics->total_physical_size_ = heap->CommittedPhysicalMemory();
6686   heap_statistics->used_heap_size_ = heap->SizeOfObjects();
6687   heap_statistics->heap_size_limit_ = heap->MaxReserved();
6688 }
6689 
6690 
SetEventLogger(LogEventCallback that)6691 void Isolate::SetEventLogger(LogEventCallback that) {
6692   // Do not overwrite the event logger if we want to log explicitly.
6693   if (i::FLAG_log_timer_events) return;
6694   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6695   isolate->set_event_logger(that);
6696 }
6697 
6698 
AddCallCompletedCallback(CallCompletedCallback callback)6699 void Isolate::AddCallCompletedCallback(CallCompletedCallback callback) {
6700   if (callback == NULL) return;
6701   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6702   isolate->AddCallCompletedCallback(callback);
6703 }
6704 
6705 
RemoveCallCompletedCallback(CallCompletedCallback callback)6706 void Isolate::RemoveCallCompletedCallback(CallCompletedCallback callback) {
6707   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6708   isolate->RemoveCallCompletedCallback(callback);
6709 }
6710 
6711 
RunMicrotasks()6712 void Isolate::RunMicrotasks() {
6713   reinterpret_cast<i::Isolate*>(this)->RunMicrotasks();
6714 }
6715 
6716 
EnqueueMicrotask(Handle<Function> microtask)6717 void Isolate::EnqueueMicrotask(Handle<Function> microtask) {
6718   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6719   isolate->EnqueueMicrotask(Utils::OpenHandle(*microtask));
6720 }
6721 
6722 
EnqueueMicrotask(MicrotaskCallback microtask,void * data)6723 void Isolate::EnqueueMicrotask(MicrotaskCallback microtask, void* data) {
6724   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6725   i::HandleScope scope(isolate);
6726   i::Handle<i::CallHandlerInfo> callback_info =
6727       i::Handle<i::CallHandlerInfo>::cast(
6728           isolate->factory()->NewStruct(i::CALL_HANDLER_INFO_TYPE));
6729   SET_FIELD_WRAPPED(callback_info, set_callback, microtask);
6730   SET_FIELD_WRAPPED(callback_info, set_data, data);
6731   isolate->EnqueueMicrotask(callback_info);
6732 }
6733 
6734 
SetAutorunMicrotasks(bool autorun)6735 void Isolate::SetAutorunMicrotasks(bool autorun) {
6736   reinterpret_cast<i::Isolate*>(this)->set_autorun_microtasks(autorun);
6737 }
6738 
6739 
WillAutorunMicrotasks() const6740 bool Isolate::WillAutorunMicrotasks() const {
6741   return reinterpret_cast<const i::Isolate*>(this)->autorun_microtasks();
6742 }
6743 
6744 
SetUseCounterCallback(UseCounterCallback callback)6745 void Isolate::SetUseCounterCallback(UseCounterCallback callback) {
6746   reinterpret_cast<i::Isolate*>(this)->SetUseCounterCallback(callback);
6747 }
6748 
6749 
SetCounterFunction(CounterLookupCallback callback)6750 void Isolate::SetCounterFunction(CounterLookupCallback callback) {
6751   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6752   isolate->stats_table()->SetCounterFunction(callback);
6753   isolate->InitializeLoggingAndCounters();
6754   isolate->counters()->ResetCounters();
6755 }
6756 
6757 
SetCreateHistogramFunction(CreateHistogramCallback callback)6758 void Isolate::SetCreateHistogramFunction(CreateHistogramCallback callback) {
6759   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6760   isolate->stats_table()->SetCreateHistogramFunction(callback);
6761   isolate->InitializeLoggingAndCounters();
6762   isolate->counters()->ResetHistograms();
6763 }
6764 
6765 
SetAddHistogramSampleFunction(AddHistogramSampleCallback callback)6766 void Isolate::SetAddHistogramSampleFunction(
6767     AddHistogramSampleCallback callback) {
6768   reinterpret_cast<i::Isolate*>(this)
6769       ->stats_table()
6770       ->SetAddHistogramSampleFunction(callback);
6771 }
6772 
6773 
IdleNotification(int idle_time_in_ms)6774 bool v8::Isolate::IdleNotification(int idle_time_in_ms) {
6775   // Returning true tells the caller that it need not
6776   // continue to call IdleNotification.
6777   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6778   if (!i::FLAG_use_idle_notification) return true;
6779   return isolate->heap()->IdleNotification(idle_time_in_ms);
6780 }
6781 
6782 
LowMemoryNotification()6783 void v8::Isolate::LowMemoryNotification() {
6784   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6785   {
6786     i::HistogramTimerScope idle_notification_scope(
6787         isolate->counters()->gc_low_memory_notification());
6788     isolate->heap()->CollectAllAvailableGarbage("low memory notification");
6789   }
6790 }
6791 
6792 
ContextDisposedNotification()6793 int v8::Isolate::ContextDisposedNotification() {
6794   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6795   return isolate->heap()->NotifyContextDisposed();
6796 }
6797 
6798 
SetJitCodeEventHandler(JitCodeEventOptions options,JitCodeEventHandler event_handler)6799 void v8::Isolate::SetJitCodeEventHandler(JitCodeEventOptions options,
6800                                          JitCodeEventHandler event_handler) {
6801   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6802   // Ensure that logging is initialized for our isolate.
6803   isolate->InitializeLoggingAndCounters();
6804   isolate->logger()->SetCodeEventHandler(options, event_handler);
6805 }
6806 
6807 
SetStackLimit(uintptr_t stack_limit)6808 void v8::Isolate::SetStackLimit(uintptr_t stack_limit) {
6809   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6810   CHECK(stack_limit);
6811   isolate->stack_guard()->SetStackLimit(stack_limit);
6812 }
6813 
6814 
Utf8Value(v8::Handle<v8::Value> obj)6815 String::Utf8Value::Utf8Value(v8::Handle<v8::Value> obj)
6816     : str_(NULL), length_(0) {
6817   i::Isolate* isolate = i::Isolate::Current();
6818   if (obj.IsEmpty()) return;
6819   ENTER_V8(isolate);
6820   i::HandleScope scope(isolate);
6821   TryCatch try_catch;
6822   Handle<String> str = obj->ToString();
6823   if (str.IsEmpty()) return;
6824   i::Handle<i::String> i_str = Utils::OpenHandle(*str);
6825   length_ = v8::Utf8Length(*i_str, isolate);
6826   str_ = i::NewArray<char>(length_ + 1);
6827   str->WriteUtf8(str_);
6828 }
6829 
6830 
~Utf8Value()6831 String::Utf8Value::~Utf8Value() {
6832   i::DeleteArray(str_);
6833 }
6834 
6835 
Value(v8::Handle<v8::Value> obj)6836 String::Value::Value(v8::Handle<v8::Value> obj)
6837     : str_(NULL), length_(0) {
6838   i::Isolate* isolate = i::Isolate::Current();
6839   if (obj.IsEmpty()) return;
6840   ENTER_V8(isolate);
6841   i::HandleScope scope(isolate);
6842   TryCatch try_catch;
6843   Handle<String> str = obj->ToString();
6844   if (str.IsEmpty()) return;
6845   length_ = str->Length();
6846   str_ = i::NewArray<uint16_t>(length_ + 1);
6847   str->Write(str_);
6848 }
6849 
6850 
~Value()6851 String::Value::~Value() {
6852   i::DeleteArray(str_);
6853 }
6854 
6855 
6856 #define DEFINE_ERROR(NAME)                                                    \
6857   Local<Value> Exception::NAME(v8::Handle<v8::String> raw_message) {          \
6858     i::Isolate* isolate = i::Isolate::Current();                              \
6859     LOG_API(isolate, #NAME);                                                  \
6860     ON_BAILOUT(isolate, "v8::Exception::" #NAME "()", return Local<Value>()); \
6861     ENTER_V8(isolate);                                                        \
6862     i::Object* error;                                                         \
6863     {                                                                         \
6864       i::HandleScope scope(isolate);                                          \
6865       i::Handle<i::String> message = Utils::OpenHandle(*raw_message);         \
6866       i::Handle<i::Object> result;                                            \
6867       EXCEPTION_PREAMBLE(isolate);                                            \
6868       i::MaybeHandle<i::Object> maybe_result =                                \
6869           isolate->factory()->New##NAME(message);                             \
6870       has_pending_exception = !maybe_result.ToHandle(&result);                \
6871       /* TODO(yangguo): crbug/403509. Return empty handle instead. */         \
6872       EXCEPTION_BAILOUT_CHECK(                                                \
6873           isolate, v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate)));   \
6874       error = *result;                                                        \
6875     }                                                                         \
6876     i::Handle<i::Object> result(error, isolate);                              \
6877     return Utils::ToLocal(result);                                            \
6878   }
6879 
6880 DEFINE_ERROR(RangeError)
DEFINE_ERROR(ReferenceError)6881 DEFINE_ERROR(ReferenceError)
6882 DEFINE_ERROR(SyntaxError)
6883 DEFINE_ERROR(TypeError)
6884 DEFINE_ERROR(Error)
6885 
6886 #undef DEFINE_ERROR
6887 
6888 
6889 // --- D e b u g   S u p p o r t ---
6890 
6891 bool Debug::SetDebugEventListener(EventCallback that, Handle<Value> data) {
6892   i::Isolate* isolate = i::Isolate::Current();
6893   ON_BAILOUT(isolate, "v8::Debug::SetDebugEventListener()", return false);
6894   ENTER_V8(isolate);
6895   i::HandleScope scope(isolate);
6896   i::Handle<i::Object> foreign = isolate->factory()->undefined_value();
6897   if (that != NULL) {
6898     foreign = isolate->factory()->NewForeign(FUNCTION_ADDR(that));
6899   }
6900   isolate->debug()->SetEventListener(foreign,
6901                                      Utils::OpenHandle(*data, true));
6902   return true;
6903 }
6904 
6905 
DebugBreak(Isolate * isolate)6906 void Debug::DebugBreak(Isolate* isolate) {
6907   reinterpret_cast<i::Isolate*>(isolate)->stack_guard()->RequestDebugBreak();
6908 }
6909 
6910 
CancelDebugBreak(Isolate * isolate)6911 void Debug::CancelDebugBreak(Isolate* isolate) {
6912   i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
6913   internal_isolate->stack_guard()->ClearDebugBreak();
6914 }
6915 
6916 
CheckDebugBreak(Isolate * isolate)6917 bool Debug::CheckDebugBreak(Isolate* isolate) {
6918   i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
6919   return internal_isolate->stack_guard()->CheckDebugBreak();
6920 }
6921 
6922 
DebugBreakForCommand(Isolate * isolate,ClientData * data)6923 void Debug::DebugBreakForCommand(Isolate* isolate, ClientData* data) {
6924   i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
6925   internal_isolate->debug()->EnqueueDebugCommand(data);
6926 }
6927 
6928 
SetMessageHandler(v8::Debug::MessageHandler handler)6929 void Debug::SetMessageHandler(v8::Debug::MessageHandler handler) {
6930   i::Isolate* isolate = i::Isolate::Current();
6931   ENTER_V8(isolate);
6932   isolate->debug()->SetMessageHandler(handler);
6933 }
6934 
6935 
SendCommand(Isolate * isolate,const uint16_t * command,int length,ClientData * client_data)6936 void Debug::SendCommand(Isolate* isolate,
6937                         const uint16_t* command,
6938                         int length,
6939                         ClientData* client_data) {
6940   i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
6941   internal_isolate->debug()->EnqueueCommandMessage(
6942       i::Vector<const uint16_t>(command, length), client_data);
6943 }
6944 
6945 
Call(v8::Handle<v8::Function> fun,v8::Handle<v8::Value> data)6946 Local<Value> Debug::Call(v8::Handle<v8::Function> fun,
6947                          v8::Handle<v8::Value> data) {
6948   i::Isolate* isolate = i::Isolate::Current();
6949   if (!isolate->IsInitialized()) return Local<Value>();
6950   ON_BAILOUT(isolate, "v8::Debug::Call()", return Local<Value>());
6951   ENTER_V8(isolate);
6952   i::MaybeHandle<i::Object> maybe_result;
6953   EXCEPTION_PREAMBLE(isolate);
6954   if (data.IsEmpty()) {
6955     maybe_result = isolate->debug()->Call(
6956         Utils::OpenHandle(*fun), isolate->factory()->undefined_value());
6957   } else {
6958     maybe_result = isolate->debug()->Call(
6959         Utils::OpenHandle(*fun), Utils::OpenHandle(*data));
6960   }
6961   i::Handle<i::Object> result;
6962   has_pending_exception = !maybe_result.ToHandle(&result);
6963   EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
6964   return Utils::ToLocal(result);
6965 }
6966 
6967 
GetMirror(v8::Handle<v8::Value> obj)6968 Local<Value> Debug::GetMirror(v8::Handle<v8::Value> obj) {
6969   i::Isolate* isolate = i::Isolate::Current();
6970   if (!isolate->IsInitialized()) return Local<Value>();
6971   ON_BAILOUT(isolate, "v8::Debug::GetMirror()", return Local<Value>());
6972   ENTER_V8(isolate);
6973   v8::EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate));
6974   i::Debug* isolate_debug = isolate->debug();
6975   EXCEPTION_PREAMBLE(isolate);
6976   has_pending_exception = !isolate_debug->Load();
6977   v8::Local<v8::Value> result;
6978   if (!has_pending_exception) {
6979     i::Handle<i::JSObject> debug(
6980         isolate_debug->debug_context()->global_object());
6981     i::Handle<i::String> name = isolate->factory()->InternalizeOneByteString(
6982         STATIC_CHAR_VECTOR("MakeMirror"));
6983     i::Handle<i::Object> fun_obj =
6984         i::Object::GetProperty(debug, name).ToHandleChecked();
6985     i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(fun_obj);
6986     v8::Handle<v8::Function> v8_fun = Utils::ToLocal(fun);
6987     const int kArgc = 1;
6988     v8::Handle<v8::Value> argv[kArgc] = { obj };
6989     result = v8_fun->Call(Utils::ToLocal(debug), kArgc, argv);
6990     has_pending_exception = result.IsEmpty();
6991   }
6992   EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
6993   return scope.Escape(result);
6994 }
6995 
6996 
ProcessDebugMessages()6997 void Debug::ProcessDebugMessages() {
6998   i::Isolate::Current()->debug()->ProcessDebugMessages(true);
6999 }
7000 
7001 
GetDebugContext()7002 Local<Context> Debug::GetDebugContext() {
7003   i::Isolate* isolate = i::Isolate::Current();
7004   ENTER_V8(isolate);
7005   return Utils::ToLocal(i::Isolate::Current()->debug()->GetDebugContext());
7006 }
7007 
7008 
SetLiveEditEnabled(Isolate * isolate,bool enable)7009 void Debug::SetLiveEditEnabled(Isolate* isolate, bool enable) {
7010   i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
7011   internal_isolate->debug()->set_live_edit_enabled(enable);
7012 }
7013 
7014 
GetFunctionName() const7015 Handle<String> CpuProfileNode::GetFunctionName() const {
7016   i::Isolate* isolate = i::Isolate::Current();
7017   const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
7018   const i::CodeEntry* entry = node->entry();
7019   i::Handle<i::String> name =
7020       isolate->factory()->InternalizeUtf8String(entry->name());
7021   if (!entry->has_name_prefix()) {
7022     return ToApiHandle<String>(name);
7023   } else {
7024     // We do not expect this to fail. Change this if it does.
7025     i::Handle<i::String> cons = isolate->factory()->NewConsString(
7026         isolate->factory()->InternalizeUtf8String(entry->name_prefix()),
7027         name).ToHandleChecked();
7028     return ToApiHandle<String>(cons);
7029   }
7030 }
7031 
7032 
GetScriptId() const7033 int CpuProfileNode::GetScriptId() const {
7034   const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
7035   const i::CodeEntry* entry = node->entry();
7036   return entry->script_id();
7037 }
7038 
7039 
GetScriptResourceName() const7040 Handle<String> CpuProfileNode::GetScriptResourceName() const {
7041   i::Isolate* isolate = i::Isolate::Current();
7042   const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
7043   return ToApiHandle<String>(isolate->factory()->InternalizeUtf8String(
7044       node->entry()->resource_name()));
7045 }
7046 
7047 
GetLineNumber() const7048 int CpuProfileNode::GetLineNumber() const {
7049   return reinterpret_cast<const i::ProfileNode*>(this)->entry()->line_number();
7050 }
7051 
7052 
GetColumnNumber() const7053 int CpuProfileNode::GetColumnNumber() const {
7054   return reinterpret_cast<const i::ProfileNode*>(this)->
7055       entry()->column_number();
7056 }
7057 
7058 
GetBailoutReason() const7059 const char* CpuProfileNode::GetBailoutReason() const {
7060   const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
7061   return node->entry()->bailout_reason();
7062 }
7063 
7064 
GetHitCount() const7065 unsigned CpuProfileNode::GetHitCount() const {
7066   return reinterpret_cast<const i::ProfileNode*>(this)->self_ticks();
7067 }
7068 
7069 
GetCallUid() const7070 unsigned CpuProfileNode::GetCallUid() const {
7071   return reinterpret_cast<const i::ProfileNode*>(this)->entry()->GetCallUid();
7072 }
7073 
7074 
GetNodeId() const7075 unsigned CpuProfileNode::GetNodeId() const {
7076   return reinterpret_cast<const i::ProfileNode*>(this)->id();
7077 }
7078 
7079 
GetChildrenCount() const7080 int CpuProfileNode::GetChildrenCount() const {
7081   return reinterpret_cast<const i::ProfileNode*>(this)->children()->length();
7082 }
7083 
7084 
GetChild(int index) const7085 const CpuProfileNode* CpuProfileNode::GetChild(int index) const {
7086   const i::ProfileNode* child =
7087       reinterpret_cast<const i::ProfileNode*>(this)->children()->at(index);
7088   return reinterpret_cast<const CpuProfileNode*>(child);
7089 }
7090 
7091 
Delete()7092 void CpuProfile::Delete() {
7093   i::Isolate* isolate = i::Isolate::Current();
7094   i::CpuProfiler* profiler = isolate->cpu_profiler();
7095   DCHECK(profiler != NULL);
7096   profiler->DeleteProfile(reinterpret_cast<i::CpuProfile*>(this));
7097 }
7098 
7099 
GetTitle() const7100 Handle<String> CpuProfile::GetTitle() const {
7101   i::Isolate* isolate = i::Isolate::Current();
7102   const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
7103   return ToApiHandle<String>(isolate->factory()->InternalizeUtf8String(
7104       profile->title()));
7105 }
7106 
7107 
GetTopDownRoot() const7108 const CpuProfileNode* CpuProfile::GetTopDownRoot() const {
7109   const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
7110   return reinterpret_cast<const CpuProfileNode*>(profile->top_down()->root());
7111 }
7112 
7113 
GetSample(int index) const7114 const CpuProfileNode* CpuProfile::GetSample(int index) const {
7115   const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
7116   return reinterpret_cast<const CpuProfileNode*>(profile->sample(index));
7117 }
7118 
7119 
GetSampleTimestamp(int index) const7120 int64_t CpuProfile::GetSampleTimestamp(int index) const {
7121   const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
7122   return (profile->sample_timestamp(index) - base::TimeTicks())
7123       .InMicroseconds();
7124 }
7125 
7126 
GetStartTime() const7127 int64_t CpuProfile::GetStartTime() const {
7128   const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
7129   return (profile->start_time() - base::TimeTicks()).InMicroseconds();
7130 }
7131 
7132 
GetEndTime() const7133 int64_t CpuProfile::GetEndTime() const {
7134   const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
7135   return (profile->end_time() - base::TimeTicks()).InMicroseconds();
7136 }
7137 
7138 
GetSamplesCount() const7139 int CpuProfile::GetSamplesCount() const {
7140   return reinterpret_cast<const i::CpuProfile*>(this)->samples_count();
7141 }
7142 
7143 
SetSamplingInterval(int us)7144 void CpuProfiler::SetSamplingInterval(int us) {
7145   DCHECK(us >= 0);
7146   return reinterpret_cast<i::CpuProfiler*>(this)->set_sampling_interval(
7147       base::TimeDelta::FromMicroseconds(us));
7148 }
7149 
7150 
StartProfiling(Handle<String> title,bool record_samples)7151 void CpuProfiler::StartProfiling(Handle<String> title, bool record_samples) {
7152   reinterpret_cast<i::CpuProfiler*>(this)->StartProfiling(
7153       *Utils::OpenHandle(*title), record_samples);
7154 }
7155 
7156 
StartCpuProfiling(Handle<String> title,bool record_samples)7157 void CpuProfiler::StartCpuProfiling(Handle<String> title, bool record_samples) {
7158   StartProfiling(title, record_samples);
7159 }
7160 
7161 
StopProfiling(Handle<String> title)7162 CpuProfile* CpuProfiler::StopProfiling(Handle<String> title) {
7163   return reinterpret_cast<CpuProfile*>(
7164       reinterpret_cast<i::CpuProfiler*>(this)->StopProfiling(
7165           *Utils::OpenHandle(*title)));
7166 }
7167 
7168 
StopCpuProfiling(Handle<String> title)7169 const CpuProfile* CpuProfiler::StopCpuProfiling(Handle<String> title) {
7170   return StopProfiling(title);
7171 }
7172 
7173 
SetIdle(bool is_idle)7174 void CpuProfiler::SetIdle(bool is_idle) {
7175   i::Isolate* isolate = reinterpret_cast<i::CpuProfiler*>(this)->isolate();
7176   i::StateTag state = isolate->current_vm_state();
7177   DCHECK(state == i::EXTERNAL || state == i::IDLE);
7178   if (isolate->js_entry_sp() != NULL) return;
7179   if (is_idle) {
7180     isolate->set_current_vm_state(i::IDLE);
7181   } else if (state == i::IDLE) {
7182     isolate->set_current_vm_state(i::EXTERNAL);
7183   }
7184 }
7185 
7186 
ToInternal(const HeapGraphEdge * edge)7187 static i::HeapGraphEdge* ToInternal(const HeapGraphEdge* edge) {
7188   return const_cast<i::HeapGraphEdge*>(
7189       reinterpret_cast<const i::HeapGraphEdge*>(edge));
7190 }
7191 
7192 
GetType() const7193 HeapGraphEdge::Type HeapGraphEdge::GetType() const {
7194   return static_cast<HeapGraphEdge::Type>(ToInternal(this)->type());
7195 }
7196 
7197 
GetName() const7198 Handle<Value> HeapGraphEdge::GetName() const {
7199   i::Isolate* isolate = i::Isolate::Current();
7200   i::HeapGraphEdge* edge = ToInternal(this);
7201   switch (edge->type()) {
7202     case i::HeapGraphEdge::kContextVariable:
7203     case i::HeapGraphEdge::kInternal:
7204     case i::HeapGraphEdge::kProperty:
7205     case i::HeapGraphEdge::kShortcut:
7206     case i::HeapGraphEdge::kWeak:
7207       return ToApiHandle<String>(
7208           isolate->factory()->InternalizeUtf8String(edge->name()));
7209     case i::HeapGraphEdge::kElement:
7210     case i::HeapGraphEdge::kHidden:
7211       return ToApiHandle<Number>(
7212           isolate->factory()->NewNumberFromInt(edge->index()));
7213     default: UNREACHABLE();
7214   }
7215   return v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
7216 }
7217 
7218 
GetFromNode() const7219 const HeapGraphNode* HeapGraphEdge::GetFromNode() const {
7220   const i::HeapEntry* from = ToInternal(this)->from();
7221   return reinterpret_cast<const HeapGraphNode*>(from);
7222 }
7223 
7224 
GetToNode() const7225 const HeapGraphNode* HeapGraphEdge::GetToNode() const {
7226   const i::HeapEntry* to = ToInternal(this)->to();
7227   return reinterpret_cast<const HeapGraphNode*>(to);
7228 }
7229 
7230 
ToInternal(const HeapGraphNode * entry)7231 static i::HeapEntry* ToInternal(const HeapGraphNode* entry) {
7232   return const_cast<i::HeapEntry*>(
7233       reinterpret_cast<const i::HeapEntry*>(entry));
7234 }
7235 
7236 
GetType() const7237 HeapGraphNode::Type HeapGraphNode::GetType() const {
7238   return static_cast<HeapGraphNode::Type>(ToInternal(this)->type());
7239 }
7240 
7241 
GetName() const7242 Handle<String> HeapGraphNode::GetName() const {
7243   i::Isolate* isolate = i::Isolate::Current();
7244   return ToApiHandle<String>(
7245       isolate->factory()->InternalizeUtf8String(ToInternal(this)->name()));
7246 }
7247 
7248 
GetId() const7249 SnapshotObjectId HeapGraphNode::GetId() const {
7250   return ToInternal(this)->id();
7251 }
7252 
7253 
GetSelfSize() const7254 int HeapGraphNode::GetSelfSize() const {
7255   size_t size = ToInternal(this)->self_size();
7256   CHECK(size <= static_cast<size_t>(internal::kMaxInt));
7257   return static_cast<int>(size);
7258 }
7259 
7260 
GetShallowSize() const7261 size_t HeapGraphNode::GetShallowSize() const {
7262   return ToInternal(this)->self_size();
7263 }
7264 
7265 
GetChildrenCount() const7266 int HeapGraphNode::GetChildrenCount() const {
7267   return ToInternal(this)->children().length();
7268 }
7269 
7270 
GetChild(int index) const7271 const HeapGraphEdge* HeapGraphNode::GetChild(int index) const {
7272   return reinterpret_cast<const HeapGraphEdge*>(
7273       ToInternal(this)->children()[index]);
7274 }
7275 
7276 
ToInternal(const HeapSnapshot * snapshot)7277 static i::HeapSnapshot* ToInternal(const HeapSnapshot* snapshot) {
7278   return const_cast<i::HeapSnapshot*>(
7279       reinterpret_cast<const i::HeapSnapshot*>(snapshot));
7280 }
7281 
7282 
Delete()7283 void HeapSnapshot::Delete() {
7284   i::Isolate* isolate = i::Isolate::Current();
7285   if (isolate->heap_profiler()->GetSnapshotsCount() > 1) {
7286     ToInternal(this)->Delete();
7287   } else {
7288     // If this is the last snapshot, clean up all accessory data as well.
7289     isolate->heap_profiler()->DeleteAllSnapshots();
7290   }
7291 }
7292 
7293 
GetUid() const7294 unsigned HeapSnapshot::GetUid() const {
7295   return ToInternal(this)->uid();
7296 }
7297 
7298 
GetTitle() const7299 Handle<String> HeapSnapshot::GetTitle() const {
7300   i::Isolate* isolate = i::Isolate::Current();
7301   return ToApiHandle<String>(
7302       isolate->factory()->InternalizeUtf8String(ToInternal(this)->title()));
7303 }
7304 
7305 
GetRoot() const7306 const HeapGraphNode* HeapSnapshot::GetRoot() const {
7307   return reinterpret_cast<const HeapGraphNode*>(ToInternal(this)->root());
7308 }
7309 
7310 
GetNodeById(SnapshotObjectId id) const7311 const HeapGraphNode* HeapSnapshot::GetNodeById(SnapshotObjectId id) const {
7312   return reinterpret_cast<const HeapGraphNode*>(
7313       ToInternal(this)->GetEntryById(id));
7314 }
7315 
7316 
GetNodesCount() const7317 int HeapSnapshot::GetNodesCount() const {
7318   return ToInternal(this)->entries().length();
7319 }
7320 
7321 
GetNode(int index) const7322 const HeapGraphNode* HeapSnapshot::GetNode(int index) const {
7323   return reinterpret_cast<const HeapGraphNode*>(
7324       &ToInternal(this)->entries().at(index));
7325 }
7326 
7327 
GetMaxSnapshotJSObjectId() const7328 SnapshotObjectId HeapSnapshot::GetMaxSnapshotJSObjectId() const {
7329   return ToInternal(this)->max_snapshot_js_object_id();
7330 }
7331 
7332 
Serialize(OutputStream * stream,HeapSnapshot::SerializationFormat format) const7333 void HeapSnapshot::Serialize(OutputStream* stream,
7334                              HeapSnapshot::SerializationFormat format) const {
7335   Utils::ApiCheck(format == kJSON,
7336                   "v8::HeapSnapshot::Serialize",
7337                   "Unknown serialization format");
7338   Utils::ApiCheck(stream->GetChunkSize() > 0,
7339                   "v8::HeapSnapshot::Serialize",
7340                   "Invalid stream chunk size");
7341   i::HeapSnapshotJSONSerializer serializer(ToInternal(this));
7342   serializer.Serialize(stream);
7343 }
7344 
7345 
GetSnapshotCount()7346 int HeapProfiler::GetSnapshotCount() {
7347   return reinterpret_cast<i::HeapProfiler*>(this)->GetSnapshotsCount();
7348 }
7349 
7350 
GetHeapSnapshot(int index)7351 const HeapSnapshot* HeapProfiler::GetHeapSnapshot(int index) {
7352   return reinterpret_cast<const HeapSnapshot*>(
7353       reinterpret_cast<i::HeapProfiler*>(this)->GetSnapshot(index));
7354 }
7355 
7356 
GetObjectId(Handle<Value> value)7357 SnapshotObjectId HeapProfiler::GetObjectId(Handle<Value> value) {
7358   i::Handle<i::Object> obj = Utils::OpenHandle(*value);
7359   return reinterpret_cast<i::HeapProfiler*>(this)->GetSnapshotObjectId(obj);
7360 }
7361 
7362 
FindObjectById(SnapshotObjectId id)7363 Handle<Value> HeapProfiler::FindObjectById(SnapshotObjectId id) {
7364   i::Handle<i::Object> obj =
7365       reinterpret_cast<i::HeapProfiler*>(this)->FindHeapObjectById(id);
7366   if (obj.is_null()) return Local<Value>();
7367   return Utils::ToLocal(obj);
7368 }
7369 
7370 
ClearObjectIds()7371 void HeapProfiler::ClearObjectIds() {
7372   reinterpret_cast<i::HeapProfiler*>(this)->ClearHeapObjectMap();
7373 }
7374 
7375 
TakeHeapSnapshot(Handle<String> title,ActivityControl * control,ObjectNameResolver * resolver)7376 const HeapSnapshot* HeapProfiler::TakeHeapSnapshot(
7377     Handle<String> title,
7378     ActivityControl* control,
7379     ObjectNameResolver* resolver) {
7380   return reinterpret_cast<const HeapSnapshot*>(
7381       reinterpret_cast<i::HeapProfiler*>(this)->TakeSnapshot(
7382           *Utils::OpenHandle(*title), control, resolver));
7383 }
7384 
7385 
StartTrackingHeapObjects(bool track_allocations)7386 void HeapProfiler::StartTrackingHeapObjects(bool track_allocations) {
7387   reinterpret_cast<i::HeapProfiler*>(this)->StartHeapObjectsTracking(
7388       track_allocations);
7389 }
7390 
7391 
StopTrackingHeapObjects()7392 void HeapProfiler::StopTrackingHeapObjects() {
7393   reinterpret_cast<i::HeapProfiler*>(this)->StopHeapObjectsTracking();
7394 }
7395 
7396 
GetHeapStats(OutputStream * stream)7397 SnapshotObjectId HeapProfiler::GetHeapStats(OutputStream* stream) {
7398   return reinterpret_cast<i::HeapProfiler*>(this)->PushHeapObjectsStats(stream);
7399 }
7400 
7401 
DeleteAllHeapSnapshots()7402 void HeapProfiler::DeleteAllHeapSnapshots() {
7403   reinterpret_cast<i::HeapProfiler*>(this)->DeleteAllSnapshots();
7404 }
7405 
7406 
SetWrapperClassInfoProvider(uint16_t class_id,WrapperInfoCallback callback)7407 void HeapProfiler::SetWrapperClassInfoProvider(uint16_t class_id,
7408                                                WrapperInfoCallback callback) {
7409   reinterpret_cast<i::HeapProfiler*>(this)->DefineWrapperClass(class_id,
7410                                                                callback);
7411 }
7412 
7413 
GetProfilerMemorySize()7414 size_t HeapProfiler::GetProfilerMemorySize() {
7415   return reinterpret_cast<i::HeapProfiler*>(this)->
7416       GetMemorySizeUsedByProfiler();
7417 }
7418 
7419 
SetRetainedObjectInfo(UniqueId id,RetainedObjectInfo * info)7420 void HeapProfiler::SetRetainedObjectInfo(UniqueId id,
7421                                          RetainedObjectInfo* info) {
7422   reinterpret_cast<i::HeapProfiler*>(this)->SetRetainedObjectInfo(id, info);
7423 }
7424 
7425 
7426 v8::Testing::StressType internal::Testing::stress_type_ =
7427     v8::Testing::kStressTypeOpt;
7428 
7429 
SetStressRunType(Testing::StressType type)7430 void Testing::SetStressRunType(Testing::StressType type) {
7431   internal::Testing::set_stress_type(type);
7432 }
7433 
7434 
GetStressRuns()7435 int Testing::GetStressRuns() {
7436   if (internal::FLAG_stress_runs != 0) return internal::FLAG_stress_runs;
7437 #ifdef DEBUG
7438   // In debug mode the code runs much slower so stressing will only make two
7439   // runs.
7440   return 2;
7441 #else
7442   return 5;
7443 #endif
7444 }
7445 
7446 
SetFlagsFromString(const char * flags)7447 static void SetFlagsFromString(const char* flags) {
7448   V8::SetFlagsFromString(flags, i::StrLength(flags));
7449 }
7450 
7451 
PrepareStressRun(int run)7452 void Testing::PrepareStressRun(int run) {
7453   static const char* kLazyOptimizations =
7454       "--prepare-always-opt "
7455       "--max-inlined-source-size=999999 "
7456       "--max-inlined-nodes=999999 "
7457       "--max-inlined-nodes-cumulative=999999 "
7458       "--noalways-opt";
7459   static const char* kForcedOptimizations = "--always-opt";
7460 
7461   // If deoptimization stressed turn on frequent deoptimization. If no value
7462   // is spefified through --deopt-every-n-times use a default default value.
7463   static const char* kDeoptEvery13Times = "--deopt-every-n-times=13";
7464   if (internal::Testing::stress_type() == Testing::kStressTypeDeopt &&
7465       internal::FLAG_deopt_every_n_times == 0) {
7466     SetFlagsFromString(kDeoptEvery13Times);
7467   }
7468 
7469 #ifdef DEBUG
7470   // As stressing in debug mode only make two runs skip the deopt stressing
7471   // here.
7472   if (run == GetStressRuns() - 1) {
7473     SetFlagsFromString(kForcedOptimizations);
7474   } else {
7475     SetFlagsFromString(kLazyOptimizations);
7476   }
7477 #else
7478   if (run == GetStressRuns() - 1) {
7479     SetFlagsFromString(kForcedOptimizations);
7480   } else if (run != GetStressRuns() - 2) {
7481     SetFlagsFromString(kLazyOptimizations);
7482   }
7483 #endif
7484 }
7485 
7486 
7487 // TODO(svenpanne) Deprecate this.
DeoptimizeAll()7488 void Testing::DeoptimizeAll() {
7489   i::Isolate* isolate = i::Isolate::Current();
7490   i::HandleScope scope(isolate);
7491   internal::Deoptimizer::DeoptimizeAll(isolate);
7492 }
7493 
7494 
7495 namespace internal {
7496 
7497 
FreeThreadResources()7498 void HandleScopeImplementer::FreeThreadResources() {
7499   Free();
7500 }
7501 
7502 
ArchiveThread(char * storage)7503 char* HandleScopeImplementer::ArchiveThread(char* storage) {
7504   HandleScopeData* current = isolate_->handle_scope_data();
7505   handle_scope_data_ = *current;
7506   MemCopy(storage, this, sizeof(*this));
7507 
7508   ResetAfterArchive();
7509   current->Initialize();
7510 
7511   return storage + ArchiveSpacePerThread();
7512 }
7513 
7514 
ArchiveSpacePerThread()7515 int HandleScopeImplementer::ArchiveSpacePerThread() {
7516   return sizeof(HandleScopeImplementer);
7517 }
7518 
7519 
RestoreThread(char * storage)7520 char* HandleScopeImplementer::RestoreThread(char* storage) {
7521   MemCopy(this, storage, sizeof(*this));
7522   *isolate_->handle_scope_data() = handle_scope_data_;
7523   return storage + ArchiveSpacePerThread();
7524 }
7525 
7526 
IterateThis(ObjectVisitor * v)7527 void HandleScopeImplementer::IterateThis(ObjectVisitor* v) {
7528 #ifdef DEBUG
7529   bool found_block_before_deferred = false;
7530 #endif
7531   // Iterate over all handles in the blocks except for the last.
7532   for (int i = blocks()->length() - 2; i >= 0; --i) {
7533     Object** block = blocks()->at(i);
7534     if (last_handle_before_deferred_block_ != NULL &&
7535         (last_handle_before_deferred_block_ <= &block[kHandleBlockSize]) &&
7536         (last_handle_before_deferred_block_ >= block)) {
7537       v->VisitPointers(block, last_handle_before_deferred_block_);
7538       DCHECK(!found_block_before_deferred);
7539 #ifdef DEBUG
7540       found_block_before_deferred = true;
7541 #endif
7542     } else {
7543       v->VisitPointers(block, &block[kHandleBlockSize]);
7544     }
7545   }
7546 
7547   DCHECK(last_handle_before_deferred_block_ == NULL ||
7548          found_block_before_deferred);
7549 
7550   // Iterate over live handles in the last block (if any).
7551   if (!blocks()->is_empty()) {
7552     v->VisitPointers(blocks()->last(), handle_scope_data_.next);
7553   }
7554 
7555   List<Context*>* context_lists[2] = { &saved_contexts_, &entered_contexts_};
7556   for (unsigned i = 0; i < arraysize(context_lists); i++) {
7557     if (context_lists[i]->is_empty()) continue;
7558     Object** start = reinterpret_cast<Object**>(&context_lists[i]->first());
7559     v->VisitPointers(start, start + context_lists[i]->length());
7560   }
7561 }
7562 
7563 
Iterate(ObjectVisitor * v)7564 void HandleScopeImplementer::Iterate(ObjectVisitor* v) {
7565   HandleScopeData* current = isolate_->handle_scope_data();
7566   handle_scope_data_ = *current;
7567   IterateThis(v);
7568 }
7569 
7570 
Iterate(ObjectVisitor * v,char * storage)7571 char* HandleScopeImplementer::Iterate(ObjectVisitor* v, char* storage) {
7572   HandleScopeImplementer* scope_implementer =
7573       reinterpret_cast<HandleScopeImplementer*>(storage);
7574   scope_implementer->IterateThis(v);
7575   return storage + ArchiveSpacePerThread();
7576 }
7577 
7578 
Detach(Object ** prev_limit)7579 DeferredHandles* HandleScopeImplementer::Detach(Object** prev_limit) {
7580   DeferredHandles* deferred =
7581       new DeferredHandles(isolate()->handle_scope_data()->next, isolate());
7582 
7583   while (!blocks_.is_empty()) {
7584     Object** block_start = blocks_.last();
7585     Object** block_limit = &block_start[kHandleBlockSize];
7586     // We should not need to check for SealHandleScope here. Assert this.
7587     DCHECK(prev_limit == block_limit ||
7588            !(block_start <= prev_limit && prev_limit <= block_limit));
7589     if (prev_limit == block_limit) break;
7590     deferred->blocks_.Add(blocks_.last());
7591     blocks_.RemoveLast();
7592   }
7593 
7594   // deferred->blocks_ now contains the blocks installed on the
7595   // HandleScope stack since BeginDeferredScope was called, but in
7596   // reverse order.
7597 
7598   DCHECK(prev_limit == NULL || !blocks_.is_empty());
7599 
7600   DCHECK(!blocks_.is_empty() && prev_limit != NULL);
7601   DCHECK(last_handle_before_deferred_block_ != NULL);
7602   last_handle_before_deferred_block_ = NULL;
7603   return deferred;
7604 }
7605 
7606 
BeginDeferredScope()7607 void HandleScopeImplementer::BeginDeferredScope() {
7608   DCHECK(last_handle_before_deferred_block_ == NULL);
7609   last_handle_before_deferred_block_ = isolate()->handle_scope_data()->next;
7610 }
7611 
7612 
~DeferredHandles()7613 DeferredHandles::~DeferredHandles() {
7614   isolate_->UnlinkDeferredHandles(this);
7615 
7616   for (int i = 0; i < blocks_.length(); i++) {
7617 #ifdef ENABLE_HANDLE_ZAPPING
7618     HandleScope::ZapRange(blocks_[i], &blocks_[i][kHandleBlockSize]);
7619 #endif
7620     isolate_->handle_scope_implementer()->ReturnBlock(blocks_[i]);
7621   }
7622 }
7623 
7624 
Iterate(ObjectVisitor * v)7625 void DeferredHandles::Iterate(ObjectVisitor* v) {
7626   DCHECK(!blocks_.is_empty());
7627 
7628   DCHECK((first_block_limit_ >= blocks_.first()) &&
7629          (first_block_limit_ <= &(blocks_.first())[kHandleBlockSize]));
7630 
7631   v->VisitPointers(blocks_.first(), first_block_limit_);
7632 
7633   for (int i = 1; i < blocks_.length(); i++) {
7634     v->VisitPointers(blocks_[i], &blocks_[i][kHandleBlockSize]);
7635   }
7636 }
7637 
7638 
InvokeAccessorGetterCallback(v8::Local<v8::Name> property,const v8::PropertyCallbackInfo<v8::Value> & info,v8::AccessorNameGetterCallback getter)7639 void InvokeAccessorGetterCallback(
7640     v8::Local<v8::Name> property,
7641     const v8::PropertyCallbackInfo<v8::Value>& info,
7642     v8::AccessorNameGetterCallback getter) {
7643   // Leaving JavaScript.
7644   Isolate* isolate = reinterpret_cast<Isolate*>(info.GetIsolate());
7645   Address getter_address = reinterpret_cast<Address>(reinterpret_cast<intptr_t>(
7646       getter));
7647   VMState<EXTERNAL> state(isolate);
7648   ExternalCallbackScope call_scope(isolate, getter_address);
7649   getter(property, info);
7650 }
7651 
7652 
InvokeFunctionCallback(const v8::FunctionCallbackInfo<v8::Value> & info,v8::FunctionCallback callback)7653 void InvokeFunctionCallback(const v8::FunctionCallbackInfo<v8::Value>& info,
7654                             v8::FunctionCallback callback) {
7655   Isolate* isolate = reinterpret_cast<Isolate*>(info.GetIsolate());
7656   Address callback_address =
7657       reinterpret_cast<Address>(reinterpret_cast<intptr_t>(callback));
7658   VMState<EXTERNAL> state(isolate);
7659   ExternalCallbackScope call_scope(isolate, callback_address);
7660   callback(info);
7661 }
7662 
7663 
7664 } }  // namespace v8::internal
7665