ya-struct 0.0.3 → 0.0.4
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.
- package/.eslintrc +7 -3
- package/.prettierrc +5 -0
- package/lib/builder.js +43 -107
- package/lib/index.js +55 -89
- package/lib/marshaller.js +80 -0
- package/lib/refbuf.js +1 -1
- package/lib/types/basic.js +200 -0
- package/lib/types/ctypes.js +160 -0
- package/package.json +4 -3
- package/test/abi.js +90 -79
- package/test/basic.js +37 -27
- package/test/ctypes.js +166 -0
- package/test/ref.js +12 -8
- package/.jsbeautifyrc +0 -24
package/.eslintrc
CHANGED
|
@@ -6,11 +6,13 @@
|
|
|
6
6
|
},
|
|
7
7
|
"env": {
|
|
8
8
|
"node": true,
|
|
9
|
-
"
|
|
9
|
+
"es2020": true
|
|
10
10
|
},
|
|
11
11
|
"rules": {
|
|
12
12
|
"global-require": "off",
|
|
13
|
-
"quote-props": "warn",
|
|
13
|
+
"quote-props": ["warn", "consistent-as-needed"],
|
|
14
|
+
"comma-dangle": ["error", {"arrays": "always-multiline", "objects": "always-multiline", "functions": "never"}],
|
|
15
|
+
"id-length": ["error", {"min": 3, "properties": "always", "exceptions": ["i", "os", "fs"]}],
|
|
14
16
|
"quotes": ["error", "double", { "allowTemplateLiterals": true }],
|
|
15
17
|
"no-plusplus": "error",
|
|
16
18
|
"no-nested-ternary": "error",
|
|
@@ -21,6 +23,8 @@
|
|
|
21
23
|
"no-delete-var": "error",
|
|
22
24
|
"no-param-reassign": "error",
|
|
23
25
|
"no-return-assign": "error",
|
|
26
|
+
"no-import-assign": "error",
|
|
27
|
+
"no-multi-assign": "error",
|
|
24
28
|
"keyword-spacing": "error",
|
|
25
29
|
"max-len": [ "warn", { "code": 140 } ],
|
|
26
30
|
"max-params": ["error", 4],
|
|
@@ -47,6 +51,7 @@
|
|
|
47
51
|
"no-new-object": "error",
|
|
48
52
|
"no-new-wrappers": "error",
|
|
49
53
|
"no-useless-concat": "error",
|
|
54
|
+
"no-unused-vars": ["error", {"ignoreRestSiblings": true}],
|
|
50
55
|
"array-bracket-newline": ["error", "consistent"],
|
|
51
56
|
"func-names": ["error", "never"],
|
|
52
57
|
"func-style": ["error", "expression", { "allowArrowFunctions": true }],
|
|
@@ -54,7 +59,6 @@
|
|
|
54
59
|
"arrow-parens": "error",
|
|
55
60
|
"no-confusing-arrow": "error",
|
|
56
61
|
"prefer-const": "error",
|
|
57
|
-
"prefer-destructuring": ["error", {"object": true, "array": false}],
|
|
58
62
|
"rest-spread-spacing": ["error", "never"],
|
|
59
63
|
"template-curly-spacing": ["error", "never"],
|
|
60
64
|
"prefer-rest-params": "error",
|
package/.prettierrc
ADDED
package/lib/builder.js
CHANGED
|
@@ -1,126 +1,62 @@
|
|
|
1
|
-
|
|
1
|
+
import ctypes from "./types/ctypes.js";
|
|
2
|
+
import basicTypes from "./types/basic.js";
|
|
3
|
+
import marshallerFactory from "./marshaller.js";
|
|
2
4
|
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
"
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
"UInt32BE": 4,
|
|
9
|
-
"BigUInt64LE": 8,
|
|
10
|
-
"BigUInt64BE": 8,
|
|
11
|
-
|
|
12
|
-
"Int8": 1,
|
|
13
|
-
"Int16LE": 2,
|
|
14
|
-
"Int16BE": 2,
|
|
15
|
-
"Int32LE": 4,
|
|
16
|
-
"Int32BE": 4,
|
|
17
|
-
"BigInt64LE": 8,
|
|
18
|
-
"BigInt64BE": 8
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
const dataModelMaps = {
|
|
22
|
-
"LP64": {
|
|
23
|
-
"Pointer": "UInt64"
|
|
24
|
-
}
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
const createAccessorFor = ({ type, offset }) => {
|
|
28
|
-
const readFrom = ({ buffer }) => {
|
|
29
|
-
return BigInt(buffer[`read${type}`](offset));
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
const writeTo = ({ buffer, value }) => {
|
|
33
|
-
if (type.indexOf("Big") >= 0) {
|
|
34
|
-
buffer[`write${type}`](value, offset);
|
|
35
|
-
} else {
|
|
36
|
-
buffer[`write${type}`](Number(value), offset);
|
|
37
|
-
}
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
return {
|
|
41
|
-
readFrom,
|
|
42
|
-
writeTo
|
|
43
|
-
};
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
const createFieldsViaBuilder = ({ builder, "abi": { endianness, dataModel, alignmentModel = {} } = {} }) => {
|
|
47
|
-
let fields = {};
|
|
5
|
+
const createFieldsViaBuilder = ({
|
|
6
|
+
builder,
|
|
7
|
+
abi: { endianness = "LE", dataModel = "LP64", compiler = "gcc" } = {},
|
|
8
|
+
}) => {
|
|
9
|
+
let fieldDefinitions = {};
|
|
48
10
|
|
|
49
11
|
let currentOffset = 0;
|
|
50
12
|
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
writeTo,
|
|
69
|
-
offset,
|
|
70
|
-
size
|
|
71
|
-
}
|
|
72
|
-
});
|
|
13
|
+
const fieldBuilderForAbi = ({ abi }) => {
|
|
14
|
+
let result = {};
|
|
15
|
+
Object.keys(abi).forEach((typeName) => {
|
|
16
|
+
result = {
|
|
17
|
+
...result,
|
|
18
|
+
[typeName]: (name) => {
|
|
19
|
+
const def = abi[typeName]({ offset: currentOffset });
|
|
20
|
+
|
|
21
|
+
fieldDefinitions = {
|
|
22
|
+
...fieldDefinitions,
|
|
23
|
+
[name]: def,
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
currentOffset = def.offset + def.size;
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
});
|
|
73
30
|
|
|
74
|
-
|
|
75
|
-
};
|
|
31
|
+
return result;
|
|
76
32
|
};
|
|
77
33
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
"UInt16LE": standardField("UInt16LE", alignmentModel.UInt16),
|
|
81
|
-
"UInt16BE": standardField("UInt16BE", alignmentModel.UInt16),
|
|
82
|
-
"UInt32LE": standardField("UInt32LE", alignmentModel.UInt32),
|
|
83
|
-
"UInt32BE": standardField("UInt32BE", alignmentModel.UInt32),
|
|
84
|
-
"UInt64LE": standardField("BigUInt64LE", alignmentModel.UInt64),
|
|
85
|
-
"UInt64BE": standardField("BigUInt64BE", alignmentModel.UInt64),
|
|
34
|
+
const basicTypesAbi = basicTypes.abi({ dataModel, compiler, endianness });
|
|
35
|
+
const cTypesAbi = ctypes.abi({ dataModel, compiler, endianness });
|
|
86
36
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
"Int32LE": standardField("Int32LE", alignmentModel.Int32),
|
|
91
|
-
"Int32BE": standardField("Int32BE", alignmentModel.Int32),
|
|
92
|
-
"Int64LE": standardField("BigInt64LE", alignmentModel.Int64),
|
|
93
|
-
"Int64BE": standardField("BigInt64BE", alignmentModel.Int64)
|
|
37
|
+
const field = {
|
|
38
|
+
...fieldBuilderForAbi({ abi: basicTypesAbi }),
|
|
39
|
+
CTypes: fieldBuilderForAbi({ abi: cTypesAbi }),
|
|
94
40
|
};
|
|
95
41
|
|
|
96
|
-
|
|
97
|
-
fieldObject = Object.assign({}, fieldObject, {
|
|
98
|
-
"Int16": standardField(`Int16${endianness}`, alignmentModel.Int16),
|
|
99
|
-
"Int32": standardField(`Int32${endianness}`, alignmentModel.Int32),
|
|
100
|
-
"Int64": standardField(`BigInt64${endianness}`, alignmentModel.Int64),
|
|
101
|
-
"UInt16": standardField(`UInt16${endianness}`, alignmentModel.UInt16),
|
|
102
|
-
"UInt32": standardField(`UInt32${endianness}`, alignmentModel.UInt32),
|
|
103
|
-
"UInt64": standardField(`BigUInt64${endianness}`, alignmentModel.UInt64),
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
const dataModelMap = dataModelMaps[dataModel] || {};
|
|
108
|
-
Object.keys(dataModelMap).forEach((key) => {
|
|
109
|
-
fieldObject = Object.assign({}, fieldObject, {
|
|
110
|
-
[key]: fieldObject[dataModelMap[key]]
|
|
111
|
-
});
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
builder({ "field": fieldObject });
|
|
42
|
+
builder({ field });
|
|
115
43
|
|
|
116
44
|
const size = currentOffset;
|
|
117
45
|
|
|
46
|
+
const { marshal, unmarshal } = marshallerFactory.create({
|
|
47
|
+
fieldDefinitions,
|
|
48
|
+
size,
|
|
49
|
+
});
|
|
50
|
+
|
|
118
51
|
return {
|
|
119
|
-
fields,
|
|
120
|
-
size
|
|
52
|
+
fields: fieldDefinitions,
|
|
53
|
+
size,
|
|
54
|
+
|
|
55
|
+
marshal,
|
|
56
|
+
unmarshal,
|
|
121
57
|
};
|
|
122
58
|
};
|
|
123
59
|
|
|
124
60
|
export default {
|
|
125
|
-
createFieldsViaBuilder
|
|
61
|
+
createFieldsViaBuilder,
|
|
126
62
|
};
|
package/lib/index.js
CHANGED
|
@@ -2,28 +2,10 @@ import b2a from "buffer2address";
|
|
|
2
2
|
import os from "os";
|
|
3
3
|
|
|
4
4
|
import fieldBuilder from "./builder.js";
|
|
5
|
-
import refbuf from "./refbuf.js";
|
|
6
5
|
|
|
7
6
|
const defineWithBuilderAndAbi = ({ builder, abi }) => {
|
|
8
|
-
const { fields, size
|
|
9
|
-
|
|
10
|
-
const offsetof = (fieldName) => {
|
|
11
|
-
const field = fields[fieldName];
|
|
12
|
-
if (!field) {
|
|
13
|
-
throw new Error(`field "${fieldName}" not found`);
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
return field.offset;
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
const sizeof = (fieldName) => {
|
|
20
|
-
const field = fields[fieldName];
|
|
21
|
-
if (!field) {
|
|
22
|
-
throw new Error(`field "${fieldName}" not found`);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
return field.size;
|
|
26
|
-
};
|
|
7
|
+
const { fields, size, marshal, unmarshal } =
|
|
8
|
+
fieldBuilder.createFieldsViaBuilder({ builder, abi });
|
|
27
9
|
|
|
28
10
|
const parse = (buf) => {
|
|
29
11
|
if (!Buffer.isBuffer(buf)) {
|
|
@@ -31,22 +13,22 @@ const defineWithBuilderAndAbi = ({ builder, abi }) => {
|
|
|
31
13
|
}
|
|
32
14
|
|
|
33
15
|
if (buf.length < size) {
|
|
34
|
-
throw new Error(
|
|
16
|
+
throw new Error(
|
|
17
|
+
`given buffer is too small for structure (has ${buf.length} bytes, needs ${size} bytes)`
|
|
18
|
+
);
|
|
35
19
|
}
|
|
36
20
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
Object.keys(fields).forEach((name) => {
|
|
40
|
-
const field = fields[name];
|
|
41
|
-
|
|
42
|
-
result = Object.assign({}, result, {
|
|
43
|
-
[name]: field.readFrom({ "buffer": buf })
|
|
44
|
-
});
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
return result;
|
|
21
|
+
return unmarshal({ buffer: buf });
|
|
48
22
|
};
|
|
49
23
|
|
|
24
|
+
let emptyData = {};
|
|
25
|
+
Object.keys(fields).forEach((fieldName) => {
|
|
26
|
+
emptyData = {
|
|
27
|
+
...emptyData,
|
|
28
|
+
[fieldName]: 0n,
|
|
29
|
+
};
|
|
30
|
+
});
|
|
31
|
+
|
|
50
32
|
const format = (data) => {
|
|
51
33
|
if (typeof data !== "object") {
|
|
52
34
|
throw new Error(`given argument is not a object`);
|
|
@@ -60,53 +42,61 @@ const defineWithBuilderAndAbi = ({ builder, abi }) => {
|
|
|
60
42
|
const value = data[fieldName];
|
|
61
43
|
if (Buffer.isBuffer(value)) {
|
|
62
44
|
buffers = Object.assign({}, buffers, {
|
|
63
|
-
[fieldName]: value
|
|
45
|
+
[fieldName]: value,
|
|
64
46
|
});
|
|
65
47
|
links = [...links, value];
|
|
66
48
|
} else if (typeof value === "bigint") {
|
|
67
49
|
primitives = Object.assign({}, primitives, {
|
|
68
|
-
[fieldName]: value
|
|
50
|
+
[fieldName]: value,
|
|
69
51
|
});
|
|
70
52
|
} else {
|
|
71
|
-
throw new Error(
|
|
53
|
+
throw new Error(
|
|
54
|
+
`only Buffer and BigInt supported, "${fieldName}" was of type "${typeof value}"`
|
|
55
|
+
);
|
|
72
56
|
}
|
|
73
57
|
});
|
|
74
58
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
Object.keys(primitives).forEach((fieldName) => {
|
|
78
|
-
const value = data[fieldName];
|
|
79
|
-
const field = fields[fieldName];
|
|
80
|
-
field.writeTo({ "buffer": result, value });
|
|
81
|
-
});
|
|
59
|
+
let bufferDataToMarshal = {};
|
|
82
60
|
|
|
83
61
|
Object.keys(buffers).forEach((fieldName) => {
|
|
84
62
|
const value = b2a.buffer2address(data[fieldName]);
|
|
85
|
-
|
|
86
|
-
|
|
63
|
+
|
|
64
|
+
bufferDataToMarshal = {
|
|
65
|
+
...bufferDataToMarshal,
|
|
66
|
+
[fieldName]: value,
|
|
67
|
+
};
|
|
87
68
|
});
|
|
88
69
|
|
|
89
|
-
return
|
|
70
|
+
return marshal({
|
|
71
|
+
data: {
|
|
72
|
+
...emptyData,
|
|
73
|
+
...primitives,
|
|
74
|
+
...bufferDataToMarshal,
|
|
75
|
+
},
|
|
76
|
+
links,
|
|
77
|
+
});
|
|
90
78
|
};
|
|
91
79
|
|
|
92
80
|
return {
|
|
93
|
-
|
|
94
|
-
sizeof,
|
|
81
|
+
fields,
|
|
95
82
|
size,
|
|
96
83
|
|
|
97
84
|
parse,
|
|
98
|
-
format
|
|
85
|
+
format,
|
|
99
86
|
};
|
|
100
87
|
};
|
|
101
88
|
|
|
102
89
|
const hostDataModels = {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
90
|
+
x64: {
|
|
91
|
+
win32: "LLP64",
|
|
92
|
+
linux: "LP64",
|
|
93
|
+
},
|
|
94
|
+
arm: {
|
|
95
|
+
linux: "ILP32",
|
|
96
|
+
},
|
|
97
|
+
arm64: {
|
|
98
|
+
linux: "LP64",
|
|
106
99
|
},
|
|
107
|
-
"arm64": {
|
|
108
|
-
"linux": "LP64"
|
|
109
|
-
}
|
|
110
100
|
};
|
|
111
101
|
|
|
112
102
|
const findDataModelFor = ({ arch, platform }) => {
|
|
@@ -125,69 +115,45 @@ const findDataModelFor = ({ arch, platform }) => {
|
|
|
125
115
|
|
|
126
116
|
const findHostDataModel = () => {
|
|
127
117
|
return findDataModelFor({
|
|
128
|
-
|
|
129
|
-
|
|
118
|
+
arch: process.arch,
|
|
119
|
+
platform: process.platform,
|
|
130
120
|
});
|
|
131
121
|
};
|
|
132
122
|
|
|
133
|
-
const alignmentModels = {
|
|
134
|
-
"LP64": {
|
|
135
|
-
"gcc": {
|
|
136
|
-
"Int8": 1,
|
|
137
|
-
"UInt8": 1,
|
|
138
|
-
"Int16": 2,
|
|
139
|
-
"UInt16": 2,
|
|
140
|
-
"Int32": 4,
|
|
141
|
-
"UInt32": 4,
|
|
142
|
-
"Int64": 8,
|
|
143
|
-
"UInt64": 8
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
};
|
|
147
|
-
|
|
148
123
|
const findLikelyHostCompiler = () => {
|
|
149
124
|
return "gcc";
|
|
150
125
|
};
|
|
151
126
|
|
|
152
|
-
const findHostAlignmentModel = () => {
|
|
153
|
-
const dataModel = findHostDataModel();
|
|
154
|
-
|
|
155
|
-
const compiler = findLikelyHostCompiler();
|
|
156
|
-
|
|
157
|
-
return alignmentModels[dataModel] && alignmentModels[dataModel][compiler];
|
|
158
|
-
};
|
|
159
|
-
|
|
160
127
|
const define = (builder) => {
|
|
161
|
-
const abi = ({ endianness, dataModel,
|
|
128
|
+
const abi = ({ endianness, dataModel, compiler }) => {
|
|
162
129
|
return defineWithBuilderAndAbi({
|
|
163
130
|
builder,
|
|
164
|
-
|
|
131
|
+
abi: {
|
|
165
132
|
endianness,
|
|
166
133
|
dataModel,
|
|
167
|
-
|
|
168
|
-
}
|
|
134
|
+
compiler,
|
|
135
|
+
},
|
|
169
136
|
});
|
|
170
137
|
};
|
|
171
138
|
|
|
172
139
|
const forHost = () => {
|
|
173
140
|
const endianness = os.endianness();
|
|
174
141
|
const dataModel = findHostDataModel();
|
|
175
|
-
const
|
|
176
|
-
|
|
142
|
+
const compiler = findLikelyHostCompiler();
|
|
143
|
+
|
|
177
144
|
return abi({
|
|
178
145
|
endianness,
|
|
179
146
|
dataModel,
|
|
180
|
-
|
|
147
|
+
compiler,
|
|
181
148
|
});
|
|
182
149
|
};
|
|
183
|
-
|
|
150
|
+
|
|
184
151
|
return {
|
|
185
152
|
abi,
|
|
186
|
-
forHost
|
|
153
|
+
forHost,
|
|
187
154
|
};
|
|
188
155
|
};
|
|
189
156
|
|
|
190
157
|
export default {
|
|
191
158
|
define,
|
|
192
|
-
alignmentModels
|
|
193
159
|
};
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import refbuf from "./refbuf.js";
|
|
2
|
+
|
|
3
|
+
const createInterpretingMarshaller = ({ fieldDefinitions, size }) => {
|
|
4
|
+
const findReadWriteMethodName = ({ signed, fieldSizeInBits, endianness }) => {
|
|
5
|
+
const bigOrNot = fieldSizeInBits === 64 ? "Big" : "";
|
|
6
|
+
const signedOrNot = signed ? "" : "U";
|
|
7
|
+
const intType = `Int${fieldSizeInBits}`;
|
|
8
|
+
|
|
9
|
+
return `${bigOrNot}${signedOrNot}${intType}${endianness || ""}`;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const marshal = ({ data, links }) => {
|
|
13
|
+
const result = refbuf.create({ links, size });
|
|
14
|
+
|
|
15
|
+
Object.keys(fieldDefinitions).forEach((fieldName) => {
|
|
16
|
+
const {
|
|
17
|
+
signed,
|
|
18
|
+
offset,
|
|
19
|
+
size: fieldSize,
|
|
20
|
+
endianness,
|
|
21
|
+
} = fieldDefinitions[fieldName];
|
|
22
|
+
|
|
23
|
+
const fieldSizeInBits = fieldSize * 8;
|
|
24
|
+
const writeFuncName = `write${findReadWriteMethodName({
|
|
25
|
+
signed,
|
|
26
|
+
fieldSizeInBits,
|
|
27
|
+
endianness,
|
|
28
|
+
})}`;
|
|
29
|
+
const valueToWrite = writeFuncName.includes("Big")
|
|
30
|
+
? BigInt(data[fieldName])
|
|
31
|
+
: Number(data[fieldName]);
|
|
32
|
+
|
|
33
|
+
result[writeFuncName](valueToWrite, offset);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
return result;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const unmarshal = ({ buffer }) => {
|
|
40
|
+
let result = {};
|
|
41
|
+
|
|
42
|
+
Object.keys(fieldDefinitions).forEach((fieldName) => {
|
|
43
|
+
const {
|
|
44
|
+
signed,
|
|
45
|
+
offset,
|
|
46
|
+
size: fieldSize,
|
|
47
|
+
endianness,
|
|
48
|
+
} = fieldDefinitions[fieldName];
|
|
49
|
+
|
|
50
|
+
const fieldSizeInBits = fieldSize * 8;
|
|
51
|
+
const readFuncName = `read${findReadWriteMethodName({
|
|
52
|
+
signed,
|
|
53
|
+
fieldSizeInBits,
|
|
54
|
+
endianness,
|
|
55
|
+
})}`;
|
|
56
|
+
|
|
57
|
+
const val = buffer[readFuncName](offset);
|
|
58
|
+
|
|
59
|
+
result = {
|
|
60
|
+
...result,
|
|
61
|
+
[fieldName]: BigInt(val),
|
|
62
|
+
};
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
return result;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
return {
|
|
69
|
+
marshal,
|
|
70
|
+
unmarshal,
|
|
71
|
+
};
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
const create = ({ fieldDefinitions, size }) => {
|
|
75
|
+
return createInterpretingMarshaller({ fieldDefinitions, size });
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
export default {
|
|
79
|
+
create,
|
|
80
|
+
};
|
package/lib/refbuf.js
CHANGED