Skip to content

Commit

Permalink
add DOMException
Browse files Browse the repository at this point in the history
  • Loading branch information
zloirock committed Oct 3, 2021
1 parent 57a189e commit a72f50d
Show file tree
Hide file tree
Showing 11 changed files with 274 additions and 0 deletions.
6 changes: 6 additions & 0 deletions packages/core-js-compat/src/data.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -1760,6 +1760,12 @@ export const data = {
safari: '13.1',
rhino: '1.7.13',
},
'web.dom-exception': {
chrome: '46',
deno: '1.7', // ?
firefox: '37',
safari: '10.1',
},
'web.immediate': {
ie: '10',
node: '0.9.1',
Expand Down
3 changes: 3 additions & 0 deletions packages/core-js-compat/src/modules-by-versions.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -111,4 +111,7 @@ export default {
'esnext.array.from-async',
'esnext.typed-array.from-async',
],
3.19: [
'web.dom-exception',
],
};
3 changes: 3 additions & 0 deletions packages/core-js/features/dom-exception.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
var parent = require('../stable/dom-exception');

module.exports = parent;
101 changes: 101 additions & 0 deletions packages/core-js/modules/web.dom-exception.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
'use strict';
var $ = require('../internals/export');
var global = require('../internals/global');
var create = require('../internals/object-create');
var createPropertyDescriptor = require('../internals/create-property-descriptor');
var defineProperty = require('../internals/object-define-property').f;
var defineProperties = require('../internals/object-define-properties');
var redefine = require('../internals/redefine');
var hasOwn = require('../internals/has-own-property');
var anInstance = require('../internals/an-instance');
var $toString = require('../internals/to-string');
var setToStringTag = require('../internals/set-to-string-tag');
var InternalStateModule = require('../internals/internal-state');
var DESCRIPTORS = require('../internals/descriptors');

var DOM_EXCEPTION = 'DOMException';
var setInternalState = InternalStateModule.set;
var getInternalState = InternalStateModule.getterFor(DOM_EXCEPTION);

var errors = {
IndexSizeError: { s: 'INDEX_SIZE_ERR', c: 1, m: 1 },
DOMStringSizeError: { s: 'DOMSTRING_SIZE_ERR', c: 2, m: 0 },
HierarchyRequestError: { s: 'HIERARCHY_REQUEST_ERR', c: 3, m: 1 },
WrongDocumentError: { s: 'WRONG_DOCUMENT_ERR', c: 4, m: 1 },
InvalidCharacterError: { s: 'INVALID_CHARACTER_ERR', c: 5, m: 1 },
NoDataAllowedError: { s: 'NO_DATA_ALLOWED_ERR', c: 6, m: 0 },
NoModificationAllowedError: { s: 'NO_MODIFICATION_ALLOWED_ERR', c: 7, m: 1 },
NotFoundError: { s: 'NOT_FOUND_ERR', c: 8, m: 1 },
NotSupportedError: { s: 'NOT_SUPPORTED_ERR', c: 9, m: 1 },
InUseAttributeError: { s: 'INUSE_ATTRIBUTE_ERR', c: 10, m: 1 },
InvalidStateError: { s: 'INVALID_STATE_ERR', c: 11, m: 1 },
SyntaxError: { s: 'SYNTAX_ERR', c: 12, m: 1 },
InvalidModificationError: { s: 'INVALID_MODIFICATION_ERR', c: 13, m: 1 },
NamespaceError: { s: 'NAMESPACE_ERR', c: 14, m: 1 },
InvalidAccessError: { s: 'INVALID_ACCESS_ERR', c: 15, m: 1 },
ValidationError: { s: 'VALIDATION_ERR', c: 16, m: 0 },
TypeMismatchError: { s: 'TYPE_MISMATCH_ERR', c: 17, m: 1 },
SecurityError: { s: 'SECURITY_ERR', c: 18, m: 1 },
NetworkError: { s: 'NETWORK_ERR', c: 19, m: 1 },
AbortError: { s: 'ABORT_ERR', c: 20, m: 1 },
URLMismatchError: { s: 'URL_MISMATCH_ERR', c: 21, m: 1 },
QuotaExceededError: { s: 'QUOTA_EXCEEDED_ERR', c: 22, m: 1 },
TimeoutError: { s: 'TIMEOUT_ERR', c: 23, m: 1 },
InvalidNodeTypeError: { s: 'INVALID_NODE_TYPE_ERR', c: 24, m: 1 },
DataCloneError: { s: 'DATA_CLONE_ERR', c: 25, m: 1 }
};

