зеркало из https://github.com/mozilla/shumway.git
Fix dumpclass.js and make SourceTracer less dumb
This commit is contained in:
Родитель
e65d000ef1
Коммит
4aa448087c
|
@ -20,9 +20,10 @@ load("../../swf/text.js");
|
|||
|
||||
load("../util.js");
|
||||
load("../options.js");
|
||||
load("../metrics.js");
|
||||
|
||||
var Timer = metrics.Timer;
|
||||
var stdout = new IndentingWriter();
|
||||
|
||||
var ArgumentParser = options.ArgumentParser;
|
||||
var Option = options.Option;
|
||||
var OptionSet = options.OptionSet;
|
||||
|
@ -59,35 +60,22 @@ try {
|
|||
}
|
||||
|
||||
function forEachABC(swf, cb) {
|
||||
var dictionary = { };
|
||||
var controlTags = [];
|
||||
var buffer = snarf(swf, "binary");
|
||||
|
||||
SWF.parse(buffer, {
|
||||
onprogress: function(result) {
|
||||
var tags = result.tags.slice(i);
|
||||
var tag = tags[tags.length - 1];
|
||||
if (!('id' in tag) && !('ref' in tag)) {
|
||||
var pframes = cast(controlTags.concat(tags), dictionary);
|
||||
controlTags = [];
|
||||
var i = 0;
|
||||
var pframe;
|
||||
while (pframe = pframes[i++]) {
|
||||
var blocks = pframe.abcBlocks;
|
||||
if (blocks) {
|
||||
var j = 0;
|
||||
var block;
|
||||
while (block = blocks[j++]) {
|
||||
cb(new AbcFile(block));
|
||||
}
|
||||
}
|
||||
SWF.parse(snarf(swf, "binary"), {
|
||||
oncomplete: function(result) {
|
||||
var tags = result.tags;
|
||||
var abcCount = 0;
|
||||
for (var i = 0, n = tags.length; i < n; i++) {
|
||||
var tag = tags[i];
|
||||
if (tag.type === "abc") {
|
||||
cb(new AbcFile(tag.data));
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var writer = new IndentingWriter();
|
||||
var tracer = new SourceTracer(writer);
|
||||
forEachABC(swfFile.value, function (abc) {
|
||||
abc.scripts.forEach(function (script) {
|
||||
script.traits.traits.forEach(function (trait) {
|
||||
|
@ -95,10 +83,10 @@ forEachABC(swfFile.value, function (abc) {
|
|||
var cname = trait.classInfo.instanceInfo.name;
|
||||
if (cname.getName() === className.value) {
|
||||
writer.enter("package " + cname.namespaces[0].originalURI + " {\n");
|
||||
SourceTracer.traceMetadata(trait.metadata);
|
||||
SourceTracer.traceClass(trait.classInfo);
|
||||
tracer.traceMetadata(trait.metadata);
|
||||
tracer.traceClass(trait.classInfo);
|
||||
writer.leave("\n}");
|
||||
SourceTracer.traceClassStub(trait);
|
||||
tracer.traceClassStub(trait);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -206,7 +206,7 @@ MethodInfo.prototype.trace = function trace(writer, abc) {
|
|||
writer.leave("}");
|
||||
}
|
||||
|
||||
var SourceTracer = (function (writer) {
|
||||
var SourceTracer = (function () {
|
||||
function literal(value) {
|
||||
if (value === undefined) {
|
||||
return "undefined";
|
||||
|
@ -234,207 +234,216 @@ var SourceTracer = (function (writer) {
|
|||
}).join(", ");
|
||||
}
|
||||
|
||||
function SourceTracer(writer) {
|
||||
this.writer = writer;
|
||||
}
|
||||
|
||||
function traceTraits(traits, isStatic, inInterfaceNamespace) {
|
||||
traits.traits.forEach(function (trait) {
|
||||
var str;
|
||||
var accessModifier = trait.name.getAccessModifier();
|
||||
var namespaceName = trait.name.namespaces[0].originalURI;
|
||||
if (namespaceName) {
|
||||
if (namespaceName === "http://adobe.com/AS3/2006/builtin") {
|
||||
namespaceName = "AS3";
|
||||
}
|
||||
if (accessModifier === "public") {
|
||||
str = inInterfaceNamespace === namespaceName ? "" : namespaceName;
|
||||
SourceTracer.prototype = {
|
||||
traceTraits: function traceTraits(traits, isStatic, inInterfaceNamespace) {
|
||||
const writer = this.writer;
|
||||
const tracer = this;
|
||||
|
||||
traits.traits.forEach(function (trait) {
|
||||
var str;
|
||||
var accessModifier = trait.name.getAccessModifier();
|
||||
var namespaceName = trait.name.namespaces[0].originalURI;
|
||||
if (namespaceName) {
|
||||
if (namespaceName === "http://adobe.com/AS3/2006/builtin") {
|
||||
namespaceName = "AS3";
|
||||
}
|
||||
if (accessModifier === "public") {
|
||||
str = inInterfaceNamespace === namespaceName ? "" : namespaceName;
|
||||
} else {
|
||||
str = accessModifier;
|
||||
}
|
||||
} else {
|
||||
str = accessModifier;
|
||||
}
|
||||
} else {
|
||||
str = accessModifier;
|
||||
}
|
||||
if (isStatic) {
|
||||
str += " static";
|
||||
}
|
||||
if (trait.isSlot() || trait.isConst()) {
|
||||
traceMetadata(trait.metadata);
|
||||
if (trait.isConst()) {
|
||||
str += " const";
|
||||
} else {
|
||||
str += " var";
|
||||
if (isStatic) {
|
||||
str += " static";
|
||||
}
|
||||
str += " " + trait.name.getName();
|
||||
if (trait.typeName) {
|
||||
str += ":" + trait.typeName.getName();
|
||||
}
|
||||
if (trait.value) {
|
||||
str += " = " + literal(trait.value);
|
||||
}
|
||||
writer.writeLn(str + ";");
|
||||
} else if (trait.isMethod() || trait.isGetter() || trait.isSetter()) {
|
||||
traceMetadata(trait.metadata);
|
||||
var mi = trait.methodInfo;
|
||||
if (trait.attributes & ATTR_Override) {
|
||||
str += " override";
|
||||
}
|
||||
if (mi.isNative()) {
|
||||
str += " native";
|
||||
}
|
||||
str += " function";
|
||||
str += trait.isGetter() ? " get" : (trait.isSetter() ? " set" : "");
|
||||
str += " " + trait.name.getName();
|
||||
str += "(" + getSignature(mi) + ")";
|
||||
str += mi.returnType ? ":" + mi.returnType.getName() : "";
|
||||
if (mi.isNative()) {
|
||||
if (trait.isSlot() || trait.isConst()) {
|
||||
tracer.traceMetadata(trait.metadata);
|
||||
if (trait.isConst()) {
|
||||
str += " const";
|
||||
} else {
|
||||
str += " var";
|
||||
}
|
||||
str += " " + trait.name.getName();
|
||||
if (trait.typeName) {
|
||||
str += ":" + trait.typeName.getName();
|
||||
}
|
||||
if (trait.value) {
|
||||
str += " = " + literal(trait.value);
|
||||
}
|
||||
writer.writeLn(str + ";");
|
||||
} else {
|
||||
if (inInterfaceNamespace) {
|
||||
} else if (trait.isMethod() || trait.isGetter() || trait.isSetter()) {
|
||||
tracer.traceMetadata(trait.metadata);
|
||||
var mi = trait.methodInfo;
|
||||
if (trait.attributes & ATTR_Override) {
|
||||
str += " override";
|
||||
}
|
||||
if (mi.isNative()) {
|
||||
str += " native";
|
||||
}
|
||||
str += " function";
|
||||
str += trait.isGetter() ? " get" : (trait.isSetter() ? " set" : "");
|
||||
str += " " + trait.name.getName();
|
||||
str += "(" + getSignature(mi) + ")";
|
||||
str += mi.returnType ? ":" + mi.returnType.getName() : "";
|
||||
if (mi.isNative()) {
|
||||
writer.writeLn(str + ";");
|
||||
} else {
|
||||
writer.writeLn(str + " { notImplemented(\"" + trait.name.getName() + "\"); }");
|
||||
}
|
||||
}
|
||||
} else if (trait.isClass()) {
|
||||
var className = trait.classInfo.instanceInfo.name;
|
||||
writer.enter("package " + className.namespaces[0].originalURI + " {\n");
|
||||
traceMetadata(trait.metadata);
|
||||
traceClass(trait.classInfo);
|
||||
writer.leave("\n}");
|
||||
traceClassStub(trait);
|
||||
} else {
|
||||
notImplemented();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function traceClassStub(trait) {
|
||||
var ci = trait.classInfo;
|
||||
var ii = ci.instanceInfo;
|
||||
var name = ii.name.getName();
|
||||
var native = trait.metadata ? trait.metadata.native : null;
|
||||
if (!native) {
|
||||
return;
|
||||
}
|
||||
writer.enter("Shumway Stub {");
|
||||
writer.enter("natives." + native.cls + " = function " + native.cls + "(scope, instance, baseClass) {");
|
||||
writer.writeLn("// Signature: " + getSignature(ii.init));
|
||||
var initSignature = getSignature(ii.init, true);
|
||||
writer.writeLn("function " + name + "(" + initSignature + ") {");
|
||||
writer.writeLn(" instance.call(this" + (initSignature ? ", " + initSignature : "") + ")");
|
||||
writer.writeLn("};");
|
||||
writer.writeLn("var c = new Class(\"" + name + "\", " + name +
|
||||
", Class.passthroughCallable(" + name + "));");
|
||||
writer.writeLn("//");
|
||||
writer.writeLn("// WARNING! This sets:")
|
||||
writer.writeLn("// " + name + ".prototype = " +
|
||||
"Object.create(baseClass.instance.prototype)");
|
||||
writer.writeLn("//");
|
||||
writer.writeLn("// If you want to manage prototypes manually, do this instead:");
|
||||
writer.writeLn("// c.baseClass = baseClass");
|
||||
writer.writeLn("//");
|
||||
writer.writeLn("c.extend(baseClass);");
|
||||
|
||||
function traceTraits(traits, isStatic) {
|
||||
traits.traits.forEach(function (trait) {
|
||||
var traitName = trait.name.getName();
|
||||
if (trait.isMethod() || trait.isGetter() || trait.isSetter()) {
|
||||
var mi = trait.methodInfo;
|
||||
if (mi.isNative()) {
|
||||
var str = isStatic ? "s" : "m";
|
||||
if (mi.parameters.length) {
|
||||
var returnTypeStr = "";
|
||||
if (mi.returnType) {
|
||||
returnTypeStr = " -> " + mi.returnType.getName();
|
||||
}
|
||||
writer.writeLn("// Signature: " + getSignature(mi) + returnTypeStr);
|
||||
}
|
||||
var prop;
|
||||
if (trait.isGetter()) {
|
||||
prop = "[\"get " + traitName + "\"]";
|
||||
} else if (trait.isSetter()) {
|
||||
prop = "[\"set " + traitName + "\"]";
|
||||
if (inInterfaceNamespace) {
|
||||
writer.writeLn(str + ";");
|
||||
} else {
|
||||
prop = "." + traitName;
|
||||
writer.writeLn(str + " { notImplemented(\"" + trait.name.getName() + "\"); }");
|
||||
}
|
||||
str += prop + " = function " + traitName + "(" + getSignature(mi, true) + ")";
|
||||
writer.writeLn(str + " {");
|
||||
writer.writeLn(" notImplemented(\"" + name + "." + traitName + "\"); };");
|
||||
writer.writeLn("}");
|
||||
}
|
||||
} else if (trait.isClass()) {
|
||||
var className = trait.classInfo.instanceInfo.name;
|
||||
writer.enter("package " + className.namespaces[0].originalURI + " {\n");
|
||||
tracer.traceMetadata(trait.metadata);
|
||||
tracer.traceClass(trait.classInfo);
|
||||
writer.leave("\n}");
|
||||
tracer.traceClassStub(trait);
|
||||
} else {
|
||||
notImplemented();
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
writer.writeLn("var m = " + name + ".prototype;");
|
||||
writer.writeLn("var s = {};");
|
||||
traceClassStub: function traceClassStub(trait) {
|
||||
const writer = this.writer;
|
||||
|
||||
traceTraits(ci.traits, true);
|
||||
traceTraits(ii.traits);
|
||||
var ci = trait.classInfo;
|
||||
var ii = ci.instanceInfo;
|
||||
var name = ii.name.getName();
|
||||
var native = trait.metadata ? trait.metadata.native : null;
|
||||
if (!native) {
|
||||
return;
|
||||
}
|
||||
writer.enter("Shumway Stub {");
|
||||
writer.enter("natives." + native.cls + " = function " + native.cls + "(scope, instance, baseClass) {");
|
||||
writer.writeLn("// Signature: " + getSignature(ii.init));
|
||||
var initSignature = getSignature(ii.init, true);
|
||||
writer.writeLn("function " + name + "(" + initSignature + ") {");
|
||||
writer.writeLn(" instance.call(this" + (initSignature ? ", " + initSignature : "") + ")");
|
||||
writer.writeLn("};");
|
||||
writer.writeLn("var c = new Class(\"" + name + "\", " + name +
|
||||
", Class.passthroughCallable(" + name + "));");
|
||||
writer.writeLn("//");
|
||||
writer.writeLn("// WARNING! This sets:")
|
||||
writer.writeLn("// " + name + ".prototype = " +
|
||||
"Object.create(baseClass.instance.prototype)");
|
||||
writer.writeLn("//");
|
||||
writer.writeLn("// If you want to manage prototypes manually, do this instead:");
|
||||
writer.writeLn("// c.baseClass = baseClass");
|
||||
writer.writeLn("//");
|
||||
writer.writeLn("c.extend(baseClass);");
|
||||
|
||||
writer.writeLn("c.nativeMethods = m;");
|
||||
writer.writeLn("c.nativeStatics = s;");
|
||||
function traceTraits(traits, isStatic) {
|
||||
traits.traits.forEach(function (trait) {
|
||||
var traitName = trait.name.getName();
|
||||
if (trait.isMethod() || trait.isGetter() || trait.isSetter()) {
|
||||
var mi = trait.methodInfo;
|
||||
if (mi.isNative()) {
|
||||
var str = isStatic ? "s" : "m";
|
||||
if (mi.parameters.length) {
|
||||
var returnTypeStr = "";
|
||||
if (mi.returnType) {
|
||||
returnTypeStr = " -> " + mi.returnType.getName();
|
||||
}
|
||||
writer.writeLn("// Signature: " + getSignature(mi) + returnTypeStr);
|
||||
}
|
||||
var prop;
|
||||
if (trait.isGetter()) {
|
||||
prop = "[\"get " + traitName + "\"]";
|
||||
} else if (trait.isSetter()) {
|
||||
prop = "[\"set " + traitName + "\"]";
|
||||
} else {
|
||||
prop = "." + traitName;
|
||||
}
|
||||
str += prop + " = function " + traitName + "(" + getSignature(mi, true) + ")";
|
||||
writer.writeLn(str + " {");
|
||||
writer.writeLn(" notImplemented(\"" + name + "." + traitName + "\"); };");
|
||||
writer.writeLn("}");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
writer.writeLn("return c;");
|
||||
writer.leave("};");
|
||||
writer.leave("}");
|
||||
}
|
||||
writer.writeLn("var m = " + name + ".prototype;");
|
||||
writer.writeLn("var s = {};");
|
||||
|
||||
function traceClass(ci) {
|
||||
var ii = ci.instanceInfo;
|
||||
var name = ii.name;
|
||||
var str = name.getAccessModifier();
|
||||
if (ii.isFinal()) {
|
||||
str += " final";
|
||||
}
|
||||
if (!ii.isSealed()) {
|
||||
str += " dynamic";
|
||||
}
|
||||
str += ii.isInterface() ? " interface " : " class ";
|
||||
str += name.getName();
|
||||
if (ii.superName && ii.superName.getName() !== "Object") {
|
||||
str += " extends " + ii.superName.getName();
|
||||
}
|
||||
if (ii.interfaces.length) {
|
||||
str += " implements " + ii.interfaces.map(function (x) {
|
||||
return x.getName();
|
||||
}).join(", ");
|
||||
}
|
||||
writer.enter(str + " {");
|
||||
if (!ii.isInterface()) {
|
||||
writer.writeLn("public function " + name.getName() + "(" + getSignature(ii.init) + ") {}");
|
||||
}
|
||||
var interfaceNamespace;
|
||||
if (ii.isInterface()) {
|
||||
interfaceNamespace = name.namespaces[0].originalURI + ":" + name.name;
|
||||
}
|
||||
traceTraits(ci.traits, true, interfaceNamespace);
|
||||
traceTraits(ii.traits, false, interfaceNamespace);
|
||||
writer.leave("}");
|
||||
}
|
||||
traceTraits(ci.traits, true);
|
||||
traceTraits(ii.traits);
|
||||
|
||||
function traceMetadata(metadata) {
|
||||
for (var key in metadata) {
|
||||
if (metadata.hasOwnProperty(key)) {
|
||||
if (key.indexOf("__") === 0) {
|
||||
continue;
|
||||
writer.writeLn("c.nativeMethods = m;");
|
||||
writer.writeLn("c.nativeStatics = s;");
|
||||
|
||||
writer.writeLn("return c;");
|
||||
writer.leave("};");
|
||||
writer.leave("}");
|
||||
},
|
||||
|
||||
traceClass: function traceClass(ci) {
|
||||
const writer = this.writer;
|
||||
|
||||
var ii = ci.instanceInfo;
|
||||
var name = ii.name;
|
||||
var str = name.getAccessModifier();
|
||||
if (ii.isFinal()) {
|
||||
str += " final";
|
||||
}
|
||||
if (!ii.isSealed()) {
|
||||
str += " dynamic";
|
||||
}
|
||||
str += ii.isInterface() ? " interface " : " class ";
|
||||
str += name.getName();
|
||||
if (ii.superName && ii.superName.getName() !== "Object") {
|
||||
str += " extends " + ii.superName.getName();
|
||||
}
|
||||
if (ii.interfaces.length) {
|
||||
str += " implements " + ii.interfaces.map(function (x) {
|
||||
return x.getName();
|
||||
}).join(", ");
|
||||
}
|
||||
writer.enter(str + " {");
|
||||
if (!ii.isInterface()) {
|
||||
writer.writeLn("public function " + name.getName() + "(" + getSignature(ii.init) + ") {}");
|
||||
}
|
||||
var interfaceNamespace;
|
||||
if (ii.isInterface()) {
|
||||
interfaceNamespace = name.namespaces[0].originalURI + ":" + name.name;
|
||||
}
|
||||
this.traceTraits(ci.traits, true, interfaceNamespace);
|
||||
this.traceTraits(ii.traits, false, interfaceNamespace);
|
||||
writer.leave("}");
|
||||
},
|
||||
|
||||
traceMetadata: function traceMetadata(metadata) {
|
||||
const writer = this.writer;
|
||||
|
||||
for (var key in metadata) {
|
||||
if (metadata.hasOwnProperty(key)) {
|
||||
if (key.indexOf("__") === 0) {
|
||||
continue;
|
||||
}
|
||||
writer.writeLn("[" + key + "(" + metadata[key].items.map(function (m) {
|
||||
var str = m.key ? m.key + "=" : "";
|
||||
return str + "\"" + m.value + "\"";
|
||||
}).join(", ") + ")]");
|
||||
}
|
||||
writer.writeLn("[" + key + "(" + metadata[key].items.map(function (m) {
|
||||
var str = m.key ? m.key + "=" : "";
|
||||
return str + "\"" + m.value + "\"";
|
||||
}).join(", ") + ")]");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
traceMetadata: traceMetadata,
|
||||
traceTraits: traceTraits,
|
||||
traceClass: traceClass,
|
||||
traceClassStub: traceClassStub
|
||||
};
|
||||
});
|
||||
|
||||
return SourceTracer;
|
||||
})();
|
||||
|
||||
function traceSource(writer, abc) {
|
||||
var tracer = SourceTracer(writer);
|
||||
var tracer = new SourceTracer(writer);
|
||||
abc.scripts.forEach(function (script) {
|
||||
tracer.traceTraits(script.traits);
|
||||
});
|
||||
|
|
Загрузка…
Ссылка в новой задаче