JSONParser.h (22570B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: set ts=8 sts=2 et sw=2 tw=80: 3 * This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef vm_JSONParser_h 8 #define vm_JSONParser_h 9 10 #include "mozilla/Assertions.h" // MOZ_ASSERT 11 #include "mozilla/Attributes.h" // MOZ_STACK_CLASS 12 #include "mozilla/Maybe.h" // mozilla::{Maybe,Some} 13 #include "mozilla/Range.h" // mozilla::Range 14 #include "mozilla/RangedPtr.h" // mozilla::RangedPtr 15 16 #include <stddef.h> // size_t 17 #include <stdint.h> // uint32_t 18 #include <utility> // std::move 19 20 #include "builtin/ParseRecordObject.h" // js::ParseRecordObject 21 #include "ds/IdValuePair.h" // IdValuePair 22 #include "gc/GC.h" // AutoSelectGCHeap 23 #include "js/GCVector.h" // JS::GCVector 24 #include "js/RootingAPI.h" // JS::Handle, JS::MutableHandle, MutableWrappedPtrOperations 25 #include "js/Value.h" // JS::Value, JS::BooleanValue, JS::NullValue 26 #include "js/Vector.h" // Vector 27 #include "util/StringBuilder.h" // JSStringBuilder 28 #include "vm/StringType.h" // JSString, JSAtom 29 30 struct JSContext; 31 class JSTracer; 32 33 namespace js { 34 35 class FrontendContext; 36 37 enum class JSONToken { 38 String, 39 Number, 40 True, 41 False, 42 Null, 43 ArrayOpen, 44 ArrayClose, 45 ObjectOpen, 46 ObjectClose, 47 Colon, 48 Comma, 49 OOM, 50 Error 51 }; 52 53 enum class JSONStringType { PropertyName, LiteralValue }; 54 55 template <typename CharT, typename ParserT> 56 class MOZ_STACK_CLASS JSONTokenizer { 57 public: 58 using CharPtr = mozilla::RangedPtr<const CharT>; 59 60 using JSONStringBuilder = typename ParserT::JSONStringBuilder; 61 62 protected: 63 CharPtr sourceStart; 64 CharPtr current; 65 const CharPtr begin, end; 66 67 ParserT* parser = nullptr; 68 69 JSONTokenizer(CharPtr sourceStart, CharPtr current, const CharPtr begin, 70 const CharPtr end, ParserT* parser) 71 : sourceStart(sourceStart), 72 current(current), 73 begin(begin), 74 end(end), 75 parser(parser) { 76 MOZ_ASSERT(current <= end); 77 MOZ_ASSERT(parser); 78 } 79 80 public: 81 JSONTokenizer(CharPtr current, const CharPtr begin, const CharPtr end, 82 ParserT* parser) 83 : JSONTokenizer(current, current, begin, end, parser) {} 84 85 explicit JSONTokenizer(mozilla::Range<const CharT> data, ParserT* parser) 86 : JSONTokenizer(data.begin(), data.begin(), data.end(), parser) {} 87 88 JSONTokenizer(JSONTokenizer<CharT, ParserT>&& other) noexcept 89 : JSONTokenizer(other.sourceStart, other.current, other.begin, other.end, 90 other.parser) {} 91 92 JSONTokenizer(const JSONTokenizer<CharT, ParserT>& other) = delete; 93 void operator=(const JSONTokenizer<CharT, ParserT>& other) = delete; 94 95 void fixupParser(ParserT* newParser) { parser = newParser; } 96 97 void getTextPosition(uint32_t* column, uint32_t* line); 98 99 bool consumeTrailingWhitespaces(); 100 101 JSONToken advance(); 102 JSONToken advancePropertyName(); 103 JSONToken advancePropertyColon(); 104 JSONToken advanceAfterProperty(); 105 JSONToken advanceAfterObjectOpen(); 106 JSONToken advanceAfterArrayElement(); 107 108 void unget() { --current; } 109 110 #ifdef DEBUG 111 bool finished() { return end == current; } 112 #endif 113 114 JSONToken token(JSONToken t) { 115 MOZ_ASSERT(t != JSONToken::String); 116 MOZ_ASSERT(t != JSONToken::Number); 117 return t; 118 } 119 120 template <JSONStringType ST> 121 JSONToken stringToken(const CharPtr start, size_t length); 122 template <JSONStringType ST> 123 JSONToken stringToken(JSONStringBuilder& builder); 124 125 JSONToken numberToken(double d); 126 127 template <JSONStringType ST> 128 JSONToken readString(); 129 130 JSONToken readNumber(); 131 132 void error(const char* msg); 133 134 protected: 135 inline mozilla::Span<const CharT> getSource() const { 136 return mozilla::Span<const CharT>(sourceStart.get(), current.get()); 137 } 138 }; 139 140 // Possible states the parser can be in between values. 141 enum class JSONParserState { 142 // An array element has just being parsed. 143 FinishArrayElement, 144 145 // An object property has just been parsed. 146 FinishObjectMember, 147 148 // At the start of the parse, before any values have been processed. 149 JSONValue 150 }; 151 152 // Character-type-agnostic base class for JSONFullParseHandler. 153 // JSONParser is templatized to work on either Latin1 154 // or TwoByte input strings, JSONFullParseHandlerAnyChar holds all state and 155 // methods that can be shared between the two encodings. 156 class MOZ_STACK_CLASS JSONFullParseHandlerAnyChar { 157 public: 158 // State related to the parser's current position. At all points in the 159 // parse this keeps track of the stack of arrays and objects which have 160 // been started but not finished yet. The actual JS object is not 161 // allocated until the literal is closed, so that the result can be sized 162 // according to its contents and have its type and shape filled in using 163 // caches. 164 165 // State for an array that is currently being parsed. This includes all 166 // elements that have been seen so far. 167 using ElementVector = JS::GCVector<JS::Value, 20>; 168 169 // State for an object that is currently being parsed. This includes all 170 // the key/value pairs that have been seen so far. 171 using PropertyVector = IdValueVector; 172 173 enum class ParseType { 174 // Parsing a string as if by JSON.parse. 175 JSONParse, 176 // Parsing what may or may not be JSON in a string of eval code. 177 // In this case, a failure to parse indicates either syntax that isn't JSON, 178 // or syntax that has different semantics in eval code than in JSON. 179 AttemptForEval, 180 }; 181 182 // Stack element for an in progress array or object. 183 struct StackEntry { 184 ElementVector& elements() { 185 MOZ_ASSERT(state == JSONParserState::FinishArrayElement); 186 return *static_cast<ElementVector*>(vector); 187 } 188 189 PropertyVector& properties() { 190 MOZ_ASSERT(state == JSONParserState::FinishObjectMember); 191 return *static_cast<PropertyVector*>(vector); 192 } 193 194 explicit StackEntry(JSContext* cx, ElementVector* elements) 195 : state(JSONParserState::FinishArrayElement), vector(elements) {} 196 197 explicit StackEntry(JSContext* cx, PropertyVector* properties) 198 : state(JSONParserState::FinishObjectMember), vector(properties) {} 199 200 JSONParserState state; 201 202 private: 203 void* vector; 204 }; 205 206 public: 207 /* Data members */ 208 209 JSContext* cx; 210 211 bool reportLineNumbersFromParsedData = false; 212 213 mozilla::Maybe<JS::ConstUTF8CharsZ> filename; 214 215 JS::Value v; 216 217 ParseType parseType = ParseType::JSONParse; 218 219 AutoSelectGCHeap gcHeap; 220 221 private: 222 // Unused element and property vectors for previous in progress arrays and 223 // objects. These vectors are not freed until the end of the parse to avoid 224 // unnecessary freeing and allocation. 225 Vector<ElementVector*, 5> freeElements; 226 Vector<PropertyVector*, 5> freeProperties; 227 228 public: 229 explicit JSONFullParseHandlerAnyChar(JSContext* cx); 230 ~JSONFullParseHandlerAnyChar(); 231 232 // Allow move construction for use with Rooted. 233 JSONFullParseHandlerAnyChar(JSONFullParseHandlerAnyChar&& other) noexcept; 234 235 JSONFullParseHandlerAnyChar(const JSONFullParseHandlerAnyChar& other) = 236 delete; 237 void operator=(const JSONFullParseHandlerAnyChar& other) = delete; 238 239 JSContext* context() { return cx; } 240 241 JS::Value numberValue() const { 242 MOZ_ASSERT(v.isNumber()); 243 return v; 244 } 245 246 JS::Value stringValue() const { 247 MOZ_ASSERT(v.isString()); 248 return v; 249 } 250 251 JSAtom* atomValue() const { 252 JS::Value strval = stringValue(); 253 return &strval.toString()->asAtom(); 254 } 255 256 inline JS::Value booleanValue(bool value) { return JS::BooleanValue(value); } 257 inline JS::Value nullValue() { return JS::NullValue(); } 258 259 inline bool objectOpen(Vector<StackEntry, 10>& stack, 260 PropertyVector** properties); 261 inline bool objectPropertyName(Vector<StackEntry, 10>& stack, 262 bool* isProtoInEval); 263 inline bool finishObjectMember(Vector<StackEntry, 10>& stack, 264 JS::Handle<JS::Value> value, 265 PropertyVector** properties); 266 inline bool finishObject(Vector<StackEntry, 10>& stack, 267 JS::MutableHandle<JS::Value> vp, 268 PropertyVector* properties); 269 270 inline bool arrayOpen(Vector<StackEntry, 10>& stack, 271 ElementVector** elements); 272 inline bool arrayElement(Vector<StackEntry, 10>& stack, 273 JS::Handle<JS::Value> value, 274 ElementVector** elements); 275 inline bool finishArray(Vector<StackEntry, 10>& stack, 276 JS::MutableHandle<JS::Value> vp, 277 ElementVector* elements); 278 279 inline bool errorReturn() const { 280 return parseType == ParseType::AttemptForEval; 281 } 282 283 inline bool ignoreError() const { 284 return parseType == ParseType::AttemptForEval; 285 } 286 287 inline void freeStackEntry(StackEntry& entry); 288 289 void trace(JSTracer* trc); 290 }; 291 292 template <typename CharT> 293 class MOZ_STACK_CLASS JSONFullParseHandler 294 : public JSONFullParseHandlerAnyChar { 295 using Base = JSONFullParseHandlerAnyChar; 296 using CharPtr = mozilla::RangedPtr<const CharT>; 297 298 public: 299 using ContextT = JSContext; 300 301 class JSONStringBuilder { 302 public: 303 JSStringBuilder buffer; 304 305 explicit JSONStringBuilder(JSContext* cx) : buffer(cx) {} 306 307 bool append(char16_t c); 308 bool append(const CharT* begin, const CharT* end); 309 }; 310 311 explicit JSONFullParseHandler(JSContext* cx) : Base(cx) {} 312 313 JSONFullParseHandler(JSONFullParseHandler&& other) noexcept 314 : Base(std::move(other)) {} 315 316 JSONFullParseHandler(const JSONFullParseHandler& other) = delete; 317 void operator=(const JSONFullParseHandler& other) = delete; 318 319 template <JSONStringType ST> 320 inline bool setStringValue(CharPtr start, size_t length, 321 mozilla::Span<const CharT>&& source); 322 template <JSONStringType ST> 323 inline bool setStringValue(JSONStringBuilder& builder, 324 mozilla::Span<const CharT>&& source); 325 inline bool setNumberValue(double d, mozilla::Span<const CharT>&& source); 326 inline bool setBooleanValue(bool value, mozilla::Span<const CharT>&& source); 327 inline bool setNullValue(mozilla::Span<const CharT>&& source); 328 329 void reportError(const char* msg, uint32_t line, uint32_t column); 330 }; 331 332 template <typename CharT> 333 class MOZ_STACK_CLASS JSONReviveHandler : public JSONFullParseHandler<CharT> { 334 using CharPtr = mozilla::RangedPtr<const CharT>; 335 using Base = JSONFullParseHandler<CharT>; 336 337 public: 338 using SourceT = mozilla::Span<const CharT>; 339 340 using JSONStringBuilder = typename Base::JSONStringBuilder; 341 using StackEntry = typename Base::StackEntry; 342 using PropertyVector = typename Base::PropertyVector; 343 using ElementVector = typename Base::ElementVector; 344 345 public: 346 explicit JSONReviveHandler(JSContext* cx) : Base(cx), parseRecordStack(cx) {} 347 348 JSONReviveHandler(JSONReviveHandler&& other) noexcept 349 : Base(std::move(other)), 350 parseRecordStack(std::move(other.parseRecordStack)) {} 351 352 JSONReviveHandler(const JSONReviveHandler& other) = delete; 353 void operator=(const JSONReviveHandler& other) = delete; 354 355 JSContext* context() { return this->cx; } 356 357 template <JSONStringType ST> 358 inline bool setStringValue(CharPtr start, size_t length, SourceT&& source) { 359 if (!Base::template setStringValue<ST>(start, length, 360 std::forward<SourceT&&>(source))) { 361 return false; 362 } 363 return finishPrimitiveParseRecord(this->v, source); 364 } 365 366 template <JSONStringType ST> 367 inline bool setStringValue(JSONStringBuilder& builder, SourceT&& source) { 368 if (!Base::template setStringValue<ST>(builder, 369 std::forward<SourceT&&>(source))) { 370 return false; 371 } 372 return finishPrimitiveParseRecord(this->v, source); 373 } 374 375 inline bool setNumberValue(double d, SourceT&& source) { 376 if (!Base::setNumberValue(d, std::forward<SourceT&&>(source))) { 377 return false; 378 } 379 return finishPrimitiveParseRecord(this->v, source); 380 } 381 382 inline bool setBooleanValue(bool value, SourceT&& source) { 383 return finishPrimitiveParseRecord(JS::BooleanValue(value), source); 384 } 385 inline bool setNullValue(SourceT&& source) { 386 return finishPrimitiveParseRecord(JS::NullValue(), source); 387 } 388 389 inline bool objectOpen(Vector<StackEntry, 10>& stack, 390 PropertyVector** properties); 391 inline bool finishObjectMember(Vector<StackEntry, 10>& stack, 392 JS::Handle<JS::Value> value, 393 PropertyVector** properties); 394 inline bool finishObject(Vector<StackEntry, 10>& stack, 395 JS::MutableHandle<JS::Value> vp, 396 PropertyVector* properties); 397 398 inline bool arrayOpen(Vector<StackEntry, 10>& stack, 399 ElementVector** elements); 400 inline bool arrayElement(Vector<StackEntry, 10>& stack, 401 JS::Handle<JS::Value> value, 402 ElementVector** elements); 403 inline bool finishArray(Vector<StackEntry, 10>& stack, 404 JS::MutableHandle<JS::Value> vp, 405 ElementVector* elements); 406 407 void trace(JSTracer* trc); 408 409 inline ParseRecordObject* getParseRecordObject() { 410 return parseRecordStack.back(); 411 }; 412 413 private: 414 inline bool finishPrimitiveParseRecord(const Value& value, SourceT source); 415 416 GCVector<ParseRecordObject*, 10> parseRecordStack; 417 }; 418 419 template <typename CharT> 420 class MOZ_STACK_CLASS JSONSyntaxParseHandler { 421 private: 422 using CharPtr = mozilla::RangedPtr<const CharT>; 423 424 public: 425 /* Types for templatized parser. */ 426 427 using ContextT = FrontendContext; 428 429 class DummyValue {}; 430 431 struct ElementVector {}; 432 struct PropertyVector {}; 433 434 class JSONStringBuilder { 435 public: 436 explicit JSONStringBuilder(FrontendContext* fc) {} 437 438 bool append(char16_t c) { return true; } 439 bool append(const CharT* begin, const CharT* end) { return true; } 440 }; 441 442 struct StackEntry { 443 JSONParserState state; 444 }; 445 446 public: 447 FrontendContext* fc; 448 449 /* Public API */ 450 451 /* Create a parser for the provided JSON data. */ 452 explicit JSONSyntaxParseHandler(FrontendContext* fc) : fc(fc) {} 453 454 JSONSyntaxParseHandler(JSONSyntaxParseHandler&& other) noexcept 455 : fc(other.fc) {} 456 457 JSONSyntaxParseHandler(const JSONSyntaxParseHandler& other) = delete; 458 void operator=(const JSONSyntaxParseHandler& other) = delete; 459 460 FrontendContext* context() { return fc; } 461 462 template <JSONStringType ST> 463 inline bool setStringValue(CharPtr start, size_t length, 464 mozilla::Span<const CharT>&& source) { 465 return true; 466 } 467 468 template <JSONStringType ST> 469 inline bool setStringValue(JSONStringBuilder& builder, 470 mozilla::Span<const CharT>&& source) { 471 return true; 472 } 473 474 inline bool setNumberValue(double d, mozilla::Span<const CharT>&& source) { 475 return true; 476 } 477 inline bool setBooleanValue(bool value, mozilla::Span<const CharT>&& source) { 478 return true; 479 } 480 inline bool setNullValue(mozilla::Span<const CharT>&& source) { return true; } 481 482 inline DummyValue numberValue() const { return DummyValue(); } 483 484 inline DummyValue stringValue() const { return DummyValue(); } 485 486 inline DummyValue booleanValue(bool value) { return DummyValue(); } 487 inline DummyValue nullValue() { return DummyValue(); } 488 489 inline bool objectOpen(Vector<StackEntry, 10>& stack, 490 PropertyVector** properties); 491 inline bool objectPropertyName(Vector<StackEntry, 10>& stack, 492 bool* isProtoInEval) { 493 *isProtoInEval = false; 494 return true; 495 } 496 inline bool finishObjectMember(Vector<StackEntry, 10>& stack, 497 DummyValue& value, 498 PropertyVector** properties) { 499 return true; 500 } 501 inline bool finishObject(Vector<StackEntry, 10>& stack, DummyValue* vp, 502 PropertyVector* properties); 503 504 inline bool arrayOpen(Vector<StackEntry, 10>& stack, 505 ElementVector** elements); 506 inline bool arrayElement(Vector<StackEntry, 10>& stack, DummyValue& value, 507 ElementVector** elements) { 508 return true; 509 } 510 inline bool finishArray(Vector<StackEntry, 10>& stack, DummyValue* vp, 511 ElementVector* elements); 512 513 inline bool errorReturn() const { return false; } 514 515 inline bool ignoreError() const { return false; } 516 517 inline void freeStackEntry(StackEntry& entry) {} 518 519 void reportError(const char* msg, uint32_t line, uint32_t column); 520 }; 521 522 template <typename CharT, typename HandlerT> 523 class MOZ_STACK_CLASS JSONPerHandlerParser { 524 using ContextT = typename HandlerT::ContextT; 525 526 using Tokenizer = JSONTokenizer<CharT, JSONPerHandlerParser<CharT, HandlerT>>; 527 528 public: 529 using JSONStringBuilder = typename HandlerT::JSONStringBuilder; 530 531 public: 532 HandlerT handler; 533 Tokenizer tokenizer; 534 535 // All in progress arrays and objects being parsed, in order from outermost 536 // to innermost. 537 Vector<typename HandlerT::StackEntry, 10> stack; 538 539 public: 540 JSONPerHandlerParser(ContextT* context, mozilla::Range<const CharT> data) 541 : handler(context), tokenizer(data, this), stack(context) {} 542 543 JSONPerHandlerParser(JSONPerHandlerParser&& other) noexcept 544 : handler(std::move(other.handler)), 545 tokenizer(std::move(other.tokenizer)), 546 stack(handler.context()) { 547 tokenizer.fixupParser(this); 548 } 549 550 ~JSONPerHandlerParser(); 551 552 JSONPerHandlerParser(const JSONPerHandlerParser<CharT, HandlerT>& other) = 553 delete; 554 void operator=(const JSONPerHandlerParser<CharT, HandlerT>& other) = delete; 555 556 template <typename TempValueT, typename ResultSetter> 557 inline bool parseImpl(TempValueT& value, ResultSetter setResult); 558 559 void outOfMemory(); 560 561 void error(const char* msg); 562 }; 563 564 template <typename CharT> 565 class MOZ_STACK_CLASS JSONParser 566 : JSONPerHandlerParser<CharT, JSONFullParseHandler<CharT>> { 567 using Base = JSONPerHandlerParser<CharT, JSONFullParseHandler<CharT>>; 568 569 public: 570 using ParseType = JSONFullParseHandlerAnyChar::ParseType; 571 572 /* Public API */ 573 574 /* Create a parser for the provided JSON data. */ 575 JSONParser(JSContext* cx, mozilla::Range<const CharT> data, 576 ParseType parseType) 577 : Base(cx, data) { 578 this->handler.parseType = parseType; 579 } 580 581 /* Allow move construction for use with Rooted. */ 582 JSONParser(JSONParser&& other) noexcept : Base(std::move(other)) {} 583 584 JSONParser(const JSONParser& other) = delete; 585 void operator=(const JSONParser& other) = delete; 586 587 /* 588 * Parse the JSON data specified at construction time. If it parses 589 * successfully, store the prescribed value in *vp and return true. If an 590 * internal error (e.g. OOM) occurs during parsing, return false. 591 * Otherwise, if invalid input was specifed but no internal error occurred, 592 * behavior depends upon the error handling specified at construction: if 593 * error handling is RaiseError then throw a SyntaxError and return false, 594 * otherwise return true and set *vp to |undefined|. (JSON syntax can't 595 * represent |undefined|, so the JSON data couldn't have specified it.) 596 */ 597 bool parse(JS::MutableHandle<JS::Value> vp); 598 599 void reportLineNumbersFromParsedData(bool b) { 600 this->handler.reportLineNumbersFromParsedData = b; 601 } 602 603 /** 604 * Set a filename to be used in error messages. 605 * This is optional and only used for error reporting. 606 */ 607 void setFilename(JS::ConstUTF8CharsZ filename) { 608 this->handler.filename = mozilla::Some(filename); 609 } 610 611 void trace(JSTracer* trc); 612 }; 613 614 template <typename CharT> 615 class MOZ_STACK_CLASS JSONReviveParser 616 : JSONPerHandlerParser<CharT, JSONReviveHandler<CharT>> { 617 using Base = JSONPerHandlerParser<CharT, JSONReviveHandler<CharT>>; 618 619 public: 620 using ParseType = JSONFullParseHandlerAnyChar::ParseType; 621 622 /* Public API */ 623 624 /* Create a parser for the provided JSON data. */ 625 JSONReviveParser(JSContext* cx, mozilla::Range<const CharT> data) 626 : Base(cx, data) {} 627 628 /* Allow move construction for use with Rooted. */ 629 JSONReviveParser(JSONReviveParser&& other) noexcept 630 : Base(std::move(other)) {} 631 632 JSONReviveParser(const JSONReviveParser& other) = delete; 633 void operator=(const JSONReviveParser& other) = delete; 634 635 /* 636 * Parse the JSON data specified at construction time. If it parses 637 * successfully, store the prescribed value in *vp and return true. If an 638 * internal error (e.g. OOM) occurs during parsing, return false. 639 * Otherwise, if invalid input was specifed but no internal error occurred, 640 * behavior depends upon the error handling specified at construction: if 641 * error handling is RaiseError then throw a SyntaxError and return false, 642 * otherwise return true and set *vp to |undefined|. (JSON syntax can't 643 * represent |undefined|, so the JSON data couldn't have specified it.) 644 * 645 * If it parses successfully, parse information for calling the reviver 646 * function is stored in *pro. If this function returns false, *pro will be 647 * set to |undefined|. 648 */ 649 bool parse(JS::MutableHandle<JS::Value> vp, 650 JS::MutableHandle<ParseRecordObject*> pro); 651 652 void trace(JSTracer* trc); 653 }; 654 655 template <typename CharT, typename Wrapper> 656 class MutableWrappedPtrOperations<JSONParser<CharT>, Wrapper> 657 : public WrappedPtrOperations<JSONParser<CharT>, Wrapper> { 658 public: 659 bool parse(JS::MutableHandle<JS::Value> vp) { 660 return static_cast<Wrapper*>(this)->get().parse(vp); 661 } 662 void setFilename(JS::ConstUTF8CharsZ filename) { 663 static_cast<Wrapper*>(this)->get().setFilename(filename); 664 } 665 void reportLineNumbersFromParsedData(bool b) { 666 static_cast<Wrapper*>(this)->get().reportLineNumbersFromParsedData(b); 667 } 668 }; 669 670 template <typename CharT> 671 class MOZ_STACK_CLASS JSONSyntaxParser 672 : JSONPerHandlerParser<CharT, JSONSyntaxParseHandler<CharT>> { 673 using HandlerT = JSONSyntaxParseHandler<CharT>; 674 using Base = JSONPerHandlerParser<CharT, HandlerT>; 675 676 public: 677 JSONSyntaxParser(FrontendContext* fc, mozilla::Range<const CharT> data) 678 : Base(fc, data) {} 679 680 JSONSyntaxParser(JSONSyntaxParser<CharT>&& other) noexcept 681 : Base(std::move(other)) {} 682 683 JSONSyntaxParser(const JSONSyntaxParser& other) = delete; 684 void operator=(const JSONSyntaxParser& other) = delete; 685 686 bool parse(); 687 }; 688 689 } /* namespace js */ 690 691 #endif /* vm_JSONParser_h */