From 715a3724425532bbccd28bd49e9610e277614fc9 Mon Sep 17 00:00:00 2001 From: Jeff Dyer Date: Fri, 15 Mar 2013 11:36:32 -0700 Subject: [PATCH] URI mangling using base64 --- src/avm2/native.js | 2 +- src/avm2/parser.js | 65 ++++++++++++++++++++++++++++++--------------- src/avm2/runtime.js | 15 +++++++---- 3 files changed, 55 insertions(+), 27 deletions(-) diff --git a/src/avm2/native.js b/src/avm2/native.js index 21d321174..f38df3355 100644 --- a/src/avm2/native.js +++ b/src/avm2/native.js @@ -872,7 +872,7 @@ var natives = (function () { uriValue = String(uriValue); } else if (uriValue !== undefined) { - if (uriValue.constructor === Namespace) { + if (uriValue.constructor === ShumwayNamespace) { return uriValue.clone(); } } diff --git a/src/avm2/parser.js b/src/avm2/parser.js index e4fc7e387..036119553 100644 --- a/src/avm2/parser.js +++ b/src/avm2/parser.js @@ -312,12 +312,11 @@ var ShumwayNamespace = (function () { this.originalURI = this.uri = uri; buildNamespace.call(this); } + // Otherwise, we are creating an empty namespace to be build + // by the parse method. } function buildNamespace() { - //this.uri = this.uri.replace(/\.|:|-|\//gi,"$"); /* No dots, colons, dashes and /s */ - this.uri = escapeString(this.uri); - if (this.isPublic() && this.uri) { /* Strip the api version mark for now. */ var n = this.uri.length - 1; @@ -325,11 +324,30 @@ var ShumwayNamespace = (function () { if (mark > MIN_API_MARK) { this.uri = this.uri.substring(0, n - 1); } + } else if (this.isUnique()) { + // Make a psuedo unique id by concatenating current milliseconds to original uri + this.uri = String(this.uri+Date.now()); } + this.uri = mangleNamespaceString(this.uri); release || assert(kinds[this.kind]); this.qualifiedName = kinds[this.kind] + (this.uri ? "$" + this.uri : ""); } + function mangleNamespaceString(strIn) { + var buf = str2ab(strIn); + var strOut = base64ArrayBuffer(buf).replace(/=/g, ""); // Erase padding + return strOut; + + function str2ab(str) { + var buf = new ArrayBuffer(str.length); + var bufView = new Uint8Array(buf); + for (var i=0, strLen=str.length; i 0) { kindName = name.substring(0, name.indexOf(" ")).trim(); uri = name.substring(name.indexOf(" ") + 1).trim(); @@ -561,7 +584,7 @@ var Multiname = (function () { flags |= ATTRIBUTE; break; } - var mn = new Multiname(namespaces, escapeString(name), flags); + var mn = new Multiname(namespaces, name, flags); if (typeParameter) { mn.typeParameter = typeParameter; } @@ -621,12 +644,21 @@ var Multiname = (function () { if (typeof mn === "number" || typeof mn === "string" || mn instanceof Number) { return mn; } else { - return mn.qualifiedName || (mn.qualifiedName = mn.namespaces[0].qualifiedName + "$" + mn.name); + return mn.qualifiedName || (mn.qualifiedName = qualifyName(mn.namespaces[0].qualifiedName, mn.name)); + } + + function qualifyName(qualifier, name) { + return qualifier ? qualifier + "$" + name : name; } }; multiname.getPublicQualifiedName = function getPublicQualifiedName(name) { - return "public$" + name; + if (typeof name === "number") { + return name; + } else if (typeof name === "string") { + return "public$"+name; + } + release || assert(false, "Invalid input to Multiname.getPublicQualifiedName()"); }; multiname.getAccessModifier = function getAccessModifier(mn) { @@ -769,12 +801,12 @@ var Multiname = (function () { } else if (this.isRuntimeNamespace()) { str += "[]::" + this.nameToString(); } else if (this.namespaces.length === 1 && this.isQName()) { - str += this.namespaces[0].qualifiedName + "::"; + str += this.namespaces[0].toString() + "::"; str += this.nameToString(); } else { str += "{"; for (var i = 0, count = this.namespaces.length; i < count; i++) { - str += this.namespaces[i].qualifiedName; + str += this.namespaces[i].toString(); if (i + 1 < count) { str += ","; } @@ -785,20 +817,11 @@ var Multiname = (function () { if (this.hasTypeParameter()) { str += "<" + this.typeParameter.toString() + ">"; } - return str; }; - return multiname; })(); -function escapeString(str) { - if (str !== undefined) { - str = str.replace(/\.|:|-|\//gi,"$"); /* No dots, colons, dashes and /s */ - } - return str; -} - var ConstantPool = (function constantPool() { function constantPool(stream, name) { var i, n; diff --git a/src/avm2/runtime.js b/src/avm2/runtime.js index ab7dd1799..e30d4b6b0 100644 --- a/src/avm2/runtime.js +++ b/src/avm2/runtime.js @@ -1,4 +1,4 @@ -/* -*- Mode: js-mode; js-indent-level: 2; indent-tabs-mode: nil; tab-width: 4 -*- */ +/* -*- Mode: js; js-indent-level: 2; indent-tabs-mode: nil; tab-width: 4 -*- */ var runtimeOptions = systemOptions.register(new OptionSet("Runtime Options")); var traceScope = runtimeOptions.register(new Option("ts", "traceScope", "boolean", false, "trace scope execution")); @@ -1388,14 +1388,14 @@ var Runtime = (function () { * code that is executed and thus we defer compilation until |m| is actually called. To do this, we create a * trampoline that compiles |m| before executing it. * - * Tm = function trampoiline() { + * Tm = function trampoline() { * return compile(m).apply(this, arguments); * } * * Of course we don't want to recompile |m| every time it is called. We can optimize the trampoline a bit * so that it keeps track of repeated executions: * - * Tm = function trampoilineContext() { + * Tm = function trampolineContext() { * var c; * return function () { * if (!c) { @@ -1409,7 +1409,7 @@ var Runtime = (function () { * to patch the instance prototype to point to the compiled version instead, so that the trampoline doesn't get * called again. * - * Tm = function trampoilineContext() { + * Tm = function trampolineContext() { * var c; * return function () { * if (!c) { @@ -1576,6 +1576,11 @@ var Runtime = (function () { return target.value.bind(this); } if (this.hasOwnProperty(qn)) { + var pd = Object.getOwnPropertyDescriptor(this, qn); + if (pd.get) { + Counter.count("Runtime: Method Closures"); + return target.value.bind(this); + } Counter.count("Runtime: Unpatched Memoizer"); return this[qn]; } @@ -1749,7 +1754,7 @@ var Runtime = (function () { } else { typeClassName = "object"; } - return this.domain.getClass("packageInternal __AS3__$vec.Vector$" + typeClassName); + return this.domain.getClass("packageInternal __AS3__.vec.Vector$" + typeClassName); } else { return notImplemented(factoryClassName); }