From a9e60be7c711453e65d28826f7fe6fd429a856a9 Mon Sep 17 00:00:00 2001 From: Ray Greenwell Date: Sat, 9 Dec 2006 00:08:09 +0000 Subject: [PATCH] Another well-thought out actionscript feature: varags! In java, if you override a varargs method you can easily call super, you just have to do a wee cast: @Override public Stuff getStuff (int thing, Object... args) { return super.getStuff(thing, (Object[]) args); } In abjectscript: override public function getStuff (thing :int, ... args) :Stuff { // This doesn't work, because now 'args' to super is an array // containing OUR args array as its first element. return super.getStuff(thing, args); // We can fix things for super by 'apply'ing the function to // all the args in one array... args.unshift(thing); return super.apply(this, args); // But it could also be the case that someone is intentionally // passing an array to this method (many flash library methods take // varargs but also accept arrays and do this same thing). if (args.length == 1 && (args[0] is Array)) { args = (args[0] as Array); } return super.getStuff(thing, args); // super must ALSO do the unjimmying // OR, we could combine the two so that super doesn't have to // do unjimmying. } As a note, there is an 'arguments' object that is secretly placed in every function call, presumably so that callers can test whether an arg is the default value because the user didn't pass it in or whether it's the default because the user happened to pass in the default. Guess yourself, because that doesn't seem worth adding as a language feature. Anyway, the 'arguments' is not an array! You can't use it to call super via 'apply'. It's another associative hash. God bless you actionscript, you just make so much fucking sense. So I made a utility method for unfucking vargs. I bitch a lot, yes, but my bitching takes only a fraction of the time that was wasted discovering whatever it is I'm bitching about (this was fun to trace backwards to the source, oh yes), and maybe I can save others some time as a result. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@4477 542714f4-19e9-0310-aa3c-eee0fc999fb1 --- src/as/com/threerings/util/MessageBundle.as | 6 ++++++ src/as/com/threerings/util/StringUtil.as | 22 ++++++++++++++++++++- src/as/com/threerings/util/Util.as | 10 ++++++++++ 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/src/as/com/threerings/util/MessageBundle.as b/src/as/com/threerings/util/MessageBundle.as index fa8a07d26..86504d328 100644 --- a/src/as/com/threerings/util/MessageBundle.as +++ b/src/as/com/threerings/util/MessageBundle.as @@ -157,6 +157,8 @@ public class MessageBundle return key.substring(1); } + args = Util.unfuckVarargs(args); + // if this is a qualified key, we need to pass the buck to the // appropriate message bundle if (key.indexOf(QUAL_PREFIX) == 0) { @@ -263,6 +265,8 @@ public class MessageBundle */ public static function compose (key :String, ... args) :String { + args = Util.unfuckVarargs(args); + var buf :StringBuilder = new StringBuilder(); buf.append(key, "|"); for (var ii :int = 0; ii < args.length; ii++) { @@ -291,6 +295,8 @@ public class MessageBundle */ public static function tcompose (key :String, ... args) :String { + args = Util.unfuckVarargs(args); + for (var ii :int = 0; ii < args.length; ii++) { args[ii] = taint(args[ii]); } diff --git a/src/as/com/threerings/util/StringUtil.as b/src/as/com/threerings/util/StringUtil.as index 39ccd0ee2..fa067e4d4 100644 --- a/src/as/com/threerings/util/StringUtil.as +++ b/src/as/com/threerings/util/StringUtil.as @@ -96,7 +96,10 @@ public class StringUtil */ public static function substitute (str :String, ... args) :String { - return mx.utils.StringUtil.substitute(str, args); + // holy christ the varargs insanity + args = Util.unfuckVarargs(args); + args.unshift(str); + return mx.utils.StringUtil.substitute.apply(null, args); } /** @@ -107,6 +110,23 @@ public class StringUtil return mx.utils.StringUtil.trim(str); } + public static function toString (obj :Object) :String + { + if (obj is Array) { + var arr :Array = (obj as Array); + var s :String = "Array("; + for (var ii :int = 0; ii < arr.length; ii++) { + if (ii > 0) { + s += ", "; + } + s += (ii + ": " + toString(arr[ii])); + } + return s + ")"; + } + + return String(obj); + } + /** * Truncate the specified String if it is longer than maxLength. * The string will be truncated at a position such that it is diff --git a/src/as/com/threerings/util/Util.as b/src/as/com/threerings/util/Util.as index 3c9bcc7cf..8019c7a6e 100644 --- a/src/as/com/threerings/util/Util.as +++ b/src/as/com/threerings/util/Util.as @@ -52,6 +52,16 @@ public class Util return false; } + /** + * If you call a varargs method by passing it an array, the array + * will end up being arg 1. + */ + public static function unfuckVarargs (args :Array) :Array + { + return (args.length == 1 && (args[0] is Array)) ? (args[0] as Array) + : args; + } + public static function cast (obj :Object, clazz :Class) :Object { if (obj == null || obj is clazz) {