add proper support for typed arrays in remote (#13055)
This commit is contained in:
Родитель
a798a40026
Коммит
4cfe5ecaa4
|
@ -59,6 +59,7 @@
|
|||
'lib/common/api/native-image.js',
|
||||
'lib/common/api/shell.js',
|
||||
'lib/common/atom-binding-setup.js',
|
||||
'lib/common/buffer-utils.js',
|
||||
'lib/common/init.js',
|
||||
'lib/common/parse-features-string.js',
|
||||
'lib/common/reset-search-paths.js',
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
'use strict'
|
||||
|
||||
const {Buffer} = require('buffer')
|
||||
const electron = require('electron')
|
||||
const {EventEmitter} = require('events')
|
||||
const fs = require('fs')
|
||||
|
@ -9,6 +8,7 @@ const v8Util = process.atomBinding('v8_util')
|
|||
const {ipcMain, isPromise, webContents} = electron
|
||||
|
||||
const objectsRegistry = require('./objects-registry')
|
||||
const bufferUtils = require('../common/buffer-utils')
|
||||
|
||||
const hasProp = {}.hasOwnProperty
|
||||
|
||||
|
@ -63,7 +63,7 @@ let valueToMeta = function (sender, value, optimizeSimpleObject = false) {
|
|||
// Recognize certain types of objects.
|
||||
if (value === null) {
|
||||
meta.type = 'value'
|
||||
} else if (ArrayBuffer.isView(value)) {
|
||||
} else if (bufferUtils.isBuffer(value)) {
|
||||
meta.type = 'buffer'
|
||||
} else if (Array.isArray(value)) {
|
||||
meta.type = 'array'
|
||||
|
@ -95,7 +95,7 @@ let valueToMeta = function (sender, value, optimizeSimpleObject = false) {
|
|||
meta.members = getObjectMembers(value)
|
||||
meta.proto = getObjectPrototype(value)
|
||||
} else if (meta.type === 'buffer') {
|
||||
meta.value = Buffer.from(value)
|
||||
meta.value = bufferUtils.bufferToMeta(value)
|
||||
} else if (meta.type === 'promise') {
|
||||
// Add default handler to prevent unhandled rejections in main process
|
||||
// Instead they should appear in the renderer process
|
||||
|
@ -180,7 +180,7 @@ const unwrapArgs = function (sender, args) {
|
|||
case 'array':
|
||||
return unwrapArgs(sender, meta.value)
|
||||
case 'buffer':
|
||||
return Buffer.from(meta.value)
|
||||
return bufferUtils.metaToBuffer(meta.value)
|
||||
case 'date':
|
||||
return new Date(meta.value)
|
||||
case 'promise':
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
// Note: Don't use destructuring assignment for `Buffer`, or we'll hit a
|
||||
// browserify bug that makes the statement invalid, throwing an error in
|
||||
// sandboxed renderer.
|
||||
const Buffer = require('buffer').Buffer
|
||||
|
||||
const typedArrays = {
|
||||
Buffer,
|
||||
ArrayBuffer,
|
||||
Int8Array,
|
||||
Uint8Array,
|
||||
Uint8ClampedArray,
|
||||
Int16Array,
|
||||
Uint16Array,
|
||||
Int32Array,
|
||||
Uint32Array,
|
||||
Float32Array,
|
||||
Float64Array
|
||||
}
|
||||
|
||||
function getType (value) {
|
||||
for (const type of Object.keys(typedArrays)) {
|
||||
if (value instanceof typedArrays[type]) {
|
||||
return type
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
exports.isBuffer = function (value) {
|
||||
return ArrayBuffer.isView(value) || value instanceof ArrayBuffer
|
||||
}
|
||||
|
||||
exports.bufferToMeta = function (value) {
|
||||
const buffer = (value instanceof ArrayBuffer)
|
||||
? Buffer.from(value)
|
||||
: Buffer.from(value.buffer, value.byteOffset, value.byteLength)
|
||||
|
||||
return {
|
||||
type: getType(value),
|
||||
data: buffer.toString('base64'),
|
||||
length: value.length
|
||||
}
|
||||
}
|
||||
|
||||
exports.metaToBuffer = function (value) {
|
||||
const constructor = typedArrays[value.type]
|
||||
const data = Buffer.from(value.data, 'base64')
|
||||
|
||||
if (constructor === Buffer) {
|
||||
return data
|
||||
} else if (constructor === ArrayBuffer) {
|
||||
return data.buffer
|
||||
} else if (constructor) {
|
||||
return new constructor(data.buffer, data.byteOffset, value.length)
|
||||
} else {
|
||||
return data
|
||||
}
|
||||
}
|
|
@ -1,13 +1,11 @@
|
|||
'use strict'
|
||||
|
||||
// Note: Don't use destructuring assignment for `Buffer`, or we'll hit a
|
||||
// browserify bug that makes the statement invalid, throwing an error in
|
||||
// sandboxed renderer.
|
||||
const Buffer = require('buffer').Buffer
|
||||
const v8Util = process.atomBinding('v8_util')
|
||||
const {ipcRenderer, isPromise, CallbacksRegistry} = require('electron')
|
||||
const resolvePromise = Promise.resolve.bind(Promise)
|
||||
|
||||
const bufferUtils = require('../../common/buffer-utils')
|
||||
|
||||
const callbacksRegistry = new CallbacksRegistry()
|
||||
const remoteObjectCache = v8Util.createIDWeakMap()
|
||||
|
||||
|
@ -30,10 +28,10 @@ function wrapArgs (args, visited = new Set()) {
|
|||
}
|
||||
visited.delete(value)
|
||||
return meta
|
||||
} else if (ArrayBuffer.isView(value)) {
|
||||
} else if (bufferUtils.isBuffer(value)) {
|
||||
return {
|
||||
type: 'buffer',
|
||||
value: Buffer.from(value)
|
||||
value: bufferUtils.bufferToMeta(value)
|
||||
}
|
||||
} else if (value instanceof Date) {
|
||||
return {
|
||||
|
@ -202,7 +200,7 @@ function metaToValue (meta) {
|
|||
const types = {
|
||||
value: () => meta.value,
|
||||
array: () => meta.members.map((member) => metaToValue(member)),
|
||||
buffer: () => Buffer.from(meta.value),
|
||||
buffer: () => bufferUtils.metaToBuffer(meta.value),
|
||||
promise: () => resolvePromise({then: metaToValue(meta.then)}),
|
||||
error: () => metaToPlainObject(meta),
|
||||
date: () => new Date(meta.value),
|
||||
|
|
|
@ -259,12 +259,94 @@ describe('remote module', () => {
|
|||
assert.ok(arrayWithBuffer[2].equals(printName.echo(arrayWithBuffer)[2]))
|
||||
})
|
||||
|
||||
it('supports TypedArray', () => {
|
||||
const values = [1, 2, 3, 4]
|
||||
assert.deepEqual(printName.typedArray(values), values)
|
||||
it('supports instanceof ArrayBuffer', () => {
|
||||
const buffer = new ArrayBuffer(8)
|
||||
const view = new DataView(buffer)
|
||||
|
||||
const int16values = new Int16Array([1, 2, 3, 4])
|
||||
assert.deepEqual(printName.typedArray(int16values), int16values)
|
||||
view.setFloat64(0, Math.PI)
|
||||
assert.deepEqual(printName.echo(buffer), buffer)
|
||||
assert.equal(printName.print(buffer), 'ArrayBuffer')
|
||||
})
|
||||
|
||||
it('supports instanceof Int8Array', () => {
|
||||
const values = [1, 2, 3, 4]
|
||||
assert.deepEqual(printName.typedArray('Int8Array', values), values)
|
||||
|
||||
const int8values = new Int8Array(values)
|
||||
assert.deepEqual(printName.typedArray('Int8Array', int8values), int8values)
|
||||
assert.equal(printName.print(int8values), 'Int8Array')
|
||||
})
|
||||
|
||||
it('supports instanceof Uint8Array', () => {
|
||||
const values = [1, 2, 3, 4]
|
||||
assert.deepEqual(printName.typedArray('Uint8Array', values), values)
|
||||
|
||||
const uint8values = new Uint8Array(values)
|
||||
assert.deepEqual(printName.typedArray('Uint8Array', uint8values), uint8values)
|
||||
assert.equal(printName.print(uint8values), 'Uint8Array')
|
||||
})
|
||||
|
||||
it('supports instanceof Uint8ClampedArray', () => {
|
||||
const values = [1, 2, 3, 4]
|
||||
assert.deepEqual(printName.typedArray('Uint8ClampedArray', values), values)
|
||||
|
||||
const uint8values = new Uint8ClampedArray(values)
|
||||
assert.deepEqual(printName.typedArray('Uint8ClampedArray', uint8values), uint8values)
|
||||
assert.equal(printName.print(uint8values), 'Uint8ClampedArray')
|
||||
})
|
||||
|
||||
it('supports instanceof Int16Array', () => {
|
||||
const values = [0x1234, 0x2345, 0x3456, 0x4567]
|
||||
assert.deepEqual(printName.typedArray('Int16Array', values), values)
|
||||
|
||||
const int16values = new Int16Array(values)
|
||||
assert.deepEqual(printName.typedArray('Int16Array', int16values), int16values)
|
||||
assert.equal(printName.print(int16values), 'Int16Array')
|
||||
})
|
||||
|
||||
it('supports instanceof Uint16Array', () => {
|
||||
const values = [0x1234, 0x2345, 0x3456, 0x4567]
|
||||
assert.deepEqual(printName.typedArray('Uint16Array', values), values)
|
||||
|
||||
const uint16values = new Uint16Array(values)
|
||||
assert.deepEqual(printName.typedArray('Uint16Array', uint16values), uint16values)
|
||||
assert.equal(printName.print(uint16values), 'Uint16Array')
|
||||
})
|
||||
|
||||
it('supports instanceof Int32Array', () => {
|
||||
const values = [0x12345678, 0x23456789]
|
||||
assert.deepEqual(printName.typedArray('Int32Array', values), values)
|
||||
|
||||
const int32values = new Int32Array(values)
|
||||
assert.deepEqual(printName.typedArray('Int32Array', int32values), int32values)
|
||||
assert.equal(printName.print(int32values), 'Int32Array')
|
||||
})
|
||||
|
||||
it('supports instanceof Uint32Array', () => {
|
||||
const values = [0x12345678, 0x23456789]
|
||||
assert.deepEqual(printName.typedArray('Uint32Array', values), values)
|
||||
|
||||
const uint32values = new Uint32Array(values)
|
||||
assert.deepEqual(printName.typedArray('Uint32Array', uint32values), uint32values)
|
||||
assert.equal(printName.print(uint32values), 'Uint32Array')
|
||||
})
|
||||
|
||||
it('supports instanceof Float32Array', () => {
|
||||
const values = [0.5, 1.0, 1.5]
|
||||
assert.deepEqual(printName.typedArray('Float32Array', values), values)
|
||||
|
||||
const float32values = new Float32Array()
|
||||
assert.deepEqual(printName.typedArray('Float32Array', float32values), float32values)
|
||||
assert.equal(printName.print(float32values), 'Float32Array')
|
||||
})
|
||||
|
||||
it('supports instanceof Float64Array', () => {
|
||||
const values = [0.5, 1.0, 1.5]
|
||||
assert.deepEqual(printName.typedArray('Float64Array', values), values)
|
||||
|
||||
const float64values = new Float64Array([0.5, 1.0, 1.5])
|
||||
assert.deepEqual(printName.typedArray('Float64Array', float64values), float64values)
|
||||
assert.equal(printName.print(float64values), 'Float64Array')
|
||||
})
|
||||
})
|
||||
|
||||
|
|
|
@ -6,10 +6,23 @@ exports.echo = function (obj) {
|
|||
return obj
|
||||
}
|
||||
|
||||
exports.typedArray = function (name) {
|
||||
const int16 = new Int16Array(name.length)
|
||||
for (let i = 0; i < name.length; ++i) {
|
||||
int16[i] = name[i]
|
||||
}
|
||||
return int16
|
||||
const typedArrays = {
|
||||
Int8Array,
|
||||
Uint8Array,
|
||||
Uint8ClampedArray,
|
||||
Int16Array,
|
||||
Uint16Array,
|
||||
Int32Array,
|
||||
Uint32Array,
|
||||
Float32Array,
|
||||
Float64Array
|
||||
}
|
||||
|
||||
exports.typedArray = function (type, values) {
|
||||
const constructor = typedArrays[type]
|
||||
const array = new constructor(values.length)
|
||||
for (let i = 0; i < values.length; ++i) {
|
||||
array[i] = values[i]
|
||||
}
|
||||
return array
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче