84 Node node;
85
86 try {
87 node = parser.parse();
88 } catch (final ParserException e) {
89 throw ECMAErrors.syntaxError(e, "invalid.json", e.getMessage());
90 }
91
92 final Global global = Context.getGlobal();
93 Object unfiltered = convertNode(global, node);
94 return applyReviver(global, unfiltered, reviver);
95 }
96
97 // -- Internals only below this point
98
99 // parse helpers
100
101 // apply 'reviver' function if available
102 private static Object applyReviver(final Global global, final Object unfiltered, final Object reviver) {
103 if (reviver instanceof ScriptFunction) {
104 assert global instanceof Global;
105 final ScriptObject root = global.newObject();
106 root.addOwnProperty("", Property.WRITABLE_ENUMERABLE_CONFIGURABLE, unfiltered);
107 return walk(root, "", (ScriptFunction)reviver);
108 }
109 return unfiltered;
110 }
111
112 // This is the abstract "Walk" operation from the spec.
113 private static Object walk(final ScriptObject holder, final Object name, final ScriptFunction reviver) {
114 final Object val = holder.get(name);
115 if (val instanceof ScriptObject) {
116 final ScriptObject valueObj = (ScriptObject)val;
117 final Iterator<String> iter = valueObj.propertyIterator();
118
119 while (iter.hasNext()) {
120 final String key = iter.next();
121 final Object newElement = walk(valueObj, key, reviver);
122
123 if (newElement == ScriptRuntime.UNDEFINED) {
124 valueObj.delete(key, false);
183 final String name = pNode.getKeyName();
184 final Object value = convertNode(global, valueNode);
185 setPropertyValue(object, name, value, false);
186 }
187
188 return object;
189 } else if (node instanceof UnaryNode) {
190 // UnaryNode used only to represent negative number JSON value
191 final UnaryNode unaryNode = (UnaryNode)node;
192 return -((LiteralNode<?>)unaryNode.rhs()).getNumber();
193 } else {
194 return null;
195 }
196 }
197
198 // add a new property if does not exist already, or else set old property
199 private static void setPropertyValue(final ScriptObject sobj, final String name, final Object value, final boolean strict) {
200 final int index = ArrayIndex.getArrayIndex(name);
201 if (ArrayIndex.isValidArrayIndex(index)) {
202 // array index key
203 sobj.defineOwnProperty(index, value);
204 } else if (sobj.getMap().findProperty(name) != null) {
205 // pre-existing non-inherited property, call set
206 sobj.set(name, value, strict);
207 } else {
208 // add new property
209 sobj.addOwnProperty(name, Property.WRITABLE_ENUMERABLE_CONFIGURABLE, value);
210 }
211 }
212
213 // does the given IR node represent a numeric array?
214 private static boolean isNumericArray(final Node[] values) {
215 for (final Node node : values) {
216 if (node instanceof LiteralNode && ((LiteralNode<?>)node).getValue() instanceof Number) {
217 continue;
218 }
219 return false;
220 }
221 return true;
222 }
223 }
|
84 Node node;
85
86 try {
87 node = parser.parse();
88 } catch (final ParserException e) {
89 throw ECMAErrors.syntaxError(e, "invalid.json", e.getMessage());
90 }
91
92 final Global global = Context.getGlobal();
93 Object unfiltered = convertNode(global, node);
94 return applyReviver(global, unfiltered, reviver);
95 }
96
97 // -- Internals only below this point
98
99 // parse helpers
100
101 // apply 'reviver' function if available
102 private static Object applyReviver(final Global global, final Object unfiltered, final Object reviver) {
103 if (reviver instanceof ScriptFunction) {
104 final ScriptObject root = global.newObject();
105 root.addOwnProperty("", Property.WRITABLE_ENUMERABLE_CONFIGURABLE, unfiltered);
106 return walk(root, "", (ScriptFunction)reviver);
107 }
108 return unfiltered;
109 }
110
111 // This is the abstract "Walk" operation from the spec.
112 private static Object walk(final ScriptObject holder, final Object name, final ScriptFunction reviver) {
113 final Object val = holder.get(name);
114 if (val instanceof ScriptObject) {
115 final ScriptObject valueObj = (ScriptObject)val;
116 final Iterator<String> iter = valueObj.propertyIterator();
117
118 while (iter.hasNext()) {
119 final String key = iter.next();
120 final Object newElement = walk(valueObj, key, reviver);
121
122 if (newElement == ScriptRuntime.UNDEFINED) {
123 valueObj.delete(key, false);
182 final String name = pNode.getKeyName();
183 final Object value = convertNode(global, valueNode);
184 setPropertyValue(object, name, value, false);
185 }
186
187 return object;
188 } else if (node instanceof UnaryNode) {
189 // UnaryNode used only to represent negative number JSON value
190 final UnaryNode unaryNode = (UnaryNode)node;
191 return -((LiteralNode<?>)unaryNode.rhs()).getNumber();
192 } else {
193 return null;
194 }
195 }
196
197 // add a new property if does not exist already, or else set old property
198 private static void setPropertyValue(final ScriptObject sobj, final String name, final Object value, final boolean strict) {
199 final int index = ArrayIndex.getArrayIndex(name);
200 if (ArrayIndex.isValidArrayIndex(index)) {
201 // array index key
202 sobj.defineOwnPropertyNoGap(index, value);
203 } else if (sobj.getMap().findProperty(name) != null) {
204 // pre-existing non-inherited property, call set
205 sobj.set(name, value, strict);
206 } else {
207 // add new property
208 sobj.addOwnProperty(name, Property.WRITABLE_ENUMERABLE_CONFIGURABLE, value);
209 }
210 }
211
212 // does the given IR node represent a numeric array?
213 private static boolean isNumericArray(final Node[] values) {
214 for (final Node node : values) {
215 if (node instanceof LiteralNode && ((LiteralNode<?>)node).getValue() instanceof Number) {
216 continue;
217 }
218 return false;
219 }
220 return true;
221 }
222 }
|