/**************************************************************************** ** ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the V4VM module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ // Copyright 2012 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following // disclaimer in the documentation and/or other materials provided // with the distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** \mainpage V8 API Reference Guide * * V8 is Google's open source JavaScript engine. * * This set of documents provides reference material generated from the * V8 header file, include/v8.h. * * For other documentation see http://code.google.com/apis/v8/ */ #ifndef V8_H_ #define V8_H_ #include "qv4global_p.h" #include "qv4string_p.h" #include #include namespace QQmlJS { namespace VM { struct Value; struct String; struct ExecutionEngine; struct Object; class MemoryManager; } } #include #define V8EXPORT Q_V4_EXPORT /** * The v8 JavaScript engine. */ namespace v8 { class Context; class String; class StringObject; class Value; class Utils; class Number; class NumberObject; class Object; class Array; class Int32; class Uint32; class External; class Primitive; class Boolean; class BooleanObject; class Integer; class Function; class Date; class ImplementationUtilities; class Signature; class AccessorSignature; template struct Handle; template class Local; template class Persistent; class FunctionTemplate; class ObjectTemplate; class Data; class AccessorInfo; class StackTrace; class StackFrame; class Isolate; class TryCatch; V8EXPORT void *gcProtect(void *handle); V8EXPORT void gcProtect(void *memoryManager, void *handle); V8EXPORT void gcUnprotect(void *memoryManager, void *handle); // --- Weak Handles --- /** * A weak reference callback function. * * This callback should either explicitly invoke Dispose on |object| if * V8 wrapper is not needed anymore, or 'revive' it by invocation of MakeWeak. * * \param object the weak global object to be reclaimed by the garbage collector * \param parameter the value passed in when making the weak global object */ typedef void (*WeakReferenceCallback)(Persistent object, void* parameter); // --- Handles --- #define TYPE_CHECK(T, S) \ while (false) { \ *(static_cast(0)) = static_cast(0); \ } /** * An object reference managed by the v8 garbage collector. * * All objects returned from v8 have to be tracked by the garbage * collector so that it knows that the objects are still alive. Also, * because the garbage collector may move objects, it is unsafe to * point directly to an object. Instead, all objects are stored in * handles which are known by the garbage collector and updated * whenever an object moves. Handles should always be passed by value * (except in cases like out-parameters) and they should never be * allocated on the heap. * * There are two types of handles: local and persistent handles. * Local handles are light-weight and transient and typically used in * local operations. They are managed by HandleScopes. Persistent * handles can be used when storing objects across several independent * operations and have to be explicitly deallocated when they're no * longer used. * * It is safe to extract the object stored in the handle by * dereferencing the handle (for instance, to extract the Object* from * a Handle); the value will still be governed by a handle * behind the scenes and the same rules apply to these values as to * their handles. */ template struct Handle; template struct HandleOperations { static void init(Handle *handle) { #if QT_POINTER_SIZE == 8 handle->val = quint64(Handle::_Null_Type) << Handle::Tag_Shift; #else handle->tag = Handle::_Null_Type; handle->int_32 = 0; #endif } static void ref(Handle *) { } static void deref(Handle *) { } static void *protect(Handle *handle) { return gcProtect(handle); } static void protect(void *memoryManager, Handle *handle) { gcProtect(memoryManager, handle); } static void unProtect(void *memoryManager, Handle *handle) { gcUnprotect(memoryManager, handle); } static bool isEmpty(const Handle *handle) { return handle->tag == Handle::_Null_Type; } static T *get(const Handle *handle) { return const_cast(reinterpret_cast(handle)); } }; #define DEFINE_REFCOUNTED_HANDLE_OPERATIONS(Type) \ template <> \ struct HandleOperations \ { \ static void init(Handle *handle) \ { \ handle->object = 0; \ } \ \ static void ref(Handle *handle) \ { \ if (handle->object) \ handle->object->ref.ref(); \ } \ \ static void deref(Handle *handle) \ { \ if (handle->object && !handle->object->ref.deref()) { \ delete handle->object; \ handle->object = 0; \ } \ } \ static void *protect(Handle *) { return 0; } \ static void protect(void *, Handle *) {} \ static void unProtect(void *, Handle *) {} \ static bool isEmpty(const Handle *handle) \ { \ return handle->object == 0; \ } \ static Type *get(const Handle *handle) \ { \ return handle->object; \ } \ \ }; template struct Handle { Handle() { HandleOperations::init(this); } template Handle(const Handle &that) : val(that.val) { HandleOperations::ref(this); } explicit Handle(T *obj) { object = obj; HandleOperations::ref(this); } Handle(const Handle &other) : val(other.val) { HandleOperations::ref(this); } Handle &operator=(const Handle &other) { if (this == &other) return *this; HandleOperations::deref(this); this->val = other.val; HandleOperations::ref(this); return *this; } ~Handle() { HandleOperations::deref(this); } bool IsEmpty() const { return HandleOperations::isEmpty(this); } T *operator->() const { return HandleOperations::get(this); } T *get() const { return HandleOperations::get(this); } template static Handle Cast(Handle that) { return that.template As(); } template Handle As() { return Handle(*this); } void Clear() { val = 0; } template inline bool operator==(Handle that) const { return val == that.val; } template inline bool operator!=(Handle that) const { return val != that.val; } enum Masks { NotDouble_Mask = 0xfffc0000, Type_Mask = 0xffff8000, Immediate_Mask = NotDouble_Mask | 0x00008000, Tag_Shift = 32 }; enum ValueType { Undefined_Type = Immediate_Mask | 0x00000, Null_Type = Immediate_Mask | 0x10000, Boolean_Type = Immediate_Mask | 0x20000, Integer_Type = Immediate_Mask | 0x30000, Object_Type = NotDouble_Mask | 0x00000, String_Type = NotDouble_Mask | 0x10000 }; enum ImmediateFlags { ConvertibleToInt = Immediate_Mask | 0x1 }; enum ValueTypeInternal { _Undefined_Type = Undefined_Type, _Null_Type = Null_Type | ConvertibleToInt, _Boolean_Type = Boolean_Type | ConvertibleToInt, _Integer_Type = Integer_Type | ConvertibleToInt, _Object_Type = Object_Type, _String_Type = String_Type }; union { T *object; quint64 val; double dbl; struct { #if Q_BYTE_ORDER != Q_LITTLE_ENDIAN uint tag; #endif union { uint uint_32; int int_32; #if QT_POINTER_SIZE == 4 T *o; #endif }; #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN uint tag; #endif }; }; }; /** * A light-weight stack-allocated object handle. All operations * that return objects from within v8 return them in local handles. They * are created within HandleScopes, and all local handles allocated within a * handle scope are destroyed when the handle scope is destroyed. Hence it * is not necessary to explicitly deallocate local handles. */ template class Local : public Handle { public: Local() {} template Local(Local that) : Handle(Handle::Cast(that)) { /** * This check fails when trying to convert between incompatible * handles. For example, converting from a Handle to a * Handle. */ TYPE_CHECK(T, S); } template Local(S* that) : Handle(that) { } template static Local Cast(Local that) { #ifdef V8_ENABLE_CHECKS // If we're going to perform the type check then we have to check // that the handle isn't empty before doing the checked cast. if (that.IsEmpty()) return Local(); #endif return Local::New(Handle::Cast(that)); } template Local As() { return Local::Cast(*this); } /** Create a local handle for the content of another handle. * The referee is kept alive by the local handle even when * the original handle is destroyed/disposed. */ static Local New(Handle that) { Local result; result.Handle::operator =(that); return result; } }; /** * An object reference that is independent of any handle scope. Where * a Local handle only lives as long as the HandleScope in which it was * allocated, a Persistent handle remains valid until it is explicitly * disposed. * * A persistent handle contains a reference to a storage cell within * the v8 engine which holds an object value and which is updated by * the garbage collector whenever the object is moved. A new storage * cell can be created using Persistent::New and existing handles can * be disposed using Persistent::Dispose. Since persistent handles * are passed by value you may have many persistent handle objects * that point to the same storage cell. For instance, if you pass a * persistent handle as an argument to a function you will not get two * different storage cells but rather two references to the same * storage cell. */ template class Persistent : public Handle { public: /** * Creates an empty persistent handle that doesn't point to any * storage cell. */ Persistent() {} ~Persistent() { HandleOperations::unProtect(m_memoryManager, this); } Persistent(const Persistent &other) : Handle(other) , m_memoryManager(other.m_memoryManager) { HandleOperations::protect(m_memoryManager, this); } Persistent &operator =(const Persistent &other) { if (&other == this) return *this; HandleOperations::unProtect(m_memoryManager, this); Handle::operator =(other); m_memoryManager = other.m_memoryManager; HandleOperations::protect(m_memoryManager, this); return *this; } /** * Creates a persistent handle for the same storage cell as the * specified handle. This constructor allows you to pass persistent * handles as arguments by value and to assign between persistent * handles. However, attempting to assign between incompatible * persistent handles, for instance from a Persistent to a * Persistent will cause a compile-time error. Assigning * between compatible persistent handles, for instance assigning a * Persistent to a variable declared as Persistent, * is allowed as String is a subclass of Value. */ template Persistent(Persistent that) : Handle(Handle::Cast(that)) { m_memoryManager = that.m_memoryManager; HandleOperations::protect(m_memoryManager, this); } template Persistent(S* that) : Handle(that) { m_memoryManager = HandleOperations::protect(this); } /** * "Casts" a plain handle which is known to be a persistent handle * to a persistent handle. */ template explicit Persistent(Handle that) : Handle(*that) { m_memoryManager = HandleOperations::protect(this); } template static Persistent Cast(Persistent that) { return Persistent(T::Cast(*that)); } template Persistent As() { return Persistent::Cast(*this); } /** * Creates a new persistent handle for an existing local or * persistent handle. */ static Persistent New(Handle that) { Persistent result; result.Handle::operator =(that); result.m_memoryManager = HandleOperations::protect(&result); return result; } /** * Releases the storage cell referenced by this persistent handle. * Does not remove the reference to the cell from any handles. * This handle's reference, and any other references to the storage * cell remain and IsEmpty will still return false. */ void Dispose() { HandleOperations::unProtect(m_memoryManager, this); m_memoryManager = 0; HandleOperations::deref(this); HandleOperations::init(this); } void Dispose(Isolate*) { Dispose(); } /** * Make the reference to this object weak. When only weak handles * refer to the object, the garbage collector will perform a * callback to the given V8::WeakReferenceCallback function, passing * it the object reference and the given parameters. */ void MakeWeak(void* parameters, WeakReferenceCallback callback); public: void *m_memoryManager; }; /** * A stack-allocated class that governs a number of local handles. * After a handle scope has been created, all local handles will be * allocated within that handle scope until either the handle scope is * deleted or another handle scope is created. If there is already a * handle scope and a new one is created, all allocations will take * place in the new handle scope until it is deleted. After that, * new handles will again be allocated in the original handle scope. * * After the handle scope of a local handle has been deleted the * garbage collector will no longer track the object stored in the * handle and may deallocate it. The behavior of accessing a handle * for which the handle scope has been deleted is undefined. */ class V8EXPORT HandleScope { public: HandleScope() {} ~HandleScope() {} /** * Closes the handle scope and returns the value as a handle in the * previous scope, which is the new current scope after the call. */ template Local Close(Handle value) { return Local::New(value); } }; // --- Special objects --- /** * The superclass of values and API object templates. */ class V8EXPORT Data : public QSharedData { }; DEFINE_REFCOUNTED_HANDLE_OPERATIONS(Data) /** * The origin, within a file, of a script. */ class V8EXPORT ScriptOrigin { public: ScriptOrigin() : m_lineNumber(0), m_columnNumber(0) {} ScriptOrigin( Handle resource_name, Handle resource_line_offset = Handle(), Handle resource_column_offset = Handle()); Handle ResourceName() const; Handle ResourceLineOffset() const; Handle ResourceColumnOffset() const; private: QString m_fileName; int m_lineNumber, m_columnNumber; friend class Script; }; class ScriptData; /** * A compiled JavaScript script. */ class V8EXPORT Script : public QSharedData { public: enum CompileFlags { Default = 0x00, QmlMode = 0x01, NativeMode = 0x02 }; /** * Compiles the specified script (context-independent). * * \param source Script source code. * \param origin Script origin, owned by caller, no references are kept * when New() returns * \param pre_data Pre-parsing data, as obtained by ScriptData::PreCompile() * using pre_data speeds compilation if it's done multiple times. * Owned by caller, no references are kept when New() returns. * \param script_data Arbitrary data associated with script. Using * this has same effect as calling SetData(), but allows data to be * available to compile event handlers. * \return Compiled script object (context independent; when run it * will use the currently entered context). */ static Local