Source code drop for the Actionscript virtual machine in the Adobe Flash Player for December 2013
230 lines
9.5 KiB
C++
230 lines
9.5 KiB
C++
/* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */
|
|
/* vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#ifndef __avmplus_ScriptObject__
|
|
#define __avmplus_ScriptObject__
|
|
|
|
|
|
namespace avmplus
|
|
{
|
|
#define avmplus_ScriptObject_isExactInterlock 1
|
|
|
|
/**
|
|
* one actionscript object. might or might not be a function.
|
|
* Base class for all objects visible to script code.
|
|
*/
|
|
class ScriptObject : public AvmPlusScriptableObject
|
|
{
|
|
protected:
|
|
ScriptObject(VTable* vtable, ScriptObject* delegate);
|
|
ScriptObject(VTable* vtable, ScriptObject* delegate, int htCapacity);
|
|
public:
|
|
REALLY_INLINE static ScriptObject* create(MMgc::GC* gc, VTable* vtable, ScriptObject* delegate);
|
|
REALLY_INLINE static ScriptObject* create(MMgc::GC* gc, VTable* vtable, ScriptObject* delegate, int htCapacity);
|
|
|
|
// Not actually entirely trivial, as it decrements reference counts
|
|
// manually, not just by GCMember smart pointer destructors.
|
|
#ifdef DRC_TRIVIAL_DESTRUCTOR
|
|
~ScriptObject();
|
|
#endif
|
|
|
|
virtual bool gcTrace(MMgc::GC* gc, size_t cursor);
|
|
|
|
ScriptObject* getDelegate() const;
|
|
void setDelegate(ScriptObject *d);
|
|
Atom atom() const;
|
|
virtual Atom toAtom() const;
|
|
Traits* traits() const;
|
|
AvmCore* core() const;
|
|
MMgc::GC* gc() const;
|
|
Toplevel* toplevel() const;
|
|
/**
|
|
* Returns a pointer to hashtable to use for dynamic
|
|
* properties, this is a derived pointer and can never be
|
|
* NULL. This method should not be called until the full
|
|
* construction sequence (C++ and AS3) is complete and will
|
|
* assert if called on a Dictionary before its init method has
|
|
* run.
|
|
*/
|
|
InlineHashtable* getTable() const;
|
|
/**
|
|
* Like getTable but doesn't init the table if its empty, and
|
|
* will return NULL and not assert on a yet to be initialized
|
|
* Dictionary.
|
|
*/
|
|
InlineHashtable* getTableNoInit() const;
|
|
|
|
Atom getSlotAtom(uint32_t slot, AvmCore *core);
|
|
|
|
Atom getSlotAtom(uint32_t slot);
|
|
|
|
// like getSlotAtom, but assume the resulting Atom is a ScriptObject...
|
|
// if it is not, return NULL. useful for callers that expect only
|
|
// a ScriptObject and reject other types (eg callproperty). If the
|
|
// slot in question is usually a ScriptObject, it's substantially faster
|
|
// to call this (vs getSlotAtom).
|
|
ScriptObject* getSlotObject(uint32_t slot);
|
|
|
|
// NOTE, this now does the equivalent of Toplevel::coerce() internally;
|
|
// it is not necessary to call coerce() prior to calling this!
|
|
void coerceAndSetSlotAtom(uint32_t slot, Atom atom);
|
|
|
|
virtual Atom getDescendants(const Multiname* name) const;
|
|
|
|
// argv[0] = receiver
|
|
virtual Atom callProperty(const Multiname* name, int argc, Atom* argv);
|
|
|
|
// common set/set/has/delete/etc virtual methods renamed to explicitly name the expected arg types,
|
|
// to avoid potentially hidden virtual functions
|
|
virtual Atom getAtomProperty(Atom name) const;
|
|
virtual void setAtomProperty(Atom name, Atom value);
|
|
virtual bool deleteAtomProperty(Atom name);
|
|
virtual bool hasAtomProperty(Atom name) const;
|
|
virtual bool getAtomPropertyIsEnumerable(Atom name) const;
|
|
virtual void setAtomPropertyIsEnumerable(Atom name, bool enumerable);
|
|
|
|
virtual Atom getMultinameProperty(const Multiname* name) const;
|
|
virtual void setMultinameProperty(const Multiname* name, Atom value);
|
|
virtual bool deleteMultinameProperty(const Multiname* name);
|
|
virtual bool hasMultinameProperty(const Multiname* name) const;
|
|
|
|
virtual Atom getUintProperty(uint32_t i) const;
|
|
virtual void setUintProperty(uint32_t i, Atom value);
|
|
virtual bool delUintProperty(uint32_t i);
|
|
virtual bool hasUintProperty(uint32_t i) const;
|
|
|
|
// convenience wrappers for passing Stringp instead of Atom
|
|
// inline, not virtual (should never need overriding)
|
|
Atom getStringProperty(Stringp name) const;
|
|
Atom getStringPropertyFromProtoChain(Stringp name, ScriptObject* protochain, Traits *origObjTraits) const;
|
|
void setStringProperty(Stringp name, Atom value);
|
|
bool deleteStringProperty(Stringp name);
|
|
bool hasStringProperty(Stringp name) const;
|
|
bool getStringPropertyIsEnumerable(Stringp name) const;
|
|
void setStringPropertyIsEnumerable(Stringp name, bool enumerable);
|
|
|
|
virtual Atom defaultValue(); // ECMA [[DefaultValue]]
|
|
virtual Stringp toString();
|
|
|
|
/**
|
|
* Implmenets the behavior of this object when called as a function.
|
|
* This function is only intended to be called by the VM, not from
|
|
* C++ host code. For the latter, use one of the avm::callFunction()
|
|
* wrappers.
|
|
*
|
|
* argv[0] is not counted in argc and is the receiver (this) parameter
|
|
* argc[1+] are the normal arguments
|
|
*/
|
|
virtual Atom call(int argc, Atom* argv);
|
|
|
|
/**
|
|
* argv[0] = receiver(ignored)
|
|
* arg1 = argv[1]
|
|
* argN = argv[argc]
|
|
*
|
|
* called as constructor, as in new C(). for user classes this
|
|
* invokes the implicit constructor followed by the user's constructor
|
|
* if any.
|
|
*
|
|
* NOTE: The contents of the given argument list can be modified during
|
|
* invocation of the constructor without further warning.
|
|
* Do not reuse an argument list AS-IS for multiple constructor calls,
|
|
* unless you make sure to reinitialize the contents of the argument list after each call.
|
|
*
|
|
* NOTE: subclasses should never need to declare this method in their class;
|
|
* an override declaration will be provided for them iff
|
|
* construct="override" or construct="instance" is specified in the AS3 file.
|
|
*/
|
|
virtual Atom construct(int argc, Atom* argv);
|
|
|
|
// TODO make this const
|
|
virtual Atom nextName(int index);
|
|
|
|
// TODO make this const
|
|
virtual Atom nextValue(int index);
|
|
|
|
// TODO make this const
|
|
virtual int nextNameIndex(int index);
|
|
|
|
virtual Atom applyTypeArgs(int argc, Atom* argv);
|
|
|
|
// This is a fast way to implement "istype(MethodClosure)"; it returns non-null if
|
|
// this is an MethodClosure (or subclass thereof)
|
|
virtual MethodClosure* toMethodClosure() const;
|
|
bool isMethodClosure() const;
|
|
|
|
// The maximum integer key we can use with our ScriptObject
|
|
// HashTable must fit within 28 bits. Any integer larger
|
|
// than 28 bits will use a string key.
|
|
static const uint32_t MAX_INTEGER_MASK = 0xF0000000;
|
|
|
|
// return true iff the object is a toplevel script init object.
|
|
bool isGlobalObject() const;
|
|
|
|
virtual Stringp implToString() const;
|
|
|
|
// this really shouldn't exist here, but AIR currently plays some games with subclassing
|
|
// "Function" that use C++ classes that don't descend from FunctionObject. Easier to fix
|
|
// by rooting this method here than by fixing AIR at this time.
|
|
virtual CodeContext* getFunctionCodeContext() const;
|
|
|
|
// This is a fast way to implement "istype(ARRAY)"; it returns non-null if
|
|
// this is an ArrayObject (or subclass thereof)
|
|
virtual ArrayObject* toArrayObject();
|
|
|
|
// This gets the property named "length" (if any) on the object, coerces it to a uint,
|
|
// and returns the value. (Since uint(undefined) == 0, undefined length is zero.)
|
|
virtual uint32_t getLengthProperty();
|
|
|
|
// This sets the property named "length" to the given uint value. If this
|
|
// is a nondynamic object, or there is a read-only length property, or uint
|
|
// can't be coerced to the type of "length", an exception will be thrown.
|
|
virtual void setLengthProperty(uint32_t newLen);
|
|
|
|
virtual ClassClosure* toClassClosure();
|
|
|
|
#ifdef AVMPLUS_VERBOSE
|
|
public:
|
|
virtual PrintWriter& print(PrintWriter& prw) const;
|
|
#endif
|
|
|
|
#ifdef DEBUGGER
|
|
public:
|
|
virtual uint64_t bytesUsed() const;
|
|
virtual void registerDependentObjects(IMemorySampler *memSampler);
|
|
#endif
|
|
#if defined(DEBUGGER) || defined(VMCFG_AOT)
|
|
public:
|
|
virtual MethodEnv* getCallMethodEnv();
|
|
#endif
|
|
|
|
protected:
|
|
|
|
Atom getAtomPropertyFromProtoChain(Atom name, ScriptObject* protochain, Traits *origObjTraits) const;
|
|
|
|
// If name defined in this (not its prototype chain), sets
|
|
// *recv to this[name] and returns true. Else returns false.
|
|
// (Assumes this is dynamic; do not call on sealed instances.)
|
|
virtual bool isOwnAtomPropertyHere(Atom name, Atom *recv) const;
|
|
|
|
void throwWriteSealedError(Atom name);
|
|
void throwWriteSealedError(const Multiname& name);
|
|
|
|
public:
|
|
void throwCantInstantiateError();
|
|
|
|
private:
|
|
void initHashtable(int capacity = InlineHashtable::kDefaultCapacity);
|
|
|
|
// ------------------------ DATA SECTION BEGIN
|
|
public: VTable* const vtable;
|
|
private: GCMember<ScriptObject> delegate; // __proto__ in AS2, archetype in semantics
|
|
// ------------------------ DATA SECTION END
|
|
};
|
|
}
|
|
|
|
#endif /* __avmplus_ScriptObject__ */
|