@es-joy/jsoe 0.5.1 → 0.6.1

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 (80) hide show
  1. package/.eslintignore +2 -0
  2. package/.eslintrc.cjs +2 -0
  3. package/.nyc_output/out.json +121296 -0
  4. package/CHANGES.md +10 -0
  5. package/README.md +47 -21
  6. package/cypress.config.ts +13 -0
  7. package/demo/index-instrumented.html +29 -0
  8. package/demo/index.html +10 -1
  9. package/demo/index.js +482 -126
  10. package/dist/formatAndTypeChoices.d.ts +2 -2
  11. package/dist/formatAndTypeChoices.d.ts.map +1 -1
  12. package/dist/formats/json.d.ts.map +1 -1
  13. package/dist/formats/structuredCloning.d.ts +2 -1
  14. package/dist/formats/structuredCloning.d.ts.map +1 -1
  15. package/dist/fundamentalTypes/arrayType.d.ts +6 -37
  16. package/dist/fundamentalTypes/arrayType.d.ts.map +1 -1
  17. package/dist/fundamentalTypes/dateType.d.ts.map +1 -1
  18. package/dist/fundamentalTypes/errorType.d.ts +6 -0
  19. package/dist/fundamentalTypes/errorType.d.ts.map +1 -0
  20. package/dist/fundamentalTypes/mapType.d.ts +6 -0
  21. package/dist/fundamentalTypes/mapType.d.ts.map +1 -0
  22. package/dist/fundamentalTypes/nullType.d.ts.map +1 -1
  23. package/dist/fundamentalTypes/objectReferenceType.d.ts.map +1 -1
  24. package/dist/fundamentalTypes/setType.d.ts +6 -0
  25. package/dist/fundamentalTypes/setType.d.ts.map +1 -0
  26. package/dist/fundamentalTypes/sparseUndefinedType.d.ts.map +1 -1
  27. package/dist/fundamentalTypes/undefinedType.d.ts.map +1 -1
  28. package/dist/subTypes/blobHTMLType.d.ts +12 -6
  29. package/dist/subTypes/blobHTMLType.d.ts.map +1 -1
  30. package/dist/superTypes/SpecialNumberType.d.ts +14 -0
  31. package/dist/superTypes/SpecialNumberType.d.ts.map +1 -0
  32. package/dist/superTypes/SpecialRealNumberType.d.ts +6 -0
  33. package/dist/superTypes/SpecialRealNumberType.d.ts.map +1 -0
  34. package/dist/superTypes/errorsSpecialType.d.ts +8 -0
  35. package/dist/superTypes/errorsSpecialType.d.ts.map +1 -0
  36. package/dist/typeChoices.d.ts +4 -2
  37. package/dist/typeChoices.d.ts.map +1 -1
  38. package/dist/types.d.ts +83 -231
  39. package/dist/types.d.ts.map +1 -1
  40. package/dist/utils/dialogs.d.ts +22 -22
  41. package/dist/utils/dialogs.d.ts.map +1 -1
  42. package/dist/utils/templateUtils.d.ts +6 -6
  43. package/dist/utils/templateUtils.d.ts.map +1 -1
  44. package/dist/vendor-imports.d.ts +1 -1
  45. package/package.json +39 -34
  46. package/rollup.config.js +14 -2
  47. package/server.js +1 -1
  48. package/src/formatAndTypeChoices.js +9 -9
  49. package/src/formats/indexedDBKey.js +2 -2
  50. package/src/formats/json.js +1 -2
  51. package/src/formats/structuredCloning.js +101 -29
  52. package/src/formats.js +2 -2
  53. package/src/fundamentalTypes/arrayReferenceType.js +3 -3
  54. package/src/fundamentalTypes/arrayType.js +390 -87
  55. package/src/fundamentalTypes/dateType.js +4 -6
  56. package/src/fundamentalTypes/errorType.js +416 -0
  57. package/src/fundamentalTypes/mapType.js +34 -0
  58. package/src/fundamentalTypes/nullType.js +1 -2
  59. package/src/fundamentalTypes/objectReferenceType.js +2 -1
  60. package/src/fundamentalTypes/regexpType.js +2 -2
  61. package/src/fundamentalTypes/setType.js +34 -0
  62. package/src/fundamentalTypes/sparseUndefinedType.js +2 -3
  63. package/src/fundamentalTypes/undefinedType.js +2 -3
  64. package/src/jsoe.css +3 -0
  65. package/src/subTypes/blobHTMLType.js +37 -33
  66. package/src/subTypes/falseType.js +2 -2
  67. package/src/subTypes/trueType.js +2 -2
  68. package/src/superTypes/{SpecialNumberSuperType.js → SpecialNumberType.js} +1 -1
  69. package/src/superTypes/{SpecialRealNumberSuperType.js → SpecialRealNumberType.js} +3 -2
  70. package/src/superTypes/errorsSpecialType.js +768 -0
  71. package/src/typeChoices.js +27 -20
  72. package/src/types.js +71 -39
  73. package/src/utils/dialogs.js +11 -12
  74. package/src/utils/jsonPointer.js +3 -3
  75. package/src/utils/templateUtils.js +4 -4
  76. package/src/vendor-imports.js +2 -2
  77. package/tsconfig.json +1 -1
  78. package/typings/CypressPlugins.d.ts +10 -0
  79. package/vendor/jamilih/dist/jml-es.js +126 -106
  80. package/vendor/typeson-registry/dist/index.js +188 -44
