@es-joy/jsoe 0.13.7 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/.eslintrc.cjs +5 -0
  2. package/.nyc_output/out.json +13027 -11984
  3. package/CHANGES.md +10 -0
  4. package/README.md +5 -4
  5. package/demo/index.js +68 -2
  6. package/dist/formats/structuredCloning.d.ts.map +1 -1
  7. package/dist/fundamentalTypes/BooleanObjectType.d.ts.map +1 -1
  8. package/dist/fundamentalTypes/NumberObjectType.d.ts.map +1 -1
  9. package/dist/fundamentalTypes/StringObjectType.d.ts.map +1 -1
  10. package/dist/fundamentalTypes/arrayType.d.ts.map +1 -1
  11. package/dist/fundamentalTypes/blobType.d.ts.map +1 -1
  12. package/dist/fundamentalTypes/dateType.d.ts.map +1 -1
  13. package/dist/fundamentalTypes/fileType.d.ts.map +1 -1
  14. package/dist/fundamentalTypes/filelistType.d.ts.map +1 -1
  15. package/dist/fundamentalTypes/mapType.d.ts.map +1 -1
  16. package/dist/fundamentalTypes/noneditableType.d.ts +6 -0
  17. package/dist/fundamentalTypes/noneditableType.d.ts.map +1 -0
  18. package/dist/fundamentalTypes/objectReferenceType.d.ts.map +1 -1
  19. package/dist/fundamentalTypes/objectType.d.ts.map +1 -1
  20. package/dist/fundamentalTypes/setType.d.ts.map +1 -1
  21. package/dist/fundamentalTypes/sparseUndefinedType.d.ts.map +1 -1
  22. package/dist/fundamentalTypes/undefinedType.d.ts.map +1 -1
  23. package/dist/index.js +436 -109
  24. package/dist/superTypes/SpecialNumberType.d.ts +2 -10
  25. package/dist/superTypes/SpecialNumberType.d.ts.map +1 -1
  26. package/dist/superTypes/SpecialRealNumberType.d.ts +2 -2
  27. package/dist/superTypes/SpecialRealNumberType.d.ts.map +1 -1
  28. package/dist/superTypes/dommatrixType.d.ts +6 -0
  29. package/dist/superTypes/dommatrixType.d.ts.map +1 -0
  30. package/dist/superTypes/dompointType.d.ts +6 -0
  31. package/dist/superTypes/dompointType.d.ts.map +1 -0
  32. package/dist/superTypes/domrectType.d.ts +6 -0
  33. package/dist/superTypes/domrectType.d.ts.map +1 -0
  34. package/dist/superTypes/errorsSpecialType.d.ts +2 -2
  35. package/dist/superTypes/errorsSpecialType.d.ts.map +1 -1
  36. package/dist/types.d.ts +27 -14
  37. package/dist/types.d.ts.map +1 -1
  38. package/dist/utils/media.d.ts.map +1 -1
  39. package/dist/vendor-imports.d.ts +1 -1
  40. package/package.json +13 -13
  41. package/src/formats/structuredCloning.js +49 -6
  42. package/src/fundamentalTypes/BooleanObjectType.js +3 -1
  43. package/src/fundamentalTypes/NumberObjectType.js +3 -1
  44. package/src/fundamentalTypes/StringObjectType.js +3 -1
  45. package/src/fundamentalTypes/arrayType.js +4 -2
  46. package/src/fundamentalTypes/blobType.js +17 -13
  47. package/src/fundamentalTypes/dateType.js +6 -2
  48. package/src/fundamentalTypes/fileType.js +14 -12
  49. package/src/fundamentalTypes/filelistType.js +3 -1
  50. package/src/fundamentalTypes/mapType.js +3 -1
  51. package/src/fundamentalTypes/noneditableType.js +87 -0
  52. package/src/fundamentalTypes/objectReferenceType.js +3 -1
  53. package/src/fundamentalTypes/objectType.js +3 -1
  54. package/src/fundamentalTypes/setType.js +3 -1
  55. package/src/fundamentalTypes/sparseUndefinedType.js +3 -1
  56. package/src/fundamentalTypes/undefinedType.js +3 -1
  57. package/src/subTypes/blobHTMLType.js +1 -1
  58. package/src/superTypes/SpecialNumberType.js +2 -8
  59. package/src/superTypes/SpecialRealNumberType.js +2 -2
  60. package/src/{fundamentalTypes → superTypes}/dommatrixType.js +63 -10
  61. package/src/{fundamentalTypes → superTypes}/dompointType.js +60 -7
  62. package/src/{fundamentalTypes → superTypes}/domrectType.js +59 -7
  63. package/src/superTypes/errorsSpecialType.js +1 -1
  64. package/src/types.js +40 -17
  65. package/src/utils/media.js +3 -2
  66. package/src/vendor-imports.js +2 -1
  67. package/vendor/typeson-registry/dist/index.js +90 -28
