9 var util = require('./compile/util');
13 'co*': checkGenerators,
14 'es7': checkAsyncFunction
19 'regenerator': getRegenerator
24 { async: 'es7', transpile: 'nodent' },
25 { async: 'co*', transpile: 'regenerator' }
29 var regenerator, nodent;
32 function setupAsync(opts, required) {
33 if (required !== false) required = true;
34 var async = opts.async
35 , transpile = opts.transpile
38 switch (typeof transpile) {
40 var get = TRANSPILE[transpile];
41 if (!get) throw new Error('bad transpiler: ' + transpile);
42 return (opts._transpileFunc = get(opts, required));
45 if (typeof async == 'string') {
47 if (!check) throw new Error('bad async mode: ' + async);
48 return (opts.transpile = check(opts, required));
51 for (var i=0; i<MODES.length; i++) {
53 if (setupAsync(_opts, false)) {
54 util.copy(_opts, opts);
55 return opts.transpile;
58 /* istanbul ignore next */
59 throw new Error('generators, nodent and regenerator are not available');
61 return (opts._transpileFunc = opts.transpile);
63 throw new Error('bad transpiler: ' + transpile);
68 function checkGenerators(opts, required) {
69 /* jshint evil: true */
71 (new Function('(function*(){})()'))();
74 /* istanbul ignore next */
75 if (required) throw new Error('generators not supported');
80 function checkAsyncFunction(opts, required) {
81 /* jshint evil: true */
83 (new Function('(async function(){})()'))();
84 /* istanbul ignore next */
87 if (required) throw new Error('es7 async functions not supported');
92 function getRegenerator(opts, required) {
95 var name = 'regenerator';
96 regenerator = require(name);
97 regenerator.runtime();
99 if (!opts.async || opts.async === true)
101 return regeneratorTranspile;
103 /* istanbul ignore next */
104 if (required) throw new Error('regenerator not available');
109 function regeneratorTranspile(code) {
110 return regenerator.compile(code).code;
114 function getNodent(opts, required) {
115 /* jshint evil: true */
119 nodent = require(name)({ log: false, dontInstallRequireHook: true });
121 if (opts.async != 'es7') {
122 if (opts.async && opts.async !== true) console.warn('nodent transpiles only es7 async functions');
125 return nodentTranspile;
127 /* istanbul ignore next */
128 if (required) throw new Error('nodent not available');
133 function nodentTranspile(code) {
134 return nodent.compile(code, '', { promises: true, sourcemap: false }).code;
139 * Creates validating function for passed schema with asynchronous loading of missing schemas.
140 * `loadSchema` option should be a function that accepts schema uri and node-style callback.
142 * @param {Object} schema schema object
143 * @param {Function} callback node-style callback, it is always called with 2 parameters: error (or null) and validating function.
145 function compileAsync(schema, callback) {
146 /* eslint no-shadow: 0 */
147 /* jshint validthis: true */
151 schemaObj = this._addSchema(schema);
153 setTimeout(function() { callback(e); });
156 if (schemaObj.validate) {
157 setTimeout(function() { callback(null, schemaObj.validate); });
159 if (typeof this._opts.loadSchema != 'function')
160 throw new Error('options.loadSchema should be a function');
161 _compileAsync(schema, callback, true);
165 function _compileAsync(schema, callback, firstCall) {
167 try { validate = self.compile(schema); }
169 if (e.missingSchema) loadMissingSchema(e);
170 else deferCallback(e);
173 deferCallback(null, validate);
175 function loadMissingSchema(e) {
176 var ref = e.missingSchema;
177 if (self._refs[ref] || self._schemas[ref])
178 return callback(new Error('Schema ' + ref + ' is loaded but ' + e.missingRef + ' cannot be resolved'));
179 var _callbacks = self._loadingSchemas[ref];
181 if (typeof _callbacks == 'function')
182 self._loadingSchemas[ref] = [_callbacks, schemaLoaded];
184 _callbacks[_callbacks.length] = schemaLoaded;
186 self._loadingSchemas[ref] = schemaLoaded;
187 self._opts.loadSchema(ref, function (err, sch) {
188 var _callbacks = self._loadingSchemas[ref];
189 delete self._loadingSchemas[ref];
190 if (typeof _callbacks == 'function') {
191 _callbacks(err, sch);
193 for (var i=0; i<_callbacks.length; i++)
194 _callbacks[i](err, sch);
199 function schemaLoaded(err, sch) {
200 if (err) return callback(err);
201 if (!(self._refs[ref] || self._schemas[ref])) {
203 self.addSchema(sch, ref);
209 _compileAsync(schema, callback);
213 function deferCallback(err, validate) {
214 if (firstCall) setTimeout(function() { callback(err, validate); });
215 else return callback(err, validate);