• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1'use strict';
2
3const {
4  ErrorCaptureStackTrace,
5  ErrorPrototype,
6  ObjectDefineProperties,
7  ObjectDefineProperty,
8  ObjectSetPrototypeOf,
9  SafeWeakMap,
10  SafeMap,
11  SafeSet,
12  SymbolToStringTag,
13  TypeError,
14} = primordials;
15
16function throwInvalidThisError(Base, type) {
17  const err = new Base();
18  const key = 'ERR_INVALID_THIS';
19  ObjectDefineProperties(err, {
20    message: {
21      __proto__: null,
22      value: `Value of "this" must be of ${type}`,
23      enumerable: false,
24      writable: true,
25      configurable: true,
26    },
27    toString: {
28      __proto__: null,
29      value() {
30        return `${this.name} [${key}]: ${this.message}`;
31      },
32      enumerable: false,
33      writable: true,
34      configurable: true,
35    },
36  });
37  err.code = key;
38  throw err;
39}
40
41const internalsMap = new SafeWeakMap();
42const nameToCodeMap = new SafeMap();
43
44// These were removed from the error names table.
45// See https://github.com/heycam/webidl/pull/946.
46const disusedNamesSet = new SafeSet()
47  .add('DOMStringSizeError')
48  .add('NoDataAllowedError')
49  .add('ValidationError');
50
51class DOMException {
52  constructor(message = '', options = 'Error') {
53    ErrorCaptureStackTrace(this);
54
55    if (options && typeof options === 'object') {
56      const { name } = options;
57      internalsMap.set(this, {
58        message: `${message}`,
59        name: `${name}`,
60      });
61
62      if ('cause' in options) {
63        ObjectDefineProperty(this, 'cause', {
64          __proto__: null,
65          value: options.cause,
66          configurable: true,
67          writable: true,
68          enumerable: false,
69        });
70      }
71    } else {
72      internalsMap.set(this, {
73        message: `${message}`,
74        name: `${options}`,
75      });
76    }
77  }
78
79  get name() {
80    const internals = internalsMap.get(this);
81    if (internals === undefined) {
82      throwInvalidThisError(TypeError, 'DOMException');
83    }
84    return internals.name;
85  }
86
87  get message() {
88    const internals = internalsMap.get(this);
89    if (internals === undefined) {
90      throwInvalidThisError(TypeError, 'DOMException');
91    }
92    return internals.message;
93  }
94
95  get code() {
96    const internals = internalsMap.get(this);
97    if (internals === undefined) {
98      throwInvalidThisError(TypeError, 'DOMException');
99    }
100
101    if (disusedNamesSet.has(internals.name)) {
102      return 0;
103    }
104
105    const code = nameToCodeMap.get(internals.name);
106    return code === undefined ? 0 : code;
107  }
108}
109
110ObjectSetPrototypeOf(DOMException.prototype, ErrorPrototype);
111ObjectDefineProperties(DOMException.prototype, {
112  [SymbolToStringTag]: { __proto__: null, configurable: true, value: 'DOMException' },
113  name: { __proto__: null, enumerable: true, configurable: true },
114  message: { __proto__: null, enumerable: true, configurable: true },
115  code: { __proto__: null, enumerable: true, configurable: true },
116});
117
118for (const { 0: name, 1: codeName, 2: value } of [
119  ['IndexSizeError', 'INDEX_SIZE_ERR', 1],
120  ['DOMStringSizeError', 'DOMSTRING_SIZE_ERR', 2],
121  ['HierarchyRequestError', 'HIERARCHY_REQUEST_ERR', 3],
122  ['WrongDocumentError', 'WRONG_DOCUMENT_ERR', 4],
123  ['InvalidCharacterError', 'INVALID_CHARACTER_ERR', 5],
124  ['NoDataAllowedError', 'NO_DATA_ALLOWED_ERR', 6],
125  ['NoModificationAllowedError', 'NO_MODIFICATION_ALLOWED_ERR', 7],
126  ['NotFoundError', 'NOT_FOUND_ERR', 8],
127  ['NotSupportedError', 'NOT_SUPPORTED_ERR', 9],
128  ['InUseAttributeError', 'INUSE_ATTRIBUTE_ERR', 10],
129  ['InvalidStateError', 'INVALID_STATE_ERR', 11],
130  ['SyntaxError', 'SYNTAX_ERR', 12],
131  ['InvalidModificationError', 'INVALID_MODIFICATION_ERR', 13],
132  ['NamespaceError', 'NAMESPACE_ERR', 14],
133  ['InvalidAccessError', 'INVALID_ACCESS_ERR', 15],
134  ['ValidationError', 'VALIDATION_ERR', 16],
135  ['TypeMismatchError', 'TYPE_MISMATCH_ERR', 17],
136  ['SecurityError', 'SECURITY_ERR', 18],
137  ['NetworkError', 'NETWORK_ERR', 19],
138  ['AbortError', 'ABORT_ERR', 20],
139  ['URLMismatchError', 'URL_MISMATCH_ERR', 21],
140  ['QuotaExceededError', 'QUOTA_EXCEEDED_ERR', 22],
141  ['TimeoutError', 'TIMEOUT_ERR', 23],
142  ['InvalidNodeTypeError', 'INVALID_NODE_TYPE_ERR', 24],
143  ['DataCloneError', 'DATA_CLONE_ERR', 25],
144  // There are some more error names, but since they don't have codes assigned,
145  // we don't need to care about them.
146]) {
147  const desc = { enumerable: true, value };
148  ObjectDefineProperty(DOMException, codeName, desc);
149  ObjectDefineProperty(DOMException.prototype, codeName, desc);
150  nameToCodeMap.set(name, value);
151}
152
153exports.DOMException = DOMException;
154