@keymanapp/kmc-kmn 17.0.155-alpha → 17.0.157-alpha

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.
Files changed (54) hide show
  1. package/build/src/compiler/compiler.d.ts +98 -50
  2. package/build/src/compiler/compiler.d.ts.map +1 -1
  3. package/build/src/compiler/compiler.js +405 -268
  4. package/build/src/compiler/compiler.js.map +1 -1
  5. package/build/src/compiler/messages.d.ts +230 -218
  6. package/build/src/compiler/messages.d.ts.map +1 -1
  7. package/build/src/compiler/messages.js +242 -234
  8. package/build/src/compiler/messages.js.map +1 -1
  9. package/build/src/import/kmcmplib/wasm-host.d.ts +5 -3
  10. package/build/src/import/kmcmplib/wasm-host.d.ts.map +1 -1
  11. package/build/src/import/kmcmplib/wasm-host.js +3264 -1145
  12. package/build/src/import/kmcmplib/wasm-host.js.map +1 -1
  13. package/build/src/import/kmcmplib/wasm-host.wasm +0 -0
  14. package/build/src/kmw-compiler/compiler-globals.d.ts +21 -0
  15. package/build/src/kmw-compiler/compiler-globals.d.ts.map +1 -0
  16. package/build/src/kmw-compiler/compiler-globals.js +37 -0
  17. package/build/src/kmw-compiler/compiler-globals.js.map +1 -0
  18. package/build/src/kmw-compiler/constants.d.ts +16 -0
  19. package/build/src/kmw-compiler/constants.d.ts.map +1 -0
  20. package/build/src/kmw-compiler/constants.js +62 -0
  21. package/build/src/kmw-compiler/constants.js.map +1 -0
  22. package/build/src/kmw-compiler/javascript-strings.d.ts +35 -0
  23. package/build/src/kmw-compiler/javascript-strings.d.ts.map +1 -0
  24. package/build/src/kmw-compiler/javascript-strings.js +854 -0
  25. package/build/src/kmw-compiler/javascript-strings.js.map +1 -0
  26. package/build/src/kmw-compiler/keymanweb-key-codes.d.ts +25 -0
  27. package/build/src/kmw-compiler/keymanweb-key-codes.d.ts.map +1 -0
  28. package/build/src/kmw-compiler/keymanweb-key-codes.js +806 -0
  29. package/build/src/kmw-compiler/keymanweb-key-codes.js.map +1 -0
  30. package/build/src/kmw-compiler/kmw-compiler.d.ts +16 -0
  31. package/build/src/kmw-compiler/kmw-compiler.d.ts.map +1 -0
  32. package/build/src/kmw-compiler/kmw-compiler.js +535 -0
  33. package/build/src/kmw-compiler/kmw-compiler.js.map +1 -0
  34. package/build/src/kmw-compiler/messages.d.ts +85 -0
  35. package/build/src/kmw-compiler/messages.d.ts.map +1 -0
  36. package/build/src/kmw-compiler/messages.js +48 -0
  37. package/build/src/kmw-compiler/messages.js.map +1 -0
  38. package/build/src/kmw-compiler/util.d.ts +77 -0
  39. package/build/src/kmw-compiler/util.d.ts.map +1 -0
  40. package/build/src/kmw-compiler/util.js +249 -0
  41. package/build/src/kmw-compiler/util.js.map +1 -0
  42. package/build/src/kmw-compiler/validate-layout-file.d.ts +10 -0
  43. package/build/src/kmw-compiler/validate-layout-file.d.ts.map +1 -0
  44. package/build/src/kmw-compiler/validate-layout-file.js +246 -0
  45. package/build/src/kmw-compiler/validate-layout-file.js.map +1 -0
  46. package/build/src/kmw-compiler/visual-keyboard-compiler.d.ts +5 -0
  47. package/build/src/kmw-compiler/visual-keyboard-compiler.d.ts.map +1 -0
  48. package/build/src/kmw-compiler/visual-keyboard-compiler.js +121 -0
  49. package/build/src/kmw-compiler/visual-keyboard-compiler.js.map +1 -0
  50. package/build/src/main.d.ts +6 -3
  51. package/build/src/main.d.ts.map +1 -1
  52. package/build/src/main.js +6 -3
  53. package/build/src/main.js.map +1 -1
  54. package/package.json +7 -5
