Skip to content

Commit 7f7d01a

Browse files
committed
wasm interop
1 parent ac031d6 commit 7f7d01a

File tree

5 files changed

+124
-105
lines changed

5 files changed

+124
-105
lines changed

src/adapters/webassembly/index.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,15 @@ export const adapterTypes = {
2424

2525
export const wasmAdapters = {
2626
/**
27-
* @param {WebAssembly.Instance} wasm
27+
* @param {WebAssembly.Exports} wasm
2828
*/
2929
model: wasm => wrapWasmModelSpec(wasm),
3030
/**
31-
* @param {WebAssembly.Instance} wasm
31+
* @param {WebAssembly.Exports} wasm
3232
*/
3333
adapter: wasm => wrapWasmAdapter(wasm),
3434
/**
35-
* @param {WebAssembly.Instance} wasm
35+
* @param {WebAssembly.Exports} wasm
3636
*/
3737
service: wasm => wrapWasmService(wasm)
3838
}

src/adapters/webassembly/wasm-import.js

Lines changed: 15 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,14 @@ exports.importWebAssembly = function (remoteEntry) {
3131

3232
const adaptedExports = Object.setPrototypeOf(
3333
{
34+
lowerString: __lowerString,
35+
liftString: __liftString,
36+
lowerArray: __lowerArray,
37+
liftArray: __liftArray,
38+
notnull: __notnull,
39+
store_ref: __store_ref,
40+
memory,
41+
3442
getModelName () {
3543
// assembly/index/getModelName() => ~lib/string/String
3644
return __liftString(exports.getModelName() >>> 0)
@@ -46,6 +54,10 @@ exports.importWebAssembly = function (remoteEntry) {
4654
return __liftString(exports.getDomain() >>> 0)
4755
},
4856

57+
callExportedFn (fn, kv) {
58+
return exports[fn](kv)
59+
},
60+
4961
ArrayOfStrings_ID: {
5062
// assembly/index/ArrayOfStrings_ID: u32
5163
valueOf () {
@@ -166,30 +178,9 @@ exports.importWebAssembly = function (remoteEntry) {
166178
.reduce((a, b) => ({ ...a, ...b }))
167179
},
168180

169-
/**
170-
* Parse the input object into a multidimensional array of key-value pairs
171-
* and pass it as an argument to the exported wasm function. Do the reverse for
172-
* the response. Consequently, any wasm port or command function must accept a
173-
* multidemensional array of strings (numbers are converted to strings) and return
174-
* a multidimensional array of strings.
175-
*
176-
* Before they can be called, they must be registered in the wasm modelspec,
177-
* that is getPorts() and getCommands() must return appropria metadata.
178-
*
179-
* Notes:
180-
*
181-
* - for the moment, we only support strings and numbers in the input
182-
* and output objects.
183-
*
184-
* - {@link args} can also be a number, in which case, so is the return value.
185-
*
186-
* @param {string} fn exported wasm function name
187-
* @param {object|number} [args] object or number, see above
188-
* @returns {object|number} object or number, see above
189-
*/
190-
__callWasmFunction (fn, obj) {
191-
const entries = Object.entries(obj)
192-
const kv =
181+
onUpdate (kv) {
182+
// assembly/index/onUpdate(~lib/array/Array<~lib/array/Array<~lib/string/String>>) => ~lib/array/Array<~lib/array/Array<~lib/string/String>>
183+
kv =
193184
__lowerArray(
194185
(pointer, value) => {
195186
__store_ref(
@@ -209,43 +200,6 @@ exports.importWebAssembly = function (remoteEntry) {
209200
},
210201
5,
211202
2,
212-
entries
213-
) || __notnull()
214-
215-
return __liftArray(
216-
pointer =>
217-
__liftArray(
218-
pointer =>
219-
__liftString(new Uint32Array(memory.buffer)[pointer >>> 2]),
220-
2,
221-
new Uint32Array(memory.buffer)[pointer >>> 2]
222-
),
223-
2,
224-
exports[fn](kv) >>> 0
225-
)
226-
.map(([k, v]) => ({ [k]: v }))
227-
.reduce((a, b) => ({ ...a, ...b }))
228-
},
229-
230-
onUpdate (kv) {
231-
// assembly/index/onUpdate(~lib/array/Array<~lib/array/Array<~lib/string/String>>) => ~lib/array/Array<~lib/array/Array<~lib/string/String>>
232-
kv =
233-
__lowerArray(
234-
(pointer, value) => {
235-
__store_ref(
236-
pointer,
237-
__lowerArray(
238-
(pointer, value) => {
239-
__store_ref(pointer, __lowerString(value) || __notnull())
240-
},
241-
4,
242-
2,
243-
value
244-
) || __notnull()
245-
)
246-
},
247-
5,
248-
2,
249203
kv
250204
) || __notnull()
251205

src/adapters/webassembly/wasm-interop.js

Lines changed: 103 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
'use strict'
22

3-
const { DefaultDeserializer } = require('v8')
4-
5-
/**@typedef {import("../../domain").ModelSpecification} ModelSpecification */
6-
/**@typedef {import("../../domain").Model} Model */
7-
/**@typedef {{[x:string]:()=>void}} Service */
8-
/**@typedef {function(Service):function(*):Promise} Adapter*/
3+
/** @typedef {import("../../domain").ModelSpecification} ModelSpecification */
4+
/** @typedef {import("../../domain").Model} Model */
5+
/** @typedef {{[x:string]:()=>void}} Service */
6+
/** @typedef {function(Service):function(*):Promise} Adapter */
97

108
/**
119
* WASM interop functions
@@ -21,39 +19,79 @@ exports.WasmInterop = function (wasmExports) {
2119
const {
2220
getCommands,
2321
getPorts,
24-
__callWasmFunction,
25-
ArrayOfStrings_ID,
26-
__pin,
27-
__unpin,
2822
liftString,
29-
liftArray
23+
liftArray,
24+
lowerString,
25+
lowerArray,
26+
store_ref,
27+
notnull,
28+
memory,
29+
callExportedFn
3030
} = wasmExports
3131

32-
/**
33-
* Construct an object from the key-value pairs in the multidimensional array
34-
* @param {number} ptr - pointer to the address of the array of string arrays
35-
* @returns {Readonly<{object}>}
36-
*/
37-
function constructObject (ptr, unpin = true) {
38-
if (!ptr) {
39-
console.debug(constructObject.name, 'null pointer', ptr)
40-
return
41-
}
32+
function lift (fn, kv) {
33+
return liftArray(
34+
pointer =>
35+
liftArray(
36+
pointer => liftString(new Uint32Array(memory.buffer)[pointer >>> 2]),
37+
2,
38+
new Uint32Array(memory.buffer)[pointer >>> 2]
39+
),
40+
2,
41+
callExportedFn(fn, kv) >>> 0
42+
)
43+
.map(([k, v]) => ({ [k]: v }))
44+
.reduce((a, b) => ({ ...a, ...b }))
45+
}
4246

43-
try {
44-
const obj = liftArray(ptr)
45-
.map(inner => liftArray(inner))
46-
.map(tuple => ({ [liftString(tuple[0])]: liftString(tuple[1]) }))
47-
.reduce((obj1, obj2) => ({ ...obj1, ...obj2 }))
47+
function lower (entries) {
48+
return (
49+
lowerArray(
50+
(pointer, value) => {
51+
store_ref(
52+
pointer,
53+
lowerArray(
54+
(pointer, value) => {
55+
store_ref(pointer, lowerString(value.toString()) || notnull())
56+
},
57+
4,
58+
2,
59+
value
60+
) || notnull()
61+
)
62+
},
63+
5,
64+
2,
65+
entries
66+
) || notnull()
67+
)
68+
}
4869

49-
const immutableClone = Object.freeze({ ...obj })
50-
!unpin || __unpin(ptr)
51-
console.debug(constructObject.name, ptr)
52-
return immutableClone
53-
} catch (e) {
54-
console.error(constructObject.name, 'error:', e.message)
55-
return {}
56-
}
70+
/**
71+
* Parse the input object into a multidimensional array of key-value pairs
72+
* and pass it as an argument to the exported wasm function. Do the reverse for
73+
* the response. Consequently, any wasm port or command function must accept a
74+
* multidemensional array of strings (numbers are converted to strings) and return
75+
* a multidimensional array of strings.
76+
*
77+
* Before they can be called, they must be registered in the wasm modelspec,
78+
* that is getPorts() and getCommands() must return appropria metadata.
79+
*
80+
* Notes:
81+
*
82+
* - for the moment, we only support strings and numbers in the input
83+
* and output objects.
84+
*
85+
* - {@link args} can also be a number, in which case, so is the return value.
86+
*
87+
* @param {string} fn exported wasm function name
88+
* @param {object|number} [obj] object or number, see above
89+
* @returns {object|number} object or number, see above
90+
*/
91+
function callWasmFunction (fn, obj) {
92+
const entries = Object.entries(obj)
93+
const kv = lower(entries)
94+
return lift(fn, kv)
5795
}
5896

5997
return Object.freeze({
@@ -64,7 +102,7 @@ exports.WasmInterop = function (wasmExports) {
64102
return {
65103
[command]: {
66104
command: model =>
67-
__callWasmFunction(command, {
105+
callWasmFunction(command, {
68106
...model,
69107
modelId: model.getId(),
70108
modelName: model.getName()
@@ -101,16 +139,44 @@ exports.WasmInterop = function (wasmExports) {
101139
type,
102140
consumesEvent,
103141
producesEvent,
104-
callback: data => __callWasmFunction(callback, data),
105-
undo: data => __callWasmFunction(undo, data),
142+
callback: data => callWasmFunction(callback, data),
143+
undo: data => callWasmFunction(undo, data),
106144
forward
107145
}
108146
}
109147
})
110148
.reduce((p, c) => ({ ...p, ...c }))
111149
},
150+
112151
constructObject (ptr) {
113152
return constructObject(ptr, false)
114153
}
115154
})
116155
}
156+
157+
/**
158+
* Construct an object from the key-value pairs in the multidimensional array
159+
* @param {number} ptr - pointer to the address of the array of string arrays
160+
* @returns {Readonly<{object}>}
161+
*/
162+
// function constructObject (ptr, unpin = true) {
163+
// if (!ptr) {
164+
// console.debug(constructObject.name, 'null pointer', ptr)
165+
// return
166+
// }
167+
168+
// try {
169+
// const obj = liftArray(ptr)
170+
// .map(inner => liftArray(inner))
171+
// .map(tuple => ({ [liftString(tuple[0])]: liftString(tuple[1]) }))
172+
// .reduce((obj1, obj2) => ({ ...obj1, ...obj2 }))
173+
174+
// const immutableClone = Object.freeze({ ...obj })
175+
// !unpin || __unpin(ptr)
176+
// console.debug(constructObject.name, ptr)
177+
// return immutableClone
178+
// } catch (e) {
179+
// console.error(constructObject.name, 'error:', e.message)
180+
// return {}
181+
// }
182+
// }

src/domain/datasource.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ export default class DataSource {
134134
*/
135135
async list (options) {
136136
const count = options.filter.__count || options.query.__count
137-
if (count) return handleCount(count)
137+
if (count) return this.handleCount(count)
138138
}
139139

140140
/**
@@ -144,7 +144,7 @@ export default class DataSource {
144144
*/
145145
listSync (query) {
146146
const count = query.__count
147-
if (count) return handleCount(count)
147+
if (count) return this.handleCount(count)
148148

149149
const list = this.generateList()
150150
return query ? this.filterList(query, list) : list

src/domain/use-cases/create-model.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
'use strict'
22

3-
import { isMainThread } from 'worker_threads'
4-
53
/**
64
* @typedef {Object} injectedDependencies injected dependencies
75
* @property {String} modelName - name of the domain model
@@ -26,6 +24,7 @@ export default function makeCreateModel ({
2624
enforceIdempotency,
2725
broker,
2826
handlers = [],
27+
isMainThread,
2928
domainEvents,
3029
AppError
3130
} = {}) {

0 commit comments

Comments
 (0)