| 341 | // definitions and invocations. These violate the Expression type, so we |
| 342 | // walk the tree as a raw object and return a raw object. |
| 343 | const walkObject = function(object) { |
| 344 | if (!goog.isObject(object)) return object; |
| 345 | const ret = Array.isArray(object) ? [] : {}; |
| 346 | const isNode = object instanceof Object.getPrototypeOf(ee.api.ValueNode); |
| 347 | const valueTable = isNode ? object.Serializable$values : object; |
| 348 | for (const [key, val] of Object.entries(valueTable)) { |
| 349 | if (!isNode) { |
| 350 | ret[key] = walkObject(val); // Always walk literal objects. |
| 351 | } else if (val === null) { |
| 352 | continue; // Serializable always skips null values. |
| 353 | } else if (key === 'functionDefinitionValue' && val.body != null) { |
| 354 | ret[key] = { |
| 355 | 'argumentNames': val.argumentNames, |
| 356 | 'body': walkObject(values[val.body]) |
| 357 | }; |
| 358 | } else if ( |
| 359 | key === 'functionInvocationValue' && val.functionReference != null) { |
| 360 | ret[key] = { |
| 361 | 'arguments': goog.object.map(val.arguments, walkObject), |
| 362 | 'functionReference': walkObject(values[val.functionReference]) |
| 363 | }; |
| 364 | } else if (key === 'constantValue') { |
| 365 | // Do not recurse into constants. |
| 366 | ret[key] = val === ee.apiclient.NULL_VALUE ? null : val; |
| 367 | } else { |
| 368 | ret[key] = walkObject(val); // Walk other ValueNode subtrees. |
| 369 | } |
| 370 | } |
| 371 | return ret; |
| 372 | }; |
| 373 | return encoded.result && walkObject(values[encoded.result]); |
| 374 | }; |
| 375 | |