zuzu-js 0.4.0 → 0.6.0
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/dist/zuzu-browser-worker.js +1107 -95
- package/dist/zuzu-browser.js +1113 -99
- package/lib/browser-bundle-entry.js +2 -0
- package/lib/cli.js +1 -1
- package/lib/collections.js +49 -2
- package/lib/host/browser-host.js +124 -0
- package/lib/runtime-helpers.js +34 -3
- package/lib/runtime.js +577 -38
- package/lib/tap.js +8 -1
- package/lib/transpiler-new/codegen.js +134 -28
- package/lib/transpiler-new/lexer.js +49 -3
- package/lib/transpiler-new/parser.js +121 -11
- package/lib/zuzu.js +5 -1
- package/modules/std/io.js +49 -4
- package/modules/std/marshal/graph.js +3 -1
- package/package.json +1 -1
- package/stdlib/modules/std/config.zzm +5 -5
- package/stdlib/modules/std/data/kdl/xml.zzm +1 -1
- package/stdlib/modules/std/gui/dialogue.zzm +1 -0
- package/stdlib/modules/std/gui.zzm +3 -1
- package/stdlib/modules/std/io.zzm +7 -0
- package/stdlib/modules/std/path/z/context.zzm +1 -0
- package/stdlib/modules/std/path/z/evaluate.zzm +4 -1
- package/stdlib/modules/std/path/z/functions.zzm +1 -0
- package/stdlib/modules/std/path/z/node.zzm +3 -2
- package/stdlib/modules/std/path/zz/functions.zzm +2 -0
- package/stdlib/modules/std/path/zz/operators.zzm +438 -75
- package/stdlib/modules/std/uuid.zzm +1 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const { createBrowserRuntime } = require( './browser-runtime' );
|
|
4
|
+
const { addBrowserModule } = require( './host/browser-host' );
|
|
4
5
|
const {
|
|
5
6
|
createBrowserGuiBridge,
|
|
6
7
|
createBrowserGuiRenderer,
|
|
@@ -147,6 +148,7 @@ if (
|
|
|
147
148
|
}
|
|
148
149
|
|
|
149
150
|
module.exports = {
|
|
151
|
+
addModule: addBrowserModule,
|
|
150
152
|
createBrowserRuntime: createConfiguredBrowserRuntime,
|
|
151
153
|
createBrowserGuiBridge,
|
|
152
154
|
createBrowserGuiRenderer,
|
package/lib/cli.js
CHANGED
|
@@ -254,7 +254,7 @@ function stripShebang( source ) {
|
|
|
254
254
|
}
|
|
255
255
|
|
|
256
256
|
function printVersion( runtime, verbose ) {
|
|
257
|
-
process.stdout.write( 'zuzu-js version 0.
|
|
257
|
+
process.stdout.write( 'zuzu-js version 0.6.0\n' );
|
|
258
258
|
if ( verbose ) {
|
|
259
259
|
process.stdout.write( '\nlib search paths:\n' );
|
|
260
260
|
for ( const p of runtime.getModuleSearchRoots() ) {
|
package/lib/collections.js
CHANGED
|
@@ -24,6 +24,10 @@ function makeSet( values ) {
|
|
|
24
24
|
return runtimeHelpers().makeSet( values );
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
function operatorString( value ) {
|
|
28
|
+
return runtimeHelpers().operatorString( value );
|
|
29
|
+
}
|
|
30
|
+
|
|
27
31
|
function stringSortComparator( a, b ) {
|
|
28
32
|
return runtimeHelpers().stringSortComparator( a, b );
|
|
29
33
|
}
|
|
@@ -68,7 +72,15 @@ class ZuzuBag {
|
|
|
68
72
|
return this;
|
|
69
73
|
}
|
|
70
74
|
push( ...values ) { return this.add( ...values ); }
|
|
71
|
-
remove( value ) {
|
|
75
|
+
remove( value ) {
|
|
76
|
+
for ( let idx = this.items.length - 1; idx >= 0; idx-- ) {
|
|
77
|
+
if ( this.items[idx] === value ) {
|
|
78
|
+
releaseCollectionValue( this, this.items[idx] );
|
|
79
|
+
this.items.splice( idx, 1 );
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return this;
|
|
83
|
+
}
|
|
72
84
|
remove_first( value ) {
|
|
73
85
|
const idx = this.items.indexOf( value );
|
|
74
86
|
if ( idx >= 0 ) {
|
|
@@ -87,7 +99,6 @@ class ZuzuBag {
|
|
|
87
99
|
} );
|
|
88
100
|
return this;
|
|
89
101
|
}
|
|
90
|
-
get( idx, fallback = null ) { return idx >= 0 && idx < this.items.length ? this.items[idx] : fallback; }
|
|
91
102
|
map( fn ) { return new ZuzuBag( this.items.map( fn ) ); }
|
|
92
103
|
grep( fn ) { return new ZuzuBag( this.items.filter( fn ) ); }
|
|
93
104
|
any( fn ) { return this.items.some( fn ) ? 1 : 0; }
|
|
@@ -193,6 +204,7 @@ class PairList {
|
|
|
193
204
|
length() { return this.list.length; }
|
|
194
205
|
count() { return this.list.length; }
|
|
195
206
|
empty() { return this.list.length === 0 ? 1 : 0; }
|
|
207
|
+
is_empty() { return this.empty(); }
|
|
196
208
|
keys() { return this.list.map( (pair) => pair[0] ); }
|
|
197
209
|
values() { return this.list.map( (pair) => pair[1] ); }
|
|
198
210
|
enumerate() { return this.to_Array(); }
|
|
@@ -279,6 +291,7 @@ Object.defineProperty( PairList.prototype, '__zuzu_builtin_type', {
|
|
|
279
291
|
});
|
|
280
292
|
|
|
281
293
|
function withArrayMethods() {
|
|
294
|
+
const nativeJoin = Array.prototype.join;
|
|
282
295
|
const define = ( name, fn ) => {
|
|
283
296
|
if ( !Object.prototype.hasOwnProperty.call( Array.prototype, name ) ) {
|
|
284
297
|
const desc = Object.create( null );
|
|
@@ -287,6 +300,40 @@ function withArrayMethods() {
|
|
|
287
300
|
Object.defineProperty( Array.prototype, name, desc );
|
|
288
301
|
}
|
|
289
302
|
};
|
|
303
|
+
if ( Array.prototype.join.__zuzu_array_join !== true ) {
|
|
304
|
+
const desc = Object.create( null );
|
|
305
|
+
desc.value = function _join( separator, fallback ) {
|
|
306
|
+
const hasFallback = arguments.length > 1;
|
|
307
|
+
let fallbackString;
|
|
308
|
+
const sep = operatorString( separator );
|
|
309
|
+
const out = [];
|
|
310
|
+
for ( const value of this ) {
|
|
311
|
+
try {
|
|
312
|
+
out.push( operatorString( value ) );
|
|
313
|
+
}
|
|
314
|
+
catch ( err ) {
|
|
315
|
+
if ( !hasFallback ) {
|
|
316
|
+
throw err;
|
|
317
|
+
}
|
|
318
|
+
if ( typeof fallback === 'function' ) {
|
|
319
|
+
out.push( operatorString( fallback( value ) ) );
|
|
320
|
+
}
|
|
321
|
+
else {
|
|
322
|
+
if ( fallbackString === undefined ) {
|
|
323
|
+
fallbackString = operatorString( fallback );
|
|
324
|
+
}
|
|
325
|
+
out.push( fallbackString );
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
return nativeJoin.call( out, sep );
|
|
330
|
+
};
|
|
331
|
+
desc.value.__zuzu_array_join = true;
|
|
332
|
+
desc.enumerable = false;
|
|
333
|
+
desc.configurable = true;
|
|
334
|
+
desc.writable = true;
|
|
335
|
+
Object.defineProperty( Array.prototype, 'join', desc );
|
|
336
|
+
}
|
|
290
337
|
define( 'count', function _count() { return this.length; } );
|
|
291
338
|
define( 'empty', function _empty() { return this.length === 0 ? 1 : 0; } );
|
|
292
339
|
define( 'is_empty', function _is_empty() { return this.empty(); } );
|
package/lib/host/browser-host.js
CHANGED
|
@@ -48,6 +48,43 @@ function _sourceUrlComment( runOptions = {} ) {
|
|
|
48
48
|
return `\n//# sourceURL=${filename.replace( /[\r\n]/gu, '_' )}`;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
+
const browserModuleUrls = new Map();
|
|
52
|
+
|
|
53
|
+
function _normalizeModuleName( value ) {
|
|
54
|
+
const name = String( value ?? '' ).trim().replace( /\\/gu, '/' );
|
|
55
|
+
if (
|
|
56
|
+
name === ''
|
|
57
|
+
|| name.startsWith( '/' )
|
|
58
|
+
|| name.endsWith( '/' )
|
|
59
|
+
|| /(^|\/)\.\.?(\/|$)/u.test( name )
|
|
60
|
+
) {
|
|
61
|
+
throw new Error( `Invalid browser module name: ${value}` );
|
|
62
|
+
}
|
|
63
|
+
return name.replace( /\.zzm$/u, '' );
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function _moduleNameFromPath( filename ) {
|
|
67
|
+
const path = _resolvePath( filename );
|
|
68
|
+
if ( !path.startsWith( '/modules/' ) || !path.endsWith( '.zzm' ) ) {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
return path.slice( '/modules/'.length, -'.zzm'.length );
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function addBrowserModule( moduleName, url ) {
|
|
75
|
+
const logicalName = _normalizeModuleName( moduleName );
|
|
76
|
+
const moduleUrl = String( url ?? '' ).trim();
|
|
77
|
+
if ( moduleUrl === '' ) {
|
|
78
|
+
throw new Error( `Invalid URL for browser module '${logicalName}'` );
|
|
79
|
+
}
|
|
80
|
+
browserModuleUrls.set( logicalName, moduleUrl );
|
|
81
|
+
return logicalName;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function hasBrowserModules() {
|
|
85
|
+
return browserModuleUrls.size > 0;
|
|
86
|
+
}
|
|
87
|
+
|
|
51
88
|
function _browserEval( source, context, runOptions = {} ) {
|
|
52
89
|
context.globalThis = context;
|
|
53
90
|
const sourceUrl = _sourceUrlComment( runOptions );
|
|
@@ -153,6 +190,18 @@ function createBrowserHost( options = {} ) {
|
|
|
153
190
|
const jsModules = new Map( Object.entries( options.jsModules || {} )
|
|
154
191
|
.map( ( [ filename, loaded ] ) => [ _resolvePath( filename ), loaded ] ) );
|
|
155
192
|
const fetchedFiles = new Map();
|
|
193
|
+
const fetchingFiles = new Map();
|
|
194
|
+
const optionModuleUrls = new Map(
|
|
195
|
+
Object.entries( options.remoteModules || {} )
|
|
196
|
+
.map( ( [ name, url ] ) => [ _normalizeModuleName( name ), String( url ) ] )
|
|
197
|
+
);
|
|
198
|
+
const fetchText = typeof options.fetch === 'function'
|
|
199
|
+
? options.fetch
|
|
200
|
+
: (
|
|
201
|
+
typeof fetch === 'function'
|
|
202
|
+
? fetch
|
|
203
|
+
: null
|
|
204
|
+
);
|
|
156
205
|
const fetchModule = typeof options.fetchModule === 'function'
|
|
157
206
|
? options.fetchModule
|
|
158
207
|
: null;
|
|
@@ -193,6 +242,58 @@ function createBrowserHost( options = {} ) {
|
|
|
193
242
|
capabilities.add( 'worker' );
|
|
194
243
|
}
|
|
195
244
|
const gui = _defaultGuiBridge( options );
|
|
245
|
+
function browserModuleUrlForPath( filename ) {
|
|
246
|
+
const logicalName = _moduleNameFromPath( filename );
|
|
247
|
+
if ( !logicalName ) {
|
|
248
|
+
return null;
|
|
249
|
+
}
|
|
250
|
+
if ( optionModuleUrls.has( logicalName ) ) {
|
|
251
|
+
return optionModuleUrls.get( logicalName );
|
|
252
|
+
}
|
|
253
|
+
return browserModuleUrls.get( logicalName ) || null;
|
|
254
|
+
}
|
|
255
|
+
function hasAsyncModules() {
|
|
256
|
+
return optionModuleUrls.size > 0 || browserModuleUrls.size > 0;
|
|
257
|
+
}
|
|
258
|
+
async function fetchBrowserModule( key, url ) {
|
|
259
|
+
if ( fetchedFiles.has( key ) ) {
|
|
260
|
+
return fetchedFiles.get( key );
|
|
261
|
+
}
|
|
262
|
+
if ( fetchingFiles.has( key ) ) {
|
|
263
|
+
return fetchingFiles.get( key );
|
|
264
|
+
}
|
|
265
|
+
if ( !fetchText ) {
|
|
266
|
+
throw new Error( `Exception: Browser host cannot fetch module '${key}'` );
|
|
267
|
+
}
|
|
268
|
+
const pending = Promise.resolve( fetchText( url ) )
|
|
269
|
+
.then( async (response) => {
|
|
270
|
+
if ( typeof response === 'string' ) {
|
|
271
|
+
return response;
|
|
272
|
+
}
|
|
273
|
+
if ( response && response.ok === false ) {
|
|
274
|
+
throw new Error(
|
|
275
|
+
`Exception: Fetch failed for browser module '${key}' (${response.status})`
|
|
276
|
+
);
|
|
277
|
+
}
|
|
278
|
+
if ( !response || typeof response.text !== 'function' ) {
|
|
279
|
+
throw new Error(
|
|
280
|
+
`Exception: Fetch did not return text for browser module '${key}'`
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
return response.text();
|
|
284
|
+
} )
|
|
285
|
+
.then( (source) => {
|
|
286
|
+
const text = String( source );
|
|
287
|
+
fetchedFiles.set( key, text );
|
|
288
|
+
fetchingFiles.delete( key );
|
|
289
|
+
return text;
|
|
290
|
+
}, (err) => {
|
|
291
|
+
fetchingFiles.delete( key );
|
|
292
|
+
throw err;
|
|
293
|
+
} );
|
|
294
|
+
fetchingFiles.set( key, pending );
|
|
295
|
+
return pending;
|
|
296
|
+
}
|
|
196
297
|
return {
|
|
197
298
|
name: 'browser',
|
|
198
299
|
repoRoot,
|
|
@@ -229,13 +330,33 @@ function createBrowserHost( options = {} ) {
|
|
|
229
330
|
return fetched;
|
|
230
331
|
}
|
|
231
332
|
}
|
|
333
|
+
if ( browserModuleUrlForPath( key ) ) {
|
|
334
|
+
throw new Error( `Exception: Browser module '${filename}' requires asynchronous loading` );
|
|
335
|
+
}
|
|
232
336
|
throw new Error( `Exception: Browser host cannot read file '${filename}'` );
|
|
233
337
|
},
|
|
338
|
+
async readFileTextAsync( filename ) {
|
|
339
|
+
const key = _resolvePath( filename );
|
|
340
|
+
if ( virtualFiles.has( key ) ) {
|
|
341
|
+
return virtualFiles.get( key );
|
|
342
|
+
}
|
|
343
|
+
if ( fetchedFiles.has( key ) ) {
|
|
344
|
+
return fetchedFiles.get( key );
|
|
345
|
+
}
|
|
346
|
+
const browserModuleUrl = browserModuleUrlForPath( key );
|
|
347
|
+
if ( browserModuleUrl ) {
|
|
348
|
+
return fetchBrowserModule( key, browserModuleUrl );
|
|
349
|
+
}
|
|
350
|
+
return this.readFileText( key );
|
|
351
|
+
},
|
|
234
352
|
fileExists( filename ) {
|
|
235
353
|
const key = _resolvePath( filename );
|
|
236
354
|
if ( virtualFiles.has( key ) || jsModules.has( key ) || fetchedFiles.has( key ) ) {
|
|
237
355
|
return true;
|
|
238
356
|
}
|
|
357
|
+
if ( browserModuleUrlForPath( key ) ) {
|
|
358
|
+
return true;
|
|
359
|
+
}
|
|
239
360
|
if ( fetchModule ) {
|
|
240
361
|
const fetched = fetchModule( key );
|
|
241
362
|
if ( typeof fetched === 'string' ) {
|
|
@@ -270,9 +391,12 @@ function createBrowserHost( options = {} ) {
|
|
|
270
391
|
}
|
|
271
392
|
return jsModules.get( key );
|
|
272
393
|
},
|
|
394
|
+
hasAsyncModules,
|
|
273
395
|
};
|
|
274
396
|
}
|
|
275
397
|
|
|
276
398
|
module.exports = {
|
|
399
|
+
addBrowserModule,
|
|
277
400
|
createBrowserHost,
|
|
401
|
+
hasBrowserModules,
|
|
278
402
|
};
|
package/lib/runtime-helpers.js
CHANGED
|
@@ -143,6 +143,15 @@ function retainValue( value ) {
|
|
|
143
143
|
return resolved;
|
|
144
144
|
}
|
|
145
145
|
|
|
146
|
+
function strongReferenceCount( value ) {
|
|
147
|
+
const resolved = resolveWeakValue( value );
|
|
148
|
+
if ( !isWeakableValue( resolved ) ) {
|
|
149
|
+
return 0;
|
|
150
|
+
}
|
|
151
|
+
const state = weakStates.get( resolved );
|
|
152
|
+
return state ? state.strong : 0;
|
|
153
|
+
}
|
|
154
|
+
|
|
146
155
|
function retainedValuesForCollection( collection, create = false ) {
|
|
147
156
|
const resolved = resolveWeakValue( collection );
|
|
148
157
|
if ( !isWeakableValue( resolved ) ) {
|
|
@@ -198,7 +207,7 @@ function releaseCollectionValues( collection ) {
|
|
|
198
207
|
return null;
|
|
199
208
|
}
|
|
200
209
|
|
|
201
|
-
function releaseValue( value ) {
|
|
210
|
+
function releaseValue( value, options = {} ) {
|
|
202
211
|
if ( isWeakCell( value ) ) {
|
|
203
212
|
return null;
|
|
204
213
|
}
|
|
@@ -209,7 +218,15 @@ function releaseValue( value ) {
|
|
|
209
218
|
const wasStrong = state.strong;
|
|
210
219
|
state.strong = Math.max( 0, state.strong - 1 );
|
|
211
220
|
if ( wasStrong > 0 && state.strong === 0 ) {
|
|
212
|
-
|
|
221
|
+
if ( !options.preserveCollectionValues ) {
|
|
222
|
+
releaseCollectionValues( resolved );
|
|
223
|
+
}
|
|
224
|
+
if (
|
|
225
|
+
!options.suppressDemolish
|
|
226
|
+
&& typeof resolved.__demolish__ === 'function'
|
|
227
|
+
) {
|
|
228
|
+
resolved.__demolish__();
|
|
229
|
+
}
|
|
213
230
|
}
|
|
214
231
|
}
|
|
215
232
|
}
|
|
@@ -571,6 +588,9 @@ function buildComparator( name ) {
|
|
|
571
588
|
if ( name === 'eq' ) {
|
|
572
589
|
return ( left, right ) => String( left ) === String( right );
|
|
573
590
|
}
|
|
591
|
+
if ( name === 'eqi' ) {
|
|
592
|
+
return ( left, right ) => String( left ).toLowerCase() === String( right ).toLowerCase();
|
|
593
|
+
}
|
|
574
594
|
if ( name === '~' ) {
|
|
575
595
|
return ( left, right ) => {
|
|
576
596
|
if ( right && typeof right.test === 'function' ) {
|
|
@@ -582,11 +602,21 @@ function buildComparator( name ) {
|
|
|
582
602
|
return ( left, right ) => left == right;
|
|
583
603
|
}
|
|
584
604
|
|
|
605
|
+
function switchTruthy( value ) {
|
|
606
|
+
return !!value;
|
|
607
|
+
}
|
|
608
|
+
|
|
585
609
|
function runSwitch( value, cmpName, cases, defaultBody ) {
|
|
586
610
|
const cmp = buildComparator( cmpName );
|
|
587
611
|
let runNext = false;
|
|
588
612
|
for ( const section of cases ) {
|
|
589
|
-
|
|
613
|
+
let matched = false;
|
|
614
|
+
if ( Array.isArray( section.tests ) ) {
|
|
615
|
+
matched = section.tests.some( (test) => switchTruthy( test( value ) ) );
|
|
616
|
+
}
|
|
617
|
+
else {
|
|
618
|
+
matched = section.values.some( (item) => cmp( value, item ) );
|
|
619
|
+
}
|
|
590
620
|
if ( matched || runNext ) {
|
|
591
621
|
const result = section.body();
|
|
592
622
|
runNext = result === true;
|
|
@@ -961,6 +991,7 @@ module.exports = {
|
|
|
961
991
|
resolveWeakValue,
|
|
962
992
|
retainValue,
|
|
963
993
|
releaseValue,
|
|
994
|
+
strongReferenceCount,
|
|
964
995
|
retainCollectionValue,
|
|
965
996
|
releaseCollectionValue,
|
|
966
997
|
releaseCollectionValues,
|