├── .gitignore ├── README.md ├── covers ├── asyncfunction.js ├── events.js ├── http.js ├── https.js ├── map.js └── nodentify.js ├── docs ├── changelog-2.md ├── helpers.md └── syntax.md ├── htmlScriptParser ├── index.js └── tests │ ├── index.js │ └── spa.html ├── lib └── runtime.js ├── nodent.js ├── package-lock.json ├── package.json └── tests ├── .gitignore ├── codegen ├── cg-es7.js ├── cg-generators.js └── cg-promises.js ├── compiler ├── args.js ├── await-usage.js ├── complex.js ├── conditional.js ├── declarations.js ├── dowhile.js ├── dual-decl-reorder.js ├── dual-destructure.js ├── dual-es6-arrow-args.js ├── dual-es6-decl-reorder.js ├── dual-for-of-const-destructure.js ├── dual-for-of.js ├── dual-for-sequence-init.js ├── dual-for-sync.js ├── dual-label-break.js ├── dual-loop-scope.js ├── dual-nested-async-finally.js ├── dual-nonblock-try.js ├── dual-reorder.js ├── dual-scoped-const.js ├── dual-sloppy-const.js ├── dual-try-except.js ├── dual-try-finally-await.js ├── dual-try-finally-try-catch.js ├── dual-try-noawait.js ├── dual-try-scoped.js ├── dual-while-throw.js ├── else-if.js ├── es6-args.js ├── es6-arrow.js ├── es6-class-async.js ├── es6-destructure.js ├── es6-for-of.js ├── es6-logical.js ├── es6-loop-label.js ├── es6-object-arrow.js ├── for-empty.js ├── for-if.js ├── for-in.js ├── for-throw.js ├── for.js ├── if-stmt.js ├── if-switch.js ├── if-try.js ├── inline.js ├── logical.js ├── loop-label.js ├── loop-this.js ├── method.js ├── nested-async.js ├── nested-await.js ├── nested-switch-stmt.js ├── nested-throw.js ├── optimized.js ├── ret-fn.js ├── sleep.js ├── switch-stmt.js ├── try-catch-finally.js ├── try-catch.js ├── try-finally.js ├── try-for-if.js ├── try-if.js ├── try-nested.js ├── try-pair.js ├── try-throw.js ├── try.js ├── while.js ├── wrap-method.js └── wrap.js ├── index.js ├── loader ├── app │ ├── .gitignore │ ├── index.js │ ├── main.js │ └── package.json └── loader-module │ ├── .gitignore │ ├── index.js │ ├── package.json │ └── version.js ├── onp ├── COPYING ├── diff.js └── onp.js ├── package-lock.json ├── package.json ├── semantics ├── asyncfunction-type.js ├── asyncify.js ├── await-multi.js ├── await-not-then.js ├── await.wrap.js ├── callback-fn-ret.js ├── es6-interop.js ├── es6-parser.js ├── fs-sync.js ├── fs.js ├── http-test.js ├── if-stmt-map.js ├── interop.js ├── map.js ├── nested-async-exit.js ├── parser.js ├── perf-2.js └── perf.js ├── syntax ├── array.js ├── arrow-expr.js ├── call.js ├── class.js ├── control.js ├── error.js ├── everything │ ├── LICENSE │ ├── README.md │ ├── es2015-module.js │ ├── es2015-script.js │ ├── es5.js │ ├── package.json │ └── test │ │ ├── parsing.js │ │ └── unit.js ├── export.js ├── function.js ├── import.js ├── loop.js ├── new.js ├── object.js ├── precedence.js ├── sequence.js ├── template.js ├── unary.js ├── variable.js ├── x-sync-await.js ├── x-sync-ret.js └── yield.js ├── test-syntax.js └── watch-comp.js /.gitignore: -------------------------------------------------------------------------------- 1 | /.project 2 | /node_modules 3 | /README.md~ 4 | /.DS_Store 5 | /coverage/ 6 | -------------------------------------------------------------------------------- /covers/asyncfunction.js: -------------------------------------------------------------------------------- 1 | function Nothing(){} 2 | 3 | module.exports = function(nodent,config) { 4 | config = config || {} ; 5 | if (!('promises' in config)) 6 | config.promises = 'Promise' in global ; 7 | if (!('log' in config) || config.log===false) 8 | config.log = Nothing ; 9 | config.sourcemap = false ; 10 | 11 | function AsyncFunction() { 12 | var params = [].slice.call(arguments,0,-1) ; 13 | var source = "async function anonymous_AsyncFunction("+params.join(",")+") {\n"+arguments[arguments.length-1]+"\n}" ; 14 | var pr = nodent.compile(source,"(new AsyncFunction)",undefined,config) ; 15 | pr.ast = pr.ast.body[0].body ; 16 | var asyncBody = nodent.prettyPrint(pr,config).code ; 17 | params.push(asyncBody.slice(2,-2)) ; 18 | var fn = Function.apply(this,params) ; 19 | fn.__proto__ = AsyncFunction.prototype ; 20 | Object.defineProperty(fn,"source",{value:source}) ; 21 | fn.constructor = AsyncFunction ; 22 | return fn ; 23 | } 24 | 25 | AsyncFunction.prototype = Object.create(Function.prototype,{ 26 | toString:{ 27 | value:function(){ 28 | return this.source ; 29 | } 30 | }, 31 | toES5String:{ 32 | value:function(){ 33 | return Function.toString.apply(this) ; 34 | } 35 | }, 36 | }) ; 37 | 38 | return AsyncFunction ; 39 | } 40 | -------------------------------------------------------------------------------- /covers/events.js: -------------------------------------------------------------------------------- 1 | module.exports = function(nodent,opts) { 2 | if (!opts) opts = {} ; 3 | if (!opts.Promise) 4 | opts.Promise = global.Promise || nodent.Thenable ; 5 | 6 | var events = require('events'); 7 | if (!events.EventEmitter.prototype.wait) { 8 | events.EventEmitter.prototype.wait = function(event) { 9 | var ee = this ; 10 | return new (opts.Promise)(function($return,$error) { 11 | ee.once(event,$return) ; 12 | ee.once('error',$error) ; 13 | }) ; 14 | }; 15 | } 16 | return events; 17 | }; 18 | -------------------------------------------------------------------------------- /covers/http.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Create an instance of noDent friendly http with the API: 3 | * res = await nodent.http.get(opts) ; 4 | * ... set up some stuff with res... 5 | * await res.wait('end') ; 6 | */ 7 | 8 | module.exports = function(nodent,config) { 9 | nodent.require('events') ; 10 | var protos = {http:require('http')} ; 11 | var cover = Object.create(protos.http) ; 12 | var protocol ; 13 | 14 | if (!config) config = {} ; 15 | if (!config.Promise) 16 | config.Promise = global.Promise || nodent.Thenable ; 17 | 18 | if (config.autoProtocol) { 19 | protos.https = require('https') ; 20 | protocol = function(opts){ 21 | var p ; 22 | if (typeof opts==="string") { 23 | p = opts.split(":")[0] ; 24 | } else if (typeof opts==="object") { 25 | p = opts.protocol.replace(/:?$/,"") ; 26 | } 27 | if (p && protos[p]) return protos[p] ; 28 | throw new Error("Protocol is not http or https") ; 29 | } 30 | } else { 31 | protocol = function(){return protos.http;} ; 32 | } 33 | 34 | cover.request = function(opts){ 35 | return new (opts.Promise || config.Promise)(function($return,$error){ 36 | var request = protocol(opts).request(opts,function(){}) ; 37 | request.on('error',$error) ; 38 | $return(request) ; 39 | }) ; 40 | }; 41 | 42 | cover.get = function(opts){ 43 | return new (opts.Promise || config.Promise)(function($return,$error){ 44 | protocol(opts).get(opts,$return).on('error',$error) ; 45 | }) ; 46 | }; 47 | 48 | cover.getBody = function(opts){ 49 | return new (opts.Promise || config.Promise)(function($return,$error){ 50 | protocol(opts).get(opts,function(res){ 51 | try { 52 | var enc = "utf8" ; 53 | if (res.headers['content-type']) { 54 | var m = res.headers['content-type'].match(/.*charset=(.*)\b/) ; 55 | if (m && m.length>1 && Buffer.isEncoding(m[1])) 56 | enc = m[1] ; 57 | } 58 | var body = "" ; 59 | function handle(s) { 60 | s.on('error',$error) ; 61 | s.on('data', function (chunk) { 62 | body += chunk ; 63 | }); 64 | s.on('end',function(){ 65 | if (res.statusCode==200) 66 | $return(body) ; 67 | else { 68 | var err = new Error("HTTP error "+res.statusCode) ; 69 | err.body = body ; 70 | err.res = res ; 71 | $error(err) ; 72 | } 73 | }) ; 74 | return s ; 75 | } 76 | 77 | switch (res.headers['content-encoding']) { 78 | // or, just use zlib.createUnzip() to handle both cases 79 | case 'gzip': 80 | case 'deflate': 81 | var z = require('zlib').createUnzip() ; 82 | handle(z); 83 | res.pipe(z); 84 | break; 85 | default: 86 | res.setEncoding(enc); 87 | handle(res) ; 88 | break; 89 | } 90 | } catch(ex) { 91 | $error(ex) ; 92 | } 93 | }).on('error',$error) ; 94 | }) ; 95 | }; 96 | return cover ; 97 | }; 98 | -------------------------------------------------------------------------------- /covers/https.js: -------------------------------------------------------------------------------- 1 | module.exports = function(nodent,config) { 2 | nodent.require('events') ; 3 | 4 | if (!config) config = {} ; 5 | if (!config.Promise) 6 | config.Promise = global.Promise || nodent.Thenable ; 7 | 8 | var http = require('https') ; 9 | var cover = Object.create(http) ; 10 | 11 | cover.request = function(opts){ 12 | return new (opts.Promise || config.Promise)(function($return,$error){ 13 | var request = http.request(opts,function(){}) ; 14 | request.on('error',$error) ; 15 | $return(request) ; 16 | }) ; 17 | }; 18 | 19 | cover.get = function(opts){ 20 | return new (opts.Promise || config.Promise)(function($return,$error){ 21 | http.get(opts,$return).on('error',$error) ; 22 | }) ; 23 | }; 24 | 25 | cover.getBody = function(opts){ 26 | return new (opts.Promise || config.Promise)(function($return,$error){ 27 | http.get(opts,function(res){ 28 | try { 29 | var enc = "utf8" ; 30 | if (res.headers['content-type']) { 31 | var m = res.headers['content-type'].match(/.*charset=(.*)\b/) ; 32 | if (m && m.length>1 && Buffer.isEncoding(m[1])) 33 | enc = m[1] ; 34 | } 35 | var body = "" ; 36 | function handle(s) { 37 | s.on('error',$error) ; 38 | s.on('data', function (chunk) { 39 | body += chunk ; 40 | }); 41 | s.on('end',function(){ 42 | if (res.statusCode==200) 43 | $return(body) ; 44 | else { 45 | var err = new Error("HTTP error "+res.statusCode) ; 46 | err.body = body ; 47 | err.res = res ; 48 | $error(err) ; 49 | } 50 | }) ; 51 | return s ; 52 | } 53 | 54 | switch (res.headers['content-encoding']) { 55 | // or, just use zlib.createUnzip() to handle both cases 56 | case 'gzip': 57 | case 'deflate': 58 | var z = require('zlib').createUnzip() ; 59 | handle(z); 60 | res.pipe(z); 61 | break; 62 | default: 63 | res.setEncoding(enc); 64 | handle(res) ; 65 | break; 66 | } 67 | } catch(ex) { 68 | $error(ex) ; 69 | } 70 | }).on('error',$error) ; 71 | }) ; 72 | }; 73 | 74 | return cover ; 75 | }; 76 | -------------------------------------------------------------------------------- /covers/map.js: -------------------------------------------------------------------------------- 1 | function MapError(message) { 2 | Error.apply(this,arguments) ; 3 | this.name = 'MapError'; 4 | } 5 | MapError.prototype = Object.create(Error.prototype); 6 | MapError.prototype.constructor = MapError; 7 | 8 | module.exports = function(nodent,opts) { 9 | if (!opts) opts = {} ; 10 | if (!opts.Promise) 11 | opts.Promise = global.Promise || nodent.Thenable ; 12 | 13 | function map(what,result,asyncFn) { 14 | var hasError = false ; 15 | if (typeof what=="number") { 16 | var period = [] ; 17 | period.length = Math.floor(what) ; 18 | period.forEach = function(fn) { 19 | for (var i=0; iv3.0.0 really want it 3 | */ 4 | 5 | module.exports = function(nodent,config) { 6 | /** 7 | * NoDentify (make async) a general function. 8 | * The format is function(a,b,cb,d,e,f){}.noDentify(cbIdx,errorIdx,resultIdx) ; 9 | * for example: 10 | * http.aGet = http.get.noDentify(1) ; // The 1st argument (from zero) is the callback. errorIdx is undefined (no error) 11 | * 12 | * The function is transformed from: 13 | * http.get(opts,function(result){}) ; 14 | * to: 15 | * http.aGet(opts).then(function(result){}) ; 16 | * 17 | * @params 18 | * idx The argument index that is the 'callback'. 'undefined' for the final parameter 19 | * errorIdx The argument index of the callback that holds the error. 'undefined' for no error value 20 | * resultIdx The argument index of the callback that holds the result. 21 | * 'undefined' for the argument after the errorIdx (errorIdx != undefined) 22 | * [] returns all the arguments 23 | * promiseProvider For promises, set this to the module providing Promises. 24 | */ 25 | return function noDentify(idx,errorIdx,resultIdx,promiseProvider) { 26 | promiseProvider = promiseProvider || nodent.Thenable ; 27 | var fn = this ; 28 | return function() { 29 | var scope = this ; 30 | var args = Array.prototype.slice.apply(arguments) ; 31 | var resolver = function(ok,error) { 32 | if (undefined==idx) // No index specified - use the final (unspecified) parameter 33 | idx = args.length ; 34 | if (undefined==errorIdx) // No error parameter in the callback - just pass to ok() 35 | args[idx] = ok ; 36 | else { 37 | args[idx] = function() { 38 | var err = arguments[errorIdx] ; 39 | if (err) 40 | return error(err) ; 41 | if (Array.isArray(resultIdx) && resultIdx.length===0) 42 | return ok(arguments) ; 43 | var result = arguments[resultIdx===undefined?errorIdx+1:resultIdx] ; 44 | return ok(result) ; 45 | } ; 46 | } 47 | return fn.apply(scope,args) ; 48 | } 49 | return new promiseProvider(resolver) ; 50 | }; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /docs/changelog-2.md: -------------------------------------------------------------------------------- 1 | 18-Sep-16 v2.6.7, v2.6.8 2 | 3 | - Handle loops with no test condition `for(;;){}` 4 | - Don't attempt to hoist `export`ed named declarations 5 | - Correctly identify Babel types Object/ClassMethod as scopes to avoid illegal mappings 6 | 7 | 05-Sep-16 v2.6.6 8 | 9 | - Fix JS output routine which (incorrectly) removed the asterisk from `yield *`. 10 | - Improve syntax testing to catch differences in primitive values in ASTs 11 | 12 | 26-Aug-16 v2.6.5 13 | 14 | - Fix JS output routine which (incorrectly) removed parenthesis from `a || (()=>b)` causing a precedence problem. 15 | 16 | 20-Aug-16 v2.6.4 17 | 18 | - Fix issue with `for..of` with a `const` or destructuring initializer 19 | - Optimize EagerThenable and guard multiple Promise resolutions 20 | 21 | 06-Aug 16 v2.6.3 22 | 23 | - Fix issue with non-trivial destructuring assignments (fixes https://github.com/MatAtBread/fast-async/issues/8 - thanks to @simonbuchan) 24 | - Fix case where empty "else" block throws an expcetion (fixes https://github.com/MatAtBread/nodent/issues/50 - thanks to @Antender) 25 | - Fix case where single line exported function was incorrectly hoisted with no reference (fixes https://github.com/MatAtBread/fast-async/issues/7 - thanks to @simonbuchan, @naturalethic and @nightwolfz) 26 | - Bump acorn to v3.3.0 27 | 28 | 20-Jul 16 v2.6.2 29 | 30 | - Update acorn-es7-plugin to fix issue with `export async` in webpack 31 | - Fix edge case where a continuation function is treated as a block-scoped 32 | 33 | 15-Jul 16 v2.6.0 34 | 35 | - Optimize case where 'engine' generates an 'awaitAnywhere' Promise-style callback for an async function nested inside a sync function, and `await` is legal. 36 | - Bump version to make support for 'engine' mode easier to detect in toolchains. 37 | 38 | 14-Jul-16 v2.5.10 39 | 40 | - Add 'engine' mode that _only_ transpiles the nodent ES7 extensions (`async get x(){}`, `async throw x`, `async return` and `await` anywhere). Standard ES7 async/await constructs are passed through the compiler unchanged to be run by the underlying engine (e.g. Chrome v53 or Edge v14). 41 | - Implement parsing for proposed ES7 Object spread `var {a,b,...x} = y ;` used in Babel (see https://github.com/MatAtBread/fast-async/issues/6) 42 | 43 | 08-Jul-16 v2.5.9 44 | 45 | - Revert change to runtime inclusion in 2.5.8 as it breaks some live uses of browserify/webpack, and was only included to make istanbul work 46 | - Correctly hoist and implement block scoping for `let`, `const`, etc. Note: the actual mapping attempts to provide the most compatable code since pre-ES6 implementations of `const` differ between JS engines and strict/sloppy mode. It is possible some early code that works on non-standard JS implementations may execute differently or fail to compile. Additionally, use of `let` and `const` is slightly slower is it involves the creation of additional scopes in awaited callbacks. 47 | - Implement dual-mode test for const scoping 48 | - Fix typo in covers/https to prevented get() from working 49 | - Fix path resolution for nodent.require() built-ins 50 | - Fix typos when defining writable Object properties 51 | 52 | 04-Jul-16 v2.5.7 53 | 54 | - Correctly export MapError (for instanceof) as map.MapError 55 | 56 | 27-Jun-16 v2.5.6 57 | 58 | - Correctly bind `this` inside loops if it is referenced (https://github.com/MatAtBread/nodent/issues/39). Many thanks to https://github.com/jeffreylin for the test case and fix. 59 | - Fix command-line option `--use=(mode)` with text input 60 | - Bump acorn-es7-plugin to to 1.0.15 61 | 62 | 06-Jun-16 v2.5.5 63 | 64 | - Correct hoisting of destructing var declarations (implemented in nodejs >6.0.0) 65 | 66 | 18-May-16 v2.5.4 67 | 68 | - Bump acorn-es7-plugin (parses comments between async and function correctly) 69 | - Correct resolution of package.json for npm >v3.x to ensure modules using different nodent configurations read the 'nearest' one based on the location of the source, not the nodent installation directory 70 | 71 | 03-May-16 v2.5.2, v2.5.3 72 | 73 | - Update to latest acorn (2.5.3) 74 | - Update acorn-es7-plugin to correctly parse the statement `export async function name(){...}` as _async function name(){...}_ is a valid named declaration. (2.5.2) 75 | 76 | 21-Apr-16 v2.5.1 77 | 78 | - Place runtimes ($asyncbind and $asyncspawn) in a separate file ('lib/runtime.js') so the dedicated Babler or other tool builder can extract them without having to include the entire compiler. 79 | 80 | 01-Apr-16 v2.5.0 81 | 82 | - Implement `nodent.EagerThenable()` to provide Promise-like (but unchainable) execution semantics (eager evaluation, asynchronous resolution) 83 | - Implement new test harness to collate performance by mode and Promise implementation 84 | - Allow optional passing of a Promise type to the covers http, https, map, events and movre Thenable to it's own fix to ease integration with Browserify or Webpack (specifically, these covers can be required directly as there is no hard dependancy on the 'nodent' parameter, and so no need to require the entire library into thebrowser). The default behaviour is now to use the global.Promise if present, or nodent.Thenable if not. 85 | - Update README 86 | 87 | 01-Mar-16 v2.4.1 88 | 89 | - Significant improvement in compilation speed by re-factoring output.js (thanks to [@davidbonnet](https://github.com/davidbonnet) for pointing it out) 90 | - Update to acorn v3.0.4 91 | 92 | 04-Feb-16 v2.4.0 93 | 94 | - Update to [Acorn v2.7.0](https://github.com/ternjs/acorn/commit/1405436064bff087f14af55a763396aa5c0ca148). This tightens up the parsing of some ES6 edge cases and could possibly [break](https://github.com/ternjs/acorn/pull/317) old ES5 sloppy mode code 95 | - Implement 'eager' evaluation for 'ES7' mode (promises & generators always were eager). 96 | 97 | 02-Feb-16 v2.3.11-v2.3.13 98 | 99 | - Fix issue where different versions of nodent attempt to use different loggers 100 | - Fix typo in mapCondOp 101 | - Improve compiler performance (approx 25%) 102 | - Fix issues related to the generation of nested FunctionDeclarations in ES5-Strict mode 103 | - Re-implement mapLogicalOps & mapCondOps to generate correct code for expressions like `a || b && await c`. Previous version produced code that wouldn't run. 104 | - Allow the option `{log:false}` instead of a no-op function 105 | - Correctly place directives at the top of the Program/function when hoisting declarations. 106 | - Thanks to https://github.com/epoberezkin for the additional test cases and enhancements 107 | 108 | 17-Dec-15 v2.3.10 109 | 110 | - Provide the cover 'asyncfunction' which implements the type `AsyncFunction` to dynamically compile and create asynchronous functions. 111 | 112 | 16-Dec-15 v2.3.9 113 | 114 | - Correct cases where arrow functions contain deeply nested expressions containing await and logical/conditional operators 115 | - Fix edge cases in code output (sparse array constants, object pattern precedence, generator member functions), add everything.js syntax tests 116 | 117 | 10-Dec-15 v2.3.7 118 | 119 | - Correctly asynchronize ES6 `for...in` loops. 120 | - Update the plugin code to remove 'async' and 'await' from the super-strict keyword tests introduced in acorn v2.6.x that generate parse errors before the plugin gets a chance to manage them. Also compatible with acorn v2.5.2 as used by previous versions of nodent. 121 | - Remove spurious 'debugger' statement, fix case where for..in body is a single expression. 122 | 123 | 09-Dec-15 v2.3.5 124 | 125 | - Correctly asynchronize ES6 `for...of` loops. 126 | 127 | 08-Dec-15 v2.3.4 128 | 129 | - Mark ArrowFunctionExpression containing a BlockStatement as having a scope (it does in Chrome 46) to constrain hoisting of variables declared inside Arrow Functions 130 | - Correct 'return undefined' suppression in object/class methods (as well as normal functions) 131 | - Numerous fixes to make Babel-style Object/ClassMethod play nicely with the ESTree Property & MethodDefinition (v2.3.1-2.3.3) 132 | 133 | 07-Dec-15 v2.3.0 134 | 135 | - Implement version-aware in-process JS compiler so modules built with different versions of nodent can co-exist 136 | - Implement wrapAwait option to allow for the `await nonPromise` edge-case enabled in the standard implementation 137 | - Implement 'optionSets' for each `use nodent` directive and allow their specification in the package.json to avoid use unnecessary use of setDefaultCompileOptions() and the consequent dependency between code and environment. 138 | - Implement labeled `break` and `continue` containing `await` 139 | - Only suppress the automatic insertion of `return undefined` if a function uses `async return` or `async throw`. Other async functions now return `undefined` asynchronously if the run to completion. 140 | 141 | 04-Dec-15: v2.2.10 142 | 143 | - Fix error that mangled the declaration of a `let` statement under certain conditions 144 | 145 | 24-Nov-15: v2.2.9 146 | 147 | - Report the original filename being parsed in handling SyntaxError from acorn. 148 | - Only warn about for...in/of loops if they contain an `await` 149 | 150 | 23-Nov-15: v2.2.8 151 | 152 | - Fix case where `await` inside a non-async arrow function attempted to evaluate the await outside of the function body. Create the test case es6-object-arrow to catch this case. 153 | 154 | 12-Nov-15: v2.2.7 155 | 156 | - Correctly bind 'Finally' so that 'this' is maintained in success cases 157 | - Return initialize from setDefaultCompileOptions() so the statement `nodent = require('nodent').setDefaultCompileOptions(...)()` works 158 | - Fix implementation of Object.isThenable 159 | 160 | 06-Nov-15: v2.2.6 161 | 162 | - Fix incorrect 'async' value on AST Property and correctly use the Property.value.async for full compliance with the ESTree spec. 163 | - Update to acorn-es7-plugin 1.0.9 (fixes source location for async and await, and adds tests thanks to @jamestalmage) 164 | 165 | 04-Nov-15: v2.2.4 166 | 167 | - Support enhanced ESTree constructs as used by Babel v6.x.x for [fast-async](https://www.npmjs.com/package/fast-async) Babel plugin 168 | - Only hoist (scoped) declarations if the scope contains an 'await'. 169 | 170 | 30-Oct-15: v2.2.2 171 | 172 | - Correct case where an ArrowFunctionExpression.body is a SequenceExpression (requires parens), e.g `x => (x,y)`, which is different from `x => x,y` 173 | - Include parentheses in the expression +(+x) to avoid it looking like ++x 174 | 175 | 29-Oct-15: v2.2.0 176 | 177 | - Implement the correct conditional execution semantics for `&& || ?:` whether they contain `await` expressions or not. 178 | - Revert to `'sourceType: 'script'` as 'module' forces 'strict' mode and breaks some existing files. You can override the sourceType (see v2.1.11) if necessary. 179 | - Enable 'import' and 'export' statements, even in 'script' mode. Nodent does nothing with these statements, but simply passes them through to your execution platform or transpiler to implement. 180 | - Add syntax testing to the test suite. This has been tested against over 75,000 .js files and a number of edge cases has been fixed. 181 | - Throw a nodent::map.MapError (derived from Error) if the `map` cover encounters an error, or one of the delegates does when `throwOnError:true` 182 | 183 | 25-Oct-15: v2.1.11 184 | 185 | - Fix a number of errors related to the output ES6 `import` and `export` statements 186 | - Change the default parsing sourceType from 'script' to modules. Use `nodent.setDefaultCompileOptions({parser:{sourceType:'script'})` to switch back. 187 | - Correct parenthesis on CallExpression & MemberExpression and some other precedence edge cases 188 | - Add syntax tests 189 | 190 | 22-Oct-15: v2.1.10 191 | 192 | - Expose acorn parser options to allow for 'module' parsing in browserifyu-nodent 193 | - Correct 'writable' descriptor so that the fast-async can ship the function binder on each file (ugly, but there's no way to include a runtime from a babel plugin) 194 | 195 | 21-Oct-15: v2.1.9 196 | 197 | - Implement correct async semantics for 'finally' clause, add try/catch/finally tests 198 | - Fix case where 'finally' block is not followed by any code at all 199 | - Fix 'double exception' case where $Catch threw both synchronous and asynchonously. 200 | - Fix 'async return;' (with no argument) in generator mode 201 | - Separate es5 and es6 parser tests (since tests/parser.js used to fail on node<4.0.0) 202 | 203 | 08-Oct-15: v2.1.3 204 | 205 | - Rationalise CLI option parsing. Allow javascript/ast from stdin 206 | - Fix get/set method output 207 | - Fix method async get _() {} 208 | - Error on method async set _() {} 209 | 210 | 06-Oct-15: v2.1.0 211 | 212 | - BREAKING CHANGE: The ES7 extensions _return async ..._ and _throw async ..._ have been changed to `async return...` and `async throw...`. This was necessary as the inability to parse 'return async function()...' unambiguously is (clearly) a mistake. If you have a large body of code using the previous syntax extension, stick to v2.0.x or earlier, however it is typically a simple search-and-replace (it was in all our code). 213 | - `async` is now only a keyword in the correct contexts, specifically before a function declaration, function expression, arrow function or member function. Elsewhere it is parsed as an identifier (i.e. a variable, named function, etc.). This change has been made to be closer to the ES7 specification for 'async'. 214 | - `await` is now only a keyword in the correct contexts, specifically inside an `async` function body (or arrow expression). This change has been made to be closer to the ES7 specification for 'await'. Additionally, outside of an `async` function body, nodent allows `await` where it cannot be an identifier. In practice this means almost everywhere, except when the argument to `await` is parenthesized, i.e. from a standard function you can `await x` (as before, with a warning), but you cannot `await (x)` as it parses as a function call to a a function called 'await'. Nodent translates 'await' outside a function into a ".then(...)" call. 215 | - Added the `asyncStackTrace` environment option, which shows the current stack and the async caller (if available). 216 | 217 | 02-Oct-15: v2.0.4 218 | 219 | - Add --pretty to cli (output input, no transformation) 220 | - Add [] as a final option to .noDentify() to forward all arguments to the callback to the awaiting call (useful for very non-standard callbacks that split results across parameters) 221 | - Include the first line of the async stack trace (usually the message) 222 | - Add 'npm test' script Rationalise x-* tests Add asyncify test 223 | 224 | 29-Sep-15: v2.0.2 225 | 226 | - Add --sourcemap option to command line 227 | - Tidy up stack trace mapping 228 | - Add option throwOnError to covers/map (and test case) 229 | - Remove extraneous line end after "debugger;" statement 230 | - Only set EventEmitter.prototype.wait once (since covers can now be re-instantiated) 231 | 232 | 27-Sep-15: v2.0.1 233 | 234 | - Fix case where `if (x) return await y ;` incorrectly evaluated the `await` before the test. 235 | 236 | 23-Sep-15: v2.0.0. Initial release of Nodent v2.x.x., which has moved from UglifyJS to the acorn parser and the ESTree AST representation, mainly for performance and to support ES6 targets such as Node v4.x.x. See "upgrading" below. 237 | 238 | -------------------------------------------------------------------------------- /docs/helpers.md: -------------------------------------------------------------------------------- 1 | Built-in conversions and helpers 2 | ============================== 3 | 4 | Nodentify has a (small but possibly growing) set of covers for common Node modules. You specify these through the `require` function: 5 | 6 | var nodent = require('nodent')() ; 7 | var nhttp = nodent.require('http') ; 8 | 9 | Some covers can accept a configuation object, in this case specify the options in the second parameter: 10 | 11 | var http = nodent.require('http',{autoProtocol:true}) ; 12 | 13 | "http" and "https" 14 | ------------------ 15 | The nodent version of http.get returns a Thenable: 16 | 17 | nhttp.get(options).then(function(response){},function(error){}) ; 18 | 19 | Hopefully you'll recognise this and be able to see you can now invoke it like: 20 | 21 | response = await nhttp.get(options) ; 22 | 23 | To make life even easier, the response is covered too, just before the first callback is invoked with an addition async function called "wait", that waits for a named event. The whole setup is therefore: 24 | 25 | var nodent = require('nodent')() ; // You have to do this somewhere to enable nodent 26 | ... 27 | var http = nodent.require('http') ; 28 | 29 | // Make a request. Nodent creates the callbacks, etc. for you 30 | // and so you can read the line as "wait for the response to be generated" 31 | var response = await http.get("http://npmjs.org/~matatbread") ; 32 | 33 | var body = "" ; 34 | response.on('data',function(chunk){ body += chunk ;} ; 35 | 36 | // Wait for the "end" event 37 | await response.wait('end') ; 38 | 39 | // The response is complete, print it out 40 | console.log('The response is:\n"+body) ; 41 | 42 | http.request is similar, but not identical as you will need access to the request object to end it (amongst other things): 43 | 44 | var req = await http.request(options) ; 45 | req.end() ; // Do whatever you need to with the request 46 | // Wait for the "response" event 47 | var response = await req.wait('response') ; 48 | var body = "" ; 49 | response.on('data',function(chunk){ body += chunk ;} ; 50 | // Wait for the response to be completed 51 | await response.wait('end') ; 52 | console.log('The response is:\n"+body) ; 53 | 54 | The convenience function http.getBody(options) asynchronously gets a body encoded in UTF-8: 55 | 56 | console.log('The response is:", 57 | await http.getBody("http://www.example.com/something")) ; 58 | 59 | The "http" cover (not https) can accept a single configuration option 'autoProtocol' that makes get(), request() and getBody() examine the passed url string or URL and use either http or https automatically. The default is "false", meaning request URLs via https will fail with a protocol mismatch. 60 | 61 | "map" 62 | ----- 63 | The nodent cover "map" works like an aynchronous, parallel object/array mapper, similar to Array.prototype.map() or Promsie.all(). The map function takes three parameters: 64 | 65 | * the entity to iterate over, 66 | * optionally an object in which to place the results (they are returned from the async map in any case), 67 | * the async function to call on each iteration. 68 | 69 | The function completes when all the aync-iteration function calls have completed (via a return or exception). The order of execution of each async function is not guarenteed. When complete, the async-return is a complementary object or array containing the mapped values as returned asynchronously. If present, the return values are placed into the optional second parameter. If omitted, a new object or array is created to hold the results. The initial argument (the entity to iterate over) can be either: 70 | 71 | * An Object - each field is passed to the async-iterator function 72 | * An Array - each element is passed to the async-iterator function 73 | * A single Number - the async function is invoked with the integer values 0 to Number-1 74 | * An array or Object of async functions - each function in the array is invoked asynchronously. In this case the third parameter must be omitted. 75 | 76 | Example: mapping an object 77 | 78 | // Use nodent.map 79 | var map = nodent.require('map') ; 80 | 81 | // Asynchronously map every key in "myObject" by adding 1 to the value of the key 82 | mapped = await map(myObject,async function(key){ 83 | // This can be async without issues 84 | return myObject[key]+1 ; 85 | }) ; 86 | // All done - mapped contains the new object with all the elements "incremeneted" 87 | 88 | 89 | Example: map an array of URLs to their content 90 | 91 | // Use nodent.map & http 92 | var map = nodent.require('map') ; 93 | var http = nodent.require('http') ; 94 | 95 | mapped = await map(['www.google.com','www.bbc.co.uk'],async function(value,index){ 96 | // Get the URL body asynchronously. 97 | return await http.getBody("http://"+value) ; 98 | }) ; 99 | // All done - mapped is the new array containing the bodies 100 | 101 | Example: iterate through a set of integer values and do something asynchronous with each one. 102 | 103 | // Use nodent.map & http 104 | var map = nodent.require('map') ; 105 | var http = nodent.require('http') ; 106 | 107 | mapped = await map(3,async function(i){ 108 | // Get the URL body asynchronously. 109 | return await nodent.http.getBody("http://example.com/cgi?test="+i) ; 110 | }) ; 111 | // All done - mapped is the new array containing the bodies 112 | 113 | Example: execute arbitrary async functions in parallel and return when they are all complete 114 | 115 | // Use nodent.map 116 | var map = nodent.require('map') ; 117 | 118 | mapped = await map([asyncFn("abc"),asyncFn2("def")]) ; 119 | 120 | // All done - mapped is an new array containing the async-returns 121 | 122 | Example: execute arbitrary labelled async functions in parallel and return when they are all complete 123 | 124 | // Use nodent.map 125 | var map = nodent.require('map') ; 126 | 127 | mapped = await map({for:asyncFn("abc"),bar:asyncFn2("def")}) ; 128 | console.log(mapped.foo, mapped.bar) ; 129 | 130 | // All done - mapped is an new object containing the async-returns in each named member 131 | 132 | In the latter two cases, where there is only an single parameter, the async return value from `map` is a corresponding array or object to the parameter where each member has been resolved if Thenable (a Promise or async function value), or passed through unchanged if not Thenable. 133 | 134 | The order of execution is not guaranteed (as with all calls to map), but the completion routine will only be called when all async functions have finished either via a return or exception. the first function (at index [0]) and the async-return of the second funcrion (at index [1]). There is no programmatic limit to the number of async functions that can be passed in the array. Note that the functions have no useful parameters (use a closure or wrap the function if necessary). The order of execution is not guaranteed (as with all calls to map), but the completion routine will only be called when all async functions have finished either via a return or exception. 135 | 136 | ### Exceptions in mapped functions 137 | By default, in the event of an error or exception in the async-mapping function, the error value is substitued in the mapped object or array. This works well since all the exceptions will be instances of the JavaScript Error() type, and so they can be easily tested for in the mapped object after completion. 138 | 139 | The map() function only errors if an async function illegally returns more than once (including multiple errors or both an error and normal response). 140 | 141 | Alternatively, if instantiated with the option `throwOnError`, if any of the async invocations throw an exception, `map()` will throw an Error() when all the functions have completed, with a member called `results` containing the other results. To use this option: 142 | 143 | var map = nodent.require('map',{throwOnError:true}) ; 144 | 145 | Instances of 'map' are independent of each other - you can require() both the throwing and non-throwing version in different modules, or the same module as different variables. 146 | 147 | "asyncfunction" 148 | --------------- 149 | 150 | The `AsyncFunction` type is returned by requiring 'asyncfunction'. This creates a class that can compile async functions on the fly (like `new Function()`). 151 | 152 | To access the type: 153 | 154 | var AsyncFunction = nodent.require('asyncfunction',opts) ; 155 | 156 | ...where the `opts` parameter is optional, but if supplied contains the compiler flags as specified in [Advanced Configuration](../README.md#advanced-configuration). By default AsyncFunction uses Promises if they are defined globally, and ES7 mode otherwise. 157 | 158 | Once defined, you can create async functions on the fly just like normal functions: 159 | 160 | // Create a new async function 161 | var add = new AsyncFunction("i","j","return i+j") ; 162 | 163 | console.log(add instanceof Function) // true: An AsyncFunction is also a function 164 | console.log(add instanceof AsyncFunction) // true 165 | console.log(add.toString()) // The original source "return i+j" 166 | console.log(add.toES5String()) // The compiled source 167 | console.log(await add(10,11)) // 21 168 | 169 | nodent.asyncify 170 | --------------- 171 | This helper function wraps "normal" Node asynchronous functions (i.e. those whose final paramter is of the form `function(err,data)`) to make them usuable with `await`. For example, to asyncify the standard Node module 'fs': 172 | 173 | // Require 'fs' 174 | var fs = require('fs') ; 175 | // Get a reference to nodent.asyncify 176 | var asyncify = require('nodent').asyncify ; 177 | // Asyncify 'fs' 178 | var afs = asyncify(nodent.Thenable)(fs) ; 179 | console.log((await afs.readFile("./test/a.js")).toString()) ; 180 | 181 | By default, asyncify creates an object that has it's ancestor as its prototype with functions members mapped to the await call signature. 182 | Internally, asyncify filters these so that only functions that don't end in 'Sync' and that have a member named the same without 'Sync'. 183 | For 'fs', this works (readFile does not end in Sync, and so is mapped, readFileSync ends in 'Sync' and a member called 'readFile' exists). 184 | 185 | You can optionally supply your own filter to asyncify. For example to only map a function called 'queryDb': 186 | 187 | var aDB = asyncify(DB,function(name,newObject){ 188 | return name=="queryDb" ; 189 | }) ; 190 | 191 | You can also supply an option third parameter to asyncify() to avoid name-clashes (you often won't need this as asyncify builds a new object with the original as the prototype). 192 | 193 | var afs = asyncify(require('fs',null,"Async") ; 194 | // Async version of readFile() has "Async" appended 195 | await afs.readFileAsync("./mydata.txt") ; 196 | 197 | If you specifiy the environment option `augmentObject` as in `require('nodent')({augmentObject:true})` you can directly asyncify an API, for example: 198 | 199 | // Create a redis client from a library that can be used with await 200 | var redis = require('redis').asyncify() ; 201 | 202 | -------------------------------------------------------------------------------- /docs/syntax.md: -------------------------------------------------------------------------------- 1 | Async and Await syntax and usage 2 | ====================== 3 | 4 | The following sections show you how to declare, call and use async functions using the ES7 `async` and `await` keywords, as well as from existing ES6 and ES5 code. 5 | 6 | Declaring Async Functions 7 | ------------------------- 8 | To declare an asynchronous function, put `async` in front of the definition. `async` is an ES7 keyword. You shouldn't use it as a top level identifier (variable or function name) in ES7 code. This is how it looks: 9 | 10 | async function myFunc(args) { 11 | body ; 12 | return expr ; 13 | } 14 | 15 | [_TRY-IT_](http://nodent.mailed.me.uk/#async%20function%20myFunc(args)%20%7B%0A%20%20body%20%3B%0A%20%20return%20expr%20%3B%0A%7D) 16 | 17 | (NB: There are other mappings too, like checking for nested functions and try catch blocks, but the essence is demonstrated in the example above). 18 | 19 | async function myFunc(args) { 20 | if (!args) 21 | throw new Error("Missing parameters") ; 22 | return doSomething(args) ; 23 | } 24 | 25 | [_TRY-IT_](http://nodent.mailed.me.uk/#async%20function%20myFunc(args)%20%7B%0A%20%20if%20(!args)%0A%20%20%20%20throw%20new%20Error(%22Missing%20parameters%22)%20%3B%0A%20%20return%20doSomething(args)%20%3B%0A%7D%0A) 26 | 27 | Like any function returning a Promise, you invoke the function and use the Promise via code such as: 28 | 29 | myFunc(args).then(function(returnValue){ 30 | -- do something -- // Success! Use returnValue 31 | }, function(exception) { 32 | -- do something else // Bad! Handle the error 33 | }) ; 34 | 35 | Async invocation 36 | ---------------- 37 | 38 | Thhe ES7 keyword `await` is implemented as a unary prefix operator (in the same kind of place you might find 'typeof' or 'delete', and also before object member definitions). It is this transformation that stops all the crazy indenting that async callbacks generate. 39 | 40 | var result = await myFunc(args) ; 41 | moreStuff(result) ; 42 | 43 | This is transformed into the code: 44 | 45 | return myFunc(args).then(function($await_myFunc$1) { 46 | var result = $await_myFunc$1 ; 47 | moreStuff(result) ; 48 | },$error) ; 49 | 50 | [_TRY-IT_](http://nodent.mailed.me.uk/#var%20result%20%3D%20await%20myFunc(args)%20%3B%0AmoreStuff(result)%20%3B%0A) 51 | 52 | Awaiting multiple times 53 | ----------------------- 54 | 55 | A statement or expression can combine multiple async results, for example: 56 | 57 | console.log(await as1(1),await as2("hello")+await as1(3)) ; 58 | [_TRY-IT_](http://nodent.mailed.me.uk/#console.log(await%20as1(1)%2Cawait%20as2(%22hello%22)%2Bawait%20as1(3))%3B) 59 | 60 | This is both syntactically and semantically meaningful, but in the current implementation will call the async functions serially (note: the order in which they are invoked is not guaranteed). It might well be more efficient in this case to use the 'map' cover function (see below) to execute all the functions in parallel first, and use the results: 61 | 62 | var nodent = require('nodent')() ; 63 | var map = nodent.require('map') ; 64 | 65 | // Execute all the async functions at the same time 66 | mapped = await map([as1(1),as2("hello"),as1(3)]) ; 67 | // When they're done: 68 | console.log(mapped[0],mapped[1]+mapped[2]) ; 69 | 70 | Most Promise libraries have a function called `Promise.all()`, which is similar to `nodent.map`. `nodent.map` is more flexible in that `Promise.all()` only accepts arrays whereas `map` can map Objects and apply a specific async function to each value in the Array/Object. See below for more details and examples). Any values passed to `map` that are not Thenable (i.e. Promises or async function calls) are simply passed through unchanged. 71 | 72 | Invoking async functions from ES5/6 73 | ----------------------------------- 74 | 75 | As described above, the return type from an async function is a Promise (or, to be accurate it's whatever type you assign the scoped variable `Promise` - if this is `nodent.Thenable`, then it has a `then()` member, and behaves enough like a Promise to work with Promises/A+-compliant libraries). So, to invoke an `async function` from a normal ES5 script you can use the code: 76 | 77 | // An async function defined somewhere 78 | async function readFile() { ... } 79 | 80 | // Calling it using ES5 syntax in a non-nodented way 81 | readFile(filename).then(function(data){ 82 | ... 83 | },function(err){ 84 | .... 85 | }) ; 86 | 87 | Similarly, you can wait for any Promise with the `await`keyword - i.e. not just functions you defined yourself as `async`: 88 | 89 | // The elasticsearch library returns a Promise if you don't supply a callback 90 | var resultPromise = elasticsearch.search(query) ; 91 | console.log(await resultPromise) ; 92 | 93 | or just: 94 | 95 | console.log(await elasticsearch.search(query)) ; 96 | 97 | Defining async functions from ES5 98 | --------------------------------- 99 | Use nodent! And any function returning a Promise (or Thenable) can be used with `await`. 100 | 101 | Missing out await 102 | ----------------- 103 | Forgetting to put `await` in front of an async call is easy, and usually not what you want - you'll get a Promise. This can be useful though, when you need a reference to an async return value: 104 | 105 | ``` 106 | var fn ; 107 | if (x) 108 | fn = test(x) ; // 'test' is async - don't await 109 | else 110 | fn = testDefault() ; // testDefault is async - don't await 111 | 112 | return await fn ; // Now await for which function fn refers to 113 | 114 | ``` 115 | 116 | ``` 117 | async function f() { return true ; } 118 | 119 | var x = f() ; // 'x' = a Promise 120 | 121 | // Call x using nodent 122 | try { 123 | result = await x ; 124 | ... 125 | } catch(error) { 126 | ... 127 | } 128 | 129 | // or call x from ES5/6 130 | x.then(function(result){ 131 | ... 132 | },function(error){ 133 | ... 134 | }) ; 135 | 136 | ``` 137 | Remember that calling an async function without `await` still runs the functions - you just can't get the return value, _except_ if use are using lazyThenables in -es7 mode. 138 | -------------------------------------------------------------------------------- /htmlScriptParser/index.js: -------------------------------------------------------------------------------- 1 | module.exports = function(nodent,html,url,options){ 2 | var f = [[],[]] ; 3 | var re = [/(.*)(]*>)(.*)/i,/(.*)(<\/script>)(.*)/i] ; 4 | var m = 0 ; 5 | var initScript = true ; 6 | html = html.split("\n") ; 7 | 8 | for (var l=0; l 2 | 3 | Nodent SPA test 4 | 5 | 12 | 17 | 18 | OK 19 | 20 | 21 | -------------------------------------------------------------------------------- /lib/runtime.js: -------------------------------------------------------------------------------- 1 | // Now moved into its own module, but still available 2 | // here for anyone who referenced it as 'nodent/lib/runtime' 3 | module.exports = require('nodent-runtime'); 4 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nodent", 3 | "version": "3.2.13", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "acorn": { 8 | "version": "5.7.4", 9 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.4.tgz", 10 | "integrity": "sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==" 11 | }, 12 | "acorn-es7-plugin": { 13 | "version": "1.1.7", 14 | "resolved": "https://registry.npmjs.org/acorn-es7-plugin/-/acorn-es7-plugin-1.1.7.tgz", 15 | "integrity": "sha1-8u4fMiipDurRJF+asZIusucdM2s=" 16 | }, 17 | "nodent-compiler": { 18 | "version": "3.2.13", 19 | "resolved": "https://registry.npmjs.org/nodent-compiler/-/nodent-compiler-3.2.13.tgz", 20 | "integrity": "sha512-nzzWPXZwSdsWie34om+4dLrT/5l1nT/+ig1v06xuSgMtieJVAnMQFuZihUwREM+M7dFso9YoHfDmweexEXXrrw==", 21 | "requires": { 22 | "acorn": ">= 2.5.2 <= 5.7.5", 23 | "acorn-es7-plugin": "^1.1.7", 24 | "nodent-transform": "^3.2.9", 25 | "source-map": "^0.5.7" 26 | } 27 | }, 28 | "nodent-runtime": { 29 | "version": "3.2.1", 30 | "resolved": "https://registry.npmjs.org/nodent-runtime/-/nodent-runtime-3.2.1.tgz", 31 | "integrity": "sha512-7Ws63oC+215smeKJQCxzrK21VFVlCFBkwl0MOObt0HOpVQXs3u483sAmtkF33nNqZ5rSOQjB76fgyPBmAUrtCA==" 32 | }, 33 | "nodent-transform": { 34 | "version": "3.2.9", 35 | "resolved": "https://registry.npmjs.org/nodent-transform/-/nodent-transform-3.2.9.tgz", 36 | "integrity": "sha512-4a5FH4WLi+daH/CGD5o/JWRR8W5tlCkd3nrDSkxbOzscJTyTUITltvOJeQjg3HJ1YgEuNyiPhQbvbtRjkQBByQ==" 37 | }, 38 | "path-parse": { 39 | "version": "1.0.5", 40 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", 41 | "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=" 42 | }, 43 | "resolve": { 44 | "version": "1.5.0", 45 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", 46 | "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==", 47 | "requires": { 48 | "path-parse": "^1.0.5" 49 | } 50 | }, 51 | "source-map": { 52 | "version": "0.5.7", 53 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", 54 | "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nodent", 3 | "version": "3.2.13", 4 | "description": "NoDent - Asynchronous Javascript language extensions", 5 | "main": "nodent.js", 6 | "scripts": { 7 | "cover": "istanbul cover ./nodent.js tests -- --quick --syntax ; open ./coverage/lcov-report/index.html", 8 | "test": "cd tests && npm i --prod && cd .. && node --expose-gc ./nodent.js tests --syntax --quick && node --expose-gc ./nodent.js tests --quick --notStrict", 9 | "test-loader": "cd tests/loader/app && npm test && cd ../../..", 10 | "start": "./nodent.js" 11 | }, 12 | "bin": { 13 | "nodentjs": "./nodent.js" 14 | }, 15 | "dependencies": { 16 | "nodent-compiler": "^3.2.13", 17 | "nodent-runtime": "^3.2.1", 18 | "resolve": "^1.5.0" 19 | }, 20 | "repository": { 21 | "type": "git", 22 | "url": "https://github.com/MatAtBread/nodent.git" 23 | }, 24 | "engines": "node >= 0.10.0", 25 | "keywords": [ 26 | "Javascript", 27 | "ES7", 28 | "async", 29 | "await", 30 | "language", 31 | "extensions", 32 | "Node", 33 | "callback", 34 | "generator", 35 | "Promise", 36 | "asynchronous" 37 | ], 38 | "author": "Mat At Bread ", 39 | "license": "BSD-2-Clause", 40 | "bugs": { 41 | "url": "https://github.com/MatAtBread/nodent/issues" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /tests/.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules/ 2 | -------------------------------------------------------------------------------- /tests/codegen/cg-es7.js: -------------------------------------------------------------------------------- 1 | 'use nodent-es7 {"lazyThenables":true}'; 2 | 3 | module.exports = { 4 | name: "es7", 5 | call:async function() { 6 | return module.exports.name ; 7 | }, 8 | consume:async function(x) { 9 | return await x() ; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tests/codegen/cg-generators.js: -------------------------------------------------------------------------------- 1 | "use nodent-generators"; 2 | 3 | module.exports = { 4 | name: "generators", 5 | call:async function() { 6 | return module.exports.name ; 7 | }, 8 | consume:async function(x) { 9 | return await x() ; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tests/codegen/cg-promises.js: -------------------------------------------------------------------------------- 1 | "use nodent-promises"; 2 | 3 | var Promise = global.Promise || require('../../nodent').Thenable ; 4 | 5 | module.exports = { 6 | name: "promises", 7 | call:async function() { 8 | return module.exports.name ; 9 | }, 10 | consume:async function(x) { 11 | return await x() ; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /tests/compiler/args.js: -------------------------------------------------------------------------------- 1 | async function a() { 2 | return arguments[0] ; 3 | } 4 | 5 | var b = async function() { 6 | return arguments[1] ; 7 | } ; 8 | 9 | var c = { 10 | a:async function() { 11 | return arguments[2] ; 12 | }, 13 | b:async function() { 14 | return arguments[3] ; 15 | } 16 | } ; 17 | 18 | async function test() { 19 | var args = "the quick brown fox".split(" ") ; 20 | var r = [await a.apply(null,args),await b.apply(null,args), 21 | await c.a.apply(null,args), await c.b.apply(null,args)] ; 22 | return (r.join(" ")===args.join(" ")) ; 23 | } 24 | 25 | module.exports = test ; 26 | -------------------------------------------------------------------------------- /tests/compiler/await-usage.js: -------------------------------------------------------------------------------- 1 | 2 | async function test() { 3 | return "t" ; 4 | } 5 | 6 | module.exports = async function() { 7 | var s = await test() ?"a":"b" ; 8 | s = s+(await test() && "c") ; 9 | s = s+(await test() || "d") ; 10 | s = s+("e" && await test() ) ; 11 | s = s+("f" || await test()) ; 12 | s = s + (s?await test():"g") ; 13 | s = s + (s?"h":await test()) ; 14 | return s=="acttfth" ; 15 | } -------------------------------------------------------------------------------- /tests/compiler/complex.js: -------------------------------------------------------------------------------- 1 | var strings = "The quick brown fox jumps over the lazy dog".split(" ") ; 2 | 3 | async function test() { 4 | try { 5 | async function getLength(y) { 6 | await breathe() ; 7 | return y.length ; 8 | } 9 | 10 | var l = 0,m = 0 ; 11 | try { 12 | function length(q,cb) { 13 | cb(await getLength(q)) ; 14 | } 15 | strings.forEach(function(v){length(v,function(n){ 16 | l += n ; 17 | })}) ; 18 | 19 | for (var i=0; i<1><2><3><4>ok"; 23 | } 24 | -------------------------------------------------------------------------------- /tests/compiler/dual-decl-reorder.js: -------------------------------------------------------------------------------- 1 | async function nop(x) { return x } 2 | 3 | var a = 123, b = 2, c = await nop(a), d = 3, e = 4 ; 4 | 5 | return [ 6 | a,b,c,d,e 7 | ].toString() ; 8 | -------------------------------------------------------------------------------- /tests/compiler/dual-destructure.js: -------------------------------------------------------------------------------- 1 | async function nop(x) { return x } 2 | 3 | // work 4 | async function trivialArray() { 5 | const [a, b] = await nop([1, 2]); 6 | return [a,b].toString() 7 | } 8 | 9 | async function trivialObject() { 10 | const { a, b } = await nop({ a: 1, b: 2 }); 11 | return [a,b].toString() 12 | } 13 | 14 | async function arraySpread() { 15 | const [a, ...b] = await nop([1, 2, 3, 4]); 16 | return [a,b].toString() 17 | } 18 | 19 | // fails in transform 20 | async function arrayElide() { 21 | const [,a,,b] = await nop([1, 2, 3, 4]); 22 | return [a,b].toString() 23 | } 24 | 25 | // generate bad code, only declaring `var a, b` 26 | async function rename() { 27 | const { a, b: c } = await nop({ a: 1, b: 2 }); 28 | return [a,c].toString() 29 | } 30 | async function key() { 31 | const { a, ['b']: c } = await nop({ a: 1, b: 2 }); 32 | return [a,c].toString() 33 | } 34 | async function nestedArray() { 35 | const { a, b: [c, d] } = await nop({ a: 1, b: [2, 3] }); 36 | return [a,c,d].toString() 37 | } 38 | async function nestedObject() { 39 | const { a, b: { c, d } } = await nop({ a: 1, b: { c: 2, d: 3 } }); 40 | return [a,c,d].toString() 41 | } 42 | async function indirect() { 43 | const result = await nop({ a: 1, b: 2 }); 44 | const { a, b: c } = result; 45 | return [a,c].toString() 46 | } 47 | 48 | // Destructuring with assignment 49 | async function assignObj() { 50 | await nop(); 51 | const {x = 456} = {x:123}; 52 | return x.toString() ; 53 | } 54 | async function assignArray() { 55 | await nop(); 56 | const {x = 456} = [789]; 57 | return x.toString() ; 58 | } 59 | 60 | return [ 61 | await trivialArray(),await trivialObject(),await rename(),await key(), 62 | await nestedArray(),await nestedObject(),await indirect(), await arrayElide(), 63 | await arraySpread(), await assignObj(), await assignArray() 64 | ].toString() ; 65 | -------------------------------------------------------------------------------- /tests/compiler/dual-es6-arrow-args.js: -------------------------------------------------------------------------------- 1 | async function a() { 2 | var x = async () => ({arguments:[789]}); 3 | return ((await x()).arguments[0]===789); 4 | } 5 | 6 | async function b() { 7 | var x = () => ({arguments:[789]}); 8 | return (x().arguments[0]===789); 9 | } 10 | 11 | async function c() { 12 | var x = async () => ({arguments}); 13 | return ((await x()).arguments[0]===56); 14 | } 15 | 16 | async function d() { 17 | var x = () => ({arguments}); 18 | return (x().arguments[0]===78); 19 | } 20 | 21 | return [await a(12), await b(34), await c(56), await d(78)].toString(); -------------------------------------------------------------------------------- /tests/compiler/dual-es6-decl-reorder.js: -------------------------------------------------------------------------------- 1 | async function nop(x) { return x } 2 | 3 | var {x:a} = {x:123}, b = 2, c = await nop(a), d = 3, e = 4 ; 4 | 5 | return [ 6 | a,b,c,d,e 7 | ].toString() ; 8 | -------------------------------------------------------------------------------- /tests/compiler/dual-for-of-const-destructure.js: -------------------------------------------------------------------------------- 1 | async function nop(x) { return x } 2 | 3 | async function b() { 4 | var n = 0 ; 5 | for (const {ans:a, z} of [{ans:5,z:10},{ans:3,z:20},{ans:1,z:30}]) { 6 | n += await nop(a*z) ; 7 | } 8 | return n ; 9 | } 10 | 11 | return await b() ; 12 | -------------------------------------------------------------------------------- /tests/compiler/dual-for-of.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | async function nop(x) { return x } 4 | 5 | var n = 0 ; 6 | for (var a of [{ans:5,z:10},{ans:3,z:20},{ans:1,z:30}]) { 7 | n += await nop(a.ans*a.z) ; 8 | } 9 | return n ; 10 | -------------------------------------------------------------------------------- /tests/compiler/dual-for-sequence-init.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | async function nop(x) { return x } 4 | 5 | await nop(0); 6 | for (var a = 1, b = 2; ;) { 7 | break ; 8 | } 9 | 10 | return a+b ; 11 | -------------------------------------------------------------------------------- /tests/compiler/dual-for-sync.js: -------------------------------------------------------------------------------- 1 | async function nop() {} 2 | 3 | async function x() { 4 | var s = "" ; 5 | i:for (var i = 0;i < 3; i++) { 6 | j:for (var j = 0;j < 3; j++) { 7 | await nop(); 8 | k:for (var k = 0;k < 3; k++) { 9 | s += [i, j, k].toString()+"_"; 10 | if (k == 2) 11 | continue i; 12 | } 13 | } 14 | } 15 | return s ; 16 | } 17 | 18 | var s = "" ; 19 | i:for (var i = 0;i < 3; i++) { 20 | j:for (var j = 0;j < 3; j++) { 21 | await nop(); 22 | k:for (var k = 0;k < 3; k++) { 23 | s += [i, j, k].toString()+"_"; 24 | if (k == 2) 25 | continue i; 26 | } 27 | } 28 | } 29 | return s+await x() ; 30 | -------------------------------------------------------------------------------- /tests/compiler/dual-label-break.js: -------------------------------------------------------------------------------- 1 | var l = ""; 2 | async function nop(a) { return a ; } 3 | async function x(f) { 4 | l += "."; 5 | a:{ 6 | l += "1"; 7 | b:{ 8 | l += "2"; 9 | switch (await nop(f)) { 10 | case 'a': 11 | break a; 12 | case 'b': 13 | break b; 14 | } 15 | l += "3"; 16 | } 17 | l += "4"; 18 | } 19 | l += "5"; 20 | } 21 | 22 | await x(); 23 | await x('a'); 24 | await x('b'); 25 | return l; 26 | -------------------------------------------------------------------------------- /tests/compiler/dual-loop-scope.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | async function nop(x) { return x } 4 | var x = { 5 | ab:"ab", 6 | cd:"cd", 7 | ef:"ef", 8 | gh:"gh", 9 | 10 | async loopScope() { 11 | var x = -1; 12 | var s = ""; 13 | for (let x = 0;x < 2; x++) { 14 | s += await nop(this.ab[x]); 15 | } 16 | for (let x = 0;x < 2; x++) { 17 | s += await nop(this.cd[x]); 18 | for (let x = 0;x < 2; x++) { 19 | s += await nop(this.ef[x]); 20 | } 21 | s += await nop(this.gh[x]); 22 | } 23 | return x === -1 && s === "abcefgdefh"; 24 | } 25 | }; 26 | 27 | return await x.loopScope(); 28 | -------------------------------------------------------------------------------- /tests/compiler/dual-nested-async-finally.js: -------------------------------------------------------------------------------- 1 | var finals = 0 ; 2 | async function inc(i) { 3 | return i+1 4 | } 5 | 6 | async function test() { 7 | let responses; 8 | try { 9 | var l = async function(x) { return await inc(x) } 10 | var n = async x => await inc(x) ; 11 | async function m(x) { return await inc(x) } 12 | return await l(1)+await m(2)+await n(3) ; 13 | } catch (err) { 14 | return; 15 | } finally { 16 | finals += 1 ; 17 | } 18 | } 19 | 20 | return await test() === 9 && finals === 1 21 | -------------------------------------------------------------------------------- /tests/compiler/dual-nonblock-try.js: -------------------------------------------------------------------------------- 1 | 'use nodent'; 2 | async function nop(x) { 3 | return x; 4 | } 5 | 6 | async function _un(a, b, c) { 7 | try { 8 | await nop(); 9 | if (b) 10 | throw b; 11 | return c; 12 | } catch (ex) { 13 | return ex; 14 | } 15 | } 16 | 17 | async function _if(a, b, c) { 18 | if (a) 19 | try { 20 | await nop(); 21 | if (b) 22 | throw b; 23 | return c; 24 | } catch (ex) { 25 | return ex; 26 | } 27 | return "." 28 | } 29 | 30 | async function _label(a, b, c) { 31 | a:try { 32 | await nop(); 33 | if (b) 34 | throw b; 35 | return c; 36 | } catch (ex) { 37 | return ex; 38 | } 39 | } 40 | 41 | var s = ""; 42 | for (var i = 0;i < 8; i++) { 43 | s = s + await _un(i & 1, i & 2, i & 4)+ await _if(i & 1, i & 2, i & 4) + await _label(i & 1, i & 2, i & 4) + ", "; 44 | } 45 | return s ; 46 | -------------------------------------------------------------------------------- /tests/compiler/dual-reorder.js: -------------------------------------------------------------------------------- 1 | async function nop(x) { return x } 2 | 3 | var a,b,c ; 4 | 5 | return [await nop((a=2,b=await nop(a*3),c=b)),a,b,c].toString() -------------------------------------------------------------------------------- /tests/compiler/dual-scoped-const.js: -------------------------------------------------------------------------------- 1 | try { 2 | async function nop(x) { return x } 3 | 4 | var r = [] ; 5 | 6 | const a = 1 ; 7 | { 8 | const a = 2 ; 9 | var b = await nop(a) ; 10 | { 11 | const a = await nop(3) ; 12 | { 13 | const a = 4 ; 14 | b = a ; 15 | r.push(a,b) ; 16 | } 17 | b = a ; 18 | r.push(a,b) ; 19 | } 20 | r.push(a,b) ; 21 | } 22 | r.push(a,await nop(b)) ; 23 | return r.join(",") ; 24 | } catch (ex) { 25 | return ex.message ; 26 | } -------------------------------------------------------------------------------- /tests/compiler/dual-sloppy-const.js: -------------------------------------------------------------------------------- 1 | async function nop(x) { return x } 2 | 3 | { 4 | const b = 2; 5 | { 6 | const a = 1; 7 | return (await nop([a,b])).join(",") ; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /tests/compiler/dual-try-except.js: -------------------------------------------------------------------------------- 1 | var r = [] ; 2 | 3 | async function op(x) { 4 | if (x==='reject') throw x ; 5 | return y ; 6 | } 7 | 8 | async function a(x,y) { 9 | try { 10 | await op(x); 11 | r.push('DONE '+y); 12 | } catch (error) { 13 | r.push('EXCEPTION '+y); 14 | } 15 | finally { 16 | r.push("Finally "+x) ; 17 | } 18 | JSON.parse(y+'#'); 19 | } 20 | 21 | try { 22 | await a('resolve','A'); 23 | } catch (ex) { 24 | r.push(ex) ; 25 | } 26 | try { 27 | await a('reject','A'); 28 | } catch (ex) { 29 | r.push(ex) ; 30 | } 31 | 32 | return (r.toString()) 33 | -------------------------------------------------------------------------------- /tests/compiler/dual-try-finally-await.js: -------------------------------------------------------------------------------- 1 | 'use nodent'; 2 | 3 | async function func1() { throw new Error('func1 error'); } 4 | async function func2() { return; } 5 | 6 | async function test() { 7 | try { 8 | await func1(); 9 | } catch (err) { 10 | throw err; 11 | } finally { 12 | await func2(); 13 | } 14 | } 15 | 16 | try { 17 | throw await test(); 18 | } catch(ex) { 19 | return ex.toString() ; 20 | } 21 | -------------------------------------------------------------------------------- /tests/compiler/dual-try-finally-try-catch.js: -------------------------------------------------------------------------------- 1 | 'use nodent'; 2 | 3 | async function normalFn() { 4 | return; 5 | } 6 | 7 | async function throwingFn() { 8 | await normalFn(); 9 | JSON.parse("*"); 10 | } 11 | 12 | async function test() { 13 | try { 14 | await normalFn(); 15 | } finally { 16 | try { 17 | await throwingFn(); 18 | } catch (err) { 19 | return err.toString() ; 20 | } 21 | } 22 | } 23 | 24 | return await test(); 25 | -------------------------------------------------------------------------------- /tests/compiler/dual-try-noawait.js: -------------------------------------------------------------------------------- 1 | 'use nodent'; 2 | 3 | async function nop(x) { return x } 4 | async function fn1() { 5 | try { 6 | throw new Error(); 7 | } 8 | catch (error) { 9 | return 'caught'; 10 | } 11 | finally { 12 | return 'ok'; 13 | } 14 | } 15 | 16 | async function fn2() { 17 | try { 18 | return '1'; 19 | } 20 | finally { 21 | return '2'; 22 | } 23 | } 24 | 25 | async function fn3() { 26 | try { 27 | throw '1'; 28 | } catch (ex) { 29 | return '2'; 30 | } 31 | } 32 | 33 | async function fn(a) { 34 | try { 35 | if (a&1) 36 | return '1'; 37 | throw new Error() ; 38 | } 39 | catch (ex) { 40 | if (a&2) 41 | return '2' ; 42 | return '4' ; 43 | } 44 | finally { 45 | if (a&4) 46 | return '3' ; 47 | } 48 | } 49 | 50 | var s = "" ; 51 | for (var i=0; i<8; i++) 52 | s += await fn(i) ; 53 | return s+await fn1()+":"+await fn2()+":"+await fn3(); 54 | -------------------------------------------------------------------------------- /tests/compiler/dual-try-scoped.js: -------------------------------------------------------------------------------- 1 | 'use nodent'; 2 | 3 | async function nop(x) { return x } 4 | async function x() { 5 | 6 | const r = [] ; 7 | let x1 = await nop(4) ; 8 | { 9 | let x2 = await nop(3) ; 10 | try { 11 | const x3 = await nop(2) ; 12 | { 13 | let x1 = await nop(1) ; 14 | r.push(x1) ; 15 | } 16 | r.push(x3) ; 17 | } catch (ex) { 18 | r.push("x") ; 19 | } 20 | r.push(x2) ; 21 | } 22 | r.push(x1) ; 23 | return r.join("-") ; 24 | } 25 | 26 | return await x() ; 27 | -------------------------------------------------------------------------------- /tests/compiler/dual-while-throw.js: -------------------------------------------------------------------------------- 1 | 'use nodent'; 2 | 3 | async function foo() { 4 | JSON.parse("*"); 5 | } 6 | 7 | async function bar() { } 8 | 9 | async function baz() { 10 | do await bar(); 11 | while(false); 12 | await foo() ; 13 | } 14 | 15 | try { 16 | await baz() ; 17 | return "baz" ; 18 | } catch (ex) { 19 | return ex.message ; 20 | } 21 | -------------------------------------------------------------------------------- /tests/compiler/else-if.js: -------------------------------------------------------------------------------- 1 | async function append(a,b) { 2 | return ""+a+b; 3 | } 4 | 5 | async function test(x) { 6 | var s ; 7 | if (x==0) 8 | s = await append(x,"zero") 9 | else if (x==1) 10 | s = await append(x,"one") 11 | else 12 | s = await append(x,"?") 13 | return s ; 14 | }; 15 | 16 | async function test2(x) { 17 | var s ; 18 | if (x==0) { 19 | s = await append(x,"zero") 20 | } else { 21 | if (x==1) { 22 | s = await append(x,"one") 23 | } else { 24 | s = await append(x,"?") 25 | } 26 | } 27 | return s ; 28 | }; 29 | 30 | module.exports = async function() { 31 | var s = await test(1)+await test(0)+await test(2); 32 | var t = await test2(1)+await test2(0)+await test2(2); 33 | return s=="1one0zero2?" && s==t; 34 | } 35 | -------------------------------------------------------------------------------- /tests/compiler/es6-args.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | async function a() { 4 | return arguments[0] ; 5 | } 6 | 7 | var b = async function() { 8 | return arguments[1] ; 9 | } ; 10 | 11 | var c = { 12 | a:async function() { 13 | return arguments[2] ; 14 | }, 15 | async b() { 16 | return arguments[3] ; 17 | } 18 | } ; 19 | 20 | var q = class { 21 | async a() { 22 | return arguments[4] ; 23 | } 24 | }; 25 | 26 | class Q { 27 | async b() { 28 | return arguments[5] ; 29 | } 30 | } 31 | 32 | async function test1() { 33 | var args = "the quick brown fox jumps over".split(" ") ; 34 | var r = [await a.apply(null,args),await b.apply(null,args), 35 | await c.a.apply(null,args), await c.b.apply(null,args), 36 | await new q().a.apply(null,args), await new Q().b.apply(null,args)] ; 37 | return (r.join(" ")===args.join(" ")) ; 38 | } 39 | 40 | async function test2() { 41 | var foo = async function() { 42 | var bar1 = async function() { return arguments[0] } ; 43 | var bar2 = async () => { return arguments[0] } ; 44 | var bar3 = async () => arguments[0] ; 45 | 46 | return await bar1(arguments[0])===123 && await bar2(arguments[0])===123 && await bar3(arguments[0])===123 ; 47 | } 48 | 49 | return await foo(123) ; 50 | } 51 | 52 | async function test() { 53 | return await test1() && await test2() ; 54 | } 55 | 56 | module.exports = test ; 57 | -------------------------------------------------------------------------------- /tests/compiler/es6-arrow.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | var q = [ 4 | async x => 3, 5 | async () => 3, 6 | async (x) => 3, 7 | async (x,y,z) => 3, 8 | async x => { return 3 }, 9 | async () => { return 3 }, 10 | async (x) => { return 3 }, 11 | async (x,y,z) => { return 3 } 12 | ]; 13 | 14 | var r = { 15 | a:async x => x*10 16 | }; 17 | 18 | module.exports = async () => { 19 | var t = 0 ; 20 | for (var i=0; i[4,3,undefined,2,1]) 52 | && await iterate(myGen) ; 53 | } 54 | -------------------------------------------------------------------------------- /tests/compiler/es6-logical.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | class X { 4 | constructor() { 5 | this.trace = "" ; 6 | } 7 | init(n,m) { 8 | this.n = n ; 9 | this.m = m ; 10 | } 11 | async x() { 12 | this.trace += "x" ; 13 | return this.n ; 14 | } 15 | async y() { 16 | this.trace += "y" ; 17 | return this.m ; 18 | } 19 | async and() { 20 | return await this.x() && await this.y() ; 21 | } 22 | async or() { 23 | return await this.x() || await this.y() ; 24 | } 25 | } 26 | 27 | async function test() { 28 | var x = new X() ; 29 | x.init(0,0) ; 30 | await x.and() ; 31 | await x.or() ; 32 | x.init(0,1) ; 33 | await x.and() ; 34 | await x.or() ; 35 | x.init(1,0) ; 36 | await x.and() ; 37 | await x.or() ; 38 | x.init(1,1) ; 39 | await x.and() ; 40 | await x.or() ; 41 | return x.trace == "xxyxxyxyxxyx" ; 42 | } 43 | 44 | module.exports = test; -------------------------------------------------------------------------------- /tests/compiler/es6-loop-label.js: -------------------------------------------------------------------------------- 1 | async function nop(x) { return x } 2 | 3 | var four = [0,1,2,3] ; 4 | async function w(done) { 5 | var res = [] ; 6 | var i,j ; 7 | outer: for (i of four) { 8 | inner: for (j in four) { 9 | await nop() ; 10 | res.push(i,j); 11 | if (i<=j) 12 | break inner ; 13 | } 14 | } 15 | return res.join("") ; 16 | } 17 | 18 | async function x(done) { 19 | var res = [] ; 20 | var i,j ; 21 | outer: for (i of four) { 22 | inner: for (j in four) { 23 | await nop() ; 24 | res.push(i,j); 25 | if (i<=j) 26 | continue outer ; 27 | } 28 | } 29 | return res.join("") ; 30 | } 31 | 32 | async function y(done) { 33 | var res = [] ; 34 | outer: for (const i of four) { 35 | inner: for (let j in four) { 36 | await nop() ; 37 | res.push(i,j); 38 | if (i<=j) 39 | break inner ; 40 | } 41 | } 42 | return res.join("") ; 43 | } 44 | 45 | async function z(done) { 46 | var res = [] ; 47 | outer: for (let i of four) { 48 | inner: for (const j in four) { 49 | await nop() ; 50 | res.push(i,j); 51 | if (i<=j) 52 | continue outer ; 53 | } 54 | } 55 | return res.join("") ; 56 | } 57 | 58 | module.exports = async function() { 59 | return await z() === "00101120212230313233" 60 | && await y() === "00101120212230313233" 61 | && await x() === "00101120212230313233" 62 | && await w() === "00101120212230313233"; 63 | }; 64 | -------------------------------------------------------------------------------- /tests/compiler/es6-object-arrow.js: -------------------------------------------------------------------------------- 1 | var res ; 2 | 3 | async function y(a) { return res = res+a } 4 | 5 | var obj = { 6 | e: async function(a) { return await y(a) }, 7 | f:async (a)=>await y(a), 8 | async g(a) { return await y(a) }, 9 | h:async (a)=>{return await y(a)} 10 | }; 11 | 12 | var sync = { 13 | e: function(a) { return await y(a) }, 14 | f: (a)=>await y(a), 15 | g(a) { return await y(a) }, 16 | h: (a)=>{return await y(a)} 17 | }; 18 | 19 | async function test(){ 20 | res = "" ; 21 | await obj.e(1) ; 22 | await obj.f(2) ; 23 | await obj.g(3) ; 24 | await obj.h(4) ; 25 | 26 | sync.e(5) ; 27 | sync.f(6) ; 28 | sync.g(7) ; 29 | sync.h(8) ; 30 | setImmediate(function(){ 31 | async return res == "12345678" ; 32 | }) ; 33 | } 34 | 35 | module.exports = test ; 36 | -------------------------------------------------------------------------------- /tests/compiler/for-empty.js: -------------------------------------------------------------------------------- 1 | async function emptyFor(){ 2 | for (;;) { 3 | await g(); 4 | } 5 | } 6 | 7 | module.exports = async function(){ 8 | return true ; 9 | } 10 | -------------------------------------------------------------------------------- /tests/compiler/for-if.js: -------------------------------------------------------------------------------- 1 | var nops = 0 ; 2 | async function nop() { 3 | nops++ ; 4 | return; 5 | } 6 | 7 | async function limit() { 8 | return 10 ; 9 | } 10 | 11 | async function test() { 12 | var s = "" ; 13 | nops = 0 ; 14 | for (var n=0;n5) { 16 | await nop() ; 17 | } 18 | s += "." ; 19 | } 20 | return s.length==10 && nops==4; 21 | } 22 | 23 | module.exports = test ; 24 | -------------------------------------------------------------------------------- /tests/compiler/for-in.js: -------------------------------------------------------------------------------- 1 | Object.defineProperty(Array.prototype,'pushAsync',{ 2 | writable:true, 3 | configurable:true, 4 | value:async function() { 5 | [].push.apply(this,arguments) ; 6 | } 7 | }) ; 8 | 9 | async function log() { 10 | console.log.apply(console,arguments) ; 11 | } 12 | 13 | async function iterate(object) { 14 | var j,b=[],c=[] ; 15 | 16 | for (var i in object) b.push(i); 17 | b.push(i); 18 | for (var i in object) await c.pushAsync(i); 19 | await c.pushAsync(i); 20 | 21 | for (var n=0; n= 30) { 9 | s += "break"+i+" " ; 10 | break ; 11 | } 12 | if (i*i >= 9) { 13 | s += "big"+i+" " ; 14 | continue ; 15 | } 16 | s += await inc(i)+"-"+i*i+" " ; 17 | } 18 | 19 | for (i=0; i<10; i++) { 20 | if (i >= 5) { 21 | return s+"ret" ; 22 | } 23 | s += await inc(i)+"-"+i*i+" " ; 24 | } 25 | s += "ok" ; 26 | return s ; 27 | } 28 | 29 | module.exports = async function() { 30 | return await test()=="1-0 2-1 3-4 big3 big4 big5 break6 1-0 2-1 3-4 4-9 5-16 ret" ; 31 | } 32 | -------------------------------------------------------------------------------- /tests/compiler/if-stmt.js: -------------------------------------------------------------------------------- 1 | async function append(a,b) { 2 | return ""+a+b; 3 | } 4 | 5 | async function finalIf(x) { 6 | if (x) 7 | await append(x,0) ; 8 | return ; 9 | } 10 | 11 | async function test(x) { 12 | await finalIf(x) ; 13 | var r = "" ; 14 | if (!x) { 15 | r = "Zero and " ; 16 | } 17 | 18 | var z ; 19 | if (x&1) { 20 | r = await append(r,"Odd") ; 21 | } else { 22 | r += "Even" ; 23 | } 24 | z = await append(x," is ") ; 25 | z = z+r+"." ; 26 | return z ; 27 | }; 28 | 29 | module.exports = async function() { 30 | var s = await test(1)+await test(0)+await test(10); 31 | return s == "1 is Odd.0 is Zero and Even.10 is Even."; 32 | } 33 | -------------------------------------------------------------------------------- /tests/compiler/if-switch.js: -------------------------------------------------------------------------------- 1 | async function x(y) { return y } ; 2 | 3 | async function run2(f) { 4 | if (f) { 5 | switch (f) { 6 | case 1: 7 | n += await x("c") ; 8 | return ; 9 | case 2: 10 | n += await x("d") ; 11 | return ; 12 | } 13 | } else return ; 14 | } 15 | 16 | async function run1(f) { 17 | if (f) { 18 | switch (f) { 19 | case 1: 20 | n += await x("a") ; 21 | break ; 22 | case 2: 23 | n += await x("b") ; 24 | return ; 25 | } 26 | return ; 27 | } 28 | } 29 | 30 | async function run3(f) { 31 | if (f) 32 | switch (f) { 33 | case 1: 34 | n += await x("e") ; 35 | break ; 36 | case 2: 37 | n += await x("f") ; 38 | return ; 39 | } 40 | return ; 41 | } 42 | 43 | async function run4(f) { 44 | if (f) 45 | switch (f) { 46 | case 1: 47 | n += await x("g") ; 48 | return ; 49 | case 2: 50 | n += await x("h") ; 51 | return ; 52 | } 53 | return ; 54 | } 55 | 56 | var n ; 57 | module.exports = async function(){ 58 | n = "" ; 59 | await run1(1)+await run1(2) ; 60 | await run2(1)+await run2(2) ; 61 | await run3(1)+await run3(2) ; 62 | await run4(1)+await run4(2) ; 63 | 64 | return n == "abcdefgh" ; 65 | } 66 | -------------------------------------------------------------------------------- /tests/compiler/if-try.js: -------------------------------------------------------------------------------- 1 | async function runTests(f) { 2 | try { 3 | if (f) { 4 | n += 1 ; 5 | await breathe(2) ; 6 | n += 3 ; 7 | } else { 8 | n += 2 ; 9 | await breathe(3) ; 10 | n += 4 ; 11 | } 12 | } catch (ex) { 13 | console.log(ex) ; 14 | } 15 | return n ; 16 | } 17 | 18 | var n ; 19 | module.exports = async function(){ 20 | n = "" ; 21 | return await runTests(1)+await runTests(0) == "131324" ; 22 | } 23 | -------------------------------------------------------------------------------- /tests/compiler/inline.js: -------------------------------------------------------------------------------- 1 | var s ; 2 | async function fn(f) { s += "."+f ; return } 3 | 4 | async function test(a,b) { 5 | if (a) { 6 | await fn(a) ; 7 | if (b) { 8 | await fn(b) ; 9 | } else { 10 | await fn(-a) ; 11 | } 12 | } else { 13 | await fn(-b) ; 14 | return ; 15 | } 16 | return ; 17 | } 18 | 19 | module.exports = async function() { 20 | s = "" ; 21 | await test(0,0)+await test(0,1)+await test(1,0)+await test(1,1) ; 22 | return s==".0.-1.1.-1.1.1" ; 23 | } -------------------------------------------------------------------------------- /tests/compiler/logical.js: -------------------------------------------------------------------------------- 1 | async function test() { 2 | var x = { 3 | trace:"", 4 | init:function(n,m) { 5 | this.n = n ; 6 | this.m = m ; 7 | }, 8 | x:async function() { 9 | this.trace += "x" ; 10 | return this.n ; 11 | }, 12 | y:async function() { 13 | this.trace += "y" ; 14 | return this.m ; 15 | }, 16 | and:async function() { 17 | return await this.x() && await this.y() ; 18 | }, 19 | or:async function() { 20 | return await this.x() || await this.y() ; 21 | } 22 | }; 23 | 24 | x.init(0,0) ; 25 | await x.and() ; 26 | await x.or() ; 27 | x.init(0,1) ; 28 | await x.and() ; 29 | await x.or() ; 30 | x.init(1,0) ; 31 | await x.and() ; 32 | await x.or() ; 33 | x.init(1,1) ; 34 | await x.and() ; 35 | await x.or() ; 36 | return x.trace == "xxyxxyxyxxyx" ; 37 | } 38 | 39 | module.exports = test; -------------------------------------------------------------------------------- /tests/compiler/loop-label.js: -------------------------------------------------------------------------------- 1 | var map = nodent.require('map') ; 2 | async function nop(x) { return x } 3 | 4 | var four = [0,1,2,3] ; 5 | async function w(done) { 6 | var res = [] ; 7 | var i,j ; 8 | outer: for (i in four) { 9 | inner: for (j in four) { 10 | await nop() ; 11 | res.push(i,j); 12 | if (i<=j) 13 | break inner ; 14 | } 15 | } 16 | return res.join("") ; 17 | } 18 | 19 | async function x(done) { 20 | var res = [] ; 21 | var i,j ; 22 | outer: for (i in four) { 23 | inner: for (j in four) { 24 | await nop() ; 25 | res.push(i,j); 26 | if (i<=j) 27 | continue outer ; 28 | } 29 | } 30 | return res.join("") ; 31 | } 32 | 33 | async function y(done) { 34 | var res = [] ; 35 | var i,j ; 36 | outer: for (i=0; i<4; i++) { 37 | inner: for (j=0; j<4; j++) { 38 | await nop() ; 39 | res.push(i,j); 40 | if (i<=j) 41 | break inner ; 42 | } 43 | } 44 | return res.join("") ; 45 | } 46 | 47 | async function z(done) { 48 | var res = [] ; 49 | var i,j ; 50 | outer: for (i=0; i<4; i++) { 51 | for (j=0; j<4; j++) { 52 | await nop() ; 53 | res.push(i,j); 54 | if (i<=j) 55 | continue outer ; 56 | } 57 | } 58 | return res.join("") ; 59 | } 60 | 61 | module.exports = async function() { 62 | var a = await map([w(),x(),y(),z()]) ; 63 | return a[0] === "00101120212230313233" 64 | && a[1] === "00101120212230313233" 65 | && a[2] === "00101120212230313233" 66 | && a[3] === "00101120212230313233"; 67 | }; -------------------------------------------------------------------------------- /tests/compiler/loop-this.js: -------------------------------------------------------------------------------- 1 | async function x() { } 2 | 3 | async function z(a) { 4 | for (var i=0; i<3; i++) { 5 | if (this !== a) 6 | return -1 ; 7 | 8 | await x() ; 9 | if (this !== a) 10 | return -1 ; 11 | } 12 | return i ; 13 | } 14 | 15 | module.exports = async function() { 16 | var obj = {} ; 17 | return await z.call(obj,obj) === 3 ; 18 | }; 19 | -------------------------------------------------------------------------------- /tests/compiler/method.js: -------------------------------------------------------------------------------- 1 | function AClass(n){ 2 | this.field = n ; 3 | } 4 | 5 | AClass.prototype.total = async function(arg) { 6 | await breathe() ; 7 | this.field += arg ; 8 | return this.field ; 9 | } 10 | 11 | AClass.prototype.barf = async function() { 12 | await breathe() ; 13 | var ex = new Error("total:"+this.field) ; 14 | ex.source = this ; 15 | throw ex ; 16 | } 17 | 18 | module.exports = async function() { 19 | /* In the ES7 Spec, async functions use Promises, which are called 20 | * in either global or undefined 'this'. 21 | * 22 | * In order to make async methods work, nodent always binds them 23 | * with .bind(this) to ensure 'this' is passed correctly through the 24 | * Promise to the resolver 25 | * 26 | * See https://promisesaplus.com/#point-35 */ 27 | var x = new AClass(100) ; 28 | var y = new AClass(200) ; 29 | var r = await x.total(23) ; 30 | var s = await y.total(34) ; 31 | try { 32 | var q = await x.barf() ; 33 | } catch (ex) { 34 | q = await ex.source.total(1) 35 | } 36 | return q+r+s == 481; 37 | } 38 | -------------------------------------------------------------------------------- /tests/compiler/nested-async.js: -------------------------------------------------------------------------------- 1 | async function add(a,b) { 2 | async function log(x) { 3 | return x ; 4 | } 5 | await log(a+b) ; 6 | return a+b ; 7 | } 8 | 9 | module.exports = async function() { 10 | return await add(123,456)==579 ; 11 | } 12 | -------------------------------------------------------------------------------- /tests/compiler/nested-await.js: -------------------------------------------------------------------------------- 1 | async function add(a,b) { 2 | return a+b 3 | } 4 | 5 | async function test(){ 6 | return await add(await add(6,4),await add(3,7)) ; 7 | } 8 | 9 | module.exports = async function() { 10 | return await test()==20 ; 11 | } 12 | -------------------------------------------------------------------------------- /tests/compiler/nested-switch-stmt.js: -------------------------------------------------------------------------------- 1 | async function inc(y) { return y+1 } 2 | 3 | async function test(x,z) { 4 | var y; 5 | switch (x) { 6 | case 1: 7 | y = await inc(x) ; 8 | break ; 9 | case 10: 10 | y = await inc(-x) ; 11 | switch (z) { 12 | case 1: 13 | y = await inc(1) ; 14 | break ; 15 | case 2: 16 | return y = await inc(100) ; 17 | default: 18 | case 3: 19 | break ; 20 | } 21 | return y*5 ; 22 | default: 23 | y = x ; 24 | break ; 25 | } 26 | y = y*10 ; 27 | return y ; 28 | }; 29 | 30 | module.exports = async function() { 31 | var x = await test(1)+await test(5)+await test(10,1)+await test(10,2)+await test(10,3) ; 32 | return x == 136 ; 33 | } 34 | 35 | -------------------------------------------------------------------------------- /tests/compiler/nested-throw.js: -------------------------------------------------------------------------------- 1 | async function x1(y) { 2 | function done() { 3 | try { 4 | if (!y) 5 | throw "a"; 6 | async return y; 7 | } catch (ex) { 8 | async return ex; 9 | } 10 | } 11 | 12 | setTimeout(done, 1); 13 | } 14 | 15 | async function x2(y) { 16 | function done() { 17 | try { 18 | if (!y) 19 | async throw "b"; 20 | async return y; 21 | } catch (ex) { 22 | async return ex; 23 | } 24 | } 25 | 26 | setTimeout(done, 1); 27 | } 28 | 29 | module.exports = async function(){ 30 | var s ; 31 | try { 32 | s = await x1('c'); 33 | s += await x2('d'); 34 | s += await x1(); 35 | s += await x2(); 36 | } catch (ex) { 37 | s += ex; 38 | } 39 | return s === 'cdab' ; 40 | } 41 | -------------------------------------------------------------------------------- /tests/compiler/optimized.js: -------------------------------------------------------------------------------- 1 | async function test() { 2 | return afterReturn() ; 3 | return 123 ; 4 | function afterReturn() { 5 | { 6 | var s = "k" ; 7 | { 8 | return s ; 9 | } 10 | } 11 | unreachable.code() ; 12 | } 13 | thats.all.folks ; 14 | } 15 | 16 | function aClass() {} 17 | 18 | function top() { 19 | function createA() { 20 | return aClass() ; 21 | } 22 | var x = createA() ; 23 | } 24 | 25 | module.exports = async function() { 26 | top() ; 27 | return await test()=="k" ; 28 | } 29 | -------------------------------------------------------------------------------- /tests/compiler/ret-fn.js: -------------------------------------------------------------------------------- 1 | "use nodent-es7"; 2 | 3 | function test() { 4 | return async function x() { 5 | return "t" ; 6 | } 7 | } 8 | 9 | function test2() { 10 | return async function() { 11 | return "u" ; 12 | } 13 | } 14 | 15 | function test3() { 16 | return function x() { 17 | return "t" ; 18 | } 19 | } 20 | 21 | function test4() { 22 | return function() { 23 | return "u" ; 24 | } 25 | } 26 | 27 | function loop() { 28 | var a = [] ; 29 | for (var x=0; x<3; x++) { 30 | a.push(function named(){ 31 | return x ; 32 | }) ; 33 | } 34 | return a.map(function(f){ return f.call()}).join(".") ; 35 | } 36 | 37 | async function assignment() { 38 | var a = function() { return "a" } ; 39 | var b = function fb() { return "b" } ; 40 | var c = async function() { return "c" } ; 41 | var d = async function fd() { return "d" } ; 42 | function hoistable() {} 43 | function twoOfMe() {} 44 | a = function() { return "za" } ; 45 | b = function fb2() { return "zb" } ; 46 | c = async function() { return "zc" } ; 47 | d = async function fd2() { 48 | return "zd" 49 | function hoistable() {} 50 | } ; 51 | function twoOfMe() {} 52 | return await d()+a()+await c()+b() ; 53 | } 54 | 55 | module.exports = async function() { 56 | var s = (await test()())+(await test2()())+(test3()())+test4()()+loop()+await assignment(); 57 | return s == "tutu3.3.3zdzazczb"; 58 | } ; 59 | -------------------------------------------------------------------------------- /tests/compiler/sleep.js: -------------------------------------------------------------------------------- 1 | async function test(doThrow) { 2 | var s = "" ; 3 | try { 4 | await sleep(1) ; 5 | s = "A" ; 6 | await sleep(2) ; 7 | s = "B" ; 8 | if (doThrow) { 9 | JSON.parse("*"); 10 | } 11 | await sleep(3) ; 12 | s = "C" ; 13 | } catch (ex) { 14 | return "X" ; 15 | } 16 | return s ; 17 | } 18 | 19 | module.exports = async function() { 20 | return await test(true)+await test(false)=="XC" ; 21 | } 22 | -------------------------------------------------------------------------------- /tests/compiler/switch-stmt.js: -------------------------------------------------------------------------------- 1 | async function inc(y) { return y+1 } 2 | 3 | async function test(x) { 4 | var y; 5 | switch (x) { 6 | case 1: 7 | y = await inc(x) ; 8 | break ; 9 | case 10: 10 | y = await inc(-x) ; 11 | return y*5 ; 12 | default: 13 | y = x ; 14 | break ; 15 | } 16 | y = y*10 ; 17 | return y ; 18 | }; 19 | 20 | module.exports = async function() { 21 | var x = await test(1)+await test(5)+await test(10) ; 22 | return x == 25 ; 23 | } 24 | 25 | -------------------------------------------------------------------------------- /tests/compiler/try-catch-finally.js: -------------------------------------------------------------------------------- 1 | function sync(r,a) { 2 | try { 3 | r.push("try") ; 4 | if (a&1) throw ["a"].concat(r) ; 5 | if (a&4) return ["b"].concat(r) ; 6 | if (a&16) JSON.parse('*') ; 7 | } catch (ex) { 8 | r.push("catch("+ex+")") ; 9 | if (a&2) throw ["c"].concat(r) ; 10 | if (a&8) return ["d"].concat(r) ; 11 | if (a&32) JSON.parse('*') ; 12 | } finally { 13 | r.push("finally") ; 14 | if (a&64) throw ["c"].concat(r) ; 15 | if (a&128) return ["d"].concat(r) ; 16 | if (a&256) JSON.parse('*') ; 17 | } 18 | r.push("done") ; 19 | return ["r"].concat(r) ; 20 | } 21 | 22 | async function async(r,a,f) { 23 | try { 24 | await f() ; 25 | r.push("try") ; 26 | if (a&1) throw ["a"].concat(r) ; 27 | if (a&4) return ["b"].concat(r) ; 28 | if (a&16) JSON.parse('*') ; 29 | } catch (ex) { 30 | r.push("catch("+ex+")") ; 31 | if (a&2) throw ["c"].concat(r) ; 32 | if (a&8) return ["d"].concat(r) ; 33 | if (a&32) JSON.parse('*') ; 34 | } finally { 35 | r.push("finally") ; 36 | if (a&64) throw ["c"].concat(r) ; 37 | if (a&128) return ["d"].concat(r) ; 38 | if (a&256) JSON.parse('*') ; 39 | } 40 | r.push("done") ; 41 | return ["r"].concat(r) ; 42 | } 43 | 44 | async function check() { 45 | var f = true,r,a,b,c,i,z = 512; 46 | for (i=0; i2) 13 | throw "inner" ; 14 | } 15 | } 16 | } catch (ex) { 17 | throw ex+"-outer" ; 18 | } 19 | return ; 20 | } 21 | 22 | module.exports = async function() { 23 | try { 24 | await test(); 25 | } catch (ex) { 26 | if (ex==="inner-outer") 27 | return true ; 28 | } 29 | return false ; 30 | } 31 | -------------------------------------------------------------------------------- /tests/compiler/try.js: -------------------------------------------------------------------------------- 1 | async function maybe(x) { 2 | await breathe() ; 3 | if (x>2) { 4 | JSON.parse("*") ; 5 | return -1 ; 6 | } 7 | else 8 | return x ; 9 | } 10 | 11 | async function test(x) { 12 | var s = "" ; 13 | for (var n=0; n ") ; 23 | } 24 | return s ; 25 | } 26 | 27 | module.exports = async function() { 28 | return await test(5) == " "; 29 | } 30 | 31 | -------------------------------------------------------------------------------- /tests/compiler/while.js: -------------------------------------------------------------------------------- 1 | async function inc(x) { 2 | await breathe() ; 3 | return x+1 ; 4 | }; 5 | 6 | async function test() { 7 | var s = "" ; 8 | var i = 0 ; 9 | while (i<5) { 10 | s += "<" ; 11 | i = await inc(i) ; 12 | s += i ; 13 | s += ">" ; 14 | } 15 | s += ("ok") ; 16 | return s ; 17 | } 18 | 19 | module.exports = async function() { 20 | return await test()=="<1><2><3><4><5>ok" ; 21 | } 22 | 23 | -------------------------------------------------------------------------------- /tests/compiler/wrap-method.js: -------------------------------------------------------------------------------- 1 | function AClass(name) { 2 | this.name = ":) "+name ; 3 | this.fail = ":( "+name ; 4 | } 5 | 6 | AClass.prototype.abc = async function(x) { 7 | if (x) { 8 | throw this.fail ; 9 | } 10 | return this.name ; 11 | }; 12 | 13 | AClass.prototype.test1 = async function(x) { 14 | return this.abc(x) ; 15 | } ; 16 | AClass.prototype.test2 = async function(x) { 17 | return await this.abc(x) ; 18 | }; 19 | AClass.prototype.test3 = async function(x) { 20 | return this.test1(x) ; 21 | }; 22 | AClass.prototype.test4 = function(x) { 23 | return this.abc(x) ; 24 | }; 25 | AClass.prototype.test5 = function(x) { 26 | return this.test1(x) ; 27 | }; 28 | 29 | async function go() { 30 | var a = new AClass("mat") ; 31 | 32 | var passes = 0 ; 33 | for (var i=1; i<6; i++) { 34 | var fn = "test"+i ; 35 | 36 | if (await a[fn]()===a.name) 37 | passes += 1 ; 38 | } 39 | 40 | for (var i=1; i<6; i++) { 41 | fn = "test"+i ; 42 | try { 43 | await a[fn](1) ; 44 | } catch(ex) { 45 | if (ex===a.fail) 46 | passes += 1 ; 47 | } 48 | } 49 | return passes==10 ; 50 | } 51 | 52 | module.exports = go ; 53 | -------------------------------------------------------------------------------- /tests/compiler/wrap.js: -------------------------------------------------------------------------------- 1 | async function abc(x) { 2 | if (x) { 3 | throw "def" ; 4 | } 5 | return "abc" ; 6 | }; 7 | 8 | async function test1(x) { 9 | return abc(x) ; 10 | } 11 | 12 | var tests = [ 13 | test1, 14 | async function(x) { 15 | return await abc(x) ; 16 | }, 17 | async function(x) { 18 | return test1(x) ; 19 | }, 20 | function(x) { 21 | return abc(x) ; 22 | }, 23 | function(x) { 24 | return test1(x) ; 25 | } 26 | ]; 27 | 28 | async function go() { 29 | var passes = 0 ; 30 | for (var i=0; i0") ; 158 | } catch (ex) { 159 | console.log(("V8 "+process.versions.v8+" does not arrow functions. Skipping es6target tests. ").yellow) ; 160 | useES6 = false ; 161 | } 162 | 163 | function pad(s, n) { 164 | return (" " + s).substr(-(n || 32)); 165 | } 166 | 167 | if (syntaxTest) { 168 | require('./test-syntax').testFiles(process.argv.length > idx ? process.argv.slice(idx) : [__dirname + "/.."], true); 169 | if (syntaxTest == 1) 170 | return; 171 | } 172 | var files = (process.argv.length > idx ? process.argv.slice(idx) : fs.readdirSync('./tests/semantics').map(function (fn) { 173 | return './tests/semantics/' + fn; 174 | })).filter(function (n) { 175 | return n.match(/.*\.js$/); 176 | }); 177 | 178 | var tTotalCompilerTime = 0; 179 | var test = []; 180 | var i = 0; 181 | function time(hr) { 182 | var t = process.hrtime(hr); 183 | return t[0] * 1000 + t[1] / 1e6; 184 | } 185 | 186 | function DoNotTest() { 187 | throw DoNotTest; 188 | } 189 | 190 | var types = []; 191 | files.forEach(function (n) { 192 | test[i] = { 193 | name: n.split("/").pop().replace(/\.js$/, ""), 194 | fn: [] 195 | }; 196 | process.stdout.write('\r- Compiling ' + test[i].name + ' \r'); 197 | var code = fs.readFileSync(n).toString(); 198 | var dualMode = n.match(/\/dual-/) ; 199 | if (dualMode) { 200 | code = "module.exports = async function() { "+ 201 | "var s = _s(), a = await _a() ;"+ 202 | "if (s !== a) {console.log(s,a)} "+ 203 | "return s === a }\n"+ 204 | "function _s() { "+forceStrict + code.replace(/async|await/g,"")+" }\n"+ 205 | "async function _a() { "+forceStrict + code+" }" ; 206 | } 207 | var compileException = false; 208 | for (var mode = 0; mode < 5; mode++) { 209 | for (var flags=0; flags<8; flags++) { 210 | var opts = {} ; 211 | if (noNodentExtensions) 212 | opts.parser = { noNodentExtensions: true } ; 213 | 214 | switch (mode) { 215 | case 0: // es7 (lazy) 216 | opts.es7 = true ; 217 | opts.lazyThenables = true ; 218 | break; 219 | case 1: // es7 (eager) 220 | opts.es7 = true ; 221 | break; 222 | case 2: // Promises 223 | opts.promises = true ; 224 | break; 225 | case 3: // Generators 226 | if (!useGenerators) 227 | continue ; 228 | opts.generators = true ; 229 | break; 230 | case 4: // Engine 231 | if (!useEngine) 232 | continue ; 233 | opts.engine = true ; 234 | break; 235 | } 236 | if (flags & 1) { 237 | if (!useES6) 238 | continue ; 239 | opts.es6target = true ; 240 | } 241 | if (flags & 2) { 242 | if (!(opts.promises || opts.engine)) 243 | continue ; 244 | opts.noRuntime = true ; 245 | } 246 | if (flags & 4) 247 | opts.wrapAwait = true ; 248 | 249 | var type = mode*8+flags ; 250 | types[type] = Object.keys(opts).toString() ; 251 | 252 | try { 253 | var pr, tCompiler = process.hrtime(); 254 | pr = nodent.compile(forceStrict + code, n, opts).code; 255 | tTotalCompilerTime += time(tCompiler); 256 | try { 257 | test[i].fn[type] = new Function("module", "require", "Promise", "__unused", "nodent", "DoNotTest", pr); 258 | test[i].fn[type].opts = opts ; 259 | } catch (ex) { 260 | if (!compileException) 261 | console.warn(test[i].name+(" not supported by V8 "+process.versions.v8+" (try a later version of nodejs): ").yellow+ex.message.red) ; 262 | compileException = true ; 263 | test[i].fn[type] = function(m) { 264 | m.exports = DoNotTest ; 265 | } 266 | } 267 | } catch (ex) { 268 | if (!compileException) 269 | console.warn(test[i].name+(" nodent failed to compile ").yellow+" ("+types[type]+") "+ex.message.red) ; 270 | compileException = true ; 271 | test[i].fn[type] = function(m) { 272 | m.exports = DoNotTest ; 273 | } 274 | } 275 | } 276 | } 277 | i += 1; 278 | }); 279 | console.log("Total compile time:", ((tTotalCompilerTime | 0) + "ms").yellow); 280 | if (useQuick) 281 | console.log('Note:'.cyan,'Timings with '+'--quick'.underline+' are subject to significant GC jitter. Remove '+'--quick'.underline+' for accurate timing comparison'); 282 | if (promiseImpls == providers.length) 283 | console.log('To test against some popular Promise implementations,', 'cd tests && npm i && cd ..'.yellow); 284 | 285 | var testCache = {} ; 286 | async function runTest(test, provider, type) { 287 | if (!test.fn[type].opts || (provider.p && !(test.fn[type].opts.promises || test.fn[type].opts.generators || test.fn[type].opts.engine))) { 288 | return { 289 | result: DoNotTest 290 | }; 291 | } 292 | 293 | if (!provider.p && test.fn[type].opts.engine) { 294 | return { 295 | result: DoNotTest 296 | }; 297 | } 298 | 299 | 300 | await sleep(1); 301 | var key = [test.name,provider.name,type].join(); 302 | var m = {}; 303 | if (!testCache[key]) { 304 | test.fn[type](m, require, provider.p || DoNotTest, undefined, nodent, DoNotTest); 305 | testCache[key] = m ; 306 | } else { 307 | m = testCache[key] ; 308 | } 309 | var returned = false ; 310 | function onResult(r) { 311 | if (tID) { 312 | clearTimeout(tID) ; 313 | tID = null ; 314 | } 315 | if (returned) 316 | return ; 317 | returned = true ; 318 | async return { 319 | alwaysQuick: m.exports.alwaysQuick, 320 | t: time(t), 321 | result: r 322 | } 323 | } 324 | try { 325 | var thenable = m.exports(); 326 | var tID = setTimeout(function(){ 327 | tID = null ; 328 | if (returned) 329 | return ; 330 | console.log("Timeout".red,test.name,provider.name.yellow); 331 | onResult(new Error("Timed out")) ; 332 | },10000) ; 333 | var t = process.hrtime(); 334 | thenable.then(onResult,onResult) ; 335 | } catch (ex) { 336 | return { 337 | alwaysQuick: m.exports.alwaysQuick, 338 | t: t?time(t):10000, 339 | result: ex 340 | } 341 | } 342 | } 343 | 344 | try { 345 | var result, byType = {}, byProvider = {}, byTest = {}, table = [], fails = [], tMedian = 0, nMedian = 0 ; 346 | var maxLines = 0 ; 347 | nextTest: for (i = 0;i < test.length; i++) { 348 | var benchmark = null; 349 | nextProvider: for (var j = 0;j < providers.length; j++) { 350 | try { 351 | process.stdout.write('\r- Test: ' + test[i].name + ' using ' + providers[j].name.yellow + spaces + '\n'); 352 | gc() ; 353 | 354 | for (var type in types) if (Object.getOwnPropertyDescriptor(types,type)) { 355 | table[type] = table[type] || []; 356 | table[type][j] = table[type][j] || []; 357 | // Warm up V8 358 | result = await runTest(test[i], providers[j], type); 359 | if (result.result !== true) { 360 | if (result.result !== DoNotTest) { 361 | console.log(test[i].name, '\u2717'.red, types[type].red, providers[j].name.red, result.result.toString().red, spaces); 362 | continue nextProvider ; 363 | } 364 | continue; 365 | } 366 | var t = 0; 367 | var ticks = []; 368 | var cond = result.alwaysQuick?function(){ return ticks.length < result.alwaysQuick } : ( useQuick ? function () { 369 | return ticks.length < 2; 370 | } : function () { 371 | return (t < 100 || ticks.length < 20) && ticks.length < 200; 372 | }); 373 | while (cond()) { 374 | result = await runTest(test[i], providers[j], type); 375 | ticks.push(result.t); 376 | t += result.t; 377 | } 378 | ticks = ticks.sort(); 379 | var median = ticks[ticks.length / 2 | 0]; 380 | var metric = median; 381 | if (!benchmark) { 382 | benchmark = metric; 383 | tMedian = tMedian+benchmark ; 384 | nMedian += 1 ; 385 | } 386 | metric = metric / benchmark * 100; 387 | result = { 388 | value: result.result, 389 | metric: metric, 390 | provider: providers[j].name, 391 | type: types[type], 392 | test: test[i].name 393 | }; 394 | table[type][j].push(metric); 395 | byType[types[type]] = byType[types[type]] || []; 396 | byType[types[type]].push(result); 397 | byProvider[providers[j].name] = byProvider[providers[j].name] || []; 398 | byProvider[providers[j].name].push(result); 399 | } 400 | console.log(spaces+'\n') ; 401 | var lines = 2+showPerformanceTable() ; 402 | if (maxLines < lines+1) 403 | maxLines = lines+1 ; 404 | while (lines--) { 405 | process.stdout.write('\u001B[1A') ; 406 | } 407 | } catch(ex) { 408 | fails.push(test[i].name.yellow + ' using ' + providers[j].name.yellow + ': ',ex.toString().red); 409 | } finally { 410 | process.stdout.write('\u001B[1A') ; 411 | } 412 | } 413 | } 414 | 415 | while (maxLines--) console.log("") ; 416 | console.log('Benchmark execution time: '+((tMedian/nMedian)+' ms').cyan) ; 417 | console.log(fails.join("\n")) ; 418 | 419 | function showPerformanceTable() { 420 | var i,j,lines = 0 ; 421 | function log() { 422 | console.log.apply(console,arguments) ; 423 | lines++ ; 424 | } 425 | function extract(a, field) { 426 | if (!Array.isArray(a)) { 427 | return NaN; 428 | } 429 | return a.map(function (n) { 430 | return n[field]; 431 | }); 432 | } 433 | 434 | function avg(by) { 435 | if (!Array.isArray(by)) 436 | return NaN; 437 | return by.filter(function (n) { 438 | return typeof n === 'number'; 439 | }).reduce(function (a, b) { 440 | return a + b; 441 | }, 0) / by.length; 442 | } 443 | 444 | function traffic(n) { 445 | if (isNaN(n)) 446 | return pad('-', 16).blue; 447 | if (n < 120) 448 | return pad('' + (n | 0), 16).green; 449 | if (n < 200) 450 | return pad('' + (n | 0), 16).white; 451 | if (n < 300) 452 | return pad('' + (n | 0), 16).yellow; 453 | return pad('' + (n | 0), 16).red; 454 | } 455 | 456 | var n; 457 | var fidx = Object.keys(table)[0] ; 458 | n = pad('') + pad('', 16); 459 | for (i = 0; i < table[fidx].length; i++) { 460 | n += pad(providers[i].name, 16); 461 | } 462 | log(n); 463 | n = pad('Compiler flags') + pad('Mean', 16); 464 | for (i = 0; i < table[fidx].length; i++) { 465 | n += traffic(avg(extract(byProvider[providers[i].name], 'metric'))); 466 | } 467 | log(n.underline); 468 | for (i = 0; i < table.length; i++) { 469 | var typed = table[i]; 470 | if (typed) { 471 | n = pad(types[i]) + traffic(avg(extract(byType[types[i]], 'metric'))); 472 | for (j = 0; j < typed.length; j++) { 473 | n += traffic(avg(typed[j])); 474 | } 475 | log(n); 476 | } 477 | } 478 | log(''); 479 | return lines ; 480 | } 481 | } catch (ex) { 482 | console.error(ex.stack || ex); 483 | } 484 | -------------------------------------------------------------------------------- /tests/loader/app/.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules/ 2 | -------------------------------------------------------------------------------- /tests/loader/app/index.js: -------------------------------------------------------------------------------- 1 | var nodent = require('../../../../nodent')() ; 2 | console.log("App nodent version",nodent.version) ; 3 | require('./main')(nodent) ; 4 | -------------------------------------------------------------------------------- /tests/loader/app/main.js: -------------------------------------------------------------------------------- 1 | 'use nodent-promises'; 2 | 3 | module.exports = function(nodent) { 4 | var loaded = await require('../loader-module')() ; 5 | console.log("loader-module nodent version",loaded.version) ; 6 | var self = {version: nodent.version, options:__nodent} ; 7 | if (self.version > loaded.version 8 | && loaded.version === "2.3.0" 9 | && loaded.options.generatedSymbolPrefix === "_early_nodent_") { 10 | console.log('versionAwareLoader test PASSED') ; 11 | return true ; 12 | } else { 13 | console.log(loaded) ; 14 | console.log(self) ; 15 | var ex = new Error('versionAwareLoader test FAILED') ; 16 | ex.stack = "" ; 17 | throw ex ; 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /tests/loader/app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "app", 3 | "version": "1.0.0", 4 | "description": "Test app using current Nodent version but depending on an ealier version", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo '### This test requires npm >2.x ###' && cd ../loader-module && npm i && cd ../app && npm i && node ." 8 | }, 9 | "author": "", 10 | "license": "ISC" 11 | } 12 | -------------------------------------------------------------------------------- /tests/loader/loader-module/.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules/ 2 | -------------------------------------------------------------------------------- /tests/loader/loader-module/index.js: -------------------------------------------------------------------------------- 1 | require('nodent')() ; 2 | module.exports = require('./version') ; 3 | -------------------------------------------------------------------------------- /tests/loader/loader-module/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "loader-module", 3 | "version": "1.0.0", 4 | "description": "Test module using an early version of Nodent", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "nodent": "2.3.0" 13 | }, 14 | "nodent": { 15 | "directive": { 16 | "es7": { 17 | "generatedSymbolPrefix": "_early_nodent_", 18 | "sourcemap": "false" 19 | } 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tests/loader/loader-module/version.js: -------------------------------------------------------------------------------- 1 | 'use nodent-es7'; 2 | 3 | module.exports = async function getVersion() { 4 | return {version:require('nodent')().version, options:__nodent} ; 5 | } 6 | -------------------------------------------------------------------------------- /tests/onp/COPYING: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 Tatsuhiko Kubo 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. -------------------------------------------------------------------------------- /tests/onp/diff.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This program is checked with node.js 3 | */ 4 | 5 | var color, onp = require('./onp.js'); 6 | try { 7 | color = require('colors') ; 8 | } catch (ex) { 9 | function nop() { return this } ; 10 | String.prototype.red = nop ; 11 | String.prototype.green = nop ; 12 | String.prototype.dim = nop ; 13 | } 14 | 15 | module.exports = function(a,b) { 16 | var diff = new onp.Diff(a,b); 17 | diff.compose(); 18 | // console.log("editdistance:" + diff.editdistance()); 19 | // console.log("lcs:" + diff.getlcs()); 20 | // console.log("ses"); 21 | 22 | var line = "" ; 23 | var doc = [] ; 24 | var diffs = [] ; 25 | var i = 0; 26 | var ld = -1 ; 27 | var ses = diff.getses(); 28 | for (i=0;i=0, 54 | toString:function(){ return doc.join('\n') }, 55 | summary:function() { 56 | return diffs.map(function(n){ 57 | return ""+n+": "+doc[n] 58 | }).join('\n'); 59 | } 60 | } ; 61 | } 62 | -------------------------------------------------------------------------------- /tests/onp/onp.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This program is checked with node.js 3 | */ 4 | 5 | /** 6 | * The algorithm implemented here is based on "An O(NP) Sequence Comparison Algorithm" 7 | * by described by Sun Wu, Udi Manber and Gene Myers 8 | */ 9 | 10 | exports.Diff = function (a_, b_) { 11 | var a = a_, 12 | b = b_, 13 | m = a.length, 14 | n = b.length, 15 | reverse = false, 16 | ed = null, 17 | offset = m + 1, 18 | path = [], 19 | pathposi = [], 20 | ses = [], 21 | lcs = "", 22 | SES_DELETE = -1, 23 | SES_COMMON = 0, 24 | SES_ADD = 1; 25 | 26 | var tmp1, 27 | tmp2; 28 | 29 | var init = function () { 30 | if (m >= n) { 31 | tmp1 = a; 32 | tmp2 = m; 33 | a = b; 34 | b = tmp1; 35 | m = n; 36 | n = tmp2; 37 | reverse = true; 38 | } 39 | }; 40 | 41 | var P = function (x, y, k) { 42 | return { 43 | 'x' : x, 44 | 'y' : y, 45 | 'k' : k, 46 | }; 47 | }; 48 | 49 | var seselem = function (elem, t) { 50 | return { 51 | 'elem' : elem, 52 | 't' : t, 53 | }; 54 | }; 55 | 56 | var snake = function (k, p, pp) { 57 | var r, x, y; 58 | if (p > pp) { 59 | r = path[k-1+offset]; 60 | } else { 61 | r = path[k+1+offset]; 62 | } 63 | 64 | y = Math.max(p, pp); 65 | x = y - k; 66 | while (x < m && y < n && a[x] === b[y]) { 67 | ++x; 68 | ++y; 69 | } 70 | 71 | path[k+offset] = pathposi.length; 72 | pathposi[pathposi.length] = new P(x, y, r); 73 | return y; 74 | }; 75 | 76 | var recordseq = function (epc) { 77 | var x_idx, y_idx, px_idx, py_idx, i; 78 | x_idx = y_idx = 1; 79 | px_idx = py_idx = 0; 80 | for (i=epc.length-1;i>=0;--i) { 81 | while(px_idx < epc[i].x || py_idx < epc[i].y) { 82 | if (epc[i].y - epc[i].x > py_idx - px_idx) { 83 | if (reverse) { 84 | ses[ses.length] = new seselem(b[py_idx], SES_DELETE); 85 | } else { 86 | ses[ses.length] = new seselem(b[py_idx], SES_ADD); 87 | } 88 | ++y_idx; 89 | ++py_idx; 90 | } else if (epc[i].y - epc[i].x < py_idx - px_idx) { 91 | if (reverse) { 92 | ses[ses.length] = new seselem(a[px_idx], SES_ADD); 93 | } else { 94 | ses[ses.length] = new seselem(a[px_idx], SES_DELETE); 95 | } 96 | ++x_idx; 97 | ++px_idx; 98 | } else { 99 | ses[ses.length] = new seselem(a[px_idx], SES_COMMON); 100 | lcs += a[px_idx]; 101 | ++x_idx; 102 | ++y_idx; 103 | ++px_idx; 104 | ++py_idx; 105 | } 106 | } 107 | } 108 | }; 109 | 110 | init(); 111 | 112 | return { 113 | SES_DELETE : -1, 114 | SES_COMMON : 0, 115 | SES_ADD : 1, 116 | editdistance : function () { 117 | return ed; 118 | }, 119 | getlcs : function () { 120 | return lcs; 121 | }, 122 | getses : function () { 123 | return ses; 124 | }, 125 | compose : function () { 126 | var delta, size, fp, p, r, epc, i, k; 127 | delta = n - m; 128 | size = m + n + 3; 129 | fp = {}; 130 | for (i=0;i=delta+1;--k) { 141 | fp[k+offset] = snake(k, fp[k-1+offset]+1, fp[k+1+offset]); 142 | } 143 | fp[delta+offset] = snake(delta, fp[delta-1+offset]+1, fp[delta+1+offset]); 144 | } while (fp[delta+offset] !== n); 145 | 146 | ed = delta + 2 * p; 147 | 148 | r = path[delta+offset]; 149 | 150 | epc = []; 151 | while (r !== -1) { 152 | epc[epc.length] = new P(pathposi[r].x, pathposi[r].y, null); 153 | r = pathposi[r].k; 154 | } 155 | recordseq(epc); 156 | } 157 | }; 158 | }; -------------------------------------------------------------------------------- /tests/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nodent-tests", 3 | "requires": true, 4 | "lockfileVersion": 1, 5 | "dependencies": { 6 | "asap": { 7 | "version": "2.0.6", 8 | "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", 9 | "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=", 10 | "dev": true 11 | }, 12 | "bluebird": { 13 | "version": "3.5.1", 14 | "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", 15 | "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==", 16 | "dev": true 17 | }, 18 | "colors": { 19 | "version": "1.1.2", 20 | "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", 21 | "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=" 22 | }, 23 | "promiscuous": { 24 | "version": "0.7.1", 25 | "resolved": "https://registry.npmjs.org/promiscuous/-/promiscuous-0.7.1.tgz", 26 | "integrity": "sha512-ajyB0hUWLYJu4nM7EinpY+5vhNAb+FB5tM/vUKp6Zr48db3TvKa/+fhFcgocs0w1dPIoQkQHUvqL+UzfqFvIUw==", 27 | "dev": true 28 | }, 29 | "promise": { 30 | "version": "8.0.1", 31 | "resolved": "https://registry.npmjs.org/promise/-/promise-8.0.1.tgz", 32 | "integrity": "sha1-5F1osAoXZHttpxG/he1u1HII9FA=", 33 | "dev": true, 34 | "requires": { 35 | "asap": "~2.0.3" 36 | } 37 | }, 38 | "rsvp": { 39 | "version": "4.8.3", 40 | "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.3.tgz", 41 | "integrity": "sha512-/OlbK31XtkPnLD2ktmZXj4g/v6q1boTDr6/3lFuDTgxVsrA3h7PH5eYyAxIvDMjRHr/DoOlzNicqDwBEo9xU7g==", 42 | "dev": true 43 | }, 44 | "when": { 45 | "version": "3.7.8", 46 | "resolved": "https://registry.npmjs.org/when/-/when-3.7.8.tgz", 47 | "integrity": "sha1-xxMLan6gRpPoQs3J56Hyqjmjn4I=", 48 | "dev": true 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /tests/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nodent-tests", 3 | "description": "A suite of tests to check the syntax (parser & out), semantics (operation & execution) and performance of nodent", 4 | "main": "index.js", 5 | "scripts": { 6 | "test": "cd .. && npm test" 7 | }, 8 | "repository": { 9 | "type": "git", 10 | "url": "https://github.com/MatAtBread/nodent.git" 11 | }, 12 | "author": "", 13 | "license": "ISC", 14 | "dependencies": { 15 | "colors": "^1.1.2" 16 | }, 17 | "devDependencies": { 18 | "promise": ">=7.1.1", 19 | "bluebird": ">=3.4.6", 20 | "promiscuous": ">=0.6.0", 21 | "rsvp": ">=3.3.1", 22 | "when": ">=3.7.7" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tests/semantics/asyncfunction-type.js: -------------------------------------------------------------------------------- 1 | var AsyncFunction = require('../../nodent')().require('asyncfunction') ; 2 | 3 | var add = new AsyncFunction("i","j","return i+j") ; 4 | 5 | module.exports = async function() { 6 | return (add instanceof Function)===true 7 | && (add instanceof AsyncFunction)===true 8 | && (add.toString()) 9 | && (add.toES5String()) 10 | && await add(10,11)===21 ; 11 | }; 12 | -------------------------------------------------------------------------------- /tests/semantics/asyncify.js: -------------------------------------------------------------------------------- 1 | var map = nodent.require('map',{throwOnError:true}) ; 2 | Function.prototype.noDentify = nodent.require('nodentify') ; 3 | 4 | Function.prototype.asAsync = function(){ 5 | var fn = this ; 6 | var args = Array.prototype.slice.call(arguments) ; 7 | return new nodent.Thenable(function(ok,err){ 8 | ok(fn.apply(this,await map(args))) ; 9 | }) ; 10 | } 11 | 12 | var fs = require('fs') ; 13 | var afs = fs.asyncify() ; 14 | var readFile = fs.readFile.bind(fs).noDentify(1,0) ; 15 | 16 | async function test() { 17 | return ((await map([ 18 | JSON.parse(fs.readFileSync('package.json')), 19 | JSON.parse.asAsync(fs.readFileSync.asAsync('package.json')), 20 | JSON.parse.asAsync(readFile('package.json')), 21 | JSON.parse.asAsync(afs.readFile('package.json')), 22 | JSON.parse.asAsync(await readFile('package.json')), 23 | JSON.parse.asAsync(await afs.readFile('package.json')), 24 | JSON.parse.asAsync(await fs.readFileSync.asAsync('package.json')), 25 | JSON.parse(await readFile('package.json')), 26 | JSON.parse(await afs.readFile('package.json')), 27 | JSON.parse(await fs.readFileSync.asAsync('package.json')) 28 | ])).map(function(p){ return p.version }).every(function(v,_,a){ return v===a[0] })) ; 29 | } 30 | 31 | module.exports = test ; 32 | //test().then(console.log.bind(console),function(ex){ console.log(ex.stack) }); 33 | -------------------------------------------------------------------------------- /tests/semantics/await-multi.js: -------------------------------------------------------------------------------- 1 | async function pause() { 2 | setImmediate(function(){ async return }) ; 3 | } 4 | 5 | async function half(x) { 6 | return x/2 ; 7 | } 8 | 9 | async function otherHalf(x) { 10 | await pause() ; 11 | return x/2 ; 12 | } 13 | 14 | async function test() { 15 | var a = half(10) ; 16 | var b = otherHalf(10) ; 17 | var f = (await a + await a)===10 && (await b + await b)===10 ; 18 | return f ; 19 | } 20 | 21 | module.exports = test ; 22 | -------------------------------------------------------------------------------- /tests/semantics/await-not-then.js: -------------------------------------------------------------------------------- 1 | // Only run this test if await-wrapping is enabled 2 | if (__nodent.wrapAwait) { 3 | module.exports = async function() { 4 | return 'abc' === await 'abc' ; 5 | } ; 6 | } else { 7 | module.exports = async function() { DoNotTest() } ; 8 | } 9 | -------------------------------------------------------------------------------- /tests/semantics/await.wrap.js: -------------------------------------------------------------------------------- 1 | if (!__nodent.wrapAwait) 2 | module.exports = async function() { DoNotTest() } 3 | else { 4 | async function inc(x) { return x+1 ; } 5 | 6 | async function test() { 7 | var a = await inc(999) ; 8 | var b = await 1000 ; 9 | var c = await 999+1 ; 10 | return a==b && b==c; 11 | } 12 | module.exports = test ; 13 | } 14 | -------------------------------------------------------------------------------- /tests/semantics/callback-fn-ret.js: -------------------------------------------------------------------------------- 1 | // Return an async function asynchronously 2 | async function x() { 3 | setImmediate(function(){ 4 | async return async function xy() { return 2 } 5 | }) ; 6 | } 7 | 8 | //Return a sync function asynchronously 9 | async function z() { 10 | setImmediate(function(){ 11 | async return function ab() { return 3 } ; 12 | }) ; 13 | } 14 | 15 | //Return an async function synchronously 16 | function w() { 17 | return async function() { return 5 } 18 | } 19 | 20 | //Return an sync function asynchronously 21 | async function y() { 22 | return function() { return 7 } 23 | } 24 | 25 | //Return an async function asynchronously 26 | async function v() { 27 | return async function() { return 11 } 28 | } 29 | 30 | module.exports = async function() { 31 | var r = await w()() ; 32 | r *= await (await x())() ; 33 | r *= (await z())() ; 34 | r *= (await y())() ; 35 | r *= await (await v())() ; 36 | return r==210*11 ; 37 | } 38 | 39 | -------------------------------------------------------------------------------- /tests/semantics/es6-interop.js: -------------------------------------------------------------------------------- 1 | var gen = [ 2 | require('./codegen/cg-es7.js'), 3 | require('./codegen/cg-promises.js'), 4 | require('./codegen/cg-generators.js') 5 | ]; 6 | 7 | function* doWeKnowGenerators(){} 8 | 9 | async function inter(i,j) { 10 | return (gen[j].name == await gen[j].call() && await gen[j].call() == await gen[i].consume(gen[j].call))?1:100 ; 11 | } 12 | 13 | async function test() { 14 | for (var q=0; q w+1 ; 10 | r = async(w) => { return async function(async) { return (async(async)=>async+1)(async-1) }} ; 11 | 12 | 13 | // An async arrow 14 | async(b)=>0 ; 15 | 16 | // A call to 'async' 17 | async((b)=>0) ; 18 | } 19 | 20 | function nothing(){} 21 | 22 | // Template strings 23 | nothing(`${(123).toString()}`.toString()) ; -------------------------------------------------------------------------------- /tests/semantics/fs-sync.js: -------------------------------------------------------------------------------- 1 | var fs = require('../../nodent').asyncify(Promise)(require('fs')) ; 2 | 3 | var n = fs.readdirSync('.').length ; 4 | 5 | function test(dir) { 6 | var files ; 7 | for (var i=0; i<10; i++) { 8 | files = fs.readdirSync(dir) ; 9 | for (var j=0; j1) ; 2 | var b = ()=>2 + 3 ; 3 | var c = ()=>4 + (()=>5) ; 4 | -------------------------------------------------------------------------------- /tests/syntax/call.js: -------------------------------------------------------------------------------- 1 | f(); 2 | g(a); 3 | h(a, b); 4 | i(a, b, ...c); 5 | j(...a); 6 | a.k(); 7 | (a + b).l(); 8 | a.m().n(); 9 | new A(); 10 | new A(a); 11 | -------------------------------------------------------------------------------- /tests/syntax/class.js: -------------------------------------------------------------------------------- 1 | class A { 2 | constructor() {} 3 | } 4 | class B extends A {} 5 | class C extends A { 6 | method() {} 7 | get property() { 8 | return this._property; 9 | } 10 | set property(value) { 11 | this._property = value; 12 | } 13 | } 14 | class D extends class A {} {} 15 | class E extends class { 16 | constructor() {} 17 | } {} 18 | class F extends class { 19 | constructor() {} 20 | } { 21 | constructor() {} 22 | } 23 | class G { 24 | [Symbol.iterator]() {} 25 | ["method"]() {} 26 | } 27 | class H { 28 | static classMethod() {} 29 | method() {} 30 | } 31 | class I { 32 | static get property() {} 33 | static set property(value) {} 34 | } 35 | class J extends A { 36 | constructor() { 37 | super(); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /tests/syntax/control.js: -------------------------------------------------------------------------------- 1 | if (a > b) {} else {} 2 | if (c != d) {} 3 | var a = b > c ? d : e; 4 | switch (a) { 5 | case b: 6 | break; 7 | case "c": 8 | break; 9 | case 42: 10 | break; 11 | case d: 12 | if (a < b) {} 13 | break; 14 | default: 15 | break; 16 | } 17 | while (a > b) { 18 | if (c == d) { 19 | break; 20 | } 21 | } 22 | do { 23 | if (e === f) { 24 | continue; 25 | } 26 | } while (g < h); 27 | label: if (a === b) { 28 | if (b = c) { 29 | break label; 30 | } 31 | } 32 | if (a != b) {} 33 | endingLabel: {} 34 | -------------------------------------------------------------------------------- /tests/syntax/error.js: -------------------------------------------------------------------------------- 1 | try { 2 | let a = 42; 3 | } catch (error) { 4 | let b = error; 5 | } 6 | try { 7 | let a = 42; 8 | } catch (error) { 9 | let b = error; 10 | } finally { 11 | let c = "done"; 12 | } 13 | throw new Error("this is an error"); 14 | -------------------------------------------------------------------------------- /tests/syntax/everything/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014, Michael Ficarra. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are met: 5 | 6 | * Redistributions of source code must retain the above copyright notice, this 7 | list of conditions and the following disclaimer. 8 | 9 | * Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | 13 | * Neither the name of the project nor the names of its contributors may be 14 | used to endorse or promote products derived from this software without 15 | specific prior written permission. 16 | 17 | This software is provided by the copyright holders and contributors "as is" and 18 | any express or implied warranties, including, but not limited to, the implied 19 | warranties of merchantability and fitness for a particular purpose are 20 | disclaimed. In no event shall the copyright holder be liable for any direct, 21 | indirect, incidental, special, exemplary, or consequential damages (including, 22 | but not limited to, procurement of substitute goods or services; loss of use, 23 | data, or profits; or business interruption) however caused and on any theory of 24 | liability, whether in contract, strict liability, or tort (including negligence 25 | or otherwise) arising in any way out of the use of this software, even if 26 | advised of the possibility of such damage. 27 | -------------------------------------------------------------------------------- /tests/syntax/everything/README.md: -------------------------------------------------------------------------------- 1 | everything.js 2 | ============= 3 | 4 | A single javascript file that contains every ECMA-262 grammatical production. 5 | 6 | ### Usage Example 7 | 8 | Mocha: 9 | 10 | ```js 11 | test("exercise my program", function(done) { 12 | fs.readFile(require.resolve("everything.js"), function(err, programText) { 13 | var program = esprima.parse("" + programText); 14 | assert.equal(runMyProgramOn(program), /* expected value */, "message"); 15 | done(); 16 | }); 17 | }); 18 | ``` 19 | 20 | ### Further ECMAScript Version Support 21 | 22 | Support has been added for ECMAScript 2015. Version can be specified through 23 | `require.resolve("everything.js/")`, where `` is one of: 24 | 25 | * `es5`: ECMASCript 5.1 26 | * `es2015-module`: ECMAScript 2015 module 27 | * `es2015-script`: ECMAScript 2015 script 28 | -------------------------------------------------------------------------------- /tests/syntax/everything/es2015-module.js: -------------------------------------------------------------------------------- 1 | /* this file contains all grammatical productions in ECMA-262 edition 5.1 ** * **/ 2 | 3 | import i0 from "module"; 4 | import * as i1 from "module"; 5 | import {} from "module"; 6 | import { i2, a as i3, } from "module"; 7 | import i4, * as i5 from "module"; 8 | import i6, {} from "module"; 9 | import i7, { i8, var as i9 } from "module"; 10 | import "module"; 11 | 12 | export * from "module"; 13 | export {} from "module"; 14 | export { i0, i1 as a, i2 as var, } from "module"; 15 | export {}; 16 | export { i3, i4 as in }; 17 | export var e5, e6 = 0; 18 | export let e7, e8 = 0; 19 | export const e9 = 0, e10 = 0; 20 | export function e11(){} 21 | export function* e12(){} 22 | export class e13 {} 23 | export class e14 extends e15 {} 24 | export default function e16(){} 25 | // Unfortunately (for us), we can only have a single default export. 26 | /* 27 | export default function (){} 28 | export default function* i16(){} 29 | export default function* (){} 30 | export default class i17 {} 31 | export default class i18 extends i19 {} 32 | export default class {} 33 | export default x = 0; 34 | export default 0; 35 | export default (0, 1); 36 | */ 37 | 38 | // whitespace 39 | tab:for(;;)break tab; 40 | verticalTab:for(;;)break verticalTab; 41 | formFeed:for(;;)break formFeed; 42 | space:for(;;)break space; 43 | nbsp:for(;;)break nbsp; 44 | bom:for(;;)breakbom; 45 | 46 | // line terminators 47 | lineFeed:0 48 | 0; 49 | carriageReturn:0 0; 50 | carriageReturnLineFeed:0 51 | 0; 52 | lineSeparator:0
0; 53 | paragraphSeparator:0
0; 54 | 55 | // identifier names 56 | var $, _, \u0078, \u{2F9F9}, x$, x_, x\u0030, x\u{e01d5}, xa, x0, x0a, 57 | x0123456789, qwertyuiopasdfghjklzxcvbnm, QWERTYUIOPASDFGHJKLZXCVBNM; 58 | // a representative sample of ID_Start and ID_Continue 59 | var 䩶, x󠇕, œ一, ǻ둘, ɤ〩, φ, fiⅷ, ユニコード, x‌‍; 60 | let letx; let[x\u0078] = 0; const constx = 0; 61 | { let x; let y = 0; const z = 0; } 62 | 63 | null; true; false; 64 | 65 | 0; 1234567890; 66 | 0.; 0.00; 10.00; .0; .00 67 | 0e0; 0E0; 0.e0; 0.00e+0; .00e-0; 68 | 0x0; 0X0; 0x0123456789abcdefABCDEF; 69 | 0b0; 0B0; 0b01; 0b10; 0b10101010; 70 | 0o0; 0O0; 0o01234567; 71 | 2e308; 72 | 73 | ""; "'"; "\'\"\\\b\f\n\r\t\v\0"; 74 | "\0"; 75 | "\x01\x23\x45\x67\x89\xAB\xCD\xEF\xab\xcd\xef"; 76 | "\u0123\u4567\u89AB\uCDEF\u00ab\ucdef"; 77 | "\uD834\uDF06\u2603\u03C6 \u{0000001F4a9}\u{1D306}\u{2603}\u{3c6} 𝌆☃φ"; "\ 78 | "; 79 | 80 | ''; '"'; '\'\"\\\b\f\n\r\t\v\0'; 81 | '\0'; 82 | '\x01\x23\x45\x67\x89\xAB\xCD\xEF\xab\xcd\xef'; 83 | '\u0123\u4567\u89AB\uCDEF\u00ab\ucdef'; 84 | '\uD834\uDF06\u2603\u03C6 \u{0000001F4a9} \u{1D306}\u{2603}\u{3c6} 𝌆☃φ'; '\ 85 | '; 86 | 87 | /x/; /|/; /|||/; 88 | /^$\b\B/; /(?=(?!(?:(.))))/; 89 | /a.\f\n\r\t\v\0\[\-\/\\\x00\u0000\uD834\uDF06/; /\u{00000001d306}/u; /\d\D\s\S\w\W/; 90 | /\ca\cb\cc\cd\ce\cf\cg\ch\ci\cj\ck\cl\cm\cn\co\cp\cq\cr\cs\ct\cu\cv\cw\cx\cy\cz/; 91 | /\cA\cB\cC\cD\cE\cF\cG\cH\cI\cJ\cK\cL\cM\cN\cO\cP\cQ\cR\cS\cT\cU\cV\cW\cX\cY\cZ/; 92 | /[a-z-]/; /[^\b\-^]/; /[/\]\\]/; 93 | /./i; /./g; /./m; /./igm; 94 | /.*/; /.*?/; /.+/; /.+?/; /.?/; /.??/; 95 | /.{0}/; /.{0,}/; /.{0,0}/; 96 | 97 | `a`; `${0}`; `0${0,1}2`; `0${`1${2}3`}4`; 98 | `\``; `a\${b`; `\0\n\x0A\u000A\u{A}`; 99 | 100 | this; 101 | 102 | x; 103 | 104 | []; [,]; [0]; [0,]; [,0]; [0,0]; [0,0,]; [0,,0]; [,,]; 105 | 106 | ({}); ({x}); ({x:0}); ({x:0,y:0}); ({x:0,}); ({'x':0,"y":0,in:0}); 107 | ({ 108 | 0: 0, 0.: 0, 0.0: 0, .0: 0, 0e0: 0, 0x0: 0, [0]: 0, 109 | get x(){}, set x(a){}, get 'y'(){}, set "y"(a){}, 110 | get 0(){}, set 0(a){}, get var(){}, set var(a){}, 111 | get [0](){}, set [0](a){}, [1](){}, 112 | a(){}, 'b'(){}, "c"(){}, 0(){}, .1(){}, 1.(){}, 1e1(){}, 113 | var(a, b = 0, [c,, d = 0, ...e], {f, g: h, i = 0, i: j = 0}, ...k){}, 114 | set in([a, b = 0, [c,, d = 0, ...e], {f, g: h, i = 0, i: j = 0}, ...k]){}, 115 | *d(){}, *'e'(){}, *"f"(){}, *2(){}, *.2(){}, *3.(){}, *2e2(){}, *in(){}, 116 | }); 117 | ({ __proto__: null, get __proto__(){}, set __proto__(a){}, }); 118 | ({ "__proto__": null, __proto__(){}, }); 119 | 120 | 0..a; 0 .a; (0).a; 121 | 122 | 0[0]; 123 | 124 | // this function makes the NewExpression and CallExpression tests not throw at runtime 125 | x = function f(){ return f; }; x[0] = x; x.a = x; 126 | 127 | new x(); new new x()(); 128 | new x[0](); new x.a(); new x[0].a(); new x.a[0](); 129 | new x; new new x; new new x(); 130 | new new x().a; new new x()[0]; 131 | 132 | x(); x()(); x(x); x(x, x); 133 | x.a().a(); x[0]()[0](); x().a[0](); 134 | x(...[0,1,], ...[], ...function* f(){ return yield 2; }); 135 | x`a`; x`0${1}2`; 136 | 137 | x++; x--; 138 | 139 | delete void typeof+-~!x; ++x; --x; 140 | 141 | 0*0; 0/0; 0%0; 142 | 143 | 0+0; 0-0; 144 | 145 | 0<<0; 0>>0; 0>>>0; 146 | 147 | 0<0; 0>0; 0<=0; 0>=0; 148 | 0 instanceof function(){}; 149 | 0 in{}; 150 | 151 | 0==0; 0!=0; 0===0; 0!==0; 152 | 153 | 0&0; 0^0; 0|0; 0&&0; 0||0; 154 | 155 | 0?0:0; 0?0?0:0:0; 0||0?x=0:x=0; 156 | 157 | x=0; x*=0; x/=0; x%=0; x+=0; x-=0; 158 | x<<=0; x>>=0; x>>>=0; x&=0; x^=0; x|=0; 159 | 160 | 0,0; 0,0,0; x=0,x=0; 161 | 162 | 163 | {} {;} {0} {0;} {0;0} {0;0;} 164 | 165 | var x0; var x1,y2; var x3,y4,z5; 166 | var x6=0; var x7=0,y8; var x9,y10=0; var x11=0,y12=0; 167 | 168 | ; 169 | 170 | if(0); if(0);else; 171 | 172 | do;while(0) 0; 173 | do;while(0); 174 | do;while(0) 0 175 | while(0); 176 | for(;;)break; for(0;0;0); for((0 in[]);0;); 177 | for(var a0;;)break; for(var a1,b2;0;0); 178 | for(var a3=0;;)break; for(var a4=(0 in[]);0;); 179 | for(x in{}); for(var x12 in{}); 180 | for(x of[]); for(var x13 of[]); 181 | 182 | for(;0;)continue; x:for(;0;)continue x; 183 | 184 | for(;;)break; x:for(;;)break x; 185 | switch(0){case 0:break;} 186 | 187 | function f0(){ return; } 188 | function f1(){ return 0; } 189 | 190 | switch(0){} switch(0){case 0:} switch(0){case 0:case 0:} 191 | switch(0){default:} switch(0){case 0:default:case 0:} 192 | switch(0){case 0:;} switch(0){case 0:;;} 193 | switch(0){default:;} switch(0){default:;;} 194 | 195 | x:; x:y:; 196 | 197 | try { throw 0; }catch(x){} 198 | 199 | try{}catch(x){} 200 | try{}finally{} 201 | try{}catch(x){}finally{} 202 | 203 | debugger; 204 | 205 | function f2(){} 206 | function f3(x){} 207 | function f4(x,y){} 208 | function f5(){ function f6(){} } 209 | { function f7(){} }; 210 | for (;0;) +function f8(){}; 0 211 | do +function f9(){}; while(0) 212 | 213 | function f10(a, b = 0, [c,, d = 0, ...e], {f, g: h, i = 0, i: j = 0}, ...k){} 214 | function f11(){ "use strict" } 215 | function f12(){ 'use strict' } 216 | function f13(){ "other directive" } 217 | function f14(){ 'other directive' } 218 | function f15(){ ("string") } 219 | function f16(){ ('string') } 220 | function f17(){ 221 | 'string' 222 | +0 223 | } 224 | 225 | function*g0(a, b = 0, [c,, d = 0, ...e], {f, g: h, i = 0, i: j = 0}, ...k){ 226 | return a = yield* b = yield c = yield yield; 227 | } 228 | (function * g1(a, b = 0, [c,, d = 0, ...e], {f, g: h, i = 0, i: j = 0}, ...k){ 229 | return a = yield* b = yield c = yield yield; 230 | }) 231 | 232 | (function(){}); 233 | (function(x){}); 234 | (function(x,y){}); 235 | (function(){ function f(){} }); 236 | (function f(){}); 237 | (function f(x){}); 238 | (function f(x,y){}); 239 | (function f(){ function f(){} }); 240 | 241 | () => 0; 242 | () => {;} 243 | x => x 244 | x => x = 0 245 | x => y => x 246 | x => {x} 247 | x => ({x}); 248 | (x) => x; 249 | (x) => {return x}; 250 | (x) => ({x}); 251 | ({x}) => ({x}); 252 | (a, b = 0, [c,, d = 0, ...e], {f, g: h, i = 0, i: j = 0}, ...k) => {;}; 253 | 254 | [a] = [...[0]]; 255 | ({a} = {}); 256 | try{}catch([e]){} 257 | try{}catch({e}){} 258 | 259 | class A {} 260 | class B extends new A { 261 | constructor(a, b = 0, [c,, d = 0, ...e], {f, g: h, i = 0, i: j = 0}, ...k) { 262 | super(new.target); 263 | super()`template`; 264 | () => super(this); 265 | } 266 | m(a, b = 0, [c,, d = 0, ...e], {f, g: h, i = 0, i: j = 0}, ...k) { 267 | super.m(); 268 | super.m`template`; 269 | () => super.m(this); 270 | } 271 | 272 | ; 273 | 274 | static a(){} static 'b'(){} static 0(){} static [0](){} 275 | static *c(){ yield; } static *"d"() { yield; } static *1(){ yield; } static *[1](){ yield; } 276 | static var(){} static *in(){} 277 | 278 | static get e(){} static get 'f'(){} static get 2(){} static get [2](){} 279 | static set g(a){} static set "h"(a){} static set 3(a){} static set [3](a){} 280 | static get if(){} static set if(a){} 281 | 282 | a(){} 'b'(){} 0(){} [0](){} 283 | *c(){ yield; } *"d"(){ yield; } *1(){ yield; } *[1](){ yield; } 284 | var(){} *in(){ yield; } 285 | 286 | get e(){} get 'f'(){} get 2(){} get [2](){} 287 | set g(a){} set "h"(a){} set 3(a){} set [3](a){} 288 | get if() {} set if(f) {} 289 | } 290 | class C extends B { "constructor"(){ super(); } } 291 | -------------------------------------------------------------------------------- /tests/syntax/everything/es2015-script.js: -------------------------------------------------------------------------------- 1 | /* this file contains all grammatical productions in ECMA-262 edition 5.1 ** * **/ 2 | 3 | 4 | // whitespace 5 | tab:for(;;)break tab; 6 | verticalTab:for(;;)break verticalTab; 7 | formFeed:for(;;)break formFeed; 8 | space:for(;;)break space; 9 | nbsp:for(;;)break nbsp; 10 | bom:for(;;)breakbom; 11 | 12 | // line terminators 13 | lineFeed:0 14 | 0; 15 | carriageReturn:0 0; 16 | carriageReturnLineFeed:0 17 | 0; 18 | lineSeparator:0
0; 19 | paragraphSeparator:0
0; 20 | 21 | // identifier names 22 | var $, _, \u0078, \u{2F9F9}, x$, x_, x\u0030, x\u{e01d5}, xa, x0, x0a, 23 | x0123456789, qwertyuiopasdfghjklzxcvbnm, QWERTYUIOPASDFGHJKLZXCVBNM; 24 | // a representative sample of ID_Start and ID_Continue 25 | var 䩶, x󠇕, œ一, ǻ둘, ɤ〩, φ, fiⅷ, ユニコード, x‌‍; 26 | /* Not supported as of Acorn v2.6.4: var yield; */ 27 | let letx; let[x\u0078] = 0; const constx = 0; 28 | { let x; let y = 0; const z = 0; } 29 | /* Not supported as of Acorn v2.6.4: var let; */ 30 | var await; 31 | 32 | null; true; false; 33 | 34 | 0; 00; 1234567890; 01234567; 35 | 0.; 0.00; 10.00; .0; .00 36 | 0e0; 0E0; 0.e0; 0.00e+0; .00e-0; 37 | 0x0; 0X0; 0x0123456789abcdefABCDEF; 38 | 0b0; 0B0; 0b01; 0b10; 0b10101010; 39 | 0o0; 0O0; 0o01234567; 40 | 2e308; 41 | 42 | ""; "'"; "\'\"\\\b\f\n\r\t\v\0"; 43 | "\1\00\400\000"; 44 | "\x01\x23\x45\x67\x89\xAB\xCD\xEF\xab\xcd\xef"; 45 | "\u0123\u4567\u89AB\uCDEF\u00ab\ucdef"; 46 | "\uD834\uDF06\u2603\u03C6 \u{0000001F4a9}\u{1D306}\u{2603}\u{3c6} 𝌆☃φ"; "\ 47 | "; 48 | 49 | ''; '"'; '\'\"\\\b\f\n\r\t\v\0'; 50 | '\1\00\400\000'; 51 | '\x01\x23\x45\x67\x89\xAB\xCD\xEF\xab\xcd\xef'; 52 | '\u0123\u4567\u89AB\uCDEF\u00ab\ucdef'; 53 | '\uD834\uDF06\u2603\u03C6 \u{0000001F4a9} \u{1D306}\u{2603}\u{3c6} 𝌆☃φ'; '\ 54 | '; 55 | 56 | /x/; /|/; /|||/; 57 | /^$\b\B/; /(?=(?!(?:(.))))/; 58 | /a.\f\n\r\t\v\0\[\-\/\\\x00\u0000\uD834\uDF06/; /\u{00000001d306}/u; /\d\D\s\S\w\W/; 59 | /\ca\cb\cc\cd\ce\cf\cg\ch\ci\cj\ck\cl\cm\cn\co\cp\cq\cr\cs\ct\cu\cv\cw\cx\cy\cz/; 60 | /\cA\cB\cC\cD\cE\cF\cG\cH\cI\cJ\cK\cL\cM\cN\cO\cP\cQ\cR\cS\cT\cU\cV\cW\cX\cY\cZ/; 61 | /[a-z-]/; /[^\b\-^]/; /[/\]\\]/; 62 | /./i; /./g; /./m; /./igm; 63 | /.*/; /.*?/; /.+/; /.+?/; /.?/; /.??/; 64 | /.{0}/; /.{0,}/; /.{0,0}/; 65 | 66 | `a`; `${0}`; `0${0,1}2`; `0${`1${2}3`}4`; 67 | `\``; `a\${b`; `\0\n\x0A\u000A\u{A}`; 68 | 69 | this; 70 | 71 | x; 72 | 73 | []; [,]; [0]; [0,]; [,0]; [0,0]; [0,0,]; [0,,0]; [,,]; 74 | 75 | ({}); ({x}); ({x:0}); ({x:0,y:0}); ({x:0,}); ({'x':0,"y":0,in:0}); 76 | ({ 77 | 0: 0, 0.: 0, 0.0: 0, .0: 0, 0e0: 0, 0x0: 0, [0]: 0, 78 | get x(){}, set x(a){}, get 'y'(){}, set "y"(a){}, 79 | get 0(){}, set 0(a){}, get var(){}, set var(a){}, 80 | get [0](){}, set [0](a){}, [1](){}, 81 | a(){}, 'b'(){}, "c"(){}, 0(){}, .1(){}, 1.(){}, 1e1(){}, 82 | var(a, b = 0, [c,, d = 0, ...e], {f, g: h, i = 0, i: j = 0}, ...k){}, 83 | set in([a, b = 0, [c,, d = 0, ...e], {f, g: h, i = 0, i: j = 0}, ...k]){}, 84 | *d(){}, *'e'(){}, *"f"(){}, *2(){}, *.2(){}, *3.(){}, *2e2(){}, *in(){}, 85 | }); 86 | ({ __proto__: null, get __proto__(){}, set __proto__(a){}, }); 87 | ({ "__proto__": null, __proto__(){}, }); 88 | 89 | 0..a; 0 .a; (0).a; 90 | 91 | 0[0]; 92 | 93 | // this function makes the NewExpression and CallExpression tests not throw at runtime 94 | x = function f(){ return f; }; x[0] = x; x.a = x; 95 | 96 | new x(); new new x()(); 97 | new x[0](); new x.a(); new x[0].a(); new x.a[0](); 98 | new x; new new x; new new x(); 99 | new new x().a; new new x()[0]; 100 | 101 | x(); x()(); x(x); x(x, x); 102 | x.a().a(); x[0]()[0](); x().a[0](); 103 | x(...[0,1,], ...[], ...function* f(){ return yield 2; }); 104 | x`a`; x`0${1}2`; 105 | 106 | x++; x--; 107 | 108 | delete void typeof+-~!x; ++x; --x; 109 | 110 | 0*0; 0/0; 0%0; 111 | 112 | 0+0; 0-0; 113 | 114 | 0<<0; 0>>0; 0>>>0; 115 | 116 | 0<0; 0>0; 0<=0; 0>=0; 117 | 0 instanceof function(){}; 118 | 0 in{}; 119 | 120 | 0==0; 0!=0; 0===0; 0!==0; 121 | 122 | 0&0; 0^0; 0|0; 0&&0; 0||0; 123 | 124 | 0?0:0; 0?0?0:0:0; 0||0?x=0:x=0; 125 | 126 | x=0; x*=0; x/=0; x%=0; x+=0; x-=0; 127 | x<<=0; x>>=0; x>>>=0; x&=0; x^=0; x|=0; 128 | 129 | 0,0; 0,0,0; x=0,x=0; 130 | 131 | 132 | {} {;} {0} {0;} {0;0} {0;0;} 133 | 134 | var x; var x,y; var x,y,z; 135 | var x=0; var x=0,y; var x,y=0; var x=0,y=0; 136 | 137 | ; 138 | 139 | if(0); if(0);else; 140 | 141 | do;while(0) 0; 142 | do;while(0); 143 | do;while(0) 0 144 | while(0); 145 | for(;;)break; for(0;0;0); for((0 in[]);0;); 146 | for(var a;;)break; for(var a,b;0;0); 147 | for(var a=0;;)break; for(var a=(0 in[]);0;); 148 | for(x in{}); for(var x in{}); 149 | for(x of[]); for(var x of[]); 150 | 151 | for(;0;)continue; x:for(;0;)continue x; 152 | 153 | for(;;)break; x:for(;;)break x; 154 | switch(0){case 0:break;} 155 | 156 | function f(){ return; } 157 | function f(){ return 0; } 158 | 159 | with(0); 160 | 161 | switch(0){} switch(0){case 0:} switch(0){case 0:case 0:} 162 | switch(0){default:} switch(0){case 0:default:case 0:} 163 | switch(0){case 0:;} switch(0){case 0:;;} 164 | switch(0){default:;} switch(0){default:;;} 165 | 166 | x:; x:y:; 167 | 168 | try { throw 0; }catch(x){} 169 | 170 | try{}catch(x){} 171 | try{}finally{} 172 | try{}catch(x){}finally{} 173 | 174 | debugger; 175 | 176 | function f(){} 177 | function f(x){} 178 | function f(x,y){} 179 | function f(){ function f(){} } 180 | { function f(){} }; 181 | //for (;0;) label: function f(){} 0 182 | //do label: function f(){} while(0) 183 | 184 | function f(a, b = 0, [c,, d = 0, ...e], {f, g: h, i = 0, i: j = 0}, ...k){} 185 | function f(){ "use strict" } 186 | function f(){ 'use strict' } 187 | function f(){ "other directive" } 188 | function f(){ 'other directive' } 189 | function f(){ ("string") } 190 | function f(){ ('string') } 191 | function f(){ 192 | 'string' 193 | +0 194 | } 195 | 196 | function*g(a, b = 0, [c,, d = 0, ...e], {f, g: h, i = 0, i: j = 0}, ...k){ 197 | return a = yield* b = yield c = yield yield; 198 | } 199 | (function * g(a, b = 0, [c,, d = 0, ...e], {f, g: h, i = 0, i: j = 0}, ...k){ 200 | return a = yield* b = yield c = yield yield; 201 | }) 202 | yield; 203 | yield +0; 204 | yield * 0; 205 | 206 | (function(){}); 207 | (function(x){}); 208 | (function(x,y){}); 209 | (function(){ function f(){} }); 210 | (function f(){}); 211 | (function f(x){}); 212 | (function f(x,y){}); 213 | (function f(){ function f(){} }); 214 | 215 | () => 0; 216 | () => {;} 217 | x => x 218 | x => x = 0 219 | x => y => x 220 | x => {x} 221 | x => ({x}); 222 | (x) => x; 223 | (x) => {return x}; 224 | (x) => ({x}); 225 | ({x}) => ({x}); 226 | (a, b = 0, [c,, d = 0, ...e], {f, g: h, i = 0, i: j = 0}, ...k) => {;}; 227 | 228 | [a] = [...[0]]; 229 | ({a} = {}); 230 | try{}catch([e]){} 231 | try{}catch({e}){} 232 | 233 | class A {} 234 | class B extends new A { 235 | constructor(a, b = 0, [c,, d = 0, ...e], {f, g: h, i = 0, i: j = 0}, ...k) { 236 | super(new.target); 237 | super()`template`; 238 | () => super(this); 239 | } 240 | m(a, b = 0, [c,, d = 0, ...e], {f, g: h, i = 0, i: j = 0}, ...k) { 241 | super.m(); 242 | super.m`template`; 243 | () => super.m(this); 244 | } 245 | 246 | ; 247 | 248 | static a(){} static 'b'(){} static 0(){} static [0](){} 249 | static *c(){ yield; } static *"d"() { yield; } static *1(){ yield; } static *[1](){ yield; } 250 | static var(){} static *in(){} 251 | 252 | static get e(){} static get 'f'(){} static get 2(){} static get [2](){} 253 | static set g(a){} static set "h"(a){} static set 3(a){} static set [3](a){} 254 | static get if(){} static set if(a){} 255 | 256 | a(){} 'b'(){} 0(){} [0](){} 257 | *c(){ yield; } *"d"(){ yield; } *1(){ yield; } *[1](){ yield; } 258 | var(){} *in(){ yield; } 259 | 260 | get e(){} get 'f'(){} get 2(){} get [2](){} 261 | set g(a){} set "h"(a){} set 3(a){} set [3](a){} 262 | get if() {} set if(f) {} 263 | } 264 | class C extends B { "constructor"(){ super(); } } 265 | -------------------------------------------------------------------------------- /tests/syntax/everything/es5.js: -------------------------------------------------------------------------------- 1 | /* this file contains all grammatical productions in ECMA-262 edition 5.1 ** * **/ 2 | 3 | // whitespace 4 | tab:for(;;)break tab; 5 | verticalTab:for(;;)break verticalTab; 6 | formFeed:for(;;)break formFeed; 7 | space:for(;;)break space; 8 | nbsp:for(;;)break nbsp; 9 | bom:for(;;)breakbom; 10 | 11 | // line terminators 12 | lineFeed:0 13 | 0; 14 | carriageReturn:0 0; 15 | carriageReturnLineFeed:0 16 | 0; 17 | lineSeparator:0
0; 18 | paragraphSeparator:0
0; 19 | 20 | // identifier names 21 | var $, _, \u0078, x$, x_, x\u0030, xa, x0, x0a, x0123456789, 22 | qwertyuiopasdfghjklzxcvbnm, QWERTYUIOPASDFGHJKLZXCVBNM; 23 | // a representative sample of unicode letters and numbers 24 | var œ一, ǻ둘, ɤ〩, φ, fiⅷ, ユニコード, x‌‍; 25 | 26 | null; true; false; 27 | 28 | 0; 00; 1234567890; 01234567; 29 | 0.; 0.00; 10.00; .0; .00 30 | 0e0; 0E0; 0.e0; 0.00e+0; .00e-0; 31 | 0x0; 0X0; 0x0123456789abcdefABCDEF; 32 | 2e308; 33 | 34 | ""; "'"; "\'\"\\\b\f\n\r\t\v\0"; 35 | "\1\00\400\000"; 36 | "\x01\x23\x45\x67\x89\xAB\xCD\xEF"; 37 | "\u0123\u4567\u89AB\uCDEF"; "\ 38 | "; 39 | 40 | ''; '"'; '\'\"\\\b\f\n\r\t\v\0'; 41 | '\1\00\400\000'; 42 | '\x01\x23\x45\x67\x89\xAB\xCD\xEF'; 43 | '\u0123\u4567\u89AB\uCDEF'; '\ 44 | '; 45 | 46 | /x/; /|/; /|||/; 47 | /^$\b\B/; /(?=(?!(?:(.))))/; 48 | /a.\f\n\r\t\v\0\[\-\/\\\x00\u0000/; /\d\D\s\S\w\W/; 49 | /\ca\cb\cc\cd\ce\cf\cg\ch\ci\cj\ck\cl\cm\cn\co\cp\cq\cr\cs\ct\cu\cv\cw\cx\cy\cz/; 50 | /\cA\cB\cC\cD\cE\cF\cG\cH\cI\cJ\cK\cL\cM\cN\cO\cP\cQ\cR\cS\cT\cU\cV\cW\cX\cY\cZ/; 51 | /[a-z-]/; /[^\b\-^]/; /[/\]\\]/; 52 | /./i; /./g; /./m; /./igm; 53 | /.*/; /.*?/; /.+/; /.+?/; /.?/; /.??/; 54 | /.{0}/; /.{0,}/; /.{0,0}/; 55 | 56 | this; 57 | 58 | x; 59 | 60 | []; [,]; [0]; [0,]; [,0]; [0,0]; [0,0,]; [0,,0]; [,,]; 61 | 62 | ({}); ({x:0}); ({x:0,y:0}); ({x:0,}); ({'x':0,"y":0,var:0,}); 63 | ({0:0}); ({0.:0}); ({0.0:0}); ({.0:0}); ({0e0:0}); ({0x0:0}); 64 | ({ 65 | get x(){}, set x(a){}, get 'y'(){}, set "y"(a){}, 66 | get 0(){}, set 0(a){}, get var(){}, set var(x){}, 67 | }); 68 | 69 | 0..a; 70 | 71 | 0[0]; 72 | 73 | // this function makes the NewExpression and CallExpression tests not throw at runtime 74 | x = function f(){ return f; }; x[0] = x; x.a = x; 75 | 76 | new x(); new new x()(); 77 | new x[0](); new x.a(); new x[0].a(); new x.a[0](); 78 | new x; new new x; new new x(); 79 | new new x().a; new new x()[0]; 80 | 81 | x(); x()(); x(x); x(x, x); 82 | x.a().a(); x[0]()[0](); x().a[0](); 83 | 84 | x++; x--; 85 | 86 | delete void typeof+-~!x; ++x; --x; 87 | 88 | 0*0; 0/0; 0%0; 89 | 90 | 0+0; 0-0; 91 | 92 | 0<<0; 0>>0; 0>>>0; 93 | 94 | 0<0; 0>0; 0<=0; 0>=0; 95 | 0 instanceof function(){}; 96 | 0 in{}; 97 | 98 | 0==0; 0!=0; 0===0; 0!==0; 99 | 100 | 0&0; 0^0; 0|0; 0&&0; 0||0; 101 | 102 | 0?0:0; 0?0?0:0:0; 0||0?x=0:x=0; 103 | 104 | x=0; x*=0; x/=0; x%=0; x+=0; x-=0; 105 | x<<=0; x>>=0; x>>>=0; x&=0; x^=0; x|=0; 106 | 107 | 0,0; 0,0,0; x=0,x=0; 108 | 109 | 110 | {} {;} {0} {0;} {0;0} {0;0;} 111 | 112 | var x; var x,y; var x,y,z; 113 | var x=0; var x=0,y; var x,y=0; var x=0,y=0; 114 | 115 | ; 116 | 117 | if(0); if(0);else; 118 | 119 | do;while(0); 120 | while(0); 121 | for(;;)break; for(0;0;0); for((0 in[]);0;); 122 | for(var a;;)break; for(var a,b;0;0); 123 | for(var a=0;;)break; for(var a=(0 in[]);0;); 124 | for(x in{}); for(var x in{}); 125 | for(var x=[]in{}); for(var x=(0 in[])in{}); 126 | 127 | for(;0;)continue; x:for(;0;)continue x; 128 | 129 | for(;;)break; x:for(;;)break x; 130 | switch(0){case 0:break;} 131 | 132 | function f(){ return; } 133 | function f(){ return 0; } 134 | 135 | with(0); 136 | 137 | switch(0){} switch(0){case 0:} switch(0){case 0:case 0:} 138 | switch(0){default:} switch(0){case 0:default:case 0:} 139 | switch(0){case 0:;} switch(0){case 0:;;} 140 | switch(0){default:;} switch(0){default:;;} 141 | 142 | x:; x:y:; 143 | 144 | try { throw 0; }catch(x){} 145 | 146 | try{}catch(x){} 147 | try{}finally{} 148 | try{}catch(x){}finally{} 149 | 150 | debugger; 151 | 152 | function f(){} 153 | function f(x){} 154 | function f(x,y){} 155 | function f(){ function f(){} } 156 | 157 | function f(){ "use strict" } 158 | function f(){ 'use strict' } 159 | function f(){ "other directive" } 160 | function f(){ 'other directive' } 161 | function f(){ ("string") } 162 | function f(){ ('string') } 163 | function f(){ 164 | 'string' 165 | +0 166 | } 167 | 168 | (function(){}); 169 | (function(x){}); 170 | (function(x,y){}); 171 | (function(){ function f(){} }); 172 | (function f(){}); 173 | (function f(x){}); 174 | (function f(x,y){}); 175 | (function f(){ function f(){} }); 176 | -------------------------------------------------------------------------------- /tests/syntax/everything/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "everything.js", 3 | "version": "1.0.3", 4 | "description": "a single javascript file that contains every ECMA-262 edition 5.1 grammatical production", 5 | "main": "es5.js", 6 | "scripts": { 7 | "test": "mocha --inline-diffs --check-leaks -u tdd -R dot test" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git@github.com:michaelficarra/everything.js.git" 12 | }, 13 | "keywords": [ 14 | "ECMA-262", 15 | "grammar", 16 | "example", 17 | "javascript" 18 | ], 19 | "author": "Michael Ficarra", 20 | "license": "BSD-3-Clause", 21 | "bugs": { 22 | "url": "https://github.com/michaelficarra/everything.js/issues" 23 | }, 24 | "homepage": "https://github.com/michaelficarra/everything.js", 25 | "devDependencies": { 26 | "esprima": "^1.2.2", 27 | "mocha": "^1.21.3" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /tests/syntax/everything/test/parsing.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var fs = require("fs"); 4 | 5 | suite("parsing", function() { 6 | test("can be parsed and evaluated without error by node", function() { 7 | require(".."); 8 | }); 9 | test("can be parsed by esprima", function() { 10 | var programText = "" + fs.readFileSync(require.resolve("..")); 11 | require("esprima").parse(programText); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /tests/syntax/everything/test/unit.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var assert = require("assert"); 4 | var fs = require("fs"); 5 | 6 | var programText = "" + fs.readFileSync(require.resolve("..")); 7 | 8 | suite("unit", function() { 9 | test("contains all whitespace characters", function() { 10 | assert.notEqual(-1, programText.indexOf("\u0009"), "tab"); 11 | assert.notEqual(-1, programText.indexOf("\u000B"), "vertical tab"); 12 | assert.notEqual(-1, programText.indexOf("\u000C"), "form feed"); 13 | assert.notEqual(-1, programText.indexOf("\u0020"), "space"); 14 | assert.notEqual(-1, programText.indexOf("\u00A0"), "non-breaking space"); 15 | assert.notEqual(-1, programText.indexOf("\uFEFF"), "byte order mark (BOM)"); 16 | }); 17 | test("contains all newline characters", function() { 18 | assert.notEqual(-1, programText.indexOf("\u000A"), "line feed"); 19 | assert.notEqual(-1, programText.indexOf("\u000D"), "carriage return"); 20 | assert.notEqual(-1, programText.indexOf("\u2028"), "line separator"); 21 | assert.notEqual(-1, programText.indexOf("\u2029"), "paragraph separator"); 22 | }); 23 | test("contains identifier joining characters", function() { 24 | assert.notEqual(-1, programText.indexOf("\u200C"), "ZWNJ"); 25 | assert.notEqual(-1, programText.indexOf("\u200D"), "ZWJ"); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /tests/syntax/export.js: -------------------------------------------------------------------------------- 1 | export * from "module"; 2 | export {name} from "module"; 3 | export {a as b, c as d} from "module"; 4 | export {a as b1, c as d1}; 5 | export var a = 42; 6 | export let a1 = 42; 7 | export function test() {} 8 | export default function test() {} 9 | export async function atest() {} 10 | -------------------------------------------------------------------------------- /tests/syntax/function.js: -------------------------------------------------------------------------------- 1 | function f(a, b, c) { 2 | return null; 3 | } 4 | var g = function (a, b, c) { 5 | return null; 6 | }; 7 | function h(a, b = 1, c = 2) { 8 | return null; 9 | } 10 | function i(a = 1, b, c) { 11 | return null; 12 | } 13 | function j(...a) {} 14 | function k() {} 15 | var l = function () {}; 16 | var m = function (a = 1, b, c) {}; 17 | function* f() { 18 | yield 42; 19 | } 20 | function* g() { 21 | yield 42; 22 | yield 7; 23 | return "answer"; 24 | } 25 | let h2 = function* () {}; 26 | let f2 = (a) => a; 27 | let g2 = (a, b) => a + b; 28 | let h3 = (a, b = 0) => a + b; 29 | let i2 = (a, b) => {}; 30 | let j2 = () => {}; 31 | let k2 = () => ({}); 32 | let l2 = () => { 33 | let a = 42; 34 | return a; 35 | }; 36 | let m2 = () => ({ 37 | a: 1, 38 | b: 2 39 | }); 40 | -------------------------------------------------------------------------------- /tests/syntax/import.js: -------------------------------------------------------------------------------- 1 | import a1 from "module"; 2 | import a2, * as b1 from "module"; 3 | import * as a from "module"; 4 | import a3, {b as c, d as e, f} from "module"; 5 | import {a4 as b, c2} from "module"; 6 | import {a5, b as c3} from "module"; 7 | -------------------------------------------------------------------------------- /tests/syntax/loop.js: -------------------------------------------------------------------------------- 1 | for (let a in b) {} 2 | for (let [a, b] in c) {} 3 | for (let {a, b} in c) {} 4 | for (let {a: b, c} in d) {} 5 | for (let a of b) {} 6 | for (var [a, b] of c) {} 7 | for (let {a, b} in c) {} 8 | for (let {a: b, c} in d) {} 9 | for (let i = 0, {length} = list; i < length; i++) {} 10 | for (; ; ) {} 11 | -------------------------------------------------------------------------------- /tests/syntax/new.js: -------------------------------------------------------------------------------- 1 | new c(1)(2); 2 | (new c(3))(4); 3 | new(c(5)(6)); 4 | new(c(7))(8); 5 | new((c(9))(0)); 6 | -------------------------------------------------------------------------------- /tests/syntax/object.js: -------------------------------------------------------------------------------- 1 | let a = {}; 2 | let b = { 3 | "1": "one", 4 | "2": "two", 5 | "3": "three" 6 | }; 7 | let c = { 8 | [42]: "answer", 9 | [7]: "lucky" 10 | }; 11 | let d = { 12 | a: 1, 13 | b: 2, 14 | c: 3 15 | }; 16 | let e = d.a; 17 | let f = d["c"]; 18 | let g = { 19 | m() {}, 20 | ['m'](a) {}, 21 | n(a) { 22 | return a; 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /tests/syntax/precedence.js: -------------------------------------------------------------------------------- 1 | var a, b, c, d, e, f, g, x, y, z; 2 | a = 1 + 2 * 3 / 5; 3 | b = (1 + 2) * 3 / 5; 4 | c = (1 + 2) * (3 - 5); 5 | d = x | y ^ z; 6 | e = (x | y) ^ z; 7 | f = "a" + (1 + 2) + "b"; 8 | g = "a" + (1 - 2) + "b"; 9 | a = true || false && null; 10 | b = c == d || e != f; 11 | c = x instanceof y || x instanceof z; 12 | d = x == y && y != z; 13 | a = !false; 14 | b = !x instanceof Number; 15 | c = !(x instanceof Number); 16 | d = typeof a === 'boolean'; 17 | e = !typeof a === 'boolean'; 18 | f = !(typeof a === 'boolean'); 19 | a = 1.1.toString(); 20 | b = new A().toString(); 21 | c = new x.A().toString(); 22 | d = new x.y().z(); 23 | var r = /ab+c/i.exec('abc'); 24 | -------------------------------------------------------------------------------- /tests/syntax/sequence.js: -------------------------------------------------------------------------------- 1 | var x = a, b ; 2 | var y = (a,b) ; 3 | x,y ; 4 | f(1,(a,b)) ; 5 | f((a,b),3) ; 6 | if (a,b) c ; 7 | f(a, "b", (c => console.log("=" + c), c)) 8 | f(a, "b", c => (console.log("=" + c), c)) -------------------------------------------------------------------------------- /tests/syntax/template.js: -------------------------------------------------------------------------------- 1 | let a; 2 | let b = `this is a template`; 3 | let c = `this is a template 4 | with multiple 5 | lines`; 6 | let d = f`template with function`; 7 | let e = f`template with ${some} ${variables}`; 8 | let f = f`template with ${some}${variables}${attached}`; 9 | let g = f()`template with function call before`; 10 | let h = f().g`template with more complex function call`; 11 | -------------------------------------------------------------------------------- /tests/syntax/unary.js: -------------------------------------------------------------------------------- 1 | +(+2); 2 | -(-x); 3 | -------------------------------------------------------------------------------- /tests/syntax/variable.js: -------------------------------------------------------------------------------- 1 | var a; 2 | let b = 42; 3 | const c = 21 * 2; 4 | let {e} = d; 5 | var f, g = 42, h = false; 6 | let {i, j: k} = l; 7 | let [a2, b2] = c; 8 | var {a: [b3, {c2}]} = d; 9 | let {e2 = 42} = f; 10 | const {g: h2 = 42} = i; 11 | -------------------------------------------------------------------------------- /tests/syntax/x-sync-await.js: -------------------------------------------------------------------------------- 1 | // Test using 'await' in a sync function 2 | async function neg(x) { 3 | return -x ; 4 | } 5 | 6 | var syncReturnValue = {abc:123} ; 7 | var waited ; 8 | function sync(y) { 9 | waited = await neg(y)==-y ; 10 | return syncReturnValue ; 11 | } 12 | 13 | module.exports = async function() { 14 | waited = false ; 15 | var r = sync(10); 16 | setTimeout(function(){ 17 | // Although 'waited' is always true (if the test is good), 18 | // the value of 'r' is compilation/Promise specific: only 19 | // -es7 and nodent.Thenables() pass the value back 20 | // unmolested, whereas Promises (and therefore generators) 21 | // return a Promise of the value of neg(y), since that's 22 | // the first await in 'sync()' 23 | async return waited && r===syncReturnValue ; 24 | },1) ; 25 | } 26 | -------------------------------------------------------------------------------- /tests/syntax/x-sync-ret.js: -------------------------------------------------------------------------------- 1 | var res ; 2 | async function getSlowRemote() { 3 | // Do the async return after 1 seconds 4 | var timer = setTimeout(function(){ async return 0 },100) ; 5 | // Return a synchronous value too: 6 | return void function() { 7 | res = "aborted" ; 8 | clearTimeout(timer) ; 9 | } 10 | } 11 | if (!es7) { 12 | module.exports = async function() { 13 | return "n/a" ; 14 | } 15 | } else { 16 | module.exports = async function() { 17 | res = "" ; 18 | function done(){ 19 | res = "done" ; 20 | } 21 | var abort = getSlowRemote()(done) ; 22 | abort() ; 23 | var a = res ; 24 | await getSlowRemote() ; 25 | done() ; 26 | var b = res ; 27 | return a+b=="aborteddone" ; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /tests/syntax/yield.js: -------------------------------------------------------------------------------- 1 | function *w(){ 2 | var a = yield 1 ; 3 | var b = yield* 2 ; 4 | } 5 | 6 | -------------------------------------------------------------------------------- /tests/test-syntax.js: -------------------------------------------------------------------------------- 1 | /* Test parser/output routines, not async transformations */ 2 | var nodent = require('../nodent.js')() ; 3 | var fs = require('fs'); 4 | 5 | var n = 0 ; 6 | 7 | /* For each example, read it, parse it, output it, parse it again and check the trees & code strings are the same */ 8 | 9 | //List all files in a directory in Node.js recursively in a synchronous fashion 10 | function walkSync(dir, filelist) { 11 | filelist = filelist || []; 12 | if( dir[dir.length-1] != '/') dir=dir.concat('/') 13 | var fs = fs || require('fs'), 14 | files = fs.readdirSync(dir); 15 | filelist = filelist || []; 16 | files.forEach(function(file) { 17 | var stat = fs.lstatSync(dir + file) ; 18 | if (!stat.isSymbolicLink()) { 19 | if (stat.isDirectory()) 20 | filelist = walkSync(dir + file + '/', filelist); 21 | else 22 | filelist.push(dir+file); 23 | } 24 | }); 25 | return filelist; 26 | }; 27 | 28 | var diff = require('./onp/diff') ; 29 | 30 | function testFiles(paths,recurse) { 31 | var pass = [] ; 32 | paths.forEach(function(fn){ 33 | if (fs.statSync(fn).isDirectory()) { 34 | walkSync(fn,pass) ; 35 | } else { 36 | pass.push(fn) ; 37 | } 38 | }) ; 39 | pass = pass.filter(function(fn){ return fn.match(/\.js$/)}) ; 40 | 41 | console.log("Syntax check - "+pass.length+" test files installed....") ; 42 | 43 | pass.forEach(function(fn,idx){ 44 | if (idx && idx%1000==0) { 45 | console.error('Tested '+idx+'. '+(idx-n)+' fails so far...') ; 46 | } 47 | var code = fs.readFileSync(fn).toString() ; 48 | try { 49 | var r = {name:fn, toString:function(){ 50 | return this.name+": "+(this.error||"") 51 | +(this.diff?"\n"+this.diff.summary():"") 52 | +(this.tree?"\n"+this.tree.summary():"") ; 53 | }} ; 54 | 55 | var opts = {parser:{sourceType:'script',allowImportExportEverywhere:true,onComment:null}} ; 56 | try { 57 | var initialAST = nodent.parse(code,"",null,opts) ; 58 | var ci = nodent.prettyPrint(initialAST,opts) ; 59 | } catch(ex) { 60 | opts.parser.sourceType = 'module' ; 61 | ci = nodent.prettyPrint(nodent.parse(code,"",null,opts),opts) ; 62 | } 63 | var co = nodent.prettyPrint(nodent.parse(ci.code,"",null,opts)) ; 64 | r.diff = diff(ci.code,co.code) ; 65 | eqTree(ci.ast,co.ast) ; 66 | if (!r.diff.diff) { 67 | n += 1 ; 68 | return {name:fn} ; 69 | } else { 70 | console.log(r.error = r.toString()) ; 71 | return r ; 72 | } 73 | } catch (ex) { 74 | if (!initialAST) { 75 | n += 1 ; 76 | r.error = "Not valid javascript (ignored "+opts.parser.sourceType+")" ; 77 | } else { 78 | r.error = ex.message ; 79 | if (ci && co && ci.ast && co.ast) { 80 | var inTree = JSON.stringify(ci.ast,noLocations,2) ; 81 | var outTree = JSON.stringify(co.ast,noLocations,2) ; 82 | r.tree = diff(inTree,outTree) ; 83 | } 84 | } 85 | console.log(r.toString()) ; 86 | return r ; 87 | } 88 | }) ; 89 | if (n===pass.length) 90 | console.log("Syntax check - pass "+n+" of "+pass.length) ; 91 | else if (pass.length<1000) { 92 | console.log("Syntax check - FAIL "+(pass.length-n)+" of "+pass.length) ; 93 | } 94 | } 95 | 96 | function noLocations(k,v) { 97 | return locations(k)?v:undefined ; 98 | } 99 | 100 | function locations(k) { 101 | return ['end','start','loc'].indexOf(k)<0 ; 102 | } 103 | 104 | debugger ; 105 | function eqTree(a,b,p) { 106 | if (!p) p = "" ; 107 | var ka = Object.keys(a).filter(locations).sort() ; 108 | var kb = Object.keys(b).filter(locations).sort() ; 109 | if (ka.length > kb.length) 110 | throw new Error("length("+ka.length+","+kb.length+") "+p) ; 111 | 112 | for (var i=0;i "+ka[i]+":"+a[ka[i]].type) ; 119 | return true ; 120 | } 121 | 122 | module.exports = {testFiles:testFiles} ; 123 | -------------------------------------------------------------------------------- /tests/watch-comp.js: -------------------------------------------------------------------------------- 1 | try { 2 | process.stdout.write('\033[2J\033[1;1H') ; 3 | var nodent = require('../nodent.js')({log:function(){}}) ; 4 | var options = { 5 | sourcemap:false, 6 | es7:true, 7 | promises:true 8 | } ; 9 | var src = require('fs').readFileSync(process.argv[2]).toString() ; 10 | options = nodent.parseCompilerOptions(src) || {}; 11 | options.sourcemap = false ; 12 | pr = nodent.compile(src,"source.js",0,options) ; 13 | console.log(pr.code) ; 14 | eval(pr.code) ; 15 | } catch (ex) { 16 | console.warn(ex) ; 17 | } 18 | --------------------------------------------------------------------------------