diff --git a/src/org/mozilla/javascript/NativeJSON.java b/src/org/mozilla/javascript/NativeJSON.java index 10a2dabfa0..d3393f6745 100644 --- a/src/org/mozilla/javascript/NativeJSON.java +++ b/src/org/mozilla/javascript/NativeJSON.java @@ -9,8 +9,8 @@ import java.util.Arrays; import java.util.Collection; import java.util.Iterator; +import java.util.LinkedHashSet; import java.util.LinkedList; -import java.util.List; import java.util.Map; import java.util.Stack; import org.mozilla.javascript.json.JsonParser; @@ -198,7 +198,7 @@ private static class StringifyState { String indent, String gap, Callable replacer, - List propertyList) { + Object[] propertyList) { this.cx = cx; this.scope = scope; @@ -212,7 +212,7 @@ private static class StringifyState { String indent; String gap; Callable replacer; - List propertyList; + Object[] propertyList; Context cx; Scriptable scope; @@ -223,22 +223,36 @@ public static Object stringify( String indent = ""; String gap = ""; - List propertyList = null; + Object[] propertyList = null; Callable replacerFunction = null; if (replacer instanceof Callable) { replacerFunction = (Callable) replacer; } else if (replacer instanceof NativeArray) { - propertyList = new LinkedList(); + LinkedHashSet propertySet = new LinkedHashSet(); NativeArray replacerArray = (NativeArray) replacer; for (int i : replacerArray.getIndexIds()) { Object v = replacerArray.get(i, replacerArray); - if (v instanceof String || v instanceof Number) { - propertyList.add(v); - } else if (v instanceof NativeString || v instanceof NativeNumber) { - propertyList.add(ScriptRuntime.toString(v)); + if (v instanceof String) { + propertySet.add(v); + } else if (v instanceof Number + || v instanceof NativeString + || v instanceof NativeNumber) { + // TODO: This should also apply to subclasses of NativeString and NativeNumber + // once the class, extends, and super keywords are implemented + propertySet.add(ScriptRuntime.toString(v)); } } + // After items have been converted to strings and duplicates removed, transform to an + // array and convert indexed keys back to Integers as required for later processing + propertyList = new Object[propertySet.size()]; + int i = 0; + for (Object prop : propertySet) { + ScriptRuntime.StringIdOrIndex idOrIndex = ScriptRuntime.toStringIdOrIndex(cx, prop); + // This will always be a String or Integer + propertyList[i++] = + (idOrIndex.stringId == null) ? idOrIndex.index : idOrIndex.stringId; + } } if (space instanceof NativeNumber) { @@ -374,12 +388,12 @@ private static String jo(Scriptable value, StringifyState state) { state.indent = state.indent + state.gap; Object[] k = null; if (state.propertyList != null) { - k = state.propertyList.toArray(); + k = state.propertyList; } else { k = value.getIds(); } - List partial = new LinkedList(); + Collection partial = new LinkedList(); for (Object p : k) { Object strP = str(p, value, state); @@ -420,7 +434,7 @@ private static String ja(NativeArray value, StringifyState state) { String stepback = state.indent; state.indent = state.indent + state.gap; - List partial = new LinkedList(); + Collection partial = new LinkedList(); long len = value.getLength(); for (long index = 0; index < len; index++) {