@@ -1,268 +1,405 @@
1
- /*
2
- TODO: implement additional interfaces:
3
-
4
- typedef bool (*kmcmp_ValidateJsonMessageProc)();
5
- extern "C" bool kmcmp_ValidateJsonFile();
6
- */
7
- // TODO: rename wasm-host?
8
- import { UnicodeSet } from '@keymanapp/common-types';
9
- import { KvkFileWriter, KvksFileReader } from '@keymanapp/common-types';
10
- import loadWasmHost from '../import/kmcmplib/wasm-host.js';
11
- import { CompilerMessages, mapErrorFromKmcmplib } from './messages.js';
12
- ;
13
- ;
14
- ;
15
- const baseOptions = {
16
- shouldAddCompilerVersion: true,
17
- saveDebug: true,
18
- compilerWarningsAsErrors: false,
19
- warnDeprecatedCode: true
20
- };
21
- /**
22
- * Allows multiple instances of the Compiler class, by ensuring that the
23
- * 'unique' kmnCompilerCallback global will be correlated with a specific
24
- * instance of the Compiler class
25
- */
26
- let callbackProcIdentifier = 0;
27
- const callbackPrefix = 'kmnCompilerCallbacks_';
28
- ;
29
- export class KmnCompiler {
30
- Module;
31
- callbackID; // a unique numeric id added to globals with prefixed names
32
- callbacks;
33
- wasmExports;
34
- constructor() {
35
- this.callbackID = callbackPrefix + callbackProcIdentifier.toString();
36
- callbackProcIdentifier++;
37
- }
38
- async init(callbacks) {
39
- this.callbacks = callbacks;
40
- if (!this.Module) {
41
- try {
42
- this.Module = await loadWasmHost();
43
- this.wasmExports = (this.Module.wasmExports ?? this.Module.asm);
44
- }
45
- catch (e) {
46
- /* c8 ignore next 3 */
47
- this.callbacks.reportMessage(CompilerMessages.Fatal_MissingWasmModule({ e }));
48
- return false;
49
- }
50
- }
51
- return this.verifyInitialized();
52
- }
53
- /**
54
- * Verify that wasm is spun up OK.
55
- * @returns true if OK
56
- */
57
- verifyInitialized() {
58
- if (!this.callbacks) {
59
- // Can't report a message here.
60
- throw Error('Must call Compiler.init(callbacks) before proceeding');
61
- }
62
- if (!this.Module) {
63
- /* c8 ignore next 4 */
64
- // fail if wasm not loaded or function not found
65
- this.callbacks.reportMessage(CompilerMessages.Fatal_MissingWasmModule({}));
66
- return false;
67
- }
68
- return true;
69
- }
70
- run(infile, outfile, options) {
71
- let result = this.runCompiler(infile, outfile, options);
72
- if (result) {
73
- if (result.kmx) {
74
- this.callbacks.fs.writeFileSync(result.kmx.filename, result.kmx.data);
75
- }
76
- if (result.kvk) {
77
- this.callbacks.fs.writeFileSync(result.kvk.filename, result.kvk.data);
78
- }
79
- if (result.js) {
80
- this.callbacks.fs.writeFileSync(result.js.filename, result.js.data);
81
- }
82
- }
83
- return !!result;
84
- }
85
- compilerMessageCallback = (line, code, msg) => {
86
- this.callbacks.reportMessage(mapErrorFromKmcmplib(line, code, msg));
87
- return 1;
88
- };
89
- cachedFile = {
90
- filename: null,
91
- data: null
92
- };
93
- loadFileCallback = (filename, baseFilename, buffer, bufferSize) => {
94
- let resolvedFilename = this.callbacks.resolveFilename(baseFilename, filename);
95
- let data;
96
- if (this.cachedFile.filename == resolvedFilename) {
97
- data = this.cachedFile.data;
98
- }
99
- else {
100
- data = this.callbacks.loadFile(resolvedFilename);
101
- if (!data) {
102
- return -1;
103
- }
104
- this.cachedFile.filename = resolvedFilename;
105
- this.cachedFile.data = data;
106
- }
107
- if (buffer == 0) {
108
- /* We need to return buffer size required */
109
- return data.byteLength;
110
- }
111
- if (bufferSize != data.byteLength) {
112
- /* c8 ignore next 2 */
113
- throw new Error(`loadFileCallback: second call, expected file size ${bufferSize} == ${data.byteLength}`);
114
- }
115
- this.Module.HEAP8.set(data, buffer);
116
- return 1;
117
- };
118
- runCompiler(infile, outfile, options) {
119
- if (!this.verifyInitialized()) {
120
- /* c8 ignore next 2 */
121
- return null;
122
- }
123
- options = { ...baseOptions, ...options };
124
- globalThis[this.callbackID] = {
125
- message: this.compilerMessageCallback,
126
- loadFile: this.loadFileCallback
127
- };
128
- let result = {};
129
- let wasm_interface = new this.Module.CompilerInterface();
130
- let wasm_options = new this.Module.CompilerOptions();
131
- let wasm_result = null;
132
- try {
133
- wasm_options.saveDebug = options.saveDebug;
134
- wasm_options.compilerWarningsAsErrors = options.compilerWarningsAsErrors;
135
- wasm_options.warnDeprecatedCode = options.warnDeprecatedCode;
136
- wasm_options.shouldAddCompilerVersion = options.shouldAddCompilerVersion;
137
- wasm_options.target = 0; //CKF_KEYMAN; TODO, support KMW
138
- wasm_interface.callbacksKey = this.callbackID; // key of object on globalThis
139
- wasm_result = this.Module.kmcmp_compile(infile, wasm_options, wasm_interface);
140
- if (!wasm_result.result) {
141
- return null;
142
- }
143
- if (wasm_result.kvksFilename) {
144
- result.kvk = this.runKvkCompiler(wasm_result.kvksFilename, infile, outfile);
145
- if (!result.kvk) {
146
- return null;
147
- }
148
- }
149
- result.kmx = {
150
- filename: outfile,
151
- data: new Uint8Array(this.Module.HEAP8.buffer, wasm_result.kmx, wasm_result.kmxSize)
152
- };
153
- return result;
154
- }
155
- catch (e) {
156
- /* c8 ignore next 3 */
157
- this.callbacks.reportMessage(CompilerMessages.Fatal_UnexpectedException({ e: e }));
158
- return null;
159
- }
160
- finally {
161
- if (wasm_result) {
162
- wasm_result.delete();
163
- }
164
- wasm_interface.delete();
165
- wasm_options.delete();
166
- delete globalThis[this.callbackID];
167
- }
168
- }
169
- runKvkCompiler(kvksFilename, kmnFilename, kmxFilename) {
170
- // The compiler detected a .kvks file, which needs to be captured
171
- let reader = new KvksFileReader();
172
- kvksFilename = this.callbacks.resolveFilename(kmnFilename, kvksFilename);
173
- let filename = this.callbacks.path.basename(kvksFilename);
174
- let kvks = null;
175
- try {
176
- kvks = reader.read(this.callbacks.loadFile(kvksFilename));
177
- reader.validate(kvks, this.callbacks.loadSchema('kvks'));
178
- }
179
- catch (e) {
180
- this.callbacks.reportMessage(CompilerMessages.Error_InvalidKvksFile({ filename, e }));
181
- return null;
182
- }
183
- let invalidVkeys = [];
184
- let vk = reader.transform(kvks, invalidVkeys);
185
- for (let invalidVkey of invalidVkeys) {
186
- this.callbacks.reportMessage(CompilerMessages.Warn_InvalidVkeyInKvksFile({ filename, invalidVkey }));
187
- }
188
- let writer = new KvkFileWriter();
189
- return {
190
- filename: this.callbacks.path.join(this.callbacks.path.dirname(kmxFilename), this.callbacks.path.basename(kvksFilename, '.kvks') + '.kvk'),
191
- data: writer.write(vk)
192
- };
193
- }
194
- /**
195
- *
196
- * @param pattern UnicodeSet pattern such as `[a-z]`
197
- * @param rangeCount number of ranges to allocate
198
- * @returns UnicodeSet accessor object, or null on failure
199
- */
200
- parseUnicodeSet(pattern, rangeCount) {
201
- if (!this.verifyInitialized()) {
202
- /* c8 ignore next 2 */
203
- return null;
204
- }
205
- // TODO-LDML: Catch OOM
206
- const buf = this.wasmExports.malloc(rangeCount * 2 * this.Module.HEAPU32.BYTES_PER_ELEMENT);
207
- /** If <= 0: return code. If positive: range count */
208
- const rc = this.Module.kmcmp_parseUnicodeSet(pattern, buf, rangeCount * 2);
209
- if (rc >= 0) {
210
- const ranges = [];
211
- const startu = (buf / this.Module.HEAPU32.BYTES_PER_ELEMENT);
212
- for (let i = 0; i < rc; i++) {
213
- const start = this.Module.HEAPU32[startu + (i * 2) + 0];
214
- const end = this.Module.HEAPU32[startu + (i * 2) + 1];
215
- ranges.push([start, end]);
216
- }
217
- this.wasmExports.free(buf);
218
- return new UnicodeSet(pattern, ranges);
219
- }
220
- else {
221
- this.wasmExports.free(buf);
222
- // translate error code into callback
223
- this.callbacks.reportMessage(getUnicodeSetError(rc));
224
- return null;
225
- }
226
- }
227
- sizeUnicodeSet(pattern) {
228
- if (!this.verifyInitialized()) {
229
- /* c8 ignore next 2 */
230
- return null;
231
- }
232
- // call with rangeCount = 0 to invoke in 'preflight' mode.
233
- const rc = this.Module.kmcmp_parseUnicodeSet(pattern, 0, 0);
234
- if (rc >= 0) {
235
- return rc;
236
- }
237
- else {
238
- this.callbacks.reportMessage(getUnicodeSetError(rc));
239
- return -1;
240
- }
241
- }
242
- }
243
- /**
244
- * translate UnicodeSet return code into a compiler event
245
- * @param rc parseUnicodeSet error code
246
- * @returns the compiler event
247
- */
248
- function getUnicodeSetError(rc) {
249
- // from kmcmplib.h
250
- const KMCMP_ERROR_SYNTAX_ERR = -1;
251
- const KMCMP_ERROR_HAS_STRINGS = -2;
252
- const KMCMP_ERROR_UNSUPPORTED_PROPERTY = -3;
253
- const KMCMP_FATAL_OUT_OF_RANGE = -4;
254
- switch (rc) {
255
- case KMCMP_ERROR_SYNTAX_ERR:
256
- return CompilerMessages.Error_UnicodeSetSyntaxError();
257
- case KMCMP_ERROR_HAS_STRINGS:
258
- return CompilerMessages.Error_UnicodeSetHasStrings();
259
- case KMCMP_ERROR_UNSUPPORTED_PROPERTY:
260
- return CompilerMessages.Error_UnicodeSetHasProperties();
261
- case KMCMP_FATAL_OUT_OF_RANGE:
262
- return CompilerMessages.Fatal_UnicodeSetOutOfRange();
263
- default:
264
- /* c8 ignore next */
265
- return CompilerMessages.Fatal_UnexpectedException({ e: `Unexpected UnicodeSet error code ${rc}` });
266
- }
267
- }
268
- //# sourceMappingURL=compiler.js.map
1
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},n=(new Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="3d508ab8-ba7b-5f73-b2b7-308d9fd6e769")}catch(e){}}();
2
+ /*
3
+ TODO: implement additional interfaces:
4
+
5
+ typedef bool (*kmcmp_ValidateJsonMessageProc)();
6
+ extern "C" bool kmcmp_ValidateJsonFile();
7
+ */
8
+ // TODO: rename wasm-host?
9
+ import { UnicodeSet, Osk, KvkFileReader } from '@keymanapp/common-types';
10
+ import { KvkFileWriter, KvksFileReader } from '@keymanapp/common-types';
11
+ import loadWasmHost from '../import/kmcmplib/wasm-host.js';
12
+ import { CompilerMessages, mapErrorFromKmcmplib } from './messages.js';
13
+ import { WriteCompiledKeyboard } from '../kmw-compiler/kmw-compiler.js';
14
+ ;
15
+ //
16
+ // Matches kmcmplibapi.h definitions
17
+ //
18
+ export const STORETYPE_STORE = 0x01;
19
+ export const STORETYPE_RESERVED = 0x02;
20
+ export const STORETYPE_OPTION = 0x04;
21
+ export const STORETYPE_DEBUG = 0x08;
22
+ export const STORETYPE_CALL = 0x10;
23
+ export const STORETYPE__MASK = 0x1F;
24
+ ;
25
+ ;
26
+ export const COMPILETARGETS_KMX = 0x01;
27
+ export const COMPILETARGETS_JS = 0x02;
28
+ export const COMPILETARGETS__MASK = 0x03;
29
+ ;
30
+ ;
31
+ ;
32
+ const baseOptions = {
33
+ shouldAddCompilerVersion: true,
34
+ saveDebug: true,
35
+ compilerWarningsAsErrors: false,
36
+ warnDeprecatedCode: true,
37
+ };
38
+ /**
39
+ * Allows multiple instances of the Compiler class, by ensuring that the
40
+ * 'unique' kmnCompilerCallback global will be correlated with a specific
41
+ * instance of the Compiler class
42
+ */
43
+ let callbackProcIdentifier = 0;
44
+ const callbackPrefix = 'kmnCompilerCallbacks_';
45
+ ;
46
+ let Module;
47
+ export class KmnCompiler {
48
+ callbackID; // a unique numeric id added to globals with prefixed names
49
+ callbacks;
50
+ wasmExports;
51
+ constructor() {
52
+ this.callbackID = callbackPrefix + callbackProcIdentifier.toString();
53
+ callbackProcIdentifier++;
54
+ }
55
+ async init(callbacks) {
56
+ this.callbacks = callbacks;
57
+ if (!Module) {
58
+ try {
59
+ Module = await loadWasmHost();
60
+ }
61
+ catch (e) {
62
+ /* c8 ignore next 3 */
63
+ this.callbacks.reportMessage(CompilerMessages.Fatal_MissingWasmModule({ e }));
64
+ return false;
65
+ }
66
+ }
67
+ this.wasmExports = (Module.wasmExports ?? Module.asm);
68
+ return this.verifyInitialized();
69
+ }
70
+ /**
71
+ * Verify that wasm is spun up OK.
72
+ * @returns true if OK
73
+ */
74
+ verifyInitialized() {
75
+ if (!this.callbacks) {
76
+ // Can't report a message here.
77
+ throw Error('Must call Compiler.init(callbacks) before proceeding');
78
+ }
79
+ if (!Module) {
80
+ /* c8 ignore next 4 */
81
+ // fail if wasm not loaded or function not found
82
+ this.callbacks.reportMessage(CompilerMessages.Fatal_MissingWasmModule({}));
83
+ return false;
84
+ }
85
+ return true;
86
+ }
87
+ // TODO: use outFile from options
88
+ run(infile, outfile, options) {
89
+ let result = this.runCompiler(infile, outfile, options);
90
+ if (result) {
91
+ if (result.kmx) {
92
+ this.callbacks.fs.writeFileSync(result.kmx.filename, result.kmx.data);
93
+ }
94
+ if (result.kvk) {
95
+ this.callbacks.fs.writeFileSync(result.kvk.filename, result.kvk.data);
96
+ }
97
+ if (result.js) {
98
+ this.callbacks.fs.writeFileSync(result.js.filename, result.js.data);
99
+ }
100
+ }
101
+ return !!result;
102
+ }
103
+ compilerMessageCallback = (line, code, msg) => {
104
+ this.callbacks.reportMessage(mapErrorFromKmcmplib(line, code, msg));
105
+ return 1;
106
+ };
107
+ cachedFile = {
108
+ filename: null,
109
+ data: null
110
+ };
111
+ loadFileCallback = (filename, baseFilename, buffer, bufferSize) => {
112
+ let resolvedFilename = this.callbacks.resolveFilename(baseFilename, filename);
113
+ let data;
114
+ if (this.cachedFile.filename == resolvedFilename) {
115
+ data = this.cachedFile.data;
116
+ }
117
+ else {
118
+ data = this.callbacks.loadFile(resolvedFilename);
119
+ if (!data) {
120
+ return -1;
121
+ }
122
+ this.cachedFile.filename = resolvedFilename;
123
+ this.cachedFile.data = data;
124
+ }
125
+ if (buffer == 0) {
126
+ /* We need to return buffer size required */
127
+ return data.byteLength;
128
+ }
129
+ if (bufferSize != data.byteLength) {
130
+ /* c8 ignore next 2 */
131
+ throw new Error(`loadFileCallback: second call, expected file size ${bufferSize} == ${data.byteLength}`);
132
+ }
133
+ Module.HEAP8.set(data, buffer);
134
+ return 1;
135
+ };
136
+ copyWasmResult(wasm_result) {
137
+ let result = {
138
+ // We cannot Object.assign or {...} on a wasm-defined object, so...
139
+ extra: {
140
+ targets: wasm_result.extra.targets,
141
+ displayMapFilename: wasm_result.extra.displayMapFilename,
142
+ kvksFilename: wasm_result.extra.kvksFilename,
143
+ stores: [],
144
+ groups: [],
145
+ },
146
+ displayMap: null
147
+ };
148
+ for (let store of wasm_result.extra.stores) {
149
+ result.extra.stores.push({ storeType: store.storeType, name: store.name, line: store.line });
150
+ }
151
+ for (let group of wasm_result.extra.groups) {
152
+ result.extra.groups.push({ isReadOnly: group.isReadOnly, name: group.name });
153
+ }
154
+ return result;
155
+ }
156
+ /**
157
+ * By default, when a `Uint8Array` is created from an `ArrayBuffer` (e.g.
158
+ * `Module.HEAP8.buffer`), it is a dynamic view into that buffer. This module
159
+ * buffer can be dynamically reallocated at any time, which can happen when
160
+ * allocating memory in WASM code (so the change will look _really_ weird in
161
+ * a stack trace). Thus, to ensure we don't trip over ourselves, we need to
162
+ * copy the buffer. Fortunately, creating a `Uint8Array` from a `Uint8Array`
163
+ * copies the data, and is pretty quick.
164
+ * @param offset Offset into the WASM memory space, in bytes
165
+ * @param size Size of the buffer to copy, in bytes
166
+ * @returns A _copy_ of the data in a new Uint8Array
167
+ */
168
+ copyWasmBuffer(offset, size) {
169
+ return new Uint8Array(new Uint8Array(Module.HEAP8.buffer, offset, size));
170
+ }
171
+ runCompiler(infile, outfile, options) {
172
+ if (!this.verifyInitialized()) {
173
+ /* c8 ignore next 2 */
174
+ return null;
175
+ }
176
+ options = { ...baseOptions, ...options };
177
+ globalThis[this.callbackID] = {
178
+ message: this.compilerMessageCallback,
179
+ loadFile: this.loadFileCallback
180
+ };
181
+ let wasm_interface = new Module.CompilerInterface();
182
+ let wasm_options = new Module.CompilerOptions();
183
+ let wasm_result = null;
184
+ try {
185
+ wasm_options.saveDebug = options.saveDebug;
186
+ wasm_options.compilerWarningsAsErrors = options.compilerWarningsAsErrors;
187
+ wasm_options.warnDeprecatedCode = options.warnDeprecatedCode;
188
+ wasm_options.shouldAddCompilerVersion = options.shouldAddCompilerVersion;
189
+ wasm_options.target = 0; // CKF_KEYMAN; TODO use COMPILETARGETS_KMX
190
+ wasm_interface.callbacksKey = this.callbackID; // key of object on globalThis
191
+ wasm_result = Module.kmcmp_compile(infile, wasm_options, wasm_interface);
192
+ if (!wasm_result.result) {
193
+ return null;
194
+ }
195
+ const result = this.copyWasmResult(wasm_result);
196
+ if (result.extra.targets & COMPILETARGETS_KMX) {
197
+ result.kmx = {
198
+ filename: outfile,
199
+ data: this.copyWasmBuffer(wasm_result.kmx, wasm_result.kmxSize)
200
+ };
201
+ }
202
+ //
203
+ // Visual Keyboard transform
204
+ //
205
+ if (result.extra.displayMapFilename) {
206
+ result.displayMap = this.loadDisplayMapping(infile, result.extra.displayMapFilename);
207
+ }
208
+ if (result.extra.kvksFilename) {
209
+ result.kvk = this.runKvkCompiler(result.extra.kvksFilename, infile, outfile, result.displayMap);
210
+ if (!result.kvk) {
211
+ return null;
212
+ }
213
+ }
214
+ //
215
+ // KeymanWeb compiler
216
+ //
217
+ if (wasm_result.extra.targets & COMPILETARGETS_JS) {
218
+ wasm_options.target = 1; // CKF_KEYMANWEB TODO use COMPILETARGETS_JS
219
+ wasm_result = Module.kmcmp_compile(infile, wasm_options, wasm_interface);
220
+ if (!wasm_result.result) {
221
+ return null;
222
+ }
223
+ const kmw_result = this.copyWasmResult(wasm_result);
224
+ kmw_result.displayMap = result.displayMap; // we can safely re-use the kmx compile displayMap
225
+ const web_kmx = this.copyWasmBuffer(wasm_result.kmx, wasm_result.kmxSize);
226
+ result.js = this.runWebCompiler(infile, outfile, web_kmx, result.kvk?.data, kmw_result, options);
227
+ if (!result.js) {
228
+ return null;
229
+ }
230
+ }
231
+ return result;
232
+ }
233
+ catch (e) {
234
+ /* c8 ignore next 3 */
235
+ this.callbacks.reportMessage(CompilerMessages.Fatal_UnexpectedException({ e: e }));
236
+ return null;
237
+ }
238
+ finally {
239
+ if (wasm_result) {
240
+ wasm_result.delete();
241
+ }
242
+ wasm_interface.delete();
243
+ wasm_options.delete();
244
+ delete globalThis[this.callbackID];
245
+ }
246
+ }
247
+ runWebCompiler(kmnFilename, kmxFilename, web_kmx, kvk, kmxResult, options) {
248
+ const data = WriteCompiledKeyboard(this.callbacks, kmnFilename, web_kmx, kvk, kmxResult, options.saveDebug);
249
+ if (!data) {
250
+ return null;
251
+ }
252
+ return {
253
+ filename: this.callbacks.path.join(this.callbacks.path.dirname(kmxFilename), this.keyboardIdFromKmnFilename(kmnFilename) + ".js" /* KeymanFileTypes.Binary.WebKeyboard */),
254
+ data: new TextEncoder().encode(data)
255
+ };
256
+ }
257
+ keyboardIdFromKmnFilename(kmnFilename) {
258
+ return this.callbacks.path.basename(kmnFilename, ".kmn" /* KeymanFileTypes.Source.KeymanKeyboard */);
259
+ }
260
+ runKvkCompiler(kvksFilename, kmnFilename, kmxFilename, displayMap) {
261
+ // The compiler detected a .kvks file, which needs to be captured
262
+ kvksFilename = this.callbacks.resolveFilename(kmnFilename, kvksFilename);
263
+ const filename = this.callbacks.path.basename(kvksFilename);
264
+ let basename = null;
265
+ let vk = null;
266
+ if (filename.endsWith('.kvk')) {
267
+ /* Legacy keyboards may reference a binary .kvk. That's not an error */
268
+ // TODO: (lowpri) add hint to convert to .kvks?
269
+ basename = this.callbacks.path.basename(kvksFilename, ".kvk" /* KeymanFileTypes.Binary.VisualKeyboard */);
270
+ const reader = new KvkFileReader();
271
+ try {
272
+ vk = reader.read(this.callbacks.loadFile(kvksFilename));
273
+ }
274
+ catch (e) {
275
+ this.callbacks.reportMessage(CompilerMessages.Error_InvalidKvkFile({ filename, e }));
276
+ return null;
277
+ }
278
+ }
279
+ else {
280
+ basename = this.callbacks.path.basename(kvksFilename, ".kvks" /* KeymanFileTypes.Source.VisualKeyboard */);
281
+ const reader = new KvksFileReader();
282
+ let kvks = null;
283
+ try {
284
+ kvks = reader.read(this.callbacks.loadFile(kvksFilename));
285
+ reader.validate(kvks);
286
+ }
287
+ catch (e) {
288
+ this.callbacks.reportMessage(CompilerMessages.Error_InvalidKvksFile({ filename, e }));
289
+ return null;
290
+ }
291
+ let invalidVkeys = [];
292
+ vk = reader.transform(kvks, invalidVkeys);
293
+ for (let invalidVkey of invalidVkeys) {
294
+ this.callbacks.reportMessage(CompilerMessages.Warn_InvalidVkeyInKvksFile({ filename, invalidVkey }));
295
+ }
296
+ }
297
+ // Make sure that we maintain the correspondence between source keyboard and
298
+ // .kvk. Appears to be used currently only by Windows package installer.
299
+ vk.header.associatedKeyboard = this.keyboardIdFromKmnFilename(kmnFilename);
300
+ if (displayMap) {
301
+ // Remap using the osk-char-use-rewriter
302
+ Osk.remapVisualKeyboard(vk, displayMap);
303
+ }
304
+ let writer = new KvkFileWriter();
305
+ return {
306
+ filename: this.callbacks.path.join(this.callbacks.path.dirname(kmxFilename), basename + ".kvk" /* KeymanFileTypes.Binary.VisualKeyboard */),
307
+ data: writer.write(vk)
308
+ };
309
+ }
310
+ loadDisplayMapping(kmnFilename, displayMapFilename) {
311
+ // Remap using the osk-char-use-rewriter
312
+ displayMapFilename = this.callbacks.resolveFilename(kmnFilename, displayMapFilename);
313
+ try {
314
+ // Expected file format: displaymap.schema.json
315
+ const data = this.callbacks.loadFile(displayMapFilename);
316
+ const mapping = JSON.parse(new TextDecoder().decode(data));
317
+ return Osk.parseMapping(mapping);
318
+ }
319
+ catch (e) {
320
+ this.callbacks.reportMessage(CompilerMessages.Error_InvalidDisplayMapFile({ filename: displayMapFilename, e }));
321
+ return null;
322
+ }
323
+ }
324
+ testSentry() {
325
+ if (!this.verifyInitialized()) {
326
+ return null;
327
+ }
328
+ return Module.kmcmp_testSentry();
329
+ }
330
+ /**
331
+ *
332
+ * @param pattern UnicodeSet pattern such as `[a-z]`
333
+ * @param rangeCount number of ranges to allocate
334
+ * @returns UnicodeSet accessor object, or null on failure
335
+ */
336
+ parseUnicodeSet(pattern, rangeCount) {
337
+ if (!this.verifyInitialized()) {
338
+ /* c8 ignore next 2 */
339
+ return null;
340
+ }
341
+ // TODO-LDML: Catch OOM
342
+ const buf = this.wasmExports.malloc(rangeCount * 2 * Module.HEAPU32.BYTES_PER_ELEMENT);
343
+ /** If <= 0: return code. If positive: range count */
344
+ const rc = Module.kmcmp_parseUnicodeSet(pattern, buf, rangeCount * 2);
345
+ if (rc >= 0) {
346
+ const ranges = [];
347
+ const startu = (buf / Module.HEAPU32.BYTES_PER_ELEMENT);
348
+ for (let i = 0; i < rc; i++) {
349
+ const start = Module.HEAPU32[startu + (i * 2) + 0];
350
+ const end = Module.HEAPU32[startu + (i * 2) + 1];
351
+ ranges.push([start, end]);
352
+ }
353
+ this.wasmExports.free(buf);
354
+ return new UnicodeSet(pattern, ranges);
355
+ }
356
+ else {
357
+ this.wasmExports.free(buf);
358
+ // translate error code into callback
359
+ this.callbacks.reportMessage(getUnicodeSetError(rc));
360
+ return null;
361
+ }
362
+ }
363
+ sizeUnicodeSet(pattern) {
364
+ if (!this.verifyInitialized()) {
365
+ /* c8 ignore next 2 */
366
+ return null;
367
+ }
368
+ // call with rangeCount = 0 to invoke in 'preflight' mode.
369
+ const rc = Module.kmcmp_parseUnicodeSet(pattern, 0, 0);
370
+ if (rc >= 0) {
371
+ return rc;
372
+ }
373
+ else {
374
+ this.callbacks.reportMessage(getUnicodeSetError(rc));
375
+ return -1;
376
+ }
377
+ }
378
+ }
379
+ /**
380
+ * translate UnicodeSet return code into a compiler event
381
+ * @param rc parseUnicodeSet error code
382
+ * @returns the compiler event
383
+ */
384
+ function getUnicodeSetError(rc) {
385
+ // from kmcmplib.h
386
+ const KMCMP_ERROR_SYNTAX_ERR = -1;
387
+ const KMCMP_ERROR_HAS_STRINGS = -2;
388
+ const KMCMP_ERROR_UNSUPPORTED_PROPERTY = -3;
389
+ const KMCMP_FATAL_OUT_OF_RANGE = -4;
390
+ switch (rc) {
391
+ case KMCMP_ERROR_SYNTAX_ERR:
392
+ return CompilerMessages.Error_UnicodeSetSyntaxError();
393
+ case KMCMP_ERROR_HAS_STRINGS:
394
+ return CompilerMessages.Error_UnicodeSetHasStrings();
395
+ case KMCMP_ERROR_UNSUPPORTED_PROPERTY:
396
+ return CompilerMessages.Error_UnicodeSetHasProperties();
397
+ case KMCMP_FATAL_OUT_OF_RANGE:
398
+ return CompilerMessages.Fatal_UnicodeSetOutOfRange();
399
+ default:
400
+ /* c8 ignore next */
401
+ return CompilerMessages.Fatal_UnexpectedException({ e: `Unexpected UnicodeSet error code ${rc}` });
402
+ }
403
+ }
404
+ //# debugId=3d508ab8-ba7b-5f73-b2b7-308d9fd6e769
405
+ //# sourceMappingURL=compiler.js.map