zuzu-js 0.1.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/LICENSE +5 -0
- package/README.md +113 -0
- package/bin/zuzu +17 -0
- package/bin/zuzu-build-browser-bundle +57 -0
- package/bin/zuzu-generate-browser-stdlib +584 -0
- package/bin/zuzu-js +23 -0
- package/bin/zuzu-js-compile +152 -0
- package/bin/zuzu-js-electron +19 -0
- package/dist/zuzu-browser-worker.js +45574 -0
- package/dist/zuzu-browser.js +45362 -0
- package/lib/browser-bundle-entry.js +160 -0
- package/lib/browser-gui-renderer.js +387 -0
- package/lib/browser-runtime.js +167 -0
- package/lib/browser-worker-entry.js +413 -0
- package/lib/browser-ztests/runner.html +103 -0
- package/lib/browser-ztests/runner.js +369 -0
- package/lib/cli.js +350 -0
- package/lib/collections.js +367 -0
- package/lib/compiler.js +303 -0
- package/lib/electron/launcher.js +70 -0
- package/lib/electron/main.js +956 -0
- package/lib/electron/preload.js +80 -0
- package/lib/electron/renderer.html +122 -0
- package/lib/electron/renderer.js +24 -0
- package/lib/execution-metadata.js +18 -0
- package/lib/gui/dom-renderer.js +778 -0
- package/lib/host/browser-host.js +278 -0
- package/lib/host/capabilities.js +47 -0
- package/lib/host/electron-host.js +15 -0
- package/lib/host/node-host.js +74 -0
- package/lib/paths.js +150 -0
- package/lib/runtime-entrypoints.js +60 -0
- package/lib/runtime-helpers.js +886 -0
- package/lib/runtime.js +3529 -0
- package/lib/tap.js +37 -0
- package/lib/transpiler-new/ast.js +23 -0
- package/lib/transpiler-new/codegen.js +2455 -0
- package/lib/transpiler-new/errors.js +28 -0
- package/lib/transpiler-new/index.js +26 -0
- package/lib/transpiler-new/lexer.js +834 -0
- package/lib/transpiler-new/parser.js +2332 -0
- package/lib/transpiler-new/validate-bindings.js +326 -0
- package/lib/transpiler-utils.js +95 -0
- package/lib/transpiler.js +33 -0
- package/lib/zuzu.js +53 -0
- package/modules/javascript.js +193 -0
- package/modules/std/archive.js +603 -0
- package/modules/std/clib.js +338 -0
- package/modules/std/data/csv.js +1331 -0
- package/modules/std/data/json.js +531 -0
- package/modules/std/data/xml.js +441 -0
- package/modules/std/data/yaml.js +256 -0
- package/modules/std/db-worker.js +250 -0
- package/modules/std/db.js +664 -0
- package/modules/std/digest/_hash.js +443 -0
- package/modules/std/digest/md5.js +26 -0
- package/modules/std/digest/sha.js +72 -0
- package/modules/std/eval.js +10 -0
- package/modules/std/gui/objects.js +1519 -0
- package/modules/std/internals.js +571 -0
- package/modules/std/io/socks-worker.js +318 -0
- package/modules/std/io/socks.js +186 -0
- package/modules/std/io.js +475 -0
- package/modules/std/marshal/cbor.js +463 -0
- package/modules/std/marshal/graph.js +1624 -0
- package/modules/std/marshal.js +87 -0
- package/modules/std/math/bignum.js +91 -0
- package/modules/std/math.js +79 -0
- package/modules/std/net/dns.js +306 -0
- package/modules/std/net/http.js +820 -0
- package/modules/std/net/smtp.js +943 -0
- package/modules/std/net/url.js +109 -0
- package/modules/std/proc.js +602 -0
- package/modules/std/secure.js +3724 -0
- package/modules/std/string/base64.js +138 -0
- package/modules/std/string.js +299 -0
- package/modules/std/task.js +914 -0
- package/modules/std/time.js +579 -0
- package/modules/std/tui.js +188 -0
- package/modules/std/worker-thread.js +246 -0
- package/modules/std/worker.js +790 -0
- package/package.json +67 -0
- package/stdlib/modules/javascript.zzm +99 -0
- package/stdlib/modules/perl.zzm +105 -0
- package/stdlib/modules/std/archive.zzm +132 -0
- package/stdlib/modules/std/cache/lru.zzm +174 -0
- package/stdlib/modules/std/clib.zzm +112 -0
- package/stdlib/modules/std/colour.zzm +220 -0
- package/stdlib/modules/std/config.zzm +818 -0
- package/stdlib/modules/std/data/cbor.zzm +497 -0
- package/stdlib/modules/std/data/csv.zzm +285 -0
- package/stdlib/modules/std/data/ini.zzm +472 -0
- package/stdlib/modules/std/data/json/schema/core.zzm +573 -0
- package/stdlib/modules/std/data/json/schema/format.zzm +581 -0
- package/stdlib/modules/std/data/json/schema/model.zzm +255 -0
- package/stdlib/modules/std/data/json/schema/output.zzm +272 -0
- package/stdlib/modules/std/data/json/schema/relative_pointer.zzm +299 -0
- package/stdlib/modules/std/data/json/schema/validation.zzm +1503 -0
- package/stdlib/modules/std/data/json/schema.zzm +306 -0
- package/stdlib/modules/std/data/json.zzm +102 -0
- package/stdlib/modules/std/data/kdl/json.zzm +460 -0
- package/stdlib/modules/std/data/kdl/xml.zzm +387 -0
- package/stdlib/modules/std/data/kdl.zzm +1631 -0
- package/stdlib/modules/std/data/toml.zzm +756 -0
- package/stdlib/modules/std/data/toon.zzm +1017 -0
- package/stdlib/modules/std/data/xml/escape.zzm +156 -0
- package/stdlib/modules/std/data/xml.zzm +276 -0
- package/stdlib/modules/std/data/yaml.zzm +94 -0
- package/stdlib/modules/std/db.zzm +173 -0
- package/stdlib/modules/std/defer.zzm +75 -0
- package/stdlib/modules/std/digest/crc32.zzm +196 -0
- package/stdlib/modules/std/digest/md5.zzm +54 -0
- package/stdlib/modules/std/digest/sha.zzm +83 -0
- package/stdlib/modules/std/dump.zzm +317 -0
- package/stdlib/modules/std/eval.zzm +63 -0
- package/stdlib/modules/std/getopt.zzm +432 -0
- package/stdlib/modules/std/gui/dialogue.zzm +592 -0
- package/stdlib/modules/std/gui/objects.zzm +123 -0
- package/stdlib/modules/std/gui.zzm +1914 -0
- package/stdlib/modules/std/internals.zzm +139 -0
- package/stdlib/modules/std/io/socks.zzm +139 -0
- package/stdlib/modules/std/io.zzm +157 -0
- package/stdlib/modules/std/lingua/en.zzm +347 -0
- package/stdlib/modules/std/log.zzm +169 -0
- package/stdlib/modules/std/mail.zzm +2726 -0
- package/stdlib/modules/std/marshal.zzm +138 -0
- package/stdlib/modules/std/math/bignum.zzm +98 -0
- package/stdlib/modules/std/math/range.zzm +116 -0
- package/stdlib/modules/std/math/roman.zzm +156 -0
- package/stdlib/modules/std/math.zzm +141 -0
- package/stdlib/modules/std/net/dns.zzm +93 -0
- package/stdlib/modules/std/net/http.zzm +278 -0
- package/stdlib/modules/std/net/smtp.zzm +257 -0
- package/stdlib/modules/std/net/url.zzm +69 -0
- package/stdlib/modules/std/path/jsonpointer.zzm +526 -0
- package/stdlib/modules/std/path/kdl.zzm +1003 -0
- package/stdlib/modules/std/path/simple.zzm +520 -0
- package/stdlib/modules/std/path/z/context.zzm +147 -0
- package/stdlib/modules/std/path/z/evaluate.zzm +549 -0
- package/stdlib/modules/std/path/z/functions.zzm +874 -0
- package/stdlib/modules/std/path/z/lexer.zzm +490 -0
- package/stdlib/modules/std/path/z/node.zzm +1455 -0
- package/stdlib/modules/std/path/z/operators.zzm +445 -0
- package/stdlib/modules/std/path/z/parser.zzm +359 -0
- package/stdlib/modules/std/path/z.zzm +403 -0
- package/stdlib/modules/std/path/zz/functions.zzm +828 -0
- package/stdlib/modules/std/path/zz/operators.zzm +1036 -0
- package/stdlib/modules/std/path/zz.zzm +100 -0
- package/stdlib/modules/std/proc.zzm +155 -0
- package/stdlib/modules/std/result.zzm +149 -0
- package/stdlib/modules/std/secure.zzm +606 -0
- package/stdlib/modules/std/string/base64.zzm +66 -0
- package/stdlib/modules/std/string/quoted_printable.zzm +485 -0
- package/stdlib/modules/std/string.zzm +179 -0
- package/stdlib/modules/std/task.zzm +221 -0
- package/stdlib/modules/std/template/z.zzm +531 -0
- package/stdlib/modules/std/template/zz.zzm +62 -0
- package/stdlib/modules/std/time.zzm +188 -0
- package/stdlib/modules/std/tui.zzm +89 -0
- package/stdlib/modules/std/uuid.zzm +223 -0
- package/stdlib/modules/std/web/session.zzm +388 -0
- package/stdlib/modules/std/web/static.zzm +329 -0
- package/stdlib/modules/std/web.zzm +1942 -0
- package/stdlib/modules/std/worker.zzm +202 -0
- package/stdlib/modules/std/zuzuzoo.zzm +3960 -0
- package/stdlib/modules/test/more.zzm +528 -0
- package/stdlib/modules/test/parser.zzm +209 -0
|
@@ -0,0 +1,584 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const fs = require( 'node:fs' );
|
|
5
|
+
const path = require( 'node:path' );
|
|
6
|
+
const { collectStaticImports } = require( '../lib/compiler' );
|
|
7
|
+
const { stripPod } = require( '../lib/transpiler' );
|
|
8
|
+
const paths = require( '../lib/paths' );
|
|
9
|
+
|
|
10
|
+
const repoRoot = paths.projectRoot;
|
|
11
|
+
const jsRoot = paths.jsModuleRoot;
|
|
12
|
+
const pureRoot = paths.pureModuleRoot;
|
|
13
|
+
|
|
14
|
+
const DEFAULT_RUNTIME_JS_MODULES = [
|
|
15
|
+
'javascript',
|
|
16
|
+
'std/string',
|
|
17
|
+
'std/string/base64',
|
|
18
|
+
'std/time',
|
|
19
|
+
'std/marshal',
|
|
20
|
+
'std/task',
|
|
21
|
+
'std/worker',
|
|
22
|
+
'std/secure',
|
|
23
|
+
'std/data/json',
|
|
24
|
+
'std/data/yaml',
|
|
25
|
+
'std/data/csv',
|
|
26
|
+
'std/data/xml',
|
|
27
|
+
'std/digest/md5',
|
|
28
|
+
'std/digest/sha',
|
|
29
|
+
'std/net/http',
|
|
30
|
+
'std/math',
|
|
31
|
+
'std/math/bignum',
|
|
32
|
+
'std/eval',
|
|
33
|
+
'std/gui/objects',
|
|
34
|
+
'std/tui',
|
|
35
|
+
'std/internals',
|
|
36
|
+
'std/net/url',
|
|
37
|
+
];
|
|
38
|
+
|
|
39
|
+
const OPTIONAL_RUNTIME_JS_MODULES = [
|
|
40
|
+
'std/net/smtp',
|
|
41
|
+
];
|
|
42
|
+
|
|
43
|
+
const DEFAULT_PURE_ZUZU_MODULES = [
|
|
44
|
+
'std/colour',
|
|
45
|
+
'std/result',
|
|
46
|
+
'std/string/quoted_printable',
|
|
47
|
+
'std/gui',
|
|
48
|
+
'std/gui/dialogue',
|
|
49
|
+
'std/uuid',
|
|
50
|
+
'std/dump',
|
|
51
|
+
'std/data/cbor',
|
|
52
|
+
'std/data/kdl',
|
|
53
|
+
'std/data/kdl/json',
|
|
54
|
+
'std/data/kdl/xml',
|
|
55
|
+
'std/path/jsonpointer',
|
|
56
|
+
'std/data/json/schema',
|
|
57
|
+
'std/data/json/schema/core',
|
|
58
|
+
'std/data/json/schema/format',
|
|
59
|
+
'std/data/json/schema/model',
|
|
60
|
+
'std/data/json/schema/output',
|
|
61
|
+
'std/data/json/schema/relative_pointer',
|
|
62
|
+
'std/data/json/schema/validation',
|
|
63
|
+
'std/mail',
|
|
64
|
+
'std/data/xml/escape',
|
|
65
|
+
'std/path/simple',
|
|
66
|
+
'std/path/z',
|
|
67
|
+
'std/path/z/context',
|
|
68
|
+
'std/path/z/evaluate',
|
|
69
|
+
'std/path/z/functions',
|
|
70
|
+
'std/path/z/lexer',
|
|
71
|
+
'std/path/z/node',
|
|
72
|
+
'std/path/z/operators',
|
|
73
|
+
'std/path/z/parser',
|
|
74
|
+
'std/path/zz',
|
|
75
|
+
'std/path/zz/functions',
|
|
76
|
+
'std/path/zz/operators',
|
|
77
|
+
'std/template/z',
|
|
78
|
+
'std/template/zz',
|
|
79
|
+
];
|
|
80
|
+
|
|
81
|
+
const DEFAULT_RUNTIME_JS_SET = new Set( DEFAULT_RUNTIME_JS_MODULES );
|
|
82
|
+
const RUNTIME_JS_SET = new Set( [
|
|
83
|
+
...DEFAULT_RUNTIME_JS_MODULES,
|
|
84
|
+
...OPTIONAL_RUNTIME_JS_MODULES,
|
|
85
|
+
] );
|
|
86
|
+
|
|
87
|
+
const HELP_TEXT = [
|
|
88
|
+
'Usage: zuzu-generate-browser-stdlib [OUT_DIR] [OPTIONS]',
|
|
89
|
+
'',
|
|
90
|
+
'Generate browser stdlib support files for the ZuzuScript JS browser bundle.',
|
|
91
|
+
'',
|
|
92
|
+
'Options:',
|
|
93
|
+
' -M DIR Add a pure ZuzuScript module directory.',
|
|
94
|
+
' -MDIR Add a pure ZuzuScript module directory.',
|
|
95
|
+
' --include MODULE Include an additional module.',
|
|
96
|
+
' --include=MODULE Include an additional module.',
|
|
97
|
+
' --exclude MODULE Exclude a bundled module.',
|
|
98
|
+
' --exclude=MODULE Exclude a bundled module.',
|
|
99
|
+
' --help Show this help text.',
|
|
100
|
+
'',
|
|
101
|
+
'Examples:',
|
|
102
|
+
' zuzu-generate-browser-stdlib /tmp/zuzu-browser',
|
|
103
|
+
' zuzu-generate-browser-stdlib /tmp/zuzu-browser -M lib/zuzu --include=app/main',
|
|
104
|
+
].join( '\n' );
|
|
105
|
+
|
|
106
|
+
function usageError( message ) {
|
|
107
|
+
console.error( `zuzu-generate-browser-stdlib: ${message}` );
|
|
108
|
+
process.exit( 1 );
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function printHelp() {
|
|
112
|
+
console.log( HELP_TEXT );
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function normalizeModuleName( value, context ) {
|
|
116
|
+
const name = String( value ?? '' ).trim();
|
|
117
|
+
if ( name === '' ) {
|
|
118
|
+
usageError( `${context} must not be empty` );
|
|
119
|
+
}
|
|
120
|
+
if (
|
|
121
|
+
path.isAbsolute( name )
|
|
122
|
+
|| name.startsWith( '/' )
|
|
123
|
+
|| /^[A-Za-z]:[\\/]/u.test( name )
|
|
124
|
+
) {
|
|
125
|
+
usageError( `${context} must not be an absolute path: ${name}` );
|
|
126
|
+
}
|
|
127
|
+
const parts = name.split( '/' );
|
|
128
|
+
if ( parts.some( (part) => part === '' ) ) {
|
|
129
|
+
usageError( `${context} contains an empty path segment: ${name}` );
|
|
130
|
+
}
|
|
131
|
+
if ( parts.some( (part) => part === '..' ) ) {
|
|
132
|
+
usageError( `${context} must not contain '..' segments: ${name}` );
|
|
133
|
+
}
|
|
134
|
+
return name.replace( /\.(?:zzm|zzs|js)$/u, '' );
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function parseArgs( argv ) {
|
|
138
|
+
const options = {
|
|
139
|
+
outDir: null,
|
|
140
|
+
moduleRoots: [],
|
|
141
|
+
includes: [],
|
|
142
|
+
excludes: new Set(),
|
|
143
|
+
};
|
|
144
|
+
for ( let i = 0; i < argv.length; i++ ) {
|
|
145
|
+
const arg = argv[i];
|
|
146
|
+
if ( arg === '--help' ) {
|
|
147
|
+
printHelp();
|
|
148
|
+
process.exit( 0 );
|
|
149
|
+
}
|
|
150
|
+
else if ( arg === '-M' ) {
|
|
151
|
+
if ( i + 1 >= argv.length ) {
|
|
152
|
+
usageError( '-M requires a directory value' );
|
|
153
|
+
}
|
|
154
|
+
options.moduleRoots.push( path.resolve( argv[++i] ) );
|
|
155
|
+
}
|
|
156
|
+
else if ( arg.startsWith( '-M' ) && arg.length > 2 ) {
|
|
157
|
+
options.moduleRoots.push( path.resolve( arg.slice( 2 ) ) );
|
|
158
|
+
}
|
|
159
|
+
else if ( arg === '--include' ) {
|
|
160
|
+
if ( i + 1 >= argv.length ) {
|
|
161
|
+
usageError( '--include requires a module name' );
|
|
162
|
+
}
|
|
163
|
+
options.includes.push(
|
|
164
|
+
normalizeModuleName( argv[++i], '--include' )
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
else if ( arg.startsWith( '--include=' ) ) {
|
|
168
|
+
options.includes.push(
|
|
169
|
+
normalizeModuleName( arg.slice( '--include='.length ), '--include' )
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
else if ( arg === '--exclude' ) {
|
|
173
|
+
if ( i + 1 >= argv.length ) {
|
|
174
|
+
usageError( '--exclude requires a module name' );
|
|
175
|
+
}
|
|
176
|
+
options.excludes.add(
|
|
177
|
+
normalizeModuleName( argv[++i], '--exclude' )
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
else if ( arg.startsWith( '--exclude=' ) ) {
|
|
181
|
+
options.excludes.add(
|
|
182
|
+
normalizeModuleName( arg.slice( '--exclude='.length ), '--exclude' )
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
else if ( arg.startsWith( '-' ) ) {
|
|
186
|
+
usageError( `unknown option: ${arg}` );
|
|
187
|
+
}
|
|
188
|
+
else if ( options.outDir === null ) {
|
|
189
|
+
options.outDir = path.resolve( arg );
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
usageError( `unexpected positional argument: ${arg}` );
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
options.outDir ||= paths.distRoot;
|
|
196
|
+
return options;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function generatedPathForJsModule( logicalName ) {
|
|
200
|
+
return `/modules/${logicalName}.js`;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function generatedPathForRepoPureModule( logicalName, ext ) {
|
|
204
|
+
return `/modules/${logicalName}${ext}`;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function generatedPathForCustomPureModule( rootIndex, logicalName, ext ) {
|
|
208
|
+
return `/__zuzu_browser_modules__/${rootIndex}/${logicalName}${ext}`;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
function requirePathFromOutDir( outDir, target ) {
|
|
212
|
+
let requirePath = path.relative( outDir, target ).replace( /\\/g, '/' );
|
|
213
|
+
if ( !requirePath.startsWith( '.' ) ) {
|
|
214
|
+
requirePath = `./${requirePath}`;
|
|
215
|
+
}
|
|
216
|
+
return requirePath;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function sourceIsPodOnly( source ) {
|
|
220
|
+
return stripPod( source ).trim() === '';
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
function fileIfExists( filename ) {
|
|
224
|
+
return fs.existsSync( filename ) && fs.statSync( filename ).isFile()
|
|
225
|
+
? filename
|
|
226
|
+
: null;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function resolveRuntimeModule( logicalName ) {
|
|
230
|
+
if ( !RUNTIME_JS_SET.has( logicalName ) ) {
|
|
231
|
+
return null;
|
|
232
|
+
}
|
|
233
|
+
const sourcePath = path.join( jsRoot, `${logicalName}.js` );
|
|
234
|
+
if ( !fileIfExists( sourcePath ) ) {
|
|
235
|
+
throw new Error( `Missing browser JS std module: ${sourcePath}` );
|
|
236
|
+
}
|
|
237
|
+
return {
|
|
238
|
+
logicalName,
|
|
239
|
+
type: 'runtime-js',
|
|
240
|
+
sourcePath,
|
|
241
|
+
generatedPath: generatedPathForJsModule( logicalName ),
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
function resolvePureModule( logicalName, moduleRoots ) {
|
|
246
|
+
const roots = [ pureRoot, ...moduleRoots ];
|
|
247
|
+
for ( let i = 0; i < roots.length; i++ ) {
|
|
248
|
+
for ( const ext of [ '.zzm', '.zzs' ] ) {
|
|
249
|
+
const sourcePath = fileIfExists(
|
|
250
|
+
path.join( roots[i], `${logicalName}${ext}` )
|
|
251
|
+
);
|
|
252
|
+
if ( sourcePath ) {
|
|
253
|
+
const source = fs.readFileSync( sourcePath, 'utf8' );
|
|
254
|
+
if ( i === 0 && sourceIsPodOnly( source ) ) {
|
|
255
|
+
throw new Error(
|
|
256
|
+
`Module '${logicalName}' is runtime-supported and is not available in the browser bundle`
|
|
257
|
+
);
|
|
258
|
+
}
|
|
259
|
+
return {
|
|
260
|
+
logicalName,
|
|
261
|
+
type: 'pure-zuzu',
|
|
262
|
+
sourcePath,
|
|
263
|
+
source,
|
|
264
|
+
generatedPath: i === 0
|
|
265
|
+
? generatedPathForRepoPureModule( logicalName, ext )
|
|
266
|
+
: generatedPathForCustomPureModule( i - 1, logicalName, ext ),
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
return null;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
function resolveModule( logicalName, moduleRoots ) {
|
|
275
|
+
return resolveRuntimeModule( logicalName )
|
|
276
|
+
|| resolvePureModule( logicalName, moduleRoots );
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
function resolveImportedModuleName( value, requiringLogicalName ) {
|
|
280
|
+
const normalized = normalizeModuleName( value, 'import module' );
|
|
281
|
+
if ( !normalized.startsWith( '.' ) ) {
|
|
282
|
+
return normalized;
|
|
283
|
+
}
|
|
284
|
+
const baseDir = requiringLogicalName.includes( '/' )
|
|
285
|
+
? path.posix.dirname( requiringLogicalName )
|
|
286
|
+
: '';
|
|
287
|
+
const logicalName = path.posix.normalize(
|
|
288
|
+
path.posix.join( baseDir, normalized )
|
|
289
|
+
);
|
|
290
|
+
if ( logicalName === '.' || logicalName.startsWith( '../' ) ) {
|
|
291
|
+
usageError(
|
|
292
|
+
`import module must not escape the requiring module directory: ${value}`
|
|
293
|
+
);
|
|
294
|
+
}
|
|
295
|
+
return normalizeModuleName( logicalName, 'import module' );
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
function collectImports( source, requiringLogicalName ) {
|
|
299
|
+
const imports = [];
|
|
300
|
+
for ( const imported of collectStaticImports( source ) ) {
|
|
301
|
+
try {
|
|
302
|
+
imports.push( {
|
|
303
|
+
logicalName: resolveImportedModuleName(
|
|
304
|
+
imported.source,
|
|
305
|
+
requiringLogicalName
|
|
306
|
+
),
|
|
307
|
+
tryMode: Boolean( imported.tryMode ),
|
|
308
|
+
} );
|
|
309
|
+
}
|
|
310
|
+
catch ( err ) {
|
|
311
|
+
throw new Error( `${err.message} in import '${imported.source}'` );
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
return imports;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
function resolveModuleSafe( logicalName, moduleRoots ) {
|
|
318
|
+
try {
|
|
319
|
+
return resolveModule( logicalName, moduleRoots );
|
|
320
|
+
}
|
|
321
|
+
catch ( _err ) {
|
|
322
|
+
return null;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
function excludedImportError( importedName, requiringModule ) {
|
|
327
|
+
return new Error(
|
|
328
|
+
`Excluded required module '${importedName}' required by '${requiringModule.logicalName}' in ${requiringModule.sourcePath}`
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
function checkExcludedDependencies( modules, options ) {
|
|
333
|
+
for ( const mod of modules ) {
|
|
334
|
+
if ( mod.type !== 'pure-zuzu' ) {
|
|
335
|
+
continue;
|
|
336
|
+
}
|
|
337
|
+
for ( const imported of collectImports( mod.source, mod.logicalName ) ) {
|
|
338
|
+
if ( !options.excludes.has( imported.logicalName ) ) {
|
|
339
|
+
continue;
|
|
340
|
+
}
|
|
341
|
+
if (
|
|
342
|
+
imported.tryMode
|
|
343
|
+
&& !resolveModuleSafe( imported.logicalName, options.moduleRoots )
|
|
344
|
+
) {
|
|
345
|
+
continue;
|
|
346
|
+
}
|
|
347
|
+
throw excludedImportError( imported.logicalName, mod );
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
function discoverModules( options ) {
|
|
353
|
+
const modules = new Map();
|
|
354
|
+
const excludedDefaults = new Set();
|
|
355
|
+
const queue = [];
|
|
356
|
+
const queued = new Map();
|
|
357
|
+
|
|
358
|
+
function enqueue( logicalName, requestedBy = null, discover = true ) {
|
|
359
|
+
if ( modules.has( logicalName ) ) {
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
362
|
+
const pending = queued.get( logicalName );
|
|
363
|
+
if ( pending ) {
|
|
364
|
+
pending.discover ||= discover;
|
|
365
|
+
pending.requestedBy ||= requestedBy;
|
|
366
|
+
return;
|
|
367
|
+
}
|
|
368
|
+
const item = { logicalName, requestedBy, discover };
|
|
369
|
+
queued.set( logicalName, item );
|
|
370
|
+
queue.push( item );
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
for ( const logicalName of DEFAULT_RUNTIME_JS_MODULES ) {
|
|
374
|
+
if ( options.excludes.has( logicalName ) ) {
|
|
375
|
+
excludedDefaults.add( logicalName );
|
|
376
|
+
}
|
|
377
|
+
else {
|
|
378
|
+
enqueue( logicalName, null, false );
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
for ( const logicalName of DEFAULT_PURE_ZUZU_MODULES ) {
|
|
382
|
+
if ( options.excludes.has( logicalName ) ) {
|
|
383
|
+
excludedDefaults.add( logicalName );
|
|
384
|
+
}
|
|
385
|
+
else {
|
|
386
|
+
enqueue( logicalName, null, false );
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
for ( const logicalName of options.includes ) {
|
|
390
|
+
enqueue( logicalName, null, true );
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
while ( queue.length > 0 ) {
|
|
394
|
+
const request = queue.shift();
|
|
395
|
+
queued.delete( request.logicalName );
|
|
396
|
+
if ( modules.has( request.logicalName ) ) {
|
|
397
|
+
continue;
|
|
398
|
+
}
|
|
399
|
+
const resolved = resolveModule( request.logicalName, options.moduleRoots );
|
|
400
|
+
if ( !resolved ) {
|
|
401
|
+
const from = request.requestedBy
|
|
402
|
+
? ` required by '${request.requestedBy.logicalName}' in ${request.requestedBy.sourcePath}`
|
|
403
|
+
: '';
|
|
404
|
+
throw new Error(
|
|
405
|
+
`Unable to resolve browser module '${request.logicalName}'${from}`
|
|
406
|
+
);
|
|
407
|
+
}
|
|
408
|
+
if ( options.excludes.has( request.logicalName ) ) {
|
|
409
|
+
const from = request.requestedBy
|
|
410
|
+
? `'${request.requestedBy.logicalName}' (${request.requestedBy.sourcePath})`
|
|
411
|
+
: 'explicit include/default set';
|
|
412
|
+
throw new Error(
|
|
413
|
+
`Excluded required module '${request.logicalName}' required by ${from}`
|
|
414
|
+
);
|
|
415
|
+
}
|
|
416
|
+
modules.set( request.logicalName, resolved );
|
|
417
|
+
if ( !request.discover || resolved.type !== 'pure-zuzu' ) {
|
|
418
|
+
continue;
|
|
419
|
+
}
|
|
420
|
+
for ( const imported of collectImports( resolved.source, resolved.logicalName ) ) {
|
|
421
|
+
if ( options.excludes.has( imported.logicalName ) ) {
|
|
422
|
+
if (
|
|
423
|
+
imported.tryMode
|
|
424
|
+
&& !resolveModuleSafe( imported.logicalName, options.moduleRoots )
|
|
425
|
+
) {
|
|
426
|
+
continue;
|
|
427
|
+
}
|
|
428
|
+
throw excludedImportError( imported.logicalName, resolved );
|
|
429
|
+
}
|
|
430
|
+
let dependency;
|
|
431
|
+
try {
|
|
432
|
+
dependency = resolveModule(
|
|
433
|
+
imported.logicalName,
|
|
434
|
+
options.moduleRoots
|
|
435
|
+
);
|
|
436
|
+
}
|
|
437
|
+
catch ( err ) {
|
|
438
|
+
if ( imported.tryMode ) {
|
|
439
|
+
continue;
|
|
440
|
+
}
|
|
441
|
+
throw err;
|
|
442
|
+
}
|
|
443
|
+
if ( !dependency ) {
|
|
444
|
+
if ( imported.tryMode ) {
|
|
445
|
+
continue;
|
|
446
|
+
}
|
|
447
|
+
throw new Error(
|
|
448
|
+
`Unable to resolve browser module '${imported.logicalName}' required by '${resolved.logicalName}' in ${resolved.sourcePath}`
|
|
449
|
+
);
|
|
450
|
+
}
|
|
451
|
+
enqueue( imported.logicalName, resolved, true );
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
for ( const logicalName of excludedDefaults ) {
|
|
456
|
+
modules.delete( logicalName );
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
const discovered = [ ...modules.values() ];
|
|
460
|
+
checkExcludedDependencies( discovered, options );
|
|
461
|
+
return discovered;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
function emitBrowserStdlib( outDir, modules, customRootCount ) {
|
|
465
|
+
fs.mkdirSync( outDir, { recursive: true } );
|
|
466
|
+
|
|
467
|
+
const lines = [
|
|
468
|
+
"'use strict';",
|
|
469
|
+
'',
|
|
470
|
+
'function createBrowserStdlib() {',
|
|
471
|
+
'\tconst jsModules = Object.create( null );',
|
|
472
|
+
];
|
|
473
|
+
|
|
474
|
+
for ( const mod of modules.filter( (item) => item.type === 'runtime-js' ) ) {
|
|
475
|
+
const requirePath = requirePathFromOutDir( outDir, mod.sourcePath );
|
|
476
|
+
lines.push(
|
|
477
|
+
`\tjsModules[${JSON.stringify( mod.generatedPath )}] = require( ${JSON.stringify( requirePath )} );`
|
|
478
|
+
);
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
lines.push(
|
|
482
|
+
'\tconst virtualFiles = Object.create( null );'
|
|
483
|
+
);
|
|
484
|
+
|
|
485
|
+
for ( const mod of modules.filter( (item) => item.type === 'pure-zuzu' ) ) {
|
|
486
|
+
const source = mod.source.replace( /[ \t]+$/gmu, '' );
|
|
487
|
+
lines.push(
|
|
488
|
+
`\tvirtualFiles[${JSON.stringify( mod.generatedPath )}] = ${JSON.stringify( source )};`
|
|
489
|
+
);
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
const includePaths = [];
|
|
493
|
+
for ( let i = 0; i < customRootCount; i++ ) {
|
|
494
|
+
includePaths.push( `/__zuzu_browser_modules__/${i}` );
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
lines.push(
|
|
498
|
+
'\treturn {',
|
|
499
|
+
"\t\trepoRoot: '/',",
|
|
500
|
+
`\t\tincludePaths: ${JSON.stringify( includePaths )},`,
|
|
501
|
+
'\t\tjsModules,',
|
|
502
|
+
'\t\tvirtualFiles,',
|
|
503
|
+
'\t};',
|
|
504
|
+
'}',
|
|
505
|
+
'',
|
|
506
|
+
'module.exports = {',
|
|
507
|
+
'\tcreateBrowserStdlib,',
|
|
508
|
+
'};',
|
|
509
|
+
''
|
|
510
|
+
);
|
|
511
|
+
|
|
512
|
+
fs.writeFileSync(
|
|
513
|
+
path.join( outDir, 'browser-stdlib.generated.js' ),
|
|
514
|
+
`${lines.join( '\n' )}\n`,
|
|
515
|
+
'utf8'
|
|
516
|
+
);
|
|
517
|
+
|
|
518
|
+
fs.writeFileSync(
|
|
519
|
+
path.join( outDir, 'browser-worker-source.generated.js' ),
|
|
520
|
+
[
|
|
521
|
+
"'use strict';",
|
|
522
|
+
'',
|
|
523
|
+
'module.exports = {',
|
|
524
|
+
"\tbrowserWorkerSource: '',",
|
|
525
|
+
'};',
|
|
526
|
+
'',
|
|
527
|
+
].join( '\n' ),
|
|
528
|
+
'utf8'
|
|
529
|
+
);
|
|
530
|
+
|
|
531
|
+
fs.writeFileSync(
|
|
532
|
+
path.join( outDir, 'browser-bundle-entry.generated.js' ),
|
|
533
|
+
[
|
|
534
|
+
"'use strict';",
|
|
535
|
+
'',
|
|
536
|
+
"const { createBrowserStdlib } = require( './browser-stdlib.generated' );",
|
|
537
|
+
"const { browserWorkerSource } = require( './browser-worker-source.generated' );",
|
|
538
|
+
'',
|
|
539
|
+
'const browserStdlib = createBrowserStdlib();',
|
|
540
|
+
'browserStdlib.workerSource = browserWorkerSource;',
|
|
541
|
+
'globalThis.__ZUZU_BROWSER_DEFAULT_RUNTIME_OPTIONS__ = browserStdlib;',
|
|
542
|
+
`module.exports = require( ${JSON.stringify( requirePathFromOutDir( outDir, path.join( repoRoot, 'lib', 'browser-bundle-entry.js' ) ) )} );`,
|
|
543
|
+
'',
|
|
544
|
+
].join( '\n' ),
|
|
545
|
+
'utf8'
|
|
546
|
+
);
|
|
547
|
+
|
|
548
|
+
fs.writeFileSync(
|
|
549
|
+
path.join( outDir, 'browser-worker-entry.generated.js' ),
|
|
550
|
+
[
|
|
551
|
+
"'use strict';",
|
|
552
|
+
'',
|
|
553
|
+
"const { createBrowserStdlib } = require( './browser-stdlib.generated' );",
|
|
554
|
+
'',
|
|
555
|
+
'globalThis.__ZUZU_BROWSER_DEFAULT_RUNTIME_OPTIONS__ = createBrowserStdlib();',
|
|
556
|
+
`const { installBrowserWorker } = require( ${JSON.stringify( requirePathFromOutDir( outDir, path.join( repoRoot, 'lib', 'browser-worker-entry.js' ) ) )} );`,
|
|
557
|
+
'installBrowserWorker( globalThis.__ZUZU_BROWSER_DEFAULT_RUNTIME_OPTIONS__ );',
|
|
558
|
+
'',
|
|
559
|
+
].join( '\n' ),
|
|
560
|
+
'utf8'
|
|
561
|
+
);
|
|
562
|
+
|
|
563
|
+
console.log( `Generated ${path.join( outDir, 'browser-stdlib.generated.js' )}` );
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
function main() {
|
|
567
|
+
const options = parseArgs( process.argv.slice( 2 ) );
|
|
568
|
+
try {
|
|
569
|
+
const modules = discoverModules( options );
|
|
570
|
+
console.error( 'Bundling ZuzuScript browser modules:' );
|
|
571
|
+
for ( const mod of modules ) {
|
|
572
|
+
console.error(
|
|
573
|
+
`${mod.logicalName}\t${mod.type}\t${mod.sourcePath}`
|
|
574
|
+
);
|
|
575
|
+
}
|
|
576
|
+
emitBrowserStdlib( options.outDir, modules, options.moduleRoots.length );
|
|
577
|
+
}
|
|
578
|
+
catch ( err ) {
|
|
579
|
+
console.error( `zuzu-generate-browser-stdlib: ${err.message}` );
|
|
580
|
+
process.exit( 1 );
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
main();
|
package/bin/zuzu-js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const { createNodeRuntime } = require( '../lib/runtime-entrypoints' );
|
|
5
|
+
const { runCliAsync } = require( '../lib/cli' );
|
|
6
|
+
const paths = require( '../lib/paths' );
|
|
7
|
+
|
|
8
|
+
runCliAsync( process.argv.slice( 2 ), ( options ) => createNodeRuntime( {
|
|
9
|
+
repoRoot: paths.projectRoot,
|
|
10
|
+
includePaths: options.includePaths,
|
|
11
|
+
denyCapabilities: options.denyCapabilities,
|
|
12
|
+
denyModules: options.denyModules,
|
|
13
|
+
debugLevel: options.debugLevel,
|
|
14
|
+
transpiler: options.transpiler,
|
|
15
|
+
} ) ).then(
|
|
16
|
+
(exitCode) => {
|
|
17
|
+
process.exitCode = exitCode;
|
|
18
|
+
},
|
|
19
|
+
(err) => {
|
|
20
|
+
process.stderr.write( `${err && err.stack ? err.stack : String( err )}\n` );
|
|
21
|
+
process.exitCode = 1;
|
|
22
|
+
},
|
|
23
|
+
);
|