Comparing version
@@ -563,4 +563,9 @@ 'use strict'; | ||
state.write(node, 'async '); | ||
this.formatParameters(node.params, state); | ||
state.write(node, '=> '); | ||
if (node.params.length===1 && node.params[0].type==='Identifier') { | ||
this.out(node.params[0], state, node.params[0].type) ; | ||
state.write(node, ' => '); | ||
} else { | ||
this.formatParameters(node.params, state); | ||
state.write(node, '=> '); | ||
} | ||
if (node.body.type === 'ObjectExpression' || node.body.type === 'SequenceExpression') { | ||
@@ -567,0 +572,0 @@ state.write(null, '('); |
{ | ||
"name": "nodent", | ||
"version": "3.0.7", | ||
"version": "3.0.8", | ||
"description": "NoDent - Asynchronous Javascript language extensions", | ||
@@ -17,5 +17,5 @@ "main": "nodent.js", | ||
"acorn": ">=2.5.2", | ||
"acorn-es7-plugin": "^1.1.3", | ||
"nodent-runtime": "^3.0.3", | ||
"resolve": "^1.1.7", | ||
"acorn-es7-plugin": ">=1.1.5", | ||
"nodent-runtime": ">=3.0.3", | ||
"resolve": "1.2.0", | ||
"source-map": "0.5.6" | ||
@@ -22,0 +22,0 @@ }, |
@@ -133,3 +133,3 @@ [](https://nodei.co/npm/nodent/) | ||
| --noruntime | Compile code (in -promises or -engine mode) for execution with no runtime requirement at all | ||
| --es6target | Compile code assuming an ES6 target (As of v3.0.0 this doesn't do anything different. When it does the exact ES6 features will be listed) | ||
| --es6target | Compile code assuming an ES6 target (as of v3.0.8, this only requires support for arrow functions) | ||
@@ -208,3 +208,3 @@ Use within your Node scripts | ||
noRuntime:<boolean>, // Only compatible with promises & engine. Generate pure ES5 code for an environment that support Promises natively or as a global declaration. Currently about 15% slower that using the built-in runtime $asyncbind. Default is false. | ||
es6target:<boolean> // Compile code assuming an ES6 target (As of v3.0.0 this doesn't do anything different. When it does the exact ES6 features will be listed) | ||
es6target:<boolean> // Compile code assuming an ES6 target (as of v3.0.8, this only requires support for arrow functions) | ||
} | ||
@@ -317,22 +317,22 @@ setHeaders: function(response) {} // Called prior to outputting compiled code to allow for headers (e.g. cache settings) to be sent | ||
However, this has a performance overhead. For maximum performance, you can specify this code generation option in `use nodent-es7 {"lazyThenables":true}` mode. In this case mode, if you call the async function the body _is not actually executed_ until resolved with an `await` (or a `.then()`). If you know your code always uses `await`, you can use this option to improve performance. | ||
However, this has a performance overhead. For maximum performance, you can specify this code generation option in `use nodent-es7 {"lazyThenables":true}` mode. In this mode, if you call the async function the body _is not actually executed_ until resolved with an `await` (or a `.then()`). If you know your code always uses `await`, you can use this option to improve performance. | ||
In `use nodent-promises` mode, it is the implementation of the Promise that determines the execution scheduling and performance. The table below is a summary of modes and execution semantics. You can test the performance on your own hardware with the following command. Note the relative performance is a worst case, since the test does nothing other than make async calls in a loop. | ||
./nodent.js tests --generators tests/semantics/perf.js | ||
./nodent.js tests tests/semantics/perf.js | ||
| Mode | Flags / Implementation | Lazy / Eager | Possibly sync resolution | Performance (relative) | | ||
|-----------|----------|----|--------------------------|------------------------| | ||
| es7 | lazyThenable | Lazy | Yes | 1.0 | ||
| es7 | (none)| Eager | No | 1.7x slower | ||
| promises | nodent | Eager | No | 1.7x slower | ||
| promises | node 6.6 native | Eager | No | 5.2x slower | ||
| promises | bluebird 3.4.6 | Eager | No | 2.0x slower | ||
| promises | rsvp 3.3.1 | Eager | No | 2.2x slower | ||
| promises | when 3.7.7 | Eager | No | 1.6x slower | ||
| generators | nodent | Eager | No | 7.5x slower | ||
| generators | node 6.6 native | Eager | No | 15.0x slower | ||
| generators | bluebird 3.4.6 | Eager | No | 8.5x slower | ||
| generators | rsvp 3.3.1 | Eager | No | 7.6x slower | ||
| generators | when 3.7.7 | Eager | No | 8.3x slower | ||
| Mode | Flags / Implementation | Lazy / Eager | Possibly sync resolution | Performance (relative) | | ||
|------------|--------------------------|---------------|---------------------------|------------------------| | ||
| es7 | lazyThenable | Lazy | Yes | 1.0 | ||
| es7 | (none) | Eager | No | 1.7x slower | ||
| promises | nodent | Eager | No | 1.7x slower | ||
| promises | node 6.6 native | Eager | No | 5.2x slower | ||
| promises | bluebird 3.4.6 | Eager | No | 2.0x slower | ||
| promises | rsvp 3.3.1 | Eager | No | 2.2x slower | ||
| promises | when 3.7.7 | Eager | No | 1.6x slower | ||
| generators | nodent | Eager | No | 7.5x slower | ||
| generators | node 6.6 native | Eager | No | 15.0x slower | ||
| generators | bluebird 3.4.6 | Eager | No | 8.5x slower | ||
| generators | rsvp 3.3.1 | Eager | No | 7.6x slower | ||
| generators | when 3.7.7 | Eager | No | 8.3x slower | ||
@@ -379,3 +379,3 @@ All other JavaScript ES5/6/2015 constructs will be transformed as necessary to implement `async` and `await`. | ||
|noRuntime |boolean| default: false - generate pure ES5 code with external dependencies. The code is bigger and slower, and only works with -promises or -engine | ||
|es6target |boolean| default: false - use ES6 constructs like arrow functions to improve code speed and size | ||
|es6target |boolean| default: false - use ES6 constructs to improve code speed and size (as of v3.0.8, this only requires support for arrow functions) | ||
|parser |object | default: {sourceType:'script'} - passed to [Acorn](https://github.com/ternjs/acorn) to control the parser | ||
@@ -565,2 +565,6 @@ |mapStartLine |int | default: 0 - initial line number for the source-map | ||
20-Dec-16 v3.0.8 | ||
- Use arrow functions when the `es6target` option is specified. This generates async call sequences that run approximately 20% faster (on on V8 v5.4.x) as calls to `bind(this)` and `$asyncbind(this)` are omitted from the generated code, esepcially when `noRuntime` is also specified. | ||
23-Oct-16 v3.0.5, v3.0.4 | ||
@@ -567,0 +571,0 @@ |
@@ -94,3 +94,3 @@ 'use nodent-es7 {"lazyThenables":true}'; | ||
} catch (ex) {} | ||
var useQuick = false, quiet = false, useGenerators = undefined, useGenOnly = false, syntaxTest = 0, forceStrict = "", useEngine = true ; | ||
var useQuick = false, quiet = false, useGenerators = true, useGenOnly = false, syntaxTest = 0, forceStrict = "", useEngine = true, useES6 = true ; | ||
var idx; | ||
@@ -138,3 +138,2 @@ for (idx = 0; idx < process.argv.length; idx++) { | ||
if (useGenerators !== false) useGenerators = true ; | ||
if (useGenerators) { | ||
@@ -151,2 +150,9 @@ try { | ||
try { | ||
eval("(a)=>0") ; | ||
} catch (ex) { | ||
console.log(("V8 "+process.versions.v8+" does not arrow functions. Skipping es6target tests. ").yellow) ; | ||
useES6 = false ; | ||
} | ||
function pad(s, n) { | ||
@@ -189,47 +195,69 @@ return (" " + s).substr(-(n || 32)); | ||
if (dualMode) { | ||
code = "module.exports = async function() { return _s() === await _a() }\n"+ | ||
"function _s() { "+code.replace(/async|await/g,"")+" }\n"+ | ||
code = "module.exports = async function() { "+ | ||
"var s = _s(), a = await _a() ;"+ | ||
"if (s !== a) {console.log(s,a)} "+ | ||
"return s === a }\n"+ | ||
"function _s() { "+forceStrict + code.replace(/async|await/g,"")+" }\n"+ | ||
"async function _a() { "+forceStrict + code+" }" ; | ||
} | ||
var compileException = false; | ||
for (var type = 0;type < (useEngine?24:16); type++) { | ||
var opts = {}; | ||
if (type&16) { | ||
if (!(type & 4)) | ||
continue ; | ||
opts.engine = true ; | ||
} | ||
if (!(type & 12) && !(type & 1)) | ||
opts.lazyThenables = true; | ||
if (type & 2) | ||
opts.wrapAwait = true; | ||
if (type & 4) { | ||
opts.promises = true; | ||
if (type & 1) | ||
for (var mode = 0; mode < 5; mode++) { | ||
for (var flags=0; flags<8; flags++) { | ||
var opts = {} ; | ||
switch (mode) { | ||
case 0: // es7 (lazy) | ||
opts.es7 = true ; | ||
opts.lazyThenables = true ; | ||
break; | ||
case 1: // es7 (eager) | ||
opts.es7 = true ; | ||
break; | ||
case 2: // Promises | ||
opts.promises = true ; | ||
break; | ||
case 3: // Generators | ||
if (!useGenerators) | ||
continue ; | ||
opts.generators = true ; | ||
break; | ||
case 4: // Engine | ||
if (!useEngine) | ||
continue ; | ||
opts.engine = true ; | ||
break; | ||
} | ||
if (flags & 1) { | ||
if (!useES6) | ||
continue ; | ||
opts.es6target = true ; | ||
} | ||
if (flags & 2) { | ||
if (!(opts.promises || opts.engine)) | ||
continue ; | ||
opts.noRuntime = true ; | ||
} | ||
if (type & 8) { | ||
if (!useGenerators) | ||
continue ; | ||
opts.generators = true; | ||
if (opts.noRuntime) | ||
continue ; | ||
} else if (useGenOnly) | ||
continue ; | ||
if (!(type & (4|8))) | ||
opts.es7 = true; | ||
types[type] = Object.keys(opts).toString() ; | ||
try { | ||
var pr, tCompiler = process.hrtime(); | ||
pr = nodent.compile(forceStrict + code, n, opts).code; | ||
tTotalCompilerTime += time(tCompiler); | ||
} | ||
if (flags & 4) | ||
opts.wrapAwait = true ; | ||
var type = mode*8+flags ; | ||
types[type] = Object.keys(opts).toString() ; | ||
try { | ||
test[i].fn[type] = new Function("module", "require", "Promise", "__unused", "nodent", "DoNotTest", pr); | ||
var pr, tCompiler = process.hrtime(); | ||
pr = nodent.compile(forceStrict + code, n, opts).code; | ||
tTotalCompilerTime += time(tCompiler); | ||
try { | ||
test[i].fn[type] = new Function("module", "require", "Promise", "__unused", "nodent", "DoNotTest", pr); | ||
test[i].fn[type].opts = opts ; | ||
} catch (ex) { | ||
if (!compileException) | ||
console.warn(test[i].name+(" not supported by V8 "+process.versions.v8+" (try a later version of nodejs): ").yellow+ex.message.red) ; | ||
compileException = true ; | ||
test[i].fn[type] = function(m) { | ||
m.exports = DoNotTest ; | ||
} | ||
} | ||
} catch (ex) { | ||
if (!compileException) | ||
console.warn(test[i].name+(" not supported by V8 "+process.versions.v8+" (try a later version of nodejs): ").yellow+ex.message.red) ; | ||
console.warn(test[i].name+(" nodent failed to compile ").yellow+" ("+types[type]+") "+ex.message.red) ; | ||
compileException = true ; | ||
@@ -240,9 +268,2 @@ test[i].fn[type] = function(m) { | ||
} | ||
} catch (ex) { | ||
if (!compileException) | ||
console.warn(test[i].name+(" nodent failed to compile - FAIL ").yellow+ex.message.red) ; | ||
compileException = true ; | ||
test[i].fn[type] = function(m) { | ||
m.exports = DoNotTest ; | ||
} | ||
} | ||
@@ -260,3 +281,3 @@ } | ||
async function runTest(test, provider, type) { | ||
if ((provider.p && !(type & (4 | 8 | 16))) || (!provider.p && (type & (4 | 8 | 16)))) { | ||
if (!test.fn[type].opts || (provider.p && !(test.fn[type].opts.promises || test.fn[type].opts.generators || test.fn[type].opts.engine))) { | ||
return { | ||
@@ -266,2 +287,10 @@ result: DoNotTest | ||
} | ||
if (!provider.p && test.fn[type].opts.engine) { | ||
return { | ||
result: DoNotTest | ||
}; | ||
} | ||
await sleep(1); | ||
@@ -313,2 +342,3 @@ var key = [test.name,provider.name,type].join(); | ||
var result, byType = {}, byProvider = {}, byTest = {}, table = [], fails = [], tMedian = 0, nMedian = 0 ; | ||
var maxLines = 0 ; | ||
nextTest: for (i = 0;i < test.length; i++) { | ||
@@ -322,5 +352,2 @@ var benchmark = null; | ||
for (var type in types) if (Object.getOwnPropertyDescriptor(types,type)) { | ||
if (!(type & 1) && (type&8)) | ||
continue ; | ||
table[type] = table[type] || []; | ||
@@ -374,2 +401,4 @@ table[type][j] = table[type][j] || []; | ||
var lines = 2+showPerformanceTable() ; | ||
if (maxLines < lines+1) | ||
maxLines = lines+1 ; | ||
while (lines--) { | ||
@@ -386,3 +415,4 @@ process.stdout.write('\u001B[1A') ; | ||
console.log('\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nBenchmark execution time: '+((tMedian/nMedian)+' ms').cyan) ; | ||
while (maxLines--) console.log("") ; | ||
console.log('Benchmark execution time: '+((tMedian/nMedian)+' ms').cyan) ; | ||
console.log(fails.join("\n")) ; | ||
@@ -389,0 +419,0 @@ |
@@ -18,8 +18,8 @@ { | ||
"devDependencies": { | ||
"promise": "^7.1.1", | ||
"bluebird": "^3.4.6", | ||
"promiscuous": "^0.6.0", | ||
"rsvp": "^3.3.1", | ||
"when": "^3.7.7" | ||
"promise": ">=7.1.1", | ||
"bluebird": ">=3.4.6", | ||
"promiscuous": ">=0.6.0", | ||
"rsvp": ">=3.3.1", | ||
"when": ">=3.7.7" | ||
} | ||
} |
@@ -0,1 +1,3 @@ | ||
'use nodent'; | ||
async function foo() { | ||
@@ -2,0 +4,0 @@ JSON.parse("*"); |
Sorry, the diff of this file is too big to display
370101
1.08%8650
0.97%617
0.65%9
12.5%+ Added
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
Updated
Updated
Updated