Пример #1
0
inline bool
JSONParser::finishArray(MutableHandleValue vp, ElementVector &elements)
{
    JS_ASSERT(&elements == &stack.back().elements());

    JSObject *obj = NewDenseCopiedArray(cx, elements.length(), elements.begin());
    if (!obj)
        return false;

    /* Try to assign a new type to the array according to its elements. */
    cx->compartment()->types.fixArrayType(cx, obj);

    vp.setObject(*obj);
    if (!freeElements.append(&elements))
        return false;
    stack.popBack();
    return true;
}
Пример #2
0
inline bool
JSONParserBase::finishArray(MutableHandleValue vp, ElementVector& elements)
{
    MOZ_ASSERT(&elements == &stack.back().elements());

    JSObject* obj = ObjectGroup::newArrayObject(cx, elements.begin(), elements.length(),
                                                GenericObject);
    if (!obj)
        return false;

    vp.setObject(*obj);
    if (!freeElements.append(&elements))
        return false;
    stack.popBack();

    if (!stack.empty() && stack.back().state == FinishArrayElement) {
        const ElementVector& elements = stack.back().elements();
        if (!CombineArrayElementTypes(cx, obj, elements.begin(), elements.length()))
            return false;
    }

    return true;
}
Пример #3
0
bool
JSONParser::parse(MutableHandleValue vp)
{
    RootedValue value(cx);
    JS_ASSERT(stack.empty());

    vp.setUndefined();

    Token token;
    ParserState state = JSONValue;
    while (true) {
        switch (state) {
          case FinishObjectMember: {
            PropertyVector &properties = stack.back().properties();
            properties.back().value = value;

            token = advanceAfterProperty();
            if (token == ObjectClose) {
                if (!finishObject(&value, properties))
                    return false;
                break;
            }
            if (token != Comma) {
                if (token == OOM)
                    return false;
                if (token != Error)
                    error("expected ',' or '}' after property-value pair in object literal");
                return errorReturn();
            }
            token = advancePropertyName();
            /* FALL THROUGH */
          }

          JSONMember:
            if (token == String) {
                jsid id = AtomToId(atomValue());
                PropertyVector &properties = stack.back().properties();
                if (!properties.append(IdValuePair(id)))
                    return false;
                token = advancePropertyColon();
                if (token != Colon) {
                    JS_ASSERT(token == Error);
                    return errorReturn();
                }
                goto JSONValue;
            }
            if (token == OOM)
                return false;
            if (token != Error)
                error("property names must be double-quoted strings");
            return errorReturn();

          case FinishArrayElement: {
            ElementVector &elements = stack.back().elements();
            if (!elements.append(value.get()))
                return false;
            token = advanceAfterArrayElement();
            if (token == Comma)
                goto JSONValue;
            if (token == ArrayClose) {
                if (!finishArray(&value, elements))
                    return false;
                break;
            }
            JS_ASSERT(token == Error);
            return errorReturn();
          }

          JSONValue:
          case JSONValue:
            token = advance();
          JSONValueSwitch:
            switch (token) {
              case String:
                value = stringValue();
                break;
              case Number:
                value = numberValue();
                break;
              case True:
                value = BooleanValue(true);
                break;
              case False:
                value = BooleanValue(false);
                break;
              case Null:
                value = NullValue();
                break;

              case ArrayOpen: {
                ElementVector *elements;
                if (!freeElements.empty()) {
                    elements = freeElements.popCopy();
                    elements->clear();
                } else {
                    elements = cx->new_<ElementVector>(cx);
                    if (!elements)
                        return false;
                }
                if (!stack.append(elements))
                    return false;

                token = advance();
                if (token == ArrayClose) {
                    if (!finishArray(&value, *elements))
                        return false;
                    break;
                }
                goto JSONValueSwitch;
              }

              case ObjectOpen: {
                PropertyVector *properties;
                if (!freeProperties.empty()) {
                    properties = freeProperties.popCopy();
                    properties->clear();
                } else {
                    properties = cx->new_<PropertyVector>(cx);
                    if (!properties)
                        return false;
                }
                if (!stack.append(properties))
                    return false;

                token = advanceAfterObjectOpen();
                if (token == ObjectClose) {
                    if (!finishObject(&value, *properties))
                        return false;
                    break;
                }
                goto JSONMember;
              }

              case ArrayClose:
              case ObjectClose:
              case Colon:
              case Comma:
                // Move the current pointer backwards so that the position
                // reported in the error message is correct.
                --current;
                error("unexpected character");
                return errorReturn();

              case OOM:
                return false;

              case Error:
                return errorReturn();
            }
            break;
        }

        if (stack.empty())
            break;
        state = stack.back().state;
    }

    for (; current < end; current++) {
        if (!IsJSONWhitespace(*current)) {
            error("unexpected non-whitespace character after JSON data");
            return errorReturn();
        }
    }

    JS_ASSERT(end == current);
    JS_ASSERT(stack.empty());

    vp.set(value);
    return true;
}