• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2009 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 //     * Redistributions of source code must retain the above copyright
7 //       notice, this list of conditions and the following disclaimer.
8 //     * Redistributions in binary form must reproduce the above
9 //       copyright notice, this list of conditions and the following
10 //       disclaimer in the documentation and/or other materials provided
11 //       with the distribution.
12 //     * Neither the name of Google Inc. nor the names of its
13 //       contributors may be used to endorse or promote products derived
14 //       from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 #include "v8.h"
29 
30 #include "api.h"
31 #include "bootstrapper.h"
32 #include "compiler.h"
33 #include "debug.h"
34 #include "execution.h"
35 #include "global-handles.h"
36 #include "platform.h"
37 #include "serialize.h"
38 #include "snapshot.h"
39 #include "v8threads.h"
40 #include "version.h"
41 
42 
43 #define LOG_API(expr) LOG(ApiEntryCall(expr))
44 
45 #ifdef ENABLE_HEAP_PROTECTION
46 #define ENTER_V8 i::VMState __state__(i::OTHER)
47 #define LEAVE_V8 i::VMState __state__(i::EXTERNAL)
48 #else
49 #define ENTER_V8 ((void) 0)
50 #define LEAVE_V8 ((void) 0)
51 #endif
52 
53 namespace v8 {
54 
55 
56 #define ON_BAILOUT(location, code)              \
57   if (IsDeadCheck(location)) {                  \
58     code;                                       \
59     UNREACHABLE();                              \
60   }
61 
62 
63 #define EXCEPTION_PREAMBLE()                                      \
64   thread_local.IncrementCallDepth();                              \
65   ASSERT(!i::Top::external_caught_exception());                   \
66   bool has_pending_exception = false
67 
68 
69 #define EXCEPTION_BAILOUT_CHECK(value)                                         \
70   do {                                                                         \
71     thread_local.DecrementCallDepth();                                         \
72     if (has_pending_exception) {                                               \
73       if (thread_local.CallDepthIsZero() && i::Top::is_out_of_memory()) {      \
74         if (!thread_local.IgnoreOutOfMemory())                                 \
75           i::V8::FatalProcessOutOfMemory(NULL);                                \
76       }                                                                        \
77       bool call_depth_is_zero = thread_local.CallDepthIsZero();                \
78       i::Top::OptionalRescheduleException(call_depth_is_zero);                 \
79       return value;                                                            \
80     }                                                                          \
81   } while (false)
82 
83 
84 #define API_ENTRY_CHECK(msg)                                                   \
85   do {                                                                         \
86     if (v8::Locker::IsActive()) {                                              \
87       ApiCheck(i::ThreadManager::IsLockedByCurrentThread(),                    \
88                msg,                                                            \
89                "Entering the V8 API without proper locking in place");         \
90     }                                                                          \
91   } while (false)
92 
93 // --- D a t a   t h a t   i s   s p e c i f i c   t o   a   t h r e a d ---
94 
95 
96 static i::HandleScopeImplementer thread_local;
97 
98 
99 // --- E x c e p t i o n   B e h a v i o r ---
100 
101 
102 static FatalErrorCallback exception_behavior = NULL;
103 int i::Internals::kJSObjectType = JS_OBJECT_TYPE;
104 int i::Internals::kFirstNonstringType = FIRST_NONSTRING_TYPE;
105 int i::Internals::kProxyType = PROXY_TYPE;
106 
DefaultFatalErrorHandler(const char * location,const char * message)107 static void DefaultFatalErrorHandler(const char* location,
108                                      const char* message) {
109   ENTER_V8;
110   API_Fatal(location, message);
111 }
112 
113 
114 
GetFatalErrorHandler()115 static FatalErrorCallback& GetFatalErrorHandler() {
116   if (exception_behavior == NULL) {
117     exception_behavior = DefaultFatalErrorHandler;
118   }
119   return exception_behavior;
120 }
121 
122 
123 
124 // When V8 cannot allocated memory FatalProcessOutOfMemory is called.
125 // The default fatal error handler is called and execution is stopped.
FatalProcessOutOfMemory(const char * location)126 void i::V8::FatalProcessOutOfMemory(const char* location) {
127   i::V8::SetFatalError();
128   FatalErrorCallback callback = GetFatalErrorHandler();
129   {
130     LEAVE_V8;
131     callback(location, "Allocation failed - process out of memory");
132   }
133   // If the callback returns, we stop execution.
134   UNREACHABLE();
135 }
136 
137 
SetFatalErrorHandler(FatalErrorCallback that)138 void V8::SetFatalErrorHandler(FatalErrorCallback that) {
139   exception_behavior = that;
140 }
141 
142 
ReportApiFailure(const char * location,const char * message)143 bool Utils::ReportApiFailure(const char* location, const char* message) {
144   FatalErrorCallback callback = GetFatalErrorHandler();
145   callback(location, message);
146   i::V8::SetFatalError();
147   return false;
148 }
149 
150 
IsDead()151 bool V8::IsDead() {
152   return i::V8::IsDead();
153 }
154 
155 
ApiCheck(bool condition,const char * location,const char * message)156 static inline bool ApiCheck(bool condition,
157                             const char* location,
158                             const char* message) {
159   return condition ? true : Utils::ReportApiFailure(location, message);
160 }
161 
162 
ReportV8Dead(const char * location)163 static bool ReportV8Dead(const char* location) {
164   FatalErrorCallback callback = GetFatalErrorHandler();
165   callback(location, "V8 is no longer usable");
166   return true;
167 }
168 
169 
ReportEmptyHandle(const char * location)170 static bool ReportEmptyHandle(const char* location) {
171   FatalErrorCallback callback = GetFatalErrorHandler();
172   callback(location, "Reading from empty handle");
173   return true;
174 }
175 
176 
177 /**
178  * IsDeadCheck checks that the vm is usable.  If, for instance, the vm has been
179  * out of memory at some point this check will fail.  It should be called on
180  * entry to all methods that touch anything in the heap, except destructors
181  * which you sometimes can't avoid calling after the vm has crashed.  Functions
182  * that call EnsureInitialized or ON_BAILOUT don't have to also call
183  * IsDeadCheck.  ON_BAILOUT has the advantage over EnsureInitialized that you
184  * can arrange to return if the VM is dead.  This is needed to ensure that no VM
185  * heap allocations are attempted on a dead VM.  EnsureInitialized has the
186  * advantage over ON_BAILOUT that it actually initializes the VM if this has not
187  * yet been done.
188  */
IsDeadCheck(const char * location)189 static inline bool IsDeadCheck(const char* location) {
190   return !i::V8::IsRunning()
191       && i::V8::IsDead() ? ReportV8Dead(location) : false;
192 }
193 
194 
EmptyCheck(const char * location,v8::Handle<v8::Data> obj)195 static inline bool EmptyCheck(const char* location, v8::Handle<v8::Data> obj) {
196   return obj.IsEmpty() ? ReportEmptyHandle(location) : false;
197 }
198 
199 
EmptyCheck(const char * location,const v8::Data * obj)200 static inline bool EmptyCheck(const char* location, const v8::Data* obj) {
201   return (obj == 0) ? ReportEmptyHandle(location) : false;
202 }
203 
204 // --- S t a t i c s ---
205 
206 
207 static i::StringInputBuffer write_input_buffer;
208 
209 
EnsureInitialized(const char * location)210 static inline bool EnsureInitialized(const char* location) {
211   if (i::V8::IsRunning()) {
212     return true;
213   }
214   if (IsDeadCheck(location)) {
215     return false;
216   }
217   return ApiCheck(v8::V8::Initialize(), location, "Error initializing V8");
218 }
219 
220 
221 ImplementationUtilities::HandleScopeData*
CurrentHandleScope()222     ImplementationUtilities::CurrentHandleScope() {
223   return &i::HandleScope::current_;
224 }
225 
226 
227 #ifdef DEBUG
ZapHandleRange(i::Object ** begin,i::Object ** end)228 void ImplementationUtilities::ZapHandleRange(i::Object** begin,
229                                              i::Object** end) {
230   i::HandleScope::ZapRange(begin, end);
231 }
232 #endif
233 
234 
Undefined()235 v8::Handle<v8::Primitive> ImplementationUtilities::Undefined() {
236   if (!EnsureInitialized("v8::Undefined()")) return v8::Handle<v8::Primitive>();
237   return v8::Handle<Primitive>(ToApi<Primitive>(i::Factory::undefined_value()));
238 }
239 
240 
Null()241 v8::Handle<v8::Primitive> ImplementationUtilities::Null() {
242   if (!EnsureInitialized("v8::Null()")) return v8::Handle<v8::Primitive>();
243   return v8::Handle<Primitive>(ToApi<Primitive>(i::Factory::null_value()));
244 }
245 
246 
True()247 v8::Handle<v8::Boolean> ImplementationUtilities::True() {
248   if (!EnsureInitialized("v8::True()")) return v8::Handle<v8::Boolean>();
249   return v8::Handle<v8::Boolean>(ToApi<Boolean>(i::Factory::true_value()));
250 }
251 
252 
False()253 v8::Handle<v8::Boolean> ImplementationUtilities::False() {
254   if (!EnsureInitialized("v8::False()")) return v8::Handle<v8::Boolean>();
255   return v8::Handle<v8::Boolean>(ToApi<Boolean>(i::Factory::false_value()));
256 }
257 
258 
SetFlagsFromString(const char * str,int length)259 void V8::SetFlagsFromString(const char* str, int length) {
260   i::FlagList::SetFlagsFromString(str, length);
261 }
262 
263 
SetFlagsFromCommandLine(int * argc,char ** argv,bool remove_flags)264 void V8::SetFlagsFromCommandLine(int* argc, char** argv, bool remove_flags) {
265   i::FlagList::SetFlagsFromCommandLine(argc, argv, remove_flags);
266 }
267 
268 
ThrowException(v8::Handle<v8::Value> value)269 v8::Handle<Value> ThrowException(v8::Handle<v8::Value> value) {
270   if (IsDeadCheck("v8::ThrowException()")) return v8::Handle<Value>();
271   ENTER_V8;
272   // If we're passed an empty handle, we throw an undefined exception
273   // to deal more gracefully with out of memory situations.
274   if (value.IsEmpty()) {
275     i::Top::ScheduleThrow(i::Heap::undefined_value());
276   } else {
277     i::Top::ScheduleThrow(*Utils::OpenHandle(*value));
278   }
279   return v8::Undefined();
280 }
281 
282 
283 RegisteredExtension* RegisteredExtension::first_extension_ = NULL;
284 
285 
RegisteredExtension(Extension * extension)286 RegisteredExtension::RegisteredExtension(Extension* extension)
287     : extension_(extension), state_(UNVISITED) { }
288 
289 
Register(RegisteredExtension * that)290 void RegisteredExtension::Register(RegisteredExtension* that) {
291   that->next_ = RegisteredExtension::first_extension_;
292   RegisteredExtension::first_extension_ = that;
293 }
294 
295 
RegisterExtension(Extension * that)296 void RegisterExtension(Extension* that) {
297   RegisteredExtension* extension = new RegisteredExtension(that);
298   RegisteredExtension::Register(extension);
299 }
300 
301 
Extension(const char * name,const char * source,int dep_count,const char ** deps)302 Extension::Extension(const char* name,
303                      const char* source,
304                      int dep_count,
305                      const char** deps)
306     : name_(name),
307       source_(source),
308       dep_count_(dep_count),
309       deps_(deps),
310       auto_enable_(false) { }
311 
312 
Undefined()313 v8::Handle<Primitive> Undefined() {
314   LOG_API("Undefined");
315   return ImplementationUtilities::Undefined();
316 }
317 
318 
Null()319 v8::Handle<Primitive> Null() {
320   LOG_API("Null");
321   return ImplementationUtilities::Null();
322 }
323 
324 
True()325 v8::Handle<Boolean> True() {
326   LOG_API("True");
327   return ImplementationUtilities::True();
328 }
329 
330 
False()331 v8::Handle<Boolean> False() {
332   LOG_API("False");
333   return ImplementationUtilities::False();
334 }
335 
336 
ResourceConstraints()337 ResourceConstraints::ResourceConstraints()
338   : max_young_space_size_(0),
339     max_old_space_size_(0),
340     stack_limit_(NULL) { }
341 
342 
SetResourceConstraints(ResourceConstraints * constraints)343 bool SetResourceConstraints(ResourceConstraints* constraints) {
344   bool result = i::Heap::ConfigureHeap(constraints->max_young_space_size(),
345                                        constraints->max_old_space_size());
346   if (!result) return false;
347   if (constraints->stack_limit() != NULL) {
348     uintptr_t limit = reinterpret_cast<uintptr_t>(constraints->stack_limit());
349     i::StackGuard::SetStackLimit(limit);
350   }
351   return true;
352 }
353 
354 
GlobalizeReference(i::Object ** obj)355 i::Object** V8::GlobalizeReference(i::Object** obj) {
356   if (IsDeadCheck("V8::Persistent::New")) return NULL;
357   LOG_API("Persistent::New");
358   i::Handle<i::Object> result =
359       i::GlobalHandles::Create(*obj);
360   return result.location();
361 }
362 
363 
MakeWeak(i::Object ** object,void * parameters,WeakReferenceCallback callback)364 void V8::MakeWeak(i::Object** object, void* parameters,
365                   WeakReferenceCallback callback) {
366   LOG_API("MakeWeak");
367   i::GlobalHandles::MakeWeak(object, parameters, callback);
368 }
369 
370 
ClearWeak(i::Object ** obj)371 void V8::ClearWeak(i::Object** obj) {
372   LOG_API("ClearWeak");
373   i::GlobalHandles::ClearWeakness(obj);
374 }
375 
376 
IsGlobalNearDeath(i::Object ** obj)377 bool V8::IsGlobalNearDeath(i::Object** obj) {
378   LOG_API("IsGlobalNearDeath");
379   if (!i::V8::IsRunning()) return false;
380   return i::GlobalHandles::IsNearDeath(obj);
381 }
382 
383 
IsGlobalWeak(i::Object ** obj)384 bool V8::IsGlobalWeak(i::Object** obj) {
385   LOG_API("IsGlobalWeak");
386   if (!i::V8::IsRunning()) return false;
387   return i::GlobalHandles::IsWeak(obj);
388 }
389 
390 
DisposeGlobal(i::Object ** obj)391 void V8::DisposeGlobal(i::Object** obj) {
392   LOG_API("DisposeGlobal");
393   if (!i::V8::IsRunning()) return;
394   if ((*obj)->IsGlobalContext()) i::Heap::NotifyContextDisposed();
395   i::GlobalHandles::Destroy(obj);
396 }
397 
398 // --- H a n d l e s ---
399 
400 
HandleScope()401 HandleScope::HandleScope() : is_closed_(false) {
402   API_ENTRY_CHECK("HandleScope::HandleScope");
403   i::HandleScope::Enter(&previous_);
404 }
405 
406 
~HandleScope()407 HandleScope::~HandleScope() {
408   if (!is_closed_) {
409     i::HandleScope::Leave(&previous_);
410   }
411 }
412 
413 
NumberOfHandles()414 int HandleScope::NumberOfHandles() {
415   return i::HandleScope::NumberOfHandles();
416 }
417 
418 
CreateHandle(i::Object * value)419 i::Object** v8::HandleScope::CreateHandle(i::Object* value) {
420   return i::HandleScope::CreateHandle(value);
421 }
422 
423 
Enter()424 void Context::Enter() {
425   if (IsDeadCheck("v8::Context::Enter()")) return;
426   ENTER_V8;
427   i::Handle<i::Context> env = Utils::OpenHandle(this);
428   thread_local.EnterContext(env);
429 
430   thread_local.SaveContext(i::Top::context());
431   i::Top::set_context(*env);
432 }
433 
434 
Exit()435 void Context::Exit() {
436   if (!i::V8::IsRunning()) return;
437   if (!ApiCheck(thread_local.LeaveLastContext(),
438                 "v8::Context::Exit()",
439                 "Cannot exit non-entered context")) {
440     return;
441   }
442 
443   // Content of 'last_context' could be NULL.
444   i::Context* last_context = thread_local.RestoreContext();
445   i::Top::set_context(last_context);
446 }
447 
448 
SetData(v8::Handle<Value> data)449 void Context::SetData(v8::Handle<Value> data) {
450   if (IsDeadCheck("v8::Context::SetData()")) return;
451   ENTER_V8;
452   {
453     HandleScope scope;
454     i::Handle<i::Context> env = Utils::OpenHandle(this);
455     i::Handle<i::Object> raw_data = Utils::OpenHandle(*data);
456     ASSERT(env->IsGlobalContext());
457     if (env->IsGlobalContext()) {
458       env->set_data(*raw_data);
459     }
460   }
461 }
462 
463 
GetData()464 v8::Local<v8::Value> Context::GetData() {
465   if (IsDeadCheck("v8::Context::GetData()")) return v8::Local<Value>();
466   ENTER_V8;
467   i::Object* raw_result = NULL;
468   {
469     HandleScope scope;
470     i::Handle<i::Context> env = Utils::OpenHandle(this);
471     ASSERT(env->IsGlobalContext());
472     if (env->IsGlobalContext()) {
473       raw_result = env->data();
474     } else {
475       return Local<Value>();
476     }
477   }
478   i::Handle<i::Object> result(raw_result);
479   return Utils::ToLocal(result);
480 }
481 
482 
RawClose(i::Object ** value)483 i::Object** v8::HandleScope::RawClose(i::Object** value) {
484   if (!ApiCheck(!is_closed_,
485                 "v8::HandleScope::Close()",
486                 "Local scope has already been closed")) {
487     return 0;
488   }
489   LOG_API("CloseHandleScope");
490 
491   // Read the result before popping the handle block.
492   i::Object* result = *value;
493   is_closed_ = true;
494   i::HandleScope::Leave(&previous_);
495 
496   // Allocate a new handle on the previous handle block.
497   i::Handle<i::Object> handle(result);
498   return handle.location();
499 }
500 
501 
502 // --- N e a n d e r ---
503 
504 
505 // A constructor cannot easily return an error value, therefore it is necessary
506 // to check for a dead VM with ON_BAILOUT before constructing any Neander
507 // objects.  To remind you about this there is no HandleScope in the
508 // NeanderObject constructor.  When you add one to the site calling the
509 // constructor you should check that you ensured the VM was not dead first.
NeanderObject(int size)510 NeanderObject::NeanderObject(int size) {
511   EnsureInitialized("v8::Nowhere");
512   ENTER_V8;
513   value_ = i::Factory::NewNeanderObject();
514   i::Handle<i::FixedArray> elements = i::Factory::NewFixedArray(size);
515   value_->set_elements(*elements);
516 }
517 
518 
size()519 int NeanderObject::size() {
520   return i::FixedArray::cast(value_->elements())->length();
521 }
522 
523 
NeanderArray()524 NeanderArray::NeanderArray() : obj_(2) {
525   obj_.set(0, i::Smi::FromInt(0));
526 }
527 
528 
length()529 int NeanderArray::length() {
530   return i::Smi::cast(obj_.get(0))->value();
531 }
532 
533 
get(int offset)534 i::Object* NeanderArray::get(int offset) {
535   ASSERT(0 <= offset);
536   ASSERT(offset < length());
537   return obj_.get(offset + 1);
538 }
539 
540 
541 // This method cannot easily return an error value, therefore it is necessary
542 // to check for a dead VM with ON_BAILOUT before calling it.  To remind you
543 // about this there is no HandleScope in this method.  When you add one to the
544 // site calling this method you should check that you ensured the VM was not
545 // dead first.
add(i::Handle<i::Object> value)546 void NeanderArray::add(i::Handle<i::Object> value) {
547   int length = this->length();
548   int size = obj_.size();
549   if (length == size - 1) {
550     i::Handle<i::FixedArray> new_elms = i::Factory::NewFixedArray(2 * size);
551     for (int i = 0; i < length; i++)
552       new_elms->set(i + 1, get(i));
553     obj_.value()->set_elements(*new_elms);
554   }
555   obj_.set(length + 1, *value);
556   obj_.set(0, i::Smi::FromInt(length + 1));
557 }
558 
559 
set(int index,i::Object * value)560 void NeanderArray::set(int index, i::Object* value) {
561   if (index < 0 || index >= this->length()) return;
562   obj_.set(index + 1, value);
563 }
564 
565 
566 // --- T e m p l a t e ---
567 
568 
InitializeTemplate(i::Handle<i::TemplateInfo> that,int type)569 static void InitializeTemplate(i::Handle<i::TemplateInfo> that, int type) {
570   that->set_tag(i::Smi::FromInt(type));
571 }
572 
573 
Set(v8::Handle<String> name,v8::Handle<Data> value,v8::PropertyAttribute attribute)574 void Template::Set(v8::Handle<String> name, v8::Handle<Data> value,
575                    v8::PropertyAttribute attribute) {
576   if (IsDeadCheck("v8::Template::SetProperty()")) return;
577   ENTER_V8;
578   HandleScope scope;
579   i::Handle<i::Object> list(Utils::OpenHandle(this)->property_list());
580   if (list->IsUndefined()) {
581     list = NeanderArray().value();
582     Utils::OpenHandle(this)->set_property_list(*list);
583   }
584   NeanderArray array(list);
585   array.add(Utils::OpenHandle(*name));
586   array.add(Utils::OpenHandle(*value));
587   array.add(Utils::OpenHandle(*v8::Integer::New(attribute)));
588 }
589 
590 
591 // --- F u n c t i o n   T e m p l a t e ---
InitializeFunctionTemplate(i::Handle<i::FunctionTemplateInfo> info)592 static void InitializeFunctionTemplate(
593       i::Handle<i::FunctionTemplateInfo> info) {
594   info->set_tag(i::Smi::FromInt(Consts::FUNCTION_TEMPLATE));
595   info->set_flag(0);
596 }
597 
598 
PrototypeTemplate()599 Local<ObjectTemplate> FunctionTemplate::PrototypeTemplate() {
600   if (IsDeadCheck("v8::FunctionTemplate::PrototypeTemplate()")) {
601     return Local<ObjectTemplate>();
602   }
603   ENTER_V8;
604   i::Handle<i::Object> result(Utils::OpenHandle(this)->prototype_template());
605   if (result->IsUndefined()) {
606     result = Utils::OpenHandle(*ObjectTemplate::New());
607     Utils::OpenHandle(this)->set_prototype_template(*result);
608   }
609   return Local<ObjectTemplate>(ToApi<ObjectTemplate>(result));
610 }
611 
612 
Inherit(v8::Handle<FunctionTemplate> value)613 void FunctionTemplate::Inherit(v8::Handle<FunctionTemplate> value) {
614   if (IsDeadCheck("v8::FunctionTemplate::Inherit()")) return;
615   ENTER_V8;
616   Utils::OpenHandle(this)->set_parent_template(*Utils::OpenHandle(*value));
617 }
618 
619 
620 // To distinguish the function templates, so that we can find them in the
621 // function cache of the global context.
622 static int next_serial_number = 0;
623 
624 
New(InvocationCallback callback,v8::Handle<Value> data,v8::Handle<Signature> signature)625 Local<FunctionTemplate> FunctionTemplate::New(InvocationCallback callback,
626     v8::Handle<Value> data, v8::Handle<Signature> signature) {
627   EnsureInitialized("v8::FunctionTemplate::New()");
628   LOG_API("FunctionTemplate::New");
629   ENTER_V8;
630   i::Handle<i::Struct> struct_obj =
631       i::Factory::NewStruct(i::FUNCTION_TEMPLATE_INFO_TYPE);
632   i::Handle<i::FunctionTemplateInfo> obj =
633       i::Handle<i::FunctionTemplateInfo>::cast(struct_obj);
634   InitializeFunctionTemplate(obj);
635   obj->set_serial_number(i::Smi::FromInt(next_serial_number++));
636   if (callback != 0) {
637     if (data.IsEmpty()) data = v8::Undefined();
638     Utils::ToLocal(obj)->SetCallHandler(callback, data);
639   }
640   obj->set_undetectable(false);
641   obj->set_needs_access_check(false);
642 
643   if (!signature.IsEmpty())
644     obj->set_signature(*Utils::OpenHandle(*signature));
645   return Utils::ToLocal(obj);
646 }
647 
648 
New(Handle<FunctionTemplate> receiver,int argc,Handle<FunctionTemplate> argv[])649 Local<Signature> Signature::New(Handle<FunctionTemplate> receiver,
650       int argc, Handle<FunctionTemplate> argv[]) {
651   EnsureInitialized("v8::Signature::New()");
652   LOG_API("Signature::New");
653   ENTER_V8;
654   i::Handle<i::Struct> struct_obj =
655       i::Factory::NewStruct(i::SIGNATURE_INFO_TYPE);
656   i::Handle<i::SignatureInfo> obj =
657       i::Handle<i::SignatureInfo>::cast(struct_obj);
658   if (!receiver.IsEmpty()) obj->set_receiver(*Utils::OpenHandle(*receiver));
659   if (argc > 0) {
660     i::Handle<i::FixedArray> args = i::Factory::NewFixedArray(argc);
661     for (int i = 0; i < argc; i++) {
662       if (!argv[i].IsEmpty())
663         args->set(i, *Utils::OpenHandle(*argv[i]));
664     }
665     obj->set_args(*args);
666   }
667   return Utils::ToLocal(obj);
668 }
669 
670 
New(Handle<FunctionTemplate> type)671 Local<TypeSwitch> TypeSwitch::New(Handle<FunctionTemplate> type) {
672   Handle<FunctionTemplate> types[1] = { type };
673   return TypeSwitch::New(1, types);
674 }
675 
676 
New(int argc,Handle<FunctionTemplate> types[])677 Local<TypeSwitch> TypeSwitch::New(int argc, Handle<FunctionTemplate> types[]) {
678   EnsureInitialized("v8::TypeSwitch::New()");
679   LOG_API("TypeSwitch::New");
680   ENTER_V8;
681   i::Handle<i::FixedArray> vector = i::Factory::NewFixedArray(argc);
682   for (int i = 0; i < argc; i++)
683     vector->set(i, *Utils::OpenHandle(*types[i]));
684   i::Handle<i::Struct> struct_obj =
685       i::Factory::NewStruct(i::TYPE_SWITCH_INFO_TYPE);
686   i::Handle<i::TypeSwitchInfo> obj =
687       i::Handle<i::TypeSwitchInfo>::cast(struct_obj);
688   obj->set_types(*vector);
689   return Utils::ToLocal(obj);
690 }
691 
692 
match(v8::Handle<Value> value)693 int TypeSwitch::match(v8::Handle<Value> value) {
694   LOG_API("TypeSwitch::match");
695   i::Handle<i::Object> obj = Utils::OpenHandle(*value);
696   i::Handle<i::TypeSwitchInfo> info = Utils::OpenHandle(this);
697   i::FixedArray* types = i::FixedArray::cast(info->types());
698   for (int i = 0; i < types->length(); i++) {
699     if (obj->IsInstanceOf(i::FunctionTemplateInfo::cast(types->get(i))))
700       return i + 1;
701   }
702   return 0;
703 }
704 
705 
SetCallHandler(InvocationCallback callback,v8::Handle<Value> data)706 void FunctionTemplate::SetCallHandler(InvocationCallback callback,
707                                       v8::Handle<Value> data) {
708   if (IsDeadCheck("v8::FunctionTemplate::SetCallHandler()")) return;
709   ENTER_V8;
710   HandleScope scope;
711   i::Handle<i::Struct> struct_obj =
712       i::Factory::NewStruct(i::CALL_HANDLER_INFO_TYPE);
713   i::Handle<i::CallHandlerInfo> obj =
714       i::Handle<i::CallHandlerInfo>::cast(struct_obj);
715   obj->set_callback(*FromCData(callback));
716   if (data.IsEmpty()) data = v8::Undefined();
717   obj->set_data(*Utils::OpenHandle(*data));
718   Utils::OpenHandle(this)->set_call_code(*obj);
719 }
720 
721 
AddInstancePropertyAccessor(v8::Handle<String> name,AccessorGetter getter,AccessorSetter setter,v8::Handle<Value> data,v8::AccessControl settings,v8::PropertyAttribute attributes)722 void FunctionTemplate::AddInstancePropertyAccessor(
723       v8::Handle<String> name,
724       AccessorGetter getter,
725       AccessorSetter setter,
726       v8::Handle<Value> data,
727       v8::AccessControl settings,
728       v8::PropertyAttribute attributes) {
729   if (IsDeadCheck("v8::FunctionTemplate::AddInstancePropertyAccessor()")) {
730     return;
731   }
732   ENTER_V8;
733   HandleScope scope;
734   i::Handle<i::AccessorInfo> obj = i::Factory::NewAccessorInfo();
735   ASSERT(getter != NULL);
736   obj->set_getter(*FromCData(getter));
737   obj->set_setter(*FromCData(setter));
738   if (data.IsEmpty()) data = v8::Undefined();
739   obj->set_data(*Utils::OpenHandle(*data));
740   obj->set_name(*Utils::OpenHandle(*name));
741   if (settings & ALL_CAN_READ) obj->set_all_can_read(true);
742   if (settings & ALL_CAN_WRITE) obj->set_all_can_write(true);
743   if (settings & PROHIBITS_OVERWRITING) obj->set_prohibits_overwriting(true);
744   obj->set_property_attributes(static_cast<PropertyAttributes>(attributes));
745 
746   i::Handle<i::Object> list(Utils::OpenHandle(this)->property_accessors());
747   if (list->IsUndefined()) {
748     list = NeanderArray().value();
749     Utils::OpenHandle(this)->set_property_accessors(*list);
750   }
751   NeanderArray array(list);
752   array.add(obj);
753 }
754 
755 
InstanceTemplate()756 Local<ObjectTemplate> FunctionTemplate::InstanceTemplate() {
757   if (IsDeadCheck("v8::FunctionTemplate::InstanceTemplate()")
758       || EmptyCheck("v8::FunctionTemplate::InstanceTemplate()", this))
759     return Local<ObjectTemplate>();
760   ENTER_V8;
761   if (Utils::OpenHandle(this)->instance_template()->IsUndefined()) {
762     Local<ObjectTemplate> templ =
763         ObjectTemplate::New(v8::Handle<FunctionTemplate>(this));
764     Utils::OpenHandle(this)->set_instance_template(*Utils::OpenHandle(*templ));
765   }
766   i::Handle<i::ObjectTemplateInfo> result(i::ObjectTemplateInfo::cast(
767         Utils::OpenHandle(this)->instance_template()));
768   return Utils::ToLocal(result);
769 }
770 
771 
SetClassName(Handle<String> name)772 void FunctionTemplate::SetClassName(Handle<String> name) {
773   if (IsDeadCheck("v8::FunctionTemplate::SetClassName()")) return;
774   ENTER_V8;
775   Utils::OpenHandle(this)->set_class_name(*Utils::OpenHandle(*name));
776 }
777 
778 
SetHiddenPrototype(bool value)779 void FunctionTemplate::SetHiddenPrototype(bool value) {
780   if (IsDeadCheck("v8::FunctionTemplate::SetHiddenPrototype()")) return;
781   ENTER_V8;
782   Utils::OpenHandle(this)->set_hidden_prototype(value);
783 }
784 
785 
SetNamedInstancePropertyHandler(NamedPropertyGetter getter,NamedPropertySetter setter,NamedPropertyQuery query,NamedPropertyDeleter remover,NamedPropertyEnumerator enumerator,Handle<Value> data)786 void FunctionTemplate::SetNamedInstancePropertyHandler(
787       NamedPropertyGetter getter,
788       NamedPropertySetter setter,
789       NamedPropertyQuery query,
790       NamedPropertyDeleter remover,
791       NamedPropertyEnumerator enumerator,
792       Handle<Value> data) {
793   if (IsDeadCheck("v8::FunctionTemplate::SetNamedInstancePropertyHandler()")) {
794     return;
795   }
796   ENTER_V8;
797   HandleScope scope;
798   i::Handle<i::Struct> struct_obj =
799       i::Factory::NewStruct(i::INTERCEPTOR_INFO_TYPE);
800   i::Handle<i::InterceptorInfo> obj =
801       i::Handle<i::InterceptorInfo>::cast(struct_obj);
802   if (getter != 0) obj->set_getter(*FromCData(getter));
803   if (setter != 0) obj->set_setter(*FromCData(setter));
804   if (query != 0) obj->set_query(*FromCData(query));
805   if (remover != 0) obj->set_deleter(*FromCData(remover));
806   if (enumerator != 0) obj->set_enumerator(*FromCData(enumerator));
807   if (data.IsEmpty()) data = v8::Undefined();
808   obj->set_data(*Utils::OpenHandle(*data));
809   Utils::OpenHandle(this)->set_named_property_handler(*obj);
810 }
811 
812 
SetIndexedInstancePropertyHandler(IndexedPropertyGetter getter,IndexedPropertySetter setter,IndexedPropertyQuery query,IndexedPropertyDeleter remover,IndexedPropertyEnumerator enumerator,Handle<Value> data)813 void FunctionTemplate::SetIndexedInstancePropertyHandler(
814       IndexedPropertyGetter getter,
815       IndexedPropertySetter setter,
816       IndexedPropertyQuery query,
817       IndexedPropertyDeleter remover,
818       IndexedPropertyEnumerator enumerator,
819       Handle<Value> data) {
820   if (IsDeadCheck(
821         "v8::FunctionTemplate::SetIndexedInstancePropertyHandler()")) {
822     return;
823   }
824   ENTER_V8;
825   HandleScope scope;
826   i::Handle<i::Struct> struct_obj =
827       i::Factory::NewStruct(i::INTERCEPTOR_INFO_TYPE);
828   i::Handle<i::InterceptorInfo> obj =
829       i::Handle<i::InterceptorInfo>::cast(struct_obj);
830   if (getter != 0) obj->set_getter(*FromCData(getter));
831   if (setter != 0) obj->set_setter(*FromCData(setter));
832   if (query != 0) obj->set_query(*FromCData(query));
833   if (remover != 0) obj->set_deleter(*FromCData(remover));
834   if (enumerator != 0) obj->set_enumerator(*FromCData(enumerator));
835   if (data.IsEmpty()) data = v8::Undefined();
836   obj->set_data(*Utils::OpenHandle(*data));
837   Utils::OpenHandle(this)->set_indexed_property_handler(*obj);
838 }
839 
840 
SetInstanceCallAsFunctionHandler(InvocationCallback callback,Handle<Value> data)841 void FunctionTemplate::SetInstanceCallAsFunctionHandler(
842       InvocationCallback callback,
843       Handle<Value> data) {
844   if (IsDeadCheck("v8::FunctionTemplate::SetInstanceCallAsFunctionHandler()")) {
845     return;
846   }
847   ENTER_V8;
848   HandleScope scope;
849   i::Handle<i::Struct> struct_obj =
850       i::Factory::NewStruct(i::CALL_HANDLER_INFO_TYPE);
851   i::Handle<i::CallHandlerInfo> obj =
852       i::Handle<i::CallHandlerInfo>::cast(struct_obj);
853   obj->set_callback(*FromCData(callback));
854   if (data.IsEmpty()) data = v8::Undefined();
855   obj->set_data(*Utils::OpenHandle(*data));
856   Utils::OpenHandle(this)->set_instance_call_handler(*obj);
857 }
858 
859 
860 // --- O b j e c t T e m p l a t e ---
861 
862 
New()863 Local<ObjectTemplate> ObjectTemplate::New() {
864   return New(Local<FunctionTemplate>());
865 }
866 
867 
New(v8::Handle<FunctionTemplate> constructor)868 Local<ObjectTemplate> ObjectTemplate::New(
869       v8::Handle<FunctionTemplate> constructor) {
870   if (IsDeadCheck("v8::ObjectTemplate::New()")) return Local<ObjectTemplate>();
871   EnsureInitialized("v8::ObjectTemplate::New()");
872   LOG_API("ObjectTemplate::New");
873   ENTER_V8;
874   i::Handle<i::Struct> struct_obj =
875       i::Factory::NewStruct(i::OBJECT_TEMPLATE_INFO_TYPE);
876   i::Handle<i::ObjectTemplateInfo> obj =
877       i::Handle<i::ObjectTemplateInfo>::cast(struct_obj);
878   InitializeTemplate(obj, Consts::OBJECT_TEMPLATE);
879   if (!constructor.IsEmpty())
880     obj->set_constructor(*Utils::OpenHandle(*constructor));
881   obj->set_internal_field_count(i::Smi::FromInt(0));
882   return Utils::ToLocal(obj);
883 }
884 
885 
886 // Ensure that the object template has a constructor.  If no
887 // constructor is available we create one.
EnsureConstructor(ObjectTemplate * object_template)888 static void EnsureConstructor(ObjectTemplate* object_template) {
889   if (Utils::OpenHandle(object_template)->constructor()->IsUndefined()) {
890     Local<FunctionTemplate> templ = FunctionTemplate::New();
891     i::Handle<i::FunctionTemplateInfo> constructor = Utils::OpenHandle(*templ);
892     constructor->set_instance_template(*Utils::OpenHandle(object_template));
893     Utils::OpenHandle(object_template)->set_constructor(*constructor);
894   }
895 }
896 
897 
SetAccessor(v8::Handle<String> name,AccessorGetter getter,AccessorSetter setter,v8::Handle<Value> data,AccessControl settings,PropertyAttribute attribute)898 void ObjectTemplate::SetAccessor(v8::Handle<String> name,
899                                  AccessorGetter getter,
900                                  AccessorSetter setter,
901                                  v8::Handle<Value> data,
902                                  AccessControl settings,
903                                  PropertyAttribute attribute) {
904   if (IsDeadCheck("v8::ObjectTemplate::SetAccessor()")) return;
905   ENTER_V8;
906   HandleScope scope;
907   EnsureConstructor(this);
908   i::FunctionTemplateInfo* constructor =
909       i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
910   i::Handle<i::FunctionTemplateInfo> cons(constructor);
911   Utils::ToLocal(cons)->AddInstancePropertyAccessor(name,
912                                                     getter,
913                                                     setter,
914                                                     data,
915                                                     settings,
916                                                     attribute);
917 }
918 
919 
SetNamedPropertyHandler(NamedPropertyGetter getter,NamedPropertySetter setter,NamedPropertyQuery query,NamedPropertyDeleter remover,NamedPropertyEnumerator enumerator,Handle<Value> data)920 void ObjectTemplate::SetNamedPropertyHandler(NamedPropertyGetter getter,
921                                              NamedPropertySetter setter,
922                                              NamedPropertyQuery query,
923                                              NamedPropertyDeleter remover,
924                                              NamedPropertyEnumerator enumerator,
925                                              Handle<Value> data) {
926   if (IsDeadCheck("v8::ObjectTemplate::SetNamedPropertyHandler()")) return;
927   ENTER_V8;
928   HandleScope scope;
929   EnsureConstructor(this);
930   i::FunctionTemplateInfo* constructor =
931       i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
932   i::Handle<i::FunctionTemplateInfo> cons(constructor);
933   Utils::ToLocal(cons)->SetNamedInstancePropertyHandler(getter,
934                                                         setter,
935                                                         query,
936                                                         remover,
937                                                         enumerator,
938                                                         data);
939 }
940 
941 
MarkAsUndetectable()942 void ObjectTemplate::MarkAsUndetectable() {
943   if (IsDeadCheck("v8::ObjectTemplate::MarkAsUndetectable()")) return;
944   ENTER_V8;
945   HandleScope scope;
946   EnsureConstructor(this);
947   i::FunctionTemplateInfo* constructor =
948       i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
949   i::Handle<i::FunctionTemplateInfo> cons(constructor);
950   cons->set_undetectable(true);
951 }
952 
953 
SetAccessCheckCallbacks(NamedSecurityCallback named_callback,IndexedSecurityCallback indexed_callback,Handle<Value> data,bool turned_on_by_default)954 void ObjectTemplate::SetAccessCheckCallbacks(
955       NamedSecurityCallback named_callback,
956       IndexedSecurityCallback indexed_callback,
957       Handle<Value> data,
958       bool turned_on_by_default) {
959   if (IsDeadCheck("v8::ObjectTemplate::SetAccessCheckCallbacks()")) return;
960   ENTER_V8;
961   HandleScope scope;
962   EnsureConstructor(this);
963 
964   i::Handle<i::Struct> struct_info =
965       i::Factory::NewStruct(i::ACCESS_CHECK_INFO_TYPE);
966   i::Handle<i::AccessCheckInfo> info =
967       i::Handle<i::AccessCheckInfo>::cast(struct_info);
968   info->set_named_callback(*FromCData(named_callback));
969   info->set_indexed_callback(*FromCData(indexed_callback));
970   if (data.IsEmpty()) data = v8::Undefined();
971   info->set_data(*Utils::OpenHandle(*data));
972 
973   i::FunctionTemplateInfo* constructor =
974       i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
975   i::Handle<i::FunctionTemplateInfo> cons(constructor);
976   cons->set_access_check_info(*info);
977   cons->set_needs_access_check(turned_on_by_default);
978 }
979 
980 
SetIndexedPropertyHandler(IndexedPropertyGetter getter,IndexedPropertySetter setter,IndexedPropertyQuery query,IndexedPropertyDeleter remover,IndexedPropertyEnumerator enumerator,Handle<Value> data)981 void ObjectTemplate::SetIndexedPropertyHandler(
982       IndexedPropertyGetter getter,
983       IndexedPropertySetter setter,
984       IndexedPropertyQuery query,
985       IndexedPropertyDeleter remover,
986       IndexedPropertyEnumerator enumerator,
987       Handle<Value> data) {
988   if (IsDeadCheck("v8::ObjectTemplate::SetIndexedPropertyHandler()")) return;
989   ENTER_V8;
990   HandleScope scope;
991   EnsureConstructor(this);
992   i::FunctionTemplateInfo* constructor =
993       i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
994   i::Handle<i::FunctionTemplateInfo> cons(constructor);
995   Utils::ToLocal(cons)->SetIndexedInstancePropertyHandler(getter,
996                                                           setter,
997                                                           query,
998                                                           remover,
999                                                           enumerator,
1000                                                           data);
1001 }
1002 
1003 
SetCallAsFunctionHandler(InvocationCallback callback,Handle<Value> data)1004 void ObjectTemplate::SetCallAsFunctionHandler(InvocationCallback callback,
1005                                               Handle<Value> data) {
1006   if (IsDeadCheck("v8::ObjectTemplate::SetCallAsFunctionHandler()")) return;
1007   ENTER_V8;
1008   HandleScope scope;
1009   EnsureConstructor(this);
1010   i::FunctionTemplateInfo* constructor =
1011       i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1012   i::Handle<i::FunctionTemplateInfo> cons(constructor);
1013   Utils::ToLocal(cons)->SetInstanceCallAsFunctionHandler(callback, data);
1014 }
1015 
1016 
InternalFieldCount()1017 int ObjectTemplate::InternalFieldCount() {
1018   if (IsDeadCheck("v8::ObjectTemplate::InternalFieldCount()")) {
1019     return 0;
1020   }
1021   return i::Smi::cast(Utils::OpenHandle(this)->internal_field_count())->value();
1022 }
1023 
1024 
SetInternalFieldCount(int value)1025 void ObjectTemplate::SetInternalFieldCount(int value) {
1026   if (IsDeadCheck("v8::ObjectTemplate::SetInternalFieldCount()")) return;
1027   if (!ApiCheck(i::Smi::IsValid(value),
1028                 "v8::ObjectTemplate::SetInternalFieldCount()",
1029                 "Invalid internal field count")) {
1030     return;
1031   }
1032   ENTER_V8;
1033   if (value > 0) {
1034     // The internal field count is set by the constructor function's
1035     // construct code, so we ensure that there is a constructor
1036     // function to do the setting.
1037     EnsureConstructor(this);
1038   }
1039   Utils::OpenHandle(this)->set_internal_field_count(i::Smi::FromInt(value));
1040 }
1041 
1042 
1043 // --- S c r i p t D a t a ---
1044 
1045 
PreCompile(const char * input,int length)1046 ScriptData* ScriptData::PreCompile(const char* input, int length) {
1047   unibrow::Utf8InputBuffer<> buf(input, length);
1048   return i::PreParse(i::Handle<i::String>(), &buf, NULL);
1049 }
1050 
1051 
New(unsigned * data,int length)1052 ScriptData* ScriptData::New(unsigned* data, int length) {
1053   return new i::ScriptDataImpl(i::Vector<unsigned>(data, length));
1054 }
1055 
1056 
1057 // --- S c r i p t ---
1058 
1059 
New(v8::Handle<String> source,v8::ScriptOrigin * origin,v8::ScriptData * script_data)1060 Local<Script> Script::New(v8::Handle<String> source,
1061                           v8::ScriptOrigin* origin,
1062                           v8::ScriptData* script_data) {
1063   ON_BAILOUT("v8::Script::New()", return Local<Script>());
1064   LOG_API("Script::New");
1065   ENTER_V8;
1066   i::Handle<i::String> str = Utils::OpenHandle(*source);
1067   i::Handle<i::Object> name_obj;
1068   int line_offset = 0;
1069   int column_offset = 0;
1070   if (origin != NULL) {
1071     if (!origin->ResourceName().IsEmpty()) {
1072       name_obj = Utils::OpenHandle(*origin->ResourceName());
1073     }
1074     if (!origin->ResourceLineOffset().IsEmpty()) {
1075       line_offset = static_cast<int>(origin->ResourceLineOffset()->Value());
1076     }
1077     if (!origin->ResourceColumnOffset().IsEmpty()) {
1078       column_offset = static_cast<int>(origin->ResourceColumnOffset()->Value());
1079     }
1080   }
1081   EXCEPTION_PREAMBLE();
1082   i::ScriptDataImpl* pre_data = static_cast<i::ScriptDataImpl*>(script_data);
1083   // We assert that the pre-data is sane, even though we can actually
1084   // handle it if it turns out not to be in release mode.
1085   ASSERT(pre_data == NULL || pre_data->SanityCheck());
1086   // If the pre-data isn't sane we simply ignore it
1087   if (pre_data != NULL && !pre_data->SanityCheck()) {
1088     pre_data = NULL;
1089   }
1090   i::Handle<i::JSFunction> boilerplate = i::Compiler::Compile(str,
1091                                                               name_obj,
1092                                                               line_offset,
1093                                                               column_offset,
1094                                                               NULL,
1095                                                               pre_data);
1096   has_pending_exception = boilerplate.is_null();
1097   EXCEPTION_BAILOUT_CHECK(Local<Script>());
1098   return Local<Script>(ToApi<Script>(boilerplate));
1099 }
1100 
1101 
New(v8::Handle<String> source,v8::Handle<Value> file_name)1102 Local<Script> Script::New(v8::Handle<String> source,
1103                           v8::Handle<Value> file_name) {
1104   ScriptOrigin origin(file_name);
1105   return New(source, &origin);
1106 }
1107 
1108 
Compile(v8::Handle<String> source,v8::ScriptOrigin * origin,v8::ScriptData * script_data)1109 Local<Script> Script::Compile(v8::Handle<String> source,
1110                               v8::ScriptOrigin* origin,
1111                               v8::ScriptData* script_data) {
1112   ON_BAILOUT("v8::Script::Compile()", return Local<Script>());
1113   LOG_API("Script::Compile");
1114   ENTER_V8;
1115   Local<Script> generic = New(source, origin, script_data);
1116   if (generic.IsEmpty())
1117     return generic;
1118   i::Handle<i::JSFunction> boilerplate = Utils::OpenHandle(*generic);
1119   i::Handle<i::JSFunction> result =
1120       i::Factory::NewFunctionFromBoilerplate(boilerplate,
1121                                              i::Top::global_context());
1122   return Local<Script>(ToApi<Script>(result));
1123 }
1124 
1125 
Compile(v8::Handle<String> source,v8::Handle<Value> file_name)1126 Local<Script> Script::Compile(v8::Handle<String> source,
1127                               v8::Handle<Value> file_name) {
1128   ScriptOrigin origin(file_name);
1129   return Compile(source, &origin);
1130 }
1131 
1132 
Run()1133 Local<Value> Script::Run() {
1134   ON_BAILOUT("v8::Script::Run()", return Local<Value>());
1135   LOG_API("Script::Run");
1136   ENTER_V8;
1137   i::Object* raw_result = NULL;
1138   {
1139     HandleScope scope;
1140     i::Handle<i::JSFunction> fun = Utils::OpenHandle(this);
1141     if (fun->IsBoilerplate()) {
1142       fun = i::Factory::NewFunctionFromBoilerplate(fun,
1143                                                    i::Top::global_context());
1144     }
1145     EXCEPTION_PREAMBLE();
1146     i::Handle<i::Object> receiver(i::Top::context()->global_proxy());
1147     i::Handle<i::Object> result =
1148         i::Execution::Call(fun, receiver, 0, NULL, &has_pending_exception);
1149     EXCEPTION_BAILOUT_CHECK(Local<Value>());
1150     raw_result = *result;
1151   }
1152   i::Handle<i::Object> result(raw_result);
1153   return Utils::ToLocal(result);
1154 }
1155 
1156 
Id()1157 Local<Value> Script::Id() {
1158   ON_BAILOUT("v8::Script::Id()", return Local<Value>());
1159   LOG_API("Script::Id");
1160   i::Object* raw_id = NULL;
1161   {
1162     HandleScope scope;
1163     i::Handle<i::JSFunction> fun = Utils::OpenHandle(this);
1164     i::Handle<i::Script> script(i::Script::cast(fun->shared()->script()));
1165     i::Handle<i::Object> id(script->id());
1166     raw_id = *id;
1167   }
1168   i::Handle<i::Object> id(raw_id);
1169   return Utils::ToLocal(id);
1170 }
1171 
1172 
SetData(v8::Handle<Value> data)1173 void Script::SetData(v8::Handle<Value> data) {
1174   ON_BAILOUT("v8::Script::SetData()", return);
1175   LOG_API("Script::SetData");
1176   {
1177     HandleScope scope;
1178     i::Handle<i::JSFunction> fun = Utils::OpenHandle(this);
1179     i::Handle<i::Object> raw_data = Utils::OpenHandle(*data);
1180     i::Handle<i::Script> script(i::Script::cast(fun->shared()->script()));
1181     script->set_data(*raw_data);
1182   }
1183 }
1184 
1185 
1186 // --- E x c e p t i o n s ---
1187 
1188 
TryCatch()1189 v8::TryCatch::TryCatch()
1190     : next_(i::Top::try_catch_handler()),
1191       exception_(i::Heap::the_hole_value()),
1192       message_(i::Smi::FromInt(0)),
1193       is_verbose_(false),
1194       capture_message_(true),
1195       js_handler_(NULL) {
1196   i::Top::RegisterTryCatchHandler(this);
1197 }
1198 
1199 
~TryCatch()1200 v8::TryCatch::~TryCatch() {
1201   i::Top::UnregisterTryCatchHandler(this);
1202 }
1203 
1204 
HasCaught() const1205 bool v8::TryCatch::HasCaught() const {
1206   return !reinterpret_cast<i::Object*>(exception_)->IsTheHole();
1207 }
1208 
1209 
CanContinue() const1210 bool v8::TryCatch::CanContinue() const {
1211   return can_continue_;
1212 }
1213 
1214 
Exception() const1215 v8::Local<Value> v8::TryCatch::Exception() const {
1216   if (HasCaught()) {
1217     // Check for out of memory exception.
1218     i::Object* exception = reinterpret_cast<i::Object*>(exception_);
1219     return v8::Utils::ToLocal(i::Handle<i::Object>(exception));
1220   } else {
1221     return v8::Local<Value>();
1222   }
1223 }
1224 
1225 
StackTrace() const1226 v8::Local<Value> v8::TryCatch::StackTrace() const {
1227   if (HasCaught()) {
1228     i::Object* raw_obj = reinterpret_cast<i::Object*>(exception_);
1229     if (!raw_obj->IsJSObject()) return v8::Local<Value>();
1230     v8::HandleScope scope;
1231     i::Handle<i::JSObject> obj(i::JSObject::cast(raw_obj));
1232     i::Handle<i::String> name = i::Factory::LookupAsciiSymbol("stack");
1233     if (!obj->HasProperty(*name))
1234       return v8::Local<Value>();
1235     return scope.Close(v8::Utils::ToLocal(i::GetProperty(obj, name)));
1236   } else {
1237     return v8::Local<Value>();
1238   }
1239 }
1240 
1241 
Message() const1242 v8::Local<v8::Message> v8::TryCatch::Message() const {
1243   if (HasCaught() && message_ != i::Smi::FromInt(0)) {
1244     i::Object* message = reinterpret_cast<i::Object*>(message_);
1245     return v8::Utils::MessageToLocal(i::Handle<i::Object>(message));
1246   } else {
1247     return v8::Local<v8::Message>();
1248   }
1249 }
1250 
1251 
Reset()1252 void v8::TryCatch::Reset() {
1253   exception_ = i::Heap::the_hole_value();
1254   message_ = i::Smi::FromInt(0);
1255 }
1256 
1257 
SetVerbose(bool value)1258 void v8::TryCatch::SetVerbose(bool value) {
1259   is_verbose_ = value;
1260 }
1261 
1262 
SetCaptureMessage(bool value)1263 void v8::TryCatch::SetCaptureMessage(bool value) {
1264   capture_message_ = value;
1265 }
1266 
1267 
1268 // --- M e s s a g e ---
1269 
1270 
Get() const1271 Local<String> Message::Get() const {
1272   ON_BAILOUT("v8::Message::Get()", return Local<String>());
1273   ENTER_V8;
1274   HandleScope scope;
1275   i::Handle<i::Object> obj = Utils::OpenHandle(this);
1276   i::Handle<i::String> raw_result = i::MessageHandler::GetMessage(obj);
1277   Local<String> result = Utils::ToLocal(raw_result);
1278   return scope.Close(result);
1279 }
1280 
1281 
GetScriptResourceName() const1282 v8::Handle<Value> Message::GetScriptResourceName() const {
1283   if (IsDeadCheck("v8::Message::GetScriptResourceName()")) {
1284     return Local<String>();
1285   }
1286   ENTER_V8;
1287   HandleScope scope;
1288   i::Handle<i::JSObject> obj =
1289       i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
1290   // Return this.script.name.
1291   i::Handle<i::JSValue> script =
1292       i::Handle<i::JSValue>::cast(GetProperty(obj, "script"));
1293   i::Handle<i::Object> resource_name(i::Script::cast(script->value())->name());
1294   return scope.Close(Utils::ToLocal(resource_name));
1295 }
1296 
1297 
GetScriptData() const1298 v8::Handle<Value> Message::GetScriptData() const {
1299   if (IsDeadCheck("v8::Message::GetScriptResourceData()")) {
1300     return Local<Value>();
1301   }
1302   ENTER_V8;
1303   HandleScope scope;
1304   i::Handle<i::JSObject> obj =
1305       i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
1306   // Return this.script.data.
1307   i::Handle<i::JSValue> script =
1308       i::Handle<i::JSValue>::cast(GetProperty(obj, "script"));
1309   i::Handle<i::Object> data(i::Script::cast(script->value())->data());
1310   return scope.Close(Utils::ToLocal(data));
1311 }
1312 
1313 
CallV8HeapFunction(const char * name,i::Handle<i::Object> recv,int argc,i::Object ** argv[],bool * has_pending_exception)1314 static i::Handle<i::Object> CallV8HeapFunction(const char* name,
1315                                                i::Handle<i::Object> recv,
1316                                                int argc,
1317                                                i::Object** argv[],
1318                                                bool* has_pending_exception) {
1319   i::Handle<i::String> fmt_str = i::Factory::LookupAsciiSymbol(name);
1320   i::Object* object_fun = i::Top::builtins()->GetProperty(*fmt_str);
1321   i::Handle<i::JSFunction> fun =
1322       i::Handle<i::JSFunction>(i::JSFunction::cast(object_fun));
1323   i::Handle<i::Object> value =
1324       i::Execution::Call(fun, recv, argc, argv, has_pending_exception);
1325   return value;
1326 }
1327 
1328 
CallV8HeapFunction(const char * name,i::Handle<i::Object> data,bool * has_pending_exception)1329 static i::Handle<i::Object> CallV8HeapFunction(const char* name,
1330                                                i::Handle<i::Object> data,
1331                                                bool* has_pending_exception) {
1332   i::Object** argv[1] = { data.location() };
1333   return CallV8HeapFunction(name,
1334                             i::Top::builtins(),
1335                             1,
1336                             argv,
1337                             has_pending_exception);
1338 }
1339 
1340 
GetLineNumber() const1341 int Message::GetLineNumber() const {
1342   ON_BAILOUT("v8::Message::GetLineNumber()", return -1);
1343   ENTER_V8;
1344   HandleScope scope;
1345   EXCEPTION_PREAMBLE();
1346   i::Handle<i::Object> result = CallV8HeapFunction("GetLineNumber",
1347                                                    Utils::OpenHandle(this),
1348                                                    &has_pending_exception);
1349   EXCEPTION_BAILOUT_CHECK(0);
1350   return static_cast<int>(result->Number());
1351 }
1352 
1353 
GetStartPosition() const1354 int Message::GetStartPosition() const {
1355   if (IsDeadCheck("v8::Message::GetStartPosition()")) return 0;
1356   ENTER_V8;
1357   HandleScope scope;
1358 
1359   i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1360   return static_cast<int>(GetProperty(data_obj, "startPos")->Number());
1361 }
1362 
1363 
GetEndPosition() const1364 int Message::GetEndPosition() const {
1365   if (IsDeadCheck("v8::Message::GetEndPosition()")) return 0;
1366   ENTER_V8;
1367   HandleScope scope;
1368   i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1369   return static_cast<int>(GetProperty(data_obj, "endPos")->Number());
1370 }
1371 
1372 
GetStartColumn() const1373 int Message::GetStartColumn() const {
1374   if (IsDeadCheck("v8::Message::GetStartColumn()")) return 0;
1375   ENTER_V8;
1376   HandleScope scope;
1377   i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1378   EXCEPTION_PREAMBLE();
1379   i::Handle<i::Object> start_col_obj = CallV8HeapFunction(
1380       "GetPositionInLine",
1381       data_obj,
1382       &has_pending_exception);
1383   EXCEPTION_BAILOUT_CHECK(0);
1384   return static_cast<int>(start_col_obj->Number());
1385 }
1386 
1387 
GetEndColumn() const1388 int Message::GetEndColumn() const {
1389   if (IsDeadCheck("v8::Message::GetEndColumn()")) return 0;
1390   ENTER_V8;
1391   HandleScope scope;
1392   i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1393   EXCEPTION_PREAMBLE();
1394   i::Handle<i::Object> start_col_obj = CallV8HeapFunction(
1395       "GetPositionInLine",
1396       data_obj,
1397       &has_pending_exception);
1398   EXCEPTION_BAILOUT_CHECK(0);
1399   int start = static_cast<int>(GetProperty(data_obj, "startPos")->Number());
1400   int end = static_cast<int>(GetProperty(data_obj, "endPos")->Number());
1401   return static_cast<int>(start_col_obj->Number()) + (end - start);
1402 }
1403 
1404 
GetSourceLine() const1405 Local<String> Message::GetSourceLine() const {
1406   ON_BAILOUT("v8::Message::GetSourceLine()", return Local<String>());
1407   ENTER_V8;
1408   HandleScope scope;
1409   EXCEPTION_PREAMBLE();
1410   i::Handle<i::Object> result = CallV8HeapFunction("GetSourceLine",
1411                                                    Utils::OpenHandle(this),
1412                                                    &has_pending_exception);
1413   EXCEPTION_BAILOUT_CHECK(Local<v8::String>());
1414   if (result->IsString()) {
1415     return scope.Close(Utils::ToLocal(i::Handle<i::String>::cast(result)));
1416   } else {
1417     return Local<String>();
1418   }
1419 }
1420 
1421 
PrintCurrentStackTrace(FILE * out)1422 void Message::PrintCurrentStackTrace(FILE* out) {
1423   if (IsDeadCheck("v8::Message::PrintCurrentStackTrace()")) return;
1424   ENTER_V8;
1425   i::Top::PrintCurrentStackTrace(out);
1426 }
1427 
1428 
1429 // --- D a t a ---
1430 
IsUndefined() const1431 bool Value::IsUndefined() const {
1432   if (IsDeadCheck("v8::Value::IsUndefined()")) return false;
1433   return Utils::OpenHandle(this)->IsUndefined();
1434 }
1435 
1436 
IsNull() const1437 bool Value::IsNull() const {
1438   if (IsDeadCheck("v8::Value::IsNull()")) return false;
1439   return Utils::OpenHandle(this)->IsNull();
1440 }
1441 
1442 
IsTrue() const1443 bool Value::IsTrue() const {
1444   if (IsDeadCheck("v8::Value::IsTrue()")) return false;
1445   return Utils::OpenHandle(this)->IsTrue();
1446 }
1447 
1448 
IsFalse() const1449 bool Value::IsFalse() const {
1450   if (IsDeadCheck("v8::Value::IsFalse()")) return false;
1451   return Utils::OpenHandle(this)->IsFalse();
1452 }
1453 
1454 
IsFunction() const1455 bool Value::IsFunction() const {
1456   if (IsDeadCheck("v8::Value::IsFunction()")) return false;
1457   return Utils::OpenHandle(this)->IsJSFunction();
1458 }
1459 
1460 
FullIsString() const1461 bool Value::FullIsString() const {
1462   if (IsDeadCheck("v8::Value::IsString()")) return false;
1463   bool result = Utils::OpenHandle(this)->IsString();
1464   ASSERT_EQ(result, QuickIsString());
1465   return result;
1466 }
1467 
1468 
IsArray() const1469 bool Value::IsArray() const {
1470   if (IsDeadCheck("v8::Value::IsArray()")) return false;
1471   return Utils::OpenHandle(this)->IsJSArray();
1472 }
1473 
1474 
IsObject() const1475 bool Value::IsObject() const {
1476   if (IsDeadCheck("v8::Value::IsObject()")) return false;
1477   return Utils::OpenHandle(this)->IsJSObject();
1478 }
1479 
1480 
IsNumber() const1481 bool Value::IsNumber() const {
1482   if (IsDeadCheck("v8::Value::IsNumber()")) return false;
1483   return Utils::OpenHandle(this)->IsNumber();
1484 }
1485 
1486 
IsBoolean() const1487 bool Value::IsBoolean() const {
1488   if (IsDeadCheck("v8::Value::IsBoolean()")) return false;
1489   return Utils::OpenHandle(this)->IsBoolean();
1490 }
1491 
1492 
IsExternal() const1493 bool Value::IsExternal() const {
1494   if (IsDeadCheck("v8::Value::IsExternal()")) return false;
1495   return Utils::OpenHandle(this)->IsProxy();
1496 }
1497 
1498 
IsInt32() const1499 bool Value::IsInt32() const {
1500   if (IsDeadCheck("v8::Value::IsInt32()")) return false;
1501   i::Handle<i::Object> obj = Utils::OpenHandle(this);
1502   if (obj->IsSmi()) return true;
1503   if (obj->IsNumber()) {
1504     double value = obj->Number();
1505     return i::FastI2D(i::FastD2I(value)) == value;
1506   }
1507   return false;
1508 }
1509 
1510 
IsDate() const1511 bool Value::IsDate() const {
1512   if (IsDeadCheck("v8::Value::IsDate()")) return false;
1513   i::Handle<i::Object> obj = Utils::OpenHandle(this);
1514   return obj->HasSpecificClassOf(i::Heap::Date_symbol());
1515 }
1516 
1517 
ToString() const1518 Local<String> Value::ToString() const {
1519   if (IsDeadCheck("v8::Value::ToString()")) return Local<String>();
1520   LOG_API("ToString");
1521   i::Handle<i::Object> obj = Utils::OpenHandle(this);
1522   i::Handle<i::Object> str;
1523   if (obj->IsString()) {
1524     str = obj;
1525   } else {
1526     ENTER_V8;
1527     EXCEPTION_PREAMBLE();
1528     str = i::Execution::ToString(obj, &has_pending_exception);
1529     EXCEPTION_BAILOUT_CHECK(Local<String>());
1530   }
1531   return Local<String>(ToApi<String>(str));
1532 }
1533 
1534 
ToDetailString() const1535 Local<String> Value::ToDetailString() const {
1536   if (IsDeadCheck("v8::Value::ToDetailString()")) return Local<String>();
1537   LOG_API("ToDetailString");
1538   i::Handle<i::Object> obj = Utils::OpenHandle(this);
1539   i::Handle<i::Object> str;
1540   if (obj->IsString()) {
1541     str = obj;
1542   } else {
1543     ENTER_V8;
1544     EXCEPTION_PREAMBLE();
1545     str = i::Execution::ToDetailString(obj, &has_pending_exception);
1546     EXCEPTION_BAILOUT_CHECK(Local<String>());
1547   }
1548   return Local<String>(ToApi<String>(str));
1549 }
1550 
1551 
ToObject() const1552 Local<v8::Object> Value::ToObject() const {
1553   if (IsDeadCheck("v8::Value::ToObject()")) return Local<v8::Object>();
1554   LOG_API("ToObject");
1555   i::Handle<i::Object> obj = Utils::OpenHandle(this);
1556   i::Handle<i::Object> val;
1557   if (obj->IsJSObject()) {
1558     val = obj;
1559   } else {
1560     ENTER_V8;
1561     EXCEPTION_PREAMBLE();
1562     val = i::Execution::ToObject(obj, &has_pending_exception);
1563     EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
1564   }
1565   return Local<v8::Object>(ToApi<Object>(val));
1566 }
1567 
1568 
ToBoolean() const1569 Local<Boolean> Value::ToBoolean() const {
1570   if (IsDeadCheck("v8::Value::ToBoolean()")) return Local<Boolean>();
1571   LOG_API("ToBoolean");
1572   i::Handle<i::Object> obj = Utils::OpenHandle(this);
1573   if (obj->IsBoolean()) {
1574     return Local<Boolean>(ToApi<Boolean>(obj));
1575   } else {
1576     ENTER_V8;
1577     i::Handle<i::Object> val = i::Execution::ToBoolean(obj);
1578     return Local<Boolean>(ToApi<Boolean>(val));
1579   }
1580 }
1581 
1582 
ToNumber() const1583 Local<Number> Value::ToNumber() const {
1584   if (IsDeadCheck("v8::Value::ToNumber()")) return Local<Number>();
1585   LOG_API("ToNumber");
1586   i::Handle<i::Object> obj = Utils::OpenHandle(this);
1587   i::Handle<i::Object> num;
1588   if (obj->IsNumber()) {
1589     num = obj;
1590   } else {
1591     ENTER_V8;
1592     EXCEPTION_PREAMBLE();
1593     num = i::Execution::ToNumber(obj, &has_pending_exception);
1594     EXCEPTION_BAILOUT_CHECK(Local<Number>());
1595   }
1596   return Local<Number>(ToApi<Number>(num));
1597 }
1598 
1599 
ToInteger() const1600 Local<Integer> Value::ToInteger() const {
1601   if (IsDeadCheck("v8::Value::ToInteger()")) return Local<Integer>();
1602   LOG_API("ToInteger");
1603   i::Handle<i::Object> obj = Utils::OpenHandle(this);
1604   i::Handle<i::Object> num;
1605   if (obj->IsSmi()) {
1606     num = obj;
1607   } else {
1608     ENTER_V8;
1609     EXCEPTION_PREAMBLE();
1610     num = i::Execution::ToInteger(obj, &has_pending_exception);
1611     EXCEPTION_BAILOUT_CHECK(Local<Integer>());
1612   }
1613   return Local<Integer>(ToApi<Integer>(num));
1614 }
1615 
1616 
CheckCast(v8::Value * that)1617 void External::CheckCast(v8::Value* that) {
1618   if (IsDeadCheck("v8::External::Cast()")) return;
1619   i::Handle<i::Object> obj = Utils::OpenHandle(that);
1620   ApiCheck(obj->IsProxy(),
1621            "v8::External::Cast()",
1622            "Could not convert to external");
1623 }
1624 
1625 
CheckCast(Value * that)1626 void v8::Object::CheckCast(Value* that) {
1627   if (IsDeadCheck("v8::Object::Cast()")) return;
1628   i::Handle<i::Object> obj = Utils::OpenHandle(that);
1629   ApiCheck(obj->IsJSObject(),
1630            "v8::Object::Cast()",
1631            "Could not convert to object");
1632 }
1633 
1634 
CheckCast(Value * that)1635 void v8::Function::CheckCast(Value* that) {
1636   if (IsDeadCheck("v8::Function::Cast()")) return;
1637   i::Handle<i::Object> obj = Utils::OpenHandle(that);
1638   ApiCheck(obj->IsJSFunction(),
1639            "v8::Function::Cast()",
1640            "Could not convert to function");
1641 }
1642 
1643 
CheckCast(v8::Value * that)1644 void v8::String::CheckCast(v8::Value* that) {
1645   if (IsDeadCheck("v8::String::Cast()")) return;
1646   i::Handle<i::Object> obj = Utils::OpenHandle(that);
1647   ApiCheck(obj->IsString(),
1648            "v8::String::Cast()",
1649            "Could not convert to string");
1650 }
1651 
1652 
CheckCast(v8::Value * that)1653 void v8::Number::CheckCast(v8::Value* that) {
1654   if (IsDeadCheck("v8::Number::Cast()")) return;
1655   i::Handle<i::Object> obj = Utils::OpenHandle(that);
1656   ApiCheck(obj->IsNumber(),
1657            "v8::Number::Cast()",
1658            "Could not convert to number");
1659 }
1660 
1661 
CheckCast(v8::Value * that)1662 void v8::Integer::CheckCast(v8::Value* that) {
1663   if (IsDeadCheck("v8::Integer::Cast()")) return;
1664   i::Handle<i::Object> obj = Utils::OpenHandle(that);
1665   ApiCheck(obj->IsNumber(),
1666            "v8::Integer::Cast()",
1667            "Could not convert to number");
1668 }
1669 
1670 
CheckCast(Value * that)1671 void v8::Array::CheckCast(Value* that) {
1672   if (IsDeadCheck("v8::Array::Cast()")) return;
1673   i::Handle<i::Object> obj = Utils::OpenHandle(that);
1674   ApiCheck(obj->IsJSArray(),
1675            "v8::Array::Cast()",
1676            "Could not convert to array");
1677 }
1678 
1679 
CheckCast(v8::Value * that)1680 void v8::Date::CheckCast(v8::Value* that) {
1681   if (IsDeadCheck("v8::Date::Cast()")) return;
1682   i::Handle<i::Object> obj = Utils::OpenHandle(that);
1683   ApiCheck(obj->HasSpecificClassOf(i::Heap::Date_symbol()),
1684            "v8::Date::Cast()",
1685            "Could not convert to date");
1686 }
1687 
1688 
BooleanValue() const1689 bool Value::BooleanValue() const {
1690   if (IsDeadCheck("v8::Value::BooleanValue()")) return false;
1691   LOG_API("BooleanValue");
1692   i::Handle<i::Object> obj = Utils::OpenHandle(this);
1693   if (obj->IsBoolean()) {
1694     return obj->IsTrue();
1695   } else {
1696     ENTER_V8;
1697     i::Handle<i::Object> value = i::Execution::ToBoolean(obj);
1698     return value->IsTrue();
1699   }
1700 }
1701 
1702 
NumberValue() const1703 double Value::NumberValue() const {
1704   if (IsDeadCheck("v8::Value::NumberValue()")) return i::OS::nan_value();
1705   LOG_API("NumberValue");
1706   i::Handle<i::Object> obj = Utils::OpenHandle(this);
1707   i::Handle<i::Object> num;
1708   if (obj->IsNumber()) {
1709     num = obj;
1710   } else {
1711     ENTER_V8;
1712     EXCEPTION_PREAMBLE();
1713     num = i::Execution::ToNumber(obj, &has_pending_exception);
1714     EXCEPTION_BAILOUT_CHECK(i::OS::nan_value());
1715   }
1716   return num->Number();
1717 }
1718 
1719 
IntegerValue() const1720 int64_t Value::IntegerValue() const {
1721   if (IsDeadCheck("v8::Value::IntegerValue()")) return 0;
1722   LOG_API("IntegerValue");
1723   i::Handle<i::Object> obj = Utils::OpenHandle(this);
1724   i::Handle<i::Object> num;
1725   if (obj->IsNumber()) {
1726     num = obj;
1727   } else {
1728     ENTER_V8;
1729     EXCEPTION_PREAMBLE();
1730     num = i::Execution::ToInteger(obj, &has_pending_exception);
1731     EXCEPTION_BAILOUT_CHECK(0);
1732   }
1733   if (num->IsSmi()) {
1734     return i::Smi::cast(*num)->value();
1735   } else {
1736     return static_cast<int64_t>(num->Number());
1737   }
1738 }
1739 
1740 
ToInt32() const1741 Local<Int32> Value::ToInt32() const {
1742   if (IsDeadCheck("v8::Value::ToInt32()")) return Local<Int32>();
1743   LOG_API("ToInt32");
1744   i::Handle<i::Object> obj = Utils::OpenHandle(this);
1745   i::Handle<i::Object> num;
1746   if (obj->IsSmi()) {
1747     num = obj;
1748   } else {
1749     ENTER_V8;
1750     EXCEPTION_PREAMBLE();
1751     num = i::Execution::ToInt32(obj, &has_pending_exception);
1752     EXCEPTION_BAILOUT_CHECK(Local<Int32>());
1753   }
1754   return Local<Int32>(ToApi<Int32>(num));
1755 }
1756 
1757 
ToUint32() const1758 Local<Uint32> Value::ToUint32() const {
1759   if (IsDeadCheck("v8::Value::ToUint32()")) return Local<Uint32>();
1760   LOG_API("ToUInt32");
1761   i::Handle<i::Object> obj = Utils::OpenHandle(this);
1762   i::Handle<i::Object> num;
1763   if (obj->IsSmi()) {
1764     num = obj;
1765   } else {
1766     ENTER_V8;
1767     EXCEPTION_PREAMBLE();
1768     num = i::Execution::ToUint32(obj, &has_pending_exception);
1769     EXCEPTION_BAILOUT_CHECK(Local<Uint32>());
1770   }
1771   return Local<Uint32>(ToApi<Uint32>(num));
1772 }
1773 
1774 
ToArrayIndex() const1775 Local<Uint32> Value::ToArrayIndex() const {
1776   if (IsDeadCheck("v8::Value::ToArrayIndex()")) return Local<Uint32>();
1777   LOG_API("ToArrayIndex");
1778   i::Handle<i::Object> obj = Utils::OpenHandle(this);
1779   if (obj->IsSmi()) {
1780     if (i::Smi::cast(*obj)->value() >= 0) return Utils::Uint32ToLocal(obj);
1781     return Local<Uint32>();
1782   }
1783   ENTER_V8;
1784   EXCEPTION_PREAMBLE();
1785   i::Handle<i::Object> string_obj =
1786       i::Execution::ToString(obj, &has_pending_exception);
1787   EXCEPTION_BAILOUT_CHECK(Local<Uint32>());
1788   i::Handle<i::String> str = i::Handle<i::String>::cast(string_obj);
1789   uint32_t index;
1790   if (str->AsArrayIndex(&index)) {
1791     i::Handle<i::Object> value;
1792     if (index <= static_cast<uint32_t>(i::Smi::kMaxValue)) {
1793       value = i::Handle<i::Object>(i::Smi::FromInt(index));
1794     } else {
1795       value = i::Factory::NewNumber(index);
1796     }
1797     return Utils::Uint32ToLocal(value);
1798   }
1799   return Local<Uint32>();
1800 }
1801 
1802 
Int32Value() const1803 int32_t Value::Int32Value() const {
1804   if (IsDeadCheck("v8::Value::Int32Value()")) return 0;
1805   LOG_API("Int32Value");
1806   i::Handle<i::Object> obj = Utils::OpenHandle(this);
1807   if (obj->IsSmi()) {
1808     return i::Smi::cast(*obj)->value();
1809   } else {
1810     LOG_API("Int32Value (slow)");
1811     ENTER_V8;
1812     EXCEPTION_PREAMBLE();
1813     i::Handle<i::Object> num =
1814         i::Execution::ToInt32(obj, &has_pending_exception);
1815     EXCEPTION_BAILOUT_CHECK(0);
1816     if (num->IsSmi()) {
1817       return i::Smi::cast(*num)->value();
1818     } else {
1819       return static_cast<int32_t>(num->Number());
1820     }
1821   }
1822 }
1823 
1824 
Equals(Handle<Value> that) const1825 bool Value::Equals(Handle<Value> that) const {
1826   if (IsDeadCheck("v8::Value::Equals()")
1827       || EmptyCheck("v8::Value::Equals()", this)
1828       || EmptyCheck("v8::Value::Equals()", that)) {
1829     return false;
1830   }
1831   LOG_API("Equals");
1832   ENTER_V8;
1833   i::Handle<i::Object> obj = Utils::OpenHandle(this);
1834   i::Handle<i::Object> other = Utils::OpenHandle(*that);
1835   i::Object** args[1] = { other.location() };
1836   EXCEPTION_PREAMBLE();
1837   i::Handle<i::Object> result =
1838       CallV8HeapFunction("EQUALS", obj, 1, args, &has_pending_exception);
1839   EXCEPTION_BAILOUT_CHECK(false);
1840   return *result == i::Smi::FromInt(i::EQUAL);
1841 }
1842 
1843 
StrictEquals(Handle<Value> that) const1844 bool Value::StrictEquals(Handle<Value> that) const {
1845   if (IsDeadCheck("v8::Value::StrictEquals()")
1846       || EmptyCheck("v8::Value::StrictEquals()", this)
1847       || EmptyCheck("v8::Value::StrictEquals()", that)) {
1848     return false;
1849   }
1850   LOG_API("StrictEquals");
1851   i::Handle<i::Object> obj = Utils::OpenHandle(this);
1852   i::Handle<i::Object> other = Utils::OpenHandle(*that);
1853   // Must check HeapNumber first, since NaN !== NaN.
1854   if (obj->IsHeapNumber()) {
1855     if (!other->IsNumber()) return false;
1856     double x = obj->Number();
1857     double y = other->Number();
1858     // Must check explicitly for NaN:s on Windows, but -0 works fine.
1859     return x == y && !isnan(x) && !isnan(y);
1860   } else if (*obj == *other) {  // Also covers Booleans.
1861     return true;
1862   } else if (obj->IsSmi()) {
1863     return other->IsNumber() && obj->Number() == other->Number();
1864   } else if (obj->IsString()) {
1865     return other->IsString() &&
1866       i::String::cast(*obj)->Equals(i::String::cast(*other));
1867   } else if (obj->IsUndefined() || obj->IsUndetectableObject()) {
1868     return other->IsUndefined() || other->IsUndetectableObject();
1869   } else {
1870     return false;
1871   }
1872 }
1873 
1874 
Uint32Value() const1875 uint32_t Value::Uint32Value() const {
1876   if (IsDeadCheck("v8::Value::Uint32Value()")) return 0;
1877   LOG_API("Uint32Value");
1878   i::Handle<i::Object> obj = Utils::OpenHandle(this);
1879   if (obj->IsSmi()) {
1880     return i::Smi::cast(*obj)->value();
1881   } else {
1882     ENTER_V8;
1883     EXCEPTION_PREAMBLE();
1884     i::Handle<i::Object> num =
1885         i::Execution::ToUint32(obj, &has_pending_exception);
1886     EXCEPTION_BAILOUT_CHECK(0);
1887     if (num->IsSmi()) {
1888       return i::Smi::cast(*num)->value();
1889     } else {
1890       return static_cast<uint32_t>(num->Number());
1891     }
1892   }
1893 }
1894 
1895 
Set(v8::Handle<Value> key,v8::Handle<Value> value,v8::PropertyAttribute attribs)1896 bool v8::Object::Set(v8::Handle<Value> key, v8::Handle<Value> value,
1897                      v8::PropertyAttribute attribs) {
1898   ON_BAILOUT("v8::Object::Set()", return false);
1899   ENTER_V8;
1900   i::Handle<i::Object> self = Utils::OpenHandle(this);
1901   i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
1902   i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
1903   EXCEPTION_PREAMBLE();
1904   i::Handle<i::Object> obj = i::SetProperty(
1905       self,
1906       key_obj,
1907       value_obj,
1908       static_cast<PropertyAttributes>(attribs));
1909   has_pending_exception = obj.is_null();
1910   EXCEPTION_BAILOUT_CHECK(false);
1911   return true;
1912 }
1913 
1914 
ForceSet(v8::Handle<Value> key,v8::Handle<Value> value,v8::PropertyAttribute attribs)1915 bool v8::Object::ForceSet(v8::Handle<Value> key,
1916                           v8::Handle<Value> value,
1917                           v8::PropertyAttribute attribs) {
1918   ON_BAILOUT("v8::Object::ForceSet()", return false);
1919   ENTER_V8;
1920   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1921   i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
1922   i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
1923   EXCEPTION_PREAMBLE();
1924   i::Handle<i::Object> obj = i::ForceSetProperty(
1925       self,
1926       key_obj,
1927       value_obj,
1928       static_cast<PropertyAttributes>(attribs));
1929   has_pending_exception = obj.is_null();
1930   EXCEPTION_BAILOUT_CHECK(false);
1931   return true;
1932 }
1933 
1934 
ForceDelete(v8::Handle<Value> key)1935 bool v8::Object::ForceDelete(v8::Handle<Value> key) {
1936   ON_BAILOUT("v8::Object::ForceDelete()", return false);
1937   ENTER_V8;
1938   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1939   i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
1940   EXCEPTION_PREAMBLE();
1941   i::Handle<i::Object> obj = i::ForceDeleteProperty(self, key_obj);
1942   has_pending_exception = obj.is_null();
1943   EXCEPTION_BAILOUT_CHECK(false);
1944   return obj->IsTrue();
1945 }
1946 
1947 
Get(v8::Handle<Value> key)1948 Local<Value> v8::Object::Get(v8::Handle<Value> key) {
1949   ON_BAILOUT("v8::Object::Get()", return Local<v8::Value>());
1950   ENTER_V8;
1951   i::Handle<i::Object> self = Utils::OpenHandle(this);
1952   i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
1953   EXCEPTION_PREAMBLE();
1954   i::Handle<i::Object> result = i::GetProperty(self, key_obj);
1955   has_pending_exception = result.is_null();
1956   EXCEPTION_BAILOUT_CHECK(Local<Value>());
1957   return Utils::ToLocal(result);
1958 }
1959 
1960 
GetPrototype()1961 Local<Value> v8::Object::GetPrototype() {
1962   ON_BAILOUT("v8::Object::GetPrototype()", return Local<v8::Value>());
1963   ENTER_V8;
1964   i::Handle<i::Object> self = Utils::OpenHandle(this);
1965   i::Handle<i::Object> result = i::GetPrototype(self);
1966   return Utils::ToLocal(result);
1967 }
1968 
1969 
FindInstanceInPrototypeChain(v8::Handle<FunctionTemplate> tmpl)1970 Local<Object> v8::Object::FindInstanceInPrototypeChain(
1971     v8::Handle<FunctionTemplate> tmpl) {
1972   ON_BAILOUT("v8::Object::FindInstanceInPrototypeChain()",
1973              return Local<v8::Object>());
1974   ENTER_V8;
1975   i::JSObject* object = *Utils::OpenHandle(this);
1976   i::FunctionTemplateInfo* tmpl_info = *Utils::OpenHandle(*tmpl);
1977   while (!object->IsInstanceOf(tmpl_info)) {
1978     i::Object* prototype = object->GetPrototype();
1979     if (!prototype->IsJSObject()) return Local<Object>();
1980     object = i::JSObject::cast(prototype);
1981   }
1982   return Utils::ToLocal(i::Handle<i::JSObject>(object));
1983 }
1984 
1985 
GetPropertyNames()1986 Local<Array> v8::Object::GetPropertyNames() {
1987   ON_BAILOUT("v8::Object::GetPropertyNames()", return Local<v8::Array>());
1988   ENTER_V8;
1989   v8::HandleScope scope;
1990   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1991   i::Handle<i::FixedArray> value = i::GetKeysInFixedArrayFor(self);
1992   // Because we use caching to speed up enumeration it is important
1993   // to never change the result of the basic enumeration function so
1994   // we clone the result.
1995   i::Handle<i::FixedArray> elms = i::Factory::CopyFixedArray(value);
1996   i::Handle<i::JSArray> result = i::Factory::NewJSArrayWithElements(elms);
1997   return scope.Close(Utils::ToLocal(result));
1998 }
1999 
2000 
ObjectProtoToString()2001 Local<String> v8::Object::ObjectProtoToString() {
2002   ON_BAILOUT("v8::Object::ObjectProtoToString()", return Local<v8::String>());
2003   ENTER_V8;
2004   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2005 
2006   i::Handle<i::Object> name(self->class_name());
2007 
2008   // Native implementation of Object.prototype.toString (v8natives.js):
2009   //   var c = %ClassOf(this);
2010   //   if (c === 'Arguments') c  = 'Object';
2011   //   return "[object " + c + "]";
2012 
2013   if (!name->IsString()) {
2014     return v8::String::New("[object ]");
2015 
2016   } else {
2017     i::Handle<i::String> class_name = i::Handle<i::String>::cast(name);
2018     if (class_name->IsEqualTo(i::CStrVector("Arguments"))) {
2019       return v8::String::New("[object Object]");
2020 
2021     } else {
2022       const char* prefix = "[object ";
2023       Local<String> str = Utils::ToLocal(class_name);
2024       const char* postfix = "]";
2025 
2026       size_t prefix_len = strlen(prefix);
2027       size_t str_len = str->Length();
2028       size_t postfix_len = strlen(postfix);
2029 
2030       size_t buf_len = prefix_len + str_len + postfix_len;
2031       char* buf = i::NewArray<char>(buf_len);
2032 
2033       // Write prefix.
2034       char* ptr = buf;
2035       memcpy(ptr, prefix, prefix_len * v8::internal::kCharSize);
2036       ptr += prefix_len;
2037 
2038       // Write real content.
2039       str->WriteAscii(ptr, 0, str_len);
2040       ptr += str_len;
2041 
2042       // Write postfix.
2043       memcpy(ptr, postfix, postfix_len * v8::internal::kCharSize);
2044 
2045       // Copy the buffer into a heap-allocated string and return it.
2046       Local<String> result = v8::String::New(buf, buf_len);
2047       i::DeleteArray(buf);
2048       return result;
2049     }
2050   }
2051 }
2052 
2053 
Delete(v8::Handle<String> key)2054 bool v8::Object::Delete(v8::Handle<String> key) {
2055   ON_BAILOUT("v8::Object::Delete()", return false);
2056   ENTER_V8;
2057   HandleScope scope;
2058   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2059   i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2060   return i::DeleteProperty(self, key_obj)->IsTrue();
2061 }
2062 
2063 
Has(v8::Handle<String> key)2064 bool v8::Object::Has(v8::Handle<String> key) {
2065   ON_BAILOUT("v8::Object::Has()", return false);
2066   ENTER_V8;
2067   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2068   i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2069   return self->HasProperty(*key_obj);
2070 }
2071 
2072 
Delete(uint32_t index)2073 bool v8::Object::Delete(uint32_t index) {
2074   ON_BAILOUT("v8::Object::DeleteProperty()", return false);
2075   ENTER_V8;
2076   HandleScope scope;
2077   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2078   return i::DeleteElement(self, index)->IsTrue();
2079 }
2080 
2081 
Has(uint32_t index)2082 bool v8::Object::Has(uint32_t index) {
2083   ON_BAILOUT("v8::Object::HasProperty()", return false);
2084   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2085   return self->HasElement(index);
2086 }
2087 
2088 
HasRealNamedProperty(Handle<String> key)2089 bool v8::Object::HasRealNamedProperty(Handle<String> key) {
2090   ON_BAILOUT("v8::Object::HasRealNamedProperty()", return false);
2091   return Utils::OpenHandle(this)->HasRealNamedProperty(
2092       *Utils::OpenHandle(*key));
2093 }
2094 
2095 
HasRealIndexedProperty(uint32_t index)2096 bool v8::Object::HasRealIndexedProperty(uint32_t index) {
2097   ON_BAILOUT("v8::Object::HasRealIndexedProperty()", return false);
2098   return Utils::OpenHandle(this)->HasRealElementProperty(index);
2099 }
2100 
2101 
HasRealNamedCallbackProperty(Handle<String> key)2102 bool v8::Object::HasRealNamedCallbackProperty(Handle<String> key) {
2103   ON_BAILOUT("v8::Object::HasRealNamedCallbackProperty()", return false);
2104   ENTER_V8;
2105   return Utils::OpenHandle(this)->HasRealNamedCallbackProperty(
2106       *Utils::OpenHandle(*key));
2107 }
2108 
2109 
HasNamedLookupInterceptor()2110 bool v8::Object::HasNamedLookupInterceptor() {
2111   ON_BAILOUT("v8::Object::HasNamedLookupInterceptor()", return false);
2112   return Utils::OpenHandle(this)->HasNamedInterceptor();
2113 }
2114 
2115 
HasIndexedLookupInterceptor()2116 bool v8::Object::HasIndexedLookupInterceptor() {
2117   ON_BAILOUT("v8::Object::HasIndexedLookupInterceptor()", return false);
2118   return Utils::OpenHandle(this)->HasIndexedInterceptor();
2119 }
2120 
2121 
GetRealNamedPropertyInPrototypeChain(Handle<String> key)2122 Handle<Value> v8::Object::GetRealNamedPropertyInPrototypeChain(
2123       Handle<String> key) {
2124   ON_BAILOUT("v8::Object::GetRealNamedPropertyInPrototypeChain()",
2125              return Local<Value>());
2126   ENTER_V8;
2127   i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this);
2128   i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2129   i::LookupResult lookup;
2130   self_obj->LookupRealNamedPropertyInPrototypes(*key_obj, &lookup);
2131   if (lookup.IsValid()) {
2132     PropertyAttributes attributes;
2133     i::Handle<i::Object> result(self_obj->GetProperty(*self_obj,
2134                                                       &lookup,
2135                                                       *key_obj,
2136                                                       &attributes));
2137     return Utils::ToLocal(result);
2138   }
2139   return Local<Value>();  // No real property was found in prototype chain.
2140 }
2141 
2142 
2143 // Turns on access checks by copying the map and setting the check flag.
2144 // Because the object gets a new map, existing inline cache caching
2145 // the old map of this object will fail.
TurnOnAccessCheck()2146 void v8::Object::TurnOnAccessCheck() {
2147   ON_BAILOUT("v8::Object::TurnOnAccessCheck()", return);
2148   ENTER_V8;
2149   i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
2150 
2151   i::Handle<i::Map> new_map =
2152     i::Factory::CopyMapDropTransitions(i::Handle<i::Map>(obj->map()));
2153   new_map->set_is_access_check_needed(true);
2154   obj->set_map(*new_map);
2155 }
2156 
2157 
Clone()2158 Local<v8::Object> v8::Object::Clone() {
2159   ON_BAILOUT("v8::Object::Clone()", return Local<Object>());
2160   ENTER_V8;
2161   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2162   EXCEPTION_PREAMBLE();
2163   i::Handle<i::JSObject> result = i::Copy(self);
2164   has_pending_exception = result.is_null();
2165   EXCEPTION_BAILOUT_CHECK(Local<Object>());
2166   return Utils::ToLocal(result);
2167 }
2168 
2169 
GetIdentityHash()2170 int v8::Object::GetIdentityHash() {
2171   ON_BAILOUT("v8::Object::GetIdentityHash()", return 0);
2172   ENTER_V8;
2173   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2174   i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, true));
2175   i::Handle<i::Object> hash_symbol = i::Factory::identity_hash_symbol();
2176   i::Handle<i::Object> hash = i::GetProperty(hidden_props, hash_symbol);
2177   int hash_value;
2178   if (hash->IsSmi()) {
2179     hash_value = i::Smi::cast(*hash)->value();
2180   } else {
2181     int attempts = 0;
2182     do {
2183       // Generate a random 32-bit hash value but limit range to fit
2184       // within a smi.
2185       hash_value = i::V8::Random() & i::Smi::kMaxValue;
2186       attempts++;
2187     } while (hash_value == 0 && attempts < 30);
2188     hash_value = hash_value != 0 ? hash_value : 1;  // never return 0
2189     i::SetProperty(hidden_props,
2190                    hash_symbol,
2191                    i::Handle<i::Object>(i::Smi::FromInt(hash_value)),
2192                    static_cast<PropertyAttributes>(None));
2193   }
2194   return hash_value;
2195 }
2196 
2197 
SetHiddenValue(v8::Handle<v8::String> key,v8::Handle<v8::Value> value)2198 bool v8::Object::SetHiddenValue(v8::Handle<v8::String> key,
2199                                 v8::Handle<v8::Value> value) {
2200   ON_BAILOUT("v8::Object::SetHiddenValue()", return false);
2201   ENTER_V8;
2202   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2203   i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, true));
2204   i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2205   i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2206   EXCEPTION_PREAMBLE();
2207   i::Handle<i::Object> obj = i::SetProperty(
2208       hidden_props,
2209       key_obj,
2210       value_obj,
2211       static_cast<PropertyAttributes>(None));
2212   has_pending_exception = obj.is_null();
2213   EXCEPTION_BAILOUT_CHECK(false);
2214   return true;
2215 }
2216 
2217 
GetHiddenValue(v8::Handle<v8::String> key)2218 v8::Local<v8::Value> v8::Object::GetHiddenValue(v8::Handle<v8::String> key) {
2219   ON_BAILOUT("v8::Object::GetHiddenValue()", return Local<v8::Value>());
2220   ENTER_V8;
2221   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2222   i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, false));
2223   if (hidden_props->IsUndefined()) {
2224     return v8::Local<v8::Value>();
2225   }
2226   i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2227   EXCEPTION_PREAMBLE();
2228   i::Handle<i::Object> result = i::GetProperty(hidden_props, key_obj);
2229   has_pending_exception = result.is_null();
2230   EXCEPTION_BAILOUT_CHECK(v8::Local<v8::Value>());
2231   if (result->IsUndefined()) {
2232     return v8::Local<v8::Value>();
2233   }
2234   return Utils::ToLocal(result);
2235 }
2236 
2237 
DeleteHiddenValue(v8::Handle<v8::String> key)2238 bool v8::Object::DeleteHiddenValue(v8::Handle<v8::String> key) {
2239   ON_BAILOUT("v8::DeleteHiddenValue()", return false);
2240   ENTER_V8;
2241   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2242   i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, false));
2243   if (hidden_props->IsUndefined()) {
2244     return true;
2245   }
2246   i::Handle<i::JSObject> js_obj(i::JSObject::cast(*hidden_props));
2247   i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2248   return i::DeleteProperty(js_obj, key_obj)->IsTrue();
2249 }
2250 
2251 
SetIndexedPropertiesToPixelData(uint8_t * data,int length)2252 void v8::Object::SetIndexedPropertiesToPixelData(uint8_t* data, int length) {
2253   ON_BAILOUT("v8::SetElementsToPixelData()", return);
2254   ENTER_V8;
2255   if (!ApiCheck(i::Smi::IsValid(length),
2256                 "v8::Object::SetIndexedPropertiesToPixelData()",
2257                 "length exceeds max acceptable value")) {
2258     return;
2259   }
2260   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2261   if (!ApiCheck(!self->IsJSArray(),
2262                 "v8::Object::SetIndexedPropertiesToPixelData()",
2263                 "JSArray is not supported")) {
2264     return;
2265   }
2266   i::Handle<i::PixelArray> pixels = i::Factory::NewPixelArray(length, data);
2267   self->set_elements(*pixels);
2268 }
2269 
2270 
NewInstance() const2271 Local<v8::Object> Function::NewInstance() const {
2272   return NewInstance(0, NULL);
2273 }
2274 
2275 
NewInstance(int argc,v8::Handle<v8::Value> argv[]) const2276 Local<v8::Object> Function::NewInstance(int argc,
2277                                         v8::Handle<v8::Value> argv[]) const {
2278   ON_BAILOUT("v8::Function::NewInstance()", return Local<v8::Object>());
2279   LOG_API("Function::NewInstance");
2280   ENTER_V8;
2281   HandleScope scope;
2282   i::Handle<i::JSFunction> function = Utils::OpenHandle(this);
2283   STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
2284   i::Object*** args = reinterpret_cast<i::Object***>(argv);
2285   EXCEPTION_PREAMBLE();
2286   i::Handle<i::Object> returned =
2287       i::Execution::New(function, argc, args, &has_pending_exception);
2288   EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
2289   return scope.Close(Utils::ToLocal(i::Handle<i::JSObject>::cast(returned)));
2290 }
2291 
2292 
Call(v8::Handle<v8::Object> recv,int argc,v8::Handle<v8::Value> argv[])2293 Local<v8::Value> Function::Call(v8::Handle<v8::Object> recv, int argc,
2294                                 v8::Handle<v8::Value> argv[]) {
2295   ON_BAILOUT("v8::Function::Call()", return Local<v8::Value>());
2296   LOG_API("Function::Call");
2297   ENTER_V8;
2298   i::Object* raw_result = NULL;
2299   {
2300     HandleScope scope;
2301     i::Handle<i::JSFunction> fun = Utils::OpenHandle(this);
2302     i::Handle<i::Object> recv_obj = Utils::OpenHandle(*recv);
2303     STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
2304     i::Object*** args = reinterpret_cast<i::Object***>(argv);
2305     EXCEPTION_PREAMBLE();
2306     i::Handle<i::Object> returned =
2307         i::Execution::Call(fun, recv_obj, argc, args, &has_pending_exception);
2308     EXCEPTION_BAILOUT_CHECK(Local<Object>());
2309     raw_result = *returned;
2310   }
2311   i::Handle<i::Object> result(raw_result);
2312   return Utils::ToLocal(result);
2313 }
2314 
2315 
SetName(v8::Handle<v8::String> name)2316 void Function::SetName(v8::Handle<v8::String> name) {
2317   ENTER_V8;
2318   i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2319   func->shared()->set_name(*Utils::OpenHandle(*name));
2320 }
2321 
2322 
GetName() const2323 Handle<Value> Function::GetName() const {
2324   i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2325   return Utils::ToLocal(i::Handle<i::Object>(func->shared()->name()));
2326 }
2327 
2328 
Length() const2329 int String::Length() const {
2330   if (IsDeadCheck("v8::String::Length()")) return 0;
2331   return Utils::OpenHandle(this)->length();
2332 }
2333 
2334 
Utf8Length() const2335 int String::Utf8Length() const {
2336   if (IsDeadCheck("v8::String::Utf8Length()")) return 0;
2337   return Utils::OpenHandle(this)->Utf8Length();
2338 }
2339 
2340 
WriteUtf8(char * buffer,int capacity) const2341 int String::WriteUtf8(char* buffer, int capacity) const {
2342   if (IsDeadCheck("v8::String::WriteUtf8()")) return 0;
2343   LOG_API("String::WriteUtf8");
2344   ENTER_V8;
2345   i::Handle<i::String> str = Utils::OpenHandle(this);
2346   write_input_buffer.Reset(0, *str);
2347   int len = str->length();
2348   // Encode the first K - 3 bytes directly into the buffer since we
2349   // know there's room for them.  If no capacity is given we copy all
2350   // of them here.
2351   int fast_end = capacity - (unibrow::Utf8::kMaxEncodedSize - 1);
2352   int i;
2353   int pos = 0;
2354   for (i = 0; i < len && (capacity == -1 || pos < fast_end); i++) {
2355     i::uc32 c = write_input_buffer.GetNext();
2356     int written = unibrow::Utf8::Encode(buffer + pos, c);
2357     pos += written;
2358   }
2359   if (i < len) {
2360     // For the last characters we need to check the length for each one
2361     // because they may be longer than the remaining space in the
2362     // buffer.
2363     char intermediate[unibrow::Utf8::kMaxEncodedSize];
2364     for (; i < len && pos < capacity; i++) {
2365       i::uc32 c = write_input_buffer.GetNext();
2366       int written = unibrow::Utf8::Encode(intermediate, c);
2367       if (pos + written <= capacity) {
2368         for (int j = 0; j < written; j++)
2369           buffer[pos + j] = intermediate[j];
2370         pos += written;
2371       } else {
2372         // We've reached the end of the buffer
2373         break;
2374       }
2375     }
2376   }
2377   if (i == len && (capacity == -1 || pos < capacity))
2378     buffer[pos++] = '\0';
2379   return pos;
2380 }
2381 
2382 
WriteAscii(char * buffer,int start,int length) const2383 int String::WriteAscii(char* buffer, int start, int length) const {
2384   if (IsDeadCheck("v8::String::WriteAscii()")) return 0;
2385   LOG_API("String::WriteAscii");
2386   ENTER_V8;
2387   ASSERT(start >= 0 && length >= -1);
2388   i::Handle<i::String> str = Utils::OpenHandle(this);
2389   // Flatten the string for efficiency.  This applies whether we are
2390   // using StringInputBuffer or Get(i) to access the characters.
2391   str->TryFlattenIfNotFlat();
2392   int end = length;
2393   if ( (length == -1) || (length > str->length() - start) )
2394     end = str->length() - start;
2395   if (end < 0) return 0;
2396   write_input_buffer.Reset(start, *str);
2397   int i;
2398   for (i = 0; i < end; i++) {
2399     char c = static_cast<char>(write_input_buffer.GetNext());
2400     if (c == '\0') c = ' ';
2401     buffer[i] = c;
2402   }
2403   if (length == -1 || i < length)
2404     buffer[i] = '\0';
2405   return i;
2406 }
2407 
2408 
Write(uint16_t * buffer,int start,int length) const2409 int String::Write(uint16_t* buffer, int start, int length) const {
2410   if (IsDeadCheck("v8::String::Write()")) return 0;
2411   LOG_API("String::Write");
2412   ENTER_V8;
2413   ASSERT(start >= 0 && length >= -1);
2414   i::Handle<i::String> str = Utils::OpenHandle(this);
2415   // Flatten the string for efficiency.  This applies whether we are
2416   // using StringInputBuffer or Get(i) to access the characters.
2417   str->TryFlattenIfNotFlat();
2418   int end = length;
2419   if ( (length == -1) || (length > str->length() - start) )
2420     end = str->length() - start;
2421   if (end < 0) return 0;
2422   write_input_buffer.Reset(start, *str);
2423   int i;
2424   for (i = 0; i < end; i++)
2425     buffer[i] = write_input_buffer.GetNext();
2426   if (length == -1 || i < length)
2427     buffer[i] = '\0';
2428   return i;
2429 }
2430 
2431 
IsExternal() const2432 bool v8::String::IsExternal() const {
2433   EnsureInitialized("v8::String::IsExternal()");
2434   i::Handle<i::String> str = Utils::OpenHandle(this);
2435   return i::StringShape(*str).IsExternalTwoByte();
2436 }
2437 
2438 
IsExternalAscii() const2439 bool v8::String::IsExternalAscii() const {
2440   EnsureInitialized("v8::String::IsExternalAscii()");
2441   i::Handle<i::String> str = Utils::OpenHandle(this);
2442   return i::StringShape(*str).IsExternalAscii();
2443 }
2444 
2445 
VerifyExternalStringResource(v8::String::ExternalStringResource * value) const2446 void v8::String::VerifyExternalStringResource(
2447     v8::String::ExternalStringResource* value) const {
2448   i::Handle<i::String> str = Utils::OpenHandle(this);
2449   v8::String::ExternalStringResource* expected;
2450   if (i::StringShape(*str).IsExternalTwoByte()) {
2451     void* resource = i::Handle<i::ExternalTwoByteString>::cast(str)->resource();
2452     expected = reinterpret_cast<ExternalStringResource*>(resource);
2453   } else {
2454     expected = NULL;
2455   }
2456   CHECK_EQ(expected, value);
2457 }
2458 
2459 
2460 v8::String::ExternalAsciiStringResource*
GetExternalAsciiStringResource() const2461       v8::String::GetExternalAsciiStringResource() const {
2462   EnsureInitialized("v8::String::GetExternalAsciiStringResource()");
2463   i::Handle<i::String> str = Utils::OpenHandle(this);
2464   if (i::StringShape(*str).IsExternalAscii()) {
2465     void* resource = i::Handle<i::ExternalAsciiString>::cast(str)->resource();
2466     return reinterpret_cast<ExternalAsciiStringResource*>(resource);
2467   } else {
2468     return NULL;
2469   }
2470 }
2471 
2472 
Value() const2473 double Number::Value() const {
2474   if (IsDeadCheck("v8::Number::Value()")) return 0;
2475   i::Handle<i::Object> obj = Utils::OpenHandle(this);
2476   return obj->Number();
2477 }
2478 
2479 
Value() const2480 bool Boolean::Value() const {
2481   if (IsDeadCheck("v8::Boolean::Value()")) return false;
2482   i::Handle<i::Object> obj = Utils::OpenHandle(this);
2483   return obj->IsTrue();
2484 }
2485 
2486 
Value() const2487 int64_t Integer::Value() const {
2488   if (IsDeadCheck("v8::Integer::Value()")) return 0;
2489   i::Handle<i::Object> obj = Utils::OpenHandle(this);
2490   if (obj->IsSmi()) {
2491     return i::Smi::cast(*obj)->value();
2492   } else {
2493     return static_cast<int64_t>(obj->Number());
2494   }
2495 }
2496 
2497 
Value() const2498 int32_t Int32::Value() const {
2499   if (IsDeadCheck("v8::Int32::Value()")) return 0;
2500   i::Handle<i::Object> obj = Utils::OpenHandle(this);
2501   if (obj->IsSmi()) {
2502     return i::Smi::cast(*obj)->value();
2503   } else {
2504     return static_cast<int32_t>(obj->Number());
2505   }
2506 }
2507 
2508 
InternalFieldCount()2509 int v8::Object::InternalFieldCount() {
2510   if (IsDeadCheck("v8::Object::InternalFieldCount()")) return 0;
2511   i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
2512   return obj->GetInternalFieldCount();
2513 }
2514 
2515 
CheckedGetInternalField(int index)2516 Local<Value> v8::Object::CheckedGetInternalField(int index) {
2517   if (IsDeadCheck("v8::Object::GetInternalField()")) return Local<Value>();
2518   i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
2519   if (!ApiCheck(index < obj->GetInternalFieldCount(),
2520                 "v8::Object::GetInternalField()",
2521                 "Reading internal field out of bounds")) {
2522     return Local<Value>();
2523   }
2524   i::Handle<i::Object> value(obj->GetInternalField(index));
2525   Local<Value> result = Utils::ToLocal(value);
2526 #ifdef DEBUG
2527   Local<Value> unchecked = UncheckedGetInternalField(index);
2528   ASSERT(unchecked.IsEmpty() || (unchecked == result));
2529 #endif
2530   return result;
2531 }
2532 
2533 
SetInternalField(int index,v8::Handle<Value> value)2534 void v8::Object::SetInternalField(int index, v8::Handle<Value> value) {
2535   if (IsDeadCheck("v8::Object::SetInternalField()")) return;
2536   i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
2537   if (!ApiCheck(index < obj->GetInternalFieldCount(),
2538                 "v8::Object::SetInternalField()",
2539                 "Writing internal field out of bounds")) {
2540     return;
2541   }
2542   ENTER_V8;
2543   i::Handle<i::Object> val = Utils::OpenHandle(*value);
2544   obj->SetInternalField(index, *val);
2545 }
2546 
2547 
SetPointerInInternalField(int index,void * value)2548 void v8::Object::SetPointerInInternalField(int index, void* value) {
2549   SetInternalField(index, External::Wrap(value));
2550 }
2551 
2552 
2553 // --- E n v i r o n m e n t ---
2554 
Initialize()2555 bool v8::V8::Initialize() {
2556   if (i::V8::IsRunning()) return true;
2557   ENTER_V8;
2558   HandleScope scope;
2559   if (i::Snapshot::Initialize()) {
2560     return true;
2561   } else {
2562     return i::V8::Initialize(NULL);
2563   }
2564 }
2565 
2566 
Dispose()2567 bool v8::V8::Dispose() {
2568   i::V8::TearDown();
2569   return true;
2570 }
2571 
2572 
IdleNotification(bool is_high_priority)2573 bool v8::V8::IdleNotification(bool is_high_priority) {
2574   if (!i::V8::IsRunning()) return false;
2575   return i::V8::IdleNotification(is_high_priority);
2576 }
2577 
2578 
LowMemoryNotification()2579 void v8::V8::LowMemoryNotification() {
2580 #if defined(ANDROID)
2581   if (!i::V8::IsRunning()) return;
2582   i::Heap::CollectAllGarbage(true);
2583 #endif
2584 }
2585 
2586 
GetVersion()2587 const char* v8::V8::GetVersion() {
2588   static v8::internal::EmbeddedVector<char, 128> buffer;
2589   v8::internal::Version::GetString(buffer);
2590   return buffer.start();
2591 }
2592 
2593 
2594 static i::Handle<i::FunctionTemplateInfo>
EnsureConstructor(i::Handle<i::ObjectTemplateInfo> templ)2595     EnsureConstructor(i::Handle<i::ObjectTemplateInfo> templ) {
2596   if (templ->constructor()->IsUndefined()) {
2597     Local<FunctionTemplate> constructor = FunctionTemplate::New();
2598     Utils::OpenHandle(*constructor)->set_instance_template(*templ);
2599     templ->set_constructor(*Utils::OpenHandle(*constructor));
2600   }
2601   return i::Handle<i::FunctionTemplateInfo>(
2602     i::FunctionTemplateInfo::cast(templ->constructor()));
2603 }
2604 
2605 
New(v8::ExtensionConfiguration * extensions,v8::Handle<ObjectTemplate> global_template,v8::Handle<Value> global_object)2606 Persistent<Context> v8::Context::New(
2607     v8::ExtensionConfiguration* extensions,
2608     v8::Handle<ObjectTemplate> global_template,
2609     v8::Handle<Value> global_object) {
2610   EnsureInitialized("v8::Context::New()");
2611   LOG_API("Context::New");
2612   ON_BAILOUT("v8::Context::New()", return Persistent<Context>());
2613 
2614   // Enter V8 via an ENTER_V8 scope.
2615   i::Handle<i::Context> env;
2616   {
2617     ENTER_V8;
2618 #if defined(ANDROID)
2619     // On mobile device, full GC is expensive, leave it to the system to
2620     // decide when should make a full GC.
2621 #else
2622     // Give the heap a chance to cleanup if we've disposed contexts.
2623     i::Heap::CollectAllGarbageIfContextDisposed();
2624 #endif
2625     v8::Handle<ObjectTemplate> proxy_template = global_template;
2626     i::Handle<i::FunctionTemplateInfo> proxy_constructor;
2627     i::Handle<i::FunctionTemplateInfo> global_constructor;
2628 
2629     if (!global_template.IsEmpty()) {
2630       // Make sure that the global_template has a constructor.
2631       global_constructor =
2632           EnsureConstructor(Utils::OpenHandle(*global_template));
2633 
2634       // Create a fresh template for the global proxy object.
2635       proxy_template = ObjectTemplate::New();
2636       proxy_constructor =
2637           EnsureConstructor(Utils::OpenHandle(*proxy_template));
2638 
2639       // Set the global template to be the prototype template of
2640       // global proxy template.
2641       proxy_constructor->set_prototype_template(
2642           *Utils::OpenHandle(*global_template));
2643 
2644       // Migrate security handlers from global_template to
2645       // proxy_template.  Temporarily removing access check
2646       // information from the global template.
2647       if (!global_constructor->access_check_info()->IsUndefined()) {
2648         proxy_constructor->set_access_check_info(
2649             global_constructor->access_check_info());
2650         proxy_constructor->set_needs_access_check(
2651             global_constructor->needs_access_check());
2652         global_constructor->set_needs_access_check(false);
2653         global_constructor->set_access_check_info(i::Heap::undefined_value());
2654       }
2655     }
2656 
2657     // Create the environment.
2658     env = i::Bootstrapper::CreateEnvironment(
2659         Utils::OpenHandle(*global_object),
2660         proxy_template,
2661         extensions);
2662 
2663     // Restore the access check info on the global template.
2664     if (!global_template.IsEmpty()) {
2665       ASSERT(!global_constructor.is_null());
2666       ASSERT(!proxy_constructor.is_null());
2667       global_constructor->set_access_check_info(
2668           proxy_constructor->access_check_info());
2669       global_constructor->set_needs_access_check(
2670           proxy_constructor->needs_access_check());
2671     }
2672   }
2673   // Leave V8.
2674 
2675   if (!ApiCheck(!env.is_null(),
2676                 "v8::Context::New()",
2677                 "Could not initialize environment"))
2678     return Persistent<Context>();
2679   return Persistent<Context>(Utils::ToLocal(env));
2680 }
2681 
2682 
SetSecurityToken(Handle<Value> token)2683 void v8::Context::SetSecurityToken(Handle<Value> token) {
2684   if (IsDeadCheck("v8::Context::SetSecurityToken()")) return;
2685   ENTER_V8;
2686   i::Handle<i::Context> env = Utils::OpenHandle(this);
2687   i::Handle<i::Object> token_handle = Utils::OpenHandle(*token);
2688   env->set_security_token(*token_handle);
2689 }
2690 
2691 
UseDefaultSecurityToken()2692 void v8::Context::UseDefaultSecurityToken() {
2693   if (IsDeadCheck("v8::Context::UseDefaultSecurityToken()")) return;
2694   ENTER_V8;
2695   i::Handle<i::Context> env = Utils::OpenHandle(this);
2696   env->set_security_token(env->global());
2697 }
2698 
2699 
GetSecurityToken()2700 Handle<Value> v8::Context::GetSecurityToken() {
2701   if (IsDeadCheck("v8::Context::GetSecurityToken()")) return Handle<Value>();
2702   i::Handle<i::Context> env = Utils::OpenHandle(this);
2703   i::Object* security_token = env->security_token();
2704   i::Handle<i::Object> token_handle(security_token);
2705   return Utils::ToLocal(token_handle);
2706 }
2707 
2708 
HasOutOfMemoryException()2709 bool Context::HasOutOfMemoryException() {
2710   i::Handle<i::Context> env = Utils::OpenHandle(this);
2711   return env->has_out_of_memory();
2712 }
2713 
2714 
InContext()2715 bool Context::InContext() {
2716   return i::Top::context() != NULL;
2717 }
2718 
2719 
GetEntered()2720 v8::Local<v8::Context> Context::GetEntered() {
2721   if (IsDeadCheck("v8::Context::GetEntered()")) return Local<Context>();
2722   i::Handle<i::Object> last = thread_local.LastEnteredContext();
2723   if (last.is_null()) return Local<Context>();
2724   i::Handle<i::Context> context = i::Handle<i::Context>::cast(last);
2725   return Utils::ToLocal(context);
2726 }
2727 
2728 
GetCurrent()2729 v8::Local<v8::Context> Context::GetCurrent() {
2730   if (IsDeadCheck("v8::Context::GetCurrent()")) return Local<Context>();
2731   i::Handle<i::Context> context(i::Top::global_context());
2732   return Utils::ToLocal(context);
2733 }
2734 
2735 
GetCalling()2736 v8::Local<v8::Context> Context::GetCalling() {
2737   if (IsDeadCheck("v8::Context::GetCalling()")) return Local<Context>();
2738   i::Handle<i::Context> context(i::Top::GetCallingGlobalContext());
2739   return Utils::ToLocal(context);
2740 }
2741 
2742 
Global()2743 v8::Local<v8::Object> Context::Global() {
2744   if (IsDeadCheck("v8::Context::Global()")) return Local<v8::Object>();
2745   i::Object** ctx = reinterpret_cast<i::Object**>(this);
2746   i::Handle<i::Context> context =
2747       i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx));
2748   i::Handle<i::Object> global(context->global_proxy());
2749   return Utils::ToLocal(i::Handle<i::JSObject>::cast(global));
2750 }
2751 
2752 
DetachGlobal()2753 void Context::DetachGlobal() {
2754   if (IsDeadCheck("v8::Context::DetachGlobal()")) return;
2755   ENTER_V8;
2756   i::Object** ctx = reinterpret_cast<i::Object**>(this);
2757   i::Handle<i::Context> context =
2758       i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx));
2759   i::Bootstrapper::DetachGlobal(context);
2760 }
2761 
2762 
NewInstance()2763 Local<v8::Object> ObjectTemplate::NewInstance() {
2764   ON_BAILOUT("v8::ObjectTemplate::NewInstance()", return Local<v8::Object>());
2765   LOG_API("ObjectTemplate::NewInstance");
2766   ENTER_V8;
2767   EXCEPTION_PREAMBLE();
2768   i::Handle<i::Object> obj =
2769       i::Execution::InstantiateObject(Utils::OpenHandle(this),
2770                                       &has_pending_exception);
2771   EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
2772   return Utils::ToLocal(i::Handle<i::JSObject>::cast(obj));
2773 }
2774 
2775 
GetFunction()2776 Local<v8::Function> FunctionTemplate::GetFunction() {
2777   ON_BAILOUT("v8::FunctionTemplate::GetFunction()",
2778              return Local<v8::Function>());
2779   LOG_API("FunctionTemplate::GetFunction");
2780   ENTER_V8;
2781   EXCEPTION_PREAMBLE();
2782   i::Handle<i::Object> obj =
2783       i::Execution::InstantiateFunction(Utils::OpenHandle(this),
2784                                         &has_pending_exception);
2785   EXCEPTION_BAILOUT_CHECK(Local<v8::Function>());
2786   return Utils::ToLocal(i::Handle<i::JSFunction>::cast(obj));
2787 }
2788 
2789 
HasInstance(v8::Handle<v8::Value> value)2790 bool FunctionTemplate::HasInstance(v8::Handle<v8::Value> value) {
2791   ON_BAILOUT("v8::FunctionTemplate::HasInstanceOf()", return false);
2792   i::Object* obj = *Utils::OpenHandle(*value);
2793   return obj->IsInstanceOf(*Utils::OpenHandle(this));
2794 }
2795 
2796 
ExternalNewImpl(void * data)2797 static Local<External> ExternalNewImpl(void* data) {
2798   return Utils::ToLocal(i::Factory::NewProxy(static_cast<i::Address>(data)));
2799 }
2800 
ExternalValueImpl(i::Handle<i::Object> obj)2801 static void* ExternalValueImpl(i::Handle<i::Object> obj) {
2802   return reinterpret_cast<void*>(i::Proxy::cast(*obj)->proxy());
2803 }
2804 
2805 
2806 static const intptr_t kAlignedPointerMask = 3;
2807 
Wrap(void * data)2808 Local<Value> v8::External::Wrap(void* data) {
2809   STATIC_ASSERT(sizeof(data) == sizeof(i::Address));
2810   LOG_API("External::Wrap");
2811   EnsureInitialized("v8::External::Wrap()");
2812   ENTER_V8;
2813   if ((reinterpret_cast<intptr_t>(data) & kAlignedPointerMask) == 0) {
2814     uintptr_t data_ptr = reinterpret_cast<uintptr_t>(data);
2815     intptr_t data_value =
2816         static_cast<intptr_t>(data_ptr >> i::Internals::kAlignedPointerShift);
2817     STATIC_ASSERT(sizeof(data_ptr) == sizeof(data_value));
2818     if (i::Smi::IsIntptrValid(data_value)) {
2819       i::Handle<i::Object> obj(i::Smi::FromIntptr(data_value));
2820       return Utils::ToLocal(obj);
2821     }
2822   }
2823   return ExternalNewImpl(data);
2824 }
2825 
2826 
FullUnwrap(v8::Handle<v8::Value> wrapper)2827 void* v8::External::FullUnwrap(v8::Handle<v8::Value> wrapper) {
2828   if (IsDeadCheck("v8::External::Unwrap()")) return 0;
2829   i::Handle<i::Object> obj = Utils::OpenHandle(*wrapper);
2830   void* result;
2831   if (obj->IsSmi()) {
2832     // The external value was an aligned pointer.
2833     uintptr_t value = static_cast<uintptr_t>(
2834         i::Smi::cast(*obj)->value()) << i::Internals::kAlignedPointerShift;
2835     result = reinterpret_cast<void*>(value);
2836   } else if (obj->IsProxy()) {
2837     result = ExternalValueImpl(obj);
2838   } else {
2839     result = NULL;
2840   }
2841   ASSERT_EQ(result, QuickUnwrap(wrapper));
2842   return result;
2843 }
2844 
2845 
New(void * data)2846 Local<External> v8::External::New(void* data) {
2847   STATIC_ASSERT(sizeof(data) == sizeof(i::Address));
2848   LOG_API("External::New");
2849   EnsureInitialized("v8::External::New()");
2850   ENTER_V8;
2851   return ExternalNewImpl(data);
2852 }
2853 
2854 
Value() const2855 void* External::Value() const {
2856   if (IsDeadCheck("v8::External::Value()")) return 0;
2857   i::Handle<i::Object> obj = Utils::OpenHandle(this);
2858   return ExternalValueImpl(obj);
2859 }
2860 
2861 
Empty()2862 Local<String> v8::String::Empty() {
2863   EnsureInitialized("v8::String::Empty()");
2864   LOG_API("String::Empty()");
2865   return Utils::ToLocal(i::Factory::empty_symbol());
2866 }
2867 
2868 
New(const char * data,int length)2869 Local<String> v8::String::New(const char* data, int length) {
2870   EnsureInitialized("v8::String::New()");
2871   LOG_API("String::New(char)");
2872   if (length == 0) return Empty();
2873   ENTER_V8;
2874   if (length == -1) length = strlen(data);
2875   i::Handle<i::String> result =
2876       i::Factory::NewStringFromUtf8(i::Vector<const char>(data, length));
2877   return Utils::ToLocal(result);
2878 }
2879 
2880 
NewUndetectable(const char * data,int length)2881 Local<String> v8::String::NewUndetectable(const char* data, int length) {
2882   EnsureInitialized("v8::String::NewUndetectable()");
2883   LOG_API("String::NewUndetectable(char)");
2884   ENTER_V8;
2885   if (length == -1) length = strlen(data);
2886   i::Handle<i::String> result =
2887       i::Factory::NewStringFromUtf8(i::Vector<const char>(data, length));
2888   result->MarkAsUndetectable();
2889   return Utils::ToLocal(result);
2890 }
2891 
2892 
TwoByteStringLength(const uint16_t * data)2893 static int TwoByteStringLength(const uint16_t* data) {
2894   int length = 0;
2895   while (data[length] != '\0') length++;
2896   return length;
2897 }
2898 
2899 
New(const uint16_t * data,int length)2900 Local<String> v8::String::New(const uint16_t* data, int length) {
2901   EnsureInitialized("v8::String::New()");
2902   LOG_API("String::New(uint16_)");
2903   if (length == 0) return Empty();
2904   ENTER_V8;
2905   if (length == -1) length = TwoByteStringLength(data);
2906   i::Handle<i::String> result =
2907       i::Factory::NewStringFromTwoByte(i::Vector<const uint16_t>(data, length));
2908   return Utils::ToLocal(result);
2909 }
2910 
2911 
NewUndetectable(const uint16_t * data,int length)2912 Local<String> v8::String::NewUndetectable(const uint16_t* data, int length) {
2913   EnsureInitialized("v8::String::NewUndetectable()");
2914   LOG_API("String::NewUndetectable(uint16_)");
2915   ENTER_V8;
2916   if (length == -1) length = TwoByteStringLength(data);
2917   i::Handle<i::String> result =
2918       i::Factory::NewStringFromTwoByte(i::Vector<const uint16_t>(data, length));
2919   result->MarkAsUndetectable();
2920   return Utils::ToLocal(result);
2921 }
2922 
2923 
NewExternalStringHandle(v8::String::ExternalStringResource * resource)2924 i::Handle<i::String> NewExternalStringHandle(
2925       v8::String::ExternalStringResource* resource) {
2926   i::Handle<i::String> result =
2927       i::Factory::NewExternalStringFromTwoByte(resource);
2928   return result;
2929 }
2930 
2931 
NewExternalAsciiStringHandle(v8::String::ExternalAsciiStringResource * resource)2932 i::Handle<i::String> NewExternalAsciiStringHandle(
2933       v8::String::ExternalAsciiStringResource* resource) {
2934   i::Handle<i::String> result =
2935       i::Factory::NewExternalStringFromAscii(resource);
2936   return result;
2937 }
2938 
2939 
DisposeExternalString(v8::Persistent<v8::Value> obj,void * parameter)2940 static void DisposeExternalString(v8::Persistent<v8::Value> obj,
2941                                   void* parameter) {
2942   ENTER_V8;
2943   i::ExternalTwoByteString* str =
2944       i::ExternalTwoByteString::cast(*Utils::OpenHandle(*obj));
2945 
2946   // External symbols are deleted when they are pruned out of the symbol
2947   // table. Generally external symbols are not registered with the weak handle
2948   // callbacks unless they are upgraded to a symbol after being externalized.
2949   if (!str->IsSymbol()) {
2950     v8::String::ExternalStringResource* resource =
2951         reinterpret_cast<v8::String::ExternalStringResource*>(parameter);
2952     if (resource != NULL) {
2953       const size_t total_size = resource->length() * sizeof(*resource->data());
2954       i::Counters::total_external_string_memory.Decrement(total_size);
2955 
2956       // The object will continue to live in the JavaScript heap until the
2957       // handle is entirely cleaned out by the next GC. For example the
2958       // destructor for the resource below could bring it back to life again.
2959       // Which is why we make sure to not have a dangling pointer here.
2960       str->set_resource(NULL);
2961       delete resource;
2962     }
2963   }
2964 
2965   // In any case we do not need this handle any longer.
2966   obj.Dispose();
2967 }
2968 
2969 
DisposeExternalAsciiString(v8::Persistent<v8::Value> obj,void * parameter)2970 static void DisposeExternalAsciiString(v8::Persistent<v8::Value> obj,
2971                                        void* parameter) {
2972   ENTER_V8;
2973   i::ExternalAsciiString* str =
2974       i::ExternalAsciiString::cast(*Utils::OpenHandle(*obj));
2975 
2976   // External symbols are deleted when they are pruned out of the symbol
2977   // table. Generally external symbols are not registered with the weak handle
2978   // callbacks unless they are upgraded to a symbol after being externalized.
2979   if (!str->IsSymbol()) {
2980     v8::String::ExternalAsciiStringResource* resource =
2981         reinterpret_cast<v8::String::ExternalAsciiStringResource*>(parameter);
2982     if (resource != NULL) {
2983       const size_t total_size = resource->length() * sizeof(*resource->data());
2984       i::Counters::total_external_string_memory.Decrement(total_size);
2985 
2986       // The object will continue to live in the JavaScript heap until the
2987       // handle is entirely cleaned out by the next GC. For example the
2988       // destructor for the resource below could bring it back to life again.
2989       // Which is why we make sure to not have a dangling pointer here.
2990       str->set_resource(NULL);
2991       delete resource;
2992     }
2993   }
2994 
2995   // In any case we do not need this handle any longer.
2996   obj.Dispose();
2997 }
2998 
2999 
NewExternal(v8::String::ExternalStringResource * resource)3000 Local<String> v8::String::NewExternal(
3001       v8::String::ExternalStringResource* resource) {
3002   EnsureInitialized("v8::String::NewExternal()");
3003   LOG_API("String::NewExternal");
3004   ENTER_V8;
3005   const size_t total_size = resource->length() * sizeof(*resource->data());
3006   i::Counters::total_external_string_memory.Increment(total_size);
3007   i::Handle<i::String> result = NewExternalStringHandle(resource);
3008   i::Handle<i::Object> handle = i::GlobalHandles::Create(*result);
3009   i::GlobalHandles::MakeWeak(handle.location(),
3010                              resource,
3011                              &DisposeExternalString);
3012   return Utils::ToLocal(result);
3013 }
3014 
3015 
MakeExternal(v8::String::ExternalStringResource * resource)3016 bool v8::String::MakeExternal(v8::String::ExternalStringResource* resource) {
3017   if (IsDeadCheck("v8::String::MakeExternal()")) return false;
3018   if (this->IsExternal()) return false;  // Already an external string.
3019   ENTER_V8;
3020   i::Handle<i::String> obj = Utils::OpenHandle(this);
3021   bool result = obj->MakeExternal(resource);
3022   if (result && !obj->IsSymbol()) {
3023     // Operation was successful and the string is not a symbol. In this case
3024     // we need to make sure that the we call the destructor for the external
3025     // resource when no strong references to the string remain.
3026     i::Handle<i::Object> handle = i::GlobalHandles::Create(*obj);
3027     i::GlobalHandles::MakeWeak(handle.location(),
3028                                resource,
3029                                &DisposeExternalString);
3030   }
3031   return result;
3032 }
3033 
3034 
NewExternal(v8::String::ExternalAsciiStringResource * resource)3035 Local<String> v8::String::NewExternal(
3036       v8::String::ExternalAsciiStringResource* resource) {
3037   EnsureInitialized("v8::String::NewExternal()");
3038   LOG_API("String::NewExternal");
3039   ENTER_V8;
3040   const size_t total_size = resource->length() * sizeof(*resource->data());
3041   i::Counters::total_external_string_memory.Increment(total_size);
3042   i::Handle<i::String> result = NewExternalAsciiStringHandle(resource);
3043   i::Handle<i::Object> handle = i::GlobalHandles::Create(*result);
3044   i::GlobalHandles::MakeWeak(handle.location(),
3045                              resource,
3046                              &DisposeExternalAsciiString);
3047   return Utils::ToLocal(result);
3048 }
3049 
3050 
MakeExternal(v8::String::ExternalAsciiStringResource * resource)3051 bool v8::String::MakeExternal(
3052     v8::String::ExternalAsciiStringResource* resource) {
3053   if (IsDeadCheck("v8::String::MakeExternal()")) return false;
3054   if (this->IsExternal()) return false;  // Already an external string.
3055   ENTER_V8;
3056   i::Handle<i::String> obj = Utils::OpenHandle(this);
3057   bool result = obj->MakeExternal(resource);
3058   if (result && !obj->IsSymbol()) {
3059     // Operation was successful and the string is not a symbol. In this case
3060     // we need to make sure that the we call the destructor for the external
3061     // resource when no strong references to the string remain.
3062     i::Handle<i::Object> handle = i::GlobalHandles::Create(*obj);
3063     i::GlobalHandles::MakeWeak(handle.location(),
3064                                resource,
3065                                &DisposeExternalAsciiString);
3066   }
3067   return result;
3068 }
3069 
3070 
CanMakeExternal()3071 bool v8::String::CanMakeExternal() {
3072   if (IsDeadCheck("v8::String::CanMakeExternal()")) return false;
3073   i::Handle<i::String> obj = Utils::OpenHandle(this);
3074   int size = obj->Size();  // Byte size of the original string.
3075   if (size < i::ExternalString::kSize)
3076     return false;
3077   i::StringShape shape(*obj);
3078   return !shape.IsExternal();
3079 }
3080 
3081 
New()3082 Local<v8::Object> v8::Object::New() {
3083   EnsureInitialized("v8::Object::New()");
3084   LOG_API("Object::New");
3085   ENTER_V8;
3086   i::Handle<i::JSObject> obj =
3087       i::Factory::NewJSObject(i::Top::object_function());
3088   return Utils::ToLocal(obj);
3089 }
3090 
3091 
New(double time)3092 Local<v8::Value> v8::Date::New(double time) {
3093   EnsureInitialized("v8::Date::New()");
3094   LOG_API("Date::New");
3095   ENTER_V8;
3096   EXCEPTION_PREAMBLE();
3097   i::Handle<i::Object> obj =
3098       i::Execution::NewDate(time, &has_pending_exception);
3099   EXCEPTION_BAILOUT_CHECK(Local<v8::Value>());
3100   return Utils::ToLocal(obj);
3101 }
3102 
3103 
NumberValue() const3104 double v8::Date::NumberValue() const {
3105   if (IsDeadCheck("v8::Date::NumberValue()")) return 0;
3106   LOG_API("Date::NumberValue");
3107   i::Handle<i::Object> obj = Utils::OpenHandle(this);
3108   i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
3109   return jsvalue->value()->Number();
3110 }
3111 
3112 
New(int length)3113 Local<v8::Array> v8::Array::New(int length) {
3114   EnsureInitialized("v8::Array::New()");
3115   LOG_API("Array::New");
3116   ENTER_V8;
3117   i::Handle<i::JSArray> obj = i::Factory::NewJSArray(length);
3118   return Utils::ToLocal(obj);
3119 }
3120 
3121 
Length() const3122 uint32_t v8::Array::Length() const {
3123   if (IsDeadCheck("v8::Array::Length()")) return 0;
3124   i::Handle<i::JSArray> obj = Utils::OpenHandle(this);
3125   i::Object* length = obj->length();
3126   if (length->IsSmi()) {
3127     return i::Smi::cast(length)->value();
3128   } else {
3129     return static_cast<uint32_t>(length->Number());
3130   }
3131 }
3132 
3133 
CloneElementAt(uint32_t index)3134 Local<Object> Array::CloneElementAt(uint32_t index) {
3135   ON_BAILOUT("v8::Array::CloneElementAt()", return Local<Object>());
3136   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3137   if (!self->HasFastElements()) {
3138     return Local<Object>();
3139   }
3140   i::FixedArray* elms = i::FixedArray::cast(self->elements());
3141   i::Object* paragon = elms->get(index);
3142   if (!paragon->IsJSObject()) {
3143     return Local<Object>();
3144   }
3145   i::Handle<i::JSObject> paragon_handle(i::JSObject::cast(paragon));
3146   EXCEPTION_PREAMBLE();
3147   i::Handle<i::JSObject> result = i::Copy(paragon_handle);
3148   has_pending_exception = result.is_null();
3149   EXCEPTION_BAILOUT_CHECK(Local<Object>());
3150   return Utils::ToLocal(result);
3151 }
3152 
3153 
NewSymbol(const char * data,int length)3154 Local<String> v8::String::NewSymbol(const char* data, int length) {
3155   EnsureInitialized("v8::String::NewSymbol()");
3156   LOG_API("String::NewSymbol(char)");
3157   ENTER_V8;
3158   if (length == -1) length = strlen(data);
3159   i::Handle<i::String> result =
3160       i::Factory::LookupSymbol(i::Vector<const char>(data, length));
3161   return Utils::ToLocal(result);
3162 }
3163 
3164 
New(double value)3165 Local<Number> v8::Number::New(double value) {
3166   EnsureInitialized("v8::Number::New()");
3167   ENTER_V8;
3168   i::Handle<i::Object> result = i::Factory::NewNumber(value);
3169   return Utils::NumberToLocal(result);
3170 }
3171 
3172 
New(int32_t value)3173 Local<Integer> v8::Integer::New(int32_t value) {
3174   EnsureInitialized("v8::Integer::New()");
3175   if (i::Smi::IsValid(value)) {
3176     return Utils::IntegerToLocal(i::Handle<i::Object>(i::Smi::FromInt(value)));
3177   }
3178   ENTER_V8;
3179   i::Handle<i::Object> result = i::Factory::NewNumber(value);
3180   return Utils::IntegerToLocal(result);
3181 }
3182 
3183 
IgnoreOutOfMemoryException()3184 void V8::IgnoreOutOfMemoryException() {
3185   thread_local.SetIgnoreOutOfMemory(true);
3186 }
3187 
3188 
AddMessageListener(MessageCallback that,Handle<Value> data)3189 bool V8::AddMessageListener(MessageCallback that, Handle<Value> data) {
3190   EnsureInitialized("v8::V8::AddMessageListener()");
3191   ON_BAILOUT("v8::V8::AddMessageListener()", return false);
3192   ENTER_V8;
3193   HandleScope scope;
3194   NeanderArray listeners(i::Factory::message_listeners());
3195   NeanderObject obj(2);
3196   obj.set(0, *i::Factory::NewProxy(FUNCTION_ADDR(that)));
3197   obj.set(1, data.IsEmpty() ?
3198              i::Heap::undefined_value() :
3199              *Utils::OpenHandle(*data));
3200   listeners.add(obj.value());
3201   return true;
3202 }
3203 
3204 
RemoveMessageListeners(MessageCallback that)3205 void V8::RemoveMessageListeners(MessageCallback that) {
3206   EnsureInitialized("v8::V8::RemoveMessageListener()");
3207   ON_BAILOUT("v8::V8::RemoveMessageListeners()", return);
3208   ENTER_V8;
3209   HandleScope scope;
3210   NeanderArray listeners(i::Factory::message_listeners());
3211   for (int i = 0; i < listeners.length(); i++) {
3212     if (listeners.get(i)->IsUndefined()) continue;  // skip deleted ones
3213 
3214     NeanderObject listener(i::JSObject::cast(listeners.get(i)));
3215     i::Handle<i::Proxy> callback_obj(i::Proxy::cast(listener.get(0)));
3216     if (callback_obj->proxy() == FUNCTION_ADDR(that)) {
3217       listeners.set(i, i::Heap::undefined_value());
3218     }
3219   }
3220 }
3221 
3222 
SetCounterFunction(CounterLookupCallback callback)3223 void V8::SetCounterFunction(CounterLookupCallback callback) {
3224   if (IsDeadCheck("v8::V8::SetCounterFunction()")) return;
3225   i::StatsTable::SetCounterFunction(callback);
3226 }
3227 
SetCreateHistogramFunction(CreateHistogramCallback callback)3228 void V8::SetCreateHistogramFunction(CreateHistogramCallback callback) {
3229   if (IsDeadCheck("v8::V8::SetCreateHistogramFunction()")) return;
3230   i::StatsTable::SetCreateHistogramFunction(callback);
3231 }
3232 
SetAddHistogramSampleFunction(AddHistogramSampleCallback callback)3233 void V8::SetAddHistogramSampleFunction(AddHistogramSampleCallback callback) {
3234   if (IsDeadCheck("v8::V8::SetAddHistogramSampleFunction()")) return;
3235   i::StatsTable::SetAddHistogramSampleFunction(callback);
3236 }
3237 
EnableSlidingStateWindow()3238 void V8::EnableSlidingStateWindow() {
3239   if (IsDeadCheck("v8::V8::EnableSlidingStateWindow()")) return;
3240   i::Logger::EnableSlidingStateWindow();
3241 }
3242 
3243 
SetFailedAccessCheckCallbackFunction(FailedAccessCheckCallback callback)3244 void V8::SetFailedAccessCheckCallbackFunction(
3245       FailedAccessCheckCallback callback) {
3246   if (IsDeadCheck("v8::V8::SetFailedAccessCheckCallbackFunction()")) return;
3247   i::Top::SetFailedAccessCheckCallback(callback);
3248 }
3249 
3250 
AddObjectGroup(Persistent<Value> * objects,size_t length)3251 void V8::AddObjectGroup(Persistent<Value>* objects, size_t length) {
3252   if (IsDeadCheck("v8::V8::AddObjectGroup()")) return;
3253   STATIC_ASSERT(sizeof(Persistent<Value>) == sizeof(i::Object**));
3254   i::GlobalHandles::AddGroup(reinterpret_cast<i::Object***>(objects), length);
3255 }
3256 
3257 
AdjustAmountOfExternalAllocatedMemory(int change_in_bytes)3258 int V8::AdjustAmountOfExternalAllocatedMemory(int change_in_bytes) {
3259   if (IsDeadCheck("v8::V8::AdjustAmountOfExternalAllocatedMemory()")) return 0;
3260   return i::Heap::AdjustAmountOfExternalAllocatedMemory(change_in_bytes);
3261 }
3262 
3263 
SetGlobalGCPrologueCallback(GCCallback callback)3264 void V8::SetGlobalGCPrologueCallback(GCCallback callback) {
3265   if (IsDeadCheck("v8::V8::SetGlobalGCPrologueCallback()")) return;
3266   i::Heap::SetGlobalGCPrologueCallback(callback);
3267 }
3268 
3269 
SetGlobalGCEpilogueCallback(GCCallback callback)3270 void V8::SetGlobalGCEpilogueCallback(GCCallback callback) {
3271   if (IsDeadCheck("v8::V8::SetGlobalGCEpilogueCallback()")) return;
3272   i::Heap::SetGlobalGCEpilogueCallback(callback);
3273 }
3274 
3275 
PauseProfiler()3276 void V8::PauseProfiler() {
3277 #ifdef ENABLE_LOGGING_AND_PROFILING
3278   i::Logger::PauseProfiler(PROFILER_MODULE_CPU);
3279 #endif
3280 }
3281 
3282 
ResumeProfiler()3283 void V8::ResumeProfiler() {
3284 #ifdef ENABLE_LOGGING_AND_PROFILING
3285   i::Logger::ResumeProfiler(PROFILER_MODULE_CPU);
3286 #endif
3287 }
3288 
3289 
IsProfilerPaused()3290 bool V8::IsProfilerPaused() {
3291 #ifdef ENABLE_LOGGING_AND_PROFILING
3292   return i::Logger::GetActiveProfilerModules() & PROFILER_MODULE_CPU;
3293 #else
3294   return true;
3295 #endif
3296 }
3297 
3298 
ResumeProfilerEx(int flags)3299 void V8::ResumeProfilerEx(int flags) {
3300 #ifdef ENABLE_LOGGING_AND_PROFILING
3301   if (flags & PROFILER_MODULE_HEAP_SNAPSHOT) {
3302     // Snapshot mode: resume modules, perform GC, then pause only
3303     // those modules which haven't been started prior to making a
3304     // snapshot.
3305 
3306     // Reset snapshot flag and CPU module flags.
3307     flags &= ~(PROFILER_MODULE_HEAP_SNAPSHOT | PROFILER_MODULE_CPU);
3308     const int current_flags = i::Logger::GetActiveProfilerModules();
3309     i::Logger::ResumeProfiler(flags);
3310     i::Heap::CollectAllGarbage(false);
3311     i::Logger::PauseProfiler(~current_flags & flags);
3312   } else {
3313     i::Logger::ResumeProfiler(flags);
3314   }
3315 #endif
3316 }
3317 
3318 
PauseProfilerEx(int flags)3319 void V8::PauseProfilerEx(int flags) {
3320 #ifdef ENABLE_LOGGING_AND_PROFILING
3321   i::Logger::PauseProfiler(flags);
3322 #endif
3323 }
3324 
3325 
GetActiveProfilerModules()3326 int V8::GetActiveProfilerModules() {
3327 #ifdef ENABLE_LOGGING_AND_PROFILING
3328   return i::Logger::GetActiveProfilerModules();
3329 #else
3330   return PROFILER_MODULE_NONE;
3331 #endif
3332 }
3333 
3334 
GetLogLines(int from_pos,char * dest_buf,int max_size)3335 int V8::GetLogLines(int from_pos, char* dest_buf, int max_size) {
3336 #ifdef ENABLE_LOGGING_AND_PROFILING
3337   return i::Logger::GetLogLines(from_pos, dest_buf, max_size);
3338 #endif
3339   return 0;
3340 }
3341 
3342 
GetCurrentThreadId()3343 int V8::GetCurrentThreadId() {
3344   API_ENTRY_CHECK("V8::GetCurrentThreadId()");
3345   EnsureInitialized("V8::GetCurrentThreadId()");
3346   return i::Top::thread_id();
3347 }
3348 
3349 
TerminateExecution(int thread_id)3350 void V8::TerminateExecution(int thread_id) {
3351   if (!i::V8::IsRunning()) return;
3352   API_ENTRY_CHECK("V8::GetCurrentThreadId()");
3353   // If the thread_id identifies the current thread just terminate
3354   // execution right away.  Otherwise, ask the thread manager to
3355   // terminate the thread with the given id if any.
3356   if (thread_id == i::Top::thread_id()) {
3357     i::StackGuard::TerminateExecution();
3358   } else {
3359     i::ThreadManager::TerminateExecution(thread_id);
3360   }
3361 }
3362 
3363 
TerminateExecution()3364 void V8::TerminateExecution() {
3365   if (!i::V8::IsRunning()) return;
3366   i::StackGuard::TerminateExecution();
3367 }
3368 
3369 
Utf8Value(v8::Handle<v8::Value> obj)3370 String::Utf8Value::Utf8Value(v8::Handle<v8::Value> obj) {
3371   EnsureInitialized("v8::String::Utf8Value::Utf8Value()");
3372   if (obj.IsEmpty()) {
3373     str_ = NULL;
3374     length_ = 0;
3375     return;
3376   }
3377   ENTER_V8;
3378   HandleScope scope;
3379   TryCatch try_catch;
3380   Handle<String> str = obj->ToString();
3381   if (str.IsEmpty()) {
3382     str_ = NULL;
3383     length_ = 0;
3384   } else {
3385     length_ = str->Utf8Length();
3386     str_ = i::NewArray<char>(length_ + 1);
3387     str->WriteUtf8(str_);
3388   }
3389 }
3390 
3391 
~Utf8Value()3392 String::Utf8Value::~Utf8Value() {
3393   i::DeleteArray(str_);
3394 }
3395 
3396 
AsciiValue(v8::Handle<v8::Value> obj)3397 String::AsciiValue::AsciiValue(v8::Handle<v8::Value> obj) {
3398   EnsureInitialized("v8::String::AsciiValue::AsciiValue()");
3399   if (obj.IsEmpty()) {
3400     str_ = NULL;
3401     length_ = 0;
3402     return;
3403   }
3404   ENTER_V8;
3405   HandleScope scope;
3406   TryCatch try_catch;
3407   Handle<String> str = obj->ToString();
3408   if (str.IsEmpty()) {
3409     str_ = NULL;
3410     length_ = 0;
3411   } else {
3412     length_ = str->Length();
3413     str_ = i::NewArray<char>(length_ + 1);
3414     str->WriteAscii(str_);
3415   }
3416 }
3417 
3418 
~AsciiValue()3419 String::AsciiValue::~AsciiValue() {
3420   i::DeleteArray(str_);
3421 }
3422 
3423 
Value(v8::Handle<v8::Value> obj)3424 String::Value::Value(v8::Handle<v8::Value> obj) {
3425   EnsureInitialized("v8::String::Value::Value()");
3426   if (obj.IsEmpty()) {
3427     str_ = NULL;
3428     length_ = 0;
3429     return;
3430   }
3431   ENTER_V8;
3432   HandleScope scope;
3433   TryCatch try_catch;
3434   Handle<String> str = obj->ToString();
3435   if (str.IsEmpty()) {
3436     str_ = NULL;
3437     length_ = 0;
3438   } else {
3439     length_ = str->Length();
3440     str_ = i::NewArray<uint16_t>(length_ + 1);
3441     str->Write(str_);
3442   }
3443 }
3444 
3445 
~Value()3446 String::Value::~Value() {
3447   i::DeleteArray(str_);
3448 }
3449 
RangeError(v8::Handle<v8::String> raw_message)3450 Local<Value> Exception::RangeError(v8::Handle<v8::String> raw_message) {
3451   LOG_API("RangeError");
3452   ON_BAILOUT("v8::Exception::RangeError()", return Local<Value>());
3453   ENTER_V8;
3454   i::Object* error;
3455   {
3456     HandleScope scope;
3457     i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
3458     i::Handle<i::Object> result = i::Factory::NewRangeError(message);
3459     error = *result;
3460   }
3461   i::Handle<i::Object> result(error);
3462   return Utils::ToLocal(result);
3463 }
3464 
ReferenceError(v8::Handle<v8::String> raw_message)3465 Local<Value> Exception::ReferenceError(v8::Handle<v8::String> raw_message) {
3466   LOG_API("ReferenceError");
3467   ON_BAILOUT("v8::Exception::ReferenceError()", return Local<Value>());
3468   ENTER_V8;
3469   i::Object* error;
3470   {
3471     HandleScope scope;
3472     i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
3473     i::Handle<i::Object> result = i::Factory::NewReferenceError(message);
3474     error = *result;
3475   }
3476   i::Handle<i::Object> result(error);
3477   return Utils::ToLocal(result);
3478 }
3479 
SyntaxError(v8::Handle<v8::String> raw_message)3480 Local<Value> Exception::SyntaxError(v8::Handle<v8::String> raw_message) {
3481   LOG_API("SyntaxError");
3482   ON_BAILOUT("v8::Exception::SyntaxError()", return Local<Value>());
3483   ENTER_V8;
3484   i::Object* error;
3485   {
3486     HandleScope scope;
3487     i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
3488     i::Handle<i::Object> result = i::Factory::NewSyntaxError(message);
3489     error = *result;
3490   }
3491   i::Handle<i::Object> result(error);
3492   return Utils::ToLocal(result);
3493 }
3494 
TypeError(v8::Handle<v8::String> raw_message)3495 Local<Value> Exception::TypeError(v8::Handle<v8::String> raw_message) {
3496   LOG_API("TypeError");
3497   ON_BAILOUT("v8::Exception::TypeError()", return Local<Value>());
3498   ENTER_V8;
3499   i::Object* error;
3500   {
3501     HandleScope scope;
3502     i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
3503     i::Handle<i::Object> result = i::Factory::NewTypeError(message);
3504     error = *result;
3505   }
3506   i::Handle<i::Object> result(error);
3507   return Utils::ToLocal(result);
3508 }
3509 
Error(v8::Handle<v8::String> raw_message)3510 Local<Value> Exception::Error(v8::Handle<v8::String> raw_message) {
3511   LOG_API("Error");
3512   ON_BAILOUT("v8::Exception::Error()", return Local<Value>());
3513   ENTER_V8;
3514   i::Object* error;
3515   {
3516     HandleScope scope;
3517     i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
3518     i::Handle<i::Object> result = i::Factory::NewError(message);
3519     error = *result;
3520   }
3521   i::Handle<i::Object> result(error);
3522   return Utils::ToLocal(result);
3523 }
3524 
3525 
3526 // --- D e b u g   S u p p o r t ---
3527 
3528 #ifdef ENABLE_DEBUGGER_SUPPORT
SetDebugEventListener(EventCallback that,Handle<Value> data)3529 bool Debug::SetDebugEventListener(EventCallback that, Handle<Value> data) {
3530   EnsureInitialized("v8::Debug::SetDebugEventListener()");
3531   ON_BAILOUT("v8::Debug::SetDebugEventListener()", return false);
3532   ENTER_V8;
3533   HandleScope scope;
3534   i::Handle<i::Object> proxy = i::Factory::undefined_value();
3535   if (that != NULL) {
3536     proxy = i::Factory::NewProxy(FUNCTION_ADDR(that));
3537   }
3538   i::Debugger::SetEventListener(proxy, Utils::OpenHandle(*data));
3539   return true;
3540 }
3541 
3542 
SetDebugEventListener(v8::Handle<v8::Object> that,Handle<Value> data)3543 bool Debug::SetDebugEventListener(v8::Handle<v8::Object> that,
3544                                   Handle<Value> data) {
3545   ON_BAILOUT("v8::Debug::SetDebugEventListener()", return false);
3546   ENTER_V8;
3547   i::Debugger::SetEventListener(Utils::OpenHandle(*that),
3548                                 Utils::OpenHandle(*data));
3549   return true;
3550 }
3551 
3552 
DebugBreak()3553 void Debug::DebugBreak() {
3554   if (!i::V8::IsRunning()) return;
3555   i::StackGuard::DebugBreak();
3556 }
3557 
3558 
3559 static v8::Debug::MessageHandler message_handler = NULL;
3560 
MessageHandlerWrapper(const v8::Debug::Message & message)3561 static void MessageHandlerWrapper(const v8::Debug::Message& message) {
3562   if (message_handler) {
3563     v8::String::Value json(message.GetJSON());
3564     message_handler(*json, json.length(), message.GetClientData());
3565   }
3566 }
3567 
3568 
SetMessageHandler(v8::Debug::MessageHandler handler,bool message_handler_thread)3569 void Debug::SetMessageHandler(v8::Debug::MessageHandler handler,
3570                               bool message_handler_thread) {
3571   EnsureInitialized("v8::Debug::SetMessageHandler");
3572   ENTER_V8;
3573   // Message handler thread not supported any more. Parameter temporally left in
3574   // the API for client compatability reasons.
3575   CHECK(!message_handler_thread);
3576 
3577   // TODO(sgjesse) support the old message handler API through a simple wrapper.
3578   message_handler = handler;
3579   if (message_handler != NULL) {
3580     i::Debugger::SetMessageHandler(MessageHandlerWrapper);
3581   } else {
3582     i::Debugger::SetMessageHandler(NULL);
3583   }
3584 }
3585 
3586 
SetMessageHandler2(v8::Debug::MessageHandler2 handler)3587 void Debug::SetMessageHandler2(v8::Debug::MessageHandler2 handler) {
3588   EnsureInitialized("v8::Debug::SetMessageHandler");
3589   ENTER_V8;
3590   HandleScope scope;
3591   i::Debugger::SetMessageHandler(handler);
3592 }
3593 
3594 
SendCommand(const uint16_t * command,int length,ClientData * client_data)3595 void Debug::SendCommand(const uint16_t* command, int length,
3596                         ClientData* client_data) {
3597   if (!i::V8::IsRunning()) return;
3598   i::Debugger::ProcessCommand(i::Vector<const uint16_t>(command, length),
3599                               client_data);
3600 }
3601 
3602 
SetHostDispatchHandler(HostDispatchHandler handler,int period)3603 void Debug::SetHostDispatchHandler(HostDispatchHandler handler,
3604                                    int period) {
3605   EnsureInitialized("v8::Debug::SetHostDispatchHandler");
3606   ENTER_V8;
3607   i::Debugger::SetHostDispatchHandler(handler, period);
3608 }
3609 
3610 
Call(v8::Handle<v8::Function> fun,v8::Handle<v8::Value> data)3611 Local<Value> Debug::Call(v8::Handle<v8::Function> fun,
3612                          v8::Handle<v8::Value> data) {
3613   if (!i::V8::IsRunning()) return Local<Value>();
3614   ON_BAILOUT("v8::Debug::Call()", return Local<Value>());
3615   ENTER_V8;
3616   i::Handle<i::Object> result;
3617   EXCEPTION_PREAMBLE();
3618   if (data.IsEmpty()) {
3619     result = i::Debugger::Call(Utils::OpenHandle(*fun),
3620                                i::Factory::undefined_value(),
3621                                &has_pending_exception);
3622   } else {
3623     result = i::Debugger::Call(Utils::OpenHandle(*fun),
3624                                Utils::OpenHandle(*data),
3625                                &has_pending_exception);
3626   }
3627   EXCEPTION_BAILOUT_CHECK(Local<Value>());
3628   return Utils::ToLocal(result);
3629 }
3630 
3631 
GetMirror(v8::Handle<v8::Value> obj)3632 Local<Value> Debug::GetMirror(v8::Handle<v8::Value> obj) {
3633   if (!i::V8::IsRunning()) return Local<Value>();
3634   ON_BAILOUT("v8::Debug::GetMirror()", return Local<Value>());
3635   ENTER_V8;
3636   v8::HandleScope scope;
3637   i::Debug::Load();
3638   i::Handle<i::JSObject> debug(i::Debug::debug_context()->global());
3639   i::Handle<i::String> name = i::Factory::LookupAsciiSymbol("MakeMirror");
3640   i::Handle<i::Object> fun_obj = i::GetProperty(debug, name);
3641   i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(fun_obj);
3642   v8::Handle<v8::Function> v8_fun = Utils::ToLocal(fun);
3643   const int kArgc = 1;
3644   v8::Handle<v8::Value> argv[kArgc] = { obj };
3645   EXCEPTION_PREAMBLE();
3646   v8::Handle<v8::Value> result = v8_fun->Call(Utils::ToLocal(debug),
3647                                               kArgc,
3648                                               argv);
3649   EXCEPTION_BAILOUT_CHECK(Local<Value>());
3650   return scope.Close(result);
3651 }
3652 
3653 
EnableAgent(const char * name,int port)3654 bool Debug::EnableAgent(const char* name, int port) {
3655   return i::Debugger::StartAgent(name, port);
3656 }
3657 #endif  // ENABLE_DEBUGGER_SUPPORT
3658 
3659 namespace internal {
3660 
3661 
instance()3662 HandleScopeImplementer* HandleScopeImplementer::instance() {
3663   return &thread_local;
3664 }
3665 
3666 
ArchiveThread(char * storage)3667 char* HandleScopeImplementer::ArchiveThread(char* storage) {
3668   return thread_local.ArchiveThreadHelper(storage);
3669 }
3670 
3671 
ArchiveThreadHelper(char * storage)3672 char* HandleScopeImplementer::ArchiveThreadHelper(char* storage) {
3673   v8::ImplementationUtilities::HandleScopeData* current =
3674       v8::ImplementationUtilities::CurrentHandleScope();
3675   handle_scope_data_ = *current;
3676   memcpy(storage, this, sizeof(*this));
3677 
3678   Initialize();
3679   current->Initialize();
3680 
3681   return storage + ArchiveSpacePerThread();
3682 }
3683 
3684 
ArchiveSpacePerThread()3685 int HandleScopeImplementer::ArchiveSpacePerThread() {
3686   return sizeof(thread_local);
3687 }
3688 
3689 
RestoreThread(char * storage)3690 char* HandleScopeImplementer::RestoreThread(char* storage) {
3691   return thread_local.RestoreThreadHelper(storage);
3692 }
3693 
3694 
RestoreThreadHelper(char * storage)3695 char* HandleScopeImplementer::RestoreThreadHelper(char* storage) {
3696   memcpy(this, storage, sizeof(*this));
3697   *v8::ImplementationUtilities::CurrentHandleScope() = handle_scope_data_;
3698   return storage + ArchiveSpacePerThread();
3699 }
3700 
3701 
IterateThis(ObjectVisitor * v)3702 void HandleScopeImplementer::IterateThis(ObjectVisitor* v) {
3703   // Iterate over all handles in the blocks except for the last.
3704   for (int i = Blocks()->length() - 2; i >= 0; --i) {
3705     Object** block = Blocks()->at(i);
3706     v->VisitPointers(block, &block[kHandleBlockSize]);
3707   }
3708 
3709   // Iterate over live handles in the last block (if any).
3710   if (!Blocks()->is_empty()) {
3711     v->VisitPointers(Blocks()->last(), handle_scope_data_.next);
3712   }
3713 
3714   if (!saved_contexts_.is_empty()) {
3715     Object** start = reinterpret_cast<Object**>(&saved_contexts_.first());
3716     v->VisitPointers(start, start + saved_contexts_.length());
3717   }
3718 }
3719 
3720 
Iterate(ObjectVisitor * v)3721 void HandleScopeImplementer::Iterate(ObjectVisitor* v) {
3722   v8::ImplementationUtilities::HandleScopeData* current =
3723       v8::ImplementationUtilities::CurrentHandleScope();
3724   thread_local.handle_scope_data_ = *current;
3725   thread_local.IterateThis(v);
3726 }
3727 
3728 
Iterate(ObjectVisitor * v,char * storage)3729 char* HandleScopeImplementer::Iterate(ObjectVisitor* v, char* storage) {
3730   HandleScopeImplementer* thread_local =
3731       reinterpret_cast<HandleScopeImplementer*>(storage);
3732   thread_local->IterateThis(v);
3733   return storage + ArchiveSpacePerThread();
3734 }
3735 
3736 } }  // namespace v8::internal
3737