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 #include "frontend/BinASTTokenReaderBase.h"
8
9 #include "frontend/BinAST-macros.h"
10 #include "js/Result.h"
11
12 namespace js::frontend {
13
14 template <typename T>
15 using ErrorResult = mozilla::GenericErrorResult<T>;
16
17 // We use signalling NaN (which doesn't exist in the JS syntax)
18 // to represent a `null` number.
19 const uint64_t NULL_FLOAT_REPRESENTATION = 0x7FF0000000000001;
20
updateLatestKnownGood()21 void BinASTTokenReaderBase::updateLatestKnownGood() {
22 MOZ_ASSERT(current_ >= start_);
23 const size_t update = current_ - start_;
24 MOZ_ASSERT(update >= latestKnownGoodPos_);
25 latestKnownGoodPos_ = update;
26 }
27
raiseError(const char * description)28 ErrorResult<JS::Error&> BinASTTokenReaderBase::raiseError(
29 const char* description) {
30 MOZ_ASSERT(!hasRaisedError());
31 errorReporter_->errorNoOffset(JSMSG_BINAST, description);
32 return cx_->alreadyReportedError();
33 }
34
raiseOOM()35 ErrorResult<JS::Error&> BinASTTokenReaderBase::raiseOOM() {
36 ReportOutOfMemory(cx_);
37 return cx_->alreadyReportedError();
38 }
39
raiseInvalidNumberOfFields(const BinASTKind kind,const uint32_t expected,const uint32_t got)40 ErrorResult<JS::Error&> BinASTTokenReaderBase::raiseInvalidNumberOfFields(
41 const BinASTKind kind, const uint32_t expected, const uint32_t got) {
42 Sprinter out(cx_);
43 BINJS_TRY(out.init());
44 BINJS_TRY(out.printf("In %s, invalid number of fields: expected %u, got %u",
45 describeBinASTKind(kind), expected, got));
46 return raiseError(out.string());
47 }
48
raiseInvalidField(const char * kind,const BinASTField field)49 ErrorResult<JS::Error&> BinASTTokenReaderBase::raiseInvalidField(
50 const char* kind, const BinASTField field) {
51 Sprinter out(cx_);
52 BINJS_TRY(out.init());
53 BINJS_TRY(out.printf("In %s, invalid field '%s'", kind,
54 describeBinASTField(field)));
55 return raiseError(out.string());
56 }
57
hasRaisedError() const58 bool BinASTTokenReaderBase::hasRaisedError() const {
59 if (cx_->isHelperThreadContext()) {
60 // When performing off-main-thread parsing, we don't set a pending
61 // exception but instead add a pending compile error.
62 return cx_->isCompileErrorPending();
63 }
64
65 return cx_->isExceptionPending();
66 }
67
pos()68 TokenPos BinASTTokenReaderBase::pos() { return pos(offset()); }
69
pos(size_t start)70 TokenPos BinASTTokenReaderBase::pos(size_t start) {
71 TokenPos pos;
72 pos.begin = start;
73 pos.end = current_ - start_;
74 MOZ_ASSERT(pos.end >= pos.begin);
75 return pos;
76 }
77
seek(size_t offset)78 void BinASTTokenReaderBase::seek(size_t offset) {
79 MOZ_ASSERT(start_ + offset >= start_ && start_ + offset < stop_);
80 current_ = start_ + offset;
81 }
82
readBuf(uint8_t * bytes,uint32_t len)83 JS::Result<Ok> BinASTTokenReaderBase::readBuf(uint8_t* bytes, uint32_t len) {
84 MOZ_ASSERT(!hasRaisedError());
85
86 if (MOZ_UNLIKELY(stop_ < current_ + len)) {
87 return raiseError("Buffer exceeds length");
88 }
89
90 for (uint32_t i = 0; i < len; ++i) {
91 *bytes++ = *current_++;
92 }
93
94 return Ok();
95 }
96
readByte()97 JS::Result<uint8_t> BinASTTokenReaderBase::readByte() {
98 MOZ_ASSERT(!hasRaisedError());
99
100 if (MOZ_UNLIKELY(stop_ == current_)) {
101 return raiseError("Buffer exceeds length");
102 }
103
104 return *current_++;
105 }
106
107 } // namespace js::frontend
108