Projects
Essentials
lightspark
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 73
View file
lightspark.spec
Changed
@@ -24,7 +24,7 @@ %endif Name: lightspark -Version: 0.7.2.99+git20150629.1759 +Version: 0.7.2.99+git20150712.0853 Release: 0 Summary: Modern, free, open-source flash player implementation License: LGPL-3.0+
View file
lightspark.tar.xz/ChangeLog
Changed
@@ -2,6 +2,10 @@ Version NEXT: + * implement several missing opcodes + * fix serialization + * implement data generation mode + * support for avmplus classes (mostly stubs) * Support LLVM up to version 3.6 * fix event dispatcher handling * several fixes for object initialization
View file
lightspark.tar.xz/docs/man/lightspark.1
Changed
@@ -19,7 +19,7 @@ lightspark \- a free Flash player .SH SYNOPSIS .B lightspark -[\-\-url|\-u http://loader.url/file.swf] [\-\-air] [\-\-disable-interpreter|\-ni] [\-\-enable-fast-interpreter|\-fi] [\-\-enable\-jit|\-j] [\-\-log\-level|\-l 0-4] [\-\-parameters\-file|\-p params-file] [\-\-profiling-output|\-o] [\-\-security-sandbox|\-s <sandbox type>] [\-\-exit-on-error] [\-\-HTTP-cookies <cookie>] [\-\-version|\-v] file.swf +[\-\-url|\-u http://loader.url/file.swf] [\-\-air] [\-\-avmplus] [\-\-disable-interpreter|\-ni] [\-\-enable-fast-interpreter|\-fi] [\-\-enable\-jit|\-j] [\-\-log\-level|\-l 0-4] [\-\-parameters\-file|\-p params-file] [\-\-profiling-output|\-o] [\-\-security-sandbox|\-s <sandbox type>] [\-\-exit-on-error] [\-\-HTTP-cookies <cookie>] [\-\-version|\-v] file.swf .SH DESCRIPTION .B Lightspark is a free, modern Flash Player implementation, this documents the options accepted by the standalone version of the program. @@ -77,6 +77,10 @@ .IP Run as an AIR application: grant permission to access both local files and network, and enable AIR APIs. .HP +\fB\-\-avmplus\fP +.IP +Run as an application with avmplus package: grant permission to access both local files and network, and enable avmplus APIs. +.HP \fB\-\-version\fP, \fB\-v\fP .IP Shows lightspark version and exits.
View file
lightspark.tar.xz/src/CMakeLists.txt
Changed
@@ -105,6 +105,7 @@ scripting/flash/text/flashtextengine.cpp scripting/flash/utils/flashutils.cpp scripting/flash/utils/ByteArray.cpp + scripting/flash/utils/CompressionAlgorithm.cpp scripting/flash/utils/Dictionary.cpp scripting/flash/utils/Proxy.cpp scripting/flash/utils/Timer.cpp @@ -132,6 +133,7 @@ scripting/toplevel/XMLList.cpp scripting/class.cpp scripting/toplevel/toplevel.cpp + scripting/avmplus/avmplus.cpp platforms/engineutils.cpp) IF(MINGW) SET(LIBSPARK_SOURCES ${LIBSPARK_SOURCES} platforms/slowpaths_generic.cpp)
View file
lightspark.tar.xz/src/allclasses.cpp
Changed
@@ -59,6 +59,7 @@ #include "scripting/flash/sensors/flashsensors.h" #include "scripting/flash/utils/flashutils.h" #include "scripting/flash/utils/ByteArray.h" +#include "scripting/flash/utils/CompressionAlgorithm.h" #include "scripting/flash/utils/Dictionary.h" #include "scripting/flash/utils/Proxy.h" #include "scripting/flash/utils/Timer.h" @@ -76,6 +77,7 @@ #include "scripting/flash/ui/ContextMenu.h" #include "scripting/flash/ui/ContextMenuItem.h" #include "scripting/flash/ui/ContextMenuBuiltInItems.h" +#include "scripting/avmplus/avmplus.h" using namespace lightspark;
View file
lightspark.tar.xz/src/allclasses.h
Changed
@@ -273,6 +273,7 @@ //Utils REGISTER_CLASS_NAME(ByteArray,"flash.utils") +REGISTER_CLASS_NAME(CompressionAlgorithm,"flash.utils") REGISTER_CLASS_NAME(Dictionary,"flash.utils") REGISTER_CLASS_NAME(Endian,"flash.utils") REGISTER_CLASS_NAME(IDataInput,"flash.utils") @@ -294,3 +295,9 @@ REGISTER_CLASS_NAME(XMLDocument,"flash.xml") REGISTER_CLASS_NAME(XMLNode,"flash.xml") +//avmplus +REGISTER_CLASS_NAME(avmplusFile,"avmplus") +REGISTER_CLASS_NAME(avmplusSystem,"avmplus") +REGISTER_CLASS_NAME(avmplusDomain,"avmplus") + +
View file
lightspark.tar.xz/src/asobject.cpp
Changed
@@ -384,34 +384,27 @@ return _MR(ret); } -bool ASObject::has_toJSON() -{ - multiname toJSONName(NULL); - toJSONName.name_type=multiname::NAME_STRING; - toJSONName.name_s_id=getSys()->getUniqueStringId("toJSON"); - toJSONName.ns.push_back(nsNameAndKind("",NAMESPACE)); - toJSONName.ns.push_back(nsNameAndKind(AS3,NAMESPACE)); - toJSONName.isAttribute = false; - return ASObject::hasPropertyByMultiname(toJSONName, true, true); -} - -tiny_string ASObject::call_toJSON() +tiny_string ASObject::call_toJSON(bool& ok,std::vector<ASObject *> &path, IFunction *replacer, const tiny_string &spaces,const tiny_string& filter) { + tiny_string res; + ok = false; multiname toJSONName(NULL); toJSONName.name_type=multiname::NAME_STRING; toJSONName.name_s_id=getSys()->getUniqueStringId("toJSON"); toJSONName.ns.push_back(nsNameAndKind("",NAMESPACE)); toJSONName.ns.push_back(nsNameAndKind(AS3,NAMESPACE)); toJSONName.isAttribute = false; - assert(ASObject::hasPropertyByMultiname(toJSONName, true, true)); + if (!ASObject::hasPropertyByMultiname(toJSONName, true, true)) + return res; _NR<ASObject> o=getVariableByMultiname(toJSONName,SKIP_IMPL); - assert_and_throw(o->is<IFunction>()); + if (!o->is<IFunction>()) + return res; + IFunction* f=o->as<IFunction>(); incRef(); ASObject *ret=f->call(this,NULL,0); - tiny_string res; if (ret->is<ASString>()) { res += "\""; @@ -419,8 +412,8 @@ res += "\""; } else - res = ret->toString(); - + res = ret->toJSON(path,replacer,spaces,filter); + ok = true; return res; } @@ -1701,13 +1694,12 @@ tiny_string ASObject::toJSON(std::vector<ASObject *> &path, IFunction *replacer, const tiny_string &spaces,const tiny_string& filter) { - if (has_toJSON()) - { - return call_toJSON(); - } + bool ok; + tiny_string res = call_toJSON(ok,path,replacer,spaces,filter); + if (ok) + return res; tiny_string newline = (spaces.empty() ? "" : "\n"); - tiny_string res; if (this->isPrimitive()) { switch(this->type) @@ -1759,6 +1751,17 @@ case T_UNDEFINED: res += "null"; break; + case T_NUMBER: + case T_INTEGER: + case T_UINTEGER: + { + tiny_string s = this->toString(); + if (s == "Infinity" || s == "-Infinity" || s == "NaN") + res += "null"; + else + res += s; + break; + } default: res += this->toString(); break;
View file
lightspark.tar.xz/src/asobject.h
Changed
@@ -451,8 +451,7 @@ _R<ASObject> call_valueOf(); bool has_toString(); _R<ASObject> call_toString(); - bool has_toJSON(); - tiny_string call_toJSON(); + tiny_string call_toJSON(bool &ok, std::vector<ASObject *> &path, IFunction *replacer, const tiny_string &spaces, const tiny_string &filter); /* Helper function for calling getClass()->getQualifiedClassName() */ virtual tiny_string getClassName() const;
View file
lightspark.tar.xz/src/backends/urlutils.cpp
Changed
@@ -68,6 +68,8 @@ std::string str = std::string(url.raw_buf()); valid = false; + if (u.empty()) + return; //Check for :// marking that there is a protocol in this url size_t colonPos = str.find("://"); @@ -513,14 +515,27 @@ isxdigit(u[i+2]) && isxdigit(u[i+3]) && isxdigit(u[i+4]) && isxdigit(u[i+5])) { - tiny_string s=tiny_string::fromChar((uint32_t)strtoul(u.substr(i+2, 4).c_str(), NULL, 16)); - str.append(s.raw_buf()); + uint32_t c = (uint32_t)strtoul(u.substr(i+2, 4).c_str(), NULL, 16); + if (c == 0) + str.push_back(c); + else + { + tiny_string s=tiny_string::fromChar(c); + str.append(s.raw_buf()); + } i += 5; + } else if(isxdigit(u[i+1]) && isxdigit(u[i+2])) { - tiny_string s=tiny_string::fromChar((uint32_t)strtoul(u.substr(i+1, 2).c_str(), NULL, 16)); - str.append(s.raw_buf()); + uint32_t c = (uint32_t)strtoul(u.substr(i+1, 2).c_str(), NULL, 16); + if (c == 0) + str.push_back(c); + else + { + tiny_string s=tiny_string::fromChar(c); + str.append(s.raw_buf()); + } i += 2; } else
View file
lightspark.tar.xz/src/backends/xml_support.cpp
Changed
@@ -61,7 +61,7 @@ if(!context_->wellFormed) LOG(LOG_ERROR, "XML data not well formed!"); - if (context_->myDoc) + if (context_->wellFormed && context_->myDoc) doc_ = new RecoveryDocument(context_->myDoc); // This is to indicate to release_underlying that we took the // ownership on the doc. @@ -86,13 +86,17 @@ } catch(const exception& e) { + LOG(LOG_ERROR,"xml error: "<<e.what()); } xmlpp::Document* doc=parser.get_document(); if(doc) { + xmlpp::Node *root = NULL; if (!doc->get_root_node()) { - buf = removeWhitespace(str)+"<parent></parent>"; + buf="<parent>"; + buf += str; + buf += "</parent>"; try { parser.parse_memory_raw((const unsigned char*)buf.c_str(), buf.size()); @@ -101,11 +105,33 @@ { } doc=parser.get_document(); + if (doc && doc->get_root_node()) + { + root = doc->get_root_node()->get_first_child(); + } + } + if (!doc || !doc->get_root_node()) + { + try + { + buf="<parent>"; + buf += XMLBase::encodeToXML(str,false); + buf += "</parent>"; + parser.parse_memory_raw((const unsigned char*)buf.c_str(), buf.size()); + } + catch(const exception& e) + { + } + doc=parser.get_document(); + if (doc && doc->get_root_node()) + { + root = doc->get_root_node()->get_first_child(); + } } if (doc && doc->get_root_node()) { *hasParent = true; - xmlpp::Element *root = doc->get_root_node(); + if (root==NULL) root = doc->get_root_node(); // It would be better to remove empty nodes during // parsing, but xmlpp doesn't offer an interface. if (ignoreEmptyTextNodes) @@ -116,6 +142,7 @@ } //If everything fails, create a fake document and add a single text string child // see 10.3.1 in ECMA 357 + if (default_ns.empty()) buf="<parent></parent>"; else @@ -125,8 +152,46 @@ *hasParent = false; return parser.get_document()->get_root_node()->add_child_text(str); } +const tiny_string XMLBase::encodeToXML(const tiny_string value, bool bIsAttribute) +{ + + tiny_string res; + auto it = value.begin(); + while (it != value.end()) + { + switch (*it) + { + case '<': + res += "<"; + break; + case '>': + res += bIsAttribute ? ">" : ">"; + break; + case '&': + res += "&"; + break; + case '\"': + res += bIsAttribute ? """ : "\""; + break; + case '\r': + res += bIsAttribute ? "
" : "\r"; + break; + case '\n': + res += bIsAttribute ? "
" : "\n"; + break; + case '\t': + res += bIsAttribute ? "	" : "\t"; + break; + default: + res += *it; + break; + } + it++; + } + return res; +} -void XMLBase::addDefaultNamespace(xmlpp::Element *root, const string& default_ns) +void XMLBase::addDefaultNamespace(xmlpp::Node *root, const string& default_ns) { if(default_ns.empty() || !root->get_namespace_uri().empty()) return; @@ -190,10 +255,10 @@ string XMLBase::quirkCData(const string& str) { //if this is a CDATA node replace CDATA tags to make it look like a text-node //for compatibility with the Adobe player - if (str.compare(0, 9, "<![CDATA[") == 0) { - return "<a>"+str.substr(9, str.size()-12)+"</a>"; - } - else + //if (str.compare(0, 9, "<![CDATA[") == 0) { + // return "<a>"+str.substr(9, str.size()-12)+"</a>"; + //} + //else return str; } @@ -219,7 +284,7 @@ return buf; } -void XMLBase::removeWhitespaceNodes(xmlpp::Element *node) +void XMLBase::removeWhitespaceNodes(xmlpp::Node *node) { xmlpp::Node::NodeList children = node->get_children(); xmlpp::Node::NodeList::iterator it;
View file
lightspark.tar.xz/src/backends/xml_support.h
Changed
@@ -60,16 +60,17 @@ bool ignoreEmptyTextnodes, bool *hasParent, const std::string& default_ns=std::string()); - void addDefaultNamespace(xmlpp::Element *root, const std::string& default_ns); + void addDefaultNamespace(xmlpp::Node *root, const std::string& default_ns); void addDefaultNamespaceRecursive(xmlNodePtr node, xmlNsPtr ns); // Set the root to be a copy of src. If src is a text node, // create a new element node with the same content. xmlpp::Node* buildCopy(const xmlpp::Node* node, bool *hasParent); static std::string quirkCData(const std::string& str); static std::string quirkXMLDeclarationInMiddle(const std::string& str); - void removeWhitespaceNodes(xmlpp::Element *node); + void removeWhitespaceNodes(xmlpp::Node *node); tiny_string removeWhitespace(tiny_string val); public: + static const tiny_string encodeToXML(const tiny_string value, bool bIsAttribute); static std::string parserQuirks(const std::string& str); };
View file
lightspark.tar.xz/src/main.cpp
Changed
@@ -147,6 +147,8 @@ } else if(strcmp(argv[i],"--air")==0) flashMode=SystemState::AIR; + else if(strcmp(argv[i],"--avmplus")==0) + flashMode=SystemState::AVMPLUS; else if(strcmp(argv[i],"-ni")==0 || strcmp(argv[i],"--disable-interpreter")==0) useInterpreter=false; else if(strcmp(argv[i],"-fi")==0 || strcmp(argv[i],"--enable-fast-interpreter")==0) @@ -242,7 +244,7 @@ LOG(LOG_ERROR, "Usage: " << argv[0] << " [--url|-u http://loader.url/file.swf]" << " [--disable-interpreter|-ni] [--enable-fast-interpreter|-fi] [--enable-jit|-j]" << " [--log-level|-l 0-4] [--parameters-file|-p params-file] [--security-sandbox|-s sandbox]" << - " [--exit-on-error] [--HTTP-cookies cookie] [--air]" << + " [--exit-on-error] [--HTTP-cookies cookie] [--air] [--avmplus]" << #ifdef PROFILING_SUPPORT " [--profiling-output|-o profiling-file]" << #endif
View file
lightspark.tar.xz/src/parsing/amf3_generator.cpp
Changed
@@ -17,16 +17,19 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. **************************************************************************/ +#include "scripting/abc.h" #include "parsing/amf3_generator.h" #include "scripting/toplevel/toplevel.h" #include "scripting/toplevel/Array.h" #include "scripting/toplevel/ASString.h" +#include "scripting/toplevel/Date.h" #include "scripting/class.h" #include "scripting/flash/xml/flashxml.h" #include "toplevel/XML.h" #include <iostream> #include <fstream> #include "scripting/flash/utils/ByteArray.h" +#include "scripting/flash/utils/Dictionary.h" using namespace std; using namespace lightspark; @@ -65,6 +68,26 @@ return _MR(abstract_d(tmp.val)); } +_R<ASObject> Amf3Deserializer::parseDate() const +{ + union + { + uint64_t dummy; + double val; + } tmp; + uint8_t* tmpPtr=reinterpret_cast<uint8_t*>(&tmp.dummy); + + for(uint32_t i=0;i<8;i++) + { + if(!input->readByte(tmpPtr[i])) + throw ParseException("Not enough data to parse date"); + } + tmp.dummy=GINT64_FROM_BE(tmp.dummy); + Date* dt = Class<Date>::getInstanceS(); + dt->MakeDateFromMilliseconds((int64_t)tmp.val); + return _MR(dt); +} + tiny_string Amf3Deserializer::parseStringVR(std::vector<tiny_string>& stringMap) const { uint32_t strRef; @@ -138,6 +161,190 @@ return ret; } +_R<ASObject> Amf3Deserializer::parseVector(uint8_t marker, std::vector<tiny_string>& stringMap, + std::vector<ASObject*>& objMap, + std::vector<TraitsRef>& traitsMap) const +{ + uint32_t vectorRef; + if(!input->readU29(vectorRef)) + throw ParseException("Not enough data to parse AMF3 vector"); + + if((vectorRef&0x01)==0) + { + //Just a reference + if(objMap.size() <= (vectorRef >> 1)) + throw ParseException("Invalid object reference in AMF3 data"); + ASObject* ret=objMap[vectorRef >> 1]; + ret->incRef(); + return _MR(ret); + } + + uint8_t b; + if (!input->readByte(b)) + throw ParseException("Not enough data to parse AMF3 vector"); + const Type* type =NULL; + switch (marker) + { + case vector_int_marker: + type = Class<Integer>::getClass(); + break; + case vector_uint_marker: + type = Class<UInteger>::getClass(); + break; + case vector_double_marker: + type = Class<Number>::getClass(); + break; + case vector_object_marker: + { + tiny_string vectypename; + vectypename = parseStringVR(stringMap); + multiname m(NULL); + m.name_type=multiname::NAME_STRING; + m.name_s_id=getSys()->getUniqueStringId(vectypename); + m.ns.push_back(nsNameAndKind("",NAMESPACE)); + m.isAttribute = false; + type = Type::getTypeFromMultiname(&m,getVm()->currentCallContext->context); + if (type == NULL) + { + LOG(LOG_ERROR,"unknown vector type during deserialization:"<<m); + type = Class<ASObject>::getClass(); + } + break; + } + default: + LOG(LOG_ERROR,"invalid marker during deserialization of vector:"<<marker); + throw ParseException("invalid marker in AMF3 vector"); + + } + _R<lightspark::Vector> ret=_MR(Template<Vector>::getInstanceS(type)); + //Add object to the map + objMap.push_back(ret.getPtr()); + + + int32_t count = vectorRef >> 1; + + for(int32_t i=0;i<count;i++) + { + switch (marker) + { + case vector_int_marker: + { + uint32_t value = 0; + if (!input->readUnsignedInt(value)) + throw ParseException("Not enough data to parse AMF3 vector"); + ret->append(abstract_i(value)); + break; + } + case vector_uint_marker: + { + uint32_t value = 0; + if (!input->readUnsignedInt(value)) + throw ParseException("Not enough data to parse AMF3 vector"); + ret->append(abstract_ui(value)); + break; + } + case vector_double_marker: + { + _R<ASObject> v = parseDouble(); + v->incRef(); + ret->append(v.getPtr()); + break; + } + case vector_object_marker: + { + _R<ASObject> value=parseValue(stringMap, objMap, traitsMap); + value->incRef(); + ret->append(value.getPtr()); + break; + } + } + } + // set fixed at last to avoid rangeError + ret->setFixed(b == 0x01); + return ret; +} + + +_R<ASObject> Amf3Deserializer::parseDictionary(std::vector<tiny_string>& stringMap, + std::vector<ASObject*>& objMap, + std::vector<TraitsRef>& traitsMap) const +{ + uint32_t dictRef; + if(!input->readU29(dictRef)) + throw ParseException("Not enough data to parse AMF3 dictionary"); + + if((dictRef&0x01)==0) + { + //Just a reference + if(objMap.size() <= (dictRef >> 1)) + throw ParseException("Invalid object reference in AMF3 data"); + ASObject* ret=objMap[dictRef >> 1]; + ret->incRef(); + return _MR(ret); + } + + uint8_t weakkeys; + if (!input->readByte(weakkeys)) + throw ParseException("Not enough data to parse AMF3 vector"); + if (weakkeys) + LOG(LOG_NOT_IMPLEMENTED,"handling of weak keys in Dictionary"); + _R<Dictionary> ret=_MR(Class<Dictionary>::getInstanceS()); + //Add object to the map + objMap.push_back(ret.getPtr()); + + + int32_t count = dictRef >> 1; + + for(int32_t i=0;i<count;i++) + { + _R<ASObject> key=parseValue(stringMap, objMap, traitsMap); + _R<ASObject> value=parseValue(stringMap, objMap, traitsMap); + multiname name(NULL); + name.name_type=multiname::NAME_OBJECT; + name.name_o = key.getPtr(); + name.ns.push_back(nsNameAndKind("",NAMESPACE)); + key->incRef(); + value->incRef(); + ret->setVariableByMultiname(name,value.getPtr(),ASObject::CONST_ALLOWED); + } + return ret; +} + +_R<ASObject> Amf3Deserializer::parseByteArray(std::vector<tiny_string>& stringMap, + std::vector<ASObject*>& objMap, + std::vector<TraitsRef>& traitsMap) const +{ + uint32_t bytearrayRef; + if(!input->readU29(bytearrayRef)) + throw ParseException("Not enough data to parse AMF3 bytearray"); + + if((bytearrayRef&0x01)==0) + { + //Just a reference + if(objMap.size() <= (bytearrayRef >> 1)) + throw ParseException("Invalid object reference in AMF3 data"); + ASObject* ret=objMap[bytearrayRef >> 1]; + ret->incRef(); + return _MR(ret); + } + + _R<ByteArray> ret=_MR(Class<ByteArray>::getInstanceS()); + //Add object to the map + objMap.push_back(ret.getPtr()); + + + int32_t count = bytearrayRef >> 1; + + for(int32_t i=0;i<count;i++) + { + uint8_t b; + if (!input->readByte(b)) + throw ParseException("Not enough data to parse AMF3 bytearray"); + ret->writeByte(b); + } + return ret; +} + _R<ASObject> Amf3Deserializer::parseObject(std::vector<tiny_string>& stringMap, std::vector<ASObject*>& objMap, std::vector<TraitsRef>& traitsMap) const @@ -299,6 +506,8 @@ return parseInteger(); case double_marker: return parseDouble(); + case date_marker: + return parseDate(); case string_marker: return _MR(Class<ASString>::getInstanceS(parseStringVR(stringMap))); case xml_doc_marker: @@ -309,6 +518,15 @@ return parseObject(stringMap, objMap, traitsMap); case xml_marker: return parseXML(objMap, false); + case byte_array_marker: + return parseByteArray(stringMap, objMap, traitsMap); + case vector_int_marker: + case vector_uint_marker: + case vector_double_marker: + case vector_object_marker: + return parseVector(marker, stringMap, objMap, traitsMap); + case dictionary_marker: + return parseDictionary(stringMap, objMap, traitsMap); default: LOG(LOG_ERROR,"Unsupported marker " << (uint32_t)marker); throw UnsupportedException("Unsupported marker");
View file
lightspark.tar.xz/src/parsing/amf3_generator.h
Changed
@@ -46,8 +46,14 @@ xml_doc_marker = 0x7, date_marker = 0x8, array_marker = 0x9, - object_marker = 0xa, - xml_marker = 0xb + object_marker = 0xA, + xml_marker = 0xB, + byte_array_marker = 0x0C, + vector_int_marker = 0x0D, + vector_uint_marker = 0x0E, + vector_double_marker = 0x0F, + vector_object_marker = 0x10, + dictionary_marker = 0x11 }; enum amf0_markers_type @@ -93,11 +99,21 @@ _R<ASObject> parseArray(std::vector<tiny_string>& stringMap, std::vector<ASObject*>& objMap, std::vector<TraitsRef>& traitsMap) const; + _R<ASObject> parseVector(uint8_t marker, std::vector<tiny_string>& stringMap, + std::vector<ASObject*>& objMap, + std::vector<TraitsRef>& traitsMap) const; + _R<ASObject> parseDictionary(std::vector<tiny_string>& stringMap, + std::vector<ASObject*>& objMap, + std::vector<TraitsRef>& traitsMap) const; + _R<ASObject> parseByteArray(std::vector<tiny_string>& stringMap, + std::vector<ASObject*>& objMap, + std::vector<TraitsRef>& traitsMap) const; _R<ASObject> parseValue(std::vector<tiny_string>& stringMap, std::vector<ASObject*>& objMap, std::vector<TraitsRef>& traitsMap) const; _R<ASObject> parseInteger() const; _R<ASObject> parseDouble() const; + _R<ASObject> parseDate() const; _R<ASObject> parseXML(std::vector<ASObject*>& objMap, bool legacyXML) const;
View file
lightspark.tar.xz/src/scripting/abc.cpp
Changed
@@ -101,6 +101,7 @@ #include "scripting/flash/system/flashsystem.h" #include "scripting/flash/sensors/flashsensors.h" #include "scripting/flash/utils/flashutils.h" +#include "scripting/flash/utils/CompressionAlgorithm.h" #include "scripting/flash/utils/Dictionary.h" #include "scripting/flash/utils/Proxy.h" #include "scripting/flash/utils/Timer.h" @@ -116,6 +117,7 @@ #include "scripting/flash/ui/ContextMenu.h" #include "scripting/flash/ui/ContextMenuItem.h" #include "scripting/flash/ui/ContextMenuBuiltInItems.h" +#include "scripting/avmplus/avmplus.h" #include "scripting/class.h" #include "exceptions.h" #include "scripting/abc.h" @@ -376,6 +378,7 @@ builtin->registerBuiltin("Endian","flash.utils",Class<Endian>::getRef()); builtin->registerBuiltin("ByteArray","flash.utils",Class<ByteArray>::getRef()); + builtin->registerBuiltin("CompressionAlgorithm","flash.utils",Class<CompressionAlgorithm>::getRef()); builtin->registerBuiltin("Dictionary","flash.utils",Class<Dictionary>::getRef()); builtin->registerBuiltin("Proxy","flash.utils",Class<Proxy>::getRef()); builtin->registerBuiltin("Timer","flash.utils",Class<Timer>::getRef()); @@ -508,7 +511,6 @@ builtin->registerBuiltin("isFinite","",_MR(Class<IFunction>::getFunction(isFinite,1))); builtin->registerBuiltin("isXMLName","",_MR(Class<IFunction>::getFunction(_isXMLName))); - //If needed add AIR definitions if(getSys()->flashMode==SystemState::AIR) { @@ -519,6 +521,32 @@ builtin->registerBuiltin("FileStream","flash.filesystem",Class<FileStream>::getRef()); } + // if needed add AVMPLUS definitions + if(getSys()->flashMode==SystemState::AVMPLUS) + { + builtin->registerBuiltin("getQualifiedClassName","avmplus",_MR(Class<IFunction>::getFunction(getQualifiedClassName))); + builtin->registerBuiltin("getQualifiedSuperclassName","avmplus",_MR(Class<IFunction>::getFunction(getQualifiedSuperclassName))); + builtin->registerBuiltin("getTimer","",_MR(Class<IFunction>::getFunction(getTimer))); + builtin->registerBuiltin("FLASH10_FLAGS","avmplus",_MR(abstract_ui(0x7FF))); + builtin->registerBuiltin("describeType","avmplus",_MR(Class<IFunction>::getFunction(describeType))); + + builtin->registerBuiltin("System","avmplus",Class<avmplusSystem>::getRef()); + builtin->registerBuiltin("Domain","avmplus",Class<avmplusDomain>::getRef()); + builtin->registerBuiltin("File","avmplus",Class<avmplusFile>::getRef()); + + builtin->registerBuiltin("AbstractBase","avmshell",Class<ASObject>::getRef()); + builtin->registerBuiltin("AbstractRestrictedBase","avmshell",Class<ASObject>::getRef()); + builtin->registerBuiltin("NativeBase","avmshell",Class<ASObject>::getRef()); + builtin->registerBuiltin("NativeBaseAS3","avmshell",Class<ASObject>::getRef()); + builtin->registerBuiltin("NativeSubclassOfAbstractBase","avmshell",Class<ASObject>::getRef()); + builtin->registerBuiltin("NativeSubclassOfAbstractRestrictedBase","avmshell",Class<ASObject>::getRef()); + builtin->registerBuiltin("NativeSubclassOfRestrictedBase","avmshell",Class<ASObject>::getRef()); + builtin->registerBuiltin("RestrictedBase","avmshell",Class<ASObject>::getRef()); + builtin->registerBuiltin("SubclassOfAbstractBase","avmshell",Class<ASObject>::getRef()); + builtin->registerBuiltin("SubclassOfAbstractRestrictedBase","avmshell",Class<ASObject>::getRef()); + builtin->registerBuiltin("SubclassOfRestrictedBase","avmshell",Class<ASObject>::getRef()); + } + Class_object::getRef()->getClass()->prototype = _MNR(new_objectPrototype()); Class_object::getRef()->getClass()->initStandardProps(); @@ -1387,7 +1415,7 @@ derived_class_tmp->bindToTag(t); } -inline method_info* ABCContext::get_method(unsigned int m) +method_info* ABCContext::get_method(unsigned int m) { if(m<method_count) return &methods[m]; @@ -2038,7 +2066,7 @@ { multiname* mname=getMultiname(t->name,NULL); //Should be a Qname - assert_and_throw(mname->ns.size()==1 && mname->name_type==multiname::NAME_STRING); + assert_and_throw(mname->name_type==multiname::NAME_STRING); if(t->kind>>4) LOG(LOG_CALLS,_("Next slot has flags ") << (t->kind>>4));
View file
lightspark.tar.xz/src/scripting/abc.h
Changed
@@ -256,28 +256,49 @@ _R<ApplicationDomain> appDomain = getCurrentApplicationDomain(th); appDomain->writeToDomainMemory<T>(addr, val); } + static void loadFloat(call_context* th) + { + ASObject* arg1=th->runtime_stack_pop(); + float addr=arg1->toNumber(); + arg1->decRef(); + _R<ApplicationDomain> appDomain = getCurrentApplicationDomain(th); + number_t ret=appDomain->readFromDomainMemory<float>(addr); + th->runtime_stack_push(abstract_d(ret)); + } - static void loadNumber(call_context* th) + static void loadDouble(call_context* th) { ASObject* arg1=th->runtime_stack_pop(); - number_t addr=arg1->toNumber(); + double addr=arg1->toNumber(); arg1->decRef(); _R<ApplicationDomain> appDomain = getCurrentApplicationDomain(th); - number_t ret=appDomain->readFromDomainMemory<number_t>(addr); + number_t ret=appDomain->readFromDomainMemory<double>(addr); th->runtime_stack_push(abstract_d(ret)); } - static void storeNumber(call_context* th) + static void storeFloat(call_context* th) + { + ASObject* arg1=th->runtime_stack_pop(); + ASObject* arg2=th->runtime_stack_pop(); + number_t addr=arg1->toNumber(); + arg1->decRef(); + float val=(float)arg2->toNumber(); + arg2->decRef(); + _R<ApplicationDomain> appDomain = getCurrentApplicationDomain(th); + appDomain->writeToDomainMemory<float>(addr, val); + } + static void storeDouble(call_context* th) { ASObject* arg1=th->runtime_stack_pop(); ASObject* arg2=th->runtime_stack_pop(); number_t addr=arg1->toNumber(); arg1->decRef(); - number_t val=arg2->toNumber(); + double val=arg2->toNumber(); arg2->decRef(); _R<ApplicationDomain> appDomain = getCurrentApplicationDomain(th); - appDomain->writeToDomainMemory<number_t>(addr, val); + appDomain->writeToDomainMemory<double>(addr, val); } + static void callStatic(call_context* th, int n, int m, method_info** called_mi, bool keepReturn); static void callSuper(call_context* th, int n, int m, method_info** called_mi, bool keepReturn); static void callProperty(call_context* th, int n, int m, method_info** called_mi, bool keepReturn); static void callImpl(call_context* th, ASObject* f, ASObject* obj, ASObject** args, int m, method_info** called_mi, bool keepReturn);
View file
lightspark.tar.xz/src/scripting/abc_fast_interpreter.cpp
Changed
@@ -575,14 +575,14 @@ { //lf32 LOG(LOG_CALLS, "lf32"); - loadNumber(context); + loadFloat(context); break; } case 0x39: { //lf32 LOG(LOG_CALLS, "lf64"); - loadNumber(context); + loadDouble(context); break; } case 0x3a: @@ -606,6 +606,20 @@ storeIntN<uint32_t>(context); break; } + case 0x3d: + { + //sf32 + LOG(LOG_CALLS, "sf32"); + storeFloat(context); + break; + } + case 0x3e: + { + //sf32 + LOG(LOG_CALLS, "sf64"); + storeDouble(context); + break; + } case 0x40: { //newfunction @@ -634,6 +648,20 @@ instructionPointer+=4; break; } + case 0x44: + { + //callstatic + uint32_t t=data->uints[0]; + uint32_t t2=data->uints[1]; + method_info* called_mi=NULL; + PROF_ACCOUNT_TIME(mi->profTime[instructionPointer],profilingCheckpoint(startTime)); + callStatic(context,t,t2,&called_mi,true); + if(called_mi) + PROF_ACCOUNT_TIME(mi->profCalls[called_mi],profilingCheckpoint(startTime)); + else + PROF_IGNORE_TIME(profilingCheckpoint(startTime)); + break; + } case 0x45: { //callsuper @@ -726,6 +754,36 @@ instructionPointer+=8; break; } + case 0x50: + { + //sxi1 + LOG(LOG_CALLS, "sxi1"); + ASObject* arg1=context->runtime_stack_pop(); + int32_t ret=arg1->toUInt() & 0x1; + arg1->decRef(); + context->runtime_stack_push(abstract_i(ret)); + break; + } + case 0x51: + { + //sxi8 + LOG(LOG_CALLS, "sxi8"); + ASObject* arg1=context->runtime_stack_pop(); + int32_t ret=(int8_t)arg1->toUInt(); + arg1->decRef(); + context->runtime_stack_push(abstract_i(ret)); + break; + } + case 0x52: + { + //sxi16 + LOG(LOG_CALLS, "sxi16"); + ASObject* arg1=context->runtime_stack_pop(); + int32_t ret=(int16_t)arg1->toUInt(); + arg1->decRef(); + context->runtime_stack_push(abstract_i(ret)); + break; + } case 0x53: { //constructgenerictype @@ -841,7 +899,7 @@ LOG(LOG_CALLS, _("setLocal ") << i ); ASObject* obj=context->runtime_stack_pop(); assert_and_throw(obj); - if ((int)i != context->argarrayposition) + if ((int)i != context->argarrayposition || obj->is<Array>()) { if(context->locals[i]) context->locals[i]->decRef(); @@ -1445,7 +1503,7 @@ int i=opcode&3; LOG(LOG_CALLS, "setLocal " << i ); ASObject* obj=context->runtime_stack_pop(); - if ((int)i != context->argarrayposition) + if ((int)i != context->argarrayposition || obj->is<Array>()) { if(context->locals[i]) context->locals[i]->decRef();
View file
lightspark.tar.xz/src/scripting/abc_interpreter.cpp
Changed
@@ -673,14 +673,14 @@ { //lf32 LOG(LOG_CALLS, "lf32"); - loadNumber(context); + loadFloat(context); break; } case 0x39: { //lf32 LOG(LOG_CALLS, "lf64"); - loadNumber(context); + loadDouble(context); break; } case 0x3a: @@ -708,14 +708,14 @@ { //sf32 LOG(LOG_CALLS, "sf32"); - storeNumber(context); + storeFloat(context); break; } case 0x3e: { //sf32 LOG(LOG_CALLS, "sf64"); - storeNumber(context); + storeDouble(context); break; } case 0x40: @@ -748,6 +748,21 @@ construct(context,t); break; } + case 0x44: + { + //callstatic + u30 t,t2; + code >> t; + code >> t2; + method_info* called_mi=NULL; + PROF_ACCOUNT_TIME(mi->profTime[instructionPointer],profilingCheckpoint(startTime)); + callStatic(context,t,t2,&called_mi,true); + if(called_mi) + PROF_ACCOUNT_TIME(mi->profCalls[called_mi],profilingCheckpoint(startTime)); + else + PROF_IGNORE_TIME(profilingCheckpoint(startTime)); + break; + } case 0x45: { //callsuper @@ -841,6 +856,36 @@ PROF_IGNORE_TIME(profilingCheckpoint(startTime)); break; } + case 0x50: + { + //sxi1 + LOG(LOG_CALLS, "sxi1"); + ASObject* arg1=context->runtime_stack_pop(); + int32_t ret=arg1->toUInt() >>31; + arg1->decRef(); + context->runtime_stack_push(abstract_i(ret)); + break; + } + case 0x51: + { + //sxi8 + LOG(LOG_CALLS, "sxi8"); + ASObject* arg1=context->runtime_stack_pop(); + int32_t ret=(int8_t)arg1->toUInt(); + arg1->decRef(); + context->runtime_stack_push(abstract_i(ret)); + break; + } + case 0x52: + { + //sxi16 + LOG(LOG_CALLS, "sxi16"); + ASObject* arg1=context->runtime_stack_pop(); + int32_t ret=(int16_t)arg1->toUInt(); + arg1->decRef(); + context->runtime_stack_push(abstract_i(ret)); + break; + } case 0x53: { //constructgenerictype @@ -962,7 +1007,7 @@ LOG(LOG_CALLS, _("setLocal ") << i ); ASObject* obj=context->runtime_stack_pop(); assert_and_throw(obj); - if ((int)i != context->argarrayposition) + if ((int)i != context->argarrayposition || obj->is<Array>()) { if(context->locals[i]) context->locals[i]->decRef(); @@ -1005,8 +1050,8 @@ u30 t; code >> t; ASObject* value=context->runtime_stack_pop(); - multiname* name=context->context->getMultiname(t,context); - ASObject* obj=context->runtime_stack_pop(); + multiname* name=context->context->getMultiname(t,context); + ASObject* obj=context->runtime_stack_pop(); initProperty(obj,value,name); name->resetNameIfObject(); break; @@ -1554,7 +1599,7 @@ int i=opcode&3; LOG(LOG_CALLS, _("setLocal ") << i); ASObject* obj=context->runtime_stack_pop(); - if ((int)i != context->argarrayposition) + if ((int)i != context->argarrayposition || obj->is<Array>()) { if(context->locals[i]) context->locals[i]->decRef();
View file
lightspark.tar.xz/src/scripting/abc_opcodes.cpp
Changed
@@ -398,7 +398,10 @@ throwError<ReferenceError>(kWriteOnlyError, name->normalizedName(), obj->getClass()->getQualifiedClassName()); if (obj->getClass() && obj->getClass()->isSealed) throwError<ReferenceError>(kReadSealedError, name->normalizedName(), obj->getClass()->getQualifiedClassName()); - throwError<TypeError>(kCallNotFoundError, name->qualifiedString(), obj->getClassName()); + if (obj->is<Class_base>()) + throwError<TypeError>(kCallNotFoundError, name->qualifiedString(), obj->as<Class_base>()->class_name.getQualifiedName()); + else + throwError<TypeError>(kCallNotFoundError, name->qualifiedString(), obj->getClassName()); if(keepReturn) th->runtime_stack_push(getSys()->getUndefinedRef()); @@ -433,7 +436,7 @@ ASObject* ABCVm::getProperty(ASObject* obj, multiname* name) { - LOG(LOG_CALLS, _("getProperty ") << *name << ' ' << obj << ' '<<obj->isInitialized()); + LOG(LOG_CALLS, _("getProperty ") << *name << ' ' << obj->toDebugString() << ' '<<obj->isInitialized()); checkDeclaredTraits(obj); _NR<ASObject> prop=obj->getVariableByMultiname(*name); @@ -447,8 +450,8 @@ throwError<ReferenceError>(kReadSealedErrorNs, name->normalizedNameUnresolved(), obj->getClassName()); if (obj->is<Undefined>()) throwError<TypeError>(kConvertUndefinedToObjectError); - if (Log::getLevel() >= LOG_NOT_IMPLEMENTED && obj->getClassName() != "Object") - LOG(LOG_NOT_IMPLEMENTED,"getProperty: " << name->normalizedNameUnresolved() << " not found on " << obj->toDebugString()); + if (Log::getLevel() >= LOG_NOT_IMPLEMENTED && (!obj->getClass() || obj->getClass()->isSealed)) + LOG(LOG_NOT_IMPLEMENTED,"getProperty: " << name->normalizedNameUnresolved() << " not found on " << obj->toDebugString() << " "<<obj->getClassName()); ret = getSys()->getUndefinedRef(); } else @@ -1558,6 +1561,44 @@ obj->decRef(); } +void ABCVm::callStatic(call_context* th, int n, int m, method_info** called_mi, bool keepReturn) +{ + ASObject** args=g_newa(ASObject*, m); + for(int i=0;i<m;i++) + args[m-i-1]=th->runtime_stack_pop(); + + ASObject* obj=th->runtime_stack_pop(); + if(obj->is<Null>()) + { + LOG(LOG_ERROR,"trying to callStatic on null"); + throwError<TypeError>(kConvertNullToObjectError); + } + if (obj->is<Undefined>()) + { + LOG(LOG_ERROR,"trying to callStatic on undefined"); + throwError<TypeError>(kConvertUndefinedToObjectError); + } + method_info* mi = th->context->get_method(n); + assert_and_throw(mi); + SyntheticFunction* f=Class<IFunction>::getSyntheticFunction(mi); + + if(f) + { + f->incRef(); + callImpl(th, f, obj, args, m, called_mi, keepReturn); + } + else + { + obj->decRef(); + for(int i=0;i<m;i++) + args[i]->decRef(); + throwError<ReferenceError>(kCallNotFoundError, "?", obj->getClassName()); + if(keepReturn) + th->runtime_stack_push(getSys()->getUndefinedRef()); + } + LOG(LOG_CALLS,"End of callStatic "); +} + void ABCVm::callSuper(call_context* th, int n, int m, method_info** called_mi, bool keepReturn) { ASObject** args=g_newa(ASObject*, m); @@ -1785,6 +1826,9 @@ bool ABCVm::in(ASObject* val2, ASObject* val1) { LOG(LOG_CALLS, _("in") ); + if(val2->is<Null>()) + throwError<TypeError>(kConvertNullToObjectError); + multiname name(NULL); name.name_type=multiname::NAME_OBJECT; //Acquire the reference @@ -1826,6 +1870,11 @@ for(int i=0;i<m;++i) args[i]->decRef(); obj->decRef(); + if (obj->is<Undefined>()) + throwError<TypeError>(kConvertUndefinedToObjectError); + if (obj->isPrimitive()) + throwError<TypeError>(kConstructOfNonFunctionError); + throwError<ReferenceError>(kUndefinedVarError, name->normalizedNameUnresolved()); } @@ -1940,7 +1989,7 @@ { multiname callPropertyName(NULL); callPropertyName.name_type=multiname::NAME_STRING; - callPropertyName.name_s_id=getSys()->getUniqueStringId("callProperty"); + callPropertyName.name_s_id=getSys()->getUniqueStringId("getDescendants"); callPropertyName.ns.push_back(nsNameAndKind(flash_proxy,NAMESPACE)); _NR<ASObject> o=obj->getVariableByMultiname(callPropertyName,ASObject::SKIP_IMPL); @@ -1950,17 +1999,16 @@ IFunction* f=static_cast<IFunction*>(o.getPtr()); //Create a new array - ASObject** proxyArgs=g_newa(ASObject*, 2); - proxyArgs[0]=Class<ASString>::getInstanceS("descendants"); + ASObject** proxyArgs=g_newa(ASObject*, 1); ASObject* namearg = Class<ASString>::getInstanceS(name->normalizedName()); namearg->setProxyProperty(*name); - proxyArgs[1]=namearg; + proxyArgs[0]=namearg; //We now suppress special handling - LOG(LOG_CALLS,_("Proxy::callProperty")); + LOG(LOG_CALLS,_("Proxy::getDescendants")); f->incRef(); obj->incRef(); - ASObject* ret=f->call(obj,proxyArgs,2); + ASObject* ret=f->call(obj,proxyArgs,1); f->decRef(); th->runtime_stack_push(ret); @@ -2177,7 +2225,7 @@ #ifdef PROFILING_SUPPORT if(!constructor->validProfName) { - constructor->profName=mname->name_s+"::__CONSTRUCTOR__"; + constructor->profName=mname->normalizedName()+"::__CONSTRUCTOR__"; constructor->validProfName=true; } #endif @@ -2482,9 +2530,6 @@ */ bool ABCVm::instanceOf(ASObject* value, ASObject* type) { - if(value->is<Null>()) - return false; - if(type->is<IFunction>()) { IFunction* t=static_cast<IFunction*>(type); @@ -2504,6 +2549,10 @@ if(!type->is<Class_base>()) throwError<TypeError>(kCantUseInstanceofOnNonObjectError); + if(value->is<Null>()) + return false; + + if(value->is<Class_base>()) // Classes are instance of Class and Object but not // itself or super classes
View file
lightspark.tar.xz/src/scripting/avmplus
Added
+(directory)
View file
lightspark.tar.xz/src/scripting/avmplus/avmplus.cpp
Added
@@ -0,0 +1,223 @@ +/************************************************************************** + Lightspark, a free flash player implementation + + Copyright (C) 2009-2013 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 Lesser 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +**************************************************************************/ + +#include "scripting/avmplus/avmplus.h" +#include "scripting/flash/utils/ByteArray.h" +#include "scripting/class.h" +#include "scripting/argconv.h" + +using namespace lightspark; + +avmplusFile::avmplusFile(Class_base* c): + ASObject(c) +{ +} + +void avmplusFile::sinit(Class_base* c) +{ + CLASS_SETUP_NO_CONSTRUCTOR(c, ASObject, CLASS_SEALED); + c->setDeclaredMethodByQName("exists","",Class<IFunction>::getFunction(exists),NORMAL_METHOD,false); + c->setDeclaredMethodByQName("read","",Class<IFunction>::getFunction(read),NORMAL_METHOD,false); + c->setDeclaredMethodByQName("write","",Class<IFunction>::getFunction(write),NORMAL_METHOD,false); + c->setDeclaredMethodByQName("readByteArray","",Class<IFunction>::getFunction(readByteArray),NORMAL_METHOD,false); + c->setDeclaredMethodByQName("writeByteArray","",Class<IFunction>::getFunction(writeByteArray),NORMAL_METHOD,false); +} + +ASFUNCTIONBODY(avmplusFile,exists) +{ + LOG(LOG_NOT_IMPLEMENTED, _("avmplus.File.exists is unimplemented.")); + return NULL; +} +ASFUNCTIONBODY(avmplusFile,read) +{ + LOG(LOG_NOT_IMPLEMENTED, _("avmplus.File.read is unimplemented.")); + return NULL; +} +ASFUNCTIONBODY(avmplusFile,write) +{ + LOG(LOG_NOT_IMPLEMENTED, _("avmplus.File.write is unimplemented.")); + return NULL; +} +ASFUNCTIONBODY(avmplusFile,readByteArray) +{ + avmplusFile* th=static_cast<avmplusFile*>(obj); + tiny_string filename; + ARG_UNPACK(filename); + + LOG(LOG_NOT_IMPLEMENTED, _("avmplus.File.readByteArray is unimplemented.")); + return Class<ByteArray>::getInstanceS(); +} +ASFUNCTIONBODY(avmplusFile,writeByteArray) +{ + LOG(LOG_NOT_IMPLEMENTED, _("avmplus.File.writeByteArray is unimplemented.")); + return NULL; +} + +avmplusSystem::avmplusSystem(Class_base* c): + ASObject(c) +{ +} + +void avmplusSystem::sinit(Class_base* c) +{ + CLASS_SETUP_NO_CONSTRUCTOR(c, ASObject, CLASS_SEALED); + c->setDeclaredMethodByQName("getFeatures","",Class<IFunction>::getFunction(getFeatures),NORMAL_METHOD,false); + c->setDeclaredMethodByQName("queueCollection","",Class<IFunction>::getFunction(queueCollection),NORMAL_METHOD,false); + c->setDeclaredMethodByQName("forceFullCollection","",Class<IFunction>::getFunction(forceFullCollection),NORMAL_METHOD,false); + c->setDeclaredMethodByQName("getAvmplusVersion","",Class<IFunction>::getFunction(getAvmplusVersion),NORMAL_METHOD,false); + c->setDeclaredMethodByQName("pauseForGCIfCollectionImminent","",Class<IFunction>::getFunction(pauseForGCIfCollectionImminent),NORMAL_METHOD,false); + c->setDeclaredMethodByQName("getRunmode","",Class<IFunction>::getFunction(getRunmode),NORMAL_METHOD,false); + c->setDeclaredMethodByQName("isDebugger","",Class<IFunction>::getFunction(isDebugger),NORMAL_METHOD,false); + c->setDeclaredMethodByQName("isGlobal","",Class<IFunction>::getFunction(isGlobal),NORMAL_METHOD,false); + c->setDeclaredMethodByQName("freeMemory","",Class<IFunction>::getFunction(_freeMemory),GETTER_METHOD,false); + c->setDeclaredMethodByQName("totalMemory","",Class<IFunction>::getFunction(_totalMemory),GETTER_METHOD,false); + c->setDeclaredMethodByQName("privateMemory","",Class<IFunction>::getFunction(_privateMemory),GETTER_METHOD,false); + c->setDeclaredMethodByQName("argv","",Class<IFunction>::getFunction(argv),NORMAL_METHOD,false); + c->setDeclaredMethodByQName("exec","",Class<IFunction>::getFunction(exec),NORMAL_METHOD,false); + c->setDeclaredMethodByQName("write","",Class<IFunction>::getFunction(write),NORMAL_METHOD,false); + c->setDeclaredMethodByQName("exit","",Class<IFunction>::getFunction(exit),NORMAL_METHOD,false); + c->setDeclaredMethodByQName("trace","",Class<IFunction>::getFunction(lightspark::trace),NORMAL_METHOD,false); + c->setDeclaredMethodByQName("canonicalizeNumber","",Class<IFunction>::getFunction(canonicalizeNumber),NORMAL_METHOD,false); +} + +ASFUNCTIONBODY(avmplusSystem,getFeatures) +{ + LOG(LOG_NOT_IMPLEMENTED, _("avmplus.System.getFeatures is unimplemented.")); + return Class<ASString>::getInstanceS(""); +} +ASFUNCTIONBODY(avmplusSystem,getRunmode) +{ + LOG(LOG_NOT_IMPLEMENTED, _("avmplus.System.getRunmode is unimplemented.")); + return Class<ASString>::getInstanceS("jit"); +} + +ASFUNCTIONBODY(avmplusSystem,queueCollection) +{ + LOG(LOG_NOT_IMPLEMENTED, _("avmplus.System.queueCollection is unimplemented.")); + return NULL; +} + +ASFUNCTIONBODY(avmplusSystem,forceFullCollection) +{ + LOG(LOG_NOT_IMPLEMENTED, _("avmplus.System.forceFullCollection is unimplemented.")); + return NULL; +} + +ASFUNCTIONBODY(avmplusSystem,getAvmplusVersion) +{ + LOG(LOG_NOT_IMPLEMENTED, _("avmplus.System.getAvmplusVersion is unimplemented.")); + return Class<ASString>::getInstanceS("0"); +} +ASFUNCTIONBODY(avmplusSystem,pauseForGCIfCollectionImminent) +{ + LOG(LOG_NOT_IMPLEMENTED, _("avmplus.System.pauseForGCIfCollectionImminent is unimplemented.")); + return NULL; +} + +ASFUNCTIONBODY(avmplusSystem,isDebugger) +{ + LOG(LOG_NOT_IMPLEMENTED, _("avmplus.System.isDebugger is unimplemented.")); + return abstract_b(false); +} +ASFUNCTIONBODY(avmplusSystem,isGlobal) +{ + LOG(LOG_NOT_IMPLEMENTED, _("avmplus.System.isDebugger is unimplemented.")); + return abstract_b(false); +} +ASFUNCTIONBODY(avmplusSystem,_freeMemory) +{ + LOG(LOG_NOT_IMPLEMENTED, _("avmplus.System.freeMemory is unimplemented.")); + return abstract_d(1024); +} +ASFUNCTIONBODY(avmplusSystem,_totalMemory) +{ + LOG(LOG_NOT_IMPLEMENTED, _("avmplus.System.totalMemory is unimplemented.")); + return abstract_d(1024); +} +ASFUNCTIONBODY(avmplusSystem,_privateMemory) +{ + LOG(LOG_NOT_IMPLEMENTED, _("avmplus.System.privateMemory is unimplemented.")); + return abstract_d(1024); +} +ASFUNCTIONBODY(avmplusSystem,argv) +{ + LOG(LOG_NOT_IMPLEMENTED, _("avmplus.System.argv is unimplemented.")); + return Class<Array>::getInstanceS(); +} +ASFUNCTIONBODY(avmplusSystem,exec) +{ + LOG(LOG_NOT_IMPLEMENTED, _("avmplus.System.exec is unimplemented.")); + return NULL; +} +ASFUNCTIONBODY(avmplusSystem,write) +{ + LOG(LOG_NOT_IMPLEMENTED, _("avmplus.System.write is unimplemented.")); + return NULL; +} +ASFUNCTIONBODY(avmplusSystem,exit) +{ + LOG(LOG_NOT_IMPLEMENTED, _("avmplus.System.exit is unimplemented.")); + return NULL; +} +ASFUNCTIONBODY(avmplusSystem,canonicalizeNumber) +{ + LOG(LOG_NOT_IMPLEMENTED, _("avmplus.System.canonicalizeNumber is unimplemented.")); + _NR<ASObject> o; + ARG_UNPACK(o); + o->incRef(); + return o.getPtr(); +} + +avmplusDomain::avmplusDomain(Class_base* c): + ApplicationDomain(c) +{ + domainMemory->setLength(0); +} + +void avmplusDomain::sinit(Class_base* c) +{ + CLASS_SETUP(c, ApplicationDomain,_constructor, CLASS_SEALED); + c->setDeclaredMethodByQName("currentDomain","",Class<IFunction>::getFunction(_getCurrentDomain),GETTER_METHOD,false); + c->setDeclaredMethodByQName("MIN_DOMAIN_MEMORY_LENGTH","",Class<IFunction>::getFunction(_getMinDomainMemoryLength),GETTER_METHOD,false); + c->setDeclaredMethodByQName("load","",Class<IFunction>::getFunction(load),NORMAL_METHOD,true); + c->setDeclaredMethodByQName("loadBytes","",Class<IFunction>::getFunction(load),NORMAL_METHOD,true); + c->setDeclaredMethodByQName("getClass","",Class<IFunction>::getFunction(getClass),NORMAL_METHOD,true); +} +ASFUNCTIONBODY(avmplusDomain,_constructor) +{ + LOG(LOG_NOT_IMPLEMENTED, _("avmplus.Domain constructor is unimplemented.")); + return NULL; +} + +ASFUNCTIONBODY(avmplusDomain,load) +{ + LOG(LOG_NOT_IMPLEMENTED, _("avmplus.Domain.load is unimplemented.")); + throwError<VerifyError>(kIllegalOpcodeError,"","",""); + return NULL; +} +ASFUNCTIONBODY(avmplusDomain,loadBytes) +{ + LOG(LOG_NOT_IMPLEMENTED, _("avmplus.Domain.loadBytes is unimplemented.")); + return NULL; +} +ASFUNCTIONBODY(avmplusDomain,getClass) +{ + LOG(LOG_NOT_IMPLEMENTED, _("avmplus.Domain.getClass is unimplemented.")); + return Class<ASObject>::getRef()->getClass(); +}
View file
lightspark.tar.xz/src/scripting/avmplus/avmplus.h
Added
@@ -0,0 +1,76 @@ +/************************************************************************** + Lightspark, a free flash player implementation + + Copyright (C) 2009-2013 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 Lesser 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +**************************************************************************/ + +#ifndef SCRIPTING_AVMPLUS_AVMPLUS_H +#define SCRIPTING_AVMPLUS_AVMPLUS_H 1 + +#include "asobject.h" +#include "scripting/flash/system/flashsystem.h" + +namespace lightspark +{ + +class avmplusFile : public ASObject +{ +public: + avmplusFile(Class_base* c); + static void sinit(Class_base*); + ASFUNCTION(exists); + ASFUNCTION(read); + ASFUNCTION(write); + ASFUNCTION(readByteArray); + ASFUNCTION(writeByteArray); +}; + +class avmplusSystem : public ASObject +{ +public: + avmplusSystem(Class_base* c); + static void sinit(Class_base*); + ASFUNCTION(getFeatures); + ASFUNCTION(queueCollection); + ASFUNCTION(forceFullCollection); + ASFUNCTION(getAvmplusVersion); + ASFUNCTION(pauseForGCIfCollectionImminent); + ASFUNCTION(getRunmode); + ASFUNCTION(isDebugger); + ASFUNCTION(isGlobal); + ASFUNCTION(_freeMemory); + ASFUNCTION(_totalMemory); + ASFUNCTION(_privateMemory); + ASFUNCTION(argv); + ASFUNCTION(exec); + ASFUNCTION(write); + ASFUNCTION(exit); + ASFUNCTION(canonicalizeNumber); +}; + +class avmplusDomain : public ApplicationDomain +{ +public: + avmplusDomain(Class_base* c); + static void sinit(Class_base*); + ASFUNCTION(_constructor); + ASFUNCTION(load); + ASFUNCTION(loadBytes); + ASFUNCTION(getClass); +}; + +} +#endif /* SCRIPTING_AVMPLUS_AVMPLUS_H */
View file
lightspark.tar.xz/src/scripting/class.h
Changed
@@ -381,7 +381,7 @@ o->decRef(); return getSys()->getNullRef(); } - else if ((o->is<Vector>() && o->as<Vector>()->sameType(this->class_name)) || + else if ((o->is<Vector>() && o->as<Vector>()->sameType(this)) || o->is<Null>()) { // Vector.<x> can be coerced to Vector.<y>
View file
lightspark.tar.xz/src/scripting/flash/net/flashnet.cpp
Changed
@@ -398,11 +398,13 @@ { //Send a complete event for this object loader->setData(data); + loader->incRef(); getVm()->addEvent(loader,_MR(Class<Event>::getInstanceS("complete"))); } else if(!success && !threadAborting) { //Notify an error during loading + loader->incRef(); getVm()->addEvent(loader,_MR(Class<IOErrorEvent>::getInstanceS())); } @@ -1538,8 +1540,11 @@ } if (frameRate) { - this->bufferLength = (framesdecoded / frameRate) - (streamTime-prevstreamtime)/1000.0; this->playbackBytesPerSecond = s.tellg() / (framesdecoded / frameRate); + // TODO this overrides the real number of decoded frames + // otherwise on slow computers we never get the buffer filled + framesdecoded = (this->getReceivedLength() / this->playbackBytesPerSecond) * frameRate; + this->bufferLength = (framesdecoded / frameRate) - (streamTime-prevstreamtime)/1000.0; } countermutex.unlock(); }
View file
lightspark.tar.xz/src/scripting/flash/system/flashsystem.cpp
Changed
@@ -63,7 +63,15 @@ ASFUNCTIONBODY(Capabilities,_getPlayerType) { - return Class<ASString>::getInstanceS("PlugIn"); + switch (getSys()->flashMode) + { + case SystemState::AVMPLUS: + return Class<ASString>::getInstanceS("AVMPlus"); + case SystemState::AIR: + return Class<ASString>::getInstanceS("Desktop"); + default: + return Class<ASString>::getInstanceS("PlugIn"); + } } ASFUNCTIONBODY(Capabilities,_getLanguage) @@ -110,7 +118,7 @@ ASFUNCTIONBODY(Capabilities,_getServerString) { LOG(LOG_NOT_IMPLEMENTED,"Capabilities: not all capabilities are reported in ServerString"); - tiny_string res = "A=t&SA=t&SV=t&MP3=t&OS=Linux&PT=PlugIn&L=en&TLS=t"; + tiny_string res = "A=t&SA=t&SV=t&MP3=t&OS=Linux&PT=PlugIn&L=en&TLS=t&DD=t"; res +="&V="; res += EMULATED_VERSION; res +="&M="; @@ -596,11 +604,17 @@ { CLASS_SETUP(c, EventDispatcher, _constructorNotInstantiatable, CLASS_SEALED | CLASS_FINAL); c->setDeclaredMethodByQName("current","",Class<IFunction>::getFunction(_getCurrent),GETTER_METHOD,false); + c->setDeclaredMethodByQName("getSharedProperty","",Class<IFunction>::getFunction(getSharedProperty),NORMAL_METHOD,true); } ASFUNCTIONBODY(ASWorker,_getCurrent) { LOG(LOG_NOT_IMPLEMENTED, "Worker not implemented"); return Class<ASObject>::getInstanceS(); } +ASFUNCTIONBODY(ASWorker,getSharedProperty) +{ + LOG(LOG_NOT_IMPLEMENTED, "Worker.getSharedProperty not implemented"); + return Class<ASObject>::getInstanceS(); +}
View file
lightspark.tar.xz/src/scripting/flash/system/flashsystem.h
Changed
@@ -88,10 +88,10 @@ T readFromDomainMemory(uint32_t addr) const { if(domainMemory.isNull()) - throw RunTimeException("No memory domain is set"); + return 0; uint32_t bufLen=domainMemory->getLength(); if(bufLen < (addr+sizeof(T))) - throw RunTimeException("Memory domain access is out of bounds"); + throwError<RangeError>(kInvalidRangeError); uint8_t* buf=domainMemory->getBuffer(bufLen, false); return *reinterpret_cast<T*>(buf+addr); } @@ -99,10 +99,10 @@ void writeToDomainMemory(uint32_t addr, T val) { if(domainMemory.isNull()) - throw RunTimeException("No memory domain is set"); + return; uint32_t bufLen=domainMemory->getLength(); if(bufLen < (addr+sizeof(T))) - throw RunTimeException("Memory domain access is out of bounds"); + throwError<RangeError>(kInvalidRangeError); uint8_t* buf=domainMemory->getBuffer(bufLen, false); *reinterpret_cast<T*>(buf+addr)=val; } @@ -165,6 +165,7 @@ ASWorker(Class_base* c); static void sinit(Class_base*); ASFUNCTION(_getCurrent); + ASFUNCTION(getSharedProperty); }; }
View file
lightspark.tar.xz/src/scripting/flash/utils/ByteArray.cpp
Changed
@@ -105,7 +105,7 @@ REGISTER_GETTER_SETTER(c,shareable); c->setDeclaredMethodByQName("atomicCompareAndSwapIntAt","",Class<IFunction>::getFunction(atomicCompareAndSwapIntAt),NORMAL_METHOD,true); c->setDeclaredMethodByQName("atomicCompareAndSwapLength","",Class<IFunction>::getFunction(atomicCompareAndSwapLength),NORMAL_METHOD,true); - c->setDeclaredMethodByQName("toJSON",AS3,Class<IFunction>::getFunction(_toJSON),NORMAL_METHOD,true); + c->prototype->setVariableByQName("toJSON",AS3,Class<IFunction>::getFunction(_toJSON),DYNAMIC_TRAIT); c->addImplementedInterface(InterfaceClass<IDataInput>::getClass()); IDataInput::linkTraits(c); @@ -131,7 +131,7 @@ // the flash documentation doesn't tell how large ByteArrays are allowed to be // so we simply don't allow bytearrays larger than 1GiB // maybe we should set this smaller - if (size > 0x4000000) + if (size > 0x40000000) throwError<ASError>(kOutOfMemoryError); // The first allocation is exactly the size we need, // the subsequent reallocations happen in increments of BA_CHUNK_SIZE bytes @@ -420,9 +420,21 @@ return false; if(len < (position+stringLen)) return false; - //Very inefficient copy - //TODO: optmize - ret=string((char*)bytes+position, (size_t)stringLen); + // check for BOM + if (len > position+3) + { + if (bytes[position] == 0xef && + bytes[position+1] == 0xbb && + bytes[position+2] == 0xbf) + { + position += 3; + stringLen -= stringLen > 3 ? 3 : 0; + } + } + char buf[stringLen+1]; + buf[stringLen]=0; + strncpy(buf,(char*)bytes+position,(size_t)stringLen); + ret=buf; position+=stringLen; return true; } @@ -454,11 +466,25 @@ th->unlock(); throwError<EOFError>(kEOFError); } + // check for BOM + if (th->len > th->position+3) + { + if (th->bytes[th->position] == 0xef && + th->bytes[th->position+1] == 0xbb && + th->bytes[th->position+2] == 0xbf) + { + th->position += 3; + length -= length > 3 ? 3 : 0; + } + } uint8_t *bufStart=th->bytes+th->position; + char buf[length+1]; + buf[length]=0; + strncpy(buf,(char*)bufStart,(size_t)length); th->position+=length; th->unlock(); - return Class<ASString>::getInstanceS((char *)bufStart,length); + return Class<ASString>::getInstanceS((char *)buf,strlen(buf)); } void ByteArray::writeUTF(const tiny_string& str) @@ -987,8 +1013,16 @@ ASFUNCTIONBODY(ByteArray,_toString) { ByteArray* th=static_cast<ByteArray*>(obj); - //TODO: check for Byte Order Mark - return Class<ASString>::getInstanceS((char*)th->bytes,th->len); + //check for Byte Order Mark + int start = 0; + if (th->len > 3) + { + if (th->bytes[0] == 0xef && + th->bytes[1] == 0xbb && + th->bytes[2] == 0xbf) + start = 3; + } + return Class<ASString>::getInstanceS((char*)th->bytes+start,th->len-start); } bool ByteArray::hasPropertyByMultiname(const multiname& name, bool considerDynamic, bool considerPrototype) @@ -1101,6 +1135,18 @@ } } +void ByteArray::serializeDouble(number_t val) +{ + //We have to write the double in network byte order (big endian) + const uint64_t* tmpPtr=reinterpret_cast<const uint64_t*>(&val); + uint64_t bigEndianVal=GINT64_FROM_BE(*tmpPtr); + uint8_t* bigEndianPtr=reinterpret_cast<uint8_t*>(&bigEndianVal); + + for(uint32_t i=0;i<8;i++) + writeByte(bigEndianPtr[i]); + +} + void ByteArray::writeStringVR(map<tiny_string, uint32_t>& stringMap, const tiny_string& s) { const uint32_t len=s.numBytes(); @@ -1412,3 +1458,30 @@ { return Class<ASString>::getInstanceS("ByteArray"); } + +void ByteArray::serialize(ByteArray* out, std::map<tiny_string, uint32_t>& stringMap, + std::map<const ASObject*, uint32_t>& objMap, + std::map<const Class_base*, uint32_t>& traitsMap) +{ + assert_and_throw(objMap.find(this)==objMap.end()); + out->writeByte(byte_array_marker); + //Check if the bytearray has been already serialized + auto it=objMap.find(this); + if(it!=objMap.end()) + { + //The least significant bit is 0 to signal a reference + out->writeU29(it->second << 1); + } + else + { + //Add the dictionary to the map + objMap.insert(make_pair(this, objMap.size())); + + assert_and_throw(len<0x20000000); + uint32_t value = (len << 1) | 1; + out->writeU29(value); + // TODO faster implementation + for (uint i = 0; i < len; i++) + out->writeByte(this->bytes[i]); + } +}
View file
lightspark.tar.xz/src/scripting/flash/utils/ByteArray.h
Changed
@@ -46,7 +46,6 @@ Mutex mutex; void lock(); void unlock(); - void setLength(uint32_t newLen); public: ByteArray(Class_base* c, uint8_t* b = NULL, uint32_t l = 0); ~ByteArray(); @@ -65,6 +64,10 @@ void writeStringVR(std::map<tiny_string, uint32_t>& stringMap, const tiny_string& s); void writeXMLString(std::map<const ASObject*, uint32_t>& objMap, ASObject *xml, const tiny_string& s); void writeU29(uint32_t val); + + void serializeDouble(number_t val); + + void setLength(uint32_t newLen); uint32_t getPosition() const; void setPosition(uint32_t p); @@ -152,6 +155,10 @@ void setVariableByMultiname(const multiname& name, ASObject* o, CONST_ALLOWED_FLAG allowConst); void setVariableByMultiname_i(const multiname& name, int32_t value); bool hasPropertyByMultiname(const multiname& name, bool considerDynamic, bool considerPrototype); + + void serialize(ByteArray* out, std::map<tiny_string, uint32_t>& stringMap, + std::map<const ASObject*, uint32_t>& objMap, + std::map<const Class_base*, uint32_t>& traitsMap); }; }
View file
lightspark.tar.xz/src/scripting/flash/utils/CompressionAlgorithm.cpp
Added
@@ -0,0 +1,39 @@ +/************************************************************************** + Lightspark, a free flash player implementation + + Copyright (C) 2009-2013 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 Lesser 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +**************************************************************************/ + +#include "scripting/flash/utils/CompressionAlgorithm.h" +#include "asobject.h" +#include "scripting/class.h" +#include "scripting/argconv.h" + +using namespace std; +using namespace lightspark; + +CompressionAlgorithm::CompressionAlgorithm(Class_base* c): + ASObject(c) +{ +} + +void CompressionAlgorithm::sinit(Class_base* c) +{ + CLASS_SETUP_NO_CONSTRUCTOR(c, ASObject, CLASS_SEALED|CLASS_FINAL); + c->setVariableByQName("DEFLATE","",Class<ASString>::getInstanceS("deflate"),CONSTANT_TRAIT); + c->setVariableByQName("LZMA","",Class<ASString>::getInstanceS("lzma"),CONSTANT_TRAIT); + c->setVariableByQName("ZLIB","",Class<ASString>::getInstanceS("zlib"),CONSTANT_TRAIT); +}
View file
lightspark.tar.xz/src/scripting/flash/utils/CompressionAlgorithm.h
Added
@@ -0,0 +1,39 @@ +/************************************************************************** + Lightspark, a free flash player implementation + + Copyright (C) 2009-2013 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 Lesser 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +**************************************************************************/ + +#ifndef SCRIPTING_FLASH_UTILS_COMPRESSIONALGORITHM_H +#define SCRIPTING_FLASH_UTILS_COMPRESSIONALGORITHM_H 1 + +#include "compat.h" +#include "swftypes.h" +#include "scripting/flash/utils/flashutils.h" + +namespace lightspark +{ + +class CompressionAlgorithm : public ASObject +{ +public: + CompressionAlgorithm(Class_base* c); + static void sinit(Class_base*); +}; + +} + +#endif /* SCRIPTING_FLASH_UTILS_COMPRESSIONALGORITHM_H */
View file
lightspark.tar.xz/src/scripting/flash/utils/Dictionary.cpp
Changed
@@ -43,7 +43,7 @@ void Dictionary::sinit(Class_base* c) { CLASS_SETUP(c, ASObject, _constructor, CLASS_DYNAMIC_NOT_FINAL); - c->setDeclaredMethodByQName("toJSON",AS3,Class<IFunction>::getFunction(_toJSON),NORMAL_METHOD,true); + c->prototype->setVariableByQName("toJSON",AS3,Class<IFunction>::getFunction(_toJSON),DYNAMIC_TRAIT); } void Dictionary::buildTraits(ASObject* o) @@ -52,6 +52,10 @@ ASFUNCTIONBODY(Dictionary,_constructor) { + bool weak = false; + ARG_UNPACK(weak, false); + if (weak) + LOG(LOG_NOT_IMPLEMENTED,"Dictionary:weak keys not implemented"); return NULL; } @@ -348,3 +352,42 @@ return retstr.str(); } + +void Dictionary::serialize(ByteArray* out, std::map<tiny_string, uint32_t>& stringMap, + std::map<const ASObject*, uint32_t>& objMap, + std::map<const Class_base*, uint32_t>& traitsMap) +{ + assert_and_throw(objMap.find(this)==objMap.end()); + out->writeByte(dictionary_marker); + //Check if the dictionary has been already serialized + auto it=objMap.find(this); + if(it!=objMap.end()) + { + //The least significant bit is 0 to signal a reference + out->writeU29(it->second << 1); + } + else + { + //Add the dictionary to the map + objMap.insert(make_pair(this, objMap.size())); + + uint32_t count = 0; + uint32_t tmp; + while ((tmp = nextNameIndex(count)) != 0) + { + count = tmp; + } + assert_and_throw(count<0x20000000); + uint32_t value = (count << 1) | 1; + out->writeU29(value); + out->writeByte(0x00); // TODO handle weak keys + + tmp = 0; + while ((tmp = nextNameIndex(tmp)) != 0) + { + nextName(tmp)->serialize(out, stringMap, objMap, traitsMap); + nextValue(tmp)->serialize(out, stringMap, objMap, traitsMap); + } + } +} +
View file
lightspark.tar.xz/src/scripting/flash/utils/Dictionary.h
Changed
@@ -57,6 +57,10 @@ uint32_t nextNameIndex(uint32_t cur_index); _R<ASObject> nextName(uint32_t index); _R<ASObject> nextValue(uint32_t index); + + void serialize(ByteArray* out, std::map<tiny_string, uint32_t>& stringMap, + std::map<const ASObject*, uint32_t>& objMap, + std::map<const Class_base*, uint32_t>& traitsMap); }; }
View file
lightspark.tar.xz/src/scripting/flash/utils/Proxy.cpp
Changed
@@ -38,11 +38,21 @@ void Proxy::sinit(Class_base* c) { CLASS_SETUP_NO_CONSTRUCTOR(c, ASObject,CLASS_DYNAMIC_NOT_FINAL); + c->setDeclaredMethodByQName("isAttribute","",Class<IFunction>::getFunction(_isAttribute),NORMAL_METHOD,true); } void Proxy::buildTraits(ASObject* o) { } +ASFUNCTIONBODY(Proxy,_isAttribute) +{ + _NR<ASObject> name; + ARG_UNPACK(name); + multiname mname(NULL); + name->applyProxyProperty(mname); + LOG(LOG_ERROR,"isAttr:"<<mname.isAttribute); + return abstract_b(mname.isAttribute); +} void Proxy::setVariableByMultiname(const multiname& name, ASObject* o, CONST_ALLOWED_FLAG allowConst) {
View file
lightspark.tar.xz/src/scripting/flash/utils/Proxy.h
Changed
@@ -34,6 +34,7 @@ static void sinit(Class_base*); static void buildTraits(ASObject* o); // ASFUNCTION(_constructor); + ASFUNCTION(_isAttribute); _NR<ASObject> getVariableByMultiname(const multiname& name, GET_VARIABLE_OPTION opt=NONE); int32_t getVariableByMultiname_i(const multiname& name) {
View file
lightspark.tar.xz/src/scripting/flash/utils/flashutils.cpp
Changed
@@ -126,7 +126,8 @@ else c=static_cast<Class_base*>(target)->super.getPtr(); - assert_and_throw(c); + if (!c) + return getSys()->getNullRef(); return Class<ASString>::getInstanceS(c->getQualifiedClassName()); } @@ -162,7 +163,7 @@ ASFUNCTIONBODY(lightspark,describeType) { - assert_and_throw(argslen==1); + assert_and_throw(argslen>=1); return args[0]->describeType(); }
View file
lightspark.tar.xz/src/scripting/toplevel/Array.cpp
Changed
@@ -329,6 +329,8 @@ uint32_t newLen; ARG_UNPACK(newLen); Array* th=static_cast<Array*>(obj); + if (th->getClass() && th->getClass()->isSealed) + return NULL; //If newLen is equal to size do nothing if(newLen==th->size()) return NULL; @@ -408,12 +410,12 @@ int ret=-1; if(argslen == 1 && th->data.empty()) - return abstract_d(0); + return abstract_d(-1); size_t i = th->size()-1; if(argslen == 2 && std::isnan(args[1]->toNumber())) - return abstract_i(0); + return abstract_i(-1); if(argslen == 2 && args[1]->getObjectType() != T_UNDEFINED && !std::isnan(args[1]->toNumber())) { @@ -1007,6 +1009,9 @@ return getSys()->getUndefinedRef(); } Array* th=static_cast<Array*>(obj); + // Derived classes may be sealed! + if (th->getClass() && th->getClass()->isSealed) + throwError<ReferenceError>(kWriteSealedError,"unshift",th->getClass()->getQualifiedClassName()); if (argslen > 0) { th->resize(th->size()+argslen); @@ -1220,34 +1225,41 @@ uint32_t index=0; if(!isValidMultiname(name,index)) return ASObject::getVariableByMultiname(name,opt); - if(index<size()) + if(index<size() && data.count(index)) { ASObject* ret=NULL; - if (!data.count(index)) - ret = getSys()->getUndefinedRef(); - else + data_slot sl = data[index]; + switch(sl.type) { - data_slot sl = data[index]; - switch(sl.type) - { - case DATA_OBJECT: - ret=sl.data; - if(ret==NULL) - { - ret=getSys()->getUndefinedRef(); - sl.data=ret; - } - ret->incRef(); - break; - case DATA_INT: - ret=abstract_d(sl.data_i); - break; - } + case DATA_OBJECT: + ret=sl.data; + if(ret==NULL) + { + ret=getSys()->getUndefinedRef(); + sl.data=ret; + } + ret->incRef(); + break; + case DATA_INT: + ret=abstract_d(sl.data_i); + break; } return _MNR(ret); } - else - return NullRef; + _NR<ASObject> ret; + //Check prototype chain + Prototype* proto = this->getClass()->prototype.getPtr(); + while(proto) + { + ret = proto->getObj()->getVariableByMultiname(name, opt); + if(!ret.isNull()) + return ret; + proto = proto->prevPrototype.getPtr(); + } + if(index<size()) + return _MNR(getSys()->getUndefinedRef()); + + return NullRef; } void Array::setVariableByMultiname_i(const multiname& name, int32_t value) @@ -1367,6 +1379,8 @@ unsigned int index=0; if(!isValidMultiname(name,index)) return ASObject::deleteVariableByMultiname(name); + if (getClass() && getClass()->isSealed) + return false; if(index>=size()) return true; @@ -1587,13 +1601,21 @@ for(uint32_t i=0;i<denseCount;i++) { if (!data.count(i)) - throw UnsupportedException("undefined not supported in Array::serialize"); - switch(data.at(i).type) { - case DATA_INT: - throw UnsupportedException("int not supported in Array::serialize"); - case DATA_OBJECT: - data.at(i).data->serialize(out, stringMap, objMap, traitsMap); + out->writeByte(null_marker); + } + else + { + switch(data.at(i).type) + { + case DATA_INT: + out->writeByte(double_marker); + out->serializeDouble(data.at(i).data_i); + break; + case DATA_OBJECT: + data.at(i).data->serialize(out, stringMap, objMap, traitsMap); + break; + } } } } @@ -1601,12 +1623,12 @@ tiny_string Array::toJSON(std::vector<ASObject *> &path, IFunction *replacer, const tiny_string& spaces,const tiny_string& filter) { - if (has_toJSON()) - { - return call_toJSON(); - } + bool ok; + tiny_string res = call_toJSON(ok,path,replacer,spaces,filter); + if (ok) + return res; - tiny_string res = "["; + res += "["; std::map<uint32_t,data_slot>::iterator it; // check for cylic reference if (std::find(path.begin(),path.end(), this) != path.end()) @@ -1616,34 +1638,42 @@ tiny_string newline = (spaces.empty() ? "" : "\n"); for (it=data.begin() ; it != data.end(); ++it) { - if(it->second.type==DATA_OBJECT && it->second.data) + tiny_string subres; + ASObject* o = it->second.type==DATA_OBJECT ? it->second.data : abstract_i(it->second.data_i); + if (replacer != NULL) { - tiny_string subres; - if (replacer != NULL) + ASObject* params[2]; + + params[0] = Class<Number>::getInstanceS(it->first); + params[0]->incRef(); + params[1] = o; + params[1]->incRef(); + ASObject *funcret=replacer->call(getSys()->getNullRef(), params, 2); + if (funcret) + subres = funcret->toJSON(path,NULL,spaces,filter); + } + else + { + if(it->second.type==DATA_OBJECT) { - ASObject* params[2]; - - params[0] = Class<Number>::getInstanceS(it->first); - params[0]->incRef(); - params[1] = it->second.data; - params[1]->incRef(); - ASObject *funcret=replacer->call(getSys()->getNullRef(), params, 2); - if (funcret) - subres = funcret->toJSON(path,NULL,spaces,filter); + if (it->second.data) + subres = it->second.data->toJSON(path,replacer,spaces,filter); + else + continue; } else - subres = it->second.data->toJSON(path,replacer,spaces,filter); - if (!subres.empty()) - { - if (!bfirst) - res += ","; - res += newline+spaces; - - bfirst = false; - res += subres; - } - path.push_back(it->second.data); + subres = o->toString(); + } + if (!subres.empty()) + { + if (!bfirst) + res += ","; + res += newline+spaces; + + bfirst = false; + res += subres; } + path.push_back(o); } if (!bfirst) res += newline+spaces.substr_bytes(0,spaces.numBytes()/2); @@ -1692,3 +1722,12 @@ outofbounds(index); } +void Array::push(Ref<ASObject> o) +{ + // Derived classes may be sealed! + if (getClass() && getClass()->isSealed) + throwError<ReferenceError>(kWriteSealedError,"push",getClass()->getQualifiedClassName()); + currentsize++; + set(currentsize-1,o); +} +
View file
lightspark.tar.xz/src/scripting/toplevel/Array.h
Changed
@@ -132,11 +132,7 @@ { return currentsize; } - void push(_R<ASObject> o) - { - currentsize++; - set(currentsize-1,o); - } + void push(_R<ASObject> o); void resize(uint64_t n); _NR<ASObject> getVariableByMultiname(const multiname& name, GET_VARIABLE_OPTION opt); int32_t getVariableByMultiname_i(const multiname& name);
View file
lightspark.tar.xz/src/scripting/toplevel/Date.cpp
Changed
@@ -17,9 +17,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. **************************************************************************/ +#include "parsing/amf3_generator.h" #include "scripting/toplevel/Date.h" #include "scripting/class.h" #include "scripting/argconv.h" +#include "scripting/flash/utils/ByteArray.h" #include "compat.h" using namespace std; @@ -40,6 +42,7 @@ void Date::sinit(Class_base* c) { CLASS_SETUP_CONSTRUCTOR_LENGTH(c, ASObject, _constructor, 7, CLASS_FINAL); + c->prototype->isSealed=true; c->setDeclaredMethodByQName("getTimezoneOffset",AS3,Class<IFunction>::getFunction(getTimezoneOffset),NORMAL_METHOD,true); c->setDeclaredMethodByQName("valueOf",AS3,Class<IFunction>::getFunction(valueOf),NORMAL_METHOD,true); c->setDeclaredMethodByQName("getTime",AS3,Class<IFunction>::getFunction(getTime),NORMAL_METHOD,true); @@ -76,7 +79,6 @@ c->setDeclaredMethodByQName("setTime",AS3,Class<IFunction>::getFunction(setTime,1),NORMAL_METHOD,true); c->setDeclaredMethodByQName("UTC","",Class<IFunction>::getFunction(UTC,7),NORMAL_METHOD,false); c->setDeclaredMethodByQName("toString",AS3,Class<IFunction>::getFunction(_toString),NORMAL_METHOD,true); - c->setDeclaredMethodByQName("toJSON",AS3,Class<IFunction>::getFunction(_toString),NORMAL_METHOD,true); c->setDeclaredMethodByQName("toUTCString",AS3,Class<IFunction>::getFunction(toUTCString),NORMAL_METHOD,true); c->setDeclaredMethodByQName("toDateString",AS3,Class<IFunction>::getFunction(toDateString),NORMAL_METHOD,true); c->setDeclaredMethodByQName("toTimeString",AS3,Class<IFunction>::getFunction(toTimeString),NORMAL_METHOD,true); @@ -159,6 +161,7 @@ c->prototype->setVariableByQName("toLocaleTimeString","",Class<IFunction>::getFunction(toLocaleTimeString),DYNAMIC_TRAIT); c->prototype->setVariableByQName("toLocaleDateString","",Class<IFunction>::getFunction(toLocaleDateString),DYNAMIC_TRAIT); c->prototype->setVariableByQName("toLocaleString","",Class<IFunction>::getFunction(toLocaleString),DYNAMIC_TRAIT); + c->prototype->setVariableByQName("toJSON",AS3,Class<IFunction>::getFunction(_toString),DYNAMIC_TRAIT); } void Date::buildTraits(ASObject* o) @@ -878,7 +881,17 @@ ASFUNCTIONBODY(Date,toLocaleString) { Date* th=static_cast<Date*>(obj); - return Class<ASString>::getInstanceS(th->toString()); + if (!th->datetime) + return Class<ASString>::getInstanceS(""); + tiny_string res = th->toString_priv(false,"%a %b %e"); + gchar* fs = g_date_time_format(th->datetime, " %I:%M:%S"); + res += fs; + if (g_date_time_get_hour(th->datetime) > 12) + res += " PM"; + else + res += " AM"; + g_free(fs); + return Class<ASString>::getInstanceS(res); } ASFUNCTIONBODY(Date,toLocaleDateString) { @@ -1120,6 +1133,20 @@ std::map<const ASObject*, uint32_t>& objMap, std::map<const Class_base*, uint32_t>& traitsMap) { - throw UnsupportedException("Date::serialize not implemented"); + number_t val = getMsSinceEpoch(); + out->writeByte(date_marker); + auto it=objMap.find(this); + if(it!=objMap.end()) + { + //The least significant bit is 0 to signal a reference + out->writeU29(it->second << 1); + } + else + { + //Add the Date to the map + objMap.insert(make_pair(this, objMap.size())); + // write milliseconds since 1970 as double + out->serializeDouble(val); + } }
View file
lightspark.tar.xz/src/scripting/toplevel/Date.h
Changed
@@ -38,7 +38,6 @@ number_t getMsSinceEpoch(); tiny_string toString_priv(bool utc, const char* formatstr) const; void MakeDate(int64_t year, int64_t month, int64_t day, int64_t hour, int64_t minute, int64_t second, int64_t millisecond, bool bIsLocalTime); - void MakeDateFromMilliseconds(int64_t ms); static number_t parse(tiny_string str); public: Date(Class_base* c); @@ -105,6 +104,7 @@ ASFUNCTION(toLocaleDateString); ASFUNCTION(toLocaleTimeString); + void MakeDateFromMilliseconds(int64_t ms); bool isEqual(ASObject* r); TRISTATE isLess(ASObject* r); tiny_string toString();
View file
lightspark.tar.xz/src/scripting/toplevel/Integer.cpp
Changed
@@ -214,11 +214,17 @@ std::map<const ASObject*, uint32_t>& objMap, std::map<const Class_base*, uint32_t>& traitsMap) { - out->writeByte(integer_marker); - //TODO: check behaviour for negative value if(val>=0x40000000 || val<=(int32_t)0xbfffffff) - throw AssertionException("Range exception in Integer::serialize"); - out->writeU29((uint32_t)val); + { + // write as double + out->writeByte(double_marker); + out->serializeDouble(val); + } + else + { + out->writeByte(integer_marker); + out->writeU29((uint32_t)val); + } } bool Integer::fromStringFlashCompatible(const char* cur, int64_t& ret, int radix)
View file
lightspark.tar.xz/src/scripting/toplevel/JSON.cpp
Changed
@@ -555,6 +555,7 @@ name.ns.push_back(nsNameAndKind("",NAMESPACE)); name.isAttribute = false; bool done = false; + bool needdata = false; while (!done && pos < len) { while (jsonstring.charAt(pos) == ' ' || @@ -572,14 +573,16 @@ break; case ',': name.name_i++; + needdata = true; pos++; break; default: pos = parse(jsonstring,pos,&subobj,name, reviver); + needdata = false; break; } } - if (!done) + if (!done || needdata) throwError<SyntaxError>(kJSONInvalidParseInput); return pos;
View file
lightspark.tar.xz/src/scripting/toplevel/Math.cpp
Changed
@@ -228,6 +228,9 @@ ASFUNCTIONBODY(Math,random) { + if(argslen > 0) + throwError<ArgumentError>(kWrongArgumentCountError, "object", "", ""); + number_t ret=rand(); ret/=(number_t(1.)+RAND_MAX); return abstract_d(ret);
View file
lightspark.tar.xz/src/scripting/toplevel/Number.cpp
Changed
@@ -20,6 +20,7 @@ #include "parsing/amf3_generator.h" #include "scripting/argconv.h" #include "scripting/toplevel/Number.h" +#include "scripting/toplevel/Math.h" #include "scripting/flash/utils/ByteArray.h" using namespace std; @@ -276,6 +277,38 @@ c->prototype->setVariableByQName("toExponential","",Class<IFunction>::getFunction(Number::toExponential, 1),DYNAMIC_TRAIT); c->prototype->setVariableByQName("toPrecision","",Class<IFunction>::getFunction(Number::toPrecision, 1),DYNAMIC_TRAIT); c->prototype->setVariableByQName("valueOf","",Class<IFunction>::getFunction(_valueOf),DYNAMIC_TRAIT); + + // if needed add AVMPLUS definitions + if(getSys()->flashMode==SystemState::AVMPLUS) + { + c->setVariableByQName("E","",abstract_d(2.71828182845905),CONSTANT_TRAIT); + c->setVariableByQName("LN10","",abstract_d(2.302585092994046),CONSTANT_TRAIT); + c->setVariableByQName("LN2","",abstract_d(0.6931471805599453),CONSTANT_TRAIT); + c->setVariableByQName("LOG10E","",abstract_d(0.4342944819032518),CONSTANT_TRAIT); + c->setVariableByQName("LOG2E","",abstract_d(1.442695040888963387),CONSTANT_TRAIT); + c->setVariableByQName("PI","",abstract_d(3.141592653589793),CONSTANT_TRAIT); + c->setVariableByQName("SQRT1_2","",abstract_d(0.7071067811865476),CONSTANT_TRAIT); + c->setVariableByQName("SQRT2","",abstract_d(1.4142135623730951),CONSTANT_TRAIT); + + c->setDeclaredMethodByQName("abs","",Class<IFunction>::getFunction(Math::abs,1),NORMAL_METHOD,false); + c->setDeclaredMethodByQName("acos","",Class<IFunction>::getFunction(Math::acos,1),NORMAL_METHOD,false); + c->setDeclaredMethodByQName("asin","",Class<IFunction>::getFunction(Math::asin,1),NORMAL_METHOD,false); + c->setDeclaredMethodByQName("atan","",Class<IFunction>::getFunction(Math::atan,1),NORMAL_METHOD,false); + c->setDeclaredMethodByQName("atan2","",Class<IFunction>::getFunction(Math::atan2,2),NORMAL_METHOD,false); + c->setDeclaredMethodByQName("ceil","",Class<IFunction>::getFunction(Math::ceil,1),NORMAL_METHOD,false); + c->setDeclaredMethodByQName("cos","",Class<IFunction>::getFunction(Math::cos,1),NORMAL_METHOD,false); + c->setDeclaredMethodByQName("exp","",Class<IFunction>::getFunction(Math::exp,1),NORMAL_METHOD,false); + c->setDeclaredMethodByQName("floor","",Class<IFunction>::getFunction(Math::floor,1),NORMAL_METHOD,false); + c->setDeclaredMethodByQName("log","",Class<IFunction>::getFunction(Math::log,1),NORMAL_METHOD,false); + c->setDeclaredMethodByQName("max","",Class<IFunction>::getFunction(Math::_max,2),NORMAL_METHOD,false); + c->setDeclaredMethodByQName("min","",Class<IFunction>::getFunction(Math::_min,2),NORMAL_METHOD,false); + c->setDeclaredMethodByQName("pow","",Class<IFunction>::getFunction(Math::pow,2),NORMAL_METHOD,false); + c->setDeclaredMethodByQName("random","",Class<IFunction>::getFunction(Math::random),NORMAL_METHOD,false); + c->setDeclaredMethodByQName("round","",Class<IFunction>::getFunction(Math::round,1),NORMAL_METHOD,false); + c->setDeclaredMethodByQName("sin","",Class<IFunction>::getFunction(Math::sin,1),NORMAL_METHOD,false); + c->setDeclaredMethodByQName("sqrt","",Class<IFunction>::getFunction(Math::sqrt,1),NORMAL_METHOD,false); + c->setDeclaredMethodByQName("tan","",Class<IFunction>::getFunction(Math::tan,1),NORMAL_METHOD,false); + } } ASFUNCTIONBODY(Number,_constructor) @@ -497,11 +530,5 @@ std::map<const Class_base*, uint32_t>& traitsMap) { out->writeByte(double_marker); - //We have to write the double in network byte order (big endian) - const uint64_t* tmpPtr=reinterpret_cast<const uint64_t*>(&val); - uint64_t bigEndianVal=GINT64_FROM_BE(*tmpPtr); - uint8_t* bigEndianPtr=reinterpret_cast<uint8_t*>(&bigEndianVal); - - for(uint32_t i=0;i<8;i++) - out->writeByte(bigEndianPtr[i]); + out->serializeDouble(val); }
View file
lightspark.tar.xz/src/scripting/toplevel/UInteger.cpp
Changed
@@ -18,8 +18,10 @@ **************************************************************************/ #include <cmath> +#include "parsing/amf3_generator.h" #include "scripting/argconv.h" #include "scripting/toplevel/UInteger.h" +#include "scripting/flash/utils/ByteArray.h" using namespace std; using namespace lightspark; @@ -204,3 +206,20 @@ ARG_UNPACK (precision); return Class<ASString>::getInstanceS(Number::toPrecisionString(th->val, precision)); } + +void UInteger::serialize(ByteArray* out, std::map<tiny_string, uint32_t>& stringMap, + std::map<const ASObject*, uint32_t>& objMap, + std::map<const Class_base*, uint32_t>& traitsMap) +{ + if(val>=0x40000000) + { + // write as double + out->writeByte(double_marker); + out->serializeDouble(val); + } + else + { + out->writeByte(integer_marker); + out->writeU29((uint32_t)val); + } +}
View file
lightspark.tar.xz/src/scripting/toplevel/UInteger.h
Changed
@@ -53,7 +53,9 @@ ASFUNCTION(_toFixed); ASFUNCTION(_toPrecision); std::string toDebugString() { return toString()+"ui"; } - //CHECK: should this have a special serialization? + void serialize(ByteArray* out, std::map<tiny_string, uint32_t>& stringMap, + std::map<const ASObject*, uint32_t>& objMap, + std::map<const Class_base*, uint32_t>& traitsMap); }; }
View file
lightspark.tar.xz/src/scripting/toplevel/Vector.cpp
Changed
@@ -120,10 +120,10 @@ if(types.size() == 1) vec_type = types[0]; } -bool Vector::sameType(const QName& classname) const +bool Vector::sameType(const Class_base *cls) const { tiny_string clsname = this->getClass()->getQualifiedClassName(); - return (clsname.startsWith(classname.getQualifiedName().raw_buf())); + return (clsname.startsWith(cls->class_name.getQualifiedName().raw_buf())); } ASObject* Vector::generator(TemplatedClass<Vector>* o_class, ASObject* const* args, const unsigned int argslen) @@ -963,9 +963,17 @@ return ASObject::getVariableByMultiname(name,opt); unsigned int index=0; - if(!Vector::isValidMultiname(name,index)) - return ASObject::getVariableByMultiname(name,opt); + if(!Vector::isValidMultiname(name,index) || index == UINT32_MAX) + { + if (name.name_type == multiname::NAME_INT || + (name.name_type == multiname::NAME_NUMBER && Number::isInteger(name.name_d))) + throwError<RangeError>(kOutOfRangeError,Integer::toString(name.name_i),Integer::toString(vec.size())); + _NR<ASObject> ret = ASObject::getVariableByMultiname(name,opt); + if (ret.isNull()) + throwError<ReferenceError>(kReadSealedError, name.normalizedName(), this->getClass()->getQualifiedClassName()); + return ret; + } if(index < vec.size()) { if (vec[index]) @@ -994,7 +1002,15 @@ unsigned int index=0; if(!Vector::isValidMultiname(name,index)) + { + if (name.name_type == multiname::NAME_INT || + (name.name_type == multiname::NAME_NUMBER && Number::isInteger(name.name_d))) + throwError<RangeError>(kOutOfRangeError,name.normalizedName(),Integer::toString(vec.size())); + + if (!ASObject::hasPropertyByMultiname(name,false,true)) + throwError<ReferenceError>(kWriteSealedError, name.normalizedName(), this->getClass()->getQualifiedClassName()); return ASObject::setVariableByMultiname(name, o, allowConst); + } ASObject* o2 = this->vec_type->coerce(o); if(index < vec.size()) @@ -1073,14 +1089,63 @@ return false; bool validIndex=name.toUInt(index, true); - // Don't throw for non-numeric NAME_STRING or NAME_OBJECT - // because they can still be valid built-in property names. - if(!validIndex && (name.name_type==multiname::NAME_INT || name.name_type==multiname::NAME_NUMBER)) - throwError<RangeError>(kOutOfRangeError, name.normalizedNameUnresolved(), "?"); return validIndex; } +tiny_string Vector::toJSON(std::vector<ASObject *> &path, IFunction *replacer, const tiny_string &spaces, const tiny_string &filter) +{ + bool ok; + tiny_string res = call_toJSON(ok,path,replacer,spaces,filter); + if (ok) + return res; + + res += "["; + // check for cylic reference + if (std::find(path.begin(),path.end(), this) != path.end()) + throwError<TypeError>(kJSONCyclicStructure); + path.push_back(this); + bool bfirst = true; + tiny_string newline = (spaces.empty() ? "" : "\n"); + for (uint i =0; i < vec.size(); i++) + { + tiny_string subres; + ASObject* o = vec[i]; + if (!o) + o = getSys()->getNullRef(); + if (replacer != NULL) + { + ASObject* params[2]; + + params[0] = Class<Number>::getInstanceS(i); + params[0]->incRef(); + params[1] = o; + params[1]->incRef(); + ASObject *funcret=replacer->call(getSys()->getNullRef(), params, 2); + if (funcret) + subres = funcret->toJSON(path,NULL,spaces,filter); + } + else + { + subres = o->toJSON(path,replacer,spaces,filter); + } + if (!subres.empty()) + { + if (!bfirst) + res += ","; + res += newline+spaces; + + bfirst = false; + res += subres; + } + path.push_back(o); + } + if (!bfirst) + res += newline+spaces.substr_bytes(0,spaces.numBytes()/2); + res += "]"; + return res; +} + ASObject* Vector::at(unsigned int index, ASObject *defaultValue) const { if (index < vec.size()) @@ -1088,3 +1153,61 @@ else return defaultValue; } + +void Vector::serialize(ByteArray* out, std::map<tiny_string, uint32_t>& stringMap, + std::map<const ASObject*, uint32_t>& objMap, + std::map<const Class_base*, uint32_t>& traitsMap) +{ + uint8_t marker = 0; + if (vec_type == Class<Integer>::getClass()) + marker = vector_int_marker; + else if (vec_type == Class<UInteger>::getClass()) + marker = vector_uint_marker; + else if (vec_type == Class<Number>::getClass()) + marker = vector_double_marker; + else + marker = vector_object_marker; + out->writeByte(marker); + //Check if the vector has been already serialized + auto it=objMap.find(this); + if(it!=objMap.end()) + { + //The least significant bit is 0 to signal a reference + out->writeU29(it->second << 1); + } + else + { + //Add the Vector to the map + objMap.insert(make_pair(this, objMap.size())); + + uint32_t count = size(); + assert_and_throw(count<0x20000000); + uint32_t value = (count << 1) | 1; + out->writeU29(value); + out->writeByte(fixed ? 0x01 : 0x00); + if (marker == vector_object_marker) + { + out->writeStringVR(stringMap,vec_type->getName()); + } + for(uint32_t i=0;i<count;i++) + { + if (!vec[i]) + continue; + switch (marker) + { + case vector_int_marker: + out->writeUnsignedInt(out->endianIn((uint32_t)vec[i]->toInt())); + break; + case vector_uint_marker: + out->writeUnsignedInt(out->endianIn(vec[i]->toUInt())); + break; + case vector_double_marker: + out->serializeDouble(vec[i]->toNumber()); + break; + case vector_object_marker: + vec[i]->serialize(out, stringMap, objMap, traitsMap); + break; + } + } + } +}
View file
lightspark.tar.xz/src/scripting/toplevel/Vector.h
Changed
@@ -60,7 +60,7 @@ static ASObject* generator(TemplatedClass<Vector>* o_class, ASObject* const* args, const unsigned int argslen); void setTypes(const std::vector<const Type*>& types); - bool sameType(const QName& classname) const; + bool sameType(const Class_base* cls) const; //Overloads tiny_string toString(); @@ -69,6 +69,8 @@ _NR<ASObject> getVariableByMultiname(const multiname& name, GET_VARIABLE_OPTION opt); static bool isValidMultiname(const multiname& name, uint32_t& index); + tiny_string toJSON(std::vector<ASObject *> &path, IFunction *replacer, const tiny_string &spaces,const tiny_string& filter); + uint32_t nextNameIndex(uint32_t cur_index); _R<ASObject> nextName(uint32_t index); _R<ASObject> nextValue(uint32_t index); @@ -88,6 +90,7 @@ //Appends an object to the Vector. o is coerced to vec_type. //Takes ownership of o. void append(ASObject *o); + void setFixed(bool v) { fixed = v; } //TODO: do we need to implement generator? ASFUNCTION(_constructor); @@ -116,6 +119,11 @@ ASFUNCTION(slice); ASFUNCTION(every); ASFUNCTION(some); + + //Serialization interface + void serialize(ByteArray* out, std::map<tiny_string, uint32_t>& stringMap, + std::map<const ASObject*, uint32_t>& objMap, + std::map<const Class_base*, uint32_t>& traitsMap); }; }
View file
lightspark.tar.xz/src/scripting/toplevel/XML.cpp
Changed
@@ -127,6 +127,7 @@ c->setDeclaredMethodByQName("propertyIsEnumerable",AS3,Class<IFunction>::getFunction(_propertyIsEnumerable),NORMAL_METHOD,true); c->prototype->setVariableByQName("hasOwnProperty",AS3,Class<IFunction>::getFunction(_hasOwnProperty),DYNAMIC_TRAIT); c->setDeclaredMethodByQName("prependChild",AS3,Class<IFunction>::getFunction(_prependChild),NORMAL_METHOD,true); + c->setDeclaredMethodByQName("replace",AS3,Class<IFunction>::getFunction(_replace),NORMAL_METHOD,true); } ASFUNCTIONBODY(XML,generator) @@ -288,7 +289,7 @@ XMLVector ret; multiname mname(NULL); name->applyProxyProperty(mname); - th->getDescendantsByQName(name->toString(),"",mname.isAttribute,ret); + th->getDescendantsByQName(name->toString(),mname.isQName() ? mname.ns[0].getImpl().name : "",mname.isAttribute,ret); return Class<XMLList>::getInstanceS(ret,th->getChildrenlist(),multiname(NULL)); } @@ -326,6 +327,15 @@ { if (newChild->constructed) { + if (this == newChild.getPtr()) + throwError<TypeError>(kXMLIllegalCyclicalLoop); + _NR<XML> node = this->parentNode; + while (!node.isNull()) + { + if (node == newChild) + throwError<TypeError>(kXMLIllegalCyclicalLoop); + node = node->parentNode; + } this->incRef(); newChild->parentNode = _NR<XML>(this); childrenlist->append(newChild); @@ -2194,6 +2204,11 @@ { ret=nodevalue; } + else if (getNodeKind() == XML_COMMENT_NODE || + getNodeKind() == XML_PI_NODE) + { + ret=""; + } else if (hasSimpleContent()) { auto it = childrenlist->nodes.begin(); @@ -2214,41 +2229,7 @@ const tiny_string XML::encodeToXML(const tiny_string value, bool bIsAttribute) { - - tiny_string res; - auto it = value.begin(); - while (it != value.end()) - { - switch (*it) - { - case '<': - res += "<"; - break; - case '>': - res += bIsAttribute ? ">" : ">"; - break; - case '&': - res += "&"; - break; - case '\"': - res += bIsAttribute ? """ : "\""; - break; - case '\r': - res += bIsAttribute ? "
" : "\r"; - break; - case '\n': - res += bIsAttribute ? "
" : "\n"; - break; - case '\t': - res += bIsAttribute ? "	" : "\t"; - break; - default: - res += *it; - break; - } - it++; - } - return res; + return XMLBase::encodeToXML(value,bIsAttribute); } bool XML::getPrettyPrinting() @@ -2479,7 +2460,7 @@ else if(args[0]->getClass()==Class<XMLList>::getClass()) { XMLList* list=Class<XMLList>::cast(args[0]); - list->appendNodesTo(th); + list->prependNodesTo(th); th->incRef(); return th; } @@ -2491,7 +2472,7 @@ arg=_MR(Class<XML>::getInstanceS(args[0]->toString())); } - th->appendChild(arg); + th->prependChild(arg); th->incRef(); return th; } @@ -2499,10 +2480,90 @@ { if (newChild->constructed) { + if (this == newChild.getPtr()) + throwError<TypeError>(kXMLIllegalCyclicalLoop); + _NR<XML> node = this->parentNode; + while (!node.isNull()) + { + if (node == newChild) + throwError<TypeError>(kXMLIllegalCyclicalLoop); + node = node->parentNode; + } this->incRef(); newChild->parentNode = _NR<XML>(this); - childrenlist->append(newChild); + childrenlist->prepend(newChild); } else newChild->decRef(); } + +ASFUNCTIONBODY(XML,_replace) +{ + XML* th=Class<XML>::cast(obj); + _NR<ASObject> propertyName; + _NR<ASObject> value; + ARG_UNPACK(propertyName) (value); + + multiname name(NULL); + name.name_type=multiname::NAME_STRING; + if (propertyName->is<ASQName>()) + { + name.name_s_id=getSys()->getUniqueStringId(propertyName->as<ASQName>()->getLocalName()); + name.ns.push_back(nsNameAndKind(propertyName->as<ASQName>()->getURI(),NAMESPACE)); + } + else if (propertyName->toString() == "*") + { + if (value->is<XMLList>()) + { + th->childrenlist->decRef(); + value->incRef(); + th->childrenlist = _NR<XMLList>(value->as<XMLList>()); + } + else if (value->is<XML>()) + { + th->childrenlist->clear(); + value->incRef(); + th->childrenlist->append(_R<XML>(value->as<XML>())); + } + else + { + XML* x = Class<XML>::getInstanceS(value->toString()); + x->incRef(); + th->childrenlist->clear(); + th->childrenlist->append(_R<XML>(x)); + } + th->incRef(); + return th; + } + else + { + name.name_s_id=getSys()->getUniqueStringId(propertyName->toString()); + name.ns.push_back(nsNameAndKind("",NAMESPACE)); + } + uint32_t index=0; + if(XML::isValidMultiname(name,index)) + { + th->childrenlist->setVariableByMultiname(name,value.getPtr(),CONST_NOT_ALLOWED); + } + else if (th->hasPropertyByMultiname(name,true,false)) + { + if (value->is<XMLList>()) + { + th->deleteVariableByMultiname(name); + th->setVariableByMultiname(name,value.getPtr(),CONST_NOT_ALLOWED); + } + else if (value->is<XML>()) + { + th->deleteVariableByMultiname(name); + th->setVariableByMultiname(name,value.getPtr(),CONST_NOT_ALLOWED); + } + else + { + XML* x = Class<XML>::getInstanceS(value->toString()); + th->deleteVariableByMultiname(name); + th->setVariableByMultiname(name,x,CONST_NOT_ALLOWED); + } + } + th->incRef(); + return th; +}
View file
lightspark.tar.xz/src/scripting/toplevel/XML.h
Changed
@@ -134,6 +134,7 @@ ASFUNCTION(_propertyIsEnumerable); ASFUNCTION(_hasOwnProperty); ASFUNCTION(_prependChild); + ASFUNCTION(_replace); static void buildTraits(ASObject* o){} static void sinit(Class_base* c);
View file
lightspark.tar.xz/src/scripting/toplevel/XMLList.cpp
Changed
@@ -127,9 +127,8 @@ REGISTER_XML_DELEGATE2(namespace,_namespace); REGISTER_XML_DELEGATE(namespaceDeclarations); REGISTER_XML_DELEGATE(nodeKind); - REGISTER_XML_DELEGATE2(prependChild,_appendChild); + REGISTER_XML_DELEGATE2(prependChild,_prependChild); REGISTER_XML_DELEGATE(removeNamespace); - //REGISTER_XML_DELEGATE(replace); REGISTER_XML_DELEGATE2(setChildren,_setChildren); REGISTER_XML_DELEGATE2(setLocalName,_setLocalName); REGISTER_XML_DELEGATE2(setName,_setName); @@ -149,7 +148,6 @@ ASFUNCTIONBODY_XML_DELEGATE(nodeKind); ASFUNCTIONBODY_XML_DELEGATE(_prependChild); ASFUNCTIONBODY_XML_DELEGATE(removeNamespace); -//ASFUNCTIONBODY_XML_DELEGATE(replace); ASFUNCTIONBODY_XML_DELEGATE(_setChildren); ASFUNCTIONBODY_XML_DELEGATE(_setLocalName); ASFUNCTIONBODY_XML_DELEGATE(_setName); @@ -1172,3 +1170,15 @@ ret->decRef(); } } + +void XMLList::prependNodesTo(XML *dest) const +{ + std::vector<_R<XML>, reporter_allocator<_R<XML>>>::const_reverse_iterator it; + for (it=nodes.rbegin(); it!=nodes.rend(); ++it) + { + ASObject *arg0=it->getPtr(); + ASObject *ret=XML::_prependChild(dest, &arg0, 1); + if(ret) + ret->decRef(); + } +}
View file
lightspark.tar.xz/src/scripting/toplevel/XMLList.h
Changed
@@ -115,6 +115,7 @@ _R<ASObject> nextValue(uint32_t index); _R<XML> reduceToXML() const; void appendNodesTo(XML *dest) const; + void prependNodesTo(XML *dest) const; void normalize(); void clear(); XMLList* getTargetObject() { return targetobject; }
View file
lightspark.tar.xz/src/scripting/toplevel/toplevel.cpp
Changed
@@ -108,7 +108,7 @@ ASObject *Undefined::describeType() const { - return getSys()->getUndefinedRef(); + return ASObject::describeType(); } void Undefined::serialize(ByteArray* out, std::map<tiny_string, uint32_t>& stringMap, @@ -280,7 +280,9 @@ { const uint32_t opt_hit_threshold=1; const uint32_t jit_hit_threshold=20; - assert_and_throw(mi->body); + if (!mi->body) + return getSys()->getUndefinedRef(); + const uint16_t hit_count = mi->body->hit_count; const method_body_info::CODE_STATUS& codeStatus = mi->body->codeStatus; @@ -2166,6 +2168,7 @@ { o->incRef(); setVariableByQName(name,nsNameAndKind(ns,NAMESPACE),o.getPtr(),DECLARED_TRAIT); + //setVariableByQName(name,nsNameAndKind(ns,PACKAGE_NAMESPACE),o.getPtr(),DECLARED_TRAIT); } ASFUNCTIONBODY(lightspark,eval) @@ -2548,6 +2551,13 @@ return prevPrototype->getObj()->getVariableByMultiname(name, opt); } +void ObjectPrototype::setVariableByMultiname(const multiname &name, ASObject *o, ASObject::CONST_ALLOWED_FLAG allowConst) +{ + if (this->isSealed && this->hasPropertyByMultiname(name,false,true)) + throwError<ReferenceError>(kCannotAssignToMethodError, name.normalizedNameUnresolved(), ""); + ASObject::setVariableByMultiname(name, o, allowConst); +} + ObjectConstructor::ObjectConstructor(Class_base* c,uint32_t length) : ASObject(c),_length(length) {
View file
lightspark.tar.xz/src/scripting/toplevel/toplevel.h
Changed
@@ -260,11 +260,13 @@ class Prototype { public: - virtual ~Prototype() {}; + Prototype():isSealed(false) {} + virtual ~Prototype() {} _NR<Prototype> prevPrototype; virtual void incRef() = 0; virtual void decRef() = 0; virtual ASObject* getObj() = 0; + bool isSealed; /* * This method is actually forwarded to the object. It's here as a shorthand. */ @@ -286,6 +288,7 @@ void decRef() { ASObject::decRef(); } ASObject* getObj() { return this; } _NR<ASObject> getVariableByMultiname(const multiname& name, GET_VARIABLE_OPTION opt=NONE); + void setVariableByMultiname(const multiname& name, ASObject* o, CONST_ALLOWED_FLAG allowConst); bool isEqual(ASObject* r); };
View file
lightspark.tar.xz/src/swf.cpp
Changed
@@ -205,6 +205,8 @@ cookiesFileName = NULL; setTLSSys(this); + // it seems Adobe ignores any locale date settings + setlocale(LC_TIME, "en_US"); mainThread = Thread::self();
View file
lightspark.tar.xz/src/swf.h
Changed
@@ -263,7 +263,7 @@ bool showProfilingData; bool standalone; //Flash for execution mode - enum FLASH_MODE { FLASH=0, AIR }; + enum FLASH_MODE { FLASH=0, AIR, AVMPLUS }; const FLASH_MODE flashMode; // Error types used to decide when to exit, extend as a bitmap
View file
lightspark.tar.xz/src/tiny_string.cpp
Changed
@@ -508,7 +508,14 @@ uint32_t len = 0; for (CharIterator it=begin(); it!=end(); it++) { - gunichar c = g_unichar_tolower(*it); + gunichar c; + // Adobe player handles some Georgian chars not like glib does + if ( *it >= 0x10A0 && *it <= 0x10C5 ) + c = *it + 48; + else if (*it == 0x10C7 || *it == 0x10CD) + c = *it; + else + c = g_unichar_tolower(*it); gint n = g_unichar_to_utf8(c, p); p += n; len += n;
View file
lightspark.tar.xz/tests/make-tamarin
Changed
@@ -94,7 +94,7 @@ mkdir -p $CUR/tamarin-SWF/$(dirname $1) OUTPUT_SWF="$CUR/tamarin-SWF/${1/%ab[cs]/swf}" - COMMON="Assert.abc Utils.abc" + COMMON="Assert.abc Utils.abc $CUR/tamarin/test/acceptance/generated/intrinsics.abc" ABS_SUPPORT=$(if [[ -f ${1/%abc/abs} ]]; then echo abcasm/abs_helper.abc; fi) TEST_SUPPORT=$(if [[ -d ${1/%.abc/} ]]; then echo $(ls ${1/%.abc/}/*.abc 2> /dev/null); fi) sortSupportClasses @@ -109,13 +109,13 @@ # Exclude testcases that need imports from shell_toplevel (avmplus, # avmshell packages) until versioned identifiers are supported. function shouldExcludeTest() { - local asfile=${1/ab[cs]/as} - grep --quiet --no-messages "import avmplus\|import avmshell" "$asfile" - if [[ $? -eq 0 ]]; then - return 1 - else +# local asfile=${1/ab[cs]/as} +# grep --quiet --no-messages "import avmplus\|import avmshell" "$asfile" +# if [[ $? -eq 0 ]]; then +# return 1 +# else return 0 - fi +# fi } export -f linkTamarinTest sortSupportClasses shouldExcludeTest @@ -128,7 +128,7 @@ # incompatible with previous version of this script. Use Assert.as, a # file introduced in that commit, to detect the new test setup. if [[ -f $TAMARIN/test/acceptance/Assert.as ]]; then - makeTamarin2; + makeTamarin2 $1; else - makeTamarin1; + makeTamarin1 $1; fi
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.