blob: 0dc4fd7c7eb4195bff53deeaf2b14321832b11b8 [file] [log] [blame]
ager@chromium.org71daaf62009-04-01 07:22:49 +00001// Copyright 2009 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
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"
ager@chromium.orgddb913d2009-01-27 10:01:48 +000039#include "v8threads.h"
ager@chromium.org5ec48922009-05-05 07:25:34 +000040#include "version.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000041
42
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000043#define LOG_API(expr) LOG(ApiEntryCall(expr))
44
ager@chromium.org71daaf62009-04-01 07:22:49 +000045#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
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000052
53namespace 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::optional_reschedule_exception(call_depth_is_zero); \
79 return value; \
80 } \
81 } while (false)
82
83
ager@chromium.orgddb913d2009-01-27 10:01:48 +000084#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
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000093// --- 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
96static 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
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000102static FatalErrorCallback exception_behavior = NULL;
103
104
105static void DefaultFatalErrorHandler(const char* location,
106 const char* message) {
ager@chromium.org71daaf62009-04-01 07:22:49 +0000107 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000108 API_Fatal(location, message);
109}
110
111
112
113static FatalErrorCallback& GetFatalErrorHandler() {
114 if (exception_behavior == NULL) {
115 exception_behavior = DefaultFatalErrorHandler;
116 }
117 return exception_behavior;
118}
119
120
121
122// When V8 cannot allocated memory FatalProcessOutOfMemory is called.
123// The default fatal error handler is called and execution is stopped.
124void i::V8::FatalProcessOutOfMemory(const char* location) {
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000125 i::V8::SetFatalError();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000126 FatalErrorCallback callback = GetFatalErrorHandler();
ager@chromium.org71daaf62009-04-01 07:22:49 +0000127 {
128 LEAVE_V8;
129 callback(location, "Allocation failed - process out of memory");
130 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000131 // If the callback returns, we stop execution.
132 UNREACHABLE();
133}
134
135
136void V8::SetFatalErrorHandler(FatalErrorCallback that) {
137 exception_behavior = that;
138}
139
140
141bool Utils::ReportApiFailure(const char* location, const char* message) {
142 FatalErrorCallback callback = GetFatalErrorHandler();
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +0000143 callback(location, message);
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000144 i::V8::SetFatalError();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000145 return false;
146}
147
148
149bool V8::IsDead() {
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000150 return i::V8::IsDead();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000151}
152
153
154static inline bool ApiCheck(bool condition,
155 const char* location,
156 const char* message) {
157 return condition ? true : Utils::ReportApiFailure(location, message);
158}
159
160
161static bool ReportV8Dead(const char* location) {
162 FatalErrorCallback callback = GetFatalErrorHandler();
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +0000163 callback(location, "V8 is no longer usable");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000164 return true;
165}
166
167
168static bool ReportEmptyHandle(const char* location) {
169 FatalErrorCallback callback = GetFatalErrorHandler();
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +0000170 callback(location, "Reading from empty handle");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000171 return true;
172}
173
174
175/**
ager@chromium.org32912102009-01-16 10:38:43 +0000176 * IsDeadCheck checks that the vm is usable. If, for instance, the vm has been
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000177 * out of memory at some point this check will fail. It should be called on
178 * entry to all methods that touch anything in the heap, except destructors
179 * which you sometimes can't avoid calling after the vm has crashed. Functions
180 * that call EnsureInitialized or ON_BAILOUT don't have to also call
181 * IsDeadCheck. ON_BAILOUT has the advantage over EnsureInitialized that you
182 * can arrange to return if the VM is dead. This is needed to ensure that no VM
183 * heap allocations are attempted on a dead VM. EnsureInitialized has the
184 * advantage over ON_BAILOUT that it actually initializes the VM if this has not
185 * yet been done.
186 */
187static inline bool IsDeadCheck(const char* location) {
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000188 return !i::V8::IsRunning()
189 && i::V8::IsDead() ? ReportV8Dead(location) : false;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000190}
191
192
193static inline bool EmptyCheck(const char* location, v8::Handle<v8::Data> obj) {
194 return obj.IsEmpty() ? ReportEmptyHandle(location) : false;
195}
196
197
ager@chromium.org32912102009-01-16 10:38:43 +0000198static inline bool EmptyCheck(const char* location, const v8::Data* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000199 return (obj == 0) ? ReportEmptyHandle(location) : false;
200}
201
202// --- S t a t i c s ---
203
204
205static i::StringInputBuffer write_input_buffer;
206
207
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000208static inline bool EnsureInitialized(const char* location) {
209 if (i::V8::IsRunning()) {
210 return true;
211 }
212 if (IsDeadCheck(location)) {
213 return false;
214 }
215 return ApiCheck(v8::V8::Initialize(), location, "Error initializing V8");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000216}
217
218
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000219ImplementationUtilities::HandleScopeData*
220 ImplementationUtilities::CurrentHandleScope() {
221 return &i::HandleScope::current_;
222}
223
224
225#ifdef DEBUG
226void ImplementationUtilities::ZapHandleRange(void** begin, void** end) {
227 i::HandleScope::ZapRange(begin, end);
228}
229#endif
230
231
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000232v8::Handle<v8::Primitive> ImplementationUtilities::Undefined() {
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000233 if (!EnsureInitialized("v8::Undefined()")) return v8::Handle<v8::Primitive>();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000234 return v8::Handle<Primitive>(ToApi<Primitive>(i::Factory::undefined_value()));
235}
236
237
238v8::Handle<v8::Primitive> ImplementationUtilities::Null() {
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000239 if (!EnsureInitialized("v8::Null()")) return v8::Handle<v8::Primitive>();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000240 return v8::Handle<Primitive>(ToApi<Primitive>(i::Factory::null_value()));
241}
242
243
244v8::Handle<v8::Boolean> ImplementationUtilities::True() {
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000245 if (!EnsureInitialized("v8::True()")) return v8::Handle<v8::Boolean>();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000246 return v8::Handle<v8::Boolean>(ToApi<Boolean>(i::Factory::true_value()));
247}
248
249
250v8::Handle<v8::Boolean> ImplementationUtilities::False() {
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000251 if (!EnsureInitialized("v8::False()")) return v8::Handle<v8::Boolean>();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000252 return v8::Handle<v8::Boolean>(ToApi<Boolean>(i::Factory::false_value()));
253}
254
255
256void V8::SetFlagsFromString(const char* str, int length) {
257 i::FlagList::SetFlagsFromString(str, length);
258}
259
260
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000261void V8::SetFlagsFromCommandLine(int* argc, char** argv, bool remove_flags) {
262 i::FlagList::SetFlagsFromCommandLine(argc, argv, remove_flags);
263}
264
265
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000266v8::Handle<Value> ThrowException(v8::Handle<v8::Value> value) {
267 if (IsDeadCheck("v8::ThrowException()")) return v8::Handle<Value>();
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +0000268 ENTER_V8;
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000269 // If we're passed an empty handle, we throw an undefined exception
270 // to deal more gracefully with out of memory situations.
271 if (value.IsEmpty()) {
272 i::Top::ScheduleThrow(i::Heap::undefined_value());
273 } else {
274 i::Top::ScheduleThrow(*Utils::OpenHandle(*value));
275 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000276 return v8::Undefined();
277}
278
279
280RegisteredExtension* RegisteredExtension::first_extension_ = NULL;
281
282
283RegisteredExtension::RegisteredExtension(Extension* extension)
284 : extension_(extension), state_(UNVISITED) { }
285
286
287void RegisteredExtension::Register(RegisteredExtension* that) {
288 that->next_ = RegisteredExtension::first_extension_;
289 RegisteredExtension::first_extension_ = that;
290}
291
292
293void RegisterExtension(Extension* that) {
294 RegisteredExtension* extension = new RegisteredExtension(that);
295 RegisteredExtension::Register(extension);
296}
297
298
299Extension::Extension(const char* name,
300 const char* source,
301 int dep_count,
302 const char** deps)
303 : name_(name),
304 source_(source),
305 dep_count_(dep_count),
306 deps_(deps),
307 auto_enable_(false) { }
308
309
310v8::Handle<Primitive> Undefined() {
311 LOG_API("Undefined");
312 return ImplementationUtilities::Undefined();
313}
314
315
316v8::Handle<Primitive> Null() {
317 LOG_API("Null");
318 return ImplementationUtilities::Null();
319}
320
321
322v8::Handle<Boolean> True() {
323 LOG_API("True");
324 return ImplementationUtilities::True();
325}
326
327
328v8::Handle<Boolean> False() {
329 LOG_API("False");
330 return ImplementationUtilities::False();
331}
332
333
334ResourceConstraints::ResourceConstraints()
335 : max_young_space_size_(0),
336 max_old_space_size_(0),
337 stack_limit_(NULL) { }
338
339
340bool SetResourceConstraints(ResourceConstraints* constraints) {
341 bool result = i::Heap::ConfigureHeap(constraints->max_young_space_size(),
342 constraints->max_old_space_size());
343 if (!result) return false;
344 if (constraints->stack_limit() != NULL) {
345 uintptr_t limit = reinterpret_cast<uintptr_t>(constraints->stack_limit());
346 i::StackGuard::SetStackLimit(limit);
347 }
348 return true;
349}
350
351
352void** V8::GlobalizeReference(void** obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000353 if (IsDeadCheck("V8::Persistent::New")) return NULL;
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +0000354 LOG_API("Persistent::New");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000355 i::Handle<i::Object> result =
356 i::GlobalHandles::Create(*reinterpret_cast<i::Object**>(obj));
357 return reinterpret_cast<void**>(result.location());
358}
359
360
361void V8::MakeWeak(void** object, void* parameters,
362 WeakReferenceCallback callback) {
363 LOG_API("MakeWeak");
364 i::GlobalHandles::MakeWeak(reinterpret_cast<i::Object**>(object), parameters,
365 callback);
366}
367
368
369void V8::ClearWeak(void** obj) {
370 LOG_API("ClearWeak");
371 i::GlobalHandles::ClearWeakness(reinterpret_cast<i::Object**>(obj));
372}
373
374
375bool V8::IsGlobalNearDeath(void** obj) {
376 LOG_API("IsGlobalNearDeath");
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000377 if (!i::V8::IsRunning()) return false;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000378 return i::GlobalHandles::IsNearDeath(reinterpret_cast<i::Object**>(obj));
379}
380
381
382bool V8::IsGlobalWeak(void** obj) {
383 LOG_API("IsGlobalWeak");
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000384 if (!i::V8::IsRunning()) return false;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000385 return i::GlobalHandles::IsWeak(reinterpret_cast<i::Object**>(obj));
386}
387
388
389void V8::DisposeGlobal(void** obj) {
390 LOG_API("DisposeGlobal");
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000391 if (!i::V8::IsRunning()) return;
kasperl@chromium.org061ef742009-02-27 12:16:20 +0000392 i::Object** ptr = reinterpret_cast<i::Object**>(obj);
393 if ((*ptr)->IsGlobalContext()) i::Heap::NotifyContextDisposed();
394 i::GlobalHandles::Destroy(ptr);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000395}
396
397// --- H a n d l e s ---
398
399
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000400HandleScope::HandleScope() : is_closed_(false) {
401 API_ENTRY_CHECK("HandleScope::HandleScope");
402 i::HandleScope::Enter(&previous_);
403}
404
405
406HandleScope::~HandleScope() {
407 if (!is_closed_) {
408 i::HandleScope::Leave(&previous_);
409 }
410}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000411
412
413int HandleScope::NumberOfHandles() {
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000414 return i::HandleScope::NumberOfHandles();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000415}
416
417
418void** v8::HandleScope::CreateHandle(void* value) {
ager@chromium.orge2902be2009-06-08 12:21:35 +0000419 return reinterpret_cast<void**>(
420 i::HandleScope::CreateHandle(reinterpret_cast<i::Object*>(value)));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000421}
422
423
424void Context::Enter() {
425 if (IsDeadCheck("v8::Context::Enter()")) return;
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +0000426 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000427 i::Handle<i::Context> env = Utils::OpenHandle(this);
kasper.lund44510672008-07-25 07:37:58 +0000428 thread_local.EnterContext(env);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000429
kasper.lund44510672008-07-25 07:37:58 +0000430 thread_local.SaveContext(i::GlobalHandles::Create(i::Top::context()));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000431 i::Top::set_context(*env);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000432}
433
434
435void Context::Exit() {
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000436 if (!i::V8::IsRunning()) return;
kasper.lund44510672008-07-25 07:37:58 +0000437 if (!ApiCheck(thread_local.LeaveLastContext(),
438 "v8::Context::Exit()",
439 "Cannot exit non-entered context")) {
440 return;
441 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000442
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000443 // Content of 'last_context' could be NULL.
kasper.lund44510672008-07-25 07:37:58 +0000444 i::Handle<i::Object> last_context = thread_local.RestoreContext();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000445 i::Top::set_context(static_cast<i::Context*>(*last_context));
446 i::GlobalHandles::Destroy(last_context.location());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000447}
448
449
ager@chromium.org9085a012009-05-11 19:22:57 +0000450void Context::SetData(v8::Handle<Value> data) {
451 if (IsDeadCheck("v8::Context::SetData()")) return;
452 ENTER_V8;
453 {
454 HandleScope scope;
455 i::Handle<i::Context> env = Utils::OpenHandle(this);
456 i::Handle<i::Object> raw_data = Utils::OpenHandle(*data);
457 ASSERT(env->IsGlobalContext());
458 if (env->IsGlobalContext()) {
459 env->set_data(*raw_data);
460 }
461 }
462}
463
464
465v8::Local<v8::Value> Context::GetData() {
466 if (IsDeadCheck("v8::Context::GetData()")) return v8::Local<Value>();
467 ENTER_V8;
468 i::Object* raw_result = NULL;
469 {
470 HandleScope scope;
471 i::Handle<i::Context> env = Utils::OpenHandle(this);
472 ASSERT(env->IsGlobalContext());
473 if (env->IsGlobalContext()) {
474 raw_result = env->data();
475 } else {
476 return Local<Value>();
477 }
478 }
479 i::Handle<i::Object> result(raw_result);
480 return Utils::ToLocal(result);
481}
482
483
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000484void** v8::HandleScope::RawClose(void** value) {
485 if (!ApiCheck(!is_closed_,
486 "v8::HandleScope::Close()",
487 "Local scope has already been closed")) {
488 return 0;
489 }
490 LOG_API("CloseHandleScope");
491
492 // Read the result before popping the handle block.
493 i::Object* result = reinterpret_cast<i::Object*>(*value);
494 is_closed_ = true;
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000495 i::HandleScope::Leave(&previous_);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000496
497 // Allocate a new handle on the previous handle block.
498 i::Handle<i::Object> handle(result);
499 return reinterpret_cast<void**>(handle.location());
500}
501
502
503// --- N e a n d e r ---
504
505
506// A constructor cannot easily return an error value, therefore it is necessary
507// to check for a dead VM with ON_BAILOUT before constructing any Neander
508// objects. To remind you about this there is no HandleScope in the
509// NeanderObject constructor. When you add one to the site calling the
510// constructor you should check that you ensured the VM was not dead first.
511NeanderObject::NeanderObject(int size) {
512 EnsureInitialized("v8::Nowhere");
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +0000513 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000514 value_ = i::Factory::NewNeanderObject();
515 i::Handle<i::FixedArray> elements = i::Factory::NewFixedArray(size);
516 value_->set_elements(*elements);
517}
518
519
520int NeanderObject::size() {
521 return i::FixedArray::cast(value_->elements())->length();
522}
523
524
525NeanderArray::NeanderArray() : obj_(2) {
526 obj_.set(0, i::Smi::FromInt(0));
527}
528
529
530int NeanderArray::length() {
531 return i::Smi::cast(obj_.get(0))->value();
532}
533
534
535i::Object* NeanderArray::get(int offset) {
536 ASSERT(0 <= offset);
537 ASSERT(offset < length());
538 return obj_.get(offset + 1);
539}
540
541
542// This method cannot easily return an error value, therefore it is necessary
543// to check for a dead VM with ON_BAILOUT before calling it. To remind you
544// about this there is no HandleScope in this method. When you add one to the
545// site calling this method you should check that you ensured the VM was not
546// dead first.
547void NeanderArray::add(i::Handle<i::Object> value) {
548 int length = this->length();
549 int size = obj_.size();
550 if (length == size - 1) {
551 i::Handle<i::FixedArray> new_elms = i::Factory::NewFixedArray(2 * size);
552 for (int i = 0; i < length; i++)
553 new_elms->set(i + 1, get(i));
554 obj_.value()->set_elements(*new_elms);
555 }
556 obj_.set(length + 1, *value);
557 obj_.set(0, i::Smi::FromInt(length + 1));
558}
559
560
561void NeanderArray::set(int index, i::Object* value) {
562 if (index < 0 || index >= this->length()) return;
563 obj_.set(index + 1, value);
564}
565
566
567// --- T e m p l a t e ---
568
569
570static void InitializeTemplate(i::Handle<i::TemplateInfo> that, int type) {
571 that->set_tag(i::Smi::FromInt(type));
572}
573
574
575void Template::Set(v8::Handle<String> name, v8::Handle<Data> value,
576 v8::PropertyAttribute attribute) {
577 if (IsDeadCheck("v8::Template::SetProperty()")) return;
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +0000578 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000579 HandleScope scope;
580 i::Handle<i::Object> list(Utils::OpenHandle(this)->property_list());
581 if (list->IsUndefined()) {
582 list = NeanderArray().value();
583 Utils::OpenHandle(this)->set_property_list(*list);
584 }
585 NeanderArray array(list);
586 array.add(Utils::OpenHandle(*name));
587 array.add(Utils::OpenHandle(*value));
588 array.add(Utils::OpenHandle(*v8::Integer::New(attribute)));
589}
590
591
592// --- F u n c t i o n T e m p l a t e ---
593static void InitializeFunctionTemplate(
594 i::Handle<i::FunctionTemplateInfo> info) {
595 info->set_tag(i::Smi::FromInt(Consts::FUNCTION_TEMPLATE));
596 info->set_flag(0);
597}
598
599
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000600Local<ObjectTemplate> FunctionTemplate::PrototypeTemplate() {
601 if (IsDeadCheck("v8::FunctionTemplate::PrototypeTemplate()")) {
602 return Local<ObjectTemplate>();
603 }
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +0000604 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000605 i::Handle<i::Object> result(Utils::OpenHandle(this)->prototype_template());
606 if (result->IsUndefined()) {
607 result = Utils::OpenHandle(*ObjectTemplate::New());
608 Utils::OpenHandle(this)->set_prototype_template(*result);
609 }
610 return Local<ObjectTemplate>(ToApi<ObjectTemplate>(result));
611}
612
613
614void FunctionTemplate::Inherit(v8::Handle<FunctionTemplate> value) {
615 if (IsDeadCheck("v8::FunctionTemplate::Inherit()")) return;
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +0000616 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000617 Utils::OpenHandle(this)->set_parent_template(*Utils::OpenHandle(*value));
618}
619
620
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000621// To distinguish the function templates, so that we can find them in the
622// function cache of the global context.
623static int next_serial_number = 0;
624
625
626Local<FunctionTemplate> FunctionTemplate::New(InvocationCallback callback,
627 v8::Handle<Value> data, v8::Handle<Signature> signature) {
628 EnsureInitialized("v8::FunctionTemplate::New()");
629 LOG_API("FunctionTemplate::New");
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +0000630 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000631 i::Handle<i::Struct> struct_obj =
632 i::Factory::NewStruct(i::FUNCTION_TEMPLATE_INFO_TYPE);
633 i::Handle<i::FunctionTemplateInfo> obj =
634 i::Handle<i::FunctionTemplateInfo>::cast(struct_obj);
635 InitializeFunctionTemplate(obj);
636 obj->set_serial_number(i::Smi::FromInt(next_serial_number++));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000637 if (callback != 0) {
638 if (data.IsEmpty()) data = v8::Undefined();
639 Utils::ToLocal(obj)->SetCallHandler(callback, data);
640 }
641 obj->set_undetectable(false);
642 obj->set_needs_access_check(false);
643
644 if (!signature.IsEmpty())
645 obj->set_signature(*Utils::OpenHandle(*signature));
646 return Utils::ToLocal(obj);
647}
648
649
650Local<Signature> Signature::New(Handle<FunctionTemplate> receiver,
651 int argc, Handle<FunctionTemplate> argv[]) {
652 EnsureInitialized("v8::Signature::New()");
653 LOG_API("Signature::New");
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +0000654 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000655 i::Handle<i::Struct> struct_obj =
656 i::Factory::NewStruct(i::SIGNATURE_INFO_TYPE);
657 i::Handle<i::SignatureInfo> obj =
658 i::Handle<i::SignatureInfo>::cast(struct_obj);
659 if (!receiver.IsEmpty()) obj->set_receiver(*Utils::OpenHandle(*receiver));
660 if (argc > 0) {
661 i::Handle<i::FixedArray> args = i::Factory::NewFixedArray(argc);
662 for (int i = 0; i < argc; i++) {
663 if (!argv[i].IsEmpty())
664 args->set(i, *Utils::OpenHandle(*argv[i]));
665 }
666 obj->set_args(*args);
667 }
668 return Utils::ToLocal(obj);
669}
670
671
672Local<TypeSwitch> TypeSwitch::New(Handle<FunctionTemplate> type) {
673 Handle<FunctionTemplate> types[1] = { type };
674 return TypeSwitch::New(1, types);
675}
676
677
678Local<TypeSwitch> TypeSwitch::New(int argc, Handle<FunctionTemplate> types[]) {
679 EnsureInitialized("v8::TypeSwitch::New()");
680 LOG_API("TypeSwitch::New");
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +0000681 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000682 i::Handle<i::FixedArray> vector = i::Factory::NewFixedArray(argc);
683 for (int i = 0; i < argc; i++)
684 vector->set(i, *Utils::OpenHandle(*types[i]));
685 i::Handle<i::Struct> struct_obj =
686 i::Factory::NewStruct(i::TYPE_SWITCH_INFO_TYPE);
687 i::Handle<i::TypeSwitchInfo> obj =
688 i::Handle<i::TypeSwitchInfo>::cast(struct_obj);
689 obj->set_types(*vector);
690 return Utils::ToLocal(obj);
691}
692
693
694int TypeSwitch::match(v8::Handle<Value> value) {
695 LOG_API("TypeSwitch::match");
696 i::Handle<i::Object> obj = Utils::OpenHandle(*value);
697 i::Handle<i::TypeSwitchInfo> info = Utils::OpenHandle(this);
698 i::FixedArray* types = i::FixedArray::cast(info->types());
699 for (int i = 0; i < types->length(); i++) {
700 if (obj->IsInstanceOf(i::FunctionTemplateInfo::cast(types->get(i))))
701 return i + 1;
702 }
703 return 0;
704}
705
706
707void FunctionTemplate::SetCallHandler(InvocationCallback callback,
708 v8::Handle<Value> data) {
709 if (IsDeadCheck("v8::FunctionTemplate::SetCallHandler()")) return;
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +0000710 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000711 HandleScope scope;
712 i::Handle<i::Struct> struct_obj =
713 i::Factory::NewStruct(i::CALL_HANDLER_INFO_TYPE);
714 i::Handle<i::CallHandlerInfo> obj =
715 i::Handle<i::CallHandlerInfo>::cast(struct_obj);
716 obj->set_callback(*FromCData(callback));
717 if (data.IsEmpty()) data = v8::Undefined();
718 obj->set_data(*Utils::OpenHandle(*data));
719 Utils::OpenHandle(this)->set_call_code(*obj);
720}
721
722
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000723void FunctionTemplate::AddInstancePropertyAccessor(
724 v8::Handle<String> name,
725 AccessorGetter getter,
726 AccessorSetter setter,
727 v8::Handle<Value> data,
728 v8::AccessControl settings,
729 v8::PropertyAttribute attributes) {
730 if (IsDeadCheck("v8::FunctionTemplate::AddInstancePropertyAccessor()")) {
731 return;
732 }
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +0000733 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000734 HandleScope scope;
735 i::Handle<i::AccessorInfo> obj = i::Factory::NewAccessorInfo();
736 ASSERT(getter != NULL);
737 obj->set_getter(*FromCData(getter));
738 obj->set_setter(*FromCData(setter));
739 if (data.IsEmpty()) data = v8::Undefined();
740 obj->set_data(*Utils::OpenHandle(*data));
741 obj->set_name(*Utils::OpenHandle(*name));
742 if (settings & ALL_CAN_READ) obj->set_all_can_read(true);
743 if (settings & ALL_CAN_WRITE) obj->set_all_can_write(true);
ager@chromium.org870a0b62008-11-04 11:43:05 +0000744 if (settings & PROHIBITS_OVERWRITING) obj->set_prohibits_overwriting(true);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000745 obj->set_property_attributes(static_cast<PropertyAttributes>(attributes));
746
747 i::Handle<i::Object> list(Utils::OpenHandle(this)->property_accessors());
748 if (list->IsUndefined()) {
749 list = NeanderArray().value();
750 Utils::OpenHandle(this)->set_property_accessors(*list);
751 }
752 NeanderArray array(list);
753 array.add(obj);
754}
755
756
757Local<ObjectTemplate> FunctionTemplate::InstanceTemplate() {
758 if (IsDeadCheck("v8::FunctionTemplate::InstanceTemplate()")
759 || EmptyCheck("v8::FunctionTemplate::InstanceTemplate()", this))
760 return Local<ObjectTemplate>();
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +0000761 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000762 if (Utils::OpenHandle(this)->instance_template()->IsUndefined()) {
763 Local<ObjectTemplate> templ =
764 ObjectTemplate::New(v8::Handle<FunctionTemplate>(this));
765 Utils::OpenHandle(this)->set_instance_template(*Utils::OpenHandle(*templ));
766 }
767 i::Handle<i::ObjectTemplateInfo> result(i::ObjectTemplateInfo::cast(
768 Utils::OpenHandle(this)->instance_template()));
769 return Utils::ToLocal(result);
770}
771
772
kasper.lund212ac232008-07-16 07:07:30 +0000773void FunctionTemplate::SetClassName(Handle<String> name) {
774 if (IsDeadCheck("v8::FunctionTemplate::SetClassName()")) return;
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +0000775 ENTER_V8;
kasper.lund212ac232008-07-16 07:07:30 +0000776 Utils::OpenHandle(this)->set_class_name(*Utils::OpenHandle(*name));
777}
778
779
780void FunctionTemplate::SetHiddenPrototype(bool value) {
781 if (IsDeadCheck("v8::FunctionTemplate::SetHiddenPrototype()")) return;
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +0000782 ENTER_V8;
kasper.lund212ac232008-07-16 07:07:30 +0000783 Utils::OpenHandle(this)->set_hidden_prototype(value);
784}
785
786
787void FunctionTemplate::SetNamedInstancePropertyHandler(
788 NamedPropertyGetter getter,
789 NamedPropertySetter setter,
790 NamedPropertyQuery query,
791 NamedPropertyDeleter remover,
792 NamedPropertyEnumerator enumerator,
793 Handle<Value> data) {
794 if (IsDeadCheck("v8::FunctionTemplate::SetNamedInstancePropertyHandler()")) {
795 return;
796 }
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +0000797 ENTER_V8;
kasper.lund212ac232008-07-16 07:07:30 +0000798 HandleScope scope;
799 i::Handle<i::Struct> struct_obj =
800 i::Factory::NewStruct(i::INTERCEPTOR_INFO_TYPE);
801 i::Handle<i::InterceptorInfo> obj =
802 i::Handle<i::InterceptorInfo>::cast(struct_obj);
803 if (getter != 0) obj->set_getter(*FromCData(getter));
804 if (setter != 0) obj->set_setter(*FromCData(setter));
805 if (query != 0) obj->set_query(*FromCData(query));
806 if (remover != 0) obj->set_deleter(*FromCData(remover));
807 if (enumerator != 0) obj->set_enumerator(*FromCData(enumerator));
808 if (data.IsEmpty()) data = v8::Undefined();
809 obj->set_data(*Utils::OpenHandle(*data));
810 Utils::OpenHandle(this)->set_named_property_handler(*obj);
811}
812
813
814void FunctionTemplate::SetIndexedInstancePropertyHandler(
815 IndexedPropertyGetter getter,
816 IndexedPropertySetter setter,
817 IndexedPropertyQuery query,
818 IndexedPropertyDeleter remover,
819 IndexedPropertyEnumerator enumerator,
820 Handle<Value> data) {
821 if (IsDeadCheck(
822 "v8::FunctionTemplate::SetIndexedInstancePropertyHandler()")) {
823 return;
824 }
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +0000825 ENTER_V8;
kasper.lund212ac232008-07-16 07:07:30 +0000826 HandleScope scope;
827 i::Handle<i::Struct> struct_obj =
828 i::Factory::NewStruct(i::INTERCEPTOR_INFO_TYPE);
829 i::Handle<i::InterceptorInfo> obj =
830 i::Handle<i::InterceptorInfo>::cast(struct_obj);
831 if (getter != 0) obj->set_getter(*FromCData(getter));
832 if (setter != 0) obj->set_setter(*FromCData(setter));
833 if (query != 0) obj->set_query(*FromCData(query));
834 if (remover != 0) obj->set_deleter(*FromCData(remover));
835 if (enumerator != 0) obj->set_enumerator(*FromCData(enumerator));
836 if (data.IsEmpty()) data = v8::Undefined();
837 obj->set_data(*Utils::OpenHandle(*data));
838 Utils::OpenHandle(this)->set_indexed_property_handler(*obj);
839}
840
841
842void FunctionTemplate::SetInstanceCallAsFunctionHandler(
843 InvocationCallback callback,
844 Handle<Value> data) {
845 if (IsDeadCheck("v8::FunctionTemplate::SetInstanceCallAsFunctionHandler()")) {
846 return;
847 }
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +0000848 ENTER_V8;
kasper.lund212ac232008-07-16 07:07:30 +0000849 HandleScope scope;
850 i::Handle<i::Struct> struct_obj =
851 i::Factory::NewStruct(i::CALL_HANDLER_INFO_TYPE);
852 i::Handle<i::CallHandlerInfo> obj =
853 i::Handle<i::CallHandlerInfo>::cast(struct_obj);
854 obj->set_callback(*FromCData(callback));
855 if (data.IsEmpty()) data = v8::Undefined();
856 obj->set_data(*Utils::OpenHandle(*data));
857 Utils::OpenHandle(this)->set_instance_call_handler(*obj);
858}
859
860
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000861// --- O b j e c t T e m p l a t e ---
862
863
864Local<ObjectTemplate> ObjectTemplate::New() {
865 return New(Local<FunctionTemplate>());
866}
867
868
869Local<ObjectTemplate> ObjectTemplate::New(
870 v8::Handle<FunctionTemplate> constructor) {
871 if (IsDeadCheck("v8::ObjectTemplate::New()")) return Local<ObjectTemplate>();
872 EnsureInitialized("v8::ObjectTemplate::New()");
873 LOG_API("ObjectTemplate::New");
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +0000874 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000875 i::Handle<i::Struct> struct_obj =
876 i::Factory::NewStruct(i::OBJECT_TEMPLATE_INFO_TYPE);
877 i::Handle<i::ObjectTemplateInfo> obj =
878 i::Handle<i::ObjectTemplateInfo>::cast(struct_obj);
879 InitializeTemplate(obj, Consts::OBJECT_TEMPLATE);
880 if (!constructor.IsEmpty())
881 obj->set_constructor(*Utils::OpenHandle(*constructor));
kasper.lund212ac232008-07-16 07:07:30 +0000882 obj->set_internal_field_count(i::Smi::FromInt(0));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000883 return Utils::ToLocal(obj);
884}
885
886
887// Ensure that the object template has a constructor. If no
888// constructor is available we create one.
889static void EnsureConstructor(ObjectTemplate* object_template) {
890 if (Utils::OpenHandle(object_template)->constructor()->IsUndefined()) {
891 Local<FunctionTemplate> templ = FunctionTemplate::New();
892 i::Handle<i::FunctionTemplateInfo> constructor = Utils::OpenHandle(*templ);
893 constructor->set_instance_template(*Utils::OpenHandle(object_template));
894 Utils::OpenHandle(object_template)->set_constructor(*constructor);
895 }
896}
897
898
899void ObjectTemplate::SetAccessor(v8::Handle<String> name,
900 AccessorGetter getter,
901 AccessorSetter setter,
902 v8::Handle<Value> data,
903 AccessControl settings,
904 PropertyAttribute attribute) {
905 if (IsDeadCheck("v8::ObjectTemplate::SetAccessor()")) return;
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +0000906 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000907 HandleScope scope;
908 EnsureConstructor(this);
909 i::FunctionTemplateInfo* constructor =
910 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
911 i::Handle<i::FunctionTemplateInfo> cons(constructor);
912 Utils::ToLocal(cons)->AddInstancePropertyAccessor(name,
913 getter,
914 setter,
915 data,
916 settings,
917 attribute);
918}
919
920
921void ObjectTemplate::SetNamedPropertyHandler(NamedPropertyGetter getter,
922 NamedPropertySetter setter,
923 NamedPropertyQuery query,
924 NamedPropertyDeleter remover,
925 NamedPropertyEnumerator enumerator,
926 Handle<Value> data) {
927 if (IsDeadCheck("v8::ObjectTemplate::SetNamedPropertyHandler()")) return;
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +0000928 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000929 HandleScope scope;
930 EnsureConstructor(this);
931 i::FunctionTemplateInfo* constructor =
932 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
933 i::Handle<i::FunctionTemplateInfo> cons(constructor);
934 Utils::ToLocal(cons)->SetNamedInstancePropertyHandler(getter,
935 setter,
936 query,
937 remover,
938 enumerator,
939 data);
940}
941
942
943void ObjectTemplate::MarkAsUndetectable() {
944 if (IsDeadCheck("v8::ObjectTemplate::MarkAsUndetectable()")) return;
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +0000945 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000946 HandleScope scope;
947 EnsureConstructor(this);
948 i::FunctionTemplateInfo* constructor =
949 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
950 i::Handle<i::FunctionTemplateInfo> cons(constructor);
951 cons->set_undetectable(true);
952}
953
954
955void ObjectTemplate::SetAccessCheckCallbacks(
956 NamedSecurityCallback named_callback,
957 IndexedSecurityCallback indexed_callback,
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000958 Handle<Value> data,
959 bool turned_on_by_default) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000960 if (IsDeadCheck("v8::ObjectTemplate::SetAccessCheckCallbacks()")) return;
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +0000961 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000962 HandleScope scope;
963 EnsureConstructor(this);
964
965 i::Handle<i::Struct> struct_info =
966 i::Factory::NewStruct(i::ACCESS_CHECK_INFO_TYPE);
967 i::Handle<i::AccessCheckInfo> info =
968 i::Handle<i::AccessCheckInfo>::cast(struct_info);
969 info->set_named_callback(*FromCData(named_callback));
970 info->set_indexed_callback(*FromCData(indexed_callback));
971 if (data.IsEmpty()) data = v8::Undefined();
972 info->set_data(*Utils::OpenHandle(*data));
973
974 i::FunctionTemplateInfo* constructor =
975 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
976 i::Handle<i::FunctionTemplateInfo> cons(constructor);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000977 cons->set_access_check_info(*info);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000978 cons->set_needs_access_check(turned_on_by_default);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000979}
980
981
982void ObjectTemplate::SetIndexedPropertyHandler(
983 IndexedPropertyGetter getter,
984 IndexedPropertySetter setter,
985 IndexedPropertyQuery query,
986 IndexedPropertyDeleter remover,
987 IndexedPropertyEnumerator enumerator,
988 Handle<Value> data) {
989 if (IsDeadCheck("v8::ObjectTemplate::SetIndexedPropertyHandler()")) return;
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +0000990 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000991 HandleScope scope;
992 EnsureConstructor(this);
993 i::FunctionTemplateInfo* constructor =
994 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
995 i::Handle<i::FunctionTemplateInfo> cons(constructor);
996 Utils::ToLocal(cons)->SetIndexedInstancePropertyHandler(getter,
997 setter,
998 query,
999 remover,
1000 enumerator,
1001 data);
1002}
1003
1004
1005void ObjectTemplate::SetCallAsFunctionHandler(InvocationCallback callback,
1006 Handle<Value> data) {
1007 if (IsDeadCheck("v8::ObjectTemplate::SetCallAsFunctionHandler()")) return;
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00001008 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001009 HandleScope scope;
1010 EnsureConstructor(this);
1011 i::FunctionTemplateInfo* constructor =
1012 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1013 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1014 Utils::ToLocal(cons)->SetInstanceCallAsFunctionHandler(callback, data);
1015}
1016
1017
kasper.lund212ac232008-07-16 07:07:30 +00001018int ObjectTemplate::InternalFieldCount() {
1019 if (IsDeadCheck("v8::ObjectTemplate::InternalFieldCount()")) {
1020 return 0;
1021 }
1022 return i::Smi::cast(Utils::OpenHandle(this)->internal_field_count())->value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001023}
1024
1025
kasper.lund212ac232008-07-16 07:07:30 +00001026void ObjectTemplate::SetInternalFieldCount(int value) {
1027 if (IsDeadCheck("v8::ObjectTemplate::SetInternalFieldCount()")) return;
1028 if (!ApiCheck(i::Smi::IsValid(value),
1029 "v8::ObjectTemplate::SetInternalFieldCount()",
1030 "Invalid internal field count")) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001031 return;
1032 }
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00001033 ENTER_V8;
ager@chromium.org9258b6b2008-09-11 09:11:10 +00001034 if (value > 0) {
1035 // The internal field count is set by the constructor function's
1036 // construct code, so we ensure that there is a constructor
1037 // function to do the setting.
1038 EnsureConstructor(this);
1039 }
kasper.lund212ac232008-07-16 07:07:30 +00001040 Utils::OpenHandle(this)->set_internal_field_count(i::Smi::FromInt(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001041}
1042
1043
kasper.lund212ac232008-07-16 07:07:30 +00001044// --- S c r i p t D a t a ---
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001045
1046
1047ScriptData* ScriptData::PreCompile(const char* input, int length) {
1048 unibrow::Utf8InputBuffer<> buf(input, length);
1049 return i::PreParse(&buf, NULL);
1050}
1051
1052
1053ScriptData* ScriptData::New(unsigned* data, int length) {
1054 return new i::ScriptDataImpl(i::Vector<unsigned>(data, length));
1055}
1056
1057
1058// --- S c r i p t ---
1059
1060
1061Local<Script> Script::Compile(v8::Handle<String> source,
1062 v8::ScriptOrigin* origin,
1063 v8::ScriptData* script_data) {
1064 ON_BAILOUT("v8::Script::Compile()", return Local<Script>());
1065 LOG_API("Script::Compile");
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00001066 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001067 i::Handle<i::String> str = Utils::OpenHandle(*source);
mads.s.agercbaa0602008-08-14 13:41:48 +00001068 i::Handle<i::Object> name_obj;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001069 int line_offset = 0;
1070 int column_offset = 0;
1071 if (origin != NULL) {
1072 if (!origin->ResourceName().IsEmpty()) {
1073 name_obj = Utils::OpenHandle(*origin->ResourceName());
1074 }
1075 if (!origin->ResourceLineOffset().IsEmpty()) {
1076 line_offset = static_cast<int>(origin->ResourceLineOffset()->Value());
1077 }
1078 if (!origin->ResourceColumnOffset().IsEmpty()) {
1079 column_offset = static_cast<int>(origin->ResourceColumnOffset()->Value());
1080 }
1081 }
1082 EXCEPTION_PREAMBLE();
1083 i::ScriptDataImpl* pre_data = static_cast<i::ScriptDataImpl*>(script_data);
1084 // We assert that the pre-data is sane, even though we can actually
1085 // handle it if it turns out not to be in release mode.
1086 ASSERT(pre_data == NULL || pre_data->SanityCheck());
1087 // If the pre-data isn't sane we simply ignore it
kasperl@chromium.orge959c182009-07-27 08:59:04 +00001088 if (pre_data != NULL && !pre_data->SanityCheck()) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001089 pre_data = NULL;
kasperl@chromium.orge959c182009-07-27 08:59:04 +00001090 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001091 i::Handle<i::JSFunction> boilerplate = i::Compiler::Compile(str,
1092 name_obj,
1093 line_offset,
1094 column_offset,
1095 NULL,
1096 pre_data);
1097 has_pending_exception = boilerplate.is_null();
1098 EXCEPTION_BAILOUT_CHECK(Local<Script>());
1099 i::Handle<i::JSFunction> result =
1100 i::Factory::NewFunctionFromBoilerplate(boilerplate,
1101 i::Top::global_context());
1102 return Local<Script>(ToApi<Script>(result));
1103}
1104
1105
mads.s.agercbaa0602008-08-14 13:41:48 +00001106Local<Script> Script::Compile(v8::Handle<String> source,
1107 v8::Handle<Value> file_name) {
1108 ScriptOrigin origin(file_name);
1109 return Compile(source, &origin);
1110}
1111
1112
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001113Local<Value> Script::Run() {
1114 ON_BAILOUT("v8::Script::Run()", return Local<Value>());
1115 LOG_API("Script::Run");
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00001116 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001117 i::Object* raw_result = NULL;
1118 {
1119 HandleScope scope;
1120 i::Handle<i::JSFunction> fun = Utils::OpenHandle(this);
1121 EXCEPTION_PREAMBLE();
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001122 i::Handle<i::Object> receiver(i::Top::context()->global_proxy());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001123 i::Handle<i::Object> result =
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001124 i::Execution::Call(fun, receiver, 0, NULL, &has_pending_exception);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001125 EXCEPTION_BAILOUT_CHECK(Local<Value>());
1126 raw_result = *result;
1127 }
1128 i::Handle<i::Object> result(raw_result);
1129 return Utils::ToLocal(result);
1130}
1131
1132
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001133Local<Value> Script::Id() {
1134 ON_BAILOUT("v8::Script::Id()", return Local<Value>());
1135 LOG_API("Script::Id");
1136 i::Object* raw_id = NULL;
1137 {
1138 HandleScope scope;
1139 i::Handle<i::JSFunction> fun = Utils::OpenHandle(this);
1140 i::Handle<i::Script> script(i::Script::cast(fun->shared()->script()));
1141 i::Handle<i::Object> id(script->id());
1142 raw_id = *id;
1143 }
1144 i::Handle<i::Object> id(raw_id);
1145 return Utils::ToLocal(id);
1146}
1147
1148
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001149void Script::SetData(v8::Handle<Value> data) {
1150 ON_BAILOUT("v8::Script::SetData()", return);
1151 LOG_API("Script::SetData");
1152 {
1153 HandleScope scope;
1154 i::Handle<i::JSFunction> fun = Utils::OpenHandle(this);
1155 i::Handle<i::Object> raw_data = Utils::OpenHandle(*data);
1156 i::Handle<i::Script> script(i::Script::cast(fun->shared()->script()));
1157 script->set_data(*raw_data);
1158 }
1159}
1160
1161
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001162// --- E x c e p t i o n s ---
1163
1164
1165v8::TryCatch::TryCatch()
1166 : next_(i::Top::try_catch_handler()),
1167 exception_(i::Heap::the_hole_value()),
ager@chromium.org9258b6b2008-09-11 09:11:10 +00001168 message_(i::Smi::FromInt(0)),
1169 is_verbose_(false),
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001170 capture_message_(true),
1171 js_handler_(NULL) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001172 i::Top::RegisterTryCatchHandler(this);
1173}
1174
1175
1176v8::TryCatch::~TryCatch() {
1177 i::Top::UnregisterTryCatchHandler(this);
1178}
1179
1180
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001181bool v8::TryCatch::HasCaught() const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001182 return !reinterpret_cast<i::Object*>(exception_)->IsTheHole();
1183}
1184
1185
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001186v8::Local<Value> v8::TryCatch::Exception() const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001187 if (HasCaught()) {
1188 // Check for out of memory exception.
1189 i::Object* exception = reinterpret_cast<i::Object*>(exception_);
1190 return v8::Utils::ToLocal(i::Handle<i::Object>(exception));
1191 } else {
1192 return v8::Local<Value>();
1193 }
1194}
1195
1196
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001197v8::Local<v8::Message> v8::TryCatch::Message() const {
ager@chromium.org9258b6b2008-09-11 09:11:10 +00001198 if (HasCaught() && message_ != i::Smi::FromInt(0)) {
1199 i::Object* message = reinterpret_cast<i::Object*>(message_);
1200 return v8::Utils::MessageToLocal(i::Handle<i::Object>(message));
1201 } else {
1202 return v8::Local<v8::Message>();
1203 }
1204}
1205
1206
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001207void v8::TryCatch::Reset() {
1208 exception_ = i::Heap::the_hole_value();
ager@chromium.org9258b6b2008-09-11 09:11:10 +00001209 message_ = i::Smi::FromInt(0);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001210}
1211
1212
1213void v8::TryCatch::SetVerbose(bool value) {
1214 is_verbose_ = value;
1215}
1216
1217
ager@chromium.org9258b6b2008-09-11 09:11:10 +00001218void v8::TryCatch::SetCaptureMessage(bool value) {
1219 capture_message_ = value;
1220}
1221
1222
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001223// --- M e s s a g e ---
1224
1225
ager@chromium.org32912102009-01-16 10:38:43 +00001226Local<String> Message::Get() const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001227 ON_BAILOUT("v8::Message::Get()", return Local<String>());
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00001228 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001229 HandleScope scope;
1230 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1231 i::Handle<i::String> raw_result = i::MessageHandler::GetMessage(obj);
1232 Local<String> result = Utils::ToLocal(raw_result);
1233 return scope.Close(result);
1234}
1235
1236
ager@chromium.org32912102009-01-16 10:38:43 +00001237v8::Handle<Value> Message::GetScriptResourceName() const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001238 if (IsDeadCheck("v8::Message::GetScriptResourceName()")) {
1239 return Local<String>();
1240 }
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00001241 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001242 HandleScope scope;
1243 i::Handle<i::JSObject> obj =
1244 i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
1245 // Return this.script.name.
1246 i::Handle<i::JSValue> script =
1247 i::Handle<i::JSValue>::cast(GetProperty(obj, "script"));
1248 i::Handle<i::Object> resource_name(i::Script::cast(script->value())->name());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001249 return scope.Close(Utils::ToLocal(resource_name));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001250}
1251
1252
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001253v8::Handle<Value> Message::GetScriptData() const {
1254 if (IsDeadCheck("v8::Message::GetScriptResourceData()")) {
1255 return Local<Value>();
1256 }
1257 ENTER_V8;
1258 HandleScope scope;
1259 i::Handle<i::JSObject> obj =
1260 i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
1261 // Return this.script.data.
1262 i::Handle<i::JSValue> script =
1263 i::Handle<i::JSValue>::cast(GetProperty(obj, "script"));
1264 i::Handle<i::Object> data(i::Script::cast(script->value())->data());
1265 return scope.Close(Utils::ToLocal(data));
1266}
1267
1268
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001269static i::Handle<i::Object> CallV8HeapFunction(const char* name,
1270 i::Handle<i::Object> recv,
1271 int argc,
1272 i::Object** argv[],
1273 bool* has_pending_exception) {
1274 i::Handle<i::String> fmt_str = i::Factory::LookupAsciiSymbol(name);
1275 i::Object* object_fun = i::Top::builtins()->GetProperty(*fmt_str);
1276 i::Handle<i::JSFunction> fun =
1277 i::Handle<i::JSFunction>(i::JSFunction::cast(object_fun));
1278 i::Handle<i::Object> value =
1279 i::Execution::Call(fun, recv, argc, argv, has_pending_exception);
1280 return value;
1281}
1282
1283
1284static i::Handle<i::Object> CallV8HeapFunction(const char* name,
1285 i::Handle<i::Object> data,
1286 bool* has_pending_exception) {
1287 i::Object** argv[1] = { data.location() };
1288 return CallV8HeapFunction(name,
1289 i::Top::builtins(),
1290 1,
1291 argv,
1292 has_pending_exception);
1293}
1294
1295
ager@chromium.org32912102009-01-16 10:38:43 +00001296int Message::GetLineNumber() const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001297 ON_BAILOUT("v8::Message::GetLineNumber()", return -1);
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00001298 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001299 HandleScope scope;
1300 EXCEPTION_PREAMBLE();
1301 i::Handle<i::Object> result = CallV8HeapFunction("GetLineNumber",
1302 Utils::OpenHandle(this),
1303 &has_pending_exception);
1304 EXCEPTION_BAILOUT_CHECK(0);
1305 return static_cast<int>(result->Number());
1306}
1307
1308
ager@chromium.org32912102009-01-16 10:38:43 +00001309int Message::GetStartPosition() const {
ager@chromium.org9258b6b2008-09-11 09:11:10 +00001310 if (IsDeadCheck("v8::Message::GetStartPosition()")) return 0;
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00001311 ENTER_V8;
ager@chromium.org9258b6b2008-09-11 09:11:10 +00001312 HandleScope scope;
1313
1314 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1315 return static_cast<int>(GetProperty(data_obj, "startPos")->Number());
1316}
1317
1318
ager@chromium.org32912102009-01-16 10:38:43 +00001319int Message::GetEndPosition() const {
ager@chromium.org9258b6b2008-09-11 09:11:10 +00001320 if (IsDeadCheck("v8::Message::GetEndPosition()")) return 0;
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00001321 ENTER_V8;
ager@chromium.org9258b6b2008-09-11 09:11:10 +00001322 HandleScope scope;
1323 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1324 return static_cast<int>(GetProperty(data_obj, "endPos")->Number());
1325}
1326
1327
ager@chromium.org32912102009-01-16 10:38:43 +00001328int Message::GetStartColumn() const {
ager@chromium.org9258b6b2008-09-11 09:11:10 +00001329 if (IsDeadCheck("v8::Message::GetStartColumn()")) return 0;
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00001330 ENTER_V8;
ager@chromium.org9258b6b2008-09-11 09:11:10 +00001331 HandleScope scope;
1332 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1333 EXCEPTION_PREAMBLE();
1334 i::Handle<i::Object> start_col_obj = CallV8HeapFunction(
1335 "GetPositionInLine",
1336 data_obj,
1337 &has_pending_exception);
1338 EXCEPTION_BAILOUT_CHECK(0);
1339 return static_cast<int>(start_col_obj->Number());
1340}
1341
1342
ager@chromium.org32912102009-01-16 10:38:43 +00001343int Message::GetEndColumn() const {
ager@chromium.org9258b6b2008-09-11 09:11:10 +00001344 if (IsDeadCheck("v8::Message::GetEndColumn()")) return 0;
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00001345 ENTER_V8;
ager@chromium.org9258b6b2008-09-11 09:11:10 +00001346 HandleScope scope;
1347 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1348 EXCEPTION_PREAMBLE();
1349 i::Handle<i::Object> start_col_obj = CallV8HeapFunction(
1350 "GetPositionInLine",
1351 data_obj,
1352 &has_pending_exception);
1353 EXCEPTION_BAILOUT_CHECK(0);
1354 int start = static_cast<int>(GetProperty(data_obj, "startPos")->Number());
1355 int end = static_cast<int>(GetProperty(data_obj, "endPos")->Number());
1356 return static_cast<int>(start_col_obj->Number()) + (end - start);
1357}
1358
1359
ager@chromium.org32912102009-01-16 10:38:43 +00001360Local<String> Message::GetSourceLine() const {
ager@chromium.org9258b6b2008-09-11 09:11:10 +00001361 ON_BAILOUT("v8::Message::GetSourceLine()", return Local<String>());
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00001362 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001363 HandleScope scope;
1364 EXCEPTION_PREAMBLE();
1365 i::Handle<i::Object> result = CallV8HeapFunction("GetSourceLine",
1366 Utils::OpenHandle(this),
1367 &has_pending_exception);
ager@chromium.org9258b6b2008-09-11 09:11:10 +00001368 EXCEPTION_BAILOUT_CHECK(Local<v8::String>());
1369 if (result->IsString()) {
1370 return scope.Close(Utils::ToLocal(i::Handle<i::String>::cast(result)));
1371 } else {
1372 return Local<String>();
1373 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001374}
1375
1376
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001377void Message::PrintCurrentStackTrace(FILE* out) {
1378 if (IsDeadCheck("v8::Message::PrintCurrentStackTrace()")) return;
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00001379 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001380 i::Top::PrintCurrentStackTrace(out);
1381}
1382
1383
1384// --- D a t a ---
1385
ager@chromium.org32912102009-01-16 10:38:43 +00001386bool Value::IsUndefined() const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001387 if (IsDeadCheck("v8::Value::IsUndefined()")) return false;
1388 return Utils::OpenHandle(this)->IsUndefined();
1389}
1390
1391
ager@chromium.org32912102009-01-16 10:38:43 +00001392bool Value::IsNull() const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001393 if (IsDeadCheck("v8::Value::IsNull()")) return false;
1394 return Utils::OpenHandle(this)->IsNull();
1395}
1396
1397
ager@chromium.org32912102009-01-16 10:38:43 +00001398bool Value::IsTrue() const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001399 if (IsDeadCheck("v8::Value::IsTrue()")) return false;
1400 return Utils::OpenHandle(this)->IsTrue();
1401}
1402
1403
ager@chromium.org32912102009-01-16 10:38:43 +00001404bool Value::IsFalse() const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001405 if (IsDeadCheck("v8::Value::IsFalse()")) return false;
1406 return Utils::OpenHandle(this)->IsFalse();
1407}
1408
1409
ager@chromium.org32912102009-01-16 10:38:43 +00001410bool Value::IsFunction() const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001411 if (IsDeadCheck("v8::Value::IsFunction()")) return false;
1412 return Utils::OpenHandle(this)->IsJSFunction();
1413}
1414
1415
ager@chromium.org32912102009-01-16 10:38:43 +00001416bool Value::IsString() const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001417 if (IsDeadCheck("v8::Value::IsString()")) return false;
1418 return Utils::OpenHandle(this)->IsString();
1419}
1420
1421
ager@chromium.org32912102009-01-16 10:38:43 +00001422bool Value::IsArray() const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001423 if (IsDeadCheck("v8::Value::IsArray()")) return false;
1424 return Utils::OpenHandle(this)->IsJSArray();
1425}
1426
1427
ager@chromium.org32912102009-01-16 10:38:43 +00001428bool Value::IsObject() const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001429 if (IsDeadCheck("v8::Value::IsObject()")) return false;
1430 return Utils::OpenHandle(this)->IsJSObject();
1431}
1432
1433
ager@chromium.org32912102009-01-16 10:38:43 +00001434bool Value::IsNumber() const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001435 if (IsDeadCheck("v8::Value::IsNumber()")) return false;
1436 return Utils::OpenHandle(this)->IsNumber();
1437}
1438
1439
ager@chromium.org32912102009-01-16 10:38:43 +00001440bool Value::IsBoolean() const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001441 if (IsDeadCheck("v8::Value::IsBoolean()")) return false;
1442 return Utils::OpenHandle(this)->IsBoolean();
1443}
1444
1445
ager@chromium.org32912102009-01-16 10:38:43 +00001446bool Value::IsExternal() const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001447 if (IsDeadCheck("v8::Value::IsExternal()")) return false;
1448 return Utils::OpenHandle(this)->IsProxy();
1449}
1450
1451
ager@chromium.org32912102009-01-16 10:38:43 +00001452bool Value::IsInt32() const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001453 if (IsDeadCheck("v8::Value::IsInt32()")) return false;
1454 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1455 if (obj->IsSmi()) return true;
1456 if (obj->IsNumber()) {
1457 double value = obj->Number();
1458 return i::FastI2D(i::FastD2I(value)) == value;
1459 }
1460 return false;
1461}
1462
1463
ager@chromium.org32912102009-01-16 10:38:43 +00001464bool Value::IsDate() const {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001465 if (IsDeadCheck("v8::Value::IsDate()")) return false;
1466 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1467 return obj->HasSpecificClassOf(i::Heap::Date_symbol());
1468}
1469
1470
ager@chromium.org32912102009-01-16 10:38:43 +00001471Local<String> Value::ToString() const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001472 if (IsDeadCheck("v8::Value::ToString()")) return Local<String>();
1473 LOG_API("ToString");
1474 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1475 i::Handle<i::Object> str;
1476 if (obj->IsString()) {
1477 str = obj;
1478 } else {
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00001479 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001480 EXCEPTION_PREAMBLE();
1481 str = i::Execution::ToString(obj, &has_pending_exception);
1482 EXCEPTION_BAILOUT_CHECK(Local<String>());
1483 }
1484 return Local<String>(ToApi<String>(str));
1485}
1486
1487
ager@chromium.org32912102009-01-16 10:38:43 +00001488Local<String> Value::ToDetailString() const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001489 if (IsDeadCheck("v8::Value::ToDetailString()")) return Local<String>();
1490 LOG_API("ToDetailString");
1491 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1492 i::Handle<i::Object> str;
1493 if (obj->IsString()) {
1494 str = obj;
1495 } else {
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00001496 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001497 EXCEPTION_PREAMBLE();
1498 str = i::Execution::ToDetailString(obj, &has_pending_exception);
1499 EXCEPTION_BAILOUT_CHECK(Local<String>());
1500 }
1501 return Local<String>(ToApi<String>(str));
1502}
1503
1504
ager@chromium.org32912102009-01-16 10:38:43 +00001505Local<v8::Object> Value::ToObject() const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001506 if (IsDeadCheck("v8::Value::ToObject()")) return Local<v8::Object>();
1507 LOG_API("ToObject");
1508 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1509 i::Handle<i::Object> val;
1510 if (obj->IsJSObject()) {
1511 val = obj;
1512 } else {
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00001513 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001514 EXCEPTION_PREAMBLE();
1515 val = i::Execution::ToObject(obj, &has_pending_exception);
1516 EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
1517 }
1518 return Local<v8::Object>(ToApi<Object>(val));
1519}
1520
1521
ager@chromium.org32912102009-01-16 10:38:43 +00001522Local<Boolean> Value::ToBoolean() const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001523 if (IsDeadCheck("v8::Value::ToBoolean()")) return Local<Boolean>();
1524 LOG_API("ToBoolean");
1525 i::Handle<i::Object> obj = Utils::OpenHandle(this);
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00001526 if (obj->IsBoolean()) {
1527 return Local<Boolean>(ToApi<Boolean>(obj));
1528 } else {
1529 ENTER_V8;
1530 i::Handle<i::Object> val = i::Execution::ToBoolean(obj);
1531 return Local<Boolean>(ToApi<Boolean>(val));
1532 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001533}
1534
1535
ager@chromium.org32912102009-01-16 10:38:43 +00001536Local<Number> Value::ToNumber() const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001537 if (IsDeadCheck("v8::Value::ToNumber()")) return Local<Number>();
1538 LOG_API("ToNumber");
1539 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1540 i::Handle<i::Object> num;
1541 if (obj->IsNumber()) {
1542 num = obj;
1543 } else {
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00001544 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001545 EXCEPTION_PREAMBLE();
1546 num = i::Execution::ToNumber(obj, &has_pending_exception);
1547 EXCEPTION_BAILOUT_CHECK(Local<Number>());
1548 }
1549 return Local<Number>(ToApi<Number>(num));
1550}
1551
1552
ager@chromium.org32912102009-01-16 10:38:43 +00001553Local<Integer> Value::ToInteger() const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001554 if (IsDeadCheck("v8::Value::ToInteger()")) return Local<Integer>();
1555 LOG_API("ToInteger");
1556 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1557 i::Handle<i::Object> num;
1558 if (obj->IsSmi()) {
1559 num = obj;
1560 } else {
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00001561 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001562 EXCEPTION_PREAMBLE();
1563 num = i::Execution::ToInteger(obj, &has_pending_exception);
1564 EXCEPTION_BAILOUT_CHECK(Local<Integer>());
1565 }
1566 return Local<Integer>(ToApi<Integer>(num));
1567}
1568
1569
1570External* External::Cast(v8::Value* that) {
1571 if (IsDeadCheck("v8::External::Cast()")) return 0;
1572 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1573 ApiCheck(obj->IsProxy(),
1574 "v8::External::Cast()",
1575 "Could not convert to external");
1576 return static_cast<External*>(that);
1577}
1578
1579
1580v8::Object* v8::Object::Cast(Value* that) {
1581 if (IsDeadCheck("v8::Object::Cast()")) return 0;
1582 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1583 ApiCheck(obj->IsJSObject(),
1584 "v8::Object::Cast()",
1585 "Could not convert to object");
1586 return static_cast<v8::Object*>(that);
1587}
1588
1589
1590v8::Function* v8::Function::Cast(Value* that) {
1591 if (IsDeadCheck("v8::Function::Cast()")) return 0;
1592 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1593 ApiCheck(obj->IsJSFunction(),
1594 "v8::Function::Cast()",
1595 "Could not convert to function");
1596 return static_cast<v8::Function*>(that);
1597}
1598
1599
1600v8::String* v8::String::Cast(v8::Value* that) {
1601 if (IsDeadCheck("v8::String::Cast()")) return 0;
1602 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1603 ApiCheck(obj->IsString(),
1604 "v8::String::Cast()",
1605 "Could not convert to string");
1606 return static_cast<v8::String*>(that);
1607}
1608
1609
1610v8::Number* v8::Number::Cast(v8::Value* that) {
1611 if (IsDeadCheck("v8::Number::Cast()")) return 0;
1612 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1613 ApiCheck(obj->IsNumber(),
1614 "v8::Number::Cast()",
1615 "Could not convert to number");
1616 return static_cast<v8::Number*>(that);
1617}
1618
1619
1620v8::Integer* v8::Integer::Cast(v8::Value* that) {
1621 if (IsDeadCheck("v8::Integer::Cast()")) return 0;
1622 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1623 ApiCheck(obj->IsNumber(),
1624 "v8::Integer::Cast()",
1625 "Could not convert to number");
1626 return static_cast<v8::Integer*>(that);
1627}
1628
1629
1630v8::Array* v8::Array::Cast(Value* that) {
1631 if (IsDeadCheck("v8::Array::Cast()")) return 0;
1632 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1633 ApiCheck(obj->IsJSArray(),
1634 "v8::Array::Cast()",
1635 "Could not convert to array");
1636 return static_cast<v8::Array*>(that);
1637}
1638
1639
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001640v8::Date* v8::Date::Cast(v8::Value* that) {
1641 if (IsDeadCheck("v8::Date::Cast()")) return 0;
1642 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1643 ApiCheck(obj->HasSpecificClassOf(i::Heap::Date_symbol()),
1644 "v8::Date::Cast()",
1645 "Could not convert to date");
1646 return static_cast<v8::Date*>(that);
1647}
1648
1649
ager@chromium.org32912102009-01-16 10:38:43 +00001650bool Value::BooleanValue() const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001651 if (IsDeadCheck("v8::Value::BooleanValue()")) return false;
1652 LOG_API("BooleanValue");
1653 i::Handle<i::Object> obj = Utils::OpenHandle(this);
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00001654 if (obj->IsBoolean()) {
1655 return obj->IsTrue();
1656 } else {
1657 ENTER_V8;
1658 i::Handle<i::Object> value = i::Execution::ToBoolean(obj);
1659 return value->IsTrue();
1660 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001661}
1662
1663
ager@chromium.org32912102009-01-16 10:38:43 +00001664double Value::NumberValue() const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001665 if (IsDeadCheck("v8::Value::NumberValue()")) return i::OS::nan_value();
1666 LOG_API("NumberValue");
1667 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1668 i::Handle<i::Object> num;
1669 if (obj->IsNumber()) {
1670 num = obj;
1671 } else {
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00001672 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001673 EXCEPTION_PREAMBLE();
1674 num = i::Execution::ToNumber(obj, &has_pending_exception);
1675 EXCEPTION_BAILOUT_CHECK(i::OS::nan_value());
1676 }
1677 return num->Number();
1678}
1679
1680
ager@chromium.org32912102009-01-16 10:38:43 +00001681int64_t Value::IntegerValue() const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001682 if (IsDeadCheck("v8::Value::IntegerValue()")) return 0;
1683 LOG_API("IntegerValue");
1684 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1685 i::Handle<i::Object> num;
1686 if (obj->IsNumber()) {
1687 num = obj;
1688 } else {
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00001689 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001690 EXCEPTION_PREAMBLE();
1691 num = i::Execution::ToInteger(obj, &has_pending_exception);
1692 EXCEPTION_BAILOUT_CHECK(0);
1693 }
1694 if (num->IsSmi()) {
1695 return i::Smi::cast(*num)->value();
1696 } else {
1697 return static_cast<int64_t>(num->Number());
1698 }
1699}
1700
1701
ager@chromium.org32912102009-01-16 10:38:43 +00001702Local<Int32> Value::ToInt32() const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001703 if (IsDeadCheck("v8::Value::ToInt32()")) return Local<Int32>();
1704 LOG_API("ToInt32");
1705 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1706 i::Handle<i::Object> num;
1707 if (obj->IsSmi()) {
1708 num = obj;
1709 } else {
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00001710 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001711 EXCEPTION_PREAMBLE();
1712 num = i::Execution::ToInt32(obj, &has_pending_exception);
1713 EXCEPTION_BAILOUT_CHECK(Local<Int32>());
1714 }
1715 return Local<Int32>(ToApi<Int32>(num));
1716}
1717
1718
ager@chromium.org32912102009-01-16 10:38:43 +00001719Local<Uint32> Value::ToUint32() const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001720 if (IsDeadCheck("v8::Value::ToUint32()")) return Local<Uint32>();
1721 LOG_API("ToUInt32");
1722 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1723 i::Handle<i::Object> num;
1724 if (obj->IsSmi()) {
1725 num = obj;
1726 } else {
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00001727 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001728 EXCEPTION_PREAMBLE();
1729 num = i::Execution::ToUint32(obj, &has_pending_exception);
1730 EXCEPTION_BAILOUT_CHECK(Local<Uint32>());
1731 }
1732 return Local<Uint32>(ToApi<Uint32>(num));
1733}
1734
1735
ager@chromium.org32912102009-01-16 10:38:43 +00001736Local<Uint32> Value::ToArrayIndex() const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001737 if (IsDeadCheck("v8::Value::ToArrayIndex()")) return Local<Uint32>();
1738 LOG_API("ToArrayIndex");
1739 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1740 if (obj->IsSmi()) {
1741 if (i::Smi::cast(*obj)->value() >= 0) return Utils::Uint32ToLocal(obj);
1742 return Local<Uint32>();
1743 }
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00001744 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001745 EXCEPTION_PREAMBLE();
1746 i::Handle<i::Object> string_obj =
1747 i::Execution::ToString(obj, &has_pending_exception);
1748 EXCEPTION_BAILOUT_CHECK(Local<Uint32>());
1749 i::Handle<i::String> str = i::Handle<i::String>::cast(string_obj);
1750 uint32_t index;
1751 if (str->AsArrayIndex(&index)) {
1752 i::Handle<i::Object> value;
1753 if (index <= static_cast<uint32_t>(i::Smi::kMaxValue)) {
1754 value = i::Handle<i::Object>(i::Smi::FromInt(index));
1755 } else {
1756 value = i::Factory::NewNumber(index);
1757 }
1758 return Utils::Uint32ToLocal(value);
1759 }
1760 return Local<Uint32>();
1761}
1762
1763
ager@chromium.org32912102009-01-16 10:38:43 +00001764int32_t Value::Int32Value() const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001765 if (IsDeadCheck("v8::Value::Int32Value()")) return 0;
1766 LOG_API("Int32Value");
1767 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1768 if (obj->IsSmi()) {
1769 return i::Smi::cast(*obj)->value();
1770 } else {
1771 LOG_API("Int32Value (slow)");
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00001772 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001773 EXCEPTION_PREAMBLE();
1774 i::Handle<i::Object> num =
1775 i::Execution::ToInt32(obj, &has_pending_exception);
1776 EXCEPTION_BAILOUT_CHECK(0);
1777 if (num->IsSmi()) {
1778 return i::Smi::cast(*num)->value();
1779 } else {
1780 return static_cast<int32_t>(num->Number());
1781 }
1782 }
1783}
1784
1785
ager@chromium.org32912102009-01-16 10:38:43 +00001786bool Value::Equals(Handle<Value> that) const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001787 if (IsDeadCheck("v8::Value::Equals()")
1788 || EmptyCheck("v8::Value::Equals()", this)
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00001789 || EmptyCheck("v8::Value::Equals()", that)) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001790 return false;
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00001791 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001792 LOG_API("Equals");
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00001793 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001794 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1795 i::Handle<i::Object> other = Utils::OpenHandle(*that);
1796 i::Object** args[1] = { other.location() };
1797 EXCEPTION_PREAMBLE();
1798 i::Handle<i::Object> result =
1799 CallV8HeapFunction("EQUALS", obj, 1, args, &has_pending_exception);
1800 EXCEPTION_BAILOUT_CHECK(false);
1801 return *result == i::Smi::FromInt(i::EQUAL);
1802}
1803
1804
ager@chromium.org32912102009-01-16 10:38:43 +00001805bool Value::StrictEquals(Handle<Value> that) const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001806 if (IsDeadCheck("v8::Value::StrictEquals()")
1807 || EmptyCheck("v8::Value::StrictEquals()", this)
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00001808 || EmptyCheck("v8::Value::StrictEquals()", that)) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001809 return false;
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00001810 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001811 LOG_API("StrictEquals");
1812 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1813 i::Handle<i::Object> other = Utils::OpenHandle(*that);
1814 // Must check HeapNumber first, since NaN !== NaN.
1815 if (obj->IsHeapNumber()) {
1816 if (!other->IsNumber()) return false;
1817 double x = obj->Number();
1818 double y = other->Number();
1819 // Must check explicitly for NaN:s on Windows, but -0 works fine.
1820 return x == y && !isnan(x) && !isnan(y);
1821 } else if (*obj == *other) { // Also covers Booleans.
1822 return true;
1823 } else if (obj->IsSmi()) {
1824 return other->IsNumber() && obj->Number() == other->Number();
1825 } else if (obj->IsString()) {
1826 return other->IsString() &&
1827 i::String::cast(*obj)->Equals(i::String::cast(*other));
1828 } else if (obj->IsUndefined() || obj->IsUndetectableObject()) {
1829 return other->IsUndefined() || other->IsUndetectableObject();
1830 } else {
1831 return false;
1832 }
1833}
1834
1835
ager@chromium.org32912102009-01-16 10:38:43 +00001836uint32_t Value::Uint32Value() const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001837 if (IsDeadCheck("v8::Value::Uint32Value()")) return 0;
1838 LOG_API("Uint32Value");
1839 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1840 if (obj->IsSmi()) {
1841 return i::Smi::cast(*obj)->value();
1842 } else {
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00001843 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001844 EXCEPTION_PREAMBLE();
1845 i::Handle<i::Object> num =
1846 i::Execution::ToUint32(obj, &has_pending_exception);
1847 EXCEPTION_BAILOUT_CHECK(0);
1848 if (num->IsSmi()) {
1849 return i::Smi::cast(*num)->value();
1850 } else {
1851 return static_cast<uint32_t>(num->Number());
1852 }
1853 }
1854}
1855
1856
1857bool v8::Object::Set(v8::Handle<Value> key, v8::Handle<Value> value,
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001858 v8::PropertyAttribute attribs) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001859 ON_BAILOUT("v8::Object::Set()", return false);
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00001860 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001861 i::Handle<i::Object> self = Utils::OpenHandle(this);
1862 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
1863 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
1864 EXCEPTION_PREAMBLE();
1865 i::Handle<i::Object> obj = i::SetProperty(
1866 self,
1867 key_obj,
1868 value_obj,
1869 static_cast<PropertyAttributes>(attribs));
1870 has_pending_exception = obj.is_null();
1871 EXCEPTION_BAILOUT_CHECK(false);
1872 return true;
1873}
1874
1875
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001876bool v8::Object::ForceSet(v8::Handle<Value> key,
1877 v8::Handle<Value> value,
1878 v8::PropertyAttribute attribs) {
1879 ON_BAILOUT("v8::Object::ForceSet()", return false);
1880 ENTER_V8;
1881 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1882 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
1883 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
1884 EXCEPTION_PREAMBLE();
1885 i::Handle<i::Object> obj = i::ForceSetProperty(
1886 self,
1887 key_obj,
1888 value_obj,
1889 static_cast<PropertyAttributes>(attribs));
1890 has_pending_exception = obj.is_null();
1891 EXCEPTION_BAILOUT_CHECK(false);
1892 return true;
1893}
1894
1895
ager@chromium.orge2902be2009-06-08 12:21:35 +00001896bool v8::Object::ForceDelete(v8::Handle<Value> key) {
1897 ON_BAILOUT("v8::Object::ForceDelete()", return false);
1898 ENTER_V8;
1899 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1900 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
1901 EXCEPTION_PREAMBLE();
1902 i::Handle<i::Object> obj = i::ForceDeleteProperty(self, key_obj);
1903 has_pending_exception = obj.is_null();
1904 EXCEPTION_BAILOUT_CHECK(false);
1905 return obj->IsTrue();
1906}
1907
1908
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001909Local<Value> v8::Object::Get(v8::Handle<Value> key) {
1910 ON_BAILOUT("v8::Object::Get()", return Local<v8::Value>());
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00001911 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001912 i::Handle<i::Object> self = Utils::OpenHandle(this);
1913 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
1914 EXCEPTION_PREAMBLE();
1915 i::Handle<i::Object> result = i::GetProperty(self, key_obj);
1916 has_pending_exception = result.is_null();
1917 EXCEPTION_BAILOUT_CHECK(Local<Value>());
1918 return Utils::ToLocal(result);
1919}
1920
1921
1922Local<Value> v8::Object::GetPrototype() {
1923 ON_BAILOUT("v8::Object::GetPrototype()", return Local<v8::Value>());
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00001924 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001925 i::Handle<i::Object> self = Utils::OpenHandle(this);
1926 i::Handle<i::Object> result = i::GetPrototype(self);
1927 return Utils::ToLocal(result);
1928}
1929
1930
sgjesse@chromium.org900d3b72009-08-07 11:24:25 +00001931Local<Object> v8::Object::FindInstanceInPrototypeChain(
1932 v8::Handle<FunctionTemplate> tmpl) {
1933 ON_BAILOUT("v8::Object::FindInstanceInPrototypeChain()",
1934 return Local<v8::Object>());
1935 ENTER_V8;
1936 i::JSObject* object = *Utils::OpenHandle(this);
1937 i::FunctionTemplateInfo* tmpl_info = *Utils::OpenHandle(*tmpl);
1938 while (!object->IsInstanceOf(tmpl_info)) {
1939 i::Object* prototype = object->GetPrototype();
1940 if (!prototype->IsJSObject()) return Local<Object>();
1941 object = i::JSObject::cast(prototype);
1942 }
1943 return Utils::ToLocal(i::Handle<i::JSObject>(object));
1944}
1945
1946
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001947Local<Array> v8::Object::GetPropertyNames() {
1948 ON_BAILOUT("v8::Object::GetPropertyNames()", return Local<v8::Array>());
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00001949 ENTER_V8;
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001950 v8::HandleScope scope;
1951 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1952 i::Handle<i::FixedArray> value = i::GetKeysInFixedArrayFor(self);
1953 // Because we use caching to speed up enumeration it is important
1954 // to never change the result of the basic enumeration function so
1955 // we clone the result.
1956 i::Handle<i::FixedArray> elms = i::Factory::CopyFixedArray(value);
1957 i::Handle<i::JSArray> result = i::Factory::NewJSArrayWithElements(elms);
1958 return scope.Close(Utils::ToLocal(result));
1959}
1960
1961
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001962Local<String> v8::Object::ObjectProtoToString() {
1963 ON_BAILOUT("v8::Object::ObjectProtoToString()", return Local<v8::String>());
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00001964 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001965 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1966
1967 i::Handle<i::Object> name(self->class_name());
1968
1969 // Native implementation of Object.prototype.toString (v8natives.js):
1970 // var c = %ClassOf(this);
1971 // if (c === 'Arguments') c = 'Object';
1972 // return "[object " + c + "]";
1973
1974 if (!name->IsString()) {
1975 return v8::String::New("[object ]");
1976
1977 } else {
1978 i::Handle<i::String> class_name = i::Handle<i::String>::cast(name);
1979 if (class_name->IsEqualTo(i::CStrVector("Arguments"))) {
1980 return v8::String::New("[object Object]");
1981
1982 } else {
1983 const char* prefix = "[object ";
1984 Local<String> str = Utils::ToLocal(class_name);
1985 const char* postfix = "]";
1986
1987 size_t prefix_len = strlen(prefix);
1988 size_t str_len = str->Length();
1989 size_t postfix_len = strlen(postfix);
1990
1991 size_t buf_len = prefix_len + str_len + postfix_len;
1992 char* buf = i::NewArray<char>(buf_len);
1993
1994 // Write prefix.
1995 char* ptr = buf;
1996 memcpy(ptr, prefix, prefix_len * v8::internal::kCharSize);
1997 ptr += prefix_len;
1998
1999 // Write real content.
2000 str->WriteAscii(ptr, 0, str_len);
2001 ptr += str_len;
2002
2003 // Write postfix.
2004 memcpy(ptr, postfix, postfix_len * v8::internal::kCharSize);
2005
2006 // Copy the buffer into a heap-allocated string and return it.
2007 Local<String> result = v8::String::New(buf, buf_len);
2008 i::DeleteArray(buf);
2009 return result;
2010 }
2011 }
2012}
2013
2014
2015bool v8::Object::Delete(v8::Handle<String> key) {
2016 ON_BAILOUT("v8::Object::Delete()", return false);
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00002017 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002018 HandleScope scope;
2019 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2020 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2021 return i::DeleteProperty(self, key_obj)->IsTrue();
2022}
2023
2024
2025bool v8::Object::Has(v8::Handle<String> key) {
2026 ON_BAILOUT("v8::Object::Has()", return false);
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00002027 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002028 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2029 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2030 return self->HasProperty(*key_obj);
2031}
2032
2033
2034bool v8::Object::Delete(uint32_t index) {
2035 ON_BAILOUT("v8::Object::DeleteProperty()", return false);
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00002036 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002037 HandleScope scope;
2038 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2039 return i::DeleteElement(self, index)->IsTrue();
2040}
2041
2042
2043bool v8::Object::Has(uint32_t index) {
2044 ON_BAILOUT("v8::Object::HasProperty()", return false);
2045 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2046 return self->HasElement(index);
2047}
2048
2049
2050bool v8::Object::HasRealNamedProperty(Handle<String> key) {
2051 ON_BAILOUT("v8::Object::HasRealNamedProperty()", return false);
2052 return Utils::OpenHandle(this)->HasRealNamedProperty(
2053 *Utils::OpenHandle(*key));
2054}
2055
2056
2057bool v8::Object::HasRealIndexedProperty(uint32_t index) {
2058 ON_BAILOUT("v8::Object::HasRealIndexedProperty()", return false);
2059 return Utils::OpenHandle(this)->HasRealElementProperty(index);
2060}
2061
2062
2063bool v8::Object::HasRealNamedCallbackProperty(Handle<String> key) {
2064 ON_BAILOUT("v8::Object::HasRealNamedCallbackProperty()", return false);
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00002065 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002066 return Utils::OpenHandle(this)->HasRealNamedCallbackProperty(
2067 *Utils::OpenHandle(*key));
2068}
2069
2070
2071bool v8::Object::HasNamedLookupInterceptor() {
2072 ON_BAILOUT("v8::Object::HasNamedLookupInterceptor()", return false);
2073 return Utils::OpenHandle(this)->HasNamedInterceptor();
2074}
2075
2076
2077bool v8::Object::HasIndexedLookupInterceptor() {
2078 ON_BAILOUT("v8::Object::HasIndexedLookupInterceptor()", return false);
2079 return Utils::OpenHandle(this)->HasIndexedInterceptor();
2080}
2081
2082
2083Handle<Value> v8::Object::GetRealNamedPropertyInPrototypeChain(
2084 Handle<String> key) {
2085 ON_BAILOUT("v8::Object::GetRealNamedPropertyInPrototypeChain()",
2086 return Local<Value>());
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00002087 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002088 i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this);
2089 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2090 i::LookupResult lookup;
2091 self_obj->LookupRealNamedPropertyInPrototypes(*key_obj, &lookup);
2092 if (lookup.IsValid()) {
2093 PropertyAttributes attributes;
2094 i::Handle<i::Object> result(self_obj->GetProperty(*self_obj,
2095 &lookup,
2096 *key_obj,
2097 &attributes));
2098 return Utils::ToLocal(result);
2099 }
v8.team.kasperl727e9952008-09-02 14:56:44 +00002100 return Local<Value>(); // No real property was found in prototype chain.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002101}
2102
2103
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002104// Turns on access checks by copying the map and setting the check flag.
2105// Because the object gets a new map, existing inline cache caching
2106// the old map of this object will fail.
2107void v8::Object::TurnOnAccessCheck() {
2108 ON_BAILOUT("v8::Object::TurnOnAccessCheck()", return);
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00002109 ENTER_V8;
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002110 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
2111
2112 i::Handle<i::Map> new_map =
2113 i::Factory::CopyMapDropTransitions(i::Handle<i::Map>(obj->map()));
ager@chromium.org870a0b62008-11-04 11:43:05 +00002114 new_map->set_is_access_check_needed(true);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002115 obj->set_map(*new_map);
2116}
2117
2118
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002119Local<v8::Object> v8::Object::Clone() {
2120 ON_BAILOUT("v8::Object::Clone()", return Local<Object>());
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00002121 ENTER_V8;
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002122 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2123 EXCEPTION_PREAMBLE();
2124 i::Handle<i::JSObject> result = i::Copy(self);
2125 has_pending_exception = result.is_null();
2126 EXCEPTION_BAILOUT_CHECK(Local<Object>());
2127 return Utils::ToLocal(result);
2128}
2129
2130
2131int v8::Object::GetIdentityHash() {
2132 ON_BAILOUT("v8::Object::GetIdentityHash()", return 0);
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00002133 ENTER_V8;
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002134 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2135 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, true));
2136 i::Handle<i::Object> hash_symbol = i::Factory::identity_hash_symbol();
2137 i::Handle<i::Object> hash = i::GetProperty(hidden_props, hash_symbol);
2138 int hash_value;
2139 if (hash->IsSmi()) {
2140 hash_value = i::Smi::cast(*hash)->value();
2141 } else {
ager@chromium.org5ec48922009-05-05 07:25:34 +00002142 int attempts = 0;
2143 do {
ager@chromium.orgeadaf222009-06-16 09:43:10 +00002144 // Generate a random 32-bit hash value but limit range to fit
2145 // within a smi.
2146 hash_value = i::V8::Random() & i::Smi::kMaxValue;
ager@chromium.org5ec48922009-05-05 07:25:34 +00002147 attempts++;
2148 } while (hash_value == 0 && attempts < 30);
2149 hash_value = hash_value != 0 ? hash_value : 1; // never return 0
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002150 i::SetProperty(hidden_props,
2151 hash_symbol,
2152 i::Handle<i::Object>(i::Smi::FromInt(hash_value)),
2153 static_cast<PropertyAttributes>(None));
2154 }
2155 return hash_value;
2156}
2157
2158
2159bool v8::Object::SetHiddenValue(v8::Handle<v8::String> key,
2160 v8::Handle<v8::Value> value) {
2161 ON_BAILOUT("v8::Object::SetHiddenValue()", return false);
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00002162 ENTER_V8;
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002163 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2164 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, true));
2165 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2166 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2167 EXCEPTION_PREAMBLE();
2168 i::Handle<i::Object> obj = i::SetProperty(
2169 hidden_props,
2170 key_obj,
2171 value_obj,
2172 static_cast<PropertyAttributes>(None));
2173 has_pending_exception = obj.is_null();
2174 EXCEPTION_BAILOUT_CHECK(false);
2175 return true;
2176}
2177
2178
2179v8::Local<v8::Value> v8::Object::GetHiddenValue(v8::Handle<v8::String> key) {
2180 ON_BAILOUT("v8::Object::GetHiddenValue()", return Local<v8::Value>());
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00002181 ENTER_V8;
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002182 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2183 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, false));
2184 if (hidden_props->IsUndefined()) {
2185 return v8::Local<v8::Value>();
2186 }
2187 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2188 EXCEPTION_PREAMBLE();
2189 i::Handle<i::Object> result = i::GetProperty(hidden_props, key_obj);
2190 has_pending_exception = result.is_null();
2191 EXCEPTION_BAILOUT_CHECK(v8::Local<v8::Value>());
2192 if (result->IsUndefined()) {
2193 return v8::Local<v8::Value>();
2194 }
2195 return Utils::ToLocal(result);
2196}
2197
2198
2199bool v8::Object::DeleteHiddenValue(v8::Handle<v8::String> key) {
2200 ON_BAILOUT("v8::DeleteHiddenValue()", return false);
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00002201 ENTER_V8;
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002202 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
kasperl@chromium.orgacae3782009-04-11 09:17:08 +00002203 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, false));
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002204 if (hidden_props->IsUndefined()) {
kasperl@chromium.orgacae3782009-04-11 09:17:08 +00002205 return true;
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002206 }
kasperl@chromium.orgacae3782009-04-11 09:17:08 +00002207 i::Handle<i::JSObject> js_obj(i::JSObject::cast(*hidden_props));
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002208 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
kasperl@chromium.orgacae3782009-04-11 09:17:08 +00002209 return i::DeleteProperty(js_obj, key_obj)->IsTrue();
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002210}
2211
2212
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002213void v8::Object::SetIndexedPropertiesToPixelData(uint8_t* data, int length) {
2214 ON_BAILOUT("v8::SetElementsToPixelData()", return);
2215 ENTER_V8;
2216 if (!ApiCheck(i::Smi::IsValid(length),
2217 "v8::Object::SetIndexedPropertiesToPixelData()",
2218 "length exceeds max acceptable value")) {
2219 return;
2220 }
2221 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2222 if (!ApiCheck(!self->IsJSArray(),
2223 "v8::Object::SetIndexedPropertiesToPixelData()",
2224 "JSArray is not supported")) {
2225 return;
2226 }
2227 i::Handle<i::PixelArray> pixels = i::Factory::NewPixelArray(length, data);
2228 self->set_elements(*pixels);
2229}
2230
2231
ager@chromium.org32912102009-01-16 10:38:43 +00002232Local<v8::Object> Function::NewInstance() const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002233 return NewInstance(0, NULL);
2234}
2235
2236
2237Local<v8::Object> Function::NewInstance(int argc,
ager@chromium.org32912102009-01-16 10:38:43 +00002238 v8::Handle<v8::Value> argv[]) const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002239 ON_BAILOUT("v8::Function::NewInstance()", return Local<v8::Object>());
2240 LOG_API("Function::NewInstance");
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00002241 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002242 HandleScope scope;
2243 i::Handle<i::JSFunction> function = Utils::OpenHandle(this);
2244 STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
2245 i::Object*** args = reinterpret_cast<i::Object***>(argv);
2246 EXCEPTION_PREAMBLE();
2247 i::Handle<i::Object> returned =
2248 i::Execution::New(function, argc, args, &has_pending_exception);
2249 EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
2250 return scope.Close(Utils::ToLocal(i::Handle<i::JSObject>::cast(returned)));
2251}
2252
2253
2254Local<v8::Value> Function::Call(v8::Handle<v8::Object> recv, int argc,
2255 v8::Handle<v8::Value> argv[]) {
2256 ON_BAILOUT("v8::Function::Call()", return Local<v8::Value>());
2257 LOG_API("Function::Call");
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00002258 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002259 i::Object* raw_result = NULL;
2260 {
2261 HandleScope scope;
2262 i::Handle<i::JSFunction> fun = Utils::OpenHandle(this);
2263 i::Handle<i::Object> recv_obj = Utils::OpenHandle(*recv);
2264 STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
2265 i::Object*** args = reinterpret_cast<i::Object***>(argv);
2266 EXCEPTION_PREAMBLE();
2267 i::Handle<i::Object> returned =
2268 i::Execution::Call(fun, recv_obj, argc, args, &has_pending_exception);
2269 EXCEPTION_BAILOUT_CHECK(Local<Object>());
2270 raw_result = *returned;
2271 }
2272 i::Handle<i::Object> result(raw_result);
2273 return Utils::ToLocal(result);
2274}
2275
2276
2277void Function::SetName(v8::Handle<v8::String> name) {
ager@chromium.org71daaf62009-04-01 07:22:49 +00002278 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002279 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2280 func->shared()->set_name(*Utils::OpenHandle(*name));
2281}
2282
2283
ager@chromium.org32912102009-01-16 10:38:43 +00002284Handle<Value> Function::GetName() const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002285 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2286 return Utils::ToLocal(i::Handle<i::Object>(func->shared()->name()));
2287}
2288
2289
ager@chromium.org32912102009-01-16 10:38:43 +00002290int String::Length() const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002291 if (IsDeadCheck("v8::String::Length()")) return 0;
2292 return Utils::OpenHandle(this)->length();
2293}
2294
2295
ager@chromium.org32912102009-01-16 10:38:43 +00002296int String::Utf8Length() const {
ager@chromium.org9258b6b2008-09-11 09:11:10 +00002297 if (IsDeadCheck("v8::String::Utf8Length()")) return 0;
2298 return Utils::OpenHandle(this)->Utf8Length();
2299}
2300
2301
ager@chromium.org32912102009-01-16 10:38:43 +00002302int String::WriteUtf8(char* buffer, int capacity) const {
ager@chromium.org9258b6b2008-09-11 09:11:10 +00002303 if (IsDeadCheck("v8::String::WriteUtf8()")) return 0;
2304 LOG_API("String::WriteUtf8");
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00002305 ENTER_V8;
ager@chromium.org9258b6b2008-09-11 09:11:10 +00002306 i::Handle<i::String> str = Utils::OpenHandle(this);
2307 write_input_buffer.Reset(0, *str);
2308 int len = str->length();
2309 // Encode the first K - 3 bytes directly into the buffer since we
2310 // know there's room for them. If no capacity is given we copy all
2311 // of them here.
2312 int fast_end = capacity - (unibrow::Utf8::kMaxEncodedSize - 1);
2313 int i;
2314 int pos = 0;
2315 for (i = 0; i < len && (capacity == -1 || pos < fast_end); i++) {
2316 i::uc32 c = write_input_buffer.GetNext();
2317 int written = unibrow::Utf8::Encode(buffer + pos, c);
2318 pos += written;
2319 }
2320 if (i < len) {
2321 // For the last characters we need to check the length for each one
2322 // because they may be longer than the remaining space in the
2323 // buffer.
2324 char intermediate[unibrow::Utf8::kMaxEncodedSize];
2325 for (; i < len && pos < capacity; i++) {
2326 i::uc32 c = write_input_buffer.GetNext();
2327 int written = unibrow::Utf8::Encode(intermediate, c);
2328 if (pos + written <= capacity) {
2329 for (int j = 0; j < written; j++)
2330 buffer[pos + j] = intermediate[j];
2331 pos += written;
2332 } else {
2333 // We've reached the end of the buffer
2334 break;
2335 }
2336 }
2337 }
2338 if (i == len && (capacity == -1 || pos < capacity))
2339 buffer[pos++] = '\0';
2340 return pos;
2341}
2342
2343
ager@chromium.org32912102009-01-16 10:38:43 +00002344int String::WriteAscii(char* buffer, int start, int length) const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002345 if (IsDeadCheck("v8::String::WriteAscii()")) return 0;
2346 LOG_API("String::WriteAscii");
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00002347 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002348 ASSERT(start >= 0 && length >= -1);
2349 i::Handle<i::String> str = Utils::OpenHandle(this);
2350 // Flatten the string for efficiency. This applies whether we are
2351 // using StringInputBuffer or Get(i) to access the characters.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002352 str->TryFlattenIfNotFlat();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002353 int end = length;
2354 if ( (length == -1) || (length > str->length() - start) )
2355 end = str->length() - start;
2356 if (end < 0) return 0;
2357 write_input_buffer.Reset(start, *str);
2358 int i;
2359 for (i = 0; i < end; i++) {
2360 char c = static_cast<char>(write_input_buffer.GetNext());
2361 if (c == '\0') c = ' ';
2362 buffer[i] = c;
2363 }
2364 if (length == -1 || i < length)
2365 buffer[i] = '\0';
2366 return i;
2367}
2368
2369
ager@chromium.org32912102009-01-16 10:38:43 +00002370int String::Write(uint16_t* buffer, int start, int length) const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002371 if (IsDeadCheck("v8::String::Write()")) return 0;
2372 LOG_API("String::Write");
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00002373 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002374 ASSERT(start >= 0 && length >= -1);
2375 i::Handle<i::String> str = Utils::OpenHandle(this);
2376 // Flatten the string for efficiency. This applies whether we are
2377 // using StringInputBuffer or Get(i) to access the characters.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002378 str->TryFlattenIfNotFlat();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002379 int end = length;
2380 if ( (length == -1) || (length > str->length() - start) )
2381 end = str->length() - start;
2382 if (end < 0) return 0;
2383 write_input_buffer.Reset(start, *str);
2384 int i;
2385 for (i = 0; i < end; i++)
2386 buffer[i] = write_input_buffer.GetNext();
2387 if (length == -1 || i < length)
2388 buffer[i] = '\0';
2389 return i;
2390}
2391
2392
ager@chromium.org32912102009-01-16 10:38:43 +00002393bool v8::String::IsExternal() const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002394 EnsureInitialized("v8::String::IsExternal()");
2395 i::Handle<i::String> str = Utils::OpenHandle(this);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002396 return i::StringShape(*str).IsExternalTwoByte();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002397}
2398
2399
ager@chromium.org32912102009-01-16 10:38:43 +00002400bool v8::String::IsExternalAscii() const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002401 EnsureInitialized("v8::String::IsExternalAscii()");
2402 i::Handle<i::String> str = Utils::OpenHandle(this);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002403 return i::StringShape(*str).IsExternalAscii();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002404}
2405
2406
ager@chromium.org32912102009-01-16 10:38:43 +00002407v8::String::ExternalStringResource*
2408v8::String::GetExternalStringResource() const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002409 EnsureInitialized("v8::String::GetExternalStringResource()");
2410 i::Handle<i::String> str = Utils::OpenHandle(this);
ager@chromium.org9085a012009-05-11 19:22:57 +00002411 if (i::StringShape(*str).IsExternalTwoByte()) {
2412 void* resource = i::Handle<i::ExternalTwoByteString>::cast(str)->resource();
2413 return reinterpret_cast<ExternalStringResource*>(resource);
2414 } else {
2415 return NULL;
2416 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002417}
2418
2419
2420v8::String::ExternalAsciiStringResource*
ager@chromium.org32912102009-01-16 10:38:43 +00002421 v8::String::GetExternalAsciiStringResource() const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002422 EnsureInitialized("v8::String::GetExternalAsciiStringResource()");
2423 i::Handle<i::String> str = Utils::OpenHandle(this);
ager@chromium.org9085a012009-05-11 19:22:57 +00002424 if (i::StringShape(*str).IsExternalAscii()) {
2425 void* resource = i::Handle<i::ExternalAsciiString>::cast(str)->resource();
2426 return reinterpret_cast<ExternalAsciiStringResource*>(resource);
2427 } else {
2428 return NULL;
2429 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002430}
2431
2432
ager@chromium.org32912102009-01-16 10:38:43 +00002433double Number::Value() const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002434 if (IsDeadCheck("v8::Number::Value()")) return 0;
2435 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2436 return obj->Number();
2437}
2438
2439
ager@chromium.org32912102009-01-16 10:38:43 +00002440bool Boolean::Value() const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002441 if (IsDeadCheck("v8::Boolean::Value()")) return false;
2442 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2443 return obj->IsTrue();
2444}
2445
2446
ager@chromium.org32912102009-01-16 10:38:43 +00002447int64_t Integer::Value() const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002448 if (IsDeadCheck("v8::Integer::Value()")) return 0;
2449 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2450 if (obj->IsSmi()) {
2451 return i::Smi::cast(*obj)->value();
2452 } else {
2453 return static_cast<int64_t>(obj->Number());
2454 }
2455}
2456
2457
ager@chromium.org32912102009-01-16 10:38:43 +00002458int32_t Int32::Value() const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002459 if (IsDeadCheck("v8::Int32::Value()")) return 0;
2460 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2461 if (obj->IsSmi()) {
2462 return i::Smi::cast(*obj)->value();
2463 } else {
2464 return static_cast<int32_t>(obj->Number());
2465 }
2466}
2467
2468
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002469int v8::Object::InternalFieldCount() {
2470 if (IsDeadCheck("v8::Object::InternalFieldCount()")) return 0;
2471 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
2472 return obj->GetInternalFieldCount();
2473}
2474
2475
kasper.lund212ac232008-07-16 07:07:30 +00002476Local<Value> v8::Object::GetInternalField(int index) {
2477 if (IsDeadCheck("v8::Object::GetInternalField()")) return Local<Value>();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002478 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
kasper.lundbd3ec4e2008-07-09 11:06:54 +00002479 if (!ApiCheck(index < obj->GetInternalFieldCount(),
kasper.lund212ac232008-07-16 07:07:30 +00002480 "v8::Object::GetInternalField()",
kasper.lundbd3ec4e2008-07-09 11:06:54 +00002481 "Reading internal field out of bounds")) {
2482 return Local<Value>();
2483 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002484 i::Handle<i::Object> value(obj->GetInternalField(index));
2485 return Utils::ToLocal(value);
2486}
2487
2488
kasper.lund212ac232008-07-16 07:07:30 +00002489void v8::Object::SetInternalField(int index, v8::Handle<Value> value) {
2490 if (IsDeadCheck("v8::Object::SetInternalField()")) return;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002491 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
kasper.lundbd3ec4e2008-07-09 11:06:54 +00002492 if (!ApiCheck(index < obj->GetInternalFieldCount(),
kasper.lund212ac232008-07-16 07:07:30 +00002493 "v8::Object::SetInternalField()",
kasper.lundbd3ec4e2008-07-09 11:06:54 +00002494 "Writing internal field out of bounds")) {
2495 return;
2496 }
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00002497 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002498 i::Handle<i::Object> val = Utils::OpenHandle(*value);
2499 obj->SetInternalField(index, *val);
2500}
2501
2502
kasperl@chromium.orge959c182009-07-27 08:59:04 +00002503void* v8::Object::GetPointerFromInternalField(int index) {
2504 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
2505 i::Object* pointer = obj->GetInternalField(index);
2506 if (pointer->IsSmi()) {
2507 // Fast case, aligned native pointer.
2508 return pointer;
2509 }
2510
2511 // Read from uninitialized field.
2512 if (!pointer->IsProxy()) {
2513 // Play safe even if it's something unexpected.
2514 ASSERT(pointer->IsUndefined());
2515 return NULL;
2516 }
2517
2518 // Unaligned native pointer.
2519 return reinterpret_cast<void*>(i::Proxy::cast(pointer)->proxy());
2520}
2521
2522
2523void v8::Object::SetPointerInInternalField(int index, void* value) {
2524 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
2525 i::Object* as_object = reinterpret_cast<i::Object*>(value);
2526 if (as_object->IsSmi()) {
2527 // Aligned pointer, store as is.
2528 obj->SetInternalField(index, as_object);
2529 } else {
2530 // Currently internal fields are used by DOM wrappers which only
2531 // get garbage collected by the mark-sweep collector, so we
2532 // pretenure the proxy.
2533 HandleScope scope;
2534 i::Handle<i::Proxy> proxy =
2535 i::Factory::NewProxy(reinterpret_cast<i::Address>(value), i::TENURED);
2536 if (!proxy.is_null()) obj->SetInternalField(index, *proxy);
2537 }
2538}
2539
2540
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002541// --- E n v i r o n m e n t ---
2542
2543bool v8::V8::Initialize() {
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002544 if (i::V8::IsRunning()) return true;
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00002545 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002546 HandleScope scope;
2547 if (i::Snapshot::Initialize()) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002548 return true;
2549 } else {
2550 return i::V8::Initialize(NULL);
2551 }
2552}
2553
2554
ager@chromium.org41826e72009-03-30 13:30:57 +00002555bool v8::V8::Dispose() {
2556 i::V8::TearDown();
2557 return true;
2558}
2559
2560
ager@chromium.orgadd848f2009-08-13 12:44:13 +00002561void v8::V8::IdleNotification(bool is_high_priority) {
2562 i::V8::IdleNotification(is_high_priority);
2563}
2564
kasper.lund7276f142008-07-30 08:49:36 +00002565const char* v8::V8::GetVersion() {
ager@chromium.org5ec48922009-05-05 07:25:34 +00002566 static v8::internal::EmbeddedVector<char, 128> buffer;
2567 v8::internal::Version::GetString(buffer);
2568 return buffer.start();
kasper.lund7276f142008-07-30 08:49:36 +00002569}
2570
2571
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002572static i::Handle<i::FunctionTemplateInfo>
2573 EnsureConstructor(i::Handle<i::ObjectTemplateInfo> templ) {
2574 if (templ->constructor()->IsUndefined()) {
2575 Local<FunctionTemplate> constructor = FunctionTemplate::New();
2576 Utils::OpenHandle(*constructor)->set_instance_template(*templ);
2577 templ->set_constructor(*Utils::OpenHandle(*constructor));
2578 }
2579 return i::Handle<i::FunctionTemplateInfo>(
2580 i::FunctionTemplateInfo::cast(templ->constructor()));
2581}
2582
2583
2584Persistent<Context> v8::Context::New(
2585 v8::ExtensionConfiguration* extensions,
2586 v8::Handle<ObjectTemplate> global_template,
2587 v8::Handle<Value> global_object) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002588 EnsureInitialized("v8::Context::New()");
2589 LOG_API("Context::New");
2590 ON_BAILOUT("v8::Context::New()", return Persistent<Context>());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002591
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00002592 // Enter V8 via an ENTER_V8 scope.
2593 i::Handle<i::Context> env;
2594 {
2595 ENTER_V8;
2596 // Give the heap a chance to cleanup if we've disposed contexts.
2597 i::Heap::CollectAllGarbageIfContextDisposed();
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00002598 v8::Handle<ObjectTemplate> proxy_template = global_template;
2599 i::Handle<i::FunctionTemplateInfo> proxy_constructor;
2600 i::Handle<i::FunctionTemplateInfo> global_constructor;
ager@chromium.org8bb60582008-12-11 12:02:20 +00002601
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00002602 if (!global_template.IsEmpty()) {
2603 // Make sure that the global_template has a constructor.
2604 global_constructor =
2605 EnsureConstructor(Utils::OpenHandle(*global_template));
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002606
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00002607 // Create a fresh template for the global proxy object.
2608 proxy_template = ObjectTemplate::New();
2609 proxy_constructor =
2610 EnsureConstructor(Utils::OpenHandle(*proxy_template));
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002611
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00002612 // Set the global template to be the prototype template of
2613 // global proxy template.
2614 proxy_constructor->set_prototype_template(
2615 *Utils::OpenHandle(*global_template));
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002616
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00002617 // Migrate security handlers from global_template to
2618 // proxy_template. Temporarily removing access check
2619 // information from the global template.
2620 if (!global_constructor->access_check_info()->IsUndefined()) {
2621 proxy_constructor->set_access_check_info(
2622 global_constructor->access_check_info());
2623 proxy_constructor->set_needs_access_check(
2624 global_constructor->needs_access_check());
2625 global_constructor->set_needs_access_check(false);
2626 global_constructor->set_access_check_info(i::Heap::undefined_value());
2627 }
2628 }
2629
2630 // Create the environment.
2631 env = i::Bootstrapper::CreateEnvironment(
2632 Utils::OpenHandle(*global_object),
2633 proxy_template,
2634 extensions);
2635
2636 // Restore the access check info on the global template.
2637 if (!global_template.IsEmpty()) {
2638 ASSERT(!global_constructor.is_null());
2639 ASSERT(!proxy_constructor.is_null());
2640 global_constructor->set_access_check_info(
2641 proxy_constructor->access_check_info());
2642 global_constructor->set_needs_access_check(
2643 proxy_constructor->needs_access_check());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002644 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002645 }
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00002646 // Leave V8.
ager@chromium.org8bb60582008-12-11 12:02:20 +00002647
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002648 if (!ApiCheck(!env.is_null(),
2649 "v8::Context::New()",
2650 "Could not initialize environment"))
2651 return Persistent<Context>();
2652 return Persistent<Context>(Utils::ToLocal(env));
2653}
2654
2655
2656void v8::Context::SetSecurityToken(Handle<Value> token) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002657 if (IsDeadCheck("v8::Context::SetSecurityToken()")) return;
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00002658 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002659 i::Handle<i::Context> env = Utils::OpenHandle(this);
2660 i::Handle<i::Object> token_handle = Utils::OpenHandle(*token);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002661 env->set_security_token(*token_handle);
2662}
2663
2664
2665void v8::Context::UseDefaultSecurityToken() {
2666 if (IsDeadCheck("v8::Context::UseDefaultSecurityToken()")) return;
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00002667 ENTER_V8;
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002668 i::Handle<i::Context> env = Utils::OpenHandle(this);
2669 env->set_security_token(env->global());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002670}
2671
2672
2673Handle<Value> v8::Context::GetSecurityToken() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002674 if (IsDeadCheck("v8::Context::GetSecurityToken()")) return Handle<Value>();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002675 i::Handle<i::Context> env = Utils::OpenHandle(this);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002676 i::Object* security_token = env->security_token();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002677 i::Handle<i::Object> token_handle(security_token);
2678 return Utils::ToLocal(token_handle);
2679}
2680
2681
2682bool Context::HasOutOfMemoryException() {
2683 i::Handle<i::Context> env = Utils::OpenHandle(this);
2684 return env->has_out_of_memory();
2685}
2686
2687
2688bool Context::InContext() {
2689 return i::Top::context() != NULL;
2690}
2691
2692
kasper.lund44510672008-07-25 07:37:58 +00002693v8::Local<v8::Context> Context::GetEntered() {
2694 if (IsDeadCheck("v8::Context::GetEntered()")) return Local<Context>();
2695 i::Handle<i::Object> last = thread_local.LastEnteredContext();
2696 if (last.is_null()) return Local<Context>();
2697 i::Handle<i::Context> context = i::Handle<i::Context>::cast(last);
2698 return Utils::ToLocal(context);
2699}
2700
2701
2702v8::Local<v8::Context> Context::GetCurrent() {
2703 if (IsDeadCheck("v8::Context::GetCurrent()")) return Local<Context>();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002704 i::Handle<i::Context> context(i::Top::global_context());
2705 return Utils::ToLocal(context);
2706}
2707
2708
ager@chromium.org1bf0cd02009-05-20 11:34:19 +00002709v8::Local<v8::Context> Context::GetCalling() {
2710 if (IsDeadCheck("v8::Context::GetCalling()")) return Local<Context>();
2711 i::Handle<i::Context> context(i::Top::GetCallingGlobalContext());
2712 return Utils::ToLocal(context);
2713}
2714
2715
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002716v8::Local<v8::Object> Context::Global() {
2717 if (IsDeadCheck("v8::Context::Global()")) return Local<v8::Object>();
2718 i::Object** ctx = reinterpret_cast<i::Object**>(this);
2719 i::Handle<i::Context> context =
2720 i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx));
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002721 i::Handle<i::Object> global(context->global_proxy());
2722 return Utils::ToLocal(i::Handle<i::JSObject>::cast(global));
2723}
2724
2725
2726void Context::DetachGlobal() {
2727 if (IsDeadCheck("v8::Context::DetachGlobal()")) return;
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00002728 ENTER_V8;
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002729 i::Object** ctx = reinterpret_cast<i::Object**>(this);
2730 i::Handle<i::Context> context =
2731 i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx));
2732 i::Bootstrapper::DetachGlobal(context);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002733}
2734
2735
2736Local<v8::Object> ObjectTemplate::NewInstance() {
2737 ON_BAILOUT("v8::ObjectTemplate::NewInstance()", return Local<v8::Object>());
2738 LOG_API("ObjectTemplate::NewInstance");
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00002739 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002740 EXCEPTION_PREAMBLE();
2741 i::Handle<i::Object> obj =
2742 i::Execution::InstantiateObject(Utils::OpenHandle(this),
2743 &has_pending_exception);
2744 EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
2745 return Utils::ToLocal(i::Handle<i::JSObject>::cast(obj));
2746}
2747
2748
2749Local<v8::Function> FunctionTemplate::GetFunction() {
2750 ON_BAILOUT("v8::FunctionTemplate::GetFunction()",
2751 return Local<v8::Function>());
2752 LOG_API("FunctionTemplate::GetFunction");
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00002753 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002754 EXCEPTION_PREAMBLE();
2755 i::Handle<i::Object> obj =
2756 i::Execution::InstantiateFunction(Utils::OpenHandle(this),
2757 &has_pending_exception);
2758 EXCEPTION_BAILOUT_CHECK(Local<v8::Function>());
2759 return Utils::ToLocal(i::Handle<i::JSFunction>::cast(obj));
2760}
2761
2762
2763bool FunctionTemplate::HasInstance(v8::Handle<v8::Value> value) {
2764 ON_BAILOUT("v8::FunctionTemplate::HasInstanceOf()", return false);
2765 i::Object* obj = *Utils::OpenHandle(*value);
2766 return obj->IsInstanceOf(*Utils::OpenHandle(this));
2767}
2768
2769
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002770static Local<External> ExternalNewImpl(void* data) {
2771 return Utils::ToLocal(i::Factory::NewProxy(static_cast<i::Address>(data)));
2772}
2773
2774static void* ExternalValueImpl(i::Handle<i::Object> obj) {
2775 return reinterpret_cast<void*>(i::Proxy::cast(*obj)->proxy());
2776}
2777
2778
2779static const intptr_t kAlignedPointerMask = 3;
2780static const int kAlignedPointerShift = 2;
2781
2782
2783Local<Value> v8::External::Wrap(void* data) {
2784 STATIC_ASSERT(sizeof(data) == sizeof(i::Address));
2785 LOG_API("External::Wrap");
2786 EnsureInitialized("v8::External::Wrap()");
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00002787 ENTER_V8;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002788 if ((reinterpret_cast<intptr_t>(data) & kAlignedPointerMask) == 0) {
2789 uintptr_t data_ptr = reinterpret_cast<uintptr_t>(data);
ager@chromium.org9085a012009-05-11 19:22:57 +00002790 intptr_t data_value =
2791 static_cast<intptr_t>(data_ptr >> kAlignedPointerShift);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002792 STATIC_ASSERT(sizeof(data_ptr) == sizeof(data_value));
ager@chromium.org9085a012009-05-11 19:22:57 +00002793 if (i::Smi::IsIntptrValid(data_value)) {
2794 i::Handle<i::Object> obj(i::Smi::FromIntptr(data_value));
2795 return Utils::ToLocal(obj);
2796 }
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002797 }
2798 return ExternalNewImpl(data);
2799}
2800
2801
2802void* v8::External::Unwrap(v8::Handle<v8::Value> value) {
2803 if (IsDeadCheck("v8::External::Unwrap()")) return 0;
2804 i::Handle<i::Object> obj = Utils::OpenHandle(*value);
2805 if (obj->IsSmi()) {
2806 // The external value was an aligned pointer.
ager@chromium.org9085a012009-05-11 19:22:57 +00002807 uintptr_t result = static_cast<uintptr_t>(
2808 i::Smi::cast(*obj)->value()) << kAlignedPointerShift;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002809 return reinterpret_cast<void*>(result);
2810 }
2811 return ExternalValueImpl(obj);
2812}
2813
2814
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002815Local<External> v8::External::New(void* data) {
2816 STATIC_ASSERT(sizeof(data) == sizeof(i::Address));
2817 LOG_API("External::New");
2818 EnsureInitialized("v8::External::New()");
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00002819 ENTER_V8;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002820 return ExternalNewImpl(data);
2821}
2822
2823
2824void* External::Value() const {
2825 if (IsDeadCheck("v8::External::Value()")) return 0;
2826 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2827 return ExternalValueImpl(obj);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002828}
2829
2830
ager@chromium.org563b8dc2009-03-20 14:23:52 +00002831Local<String> v8::String::Empty() {
2832 EnsureInitialized("v8::String::Empty()");
2833 LOG_API("String::Empty()");
2834 return Utils::ToLocal(i::Factory::empty_symbol());
2835}
2836
2837
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002838Local<String> v8::String::New(const char* data, int length) {
2839 EnsureInitialized("v8::String::New()");
2840 LOG_API("String::New(char)");
ager@chromium.org563b8dc2009-03-20 14:23:52 +00002841 if (length == 0) return Empty();
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00002842 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002843 if (length == -1) length = strlen(data);
2844 i::Handle<i::String> result =
2845 i::Factory::NewStringFromUtf8(i::Vector<const char>(data, length));
2846 return Utils::ToLocal(result);
2847}
2848
2849
2850Local<String> v8::String::NewUndetectable(const char* data, int length) {
2851 EnsureInitialized("v8::String::NewUndetectable()");
2852 LOG_API("String::NewUndetectable(char)");
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00002853 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002854 if (length == -1) length = strlen(data);
2855 i::Handle<i::String> result =
2856 i::Factory::NewStringFromUtf8(i::Vector<const char>(data, length));
2857 result->MarkAsUndetectable();
2858 return Utils::ToLocal(result);
2859}
2860
2861
2862static int TwoByteStringLength(const uint16_t* data) {
2863 int length = 0;
2864 while (data[length] != '\0') length++;
2865 return length;
2866}
2867
2868
2869Local<String> v8::String::New(const uint16_t* data, int length) {
2870 EnsureInitialized("v8::String::New()");
2871 LOG_API("String::New(uint16_)");
ager@chromium.org563b8dc2009-03-20 14:23:52 +00002872 if (length == 0) return Empty();
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00002873 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002874 if (length == -1) length = TwoByteStringLength(data);
2875 i::Handle<i::String> result =
2876 i::Factory::NewStringFromTwoByte(i::Vector<const uint16_t>(data, length));
2877 return Utils::ToLocal(result);
2878}
2879
2880
2881Local<String> v8::String::NewUndetectable(const uint16_t* data, int length) {
2882 EnsureInitialized("v8::String::NewUndetectable()");
2883 LOG_API("String::NewUndetectable(uint16_)");
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00002884 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002885 if (length == -1) length = TwoByteStringLength(data);
2886 i::Handle<i::String> result =
2887 i::Factory::NewStringFromTwoByte(i::Vector<const uint16_t>(data, length));
2888 result->MarkAsUndetectable();
2889 return Utils::ToLocal(result);
2890}
2891
2892
2893i::Handle<i::String> NewExternalStringHandle(
2894 v8::String::ExternalStringResource* resource) {
2895 i::Handle<i::String> result =
2896 i::Factory::NewExternalStringFromTwoByte(resource);
2897 return result;
2898}
2899
2900
2901i::Handle<i::String> NewExternalAsciiStringHandle(
2902 v8::String::ExternalAsciiStringResource* resource) {
2903 i::Handle<i::String> result =
2904 i::Factory::NewExternalStringFromAscii(resource);
2905 return result;
2906}
2907
2908
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002909static void DisposeExternalString(v8::Persistent<v8::Value> obj,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002910 void* parameter) {
ager@chromium.org71daaf62009-04-01 07:22:49 +00002911 ENTER_V8;
ager@chromium.org6f10e412009-02-13 10:11:16 +00002912 i::ExternalTwoByteString* str =
2913 i::ExternalTwoByteString::cast(*Utils::OpenHandle(*obj));
2914
2915 // External symbols are deleted when they are pruned out of the symbol
2916 // table. Generally external symbols are not registered with the weak handle
2917 // callbacks unless they are upgraded to a symbol after being externalized.
2918 if (!str->IsSymbol()) {
2919 v8::String::ExternalStringResource* resource =
2920 reinterpret_cast<v8::String::ExternalStringResource*>(parameter);
2921 if (resource != NULL) {
2922 const size_t total_size = resource->length() * sizeof(*resource->data());
2923 i::Counters::total_external_string_memory.Decrement(total_size);
2924
2925 // The object will continue to live in the JavaScript heap until the
2926 // handle is entirely cleaned out by the next GC. For example the
2927 // destructor for the resource below could bring it back to life again.
2928 // Which is why we make sure to not have a dangling pointer here.
2929 str->set_resource(NULL);
2930 delete resource;
2931 }
2932 }
2933
2934 // In any case we do not need this handle any longer.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002935 obj.Dispose();
2936}
2937
2938
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002939static void DisposeExternalAsciiString(v8::Persistent<v8::Value> obj,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002940 void* parameter) {
ager@chromium.org71daaf62009-04-01 07:22:49 +00002941 ENTER_V8;
ager@chromium.org6f10e412009-02-13 10:11:16 +00002942 i::ExternalAsciiString* str =
2943 i::ExternalAsciiString::cast(*Utils::OpenHandle(*obj));
2944
2945 // External symbols are deleted when they are pruned out of the symbol
2946 // table. Generally external symbols are not registered with the weak handle
2947 // callbacks unless they are upgraded to a symbol after being externalized.
2948 if (!str->IsSymbol()) {
2949 v8::String::ExternalAsciiStringResource* resource =
2950 reinterpret_cast<v8::String::ExternalAsciiStringResource*>(parameter);
2951 if (resource != NULL) {
2952 const size_t total_size = resource->length() * sizeof(*resource->data());
2953 i::Counters::total_external_string_memory.Decrement(total_size);
2954
2955 // The object will continue to live in the JavaScript heap until the
2956 // handle is entirely cleaned out by the next GC. For example the
2957 // destructor for the resource below could bring it back to life again.
2958 // Which is why we make sure to not have a dangling pointer here.
2959 str->set_resource(NULL);
2960 delete resource;
2961 }
2962 }
2963
2964 // In any case we do not need this handle any longer.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002965 obj.Dispose();
2966}
2967
2968
2969Local<String> v8::String::NewExternal(
2970 v8::String::ExternalStringResource* resource) {
2971 EnsureInitialized("v8::String::NewExternal()");
2972 LOG_API("String::NewExternal");
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00002973 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002974 const size_t total_size = resource->length() * sizeof(*resource->data());
2975 i::Counters::total_external_string_memory.Increment(total_size);
2976 i::Handle<i::String> result = NewExternalStringHandle(resource);
2977 i::Handle<i::Object> handle = i::GlobalHandles::Create(*result);
2978 i::GlobalHandles::MakeWeak(handle.location(),
2979 resource,
2980 &DisposeExternalString);
2981 return Utils::ToLocal(result);
2982}
2983
2984
ager@chromium.org6f10e412009-02-13 10:11:16 +00002985bool v8::String::MakeExternal(v8::String::ExternalStringResource* resource) {
2986 if (IsDeadCheck("v8::String::MakeExternal()")) return false;
2987 if (this->IsExternal()) return false; // Already an external string.
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00002988 ENTER_V8;
christian.plesner.hansen@gmail.com5a6af922009-08-12 14:20:51 +00002989 i::Handle<i::String> obj = Utils::OpenHandle(this);
ager@chromium.org6f10e412009-02-13 10:11:16 +00002990 bool result = obj->MakeExternal(resource);
2991 if (result && !obj->IsSymbol()) {
2992 // Operation was successful and the string is not a symbol. In this case
2993 // we need to make sure that the we call the destructor for the external
2994 // resource when no strong references to the string remain.
2995 i::Handle<i::Object> handle = i::GlobalHandles::Create(*obj);
2996 i::GlobalHandles::MakeWeak(handle.location(),
2997 resource,
2998 &DisposeExternalString);
2999 }
3000 return result;
3001}
3002
3003
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003004Local<String> v8::String::NewExternal(
3005 v8::String::ExternalAsciiStringResource* resource) {
3006 EnsureInitialized("v8::String::NewExternal()");
3007 LOG_API("String::NewExternal");
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00003008 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003009 const size_t total_size = resource->length() * sizeof(*resource->data());
3010 i::Counters::total_external_string_memory.Increment(total_size);
3011 i::Handle<i::String> result = NewExternalAsciiStringHandle(resource);
3012 i::Handle<i::Object> handle = i::GlobalHandles::Create(*result);
3013 i::GlobalHandles::MakeWeak(handle.location(),
3014 resource,
3015 &DisposeExternalAsciiString);
3016 return Utils::ToLocal(result);
3017}
3018
3019
ager@chromium.org6f10e412009-02-13 10:11:16 +00003020bool v8::String::MakeExternal(
3021 v8::String::ExternalAsciiStringResource* resource) {
3022 if (IsDeadCheck("v8::String::MakeExternal()")) return false;
3023 if (this->IsExternal()) return false; // Already an external string.
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00003024 ENTER_V8;
christian.plesner.hansen@gmail.com5a6af922009-08-12 14:20:51 +00003025 i::Handle<i::String> obj = Utils::OpenHandle(this);
ager@chromium.org6f10e412009-02-13 10:11:16 +00003026 bool result = obj->MakeExternal(resource);
3027 if (result && !obj->IsSymbol()) {
3028 // Operation was successful and the string is not a symbol. In this case
3029 // we need to make sure that the we call the destructor for the external
3030 // resource when no strong references to the string remain.
3031 i::Handle<i::Object> handle = i::GlobalHandles::Create(*obj);
3032 i::GlobalHandles::MakeWeak(handle.location(),
3033 resource,
3034 &DisposeExternalAsciiString);
3035 }
3036 return result;
3037}
3038
3039
christian.plesner.hansen@gmail.com5a6af922009-08-12 14:20:51 +00003040bool v8::String::CanMakeExternal() {
3041 if (IsDeadCheck("v8::String::CanMakeExternal()")) return false;
3042 i::Handle<i::String> obj = Utils::OpenHandle(this);
3043 int size = obj->Size(); // Byte size of the original string.
3044 if (size < i::ExternalString::kSize)
3045 return false;
3046 i::StringShape shape(*obj);
3047 return !shape.IsExternal();
3048}
3049
3050
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003051Local<v8::Object> v8::Object::New() {
3052 EnsureInitialized("v8::Object::New()");
3053 LOG_API("Object::New");
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00003054 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003055 i::Handle<i::JSObject> obj =
3056 i::Factory::NewJSObject(i::Top::object_function());
3057 return Utils::ToLocal(obj);
3058}
3059
3060
3061Local<v8::Value> v8::Date::New(double time) {
3062 EnsureInitialized("v8::Date::New()");
3063 LOG_API("Date::New");
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00003064 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003065 EXCEPTION_PREAMBLE();
3066 i::Handle<i::Object> obj =
3067 i::Execution::NewDate(time, &has_pending_exception);
3068 EXCEPTION_BAILOUT_CHECK(Local<v8::Value>());
3069 return Utils::ToLocal(obj);
3070}
3071
3072
ager@chromium.org32912102009-01-16 10:38:43 +00003073double v8::Date::NumberValue() const {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003074 if (IsDeadCheck("v8::Date::NumberValue()")) return 0;
3075 LOG_API("Date::NumberValue");
3076 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3077 i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
3078 return jsvalue->value()->Number();
3079}
3080
3081
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003082Local<v8::Array> v8::Array::New(int length) {
3083 EnsureInitialized("v8::Array::New()");
3084 LOG_API("Array::New");
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00003085 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003086 i::Handle<i::JSArray> obj = i::Factory::NewJSArray(length);
3087 return Utils::ToLocal(obj);
3088}
3089
3090
ager@chromium.org32912102009-01-16 10:38:43 +00003091uint32_t v8::Array::Length() const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003092 if (IsDeadCheck("v8::Array::Length()")) return 0;
3093 i::Handle<i::JSArray> obj = Utils::OpenHandle(this);
3094 i::Object* length = obj->length();
3095 if (length->IsSmi()) {
3096 return i::Smi::cast(length)->value();
3097 } else {
3098 return static_cast<uint32_t>(length->Number());
3099 }
3100}
3101
3102
ager@chromium.org3e875802009-06-29 08:26:34 +00003103Local<Object> Array::CloneElementAt(uint32_t index) {
3104 ON_BAILOUT("v8::Array::CloneElementAt()", return Local<Object>());
3105 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3106 if (!self->HasFastElements()) {
3107 return Local<Object>();
3108 }
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00003109 i::FixedArray* elms = i::FixedArray::cast(self->elements());
ager@chromium.org3e875802009-06-29 08:26:34 +00003110 i::Object* paragon = elms->get(index);
3111 if (!paragon->IsJSObject()) {
3112 return Local<Object>();
3113 }
3114 i::Handle<i::JSObject> paragon_handle(i::JSObject::cast(paragon));
3115 EXCEPTION_PREAMBLE();
3116 i::Handle<i::JSObject> result = i::Copy(paragon_handle);
3117 has_pending_exception = result.is_null();
3118 EXCEPTION_BAILOUT_CHECK(Local<Object>());
3119 return Utils::ToLocal(result);
3120}
3121
3122
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003123Local<String> v8::String::NewSymbol(const char* data, int length) {
3124 EnsureInitialized("v8::String::NewSymbol()");
3125 LOG_API("String::NewSymbol(char)");
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00003126 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003127 if (length == -1) length = strlen(data);
3128 i::Handle<i::String> result =
3129 i::Factory::LookupSymbol(i::Vector<const char>(data, length));
3130 return Utils::ToLocal(result);
3131}
3132
3133
3134Local<Number> v8::Number::New(double value) {
3135 EnsureInitialized("v8::Number::New()");
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00003136 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003137 i::Handle<i::Object> result = i::Factory::NewNumber(value);
3138 return Utils::NumberToLocal(result);
3139}
3140
3141
3142Local<Integer> v8::Integer::New(int32_t value) {
3143 EnsureInitialized("v8::Integer::New()");
3144 if (i::Smi::IsValid(value)) {
3145 return Utils::IntegerToLocal(i::Handle<i::Object>(i::Smi::FromInt(value)));
3146 }
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00003147 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003148 i::Handle<i::Object> result = i::Factory::NewNumber(value);
3149 return Utils::IntegerToLocal(result);
3150}
3151
3152
3153void V8::IgnoreOutOfMemoryException() {
3154 thread_local.SetIgnoreOutOfMemory(true);
3155}
3156
3157
3158bool V8::AddMessageListener(MessageCallback that, Handle<Value> data) {
3159 EnsureInitialized("v8::V8::AddMessageListener()");
3160 ON_BAILOUT("v8::V8::AddMessageListener()", return false);
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00003161 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003162 HandleScope scope;
3163 NeanderArray listeners(i::Factory::message_listeners());
3164 NeanderObject obj(2);
3165 obj.set(0, *i::Factory::NewProxy(FUNCTION_ADDR(that)));
3166 obj.set(1, data.IsEmpty() ?
3167 i::Heap::undefined_value() :
3168 *Utils::OpenHandle(*data));
3169 listeners.add(obj.value());
3170 return true;
3171}
3172
3173
3174void V8::RemoveMessageListeners(MessageCallback that) {
3175 EnsureInitialized("v8::V8::RemoveMessageListener()");
3176 ON_BAILOUT("v8::V8::RemoveMessageListeners()", return);
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00003177 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003178 HandleScope scope;
3179 NeanderArray listeners(i::Factory::message_listeners());
3180 for (int i = 0; i < listeners.length(); i++) {
3181 if (listeners.get(i)->IsUndefined()) continue; // skip deleted ones
3182
3183 NeanderObject listener(i::JSObject::cast(listeners.get(i)));
3184 i::Handle<i::Proxy> callback_obj(i::Proxy::cast(listener.get(0)));
3185 if (callback_obj->proxy() == FUNCTION_ADDR(that)) {
3186 listeners.set(i, i::Heap::undefined_value());
3187 }
3188 }
3189}
3190
3191
3192void V8::SetCounterFunction(CounterLookupCallback callback) {
3193 if (IsDeadCheck("v8::V8::SetCounterFunction()")) return;
3194 i::StatsTable::SetCounterFunction(callback);
3195}
3196
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00003197void V8::SetCreateHistogramFunction(CreateHistogramCallback callback) {
3198 if (IsDeadCheck("v8::V8::SetCreateHistogramFunction()")) return;
3199 i::StatsTable::SetCreateHistogramFunction(callback);
3200}
3201
3202void V8::SetAddHistogramSampleFunction(AddHistogramSampleCallback callback) {
3203 if (IsDeadCheck("v8::V8::SetAddHistogramSampleFunction()")) return;
3204 i::StatsTable::SetAddHistogramSampleFunction(callback);
3205}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003206
3207void V8::EnableSlidingStateWindow() {
3208 if (IsDeadCheck("v8::V8::EnableSlidingStateWindow()")) return;
3209 i::Logger::EnableSlidingStateWindow();
3210}
3211
3212
3213void V8::SetFailedAccessCheckCallbackFunction(
3214 FailedAccessCheckCallback callback) {
3215 if (IsDeadCheck("v8::V8::SetFailedAccessCheckCallbackFunction()")) return;
3216 i::Top::SetFailedAccessCheckCallback(callback);
3217}
3218
3219
ager@chromium.org8bb60582008-12-11 12:02:20 +00003220void V8::AddObjectGroup(Persistent<Value>* objects, size_t length) {
3221 if (IsDeadCheck("v8::V8::AddObjectGroup()")) return;
3222 STATIC_ASSERT(sizeof(Persistent<Value>) == sizeof(i::Object**));
3223 i::GlobalHandles::AddGroup(reinterpret_cast<i::Object***>(objects), length);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003224}
3225
3226
kasper.lund7276f142008-07-30 08:49:36 +00003227int V8::AdjustAmountOfExternalAllocatedMemory(int change_in_bytes) {
3228 if (IsDeadCheck("v8::V8::AdjustAmountOfExternalAllocatedMemory()")) return 0;
3229 return i::Heap::AdjustAmountOfExternalAllocatedMemory(change_in_bytes);
3230}
3231
3232
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003233void V8::SetGlobalGCPrologueCallback(GCCallback callback) {
3234 if (IsDeadCheck("v8::V8::SetGlobalGCPrologueCallback()")) return;
3235 i::Heap::SetGlobalGCPrologueCallback(callback);
3236}
3237
3238
3239void V8::SetGlobalGCEpilogueCallback(GCCallback callback) {
3240 if (IsDeadCheck("v8::V8::SetGlobalGCEpilogueCallback()")) return;
3241 i::Heap::SetGlobalGCEpilogueCallback(callback);
3242}
3243
3244
iposva@chromium.org245aa852009-02-10 00:49:54 +00003245void V8::PauseProfiler() {
3246#ifdef ENABLE_LOGGING_AND_PROFILING
sgjesse@chromium.orgb9d7da12009-08-05 08:38:10 +00003247 i::Logger::PauseProfiler(PROFILER_MODULE_CPU);
iposva@chromium.org245aa852009-02-10 00:49:54 +00003248#endif
3249}
3250
kasperl@chromium.org71affb52009-05-26 05:44:31 +00003251
iposva@chromium.org245aa852009-02-10 00:49:54 +00003252void V8::ResumeProfiler() {
3253#ifdef ENABLE_LOGGING_AND_PROFILING
sgjesse@chromium.orgb9d7da12009-08-05 08:38:10 +00003254 i::Logger::ResumeProfiler(PROFILER_MODULE_CPU);
iposva@chromium.org245aa852009-02-10 00:49:54 +00003255#endif
3256}
3257
kasperl@chromium.org71affb52009-05-26 05:44:31 +00003258
3259bool V8::IsProfilerPaused() {
3260#ifdef ENABLE_LOGGING_AND_PROFILING
sgjesse@chromium.orgb9d7da12009-08-05 08:38:10 +00003261 return i::Logger::GetActiveProfilerModules() & PROFILER_MODULE_CPU;
kasperl@chromium.org71affb52009-05-26 05:44:31 +00003262#else
3263 return true;
3264#endif
3265}
3266
3267
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00003268void V8::ResumeProfilerEx(int flags) {
3269#ifdef ENABLE_LOGGING_AND_PROFILING
sgjesse@chromium.orgb9d7da12009-08-05 08:38:10 +00003270 if (flags & PROFILER_MODULE_HEAP_SNAPSHOT) {
3271 // Snapshot mode: resume modules, perform GC, then pause only
3272 // those modules which haven't been started prior to making a
3273 // snapshot.
3274
3275 // Reset snapshot flag and CPU module flags.
3276 flags &= ~(PROFILER_MODULE_HEAP_SNAPSHOT | PROFILER_MODULE_CPU);
3277 const int current_flags = i::Logger::GetActiveProfilerModules();
3278 i::Logger::ResumeProfiler(flags);
3279 i::Heap::CollectAllGarbage();
3280 i::Logger::PauseProfiler(~current_flags & flags);
3281 } else {
3282 i::Logger::ResumeProfiler(flags);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00003283 }
3284#endif
3285}
3286
3287
3288void V8::PauseProfilerEx(int flags) {
3289#ifdef ENABLE_LOGGING_AND_PROFILING
sgjesse@chromium.orgb9d7da12009-08-05 08:38:10 +00003290 i::Logger::PauseProfiler(flags);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00003291#endif
3292}
3293
3294
3295int V8::GetActiveProfilerModules() {
3296#ifdef ENABLE_LOGGING_AND_PROFILING
sgjesse@chromium.orgb9d7da12009-08-05 08:38:10 +00003297 return i::Logger::GetActiveProfilerModules();
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00003298#else
3299 return PROFILER_MODULE_NONE;
3300#endif
3301}
3302
3303
ager@chromium.org9085a012009-05-11 19:22:57 +00003304int V8::GetLogLines(int from_pos, char* dest_buf, int max_size) {
3305#ifdef ENABLE_LOGGING_AND_PROFILING
3306 return i::Logger::GetLogLines(from_pos, dest_buf, max_size);
3307#endif
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00003308 return 0;
ager@chromium.org9085a012009-05-11 19:22:57 +00003309}
ager@chromium.orga74f0da2008-12-03 16:05:52 +00003310
ager@chromium.org9258b6b2008-09-11 09:11:10 +00003311String::Utf8Value::Utf8Value(v8::Handle<v8::Value> obj) {
3312 EnsureInitialized("v8::String::Utf8Value::Utf8Value()");
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003313 if (obj.IsEmpty()) {
3314 str_ = NULL;
3315 length_ = 0;
3316 return;
3317 }
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00003318 ENTER_V8;
ager@chromium.org9258b6b2008-09-11 09:11:10 +00003319 HandleScope scope;
3320 TryCatch try_catch;
3321 Handle<String> str = obj->ToString();
3322 if (str.IsEmpty()) {
3323 str_ = NULL;
3324 length_ = 0;
3325 } else {
3326 length_ = str->Utf8Length();
3327 str_ = i::NewArray<char>(length_ + 1);
3328 str->WriteUtf8(str_);
3329 }
3330}
3331
3332
3333String::Utf8Value::~Utf8Value() {
3334 i::DeleteArray(str_);
3335}
3336
3337
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003338String::AsciiValue::AsciiValue(v8::Handle<v8::Value> obj) {
3339 EnsureInitialized("v8::String::AsciiValue::AsciiValue()");
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003340 if (obj.IsEmpty()) {
3341 str_ = NULL;
3342 length_ = 0;
3343 return;
3344 }
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00003345 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003346 HandleScope scope;
ager@chromium.org9258b6b2008-09-11 09:11:10 +00003347 TryCatch try_catch;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003348 Handle<String> str = obj->ToString();
ager@chromium.org9258b6b2008-09-11 09:11:10 +00003349 if (str.IsEmpty()) {
3350 str_ = NULL;
3351 length_ = 0;
3352 } else {
3353 length_ = str->Length();
3354 str_ = i::NewArray<char>(length_ + 1);
3355 str->WriteAscii(str_);
3356 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003357}
3358
3359
3360String::AsciiValue::~AsciiValue() {
3361 i::DeleteArray(str_);
3362}
3363
3364
3365String::Value::Value(v8::Handle<v8::Value> obj) {
3366 EnsureInitialized("v8::String::Value::Value()");
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003367 if (obj.IsEmpty()) {
3368 str_ = NULL;
3369 length_ = 0;
3370 return;
3371 }
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00003372 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003373 HandleScope scope;
ager@chromium.org9258b6b2008-09-11 09:11:10 +00003374 TryCatch try_catch;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003375 Handle<String> str = obj->ToString();
ager@chromium.org9258b6b2008-09-11 09:11:10 +00003376 if (str.IsEmpty()) {
3377 str_ = NULL;
3378 length_ = 0;
3379 } else {
3380 length_ = str->Length();
3381 str_ = i::NewArray<uint16_t>(length_ + 1);
3382 str->Write(str_);
3383 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003384}
3385
3386
3387String::Value::~Value() {
3388 i::DeleteArray(str_);
3389}
3390
3391Local<Value> Exception::RangeError(v8::Handle<v8::String> raw_message) {
3392 LOG_API("RangeError");
3393 ON_BAILOUT("v8::Exception::RangeError()", return Local<Value>());
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00003394 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003395 i::Object* error;
3396 {
3397 HandleScope scope;
3398 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
3399 i::Handle<i::Object> result = i::Factory::NewRangeError(message);
3400 error = *result;
3401 }
3402 i::Handle<i::Object> result(error);
3403 return Utils::ToLocal(result);
3404}
3405
3406Local<Value> Exception::ReferenceError(v8::Handle<v8::String> raw_message) {
3407 LOG_API("ReferenceError");
3408 ON_BAILOUT("v8::Exception::ReferenceError()", return Local<Value>());
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00003409 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003410 i::Object* error;
3411 {
3412 HandleScope scope;
3413 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
3414 i::Handle<i::Object> result = i::Factory::NewReferenceError(message);
3415 error = *result;
3416 }
3417 i::Handle<i::Object> result(error);
3418 return Utils::ToLocal(result);
3419}
3420
3421Local<Value> Exception::SyntaxError(v8::Handle<v8::String> raw_message) {
3422 LOG_API("SyntaxError");
3423 ON_BAILOUT("v8::Exception::SyntaxError()", return Local<Value>());
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00003424 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003425 i::Object* error;
3426 {
3427 HandleScope scope;
3428 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
3429 i::Handle<i::Object> result = i::Factory::NewSyntaxError(message);
3430 error = *result;
3431 }
3432 i::Handle<i::Object> result(error);
3433 return Utils::ToLocal(result);
3434}
3435
3436Local<Value> Exception::TypeError(v8::Handle<v8::String> raw_message) {
3437 LOG_API("TypeError");
3438 ON_BAILOUT("v8::Exception::TypeError()", return Local<Value>());
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00003439 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003440 i::Object* error;
3441 {
3442 HandleScope scope;
3443 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
3444 i::Handle<i::Object> result = i::Factory::NewTypeError(message);
3445 error = *result;
3446 }
3447 i::Handle<i::Object> result(error);
3448 return Utils::ToLocal(result);
3449}
3450
3451Local<Value> Exception::Error(v8::Handle<v8::String> raw_message) {
3452 LOG_API("Error");
3453 ON_BAILOUT("v8::Exception::Error()", return Local<Value>());
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00003454 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003455 i::Object* error;
3456 {
3457 HandleScope scope;
3458 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
3459 i::Handle<i::Object> result = i::Factory::NewError(message);
3460 error = *result;
3461 }
3462 i::Handle<i::Object> result(error);
3463 return Utils::ToLocal(result);
3464}
3465
3466
3467// --- D e b u g S u p p o r t ---
3468
ager@chromium.org65dad4b2009-04-23 08:48:43 +00003469#ifdef ENABLE_DEBUGGER_SUPPORT
3470bool Debug::SetDebugEventListener(EventCallback that, Handle<Value> data) {
iposva@chromium.org245aa852009-02-10 00:49:54 +00003471 EnsureInitialized("v8::Debug::SetDebugEventListener()");
3472 ON_BAILOUT("v8::Debug::SetDebugEventListener()", return false);
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00003473 ENTER_V8;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003474 HandleScope scope;
ager@chromium.org381abbb2009-02-25 13:23:22 +00003475 i::Handle<i::Object> proxy = i::Factory::undefined_value();
3476 if (that != NULL) {
3477 proxy = i::Factory::NewProxy(FUNCTION_ADDR(that));
3478 }
3479 i::Debugger::SetEventListener(proxy, Utils::OpenHandle(*data));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003480 return true;
3481}
3482
3483
iposva@chromium.org245aa852009-02-10 00:49:54 +00003484bool Debug::SetDebugEventListener(v8::Handle<v8::Object> that,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003485 Handle<Value> data) {
iposva@chromium.org245aa852009-02-10 00:49:54 +00003486 ON_BAILOUT("v8::Debug::SetDebugEventListener()", return false);
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00003487 ENTER_V8;
iposva@chromium.org245aa852009-02-10 00:49:54 +00003488 i::Debugger::SetEventListener(Utils::OpenHandle(*that),
3489 Utils::OpenHandle(*data));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003490 return true;
3491}
3492
3493
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003494void Debug::DebugBreak() {
kasperl@chromium.org71affb52009-05-26 05:44:31 +00003495 if (!i::V8::IsRunning()) return;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003496 i::StackGuard::DebugBreak();
3497}
3498
3499
ager@chromium.org5ec48922009-05-05 07:25:34 +00003500static v8::Debug::MessageHandler message_handler = NULL;
3501
3502static void MessageHandlerWrapper(const v8::Debug::Message& message) {
3503 if (message_handler) {
3504 v8::String::Value json(message.GetJSON());
3505 message_handler(*json, json.length(), message.GetClientData());
3506 }
3507}
3508
3509
ager@chromium.org65dad4b2009-04-23 08:48:43 +00003510void Debug::SetMessageHandler(v8::Debug::MessageHandler handler,
ager@chromium.org41826e72009-03-30 13:30:57 +00003511 bool message_handler_thread) {
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +00003512 EnsureInitialized("v8::Debug::SetMessageHandler");
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00003513 ENTER_V8;
ager@chromium.org3a37e9b2009-04-27 09:26:21 +00003514 // Message handler thread not supported any more. Parameter temporally left in
3515 // the API for client compatability reasons.
3516 CHECK(!message_handler_thread);
ager@chromium.org5ec48922009-05-05 07:25:34 +00003517
3518 // TODO(sgjesse) support the old message handler API through a simple wrapper.
3519 message_handler = handler;
3520 if (message_handler != NULL) {
3521 i::Debugger::SetMessageHandler(MessageHandlerWrapper);
3522 } else {
3523 i::Debugger::SetMessageHandler(NULL);
3524 }
3525}
3526
3527
3528void Debug::SetMessageHandler2(v8::Debug::MessageHandler2 handler) {
3529 EnsureInitialized("v8::Debug::SetMessageHandler");
3530 ENTER_V8;
sgjesse@chromium.orga9eaf5c2009-06-17 14:04:55 +00003531 HandleScope scope;
ager@chromium.org3a37e9b2009-04-27 09:26:21 +00003532 i::Debugger::SetMessageHandler(handler);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003533}
3534
3535
ager@chromium.org65dad4b2009-04-23 08:48:43 +00003536void Debug::SendCommand(const uint16_t* command, int length,
3537 ClientData* client_data) {
kasperl@chromium.org71affb52009-05-26 05:44:31 +00003538 if (!i::V8::IsRunning()) return;
ager@chromium.org65dad4b2009-04-23 08:48:43 +00003539 i::Debugger::ProcessCommand(i::Vector<const uint16_t>(command, length),
3540 client_data);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003541}
3542
3543
ager@chromium.org65dad4b2009-04-23 08:48:43 +00003544void Debug::SetHostDispatchHandler(HostDispatchHandler handler,
3545 int period) {
ager@chromium.org381abbb2009-02-25 13:23:22 +00003546 EnsureInitialized("v8::Debug::SetHostDispatchHandler");
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00003547 ENTER_V8;
ager@chromium.org65dad4b2009-04-23 08:48:43 +00003548 i::Debugger::SetHostDispatchHandler(handler, period);
ager@chromium.org381abbb2009-02-25 13:23:22 +00003549}
3550
3551
ager@chromium.orga74f0da2008-12-03 16:05:52 +00003552Handle<Value> Debug::Call(v8::Handle<v8::Function> fun,
3553 v8::Handle<v8::Value> data) {
kasperl@chromium.org71affb52009-05-26 05:44:31 +00003554 if (!i::V8::IsRunning()) return Handle<Value>();
ager@chromium.orga74f0da2008-12-03 16:05:52 +00003555 ON_BAILOUT("v8::Debug::Call()", return Handle<Value>());
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00003556 ENTER_V8;
ager@chromium.orga74f0da2008-12-03 16:05:52 +00003557 i::Handle<i::Object> result;
3558 EXCEPTION_PREAMBLE();
3559 if (data.IsEmpty()) {
3560 result = i::Debugger::Call(Utils::OpenHandle(*fun),
3561 i::Factory::undefined_value(),
3562 &has_pending_exception);
3563 } else {
3564 result = i::Debugger::Call(Utils::OpenHandle(*fun),
3565 Utils::OpenHandle(*data),
3566 &has_pending_exception);
3567 }
3568 EXCEPTION_BAILOUT_CHECK(Local<Value>());
3569 return Utils::ToLocal(result);
3570}
3571
3572
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00003573bool Debug::EnableAgent(const char* name, int port) {
3574 return i::Debugger::StartAgent(name, port);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00003575}
ager@chromium.org65dad4b2009-04-23 08:48:43 +00003576#endif // ENABLE_DEBUGGER_SUPPORT
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00003577
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003578namespace internal {
3579
3580
3581HandleScopeImplementer* HandleScopeImplementer::instance() {
3582 return &thread_local;
3583}
3584
3585
3586char* HandleScopeImplementer::ArchiveThread(char* storage) {
3587 return thread_local.ArchiveThreadHelper(storage);
3588}
3589
3590
3591char* HandleScopeImplementer::ArchiveThreadHelper(char* storage) {
ager@chromium.orgddb913d2009-01-27 10:01:48 +00003592 v8::ImplementationUtilities::HandleScopeData* current =
3593 v8::ImplementationUtilities::CurrentHandleScope();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003594 handle_scope_data_ = *current;
3595 memcpy(storage, this, sizeof(*this));
3596
3597 Initialize();
3598 current->Initialize();
3599
3600 return storage + ArchiveSpacePerThread();
3601}
3602
3603
3604int HandleScopeImplementer::ArchiveSpacePerThread() {
3605 return sizeof(thread_local);
3606}
3607
3608
3609char* HandleScopeImplementer::RestoreThread(char* storage) {
3610 return thread_local.RestoreThreadHelper(storage);
3611}
3612
3613
3614char* HandleScopeImplementer::RestoreThreadHelper(char* storage) {
3615 memcpy(this, storage, sizeof(*this));
ager@chromium.orgddb913d2009-01-27 10:01:48 +00003616 *v8::ImplementationUtilities::CurrentHandleScope() = handle_scope_data_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003617 return storage + ArchiveSpacePerThread();
3618}
3619
3620
3621void HandleScopeImplementer::Iterate(
3622 ObjectVisitor* v,
3623 List<void**>* blocks,
ager@chromium.orgddb913d2009-01-27 10:01:48 +00003624 v8::ImplementationUtilities::HandleScopeData* handle_data) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003625 // Iterate over all handles in the blocks except for the last.
3626 for (int i = blocks->length() - 2; i >= 0; --i) {
3627 Object** block =
3628 reinterpret_cast<Object**>(blocks->at(i));
3629 v->VisitPointers(block, &block[kHandleBlockSize]);
3630 }
3631
3632 // Iterate over live handles in the last block (if any).
3633 if (!blocks->is_empty()) {
3634 v->VisitPointers(reinterpret_cast<Object**>(blocks->last()),
3635 reinterpret_cast<Object**>(handle_data->next));
3636 }
3637}
3638
3639
3640void HandleScopeImplementer::Iterate(ObjectVisitor* v) {
ager@chromium.orgddb913d2009-01-27 10:01:48 +00003641 v8::ImplementationUtilities::HandleScopeData* current =
3642 v8::ImplementationUtilities::CurrentHandleScope();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003643 Iterate(v, thread_local.Blocks(), current);
3644}
3645
3646
3647char* HandleScopeImplementer::Iterate(ObjectVisitor* v, char* storage) {
3648 HandleScopeImplementer* thread_local =
3649 reinterpret_cast<HandleScopeImplementer*>(storage);
3650 List<void**>* blocks_of_archived_thread = thread_local->Blocks();
ager@chromium.orgddb913d2009-01-27 10:01:48 +00003651 v8::ImplementationUtilities::HandleScopeData* handle_data_of_archived_thread =
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003652 &thread_local->handle_scope_data_;
3653 Iterate(v, blocks_of_archived_thread, handle_data_of_archived_thread);
3654
3655 return storage + ArchiveSpacePerThread();
3656}
3657
3658} } // namespace v8::internal