tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ErrorReporter.h (11408B)


      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 frontend_ErrorReporter_h
      8 #define frontend_ErrorReporter_h
      9 
     10 #include "mozilla/Variant.h"
     11 
     12 #include <optional>
     13 #include <stdarg.h>  // for va_list
     14 #include <stddef.h>  // for size_t
     15 #include <stdint.h>  // for uint32_t
     16 
     17 #include "js/ColumnNumber.h"  // JS::LimitedColumnNumberOneOrigin
     18 #include "js/UniquePtr.h"
     19 #include "vm/ErrorReporting.h"  // ErrorMetadata, ReportCompile{Error,Warning}
     20 
     21 namespace JS {
     22 class JS_PUBLIC_API ReadOnlyCompileOptions;
     23 }
     24 
     25 namespace js {
     26 namespace frontend {
     27 
     28 // An interface class to provide strictMode getter method, which is used by
     29 // ErrorReportMixin::strictModeError* methods.
     30 //
     31 // This class is separated to be used as a back-channel from TokenStream to the
     32 // strict mode flag which is available inside Parser, to avoid exposing the
     33 // rest of SharedContext to TokenStream.
     34 class StrictModeGetter {
     35 public:
     36  virtual bool strictMode() const = 0;
     37 };
     38 
     39 // This class provides error reporting methods, including warning, extra
     40 // warning, and strict mode error.
     41 //
     42 // A class that inherits this class must provide the following methods:
     43 //   * options
     44 //   * getContext
     45 //   * computeErrorMetadata
     46 class ErrorReportMixin : public StrictModeGetter {
     47 public:
     48  // Returns a compile options (extra warning, warning as error) for current
     49  // compilation.
     50  virtual const JS::ReadOnlyCompileOptions& options() const = 0;
     51 
     52  // Returns the current context.
     53  virtual FrontendContext* getContext() const = 0;
     54 
     55  // A variant class for the offset of the error or warning.
     56  struct Current {};
     57  struct NoOffset {};
     58  using ErrorOffset = mozilla::Variant<uint32_t, Current, NoOffset>;
     59 
     60  // Fills ErrorMetadata fields for an error or warning at given offset.
     61  //   * offset is uint32_t if methods ending with "At" is called
     62  //   * offset is NoOffset if methods ending with "NoOffset" is called
     63  //   * offset is Current otherwise
     64  [[nodiscard]] virtual bool computeErrorMetadata(
     65      ErrorMetadata* err, const ErrorOffset& offset) const = 0;
     66 
     67  // ==== error ====
     68  //
     69  // Reports an error.
     70  //
     71  // Methods ending with "At" are for an error at given offset.
     72  // The offset is passed to computeErrorMetadata method and is transparent
     73  // for this class.
     74  //
     75  // Methods ending with "NoOffset" are for an error that doesn't correspond
     76  // to any offset. NoOffset is passed to computeErrorMetadata for them.
     77  //
     78  // Other methods except errorWithNotesAtVA are for an error at the current
     79  // offset. Current is passed to computeErrorMetadata for them.
     80  //
     81  // Methods contains "WithNotes" can be used if there are error notes.
     82  //
     83  // errorWithNotesAtVA is the actual implementation for all of above.
     84  // This can be called if the caller already has a va_list.
     85 
     86  void error(unsigned errorNumber, ...) const {
     87    va_list args;
     88    va_start(args, errorNumber);
     89 
     90    errorWithNotesAtVA(nullptr, mozilla::AsVariant(Current()), errorNumber,
     91                       &args);
     92 
     93    va_end(args);
     94  }
     95  void errorWithNotes(UniquePtr<JSErrorNotes> notes, unsigned errorNumber,
     96                      ...) const {
     97    va_list args;
     98    va_start(args, errorNumber);
     99 
    100    errorWithNotesAtVA(std::move(notes), mozilla::AsVariant(Current()),
    101                       errorNumber, &args);
    102 
    103    va_end(args);
    104  }
    105  void errorAt(uint32_t offset, unsigned errorNumber, ...) const {
    106    va_list args;
    107    va_start(args, errorNumber);
    108 
    109    errorWithNotesAtVA(nullptr, mozilla::AsVariant(offset), errorNumber, &args);
    110 
    111    va_end(args);
    112  }
    113  void errorWithNotesAt(UniquePtr<JSErrorNotes> notes, uint32_t offset,
    114                        unsigned errorNumber, ...) const {
    115    va_list args;
    116    va_start(args, errorNumber);
    117 
    118    errorWithNotesAtVA(std::move(notes), mozilla::AsVariant(offset),
    119                       errorNumber, &args);
    120 
    121    va_end(args);
    122  }
    123  void errorNoOffset(unsigned errorNumber, ...) const {
    124    va_list args;
    125    va_start(args, errorNumber);
    126 
    127    errorWithNotesAtVA(nullptr, mozilla::AsVariant(NoOffset()), errorNumber,
    128                       &args);
    129 
    130    va_end(args);
    131  }
    132  void errorWithNotesNoOffset(UniquePtr<JSErrorNotes> notes,
    133                              unsigned errorNumber, ...) const {
    134    va_list args;
    135    va_start(args, errorNumber);
    136 
    137    errorWithNotesAtVA(std::move(notes), mozilla::AsVariant(NoOffset()),
    138                       errorNumber, &args);
    139 
    140    va_end(args);
    141  }
    142  void errorWithNotesAtVA(UniquePtr<JSErrorNotes> notes,
    143                          const ErrorOffset& offset, unsigned errorNumber,
    144                          va_list* args) const {
    145    ErrorMetadata metadata;
    146    if (!computeErrorMetadata(&metadata, offset)) {
    147      return;
    148    }
    149 
    150    ReportCompileErrorLatin1VA(getContext(), std::move(metadata),
    151                               std::move(notes), errorNumber, args);
    152  }
    153 
    154  // ==== warning ====
    155  //
    156  // Reports a warning.
    157  //
    158  // Returns true if the warning is reported.
    159  // Returns false if the warning is treated as an error, or an error occurs
    160  // while reporting.
    161  //
    162  // See the comment on the error section for details on what the arguments
    163  // and function names indicate for all these functions.
    164 
    165  [[nodiscard]] bool warning(unsigned errorNumber, ...) const {
    166    va_list args;
    167    va_start(args, errorNumber);
    168 
    169    bool result = warningWithNotesAtVA(nullptr, mozilla::AsVariant(Current()),
    170                                       errorNumber, &args);
    171 
    172    va_end(args);
    173 
    174    return result;
    175  }
    176  [[nodiscard]] bool warningAt(uint32_t offset, unsigned errorNumber,
    177                               ...) const {
    178    va_list args;
    179    va_start(args, errorNumber);
    180 
    181    bool result = warningWithNotesAtVA(nullptr, mozilla::AsVariant(offset),
    182                                       errorNumber, &args);
    183 
    184    va_end(args);
    185 
    186    return result;
    187  }
    188  [[nodiscard]] bool warningNoOffset(unsigned errorNumber, ...) const {
    189    va_list args;
    190    va_start(args, errorNumber);
    191 
    192    bool result = warningWithNotesAtVA(nullptr, mozilla::AsVariant(NoOffset()),
    193                                       errorNumber, &args);
    194 
    195    va_end(args);
    196 
    197    return result;
    198  }
    199  [[nodiscard]] bool warningWithNotesAtVA(UniquePtr<JSErrorNotes> notes,
    200                                          const ErrorOffset& offset,
    201                                          unsigned errorNumber,
    202                                          va_list* args) const {
    203    ErrorMetadata metadata;
    204    if (!computeErrorMetadata(&metadata, offset)) {
    205      return false;
    206    }
    207 
    208    return compileWarning(std::move(metadata), std::move(notes), errorNumber,
    209                          args);
    210  }
    211 
    212  // ==== strictModeError ====
    213  //
    214  // Reports an error if in strict mode code, or warn if not.
    215  //
    216  // Returns true if not in strict mode and a warning is reported.
    217  // Returns false if the error reported, or an error occurs while reporting.
    218  //
    219  // See the comment on the error section for details on what the arguments
    220  // and function names indicate for all these functions.
    221 
    222  [[nodiscard]] bool strictModeError(unsigned errorNumber, ...) const {
    223    va_list args;
    224    va_start(args, errorNumber);
    225 
    226    bool result = strictModeErrorWithNotesAtVA(
    227        nullptr, mozilla::AsVariant(Current()), errorNumber, &args);
    228 
    229    va_end(args);
    230 
    231    return result;
    232  }
    233  [[nodiscard]] bool strictModeErrorWithNotes(UniquePtr<JSErrorNotes> notes,
    234                                              unsigned errorNumber, ...) const {
    235    va_list args;
    236    va_start(args, errorNumber);
    237 
    238    bool result = strictModeErrorWithNotesAtVA(
    239        std::move(notes), mozilla::AsVariant(Current()), errorNumber, &args);
    240 
    241    va_end(args);
    242 
    243    return result;
    244  }
    245  [[nodiscard]] bool strictModeErrorAt(uint32_t offset, unsigned errorNumber,
    246                                       ...) const {
    247    va_list args;
    248    va_start(args, errorNumber);
    249 
    250    bool result = strictModeErrorWithNotesAtVA(
    251        nullptr, mozilla::AsVariant(offset), errorNumber, &args);
    252 
    253    va_end(args);
    254 
    255    return result;
    256  }
    257  [[nodiscard]] bool strictModeErrorWithNotesAt(UniquePtr<JSErrorNotes> notes,
    258                                                uint32_t offset,
    259                                                unsigned errorNumber,
    260                                                ...) const {
    261    va_list args;
    262    va_start(args, errorNumber);
    263 
    264    bool result = strictModeErrorWithNotesAtVA(
    265        std::move(notes), mozilla::AsVariant(offset), errorNumber, &args);
    266 
    267    va_end(args);
    268 
    269    return result;
    270  }
    271  [[nodiscard]] bool strictModeErrorNoOffset(unsigned errorNumber, ...) const {
    272    va_list args;
    273    va_start(args, errorNumber);
    274 
    275    bool result = strictModeErrorWithNotesAtVA(
    276        nullptr, mozilla::AsVariant(NoOffset()), errorNumber, &args);
    277 
    278    va_end(args);
    279 
    280    return result;
    281  }
    282  [[nodiscard]] bool strictModeErrorWithNotesNoOffset(
    283      UniquePtr<JSErrorNotes> notes, unsigned errorNumber, ...) const {
    284    va_list args;
    285    va_start(args, errorNumber);
    286 
    287    bool result = strictModeErrorWithNotesAtVA(
    288        std::move(notes), mozilla::AsVariant(NoOffset()), errorNumber, &args);
    289 
    290    va_end(args);
    291 
    292    return result;
    293  }
    294  [[nodiscard]] bool strictModeErrorWithNotesAtVA(UniquePtr<JSErrorNotes> notes,
    295                                                  const ErrorOffset& offset,
    296                                                  unsigned errorNumber,
    297                                                  va_list* args) const {
    298    if (!strictMode()) {
    299      return true;
    300    }
    301 
    302    ErrorMetadata metadata;
    303    if (!computeErrorMetadata(&metadata, offset)) {
    304      return false;
    305    }
    306 
    307    ReportCompileErrorLatin1VA(getContext(), std::move(metadata),
    308                               std::move(notes), errorNumber, args);
    309    return false;
    310  }
    311 
    312  // Reports a warning, or an error if the warning is treated as an error.
    313  [[nodiscard]] bool compileWarning(ErrorMetadata&& metadata,
    314                                    UniquePtr<JSErrorNotes> notes,
    315                                    unsigned errorNumber, va_list* args) const {
    316    return ReportCompileWarning(getContext(), std::move(metadata),
    317                                std::move(notes), errorNumber, args);
    318  }
    319 };
    320 
    321 // An interface class to provide miscellaneous methods used by error reporting
    322 // etc.  They're mostly used by BytecodeCompiler, BytecodeEmitter, and helper
    323 // classes for emitter.
    324 class ErrorReporter : public ErrorReportMixin {
    325 public:
    326  // Returns Some(true) if the given offset is inside the given line
    327  // number `lineNum`, or Some(false) otherwise.
    328  //
    329  // Return None if an error happens.  This method itself doesn't report an
    330  // error, and any failure is supposed to be reported as OOM in the caller.
    331  virtual std::optional<bool> isOnThisLine(size_t offset,
    332                                           uint32_t lineNum) const = 0;
    333 
    334  // Returns the line number for given offset.
    335  virtual uint32_t lineAt(size_t offset) const = 0;
    336 
    337  // Returns the column number for given offset.
    338  virtual JS::LimitedColumnNumberOneOrigin columnAt(size_t offset) const = 0;
    339 };
    340 
    341 }  // namespace frontend
    342 }  // namespace js
    343 
    344 #endif  // frontend_ErrorReporter_h