Skip to content

Commit 498656e

Browse files
mrkishiRich-Harris
andauthored
DataView support (#143)
* fix: rename test file so uvu picks it up * chore: add simple benchmarks Based on Svelte's benchmark scaffolding. * feat: simplify TypedArray slices * feat: use native alternatives to encode/decode base64 * feat: whitelist `Float16Array` * fix: guarantee flatten return type * chore: add prettier configuration Add a `.prettierrc` file matching Svelte's. * chore: add missing (boxed) primitives tests * fix: support boxed bigints and boxed sentinel values * fix: reject `Symbol`s instead of producing invalid output * fix: correct typed array construction in `uneval`'s reference path * chore: add more repetition tests * fix: handle missing types in `uneval`'s reference path * feat: add `DataView` support --------- Co-authored-by: Rich Harris <rich.harris@vercel.com>
1 parent 5590634 commit 498656e

5 files changed

Lines changed: 76 additions & 2 deletions

File tree

.changeset/common-cases-shake.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'devalue': minor
3+
---
4+
5+
feat: add `DataView` support

src/parse.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,8 @@ export function unflatten(parsed, revivers) {
156156
case 'Float32Array':
157157
case 'Float64Array':
158158
case 'BigInt64Array':
159-
case 'BigUint64Array': {
159+
case 'BigUint64Array':
160+
case 'DataView': {
160161
if (values[value[1]][0] !== 'ArrayBuffer') {
161162
// without this, if we receive malformed input we could
162163
// end up trying to hydrate in a circle or allocate

src/stringify.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,8 @@ export function stringify(value, reducers) {
223223
case 'Float32Array':
224224
case 'Float64Array':
225225
case 'BigInt64Array':
226-
case 'BigUint64Array': {
226+
case 'BigUint64Array':
227+
case 'DataView': {
227228
/** @type {import("./types.js").TypedArray} */
228229
const typedArray = thing;
229230
str = '["' + type + '",' + flatten(typedArray.buffer);

src/uneval.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ export function uneval(value, replacer) {
9696
case 'Float64Array':
9797
case 'BigInt64Array':
9898
case 'BigUint64Array':
99+
case 'DataView':
99100
walk(thing.buffer);
100101
return;
101102

@@ -303,6 +304,23 @@ export function uneval(value, replacer) {
303304
return str;
304305
}
305306

307+
case 'DataView': {
308+
let str = `new DataView`;
309+
310+
if (!names.has(thing.buffer)) {
311+
str += `(new Uint8Array([${new Uint8Array(thing.buffer)}]).buffer`;
312+
} else {
313+
str += `(${stringify(thing.buffer)}`;
314+
}
315+
316+
// handle subviews
317+
if (thing.byteLength !== thing.buffer.byteLength) {
318+
str += `,${thing.startOffset},${thing.byteLength}`;
319+
}
320+
321+
return str + ')';
322+
}
323+
306324
case 'ArrayBuffer': {
307325
const ui8 = new Uint8Array(thing);
308326
return `new Uint8Array([${ui8.toString()}]).buffer`;
@@ -439,6 +457,27 @@ export function uneval(value, replacer) {
439457
break;
440458
}
441459

460+
case 'DataView': {
461+
let str = `new DataView`;
462+
463+
if (!names.has(thing.buffer)) {
464+
str += `(new Uint8Array([${new Uint8Array(thing.buffer)}]).buffer`;
465+
} else {
466+
str += `(${stringify(thing.buffer)}`;
467+
}
468+
469+
// handle subviews
470+
if (thing.byteLength !== thing.buffer.byteLength) {
471+
str += `,${thing.byteOffset},${thing.byteLength}`;
472+
}
473+
474+
str += ')';
475+
476+
values.push(`{}`);
477+
statements.push(`${name}=${str}`);
478+
break;
479+
}
480+
442481
case 'ArrayBuffer':
443482
values.push(`new Uint8Array([${new Uint8Array(thing)}]).buffer`);
444483
break;

test/index.test.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,12 @@ const fixtures = {
305305
js: 'new Uint8Array([1,2,3]).buffer',
306306
json: '[["ArrayBuffer","AQID"]]'
307307
},
308+
{
309+
name: 'DataView',
310+
value: new DataView(new Uint8Array([1, 2, 3]).buffer),
311+
js: 'new DataView(new Uint8Array([1,2,3]).buffer)',
312+
json: '[["DataView",1],["ArrayBuffer","AQID"]]'
313+
},
308314
{
309315
name: 'URL',
310316
value: new URL('https://user:password@example.com/<script>/path?foo=bar#hash'),
@@ -670,6 +676,28 @@ const fixtures = {
670676
})(),
671677
js: '(function(a,b){a=new Uint8Array(b);return [a,a,new Uint16Array(b)]}({},new Uint8Array([0,1,2,3,4,5,6,7,8,9]).buffer))',
672678
json: '[[1,1,3],["Uint8Array",2],["ArrayBuffer","AAECAwQFBgcICQ=="],["Uint16Array",2]]'
679+
},
680+
681+
{
682+
name: 'DataView (repetition)',
683+
value: (() => {
684+
const uint8 = new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
685+
const dv = new DataView(uint8.buffer);
686+
return [dv, dv];
687+
})(),
688+
js: '(function(a){a=new DataView(new Uint8Array([0,1,2,3,4,5,6,7,8,9]).buffer);return [a,a]}({}))',
689+
json: '[[1,1],["DataView",2],["ArrayBuffer","AAECAwQFBgcICQ=="]]'
690+
},
691+
692+
{
693+
name: 'Array Buffer and DataView (repetition)',
694+
value: (() => {
695+
const uint8 = new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
696+
const dv = new DataView(uint8.buffer);
697+
return [dv, dv, uint8.buffer];
698+
})(),
699+
js: '(function(a,b){a=new DataView(b);return [a,a,b]}({},new Uint8Array([0,1,2,3,4,5,6,7,8,9]).buffer))',
700+
json: '[[1,1,2],["DataView",2],["ArrayBuffer","AAECAwQFBgcICQ=="]]'
673701
}
674702
],
675703

0 commit comments

Comments
 (0)