Skip to content

Commit

Permalink
Support ArrayBuffers
Browse files Browse the repository at this point in the history
  • Loading branch information
overlookmotel committed Oct 1, 2023
1 parent 49b8dca commit ee4c77f
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 27 deletions.
68 changes: 49 additions & 19 deletions lib/serialize/buffers.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const t = require('@babel/types');

// Imports
const {createDependency, createAssignment} = require('./records.js'),
{ARRAY_BUFFER_TYPE, registerSerializer} = require('./types.js'),
{isNumberKey} = require('./utils.js');

// Exports
Expand Down Expand Up @@ -83,25 +84,16 @@ module.exports = {
return this.wrapWithProperties(buf, record, node, defaultProto, undefined, isNumberKey);
},

serializeArrayBuffer(buf, record) {
// If empty, short initialization
const uint = new Uint8Array(buf);

let node;
if (uint.every(byte => byte === 0)) {
// `new ArrayBuffer(8)`
const arrayBufferRecord = this.serializeValue(ArrayBuffer);
node = t.newExpression(arrayBufferRecord.varNode, [t.numericLiteral(uint.length)]);
createDependency(record, arrayBufferRecord, node, 'callee');
} else {
// `new Uint8Array(...).buffer`
const uintRecord = this.serializeValue(uint, `${record.varNode.name}Buffer`, '<uint>');
node = t.memberExpression(uintRecord.varNode, t.identifier('buffer'));
createDependency(record, uintRecord, node, 'object');
}

// Wrap in properties
return this.wrapWithProperties(buf, record, node, ArrayBuffer.prototype);
/**
* Trace ArrayBuffer.
* @param {ArrayBuffer} buf - ArrayBuffer
* @param {Object} record - Record
* @returns {number} - Type ID
*/
traceArrayBuffer(buf, record) {
this.traceProperties(buf, record, undefined);
record.extra = {buf};
return ARRAY_BUFFER_TYPE;
},

serializeSharedArrayBuffer(buf, record) {
Expand Down Expand Up @@ -150,3 +142,41 @@ module.exports = {
return this.wrapWithProperties(buf, record, node, SharedArrayBuffer.prototype);
}
};

/**
* Serialize ArrayBuffer.
* @this {Object} Serializer
* @param {Object} record - Record
* @param {Object} record.extra - Extra props object
* @param {ArrayBuffer} record.extra.buf - ArrayBuffer
* @returns {Object} - AST node
*/
function serializeArrayBuffer(record) {
const uint = new Uint8Array(record.extra.buf);

let allZero = true;
const valNodes = [];
for (const val of uint) {
if (val === 0) {
valNodes.push(null);
} else {
valNodes.push(t.numericLiteral(val));
allZero = false;
}
}

let node;
if (allZero) {
// `new ArrayBuffer(8)`
node = t.newExpression(this.traceAndSerializeGlobal(ArrayBuffer), [t.numericLiteral(uint.length)]);
} else {
// `new Uint8Array(...).buffer`
node = t.memberExpression(
t.newExpression(this.traceAndSerializeGlobal(Uint8Array), [t.arrayExpression(valNodes)]),
t.identifier('buffer')
);
}

return this.wrapWithProperties(node, record, this.arrayBufferPrototypeRecord, null);
}
registerSerializer(ARRAY_BUFFER_TYPE, serializeArrayBuffer);
3 changes: 2 additions & 1 deletion lib/serialize/trace.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ module.exports = {
this.numberPrototypeRecord = this.traceValue(Number.prototype, null, null);
this.bigIntPrototypeRecord = this.traceValue(BigInt.prototype, null, null);
this.symbolPrototypeRecord = this.traceValue(Symbol.prototype, null, null);
this.arrayBufferPrototypeRecord = this.traceValue(ArrayBuffer.prototype, null, null);

this.minusZeroRecord = null;

Expand Down Expand Up @@ -160,7 +161,7 @@ module.exports = {
if (objType === 'WeakRef') return this.traceWeakRef(val, record);
if (objType === 'FinalizationRegistry') return this.traceFinalizationRegistry(val, record);
// if (typedArrayRegex.test(objType)) return this.traceBuffer(val, objType, record);
// if (objType === 'ArrayBuffer') return this.traceArrayBuffer(val, record);
if (objType === 'ArrayBuffer') return this.traceArrayBuffer(val, record);
// if (objType === 'SharedArrayBuffer') return this.traceSharedArrayBuffer(val, record);
if (objType === 'String') return this.traceBoxedString(val, record);
if (objType === 'Boolean') return this.traceBoxedBoolean(val, record);
Expand Down
4 changes: 4 additions & 0 deletions lib/serialize/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ const NO_TYPE = 0,
GLOBAL_MINUS_INFINITY_TYPE = GLOBAL_TYPE | 6,
SYMBOL_TYPE = 256,
SYMBOL_FOR_TYPE = SYMBOL_TYPE | 1,
BUFFER_TYPE = 512,
ARRAY_BUFFER_TYPE = BUFFER_TYPE | 1,
EXPORT_JS_TYPE = 1,
EXPORT_COMMONJS_TYPE = 2,
EXPORT_ESM_TYPE = 3,
Expand Down Expand Up @@ -94,6 +96,8 @@ module.exports = {
GLOBAL_MINUS_INFINITY_TYPE,
SYMBOL_TYPE,
SYMBOL_FOR_TYPE,
BUFFER_TYPE,
ARRAY_BUFFER_TYPE,
EXPORT_JS_TYPE,
EXPORT_COMMONJS_TYPE,
EXPORT_ESM_TYPE,
Expand Down
14 changes: 7 additions & 7 deletions test/buffers.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ const {itSerializes, itSerializesEqual} = require('./support/index.js');

// Tests

describe.skip('Buffers', () => {
describe('nodeJS Buffers', () => {
describe('Buffers', () => {
describe.skip('nodeJS Buffers', () => {
itSerializesEqual('without extra props', {
in: () => Buffer.from('ABCDEFGHIJKLMNOPQRSTUVWXYZ'),
out: 'Buffer.from("QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVo=","base64")',
Expand Down Expand Up @@ -64,7 +64,7 @@ describe.skip('Buffers', () => {
});
});

describe('typedArrays', () => {
describe.skip('typedArrays', () => {
describe('standard', () => {
itSerializesEqual('Uint8Array', {
in: () => new Uint8Array([100, 200]),
Expand Down Expand Up @@ -211,14 +211,14 @@ describe.skip('Buffers', () => {
itSerializes('not zeroed', {
in() {
const buf = new ArrayBuffer(8);
new Uint8Array(buf).set([0, 1, 2, 3, 4, 15, 16, 0]);
new Uint8Array(buf).set([0, 1, 2, 3, 0, 15, 16, 0]);
return buf;
},
out: 'new Uint8Array([0,1,2,3,4,15,16,0]).buffer',
out: 'new Uint8Array([,1,2,3,,15,16,,]).buffer',
validate(buf) {
expect(buf).toHavePrototype(ArrayBuffer.prototype);
expect(buf.byteLength).toBe(8);
expect([...new Uint8Array(buf)]).toEqual([0, 1, 2, 3, 4, 15, 16, 0]);
expect([...new Uint8Array(buf)]).toEqual([0, 1, 2, 3, 0, 15, 16, 0]);
}
});

Expand Down Expand Up @@ -255,7 +255,7 @@ describe.skip('Buffers', () => {
});
});

describe('sharedArrayBuffers', () => {
describe.skip('sharedArrayBuffers', () => {
itSerializes('entirely zeroed', {
in: () => new SharedArrayBuffer(8),
out: 'new SharedArrayBuffer(8)',
Expand Down

0 comments on commit ee4c77f

Please sign in to comment.