/************************************************************************** Lightspark, a free flash player implementation Copyright (C) 2009,2010 Alessandro Pignotti (a.pignotti@sssup.it) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . **************************************************************************/ #ifndef ASOBJECTS_H #define ASOBJECTS_H #include #include #include "swftypes.h" #include "frame.h" #include "input.h" #include "compat.h" #include "exceptions.h" namespace lightspark { class SystemState; }; extern TLSDATA lightspark::SystemState* sys; namespace lightspark { const tiny_string AS3="http://adobe.com/AS3/2006/builtin"; class Event; class method_info; struct call_context; class InterfaceClass: public IInterface { protected: static void lookupAndLink(ASObject* o, const tiny_string& name, const tiny_string& interfaceNs); }; class Class_base: public ASObject { friend class ABCVm; friend class ABCContext; private: mutable std::vector interfaces; mutable std::vector interfaces_added; bool use_protected; tiny_string protected_ns; int _maxlevel() { return max_level; } void recursiveBuild(ASObject* target); IFunction* constructor; public: Class_base* super; //We need to know what is the context we are referring to ABCContext* context; tiny_string class_name; int class_index; int max_level; void handleConstruction(ASObject* target, ASObject* const* args, unsigned int argslen, bool buildAndLink); void setConstructor(IFunction* c); Class_base(const tiny_string& name):use_protected(false),constructor(NULL),super(NULL),context(NULL),class_name(name),class_index(-1), max_level(0) {type=T_CLASS;} ~Class_base(); virtual IInterface* getInstance(bool construct, ASObject* const* args, const unsigned int argslen)=0; objAndLevel getVariableByMultiname(const multiname& name, bool skip_impl, bool enableOverride=true) { objAndLevel ret=ASObject::getVariableByMultiname(name, skip_impl, enableOverride); if(ret.obj==NULL && super) ret=super->getVariableByMultiname(name, skip_impl, enableOverride); return ret; } intptr_t getVariableByMultiname_i(const multiname& name) { abort(); return 0; /* intptr_t ret=ASObject::getVariableByMultiname(name); if(==NULL && super) ret=super->getVariableByMultiname(name); return ret;*/ } objAndLevel getVariableByQName(const tiny_string& name, const tiny_string& ns, bool skip_impl=false) { objAndLevel ret=ASObject::getVariableByQName(name,ns,skip_impl); if(ret.obj==NULL && super) ret=super->getVariableByQName(name,ns,skip_impl); return ret; } /* void setVariableByMultiname_i(const multiname& name, intptr_t value) { abort(); } void setVariableByMultiname(const multiname& name, ASObject* o) { abort(); } void setVariableByQName(const tiny_string& name, const tiny_string& ns, ASObject* o, bool find_back=true) { abort(); }*/ void addImplementedInterface(const multiname& i); void addImplementedInterface(Class_base* i); virtual void buildInstanceTraits(ASObject* o) const=0; const std::vector& getInterfaces() const; void linkInterface(ASObject* obj) const; bool isSubClass(const Class_base* cls) const; tiny_string getQualifiedClassName() const; tiny_string toString(bool debugMsg); }; class Class_object: public Class_base { private: Class_object():Class_base("Class"){}; IInterface* getInstance(bool construct, ASObject* const* args, const unsigned int argslen) { abort(); } void buildInstanceTraits(ASObject* o) const { abort(); } public: static Class_object* getClass(); }; //Adaptor from fuction to class, it does not seems to be a good idea to //derive IFunction from Class_base, because it's too heavyweight class Class_function: public Class_base { private: IFunction* f; ASObject* asprototype; IInterface* getInstance(bool construct, ASObject* const* args, const unsigned int argslen) { abort(); } void buildInstanceTraits(ASObject* o) const { abort(); } public: //Class_function is both used as the prototype for each function and as the Function classs object Class_function():Class_base("Function"),f(NULL),asprototype(NULL){} Class_function(IFunction* _f, ASObject* _p):Class_base("Function"),f(_f),asprototype(_p){} tiny_string class_name; objAndLevel getVariableByMultiname(const multiname& name, bool skip_impl=false, bool enableOverride=true) { if(name.name_s=="borderSkin") std::cerr << "Looking for borderSkin on " << this << std::endl; objAndLevel ret=Class_base::getVariableByMultiname(name,skip_impl, enableOverride); if(ret.obj==NULL && asprototype) ret=asprototype->getVariableByMultiname(name,skip_impl, enableOverride); return ret; } intptr_t getVariableByMultiname_i(const multiname& name) { abort(); return 0; /* intptr_t ret=ASObject::getVariableByMultiname(name); if(ret==NULL && super) ret=super->getVariableByMultiname(name); return ret;*/ } objAndLevel getVariableByQName(const tiny_string& name, const tiny_string& ns, bool skip_impl=false) { objAndLevel ret=Class_base::getVariableByQName(name,ns,skip_impl); if(ret.obj==NULL && asprototype) ret=asprototype->getVariableByQName(name,ns,skip_impl); return ret; } void setVariableByMultiname_i(const multiname& name, intptr_t value) { abort(); } void setVariableByMultiname(const multiname& name, ASObject* o, bool enableOverride) { abort(); } void setVariableByQName(const tiny_string& name, const tiny_string& ns, ASObject* o, bool find_back=true, bool skip_impl=false) { abort(); } static Class_function* getClass(); }; class IFunction: public ASObject { public: ASFUNCTION(apply); IFunction(); virtual ASObject* call(ASObject* obj, ASObject* const* args,int num_args, int level)=0; IFunction* bind(ASObject* c, int level) { if(!bound) { //If binding with null we are not a class method IFunction* ret; incRef(); ret=this; ret->bound=true; ret->closure_this=c; if(c) c->incRef(); ret->closure_level=level; //std::cout << "Binding " << ret << std::endl; return ret; } else { incRef(); return this; } } void override(IFunction* f) { overriden_by=f; } IFunction* getOverride() { //Get the last override IFunction* cur=overriden_by; if(cur==NULL) return this; else return cur->getOverride(); } bool isOverridden() const { return overriden_by!=NULL; } protected: virtual IFunction* clone()=0; ASObject* closure_this; int closure_level; bool bound; IFunction* overriden_by; }; class Function : public IFunction { public: typedef ASObject* (*as_function)(ASObject*, ASObject* const *, const unsigned int); Function(){} Function(as_function v):val(v){} ASObject* call(ASObject* obj, ASObject* const* args, int num_args, int level); IFunction* toFunction(); bool isEqual(ASObject* r) { abort(); } private: as_function val; Function* clone() { return new Function(*this); } }; class SyntheticFunction : public IFunction { friend class ABCVm; //friend void ASObject::handleConstruction(ASObject* const* args, unsigned int argslen, bool buildAndLink); public: typedef ASObject* (*synt_function)(call_context* cc); SyntheticFunction(method_info* m); ASObject* call(ASObject* obj, ASObject* const* args,int num_args, int level); IFunction* toFunction(); std::vector func_scope; bool isEqual(ASObject* r) { SyntheticFunction* sf=dynamic_cast(r); if(sf==NULL) return false; return mi==sf->mi; } void acquireScope(const std::vector& scope) { assert(func_scope.empty()); func_scope=scope; for(unsigned int i=0;iincRef(); } void addToScope(ASObject* s) { func_scope.push_back(s); } private: int hit_count; method_info* mi; synt_function val; SyntheticFunction* clone() { return new SyntheticFunction(*this); } }; class Boolean: public ASObject { friend bool Boolean_concrete(ASObject* obj); private: bool val; public: Boolean(bool v):val(v){type=T_BOOLEAN;} int32_t toInt() const { return val; } bool isEqual(ASObject* r); tiny_string toString(bool debugMsg); }; class Undefined : public ASObject { public: ASFUNCTION(call); Undefined(); tiny_string toString(bool debugMsg); bool isEqual(ASObject* r); virtual ~Undefined(){} }; class ASString: public IInterface { private: tiny_string toString() const; public: std::string data; static void sinit(Class_base* c); static void buildTraits(ASObject* o); ASString(); ASString(const std::string& s); ASString(const tiny_string& s); ASString(const char* s); ASFUNCTION(split); ASFUNCTION(_getLength); ASFUNCTION(replace); ASFUNCTION(concat); ASFUNCTION(slice); ASFUNCTION(substr); ASFUNCTION(indexOf); ASFUNCTION(charCodeAt); ASFUNCTION(toLowerCase); bool isEqual(bool& ret, ASObject* o); bool isLess(bool& ret, ASObject* o); bool toString(tiny_string& ret); bool toNumber(double& ret); }; class Null: public ASObject { public: Null(){type=T_NULL;} tiny_string toString(bool debugMsg); bool isEqual(ASObject* r); }; class ASQName: public IInterface { friend class ABCContext; private: tiny_string uri; tiny_string local_name; public: ASQName(){type=T_QNAME;} static void sinit(Class_base*); ASFUNCTION(_constructor); }; class Namespace: public IInterface { friend class ASQName; friend class ABCContext; private: tiny_string uri; public: Namespace(){type=T_NAMESPACE;} Namespace(const tiny_string& _uri):uri(_uri){type=T_NAMESPACE;} static void sinit(Class_base*); static void buildTraits(ASObject* o); ASFUNCTION(_constructor); }; enum DATA_TYPE {DATA_OBJECT=0,DATA_INT}; struct data_slot { DATA_TYPE type; union { ASObject* data; int32_t data_i; }; explicit data_slot(ASObject* o,DATA_TYPE t=DATA_OBJECT):type(t),data(o){} data_slot():type(DATA_OBJECT),data(NULL){} explicit data_slot(intptr_t i):type(DATA_INT),data_i(i){} }; class Array: public IInterface { friend class ABCVm; protected: std::vector data; void outofbounds() const; public: //These utility methods are also used by ByteArray static bool isValidMultiname(const multiname& name, unsigned int& index); static bool isValidQName(const tiny_string& name, const tiny_string& ns, unsigned int& index); Array(); virtual ~Array(); static void sinit(Class_base*); static void buildTraits(ASObject* o); ASFUNCTION(_constructor); ASFUNCTION(_push); ASFUNCTION(_concat); ASFUNCTION(_pop); ASFUNCTION(join); ASFUNCTION(shift); ASFUNCTION(_sort); ASFUNCTION(unshift); ASFUNCTION(filter); ASFUNCTION(indexOf); ASFUNCTION(_getLength); ASObject* at(unsigned int index) const { if(indexcall(g,NULL,0,0); } }; class PlaceObject2Tag; class DictionaryDefinable: public Definable { private: int dict_id; PlaceObject2Tag* p; public: DictionaryDefinable(int d, PlaceObject2Tag* _p):dict_id(d),p(_p){} void define(ASObject* g); }; class Math: public IInterface { public: static void sinit(Class_base* c); ASFUNCTION(atan2); ASFUNCTION(abs); ASFUNCTION(sin); ASFUNCTION(cos); ASFUNCTION(floor); ASFUNCTION(ceil); ASFUNCTION(round); ASFUNCTION(sqrt); ASFUNCTION(random); ASFUNCTION(_max); ASFUNCTION(_min); ASFUNCTION(pow); }; class RegExp: public IInterface { friend class ASString; private: std::string re; bool global; bool ignoreCase; int lastIndex; public: RegExp(); static void sinit(Class_base* c); static void buildTraits(ASObject* o); ASFUNCTION(_constructor); ASFUNCTION(exec); ASFUNCTION(test); ASFUNCTION(_getGlobal); }; }; #endif