@@ -132,7 +132,7 @@ function binaryButton (value, editable) {
132
132
  ['textarea', {
133
133
  class: 'view-binary'
134
134
  }, [
135
- /* c8 ignore next */
135
+ /* istanbul ignore next */
136
136
  /** @type {string|null} */ (reader.result) ?? ''
137
137
  ]]
138
138
  ])]
@@ -140,12 +140,13 @@ function binaryButton (value, editable) {
140
140
  });
141
141
  });
142
142
  // Seems not feasible to accurately simulate
143
- /* c8 ignore next 10 */
144
143
  reader.addEventListener(
145
144
  'error',
146
- /* c8 ignore next 6 */
145
+ /* istanbul ignore next */
147
146
  async function () {
147
+ /* istanbul ignore next */
148
148
  console.error(reader.error);
149
+ /* istanbul ignore next */
149
150
  await dialogs.alert(/** @type {string} */ (
150
151
  /** @type {DOMException} */ (reader.error).message
151
152
  ));
@@ -224,18 +225,19 @@ const fileType = {
224
225
  'Text source',
225
226
  ['br'],
226
227
  ['textarea', {class: 'view-text'}, [
227
- /* c8 ignore next */
228
+ /* istanbul ignore next */
228
229
  /** @type {string|null} */ (reader.result) ?? ''
229
230
  ]]
230
231
  ]));
231
232
  });
232
233
  // Seems not feasible to accurately simulate
