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