var $DOMException = function DOMException() {
anInstance(this, $DOMException, DOM_EXCEPTION);
var argumentsLength = arguments.length;
var message = argumentsLength < 1 ? undefined : arguments[0];
var name = argumentsLength < 2 ? undefined : arguments[1];
message = message === undefined ? '' : $toString(message);
name = name === undefined ? 'Error' : $toString(name);
var code = hasOwn(errors, name) && errors[name].m ? errors[name].c : 0;
setInternalState(this, {
type: DOM_EXCEPTION,
name: name,
message: message,
code: code
});
if (!DESCRIPTORS) {
this.name = name;
this.message = message;
this.code = code;
}
};

var $DOMExceptionPrototype = $DOMException.prototype = create(Error.prototype);

var getter = function (key) {
return { enumerable: true, configurable: true, get: function () { return getInternalState(this)[key]; } };
};

if (DESCRIPTORS) defineProperties($DOMExceptionPrototype, {
name: getter('name'),
message: getter('message'),
code: getter('code')
});

defineProperty($DOMExceptionPrototype, 'constructor', createPropertyDescriptor(1, $DOMException));

redefine($DOMExceptionPrototype, 'toString', function toString() {
var state = getInternalState(this);
return state.name + ': ' + state.message;
});

setToStringTag($DOMException, DOM_EXCEPTION);

for (var key in errors) if (hasOwn(errors, key)) {
var constant = errors[key];
var descriptor = createPropertyDescriptor(6, constant.c);
defineProperty($DOMException, constant.s, descriptor);
defineProperty($DOMExceptionPrototype, constant.s, descriptor);
}

// `DOMException` constructor
// https://heycam.github.io/webidl/#idl-DOMException
$({ global: true, forced: typeof global[DOM_EXCEPTION] !== 'function' }, {
DOMException: $DOMException
});
4 changes: 4 additions & 0 deletions packages/core-js/stable/dom-exception.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
require('../modules/web.dom-exception');
var path = require('../internals/path');

module.exports = path.DOMException;
4 changes: 4 additions & 0 deletions packages/core-js/web/dom-exception.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
require('../modules/web.dom-exception');
var path = require('../internals/path');

module.exports = path.DOMException;
1 change: 1 addition & 0 deletions packages/core-js/web/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
require('../modules/web.dom-exception');
require('../modules/web.dom-collections.for-each');
require('../modules/web.dom-collections.iterator');
require('../modules/web.immediate');
Expand Down
2 changes: 2 additions & 0 deletions tests/commonjs.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,7 @@ for (PATH of ['core-js-pure', 'core-js']) {
}