233
- /* c8 ignore next 10 */
234
234
  reader.addEventListener(
235
235
  'error',
236
- /* c8 ignore next 6 */
236
+ /* istanbul ignore next */
237
237
  function () {
238
+ /* istanbul ignore next */
238
239
  console.error(reader.error);
240
+ /* istanbul ignore next */
239
241
  div.append(
240
242
  /** @type {DOMException} */ (reader.error).message
241
243
  );
@@ -548,7 +550,7 @@ const fileType = {
548
550
  * @this {HTMLInputElement}
549
551
  */
550
552
  change () {
551
- /* c8 ignore next 3 -- TS */
553
+ /* istanbul ignore if -- TS */
552
554
  if (!this.files) {
553
555
  return;
554
556
  }
@@ -696,7 +698,7 @@ const fileType = {
696
698
 
697
699
  if (constraints) {
698
700
  const mediaStream = await getUserMedia(constraints);
699
- /* c8 ignore next 4 */
701
+ /* istanbul ignore if */
700
702
  if (!mediaStream) {
701
703
  await dialogs.alert('Error getting user media');
702
704
  return;
@@ -744,7 +746,7 @@ const fileType = {
744
746
  const mediaStream = await startScreenCapture(
745
747
  screenShareConstraints
746
748
  );
747
- /* c8 ignore next 4 */
749
+ /* istanbul ignore if */
748
750
  if (!mediaStream) {
749
751
  await dialogs.alert('Error getting user media');
750
752
  return;
@@ -829,7 +831,7 @@ const fileType = {
829
831
  'video.previewMedia'
830
832
  ));
831
833
 
832
- /* c8 ignore next 4 */
834
+ /* istanbul ignore if */
833
835
  if (!previewMedia.srcObject) {
834
836
  dialogs.alert('No stream found to record');
835
837
  return;
@@ -862,7 +864,7 @@ const fileType = {
862
864
 
863
865
  try {
864
866
  mediaRecorder.start();
865
- /* c8 ignore next 4 */
867
+ /* istanbul ignore if */
866
868
  } catch (err) {
867
869
  dialogs.alert('Error starting media recorder');
868
870
  return;
@@ -1002,7 +1004,7 @@ const fileType = {
1002
1004
  ($e(videoContainer, 'img.photo'));
1003
1005
 
1004
1006
  canvas.toBlob((blob) => {
1005
- /* c8 ignore next 4 */
1007
+ /* istanbul ignore if */
1006
1008
  if (!blob) {
1007
1009
  dialogs.alert('Error converting canvas to Blob');
1008
1010
  return;
@@ -12,7 +12,9 @@ const filelistType = {
12
12
  stringRegexEnd: /^\)/u,
13
13
 
14
14
  toValue (...args) {
15
- return arrayType.toValue.apply(this, args);
15
+ return /** @type {import('../types.js').ToValue} */ (
16
+ arrayType.toValue
17
+ ).apply(this, args);
16
18
  },
17
19
  getValue (...args) {
18
20
  return arrayType.getValue.apply(this, args);
@@ -11,7 +11,9 @@ const mapType = {
11
11
  stringRegexBegin: /^Map\(/u,
12
12
  stringRegexEnd: /^\)/u,
13
13
  toValue (...args) {
14
- return arrayType.toValue.apply(this, args);
14
+ return /** @type {import('../types.js').ToValue} */ (
15
+ arrayType.toValue
16
+ ).apply(this, args);
15
17
  },
16
18
  getValue (...args) {
17
19
  return arrayType.getValue.apply(this, args);
@@ -0,0 +1,87 @@
1
+ import {toStringTag} from '../vendor-imports.js';
2
+ import {$e} from '../utils/templateUtils.js';
3
+
4
+ /**
5
+ * @type {import('../types.js').TypeObject}
6
+ */
7
+ const noneditableType = {
8
+ // Ideally, we would remove the option,
9
+ // but edit forms currently need a pull-down option
10
+ option: ['Non-editable'],
11
+ getInput ({root}) {
12
+ return /** @type {HTMLButtonElement} */ ($e(root, 'button'));
13
+ },
14
+ setValue ({root, value}) {
15
+ /** @type {HTMLButtonElement & {$value: any}} */ (
16
+ this.getInput({root})
17
+ ).$value = value;
18
+ /** @type {HTMLSpanElement} */ (
19
+ $e(root, '.stringTag')
20
+ ).textContent = value === undefined
21
+ ? '(None)'
22
+ : toStringTag(value);
23
+ },
24
+ getValue ({root}) {
25
+ return /** @type {HTMLButtonElement & {$value: any}} */ (
26
+ this.getInput({root})
27
+ ).$value;
28
+ },
29
+ validate ({root}) {
30
+ const val = /** @type {HTMLButtonElement & {$value: any}} */ (
31
+ this.getInput({root})
32
+ ).$value;
33
+ return {
34
+ message: 'The non-editable type is only for passing on ' +
35
+ 'pre-existing content that is unknown or currently unsupported',
36
+ valid: val !== undefined
37
+ };
38
+ },
39
+ viewUI ({value}) {
40
+ return ['div', {dataset: {type: 'resurrectable'}}, [
41
+ ['b', {class: 'emphasis'}, ['Non-editable']],
42
+ ['span', {
43
+ title: 'There is no current support for editing this element\'s ' +
44
+ 'type, but its contents will be passed on transparently.'
45
+ }, ['?']],
46
+ ['b', ['String tag: ']],
47
+ toStringTag(value)
48
+ ]];
49
+ },
50
+ editUI ({typeNamespace, value}) {
51
+ return ['div', {dataset: {type: 'resurrectable'}}, [
52
+ ['a', {
53
+ // eslint-disable-next-line no-script-url -- Safe
54
+ href: 'javascript:void(0)',
55
+ $on: {
56
+ click (e) {
57
+ e.preventDefault();
58
+ }
59
+ },
60
+ title: 'There is no current support for editing this element\'s ' +
61
+ 'type, but its contents will be passed on transparently.'
62
+ }, ['?']],
63
+ ' ',
64
+ ['button', {
65
+ $on: {
66
+ click (e) {
67
+ e.preventDefault();
68
+ console.log(/** @type {HTMLButtonElement & {$value: any}} */ (
69
+ this
70
+ ).$value);
71
+ }
72
+ },
73
+ name: `${typeNamespace}-resurrectable`,
74
+ $custom: {
75
+ $value: value
76
+ }
77
+ }, [
78
+ 'Non-editable'
79
+ ]],
80
+ ['br'],
81
+ ['b', ['String tag: ']],
82
+ ['span', {class: 'stringTag'}, [value ? toStringTag(value) : '(None)']]
83
+ ]];
84
+ }
85
+ };
86
+
87
+ export default noneditableType;
@@ -8,7 +8,9 @@ const objectReferenceType = {
8
8
  type: 'object',
9
9
  stringRegex: /^objectRef\((?:|\/[^)]*)\)$/u,
10
10
  toValue (...args) {
11
- return arrayReferenceType.toValue.apply(this, args);
11
+ return /** @type {import('../types.js').ToValue} */ (
12
+ arrayReferenceType.toValue
13
+ ).apply(this, args);
12
14
  },
13
15
  resolveReference (...args) {
14
16
  return arrayReferenceType.resolveReference?.apply(
@@ -9,7 +9,9 @@ const objectType = {
9
9
  stringRegexBegin: /^\{/u,
10
10
  stringRegexEnd: /^\}/u,
11
11
  toValue (...args) {
12
- return arrayType.toValue.apply(this, args);
12
+ return /** @type {import('../types.js').ToValue} */ (
13
+ arrayType.toValue
14
+ ).apply(this, args);
13
15
  },
14
16
  getValue (...args) {
15
17
  return arrayType.getValue.apply(this, args);
@@ -11,7 +11,9 @@ const setType = {
11
11
  stringRegexBegin: /^Set\(/u,
12
12
  stringRegexEnd: /^\)/u,
13
13
  toValue (...args) {
14
- return arrayType.toValue.apply(this, args);
14
+ return /** @type {import('../types.js').ToValue} */ (
15
+ arrayType.toValue
16
+ ).apply(this, args);
15
17
  },
16
18
  getValue (...args) {
17
19
  return arrayType.getValue.apply(this, args);
@@ -18,7 +18,9 @@ const sparseUndefinedType = {
18
18
  return {value: undefined};
19
19
  },
20
20
  getValue () {
21
- return this.toValue('').value;
21
+ return /** @type {import('../types.js').ToValue} */ (
22
+ this.toValue
23
+ )('').value;
22
24
  },
23
25
  /* istanbul ignore next -- Catching instead of this placeholder */
24
26
  viewUI (/* {value} */) {
@@ -10,7 +10,9 @@ const undefinedType = {
10
10
  return {value: undefined};
11
11
  },
12
12
  getValue () {
13
- return this.toValue('').value;
13
+ return /** @type {import('../types.js').ToValue} */ (
14
+ this.toValue
15
+ )('').value;
14
16
  },
15
17
  viewUI (/* {value} */) {
16
18
  return ['i', {dataset: {type: 'undef'}}, ['undefined']];
@@ -58,7 +58,7 @@ const blobHTMLType = {
58
58
  );
59
59
  },
60
60
  getValue ({root}) {
61
- return this.toValue(
61
+ return /** @type {import('../types.js').ToValue} */ (this.toValue)(
62
62
  'data:text/html,' + /** @type {SCEditorTextarea} */ (
63
63
  this.getInput({root})
64
64
  ).sceditorInstance.val()
@@ -1,13 +1,7 @@
1
1
  import {$e} from '../utils/templateUtils.js';
2
2
 
3
3
  /**
4
- * @typedef {import('../types.js').TypeObject & {
5
- * childTypes: string[]
6
- * }} SuperTypeObject
7
- */
8
-
9
- /**
10
- * @type {SuperTypeObject}
4
+ * @type {import('../types.js').SuperTypeObject}
11
5
  */
12
6
  const SpecialNumberSuperType = {
13
7
  option: ['Special Number', {title: '`NaN`, `Infinity`, `-Infinity`, `-0`'}],
@@ -32,7 +26,7 @@ const SpecialNumberSuperType = {
32
26
  return /** @type {HTMLSelectElement} */ ($e(root, 'select'));
33
27
  },
34
28
  getValue ({root}) {
35
- return this.toValue(
29
+ return /** @type {import('../types.js').ToValue} */ (this.toValue)(
36
30
  /** @type {Required<import('../types.js').TypeObject>} */ (
37
31
  this
38
32
  ).getSelect({root}).value
@@ -1,7 +1,7 @@
1
1
  import {$e} from '../utils/templateUtils.js';
2
2
 
3
3
  /**
4
- * @type {import('./SpecialNumberType.js').SuperTypeObject}
4
+ * @type {import('../types.js').SuperTypeObject}
5
5
  */
6
6
  const SpecialRealNumberSuperType = {
7
7
  option: ['Special Real Number', {title: '`Infinity`, `-Infinity`, `-0`'}],
@@ -20,7 +20,7 @@ const SpecialRealNumberSuperType = {
20
20
  return /** @type {HTMLSelectElement} */ ($e(root, 'select'));
21
21
  },
22
22
  getValue ({root}) {
23
- return this.toValue(
23
+ return /** @type {import('../types.js').ToValue} */ (this.toValue)(
24
24
  /** @type {Required<import('../types.js').TypeObject>} */ (
25
25
  this
26
26
  ).getSelect({root}).value
@@ -1,19 +1,31 @@
1
1
  import {$e} from '../utils/templateUtils.js';
2
+ import {toStringTag} from '../vendor-imports.js';
2
3
 
3
4
  let idx = 0;
4
5
 
5
6
  /**
6
- * @type {import('../types.js').TypeObject}
7
+ * @type {import('../types.js').SuperTypeObject}
7
8
  */
8
9
  const dommatrixType = {
9
10
  option: ['DOMMatrix'],
10
- stringRegex: /^DOMMatrix\((.*)\)$/u,
11
- toValue (s) {
11
+ childTypes: ['dommatrixreadonly'],
12
+ stringRegex: /^(?<domMatrixClass>DOMMatrix|DOMMatrixReadOnly)\((?<innerContent>.*)\)$/u,
13
+ toValue (s, rootInfo) {
14
+ const {groups: {
15
+ domMatrixClass
16
+ /* istanbul ignore next -- Should always be found */
17
+ } = {}} = /** @type {RegExpMatchArray} */ (
18
+ /** @type {import('../types.js').RootInfo} */ (rootInfo).match
19
+ );
12
20
  const o = JSON.parse(s);
13
21
 
22
+ const DOMMatrixClass = domMatrixClass === 'DOMMatrix'
23
+ ? DOMMatrix
24
+ : DOMMatrixReadOnly;
25
+
14
26
  const dommatrix = Object.hasOwn(o, 'a')
15
- ? new DOMMatrix([o.a, o.b, o.c, o.d, o.e, o.f])
16
- : new DOMMatrix([
27
+ ? new DOMMatrixClass([o.a, o.b, o.c, o.d, o.e, o.f])
28
+ : new DOMMatrixClass([
17
29
  o.m11, o.m12, o.m13, o.m14,
18
30
  o.m21, o.m22, o.m23, o.m24,
19
31
  o.m31, o.m32, o.m33, o.m34,
@@ -23,7 +35,7 @@ const dommatrixType = {
23
35
  return {value: dommatrix};
24
36
  },
25
37
  getInput ({root}) {
26
- return /** @type {HTMLInputElement} */ ($e(root, 'input'));
38
+ return /** @type {HTMLInputElement} */ ($e(root, 'input:not([type])'));
27
39
  },
28
40
  setValue ({root, value: o}) {
29
41
  const {is2D} = o;
@@ -109,8 +121,23 @@ const dommatrixType = {
109
121
  $e(root, '.m44')
110
122
  ).value = o.m44;
111
123
  }
124
+
125
+ if (toStringTag(o) === 'DOMMatrix') {
126
+ /** @type {HTMLInputElement} */ (
127
+ $e(root, '.dommatrix-readonly-readwrite')
128
+ ).checked = true;
129
+ } else {
130
+ /** @type {HTMLInputElement} */ (
131
+ $e(root, '.dommatrix-readonly-readonly')
132
+ ).checked = true;
133
+ }
112
134
  },
113
135
  getValue ({root}) {
136
+ const isReadWrite = /** @type {HTMLInputElement} */ (
137
+ $e(root, '.dommatrix-readonly-readwrite')
138
+ ).checked;
139
+ const DOMMatrixClass = isReadWrite ? DOMMatrix : DOMMatrixReadOnly;
140
+
114
141
  const aType = /** @type {HTMLInputElement} */ (
115
142
  $e(root, '.a')
116
143
  ).value;
@@ -132,7 +159,7 @@ const dommatrixType = {
132
159
  const f = Number(/** @type {HTMLInputElement} */ (
133
160
  $e(root, '.f')
134
161
  ).value);
135
- return new DOMMatrix([a, b, c, d, e, f]);
162
+ return new DOMMatrixClass([a, b, c, d, e, f]);
136
163
  }
137
164
 
138
165
  const m11 = Number(/** @type {HTMLInputElement} */ (
@@ -187,7 +214,7 @@ const dommatrixType = {
187
214
  $e(root, '.m44')
188
215
  ).value);
189
216
 
190
- return new DOMMatrix([
217
+ return new DOMMatrixClass([
191
218
  m11, m12, m13, m14,
192
219
  m21, m22, m23, m24,
193
220
  m31, m32, m33, m34,
@@ -195,8 +222,11 @@ const dommatrixType = {
195
222
  ]);
196
223
  },
197
224
  viewUI ({value}) {
225
+ const isReadWrite = toStringTag(value) === 'DOMMatrix';
198
226
  return ['div', {dataset: {type: 'dommatrix'}}, [
199
- ['b', {class: 'emphasis'}, ['DOMMatrix']],
227
+ ['b', {class: 'emphasis'}, [
228
+ isReadWrite ? 'DOMMatrix' : 'DOMMatrixReadOnly'
229
+ ]],
200
230
  value.is2D
201
231
  ? ['div', [
202
232
  ['b', ['a ']],
@@ -276,11 +306,34 @@ const dommatrixType = {
276
306
  const {is2D} = value;
277
307
  // eslint-disable-next-line @stylistic/max-len -- Long
278
308
  return ['div', {dataset: {type: 'dommatrix'}}, /** @type {import('jamilih').JamilihChildren} */ ([
309
+ ['div', [
310
+ ['label', [
311
+ ['input', {
312
+ type: 'radio',
313
+ class: 'dommatrix-readonly-readwrite',
314
+ name: `${typeNamespace}-dommatrix-readonly-${idx}`,
315
+ value: 'readwrite',
316
+ checked: toStringTag(value) !== 'DOMMatrixReadOnly'
317
+ }],
318
+ 'Readwrite'
319
+ ]],
320
+ ' ',
321
+ ['label', [
322
+ ['input', {
323
+ type: 'radio',
324
+ class: 'dommatrix-readonly-readonly',
325
+ name: `${typeNamespace}-dommatrix-readonly-${idx}`,
326
+ value: 'readonly',
327
+ checked: toStringTag(value) === 'DOMMatrixReadOnly'
328
+ }],
329
+ 'Read-only'
330
+ ]]
331
+ ]],
279
332
  ['div', {
280
333
  $on: {
281
334
  click (e) {
282
335
  const {target} = e;
283
- /* c8 ignore next 3 */
336
+ /* istanbul ignore if */
284
337
  if (/** @type {HTMLInputElement} */ (target).type !== 'radio') {
285
338
  return;
286
339
  }
@@ -1,17 +1,29 @@
1
1
  import {$e} from '../utils/templateUtils.js';
2
+ import {toStringTag} from '../vendor-imports.js';
3
+
4
+ let idx = 0;
2
5
 
3
6
  /**
4
- * @type {import('../types.js').TypeObject}
7
+ * @type {import('../types.js').SuperTypeObject}
5
8
  */
6
9
  const dompointType = {
7
10
  option: ['DOMPoint'],
8
- stringRegex: /^DOMPoint\((.*)\)$/u,
9
- toValue (s) {
11
+ childTypes: ['dompointreadonly'],
12
+ stringRegex: /^(?<domPointClass>DOMPoint|DOMPointReadOnly)\((?<innerContent>.*)\)$/u,
13
+ toValue (s, rootInfo) {
14
+ const {groups: {
15
+ domPointClass
16
+ /* istanbul ignore next -- Should always be found */
17
+ } = {}} = /** @type {RegExpMatchArray} */ (
18
+ /** @type {import('../types.js').RootInfo} */ (rootInfo).match
19
+ );
10
20
  const {x, y, z, w} = JSON.parse(s);
11
- return {value: new DOMPoint(x, y, z, w)};
21
+ return {value: new (
22
+ domPointClass === 'DOMPoint' ? DOMPoint : DOMPointReadOnly
23
+ )(x, y, z, w)};
12
24
  },
13
25
  getInput ({root}) {
14
- return /** @type {HTMLInputElement} */ ($e(root, 'input'));
26
+ return /** @type {HTMLInputElement} */ ($e(root, 'input:not([type])'));
15
27
  },
16
28
  setValue ({root, value}) {
17
29
  /** @type {HTMLInputElement} */ (
@@ -26,6 +38,16 @@ const dompointType = {
26
38
  /** @type {HTMLInputElement} */ (
27
39
  $e(root, '.w')
28
40
  ).value = String(value.w);
41
+
42
+ if (toStringTag(value) === 'DOMPoint') {
43
+ /** @type {HTMLInputElement} */ (
44
+ $e(root, '.dompoint-readonly-readwrite')
45
+ ).checked = true;
46
+ } else {
47
+ /** @type {HTMLInputElement} */ (
48
+ $e(root, '.dompoint-readonly-readonly')
49
+ ).checked = true;
50
+ }
29
51
  },
30
52
  getValue ({root}) {
31
53
  const x = Number(/** @type {HTMLInputElement} */ (
@@ -40,11 +62,18 @@ const dompointType = {
40
62
  const w = Number(/** @type {HTMLInputElement} */ (
41
63
  $e(root, '.w')
42
64
  ).value);
43
- return new DOMPoint(x, y, z, w);
65
+
66
+ const isReadWrite = /** @type {HTMLInputElement} */ (
67
+ $e(root, '.dompoint-readonly-readwrite')
68
+ ).checked;
69
+ return new (isReadWrite ? DOMPoint : DOMPointReadOnly)(x, y, z, w);
44
70
  },
45
71
  viewUI ({value}) {
72
+ const isReadWrite = toStringTag(value) === 'DOMPoint';
46
73
  return ['div', {dataset: {type: 'dompoint'}}, [
47
- ['b', {class: 'emphasis'}, ['DOMPoint']],
74
+ ['b', {class: 'emphasis'}, [
75
+ isReadWrite ? 'DOMPoint' : 'DOMPointReadOnly'
76
+ ]],
48
77
  ['br'],
49
78
  ['b', ['x ']],
50
79
  value.x,
@@ -65,8 +94,32 @@ const dompointType = {
65
94
  z: '',
66
95
  w: ''
67
96
  }}) {
97
+ idx++;
68
98
  // eslint-disable-next-line @stylistic/max-len -- Long
69
99
  return ['div', {dataset: {type: 'dompoint'}}, /** @type {import('jamilih').JamilihChildren} */ ([
100
+ ['div', [
101
+ ['label', [
102
+ ['input', {
103
+ type: 'radio',
104
+ class: 'dompoint-readonly-readwrite',
105
+ name: `${typeNamespace}-dompoint-readonly-${idx}`,
106
+ value: 'readwrite',
107
+ checked: toStringTag(value) !== 'DOMPointReadOnly'
108
+ }],
109
+ 'Readwrite'
110
+ ]],
111
+ ' ',
112
+ ['label', [
113
+ ['input', {
114
+ type: 'radio',
115
+ class: 'dompoint-readonly-readonly',
116
+ name: `${typeNamespace}-dompoint-readonly-${idx}`,
117
+ value: 'readonly',
118
+ checked: toStringTag(value) === 'DOMPointReadOnly'
119
+ }],
120
+ 'Read-only'
121
+ ]]
122
+ ]],
70
123
  ['label', [
71
124
  'x: ',
72
125
  ['input', {
@@ -1,17 +1,30 @@
1
1
  import {$e} from '../utils/templateUtils.js';
2
+ import {toStringTag} from '../vendor-imports.js';
3
+
4
+ let idx = 0;
2
5
 
3
6
  /**
4
- * @type {import('../types.js').TypeObject}
7
+ * @type {import('../types.js').SuperTypeObject}
5
8
  */
6
9
  const domrectType = {
7
10
  option: ['DOMRect'],
8
- stringRegex: /^DOMRect\((.*)\)$/u,
9
- toValue (s) {
11
+ childTypes: ['domrectreadonly'],
12
+ stringRegex: /^(?<domRectClass>DOMRect|DOMRectReadOnly)\((?<innerContent>.*)\)$/u,
13
+ toValue (s, rootInfo) {
14
+ const {groups: {
15
+ domRectClass
16
+ /* istanbul ignore next -- Should always be found */
17
+ } = {}} = /** @type {RegExpMatchArray} */ (
18
+ /** @type {import('../types.js').RootInfo} */ (rootInfo).match
19
+ );
10
20
  const {x, y, width, height} = JSON.parse(s);
11
- return {value: new DOMRect(x, y, width, height)};
21
+ return {
22
+ value: new (
23
+ domRectClass === 'DOMRect' ? DOMRect : DOMRectReadOnly
24
+ )(x, y, width, height)};
12
25
  },
13
26
  getInput ({root}) {
14
- return /** @type {HTMLInputElement} */ ($e(root, 'input'));
27
+ return /** @type {HTMLInputElement} */ ($e(root, 'input:not([type])'));
15
28
  },
16
29
  setValue ({root, value}) {
17
30
  /** @type {HTMLInputElement} */ (
@@ -26,6 +39,16 @@ const domrectType = {
26
39
  /** @type {HTMLInputElement} */ (
27
40
  $e(root, '.height')
28
41
  ).value = String(value.height);
42
+
43
+ if (toStringTag(value) === 'DOMRect') {
44
+ /** @type {HTMLInputElement} */ (
45
+ $e(root, '.domrect-readonly-readwrite')
46
+ ).checked = true;
47
+ } else {
48
+ /** @type {HTMLInputElement} */ (
49
+ $e(root, '.domrect-readonly-readonly')
50
+ ).checked = true;
51
+ }
29
52
  },
30
53
  getValue ({root}) {
31
54
  const x = Number(/** @type {HTMLInputElement} */ (
@@ -40,11 +63,16 @@ const domrectType = {
40
63
  const height = Number(/** @type {HTMLInputElement} */ (
41
64
  $e(root, '.height')
42
65
  ).value);
43
- return new DOMRect(x, y, width, height);
66
+
67
+ const isReadWrite = /** @type {HTMLInputElement} */ (
68
+ $e(root, '.domrect-readonly-readwrite')
69
+ ).checked;
70
+ return new (isReadWrite ? DOMRect : DOMRectReadOnly)(x, y, width, height);
44
71
  },
45
72
  viewUI ({value}) {
73
+ const isReadWrite = toStringTag(value) === 'DOMRect';
46
74
  return ['div', {dataset: {type: 'domrect'}}, [
47
- ['b', {class: 'emphasis'}, ['DOMRect']],
75
+ ['b', {class: 'emphasis'}, [isReadWrite ? 'DOMRect' : 'DOMRectReadOnly']],
48
76
  ['br'],
49
77
  ['b', ['x ']],
50
78
  value.x,
@@ -65,8 +93,32 @@ const domrectType = {
65
93
  width: '',
66
94
  height: ''
67
95
  }}) {
96
+ idx++;
68
97
  // eslint-disable-next-line @stylistic/max-len -- Long
69
98
  return ['div', {dataset: {type: 'domrect'}}, /** @type {import('jamilih').JamilihChildren} */ ([
99
+ ['div', [
100
+ ['label', [
101
+ ['input', {
102
+ type: 'radio',
103
+ class: 'domrect-readonly-readwrite',
104
+ name: `${typeNamespace}-domrect-readonly-${idx}`,
105
+ value: 'readwrite',
106
+ checked: toStringTag(value) !== 'DOMRectReadOnly'
107
+ }],
108
+ 'Readwrite'
109
+ ]],
110
+ ' ',
111
+ ['label', [
112
+ ['input', {
113
+ type: 'radio',
114
+ class: 'domrect-readonly-readonly',
115
+ name: `${typeNamespace}-domrect-readonly-${idx}`,
116
+ value: 'readonly',
117
+ checked: toStringTag(value) === 'DOMRectReadOnly'
118
+ }],
119
+ 'Read-only'
120
+ ]]
121
+ ]],
70
122
  ['label', [
71
123
  'x: ',
72
124
  ['input', {
@@ -44,7 +44,7 @@ if (typeof InternalError !== 'undefined') {
44
44
  const specialErrors = [...specialErrorsMap.keys()];
45
45
 
46
46
  /**
47
- * @type {import('./SpecialNumberType.js').SuperTypeObject}
47
+ * @type {import('../types.js').SuperTypeObject}
48
48
  */
49
49
  const errorsSpecialType = {
50
50
  option: ['Special errors'],