@@ -17,9 +17,10 @@ import json from './json.js';
17
17
  * type: import('../types.js').AvailableType,
18
18
  * value: import('../formats.js').StructuredCloneValue,
19
19
  * bringIntoFocus?: boolean,
20
+ * setAValue?: boolean,
20
21
  * schemaContent?: object,
21
22
  * schemaState?: import('../types.js').GetPossibleSchemasForPathAndType
22
- * }) => HTMLElement} AddAndSetArrayElement
23
+ * }) => HTMLElement|null} AddAndSetArrayElement
23
24
  */
24
25
 
25
26
  /**
@@ -44,6 +45,10 @@ const encapsulateObserver = (stateObj) => {
44
45
  * }}}
45
46
  */
46
47
  const parents = {};
48
+
49
+ /** @type {string[]} */
50
+ const mapPaths = [];
51
+
47
52
  return (observerObj) => {
48
53
  const {
49
54
  type,
@@ -57,13 +62,15 @@ const encapsulateObserver = (stateObj) => {
57
62
  endIterateUnsetNumeric,
58
63
  clone
59
64
  } = observerObj;
60
- // console.log('observerObj', observerObj);
61
65
  if ('replaced' in observerObj) {
62
66
  return;
63
67
  }
64
68
  if (cyclic === 'readonly' && !Array.isArray(observerObj.value)) {
65
69
  return;
66
70
  }
71
+ if (cyclic === 'readonly' && type === 'set') {
72
+ return;
73
+ }
67
74
  if (endIterateIn || endIterateOwn) {
68
75
  return;
69
76
  }
@@ -73,6 +80,12 @@ const encapsulateObserver = (stateObj) => {
73
80
  return;
74
81
  }
75
82
 
83
+ // What other situations is this firing twice, and it
84
+ // shouldn't reach here?
85
+ if (observerObj.replacing && type === 'negativeZero') {
86
+ return;
87
+ }
88
+
76
89
  /* istanbul ignore if -- Not part of format */
77
90
  if (type === 'sparseUndefined') { // We'll handle otherwise
78
91
  return;
@@ -119,12 +132,21 @@ const encapsulateObserver = (stateObj) => {
119
132
  const parentPath = li === -1 ? '' : keypath.slice(0, li);
120
133
 
121
134
  const hasChildren = [
122
- 'array', 'object',
135
+ 'array', 'object', 'set', 'map',
123
136
  // 'sparseArrays',
124
137
  'arrayNonindexKeys'
125
138
  ].includes(newType);
126
139
 
140
+ // Maps are followed up by arrays which we don't want as such;
141
+ // we track the paths to avoid reporting these child arrays
142
+ const mapType = type === 'map' &&
143
+ Object.prototype.toString.call(value) === '[object Map]';
144
+ if (mapType) {
145
+ mapPaths.push(keypath);
146
+ }
147
+
127
148
  if (!stateObj.rootUI) {
149
+ // console.log('vvvv0', newType, newValue);
128
150
  stateObj.rootUI = Types.getUIForModeAndType({
129
151
  readonly,
130
152
  typeNamespace,
@@ -152,6 +174,18 @@ const encapsulateObserver = (stateObj) => {
152
174
  * @type {HTMLElement &
153
175
  * {$addAndSetArrayElement: AddAndSetArrayElement}}
154
176
  */ (stateObj.rootUI);
177
+
178
+ // Since we're skipping the array elements, we need to add the
179
+ // map element to the array index where the array children
180
+ // will be found (which we do want)
181
+ if (mapType) {
182
+ /** @type {Map<any, any>} */ [...value].forEach((_, i) => {
183
+ parents[i] = /**
184
+ * @type {HTMLElement &
185
+ * {$addAndSetArrayElement: AddAndSetArrayElement}}
186
+ */ (stateObj.rootUI);
187
+ });
188
+ }
155
189
  return;
156
190
  }
157
191
 
@@ -172,6 +206,22 @@ const encapsulateObserver = (stateObj) => {
172
206
  return;
173
207
  }
174
208
 
209
+ // Skip the array structures immediately following the Map,
210
+ // as map needs to handle
211
+ if (!mapType && mapPaths.some((mapPath) => {
212
+ if (mapPath === keypath ||
213
+ (mapPath === '' && (/^\d+$/u).test(keypath))) {
214
+ return true;
215
+ }
216
+ const trailingIndex = keypath.match(/\.\d+$/u);
217
+ return (trailingIndex && mapPath !== '' &&
218
+ keypath.slice(0, -trailingIndex[0].length) === mapPath);
219
+ })) {
220
+ return;
221
+ }
222
+
223
+ // console.log('vvvv', newType, '::', newValue, '::', newValue?.cause);
224
+
175
225
  const root = ui.$addAndSetArrayElement({
176
226
  propName: arrayOrObjectPropertyName,
177
227
  type: newType,
@@ -188,6 +238,12 @@ const encapsulateObserver = (stateObj) => {
188
238
  })
189
239
  */
190
240
  });
241
+
242
+ /* istanbul ignore if -- Guard for `null` return */
243
+ if (!root) {
244
+ return;
245
+ }
246
+
191
247
  if (!readonly) {
192
248
  Types.setValue({
193
249
  type: newType,
@@ -210,6 +266,18 @@ const encapsulateObserver = (stateObj) => {
210
266
  */ (
211
267
  root
212
268
  );
269
+
270
+ // Since we're skipping the array elements, we need to add the
271
+ // map element to the array index where the array children
272
+ // will be found (which we do want)
273
+ if (mapType) {
274
+ /** @type {Map<any, any>} */ [...value].forEach((_, i) => {
275
+ parents[`${keypath}.${i}`] = /**
276
+ * @type {HTMLElement &
277
+ * {$addAndSetArrayElement: AddAndSetArrayElement}}
278
+ */ (root);
279
+ });
280
+ }
213
281
  }
214
282
  });
215
283
  };
@@ -247,7 +315,7 @@ const canonicalToAvailableType = (format, state, valType, v) => {
247
315
  * @type {import('../types.js').AvailableType|undefined}
248
316
  */
249
317
  let ret;
250
- console.log('format, state, valType, v', format, state, valType, v);
318
+ // console.log('format, state, valType, v', format, state, valType, v);
251
319
 
252
320
  /**
253
321
  * @param {string} newValType
@@ -278,9 +346,9 @@ const canonicalToAvailableType = (format, state, valType, v) => {
278
346
  })) {
279
347
  return /** @type {import('../types.js').AvailableType} */ (ret);
280
348
  }
281
- console.log('ret', ret);
349
+ // console.log('ret', ret);
282
350
  allowableTypes.some((allowableType) => {
283
- // eslint-disable-next-line max-len -- Long
351
+ // eslint-disable-next-line @stylistic/max-len -- Long
284
352
  const typeObj = /** @type {import('../types.js').TypeObject & {childTypes: string[]}} */ (
285
353
  Types.availableTypes[allowableType]
286
354
  );
@@ -298,7 +366,7 @@ const canonicalToAvailableType = (format, state, valType, v) => {
298
366
  }
299
367
  return false;
300
368
  });
301
- console.log('ret2', ret);
369
+ // console.log('ret2', ret);
302
370
  if (ret === undefined) {
303
371
  return isInvalid(valType);
304
372
  }
@@ -315,7 +383,7 @@ const canonicalToAvailableType = (format, state, valType, v) => {
315
383
  /** @type {import('../formats.js').Format} */
316
384
  const structuredCloning = {
317
385
  iterate (records, stateObj) {
318
- console.log('records', records);
386
+ // console.log('records', records);
319
387
  if (!stateObj.format) {
320
388
  stateObj.format = 'structuredCloning';
321
389
  }
@@ -348,6 +416,12 @@ const structuredCloning = {
348
416
  });
349
417
  return typesForFormat;
350
418
  }
419
+ // Todo: Could we implement schemas here by introducing new keys to
420
+ // `Types.contexts` which could be used rather than manual
421
+ // handling to determine a delimited group of children
422
+ if (state === 'errorsArray') {
423
+ return ['error', 'errors'];
424
+ }
351
425
  return this.types();
352
426
  /*
353
427
  // Todo (low): These need to specify their own inner contexts
@@ -375,35 +449,33 @@ const structuredCloning = {
375
449
  ...jsonTypes,
376
450
  'undef', // Explicit undefined only
377
451
  'bigint',
378
- 'SpecialNumber', // '`NaN`, `Infinity`, `-Infinity`'},
452
+ 'SpecialNumber', // '`NaN`, `Infinity`, `-Infinity`, `-0`
379
453
  'date',
380
454
  'regexp',
381
455
  'BooleanObject',
382
456
  'NumberObject',
383
457
  'StringObject',
384
- 'blobHTML'
458
+ 'error',
459
+ 'errors',
460
+ 'blobHTML',
461
+ 'set',
462
+ 'map'
385
463
  // Ok, but will need some work
386
- // 'map', 'set',
387
- // 'blob', 'file', 'filelist'
388
- // 'arraybuffer', 'arraybufferview'
464
+ // 'blob', 'file', 'filelist',
465
+ // 'arraybuffer',
389
466
  // 'dataview', 'imagedata', 'imagebitmap',
390
467
  /*
391
- // Typed Arrays
392
- 'int8array',
393
- 'uint8array',
394
- 'uint8clampedarray',
395
- 'int16array',
396
- 'uint16array',
397
- 'int32array',
398
- 'uint32array',
399
- 'float32array',
400
- 'float64array',
401
-
402
- // Intl (imperfect)
403
- 'IntlCollator',
404
- 'IntlDateTimeFormat',
405
- 'IntlNumberFormat'
406
- */
468
+ // Typed Arrays
469
+ 'int8array',
470
+ 'uint8array',
471
+ 'uint8clampedarray',
472
+ 'int16array',
473
+ 'uint16array',
474
+ 'int32array',
475
+ 'uint32array',
476
+ 'float32array',
477
+ 'float64array',
478
+ */
407
479
  ];
408
480
  }
409
481
  };
package/src/formats.js CHANGED
@@ -56,8 +56,8 @@ const Formats = {
56
56
  * @returns {Promise<Element>}
57
57
  */
58
58
  export async function getControlsForFormatAndValue (format, record, stateObj) {
59
- return await Formats.availableFormats[format]
60
- .iterate(record, {
59
+ return await Formats.availableFormats[format].
60
+ iterate(record, {
61
61
  ...stateObj,
62
62
  // This had been before `stateObj` but should apparently have precedence
63
63
  // or just avoid passing `format` to this function
@@ -35,7 +35,7 @@ const arrayReferenceType = {
35
35
  structuredCloning: {
36
36
  // after: 'sparseArrays',
37
37
  after: 'arrayNonindexKeys',
38
- contexts: ['arrayNonindexKeys', 'object']
38
+ contexts: ['arrayNonindexKeys', 'object', 'set']
39
39
  // contexts: ['sparseArrays', 'object']
40
40
  }
41
41
  },
@@ -47,7 +47,7 @@ const arrayReferenceType = {
47
47
  },
48
48
  getValue ({root, stateObj, currentPath}) {
49
49
  const referentPath = this.getInput({root}).value;
50
- // eslint-disable-next-line max-len -- Long
50
+ // eslint-disable-next-line @stylistic/max-len -- Long
51
51
  /* istanbul ignore else -- ArrayRef will not be a root, so should have stateObj */
52
52
  if (stateObj) {
53
53
  if (!stateObj.paths) {
@@ -97,7 +97,7 @@ const arrayReferenceType = {
97
97
  'arrayNonindexKeys'
98
98
  // 'sparseArrays'
99
99
  ].includes(
100
- /** @type {string} */ (Types.getTypeForRoot(referent))
100
+ Types.getTypeForRoot(referent)
101
101
  );
102
102
  };
103
103
  let message;