Home | History | Annotate | Download | only in src
      1 // Copyright 2011 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef V8_JSON_PARSER_H_
      6 #define V8_JSON_PARSER_H_
      7 
      8 #include "src/factory.h"
      9 #include "src/objects.h"
     10 
     11 namespace v8 {
     12 namespace internal {
     13 
     14 enum ParseElementResult { kElementFound, kElementNotFound, kNullHandle };
     15 
     16 class JsonParseInternalizer BASE_EMBEDDED {
     17  public:
     18   static MaybeHandle<Object> Internalize(Isolate* isolate,
     19                                          Handle<Object> object,
     20                                          Handle<Object> reviver);
     21 
     22  private:
     23   JsonParseInternalizer(Isolate* isolate, Handle<JSReceiver> reviver)
     24       : isolate_(isolate), reviver_(reviver) {}
     25 
     26   MaybeHandle<Object> InternalizeJsonProperty(Handle<JSReceiver> holder,
     27                                               Handle<String> key);
     28 
     29   bool RecurseAndApply(Handle<JSReceiver> holder, Handle<String> name);
     30 
     31   Isolate* isolate_;
     32   Handle<JSReceiver> reviver_;
     33 };
     34 
     35 // A simple json parser.
     36 template <bool seq_one_byte>
     37 class JsonParser BASE_EMBEDDED {
     38  public:
     39   MUST_USE_RESULT static MaybeHandle<Object> Parse(Isolate* isolate,
     40                                                    Handle<String> source,
     41                                                    Handle<Object> reviver) {
     42     Handle<Object> result;
     43     ASSIGN_RETURN_ON_EXCEPTION(isolate, result,
     44                                JsonParser(isolate, source).ParseJson(), Object);
     45     if (reviver->IsCallable()) {
     46       return JsonParseInternalizer::Internalize(isolate, result, reviver);
     47     }
     48     return result;
     49   }
     50 
     51   static const int kEndOfString = -1;
     52 
     53  private:
     54   JsonParser(Isolate* isolate, Handle<String> source);
     55 
     56   // Parse a string containing a single JSON value.
     57   MaybeHandle<Object> ParseJson();
     58 
     59   INLINE(void Advance());
     60 
     61   // The JSON lexical grammar is specified in the ECMAScript 5 standard,
     62   // section 15.12.1.1. The only allowed whitespace characters between tokens
     63   // are tab, carriage-return, newline and space.
     64 
     65   INLINE(void AdvanceSkipWhitespace());
     66   INLINE(void SkipWhitespace());
     67   INLINE(uc32 AdvanceGetChar());
     68 
     69   // Checks that current charater is c.
     70   // If so, then consume c and skip whitespace.
     71   INLINE(bool MatchSkipWhiteSpace(uc32 c));
     72 
     73   // A JSON string (production JSONString) is subset of valid JavaScript string
     74   // literals. The string must only be double-quoted (not single-quoted), and
     75   // the only allowed backslash-escapes are ", /, \, b, f, n, r, t and
     76   // four-digit hex escapes (uXXXX). Any other use of backslashes is invalid.
     77   Handle<String> ParseJsonString() {
     78     return ScanJsonString<false>();
     79   }
     80 
     81   bool ParseJsonString(Handle<String> expected);
     82 
     83   Handle<String> ParseJsonInternalizedString() {
     84     Handle<String> result = ScanJsonString<true>();
     85     if (result.is_null()) return result;
     86     return factory()->InternalizeString(result);
     87   }
     88 
     89   template <bool is_internalized>
     90   Handle<String> ScanJsonString();
     91   // Creates a new string and copies prefix[start..end] into the beginning
     92   // of it. Then scans the rest of the string, adding characters after the
     93   // prefix. Called by ScanJsonString when reaching a '\' or non-Latin1 char.
     94   template <typename StringType, typename SinkChar>
     95   Handle<String> SlowScanJsonString(Handle<String> prefix, int start, int end);
     96 
     97   // A JSON number (production JSONNumber) is a subset of the valid JavaScript
     98   // decimal number literals.
     99   // It includes an optional minus sign, must have at least one
    100   // digit before and after a decimal point, may not have prefixed zeros (unless
    101   // the integer part is zero), and may include an exponent part (e.g., "e-10").
    102   // Hexadecimal and octal numbers are not allowed.
    103   Handle<Object> ParseJsonNumber();
    104 
    105   // Parse a single JSON value from input (grammar production JSONValue).
    106   // A JSON value is either a (double-quoted) string literal, a number literal,
    107   // one of "true", "false", or "null", or an object or array literal.
    108   Handle<Object> ParseJsonValue();
    109 
    110   // Parse a JSON object literal (grammar production JSONObject).
    111   // An object literal is a squiggly-braced and comma separated sequence
    112   // (possibly empty) of key/value pairs, where the key is a JSON string
    113   // literal, the value is a JSON value, and the two are separated by a colon.
    114   // A JSON array doesn't allow numbers and identifiers as keys, like a
    115   // JavaScript array.
    116   Handle<Object> ParseJsonObject();
    117 
    118   // Helper for ParseJsonObject. Parses the form "123": obj, which is recorded
    119   // as an element, not a property.
    120   ParseElementResult ParseElement(Handle<JSObject> json_object);
    121 
    122   // Parses a JSON array literal (grammar production JSONArray). An array
    123   // literal is a square-bracketed and comma separated sequence (possibly empty)
    124   // of JSON values.
    125   // A JSON array doesn't allow leaving out values from the sequence, nor does
    126   // it allow a terminal comma, like a JavaScript array does.
    127   Handle<Object> ParseJsonArray();
    128 
    129 
    130   // Mark that a parsing error has happened at the current token, and
    131   // return a null handle. Primarily for readability.
    132   inline Handle<Object> ReportUnexpectedCharacter() {
    133     return Handle<Object>::null();
    134   }
    135 
    136   inline Isolate* isolate() { return isolate_; }
    137   inline Factory* factory() { return factory_; }
    138   inline Handle<JSFunction> object_constructor() { return object_constructor_; }
    139 
    140   static const int kInitialSpecialStringLength = 32;
    141   static const int kPretenureTreshold = 100 * 1024;
    142 
    143  private:
    144   Zone* zone() { return &zone_; }
    145 
    146   void CommitStateToJsonObject(Handle<JSObject> json_object, Handle<Map> map,
    147                                ZoneList<Handle<Object> >* properties);
    148 
    149   Handle<String> source_;
    150   int source_length_;
    151   Handle<SeqOneByteString> seq_source_;
    152 
    153   PretenureFlag pretenure_;
    154   Isolate* isolate_;
    155   Factory* factory_;
    156   Zone zone_;
    157   Handle<JSFunction> object_constructor_;
    158   uc32 c0_;
    159   int position_;
    160 };
    161 
    162 }  // namespace internal
    163 }  // namespace v8
    164 
    165 #endif  // V8_JSON_PARSER_H_
    166