@jsenv/core 27.0.0-alpha.93 → 27.0.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/README.md +62 -0
- package/dist/js/s.js +580 -380
- package/dist/js/s.js.map +207 -0
- package/dist/main.js +4834 -456
- package/package.json +10 -10
- package/src/build/build.js +1 -1
- package/src/build/start_build_server.js +46 -44
- package/src/dev/plugins/toolbar/client/jsenv_logo.svg +59 -63
- package/src/dev/start_dev_server.js +62 -52
- package/src/omega/kitchen.js +1 -0
- package/src/omega/server/file_service.js +8 -1
- package/src/omega/url_graph.js +43 -21
- package/src/plugins/node_esm_resolution/jsenv_plugin_node_esm_resolution.js +48 -48
- package/src/plugins/plugin_controller.js +1 -0
- package/src/plugins/plugins.js +5 -0
- package/src/plugins/transpilation/as_js_classic/async-to-promises.js +3844 -0
- package/src/plugins/transpilation/as_js_classic/client/s.js +63 -54
- package/src/plugins/transpilation/as_js_classic/helpers-string.js +1 -0
- package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic.js +5 -3
- package/src/plugins/transpilation/jsenv_plugin_top_level_await.js +8 -0
- package/src/test/coverage/coverage_reporter_html_directory.js +8 -12
- package/src/test/coverage/coverage_reporter_json_file.js +5 -10
- package/src/test/coverage/coverage_reporter_text_log.js +3 -3
- package/src/test/execute_plan.js +13 -14
- package/src/test/execute_test_plan.js +35 -30
- package/dist/s.js +0 -626
- package/dist/s.js.map +0 -205
- package/readme.md +0 -372
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* This file is a modified version of https://github.com/systemjs/systemjs/blob/main/dist/s.js
|
|
3
3
|
* with the following changes:
|
|
4
4
|
*
|
|
5
|
-
* - Code can use aync/await, const,
|
|
5
|
+
* - Code can use aync/await, const, etc because this file is compiled (see dist/s.js)
|
|
6
6
|
* - Can use document.currentScript because we don't support IE
|
|
7
7
|
* - auto import inline System.register
|
|
8
8
|
* - auto import first System.register in web workers
|
|
@@ -43,7 +43,9 @@
|
|
|
43
43
|
}
|
|
44
44
|
System.register = (deps, declare) => {
|
|
45
45
|
if (!document.currentScript) {
|
|
46
|
-
throw new Error(
|
|
46
|
+
throw new Error(
|
|
47
|
+
"unexpected call to System.register (document.currentScript is undefined)",
|
|
48
|
+
)
|
|
47
49
|
}
|
|
48
50
|
if (document.currentScript.__s__) {
|
|
49
51
|
registerRegistry[document.currentScript.src] = [deps, declare]
|
|
@@ -169,7 +171,9 @@
|
|
|
169
171
|
|
|
170
172
|
System.register = async (deps, declare) => {
|
|
171
173
|
System.register = () => {
|
|
172
|
-
throw new Error(
|
|
174
|
+
throw new Error(
|
|
175
|
+
"unexpected call to System.register (called outside url instantiation)",
|
|
176
|
+
)
|
|
173
177
|
}
|
|
174
178
|
const url = self.location.href
|
|
175
179
|
registerRegistry[url] = [deps, declare]
|
|
@@ -203,7 +207,7 @@
|
|
|
203
207
|
const _import = (specifier, parentUrl) => {
|
|
204
208
|
const url = resolveUrl(specifier, parentUrl)
|
|
205
209
|
const load = getOrCreateLoad(url, parentUrl)
|
|
206
|
-
return load.completionPromise || startExecution(load)
|
|
210
|
+
return load.completionPromise || startExecution(load, parentUrl)
|
|
207
211
|
}
|
|
208
212
|
|
|
209
213
|
const getOrCreateLoad = (url, firstParentUrl) => {
|
|
@@ -211,18 +215,23 @@
|
|
|
211
215
|
if (existingLoad) {
|
|
212
216
|
return existingLoad
|
|
213
217
|
}
|
|
214
|
-
|
|
218
|
+
const namespace = createNamespace()
|
|
215
219
|
const load = {
|
|
216
220
|
url,
|
|
221
|
+
deps: [],
|
|
222
|
+
dependencyLoads: [],
|
|
223
|
+
instantiatePromise: null,
|
|
224
|
+
linkPromise: null,
|
|
225
|
+
executePromise: null,
|
|
226
|
+
completionPromise: null,
|
|
227
|
+
importerSetters: [],
|
|
228
|
+
setters: [],
|
|
229
|
+
execute: null,
|
|
230
|
+
error: null,
|
|
231
|
+
hoistedExports: false,
|
|
232
|
+
namespace,
|
|
217
233
|
}
|
|
218
234
|
loadRegistry[url] = load
|
|
219
|
-
|
|
220
|
-
const importerSetters = []
|
|
221
|
-
load.importerSetters = importerSetters
|
|
222
|
-
|
|
223
|
-
const namespace = createNamespace()
|
|
224
|
-
load.namespace = namespace
|
|
225
|
-
|
|
226
235
|
load.instantiatePromise = (async () => {
|
|
227
236
|
try {
|
|
228
237
|
let registration = registerRegistry[url]
|
|
@@ -260,7 +269,7 @@
|
|
|
260
269
|
}
|
|
261
270
|
}
|
|
262
271
|
if (changed) {
|
|
263
|
-
importerSetters.forEach((importerSetter) => {
|
|
272
|
+
load.importerSetters.forEach((importerSetter) => {
|
|
264
273
|
if (importerSetter) {
|
|
265
274
|
importerSetter(namespace)
|
|
266
275
|
}
|
|
@@ -281,7 +290,6 @@
|
|
|
281
290
|
load.execute = null
|
|
282
291
|
}
|
|
283
292
|
})()
|
|
284
|
-
|
|
285
293
|
load.linkPromise = (async () => {
|
|
286
294
|
await load.instantiatePromise
|
|
287
295
|
const dependencyLoads = await Promise.all(
|
|
@@ -306,14 +314,13 @@
|
|
|
306
314
|
)
|
|
307
315
|
load.dependencyLoads = dependencyLoads
|
|
308
316
|
})()
|
|
309
|
-
|
|
310
317
|
return load
|
|
311
318
|
}
|
|
312
319
|
|
|
313
|
-
const startExecution = async (load) => {
|
|
320
|
+
const startExecution = async (load, importerUrl) => {
|
|
314
321
|
load.completionPromise = (async () => {
|
|
315
322
|
await instantiateAll(load, load, {})
|
|
316
|
-
await postOrderExec(load,
|
|
323
|
+
await postOrderExec(load, importerUrl ? [importerUrl]: [])
|
|
317
324
|
return load.namespace
|
|
318
325
|
})()
|
|
319
326
|
return load.completionPromise
|
|
@@ -329,9 +336,6 @@
|
|
|
329
336
|
// load.linkPromise is null once instantiated
|
|
330
337
|
await load.linkPromise
|
|
331
338
|
}
|
|
332
|
-
// if (!load.parent || !load.parent.execute) {
|
|
333
|
-
// load.parent = parent
|
|
334
|
-
// }
|
|
335
339
|
await Promise.all(
|
|
336
340
|
load.dependencyLoads.map((dependencyLoad) => {
|
|
337
341
|
return instantiateAll(dependencyLoad, parent, loaded)
|
|
@@ -346,26 +350,27 @@
|
|
|
346
350
|
}
|
|
347
351
|
}
|
|
348
352
|
|
|
349
|
-
const postOrderExec =
|
|
350
|
-
if (
|
|
351
|
-
return
|
|
353
|
+
const postOrderExec = (load, importStack) => {
|
|
354
|
+
if (importStack.indexOf(load.url) > -1) {
|
|
355
|
+
return undefined
|
|
352
356
|
}
|
|
353
|
-
seen[load.url] = true
|
|
354
357
|
if (!load.execute) {
|
|
355
358
|
if (load.error) {
|
|
356
359
|
throw load.error
|
|
357
360
|
}
|
|
358
361
|
if (load.executePromise) {
|
|
359
|
-
|
|
362
|
+
return load.executePromise
|
|
360
363
|
}
|
|
361
|
-
return
|
|
364
|
+
return undefined
|
|
362
365
|
}
|
|
363
366
|
|
|
364
367
|
// deps execute first, unless circular
|
|
365
368
|
const depLoadPromises = []
|
|
366
369
|
load.dependencyLoads.forEach((dependencyLoad) => {
|
|
367
370
|
try {
|
|
368
|
-
const
|
|
371
|
+
const depImportStack = importStack.slice()
|
|
372
|
+
depImportStack.push(load.url)
|
|
373
|
+
const depLoadPromise = postOrderExec(dependencyLoad, depImportStack)
|
|
369
374
|
if (depLoadPromise) {
|
|
370
375
|
depLoadPromises.push(depLoadPromise)
|
|
371
376
|
}
|
|
@@ -375,35 +380,39 @@
|
|
|
375
380
|
throw err
|
|
376
381
|
}
|
|
377
382
|
})
|
|
378
|
-
if (depLoadPromises.length) {
|
|
379
|
-
await Promise.all(depLoadPromises)
|
|
380
|
-
}
|
|
381
383
|
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
() => {
|
|
387
|
-
load.executePromise = null
|
|
388
|
-
load.completionPromise = load.namespace
|
|
389
|
-
},
|
|
390
|
-
(error) => {
|
|
391
|
-
load.executePromise = null
|
|
392
|
-
load.error = error
|
|
393
|
-
throw error
|
|
394
|
-
},
|
|
395
|
-
)
|
|
396
|
-
return
|
|
384
|
+
return (async () => {
|
|
385
|
+
if (depLoadPromises.length) {
|
|
386
|
+
const allDepPromise = Promise.all(depLoadPromises)
|
|
387
|
+
await allDepPromise
|
|
397
388
|
}
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
389
|
+
|
|
390
|
+
try {
|
|
391
|
+
const executeReturnValue = load.execute.call(nullContext)
|
|
392
|
+
if (executeReturnValue) {
|
|
393
|
+
load.executePromise = executeReturnValue.then(
|
|
394
|
+
() => {
|
|
395
|
+
load.executePromise = null
|
|
396
|
+
load.completionPromise = load.namespace
|
|
397
|
+
},
|
|
398
|
+
(error) => {
|
|
399
|
+
load.executePromise = null
|
|
400
|
+
load.error = error
|
|
401
|
+
throw error
|
|
402
|
+
},
|
|
403
|
+
)
|
|
404
|
+
return
|
|
405
|
+
}
|
|
406
|
+
load.instantiatePromise = null
|
|
407
|
+
load.linkPromise = null
|
|
408
|
+
load.completionPromise = load.namespace
|
|
409
|
+
} catch (error) {
|
|
410
|
+
load.error = error
|
|
411
|
+
throw error
|
|
412
|
+
} finally {
|
|
413
|
+
load.execute = null
|
|
414
|
+
}
|
|
415
|
+
})()
|
|
407
416
|
}
|
|
408
417
|
|
|
409
418
|
// the closest we can get to call(undefined)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default '// A type of promise-like that resolves synchronously and supports only one observer\nexport const _Pact = /*#__PURE__*/(function() {\n\tfunction _Pact() {}\n\t_Pact.prototype.then = function(onFulfilled, onRejected) {\n\t\tconst result = new _Pact();\n\t\tconst state = this.s;\n\t\tif (state) {\n\t\t\tconst callback = state & 1 ? onFulfilled : onRejected;\n\t\t\tif (callback) {\n\t\t\t\ttry {\n\t\t\t\t\t_settle(result, 1, callback(this.v));\n\t\t\t\t} catch (e) {\n\t\t\t\t\t_settle(result, 2, e);\n\t\t\t\t}\n\t\t\t\treturn result;\n\t\t\t} else {\n\t\t\t\treturn this;\n\t\t\t}\n\t\t}\n\t\tthis.o = function(_this) {\n\t\t\ttry {\n\t\t\t\tconst value = _this.v;\n\t\t\t\tif (_this.s & 1) {\n\t\t\t\t\t_settle(result, 1, onFulfilled ? onFulfilled(value) : value);\n\t\t\t\t} else if (onRejected) {\n\t\t\t\t\t_settle(result, 1, onRejected(value));\n\t\t\t\t} else {\n\t\t\t\t\t_settle(result, 2, value);\n\t\t\t\t}\n\t\t\t} catch (e) {\n\t\t\t\t_settle(result, 2, e);\n\t\t\t}\n\t\t};\n\t\treturn result;\n\t}\n\treturn _Pact;\n})();\n\n// Settles a pact synchronously\nexport function _settle(pact, state, value) {\n\tif (!pact.s) {\n\t\tif (value instanceof _Pact) {\n\t\t\tif (value.s) {\n\t\t\t\tif (state & 1) {\n\t\t\t\t\tstate = value.s;\n\t\t\t\t}\n\t\t\t\tvalue = value.v;\n\t\t\t} else {\n\t\t\t\tvalue.o = _settle.bind(null, pact, state);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tif (value && value.then) {\n\t\t\tvalue.then(_settle.bind(null, pact, state), _settle.bind(null, pact, 2));\n\t\t\treturn;\n\t\t}\n\t\tpact.s = state;\n\t\tpact.v = value;\n\t\tconst observer = pact.o;\n\t\tif (observer) {\n\t\t\tobserver(pact);\n\t\t}\n\t}\n}\n\nexport function _isSettledPact(thenable) {\n\treturn thenable instanceof _Pact && thenable.s & 1;\n}\n\n// Converts argument to a function that always returns a Promise\nexport function _async(f) {\n\treturn function() {\n\t\tfor (var args = [], i = 0; i < arguments.length; i++) {\n\t\t\targs[i] = arguments[i];\n\t\t}\n\t\ttry {\n\t\t\treturn Promise.resolve(f.apply(this, args));\n\t\t} catch(e) {\n\t\t\treturn Promise.reject(e);\n\t\t}\n\t}\n}\n\n// Awaits on a value that may or may not be a Promise (equivalent to the await keyword in ES2015, with continuations passed explicitly)\nexport function _await(value, then, direct) {\n\tif (direct) {\n\t\treturn then ? then(value) : value;\n\t}\n\tif (!value || !value.then) {\n\t\tvalue = Promise.resolve(value);\n\t}\n\treturn then ? value.then(then) : value;\n}\n\n// Awaits on a value that may or may not be a Promise, then ignores it\nexport function _awaitIgnored(value, direct) {\n\tif (!direct) {\n\t\treturn value && value.then ? value.then(_empty) : Promise.resolve();\n\t}\n}\n\n// Proceeds after a value has resolved, or proceeds immediately if the value is not thenable\nexport function _continue(value, then) {\n\treturn value && value.then ? value.then(then) : then(value);\n}\n\n// Proceeds after a value has resolved, or proceeds immediately if the value is not thenable\nexport function _continueIgnored(value) {\n\tif (value && value.then) {\n\t\treturn value.then(_empty);\n\t}\n}\n\n// Asynchronously iterate through an object that has a length property, passing the index as the first argument to the callback (even as the length property changes)\nexport function _forTo(array, body, check) {\n\tvar i = -1, pact, reject;\n\tfunction _cycle(result) {\n\t\ttry {\n\t\t\twhile (++i < array.length && (!check || !check())) {\n\t\t\t\tresult = body(i);\n\t\t\t\tif (result && result.then) {\n\t\t\t\t\tif (_isSettledPact(result)) {\n\t\t\t\t\t\tresult = result.v;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresult.then(_cycle, reject || (reject = _settle.bind(null, pact = new _Pact(), 2)));\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (pact) {\n\t\t\t\t_settle(pact, 1, result);\n\t\t\t} else {\n\t\t\t\tpact = result;\n\t\t\t}\n\t\t} catch (e) {\n\t\t\t_settle(pact || (pact = new _Pact()), 2, e);\n\t\t}\n\t}\n\t_cycle();\n\treturn pact;\n}\n\n// Asynchronously iterate through an object\'s properties (including properties inherited from the prototype)\n// Uses a snapshot of the object\'s properties\nexport function _forIn(target, body, check) {\n\tvar keys = [];\n\tfor (var key in target) {\n\t\tkeys.push(key);\n\t}\n\treturn _forTo(keys, function(i) { return body(keys[i]); }, check);\n}\n\n// Asynchronously iterate through an object\'s own properties (excluding properties inherited from the prototype)\n// Uses a snapshot of the object\'s properties\nexport function _forOwn(target, body, check) {\n\tvar keys = [];\n\tfor (var key in target) {\n\t\tif (Object.prototype.hasOwnProperty.call(target, key)) {\n\t\t\tkeys.push(key);\n\t\t}\n\t}\n\treturn _forTo(keys, function(i) { return body(keys[i]); }, check);\n}\n\nexport const _iteratorSymbol = /*#__PURE__*/ typeof Symbol !== "undefined" ? (Symbol.iterator || (Symbol.iterator = Symbol("Symbol.iterator"))) : "@@iterator";\n\n// Asynchronously iterate through an object\'s values\n// Uses for...of if the runtime supports it, otherwise iterates until length on a copy\nexport function _forOf(target, body, check) {\n\tif (typeof target[_iteratorSymbol] === "function") {\n\t\tvar iterator = target[_iteratorSymbol](), step, pact, reject;\n\t\tfunction _cycle(result) {\n\t\t\ttry {\n\t\t\t\twhile (!(step = iterator.next()).done && (!check || !check())) {\n\t\t\t\t\tresult = body(step.value);\n\t\t\t\t\tif (result && result.then) {\n\t\t\t\t\t\tif (_isSettledPact(result)) {\n\t\t\t\t\t\t\tresult = result.v;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tresult.then(_cycle, reject || (reject = _settle.bind(null, pact = new _Pact(), 2)));\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (pact) {\n\t\t\t\t\t_settle(pact, 1, result);\n\t\t\t\t} else {\n\t\t\t\t\tpact = result;\n\t\t\t\t}\n\t\t\t} catch (e) {\n\t\t\t\t_settle(pact || (pact = new _Pact()), 2, e);\n\t\t\t}\n\t\t}\n\t\t_cycle();\n\t\tif (iterator.return) {\n\t\t\tvar _fixup = function(value) {\n\t\t\t\ttry {\n\t\t\t\t\tif (!step.done) {\n\t\t\t\t\t\titerator.return();\n\t\t\t\t\t}\n\t\t\t\t} catch(e) {\n\t\t\t\t}\n\t\t\t\treturn value;\n\t\t\t}\n\t\t\tif (pact && pact.then) {\n\t\t\t\treturn pact.then(_fixup, function(e) {\n\t\t\t\t\tthrow _fixup(e);\n\t\t\t\t});\n\t\t\t}\n\t\t\t_fixup();\n\t\t}\n\t\treturn pact;\n\t}\n\t// No support for Symbol.iterator\n\tif (!("length" in target)) {\n\t\tthrow new TypeError("Object is not iterable");\n\t}\n\t// Handle live collections properly\n\tvar values = [];\n\tfor (var i = 0; i < target.length; i++) {\n\t\tvalues.push(target[i]);\n\t}\n\treturn _forTo(values, function(i) { return body(values[i]); }, check);\n}\n\nexport const _asyncIteratorSymbol = /*#__PURE__*/ typeof Symbol !== "undefined" ? (Symbol.asyncIterator || (Symbol.asyncIterator = Symbol("Symbol.asyncIterator"))) : "@@asyncIterator";\n\n// Asynchronously iterate on a value using it\'s async iterator if present, or its synchronous iterator if missing\nexport function _forAwaitOf(target, body, check) {\n\tif (typeof target[_asyncIteratorSymbol] === "function") {\n\t\tvar pact = new _Pact();\n\t\tvar iterator = target[_asyncIteratorSymbol]();\n\t\titerator.next().then(_resumeAfterNext).then(void 0, _reject);\n\t\treturn pact;\n\t\tfunction _resumeAfterBody(result) {\n\t\t\tif (check && check()) {\n\t\t\t\treturn _settle(pact, 1, iterator.return ? iterator.return().then(function() { return result; }) : result);\n\t\t\t}\n\t\t\titerator.next().then(_resumeAfterNext).then(void 0, _reject);\n\t\t}\n\t\tfunction _resumeAfterNext(step) {\n\t\t\tif (step.done) {\n\t\t\t\t_settle(pact, 1);\n\t\t\t} else {\n\t\t\t\tPromise.resolve(body(step.value)).then(_resumeAfterBody).then(void 0, _reject);\n\t\t\t}\n\t\t}\n\t\tfunction _reject(error) {\n\t\t\t_settle(pact, 2, iterator.return ? iterator.return().then(function() { return error; }) : error);\n\t\t}\n\t}\n\treturn Promise.resolve(_forOf(target, function(value) { return Promise.resolve(value).then(body); }, check));\n}\n\n// Asynchronously implement a generic for loop\nexport function _for(test, update, body) {\n\tvar stage;\n\tfor (;;) {\n\t\tvar shouldContinue = test();\n\t\tif (_isSettledPact(shouldContinue)) {\n\t\t\tshouldContinue = shouldContinue.v;\n\t\t}\n\t\tif (!shouldContinue) {\n\t\t\treturn result;\n\t\t}\n\t\tif (shouldContinue.then) {\n\t\t\tstage = 0;\n\t\t\tbreak;\n\t\t}\n\t\tvar result = body();\n\t\tif (result && result.then) {\n\t\t\tif (_isSettledPact(result)) {\n\t\t\t\tresult = result.s;\n\t\t\t} else {\n\t\t\t\tstage = 1;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (update) {\n\t\t\tvar updateValue = update();\n\t\t\tif (updateValue && updateValue.then && !_isSettledPact(updateValue)) {\n\t\t\t\tstage = 2;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\tvar pact = new _Pact();\n\tvar reject = _settle.bind(null, pact, 2);\n\t(stage === 0 ? shouldContinue.then(_resumeAfterTest) : stage === 1 ? result.then(_resumeAfterBody) : updateValue.then(_resumeAfterUpdate)).then(void 0, reject);\n\treturn pact;\n\tfunction _resumeAfterBody(value) {\n\t\tresult = value;\n\t\tdo {\n\t\t\tif (update) {\n\t\t\t\tupdateValue = update();\n\t\t\t\tif (updateValue && updateValue.then && !_isSettledPact(updateValue)) {\n\t\t\t\t\tupdateValue.then(_resumeAfterUpdate).then(void 0, reject);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\tshouldContinue = test();\n\t\t\tif (!shouldContinue || (_isSettledPact(shouldContinue) && !shouldContinue.v)) {\n\t\t\t\t_settle(pact, 1, result);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (shouldContinue.then) {\n\t\t\t\tshouldContinue.then(_resumeAfterTest).then(void 0, reject);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tresult = body();\n\t\t\tif (_isSettledPact(result)) {\n\t\t\t\tresult = result.v;\n\t\t\t}\n\t\t} while (!result || !result.then);\n\t\tresult.then(_resumeAfterBody).then(void 0, reject);\n\t}\n\tfunction _resumeAfterTest(shouldContinue) {\n\t\tif (shouldContinue) {\n\t\t\tresult = body();\n\t\t\tif (result && result.then) {\n\t\t\t\tresult.then(_resumeAfterBody).then(void 0, reject);\n\t\t\t} else {\n\t\t\t\t_resumeAfterBody(result);\n\t\t\t}\n\t\t} else {\n\t\t\t_settle(pact, 1, result);\n\t\t}\n\t}\n\tfunction _resumeAfterUpdate() {\n\t\tif (shouldContinue = test()) {\n\t\t\tif (shouldContinue.then) {\n\t\t\t\tshouldContinue.then(_resumeAfterTest).then(void 0, reject);\n\t\t\t} else {\n\t\t\t\t_resumeAfterTest(shouldContinue);\n\t\t\t}\n\t\t} else {\n\t\t\t_settle(pact, 1, result);\n\t\t}\n\t}\n}\n\n// Asynchronously implement a do ... while loop\nexport function _do(body, test) {\n\tvar awaitBody;\n\tdo {\n\t\tvar result = body();\n\t\tif (result && result.then) {\n\t\t\tif (_isSettledPact(result)) {\n\t\t\t\tresult = result.v;\n\t\t\t} else {\n\t\t\t\tawaitBody = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tvar shouldContinue = test();\n\t\tif (_isSettledPact(shouldContinue)) {\n\t\t\tshouldContinue = shouldContinue.v;\n\t\t}\n\t\tif (!shouldContinue) {\n\t\t\treturn result;\n\t\t}\n\t} while (!shouldContinue.then);\n\tconst pact = new _Pact();\n\tconst reject = _settle.bind(null, pact, 2);\n\t(awaitBody ? result.then(_resumeAfterBody) : shouldContinue.then(_resumeAfterTest)).then(void 0, reject);\n\treturn pact;\n\tfunction _resumeAfterBody(value) {\n\t\tresult = value;\n\t\tfor (;;) {\n\t\t\tshouldContinue = test();\n\t\t\tif (_isSettledPact(shouldContinue)) {\n\t\t\t\tshouldContinue = shouldContinue.v;\n\t\t\t}\n\t\t\tif (!shouldContinue) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (shouldContinue.then) {\n\t\t\t\tshouldContinue.then(_resumeAfterTest).then(void 0, reject);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tresult = body();\n\t\t\tif (result && result.then) {\n\t\t\t\tif (_isSettledPact(result)) {\n\t\t\t\t\tresult = result.v;\n\t\t\t\t} else {\n\t\t\t\t\tresult.then(_resumeAfterBody).then(void 0, reject);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t_settle(pact, 1, result);\n\t}\n\tfunction _resumeAfterTest(shouldContinue) {\n\t\tif (shouldContinue) {\n\t\t\tdo {\n\t\t\t\tresult = body();\n\t\t\t\tif (result && result.then) {\n\t\t\t\t\tif (_isSettledPact(result)) {\n\t\t\t\t\t\tresult = result.v;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresult.then(_resumeAfterBody).then(void 0, reject);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tshouldContinue = test();\n\t\t\t\tif (_isSettledPact(shouldContinue)) {\n\t\t\t\t\tshouldContinue = shouldContinue.v;\n\t\t\t\t}\n\t\t\t\tif (!shouldContinue) {\n\t\t\t\t\t_settle(pact, 1, result);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t} while (!shouldContinue.then);\n\t\t\tshouldContinue.then(_resumeAfterTest).then(void 0, reject);\n\t\t} else {\n\t\t\t_settle(pact, 1, result);\n\t\t}\n\t}\n}\n\n// Asynchronously implement a switch statement\nexport function _switch(discriminant, cases) {\n\tvar dispatchIndex = -1;\n\tvar awaitBody;\n\touter: {\n\t\tfor (var i = 0; i < cases.length; i++) {\n\t\t\tvar test = cases[i][0];\n\t\t\tif (test) {\n\t\t\t\tvar testValue = test();\n\t\t\t\tif (testValue && testValue.then) {\n\t\t\t\t\tbreak outer;\n\t\t\t\t}\n\t\t\t\tif (testValue === discriminant) {\n\t\t\t\t\tdispatchIndex = i;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Found the default case, set it as the pending dispatch case\n\t\t\t\tdispatchIndex = i;\n\t\t\t}\n\t\t}\n\t\tif (dispatchIndex !== -1) {\n\t\t\tdo {\n\t\t\t\tvar body = cases[dispatchIndex][1];\n\t\t\t\twhile (!body) {\n\t\t\t\t\tdispatchIndex++;\n\t\t\t\t\tbody = cases[dispatchIndex][1];\n\t\t\t\t}\n\t\t\t\tvar result = body();\n\t\t\t\tif (result && result.then) {\n\t\t\t\t\tawaitBody = true;\n\t\t\t\t\tbreak outer;\n\t\t\t\t}\n\t\t\t\tvar fallthroughCheck = cases[dispatchIndex][2];\n\t\t\t\tdispatchIndex++;\n\t\t\t} while (fallthroughCheck && !fallthroughCheck());\n\t\t\treturn result;\n\t\t}\n\t}\n\tconst pact = new _Pact();\n\tconst reject = _settle.bind(null, pact, 2);\n\t(awaitBody ? result.then(_resumeAfterBody) : testValue.then(_resumeAfterTest)).then(void 0, reject);\n\treturn pact;\n\tfunction _resumeAfterTest(value) {\n\t\tfor (;;) {\n\t\t\tif (value === discriminant) {\n\t\t\t\tdispatchIndex = i;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (++i === cases.length) {\n\t\t\t\tif (dispatchIndex !== -1) {\n\t\t\t\t\tbreak;\n\t\t\t\t} else {\n\t\t\t\t\t_settle(pact, 1, result);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\ttest = cases[i][0];\n\t\t\tif (test) {\n\t\t\t\tvalue = test();\n\t\t\t\tif (value && value.then) {\n\t\t\t\t\tvalue.then(_resumeAfterTest).then(void 0, reject);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tdispatchIndex = i;\n\t\t\t}\n\t\t}\n\t\tdo {\n\t\t\tvar body = cases[dispatchIndex][1];\n\t\t\twhile (!body) {\n\t\t\t\tdispatchIndex++;\n\t\t\t\tbody = cases[dispatchIndex][1];\n\t\t\t}\n\t\t\tvar result = body();\n\t\t\tif (result && result.then) {\n\t\t\t\tresult.then(_resumeAfterBody).then(void 0, reject);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar fallthroughCheck = cases[dispatchIndex][2];\n\t\t\tdispatchIndex++;\n\t\t} while (fallthroughCheck && !fallthroughCheck());\n\t\t_settle(pact, 1, result);\n\t}\n\tfunction _resumeAfterBody(result) {\n\t\tfor (;;) {\n\t\t\tvar fallthroughCheck = cases[dispatchIndex][2];\n\t\t\tif (!fallthroughCheck || fallthroughCheck()) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tdispatchIndex++;\n\t\t\tvar body = cases[dispatchIndex][1];\n\t\t\twhile (!body) {\n\t\t\t\tdispatchIndex++;\n\t\t\t\tbody = cases[dispatchIndex][1];\n\t\t\t}\n\t\t\tresult = body();\n\t\t\tif (result && result.then) {\n\t\t\t\tresult.then(_resumeAfterBody).then(void 0, reject);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\t_settle(pact, 1, result);\n\t}\n}\n\n// Asynchronously call a function and pass the result to explicitly passed continuations\nexport function _call(body, then, direct) {\n\tif (direct) {\n\t\treturn then ? then(body()) : body();\n\t}\n\ttry {\n\t\tvar result = Promise.resolve(body());\n\t\treturn then ? result.then(then) : result;\n\t} catch (e) {\n\t\treturn Promise.reject(e);\n\t}\n}\n\n// Asynchronously call a function and swallow the result\nexport function _callIgnored(body, direct) {\n\treturn _call(body, _empty, direct);\n}\n\n// Asynchronously call a function and pass the result to explicitly passed continuations\nexport function _invoke(body, then) {\n\tvar result = body();\n\tif (result && result.then) {\n\t\treturn result.then(then);\n\t}\n\treturn then(result);\n}\n\n// Asynchronously call a function and swallow the result\nexport function _invokeIgnored(body) {\n\tvar result = body();\n\tif (result && result.then) {\n\t\treturn result.then(_empty);\n\t}\n}\n\n// Asynchronously call a function and send errors to recovery continuation\nexport function _catch(body, recover) {\n\ttry {\n\t\tvar result = body();\n\t} catch(e) {\n\t\treturn recover(e);\n\t}\n\tif (result && result.then) {\n\t\treturn result.then(void 0, recover);\n\t}\n\treturn result;\n}\n\n// Asynchronously await a promise and pass the result to a finally continuation\nexport function _finallyRethrows(body, finalizer) {\n\ttry {\n\t\tvar result = body();\n\t} catch (e) {\n\t\treturn finalizer(true, e);\n\t}\n\tif (result && result.then) {\n\t\treturn result.then(finalizer.bind(null, false), finalizer.bind(null, true));\n\t}\n\treturn finalizer(false, result);\n}\n\n// Asynchronously await a promise and invoke a finally continuation that always overrides the result\nexport function _finally(body, finalizer) {\n\ttry {\n\t\tvar result = body();\n\t} catch (e) {\n\t\treturn finalizer();\n\t}\n\tif (result && result.then) {\n\t\treturn result.then(finalizer, finalizer);\n\t}\n\treturn finalizer();\n}\n\n// Rethrow or return a value from a finally continuation\nexport function _rethrow(thrown, value) {\n\tif (thrown)\n\t\tthrow value;\n\treturn value;\n}\n\n// Empty function to implement break and other control flow that ignores asynchronous results\nexport function _empty() {\n}\n\n// Sentinel value for early returns in generators \nexport const _earlyReturn = /*#__PURE__*/ {};\n\n// Asynchronously call a function and send errors to recovery continuation, skipping early returns\nexport function _catchInGenerator(body, recover) {\n\treturn _catch(body, function(e) {\n\t\tif (e === _earlyReturn) {\n\t\t\tthrow e;\n\t\t}\n\t\treturn recover(e);\n\t});\n}\n\n// Asynchronous generator class; accepts the entrypoint of the generator, to which it passes itself when the generator should start\nexport const _AsyncGenerator = /*#__PURE__*/(function() {\n\tfunction _AsyncGenerator(entry) {\n\t\tthis._entry = entry;\n\t\tthis._pact = null;\n\t\tthis._resolve = null;\n\t\tthis._return = null;\n\t\tthis._promise = null;\n\t}\n\n\tfunction _wrapReturnedValue(value) {\n\t\treturn { value: value, done: true };\n\t}\n\tfunction _wrapYieldedValue(value) {\n\t\treturn { value: value, done: false };\n\t}\n\n\t_AsyncGenerator.prototype._yield = function(value) {\n\t\t// Yield the value to the pending next call\n\t\tthis._resolve(value && value.then ? value.then(_wrapYieldedValue) : _wrapYieldedValue(value));\n\t\t// Return a pact for an upcoming next/return/throw call\n\t\treturn this._pact = new _Pact();\n\t};\n\t_AsyncGenerator.prototype.next = function(value) {\n\t\t// Advance the generator, starting it if it has yet to be started\n\t\tconst _this = this;\n\t\treturn _this._promise = new Promise(function (resolve) {\n\t\t\tconst _pact = _this._pact;\n\t\t\tif (_pact === null) {\n\t\t\t\tconst _entry = _this._entry;\n\t\t\t\tif (_entry === null) {\n\t\t\t\t\t// Generator is started, but not awaiting a yield expression\n\t\t\t\t\t// Abandon the next call!\n\t\t\t\t\treturn resolve(_this._promise);\n\t\t\t\t}\n\t\t\t\t// Start the generator\n\t\t\t\t_this._entry = null;\n\t\t\t\t_this._resolve = resolve;\n\t\t\t\tfunction returnValue(value) {\n\t\t\t\t\t_this._resolve(value && value.then ? value.then(_wrapReturnedValue) : _wrapReturnedValue(value));\n\t\t\t\t\t_this._pact = null;\n\t\t\t\t\t_this._resolve = null;\n\t\t\t\t}\n\t\t\t\tvar result = _entry(_this);\n\t\t\t\tif (result && result.then) {\n\t\t\t\t\tresult.then(returnValue, function(error) {\n\t\t\t\t\t\tif (error === _earlyReturn) {\n\t\t\t\t\t\t\treturnValue(_this._return);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tconst pact = new _Pact();\n\t\t\t\t\t\t\t_this._resolve(pact);\n\t\t\t\t\t\t\t_this._pact = null;\n\t\t\t\t\t\t\t_this._resolve = null;\n\t\t\t\t\t\t\t_resolve(pact, 2, error);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\treturnValue(result);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Generator is started and a yield expression is pending, settle it\n\t\t\t\t_this._pact = null;\n\t\t\t\t_this._resolve = resolve;\n\t\t\t\t_settle(_pact, 1, value);\n\t\t\t}\n\t\t});\n\t};\n\t_AsyncGenerator.prototype.return = function(value) {\n\t\t// Early return from the generator if started, otherwise abandons the generator\n\t\tconst _this = this;\n\t\treturn _this._promise = new Promise(function (resolve) {\n\t\t\tconst _pact = _this._pact;\n\t\t\tif (_pact === null) {\n\t\t\t\tif (_this._entry === null) {\n\t\t\t\t\t// Generator is started, but not awaiting a yield expression\n\t\t\t\t\t// Abandon the return call!\n\t\t\t\t\treturn resolve(_this._promise);\n\t\t\t\t}\n\t\t\t\t// Generator is not started, abandon it and return the specified value\n\t\t\t\t_this._entry = null;\n\t\t\t\treturn resolve(value && value.then ? value.then(_wrapReturnedValue) : _wrapReturnedValue(value));\n\t\t\t}\n\t\t\t// Settle the yield expression with a rejected "early return" value\n\t\t\t_this._return = value;\n\t\t\t_this._resolve = resolve;\n\t\t\t_this._pact = null;\n\t\t\t_settle(_pact, 2, _earlyReturn);\n\t\t});\n\t};\n\t_AsyncGenerator.prototype.throw = function(error) {\n\t\t// Inject an exception into the pending yield expression\n\t\tconst _this = this;\n\t\treturn _this._promise = new Promise(function (resolve, reject) {\n\t\t\tconst _pact = _this._pact;\n\t\t\tif (_pact === null) {\n\t\t\t\tif (_this._entry === null) {\n\t\t\t\t\t// Generator is started, but not awaiting a yield expression\n\t\t\t\t\t// Abandon the throw call!\n\t\t\t\t\treturn resolve(_this._promise);\n\t\t\t\t}\n\t\t\t\t// Generator is not started, abandon it and return a rejected Promise containing the error\n\t\t\t\t_this._entry = null;\n\t\t\t\treturn reject(error);\n\t\t\t}\n\t\t\t// Settle the yield expression with the value as a rejection\n\t\t\t_this._resolve = resolve;\n\t\t\t_this._pact = null;\n\t\t\t_settle(_pact, 2, error);\n\t\t});\n\t};\n\n\t_AsyncGenerator.prototype[_asyncIteratorSymbol] = function() {\n\t\treturn this;\n\t};\n\t\n\treturn _AsyncGenerator;\n})();\n'
|
|
@@ -21,6 +21,8 @@ import { requireBabelPlugin } from "../babel/require_babel_plugin.js"
|
|
|
21
21
|
import { babelPluginTransformImportMetaUrl } from "./helpers/babel_plugin_transform_import_meta_url.js"
|
|
22
22
|
import { jsenvPluginAsJsClassicHtml } from "./jsenv_plugin_as_js_classic_html.js"
|
|
23
23
|
import { jsenvPluginAsJsClassicWorkers } from "./jsenv_plugin_as_js_classic_workers.js"
|
|
24
|
+
// because of https://github.com/rpetrich/babel-plugin-transform-async-to-promises/issues/84
|
|
25
|
+
import customAsyncToPromises from "./async-to-promises.js"
|
|
24
26
|
|
|
25
27
|
export const jsenvPluginAsJsClassic = ({ systemJsInjection }) => {
|
|
26
28
|
const systemJsClientFileUrl = new URL(
|
|
@@ -143,7 +145,7 @@ const generateJsClassicFilename = (url) => {
|
|
|
143
145
|
) {
|
|
144
146
|
extension = ".js"
|
|
145
147
|
}
|
|
146
|
-
return `${basename}.
|
|
148
|
+
return `${basename}.nomodule${extension}`
|
|
147
149
|
}
|
|
148
150
|
|
|
149
151
|
const splitFileExtension = (filename) => {
|
|
@@ -168,13 +170,13 @@ const convertJsModuleToJsClassic = async ({
|
|
|
168
170
|
// propposal-dynamic-import required with systemjs for babel8:
|
|
169
171
|
// https://github.com/babel/babel/issues/10746
|
|
170
172
|
requireFromJsenv("@babel/plugin-proposal-dynamic-import"),
|
|
173
|
+
requireFromJsenv("@babel/plugin-transform-modules-systemjs"),
|
|
171
174
|
[
|
|
172
|
-
|
|
175
|
+
customAsyncToPromises,
|
|
173
176
|
{
|
|
174
177
|
topLevelAwait: "return",
|
|
175
178
|
},
|
|
176
179
|
],
|
|
177
|
-
requireFromJsenv("@babel/plugin-transform-modules-systemjs"),
|
|
178
180
|
]
|
|
179
181
|
: [
|
|
180
182
|
[
|
|
@@ -11,6 +11,14 @@ export const jsenvPluginTopLevelAwait = () => {
|
|
|
11
11
|
if (context.isSupportedOnCurrentClients("top_level_await")) {
|
|
12
12
|
return null
|
|
13
13
|
}
|
|
14
|
+
const willTransformJsModules =
|
|
15
|
+
!context.isSupportedOnCurrentClients("script_type_module") ||
|
|
16
|
+
!context.isSupportedOnCurrentClients("import_dynamic") ||
|
|
17
|
+
!context.isSupportedOnCurrentClients("import_meta")
|
|
18
|
+
// keep it untouched, systemjs will handle it
|
|
19
|
+
if (willTransformJsModules) {
|
|
20
|
+
return null
|
|
21
|
+
}
|
|
14
22
|
const usesTLA = await usesTopLevelAwait(urlInfo)
|
|
15
23
|
if (!usesTLA) {
|
|
16
24
|
return null
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { fileURLToPath } from "node:url"
|
|
1
2
|
import { readFileSync } from "node:fs"
|
|
2
|
-
import { resolveUrl, urlToFileSystemPath } from "@jsenv/urls"
|
|
3
3
|
|
|
4
4
|
import { requireFromJsenv } from "@jsenv/core/src/require_from_jsenv.js"
|
|
5
5
|
import { istanbulCoverageMapFromCoverage } from "./istanbul_coverage_map_from_coverage.js"
|
|
@@ -9,27 +9,23 @@ export const generateCoverageHtmlDirectory = async (
|
|
|
9
9
|
{
|
|
10
10
|
rootDirectoryUrl,
|
|
11
11
|
coverageHtmlDirectoryRelativeUrl,
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
coverageReportSkipEmpty,
|
|
13
|
+
coverageReportSkipFull,
|
|
14
14
|
},
|
|
15
15
|
) => {
|
|
16
16
|
const libReport = requireFromJsenv("istanbul-lib-report")
|
|
17
17
|
const reports = requireFromJsenv("istanbul-reports")
|
|
18
18
|
|
|
19
19
|
const context = libReport.createContext({
|
|
20
|
-
dir:
|
|
20
|
+
dir: fileURLToPath(rootDirectoryUrl),
|
|
21
21
|
coverageMap: istanbulCoverageMapFromCoverage(coverage),
|
|
22
|
-
sourceFinder: (path) =>
|
|
23
|
-
|
|
24
|
-
urlToFileSystemPath(resolveUrl(path, rootDirectoryUrl)),
|
|
25
|
-
"utf8",
|
|
26
|
-
)
|
|
27
|
-
},
|
|
22
|
+
sourceFinder: (path) =>
|
|
23
|
+
readFileSync(new URL(path, rootDirectoryUrl), "utf8"),
|
|
28
24
|
})
|
|
29
25
|
|
|
30
26
|
const report = reports.create("html", {
|
|
31
|
-
skipEmpty:
|
|
32
|
-
skipFull:
|
|
27
|
+
skipEmpty: coverageReportSkipEmpty,
|
|
28
|
+
skipFull: coverageReportSkipFull,
|
|
33
29
|
subdir: coverageHtmlDirectoryRelativeUrl,
|
|
34
30
|
})
|
|
35
31
|
report.execute(context)
|
|
@@ -5,18 +5,13 @@ import { byteAsFileSize } from "@jsenv/log"
|
|
|
5
5
|
export const generateCoverageJsonFile = async ({
|
|
6
6
|
coverage,
|
|
7
7
|
coverageJsonFileUrl,
|
|
8
|
-
coverageJsonFileLog,
|
|
9
8
|
logger,
|
|
10
9
|
}) => {
|
|
11
10
|
const coverageAsText = JSON.stringify(coverage, null, " ")
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
)})`,
|
|
18
|
-
)
|
|
19
|
-
}
|
|
20
|
-
|
|
11
|
+
logger.info(
|
|
12
|
+
`-> ${urlToFileSystemPath(coverageJsonFileUrl)} (${byteAsFileSize(
|
|
13
|
+
Buffer.byteLength(coverageAsText),
|
|
14
|
+
)})`,
|
|
15
|
+
)
|
|
21
16
|
await writeFile(coverageJsonFileUrl, coverageAsText)
|
|
22
17
|
}
|
|
@@ -3,7 +3,7 @@ import { istanbulCoverageMapFromCoverage } from "./istanbul_coverage_map_from_co
|
|
|
3
3
|
|
|
4
4
|
export const generateCoverageTextLog = (
|
|
5
5
|
coverage,
|
|
6
|
-
{
|
|
6
|
+
{ coverageReportSkipEmpty, coverageReportSkipFull },
|
|
7
7
|
) => {
|
|
8
8
|
const libReport = requireFromJsenv("istanbul-lib-report")
|
|
9
9
|
const reports = requireFromJsenv("istanbul-reports")
|
|
@@ -12,8 +12,8 @@ export const generateCoverageTextLog = (
|
|
|
12
12
|
coverageMap: istanbulCoverageMapFromCoverage(coverage),
|
|
13
13
|
})
|
|
14
14
|
const report = reports.create("text", {
|
|
15
|
-
skipEmpty:
|
|
16
|
-
skipFull:
|
|
15
|
+
skipEmpty: coverageReportSkipEmpty,
|
|
16
|
+
skipFull: coverageReportSkipFull,
|
|
17
17
|
})
|
|
18
18
|
report.execute(context)
|
|
19
19
|
}
|
package/src/test/execute_plan.js
CHANGED
|
@@ -333,22 +333,21 @@ export const executePlan = async (
|
|
|
333
333
|
}
|
|
334
334
|
let spinner
|
|
335
335
|
if (executionSpinner) {
|
|
336
|
-
const renderSpinnerText = () =>
|
|
337
|
-
createExecutionLog(beforeExecutionInfo, {
|
|
338
|
-
counters,
|
|
339
|
-
...(logTimeUsage
|
|
340
|
-
? {
|
|
341
|
-
timeEllapsed: Date.now() - startMs,
|
|
342
|
-
}
|
|
343
|
-
: {}),
|
|
344
|
-
...(logMemoryHeapUsage
|
|
345
|
-
? { memoryHeap: memoryUsage().heapUsed }
|
|
346
|
-
: {}),
|
|
347
|
-
})
|
|
348
336
|
spinner = startSpinner({
|
|
349
337
|
log: executionLog,
|
|
350
|
-
|
|
351
|
-
|
|
338
|
+
render: () => {
|
|
339
|
+
return createExecutionLog(beforeExecutionInfo, {
|
|
340
|
+
counters,
|
|
341
|
+
...(logTimeUsage
|
|
342
|
+
? {
|
|
343
|
+
timeEllapsed: Date.now() - startMs,
|
|
344
|
+
}
|
|
345
|
+
: {}),
|
|
346
|
+
...(logMemoryHeapUsage
|
|
347
|
+
? { memoryHeap: memoryUsage().heapUsed }
|
|
348
|
+
: {}),
|
|
349
|
+
})
|
|
350
|
+
},
|
|
352
351
|
})
|
|
353
352
|
}
|
|
354
353
|
beforeExecutionCallback(beforeExecutionInfo)
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { URL_META } from "@jsenv/url-meta"
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
urlToFileSystemPath,
|
|
4
|
+
resolveDirectoryUrl,
|
|
5
|
+
urlIsInsideOf,
|
|
6
|
+
urlToRelativeUrl,
|
|
7
|
+
} from "@jsenv/urls"
|
|
3
8
|
import {
|
|
4
9
|
ensureEmptyDirectory,
|
|
5
10
|
assertAndNormalizeDirectoryUrl,
|
|
@@ -57,26 +62,19 @@ export const executeTestPlan = async ({
|
|
|
57
62
|
process.argv.includes("--coverage"),
|
|
58
63
|
coverageTempDirectoryRelativeUrl = "./.coverage/tmp/",
|
|
59
64
|
coverageConfig = {
|
|
60
|
-
"./src
|
|
61
|
-
"./**/*.test.*": false, // contains .test. -> no
|
|
62
|
-
"./**/test/": false, // inside a test directory -> no
|
|
63
|
-
"./**/tests/": false, // inside a tests directory -> no
|
|
65
|
+
"./src/": true,
|
|
64
66
|
},
|
|
65
67
|
coverageIncludeMissing = true,
|
|
66
68
|
coverageAndExecutionAllowed = false,
|
|
67
69
|
coverageForceIstanbul = false,
|
|
68
70
|
coverageV8ConflictWarning = true,
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
// skip empty means empty files won't appear in the coverage reports (log and html)
|
|
77
|
-
coverageSkipEmpty = false,
|
|
78
|
-
// skip full means file with 100% coverage won't appear in coverage reports (log and html)
|
|
79
|
-
coverageSkipFull = false,
|
|
71
|
+
coverageReportTextLog = true,
|
|
72
|
+
coverageReportJsonFile = process.env.CI ? null : "./.coverage/coverage.json",
|
|
73
|
+
coverageReportHtmlDirectory = process.env.CI ? "./.coverage/" : null,
|
|
74
|
+
// skip empty means empty files won't appear in the coverage reports (json and html)
|
|
75
|
+
coverageReportSkipEmpty = false,
|
|
76
|
+
// skip full means file with 100% coverage won't appear in coverage reports (json and html)
|
|
77
|
+
coverageReportSkipFull = false,
|
|
80
78
|
|
|
81
79
|
sourcemaps = "inline",
|
|
82
80
|
plugins = [],
|
|
@@ -187,44 +185,51 @@ export const executeTestPlan = async ({
|
|
|
187
185
|
// keep this one first because it does ensureEmptyDirectory
|
|
188
186
|
// and in case coverage json file gets written in the same directory
|
|
189
187
|
// it must be done before
|
|
190
|
-
if (coverage &&
|
|
188
|
+
if (coverage && coverageReportHtmlDirectory) {
|
|
191
189
|
const coverageHtmlDirectoryUrl = resolveDirectoryUrl(
|
|
192
|
-
|
|
190
|
+
coverageReportHtmlDirectory,
|
|
193
191
|
rootDirectoryUrl,
|
|
194
192
|
)
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
logger.info(
|
|
199
|
-
`-> ${urlToFileSystemPath(htmlCoverageDirectoryIndexFileUrl)}`,
|
|
193
|
+
if (!urlIsInsideOf(coverageHtmlDirectoryUrl, rootDirectoryUrl)) {
|
|
194
|
+
throw new Error(
|
|
195
|
+
`coverageReportHtmlDirectory must be inside rootDirectoryUrl`,
|
|
200
196
|
)
|
|
201
197
|
}
|
|
198
|
+
await ensureEmptyDirectory(coverageHtmlDirectoryUrl)
|
|
199
|
+
const htmlCoverageDirectoryIndexFileUrl = `${coverageHtmlDirectoryUrl}index.html`
|
|
200
|
+
logger.info(
|
|
201
|
+
`-> ${urlToFileSystemPath(htmlCoverageDirectoryIndexFileUrl)}`,
|
|
202
|
+
)
|
|
202
203
|
promises.push(
|
|
203
204
|
generateCoverageHtmlDirectory(planCoverage, {
|
|
204
205
|
rootDirectoryUrl,
|
|
205
|
-
coverageHtmlDirectoryRelativeUrl
|
|
206
|
+
coverageHtmlDirectoryRelativeUrl: urlToRelativeUrl(
|
|
207
|
+
coverageHtmlDirectoryUrl,
|
|
208
|
+
rootDirectoryUrl,
|
|
209
|
+
),
|
|
210
|
+
coverageReportSkipEmpty,
|
|
211
|
+
coverageReportSkipFull,
|
|
206
212
|
}),
|
|
207
213
|
)
|
|
208
214
|
}
|
|
209
|
-
if (coverage &&
|
|
215
|
+
if (coverage && coverageReportJsonFile) {
|
|
210
216
|
const coverageJsonFileUrl = new URL(
|
|
211
|
-
|
|
217
|
+
coverageReportJsonFile,
|
|
212
218
|
rootDirectoryUrl,
|
|
213
219
|
).href
|
|
214
220
|
promises.push(
|
|
215
221
|
generateCoverageJsonFile({
|
|
216
222
|
coverage: result.planCoverage,
|
|
217
223
|
coverageJsonFileUrl,
|
|
218
|
-
coverageJsonFileLog,
|
|
219
224
|
logger,
|
|
220
225
|
}),
|
|
221
226
|
)
|
|
222
227
|
}
|
|
223
|
-
if (coverage &&
|
|
228
|
+
if (coverage && coverageReportTextLog) {
|
|
224
229
|
promises.push(
|
|
225
230
|
generateCoverageTextLog(result.planCoverage, {
|
|
226
|
-
|
|
227
|
-
|
|
231
|
+
coverageReportSkipEmpty,
|
|
232
|
+
coverageReportSkipFull,
|
|
228
233
|
}),
|
|
229
234
|
)
|
|
230
235
|
}
|