for (const NS of ['stable', 'features']) {
ok(typeof load(NS, 'dom-exception') === 'function');
ok(typeof load(NS, 'dom-collections').iterator === 'function');
ok(typeof load(NS, 'dom-collections/for-each') === 'function');
ok(typeof load(NS, 'dom-collections/iterator') === 'function');
Expand Down Expand Up @@ -785,6 +786,7 @@ for (PATH of ['core-js-pure', 'core-js']) {
ok(load('stage/pre'));
ok(load('stage'));

ok(load('web/dom-exception'));
ok(load('web/dom-collections'));
ok(load('web/immediate'));
ok(load('web/queue-microtask'));
Expand Down
3 changes: 3 additions & 0 deletions tests/compat/tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -1562,6 +1562,9 @@ GLOBAL.tests = {
}
return true;
},
'web.dom-exception': function () {
return typeof DOMException === 'function';
},
'web.immediate': function () {
return setImmediate && clearImmediate;
},
Expand Down
74 changes: 74 additions & 0 deletions tests/pure/web.dom-exception.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { DESCRIPTORS } from '../helpers/constants';
import DOMException from 'core-js-pure/stable/dom-exception';
import Symbol from 'core-js-pure/es/symbol';

const errors = {
IndexSizeError: { s: 'INDEX_SIZE_ERR', c: 1, m: 1 },
DOMStringSizeError: { s: 'DOMSTRING_SIZE_ERR', c: 2, m: 0 },
HierarchyRequestError: { s: 'HIERARCHY_REQUEST_ERR', c: 3, m: 1 },
WrongDocumentError: { s: 'WRONG_DOCUMENT_ERR', c: 4, m: 1 },
InvalidCharacterError: { s: 'INVALID_CHARACTER_ERR', c: 5, m: 1 },
NoDataAllowedError: { s: 'NO_DATA_ALLOWED_ERR', c: 6, m: 0 },
NoModificationAllowedError: { s: 'NO_MODIFICATION_ALLOWED_ERR', c: 7, m: 1 },
NotFoundError: { s: 'NOT_FOUND_ERR', c: 8, m: 1 },
NotSupportedError: { s: 'NOT_SUPPORTED_ERR', c: 9, m: 1 },
InUseAttributeError: { s: 'INUSE_ATTRIBUTE_ERR', c: 10, m: 1 },
InvalidStateError: { s: 'INVALID_STATE_ERR', c: 11, m: 1 },
SyntaxError: { s: 'SYNTAX_ERR', c: 12, m: 1 },
InvalidModificationError: { s: 'INVALID_MODIFICATION_ERR', c: 13, m: 1 },
NamespaceError: { s: 'NAMESPACE_ERR', c: 14, m: 1 },
InvalidAccessError: { s: 'INVALID_ACCESS_ERR', c: 15, m: 1 },
ValidationError: { s: 'VALIDATION_ERR', c: 16, m: 0 },
TypeMismatchError: { s: 'TYPE_MISMATCH_ERR', c: 17, m: 1 },
SecurityError: { s: 'SECURITY_ERR', c: 18, m: 1 },
NetworkError: { s: 'NETWORK_ERR', c: 19, m: 1 },
AbortError: { s: 'ABORT_ERR', c: 20, m: 1 },
URLMismatchError: { s: 'URL_MISMATCH_ERR', c: 21, m: 1 },
QuotaExceededError: { s: 'QUOTA_EXCEEDED_ERR', c: 22, m: 1 },
TimeoutError: { s: 'TIMEOUT_ERR', c: 23, m: 1 },
InvalidNodeTypeError: { s: 'INVALID_NODE_TYPE_ERR', c: 24, m: 1 },
DataCloneError: { s: 'DATA_CLONE_ERR', c: 25, m: 1 },
};

QUnit.test('DOMException', assert => {
assert.isFunction(DOMException);
assert.arity(DOMException, 0);
assert.name(DOMException, 'DOMException');

let error = new DOMException({}, 'Foo');
assert.ok(error instanceof DOMException, 'new DOMException({}, "Foo") instanceof DOMException');
assert.same(error.message, '[object Object]', 'new DOMException({}, "Foo").message');
assert.same(error.name, 'Foo', 'new DOMException({}, "Foo").name');
assert.same(error.code, 0, 'new DOMException({}, "Foo").code');
assert.same(String(error), 'Foo: [object Object]', 'String(new DOMException({}, "Foo"))');
assert.same(error.constructor, DOMException, 'new DOMException({}, "Foo").constructor');
assert.same(error[Symbol.toStringTag], 'DOMException', 'DOMException.prototype[Symbol.toStringTag]');

assert.same(new DOMException().message, '', 'new DOMException().message');
assert.same(new DOMException(undefined).message, '', 'new DOMException(undefined).message');
assert.same(new DOMException(42).name, 'Error', 'new DOMException(42).name');
assert.same(new DOMException(42, undefined).name, 'Error', 'new DOMException(42, undefined).name');

for (const name in errors) {
error = new DOMException(42, name);
assert.ok(error instanceof DOMException, `new DOMException({}, "${ name }") instanceof DOMException`);
assert.same(error.message, '42', `new DOMException({}, "${ name }").message`);
assert.same(error.name, name, `new DOMException({}, "${ name }").name`);
if (errors[name].m) assert.same(error.code, errors[name].c, `new DOMException({}, "${ name }").code`);
else assert.same(error.code, 0, `new DOMException({}, "${ name }").code`);
assert.same(String(error), `${ name }: 42`, `String(new DOMException({}, "${ name }"))`);

assert.same(DOMException[errors[name].s], errors[name].c, `DOMException.${ errors[name].s }`);
assert.same(DOMException.prototype[errors[name].s], errors[name].c, `DOMException.prototype.${ errors[name].s }`);
}

assert.throws(() => DOMException(42, 'DataCloneError'), "DOMException(42, 'DataCloneError')");
assert.throws(() => new DOMException(Symbol(), 'DataCloneError'), "new DOMException(Symbol(), 'DataCloneError')");
assert.throws(() => new DOMException(42, Symbol()), 'new DOMException(42, Symbol())');
if (DESCRIPTORS) {
assert.throws(() => DOMException.prototype.message, 'DOMException.prototype.message');
assert.throws(() => DOMException.prototype.name, 'DOMException.prototype.name');
assert.throws(() => DOMException.prototype.code, 'DOMException.prototype.code');
assert.throws(() => DOMException.prototype.toString(), 'DOMException.prototype.toString()');
}
});
73 changes: 73 additions & 0 deletions tests/tests/web.dom-exception.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { DESCRIPTORS } from '../helpers/constants';

const errors = {
IndexSizeError: { s: 'INDEX_SIZE_ERR', c: 1, m: 1 },
DOMStringSizeError: { s: 'DOMSTRING_SIZE_ERR', c: 2, m: 0 },
HierarchyRequestError: { s: 'HIERARCHY_REQUEST_ERR', c: 3, m: 1 },
WrongDocumentError: { s: 'WRONG_DOCUMENT_ERR', c: 4, m: 1 },
InvalidCharacterError: { s: 'INVALID_CHARACTER_ERR', c: 5, m: 1 },
NoDataAllowedError: { s: 'NO_DATA_ALLOWED_ERR', c: 6, m: 0 },
NoModificationAllowedError: { s: 'NO_MODIFICATION_ALLOWED_ERR', c: 7, m: 1 },
NotFoundError: { s: 'NOT_FOUND_ERR', c: 8, m: 1 },
NotSupportedError: { s: 'NOT_SUPPORTED_ERR', c: 9, m: 1 },
InUseAttributeError: { s: 'INUSE_ATTRIBUTE_ERR', c: 10, m: 1 },
InvalidStateError: { s: 'INVALID_STATE_ERR', c: 11, m: 1 },
SyntaxError: { s: 'SYNTAX_ERR', c: 12, m: 1 },
InvalidModificationError: { s: 'INVALID_MODIFICATION_ERR', c: 13, m: 1 },
NamespaceError: { s: 'NAMESPACE_ERR', c: 14, m: 1 },
InvalidAccessError: { s: 'INVALID_ACCESS_ERR', c: 15, m: 1 },
ValidationError: { s: 'VALIDATION_ERR', c: 16, m: 0 },
TypeMismatchError: { s: 'TYPE_MISMATCH_ERR', c: 17, m: 1 },
SecurityError: { s: 'SECURITY_ERR', c: 18, m: 1 },
NetworkError: { s: 'NETWORK_ERR', c: 19, m: 1 },
AbortError: { s: 'ABORT_ERR', c: 20, m: 1 },
URLMismatchError: { s: 'URL_MISMATCH_ERR', c: 21, m: 1 },
QuotaExceededError: { s: 'QUOTA_EXCEEDED_ERR', c: 22, m: 1 },
TimeoutError: { s: 'TIMEOUT_ERR', c: 23, m: 1 },
InvalidNodeTypeError: { s: 'INVALID_NODE_TYPE_ERR', c: 24, m: 1 },
DataCloneError: { s: 'DATA_CLONE_ERR', c: 25, m: 1 },
};

QUnit.test('DOMException', assert => {
assert.isFunction(DOMException);
assert.arity(DOMException, 0);
assert.name(DOMException, 'DOMException');
assert.looksNative(DOMException);

let error = new DOMException({}, 'Foo');
assert.ok(error instanceof DOMException, 'new DOMException({}, "Foo") instanceof DOMException');
assert.same(error.message, '[object Object]', 'new DOMException({}, "Foo").message');
assert.same(error.name, 'Foo', 'new DOMException({}, "Foo").name');
assert.same(error.code, 0, 'new DOMException({}, "Foo").code');
assert.same(String(error), 'Foo: [object Object]', 'String(new DOMException({}, "Foo"))');
assert.same(error.constructor, DOMException, 'new DOMException({}, "Foo").constructor');
assert.same(error[Symbol.toStringTag], 'DOMException', 'DOMException.prototype[Symbol.toStringTag]');

assert.same(new DOMException().message, '', 'new DOMException().message');
assert.same(new DOMException(undefined).message, '', 'new DOMException(undefined).message');
assert.same(new DOMException(42).name, 'Error', 'new DOMException(42).name');
assert.same(new DOMException(42, undefined).name, 'Error', 'new DOMException(42, undefined).name');

for (const name in errors) {
error = new DOMException(42, name);
assert.ok(error instanceof DOMException, `new DOMException({}, "${ name }") instanceof DOMException`);
assert.same(error.message, '42', `new DOMException({}, "${ name }").message`);
assert.same(error.name, name, `new DOMException({}, "${ name }").name`);
if (errors[name].m) assert.same(error.code, errors[name].c, `new DOMException({}, "${ name }").code`);
else assert.same(error.code, 0, `new DOMException({}, "${ name }").code`);
assert.same(String(error), `${ name }: 42`, `String(new DOMException({}, "${ name }"))`);

assert.same(DOMException[errors[name].s], errors[name].c, `DOMException.${ errors[name].s }`);
assert.same(DOMException.prototype[errors[name].s], errors[name].c, `DOMException.prototype.${ errors[name].s }`);
}

assert.throws(() => DOMException(42, 'DataCloneError'), "DOMException(42, 'DataCloneError')");
assert.throws(() => new DOMException(Symbol(), 'DataCloneError'), "new DOMException(Symbol(), 'DataCloneError')");
assert.throws(() => new DOMException(42, Symbol()), 'new DOMException(42, Symbol())');
if (DESCRIPTORS) {
assert.throws(() => DOMException.prototype.message, 'DOMException.prototype.message');
assert.throws(() => DOMException.prototype.name, 'DOMException.prototype.name');
assert.throws(() => DOMException.prototype.code, 'DOMException.prototype.code');
assert.throws(() => DOMException.prototype.toString(), 'DOMException.prototype.toString()');
}
});

0 comments on commit a72f50d

Please sign in to comment.