123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218 |
- 'use strict';
- module.exports = {
- setup: setupAsync,
- compile: compileAsync
- };
- var util = require('./compile/util');
- var ASYNC = {
- '*': checkGenerators,
- 'co*': checkGenerators,
- 'es7': checkAsyncFunction
- };
- var TRANSPILE = {
- 'nodent': getNodent,
- 'regenerator': getRegenerator
- };
- var MODES = [
- { async: 'co*' },
- { async: 'es7', transpile: 'nodent' },
- { async: 'co*', transpile: 'regenerator' }
- ];
- var regenerator, nodent;
- function setupAsync(opts, required) {
- if (required !== false) required = true;
- var async = opts.async
- , transpile = opts.transpile
- , check;
- switch (typeof transpile) {
- case 'string':
- var get = TRANSPILE[transpile];
- if (!get) throw new Error('bad transpiler: ' + transpile);
- return (opts._transpileFunc = get(opts, required));
- case 'undefined':
- case 'boolean':
- if (typeof async == 'string') {
- check = ASYNC[async];
- if (!check) throw new Error('bad async mode: ' + async);
- return (opts.transpile = check(opts, required));
- }
- for (var i=0; i<MODES.length; i++) {
- var _opts = MODES[i];
- if (setupAsync(_opts, false)) {
- util.copy(_opts, opts);
- return opts.transpile;
- }
- }
- /* istanbul ignore next */
- throw new Error('generators, nodent and regenerator are not available');
- case 'function':
- return (opts._transpileFunc = opts.transpile);
- default:
- throw new Error('bad transpiler: ' + transpile);
- }
- }
- function checkGenerators(opts, required) {
- /* jshint evil: true */
- try {
- (new Function('(function*(){})()'))();
- return true;
- } catch(e) {
- /* istanbul ignore next */
- if (required) throw new Error('generators not supported');
- }
- }
- function checkAsyncFunction(opts, required) {
- /* jshint evil: true */
- try {
- (new Function('(async function(){})()'))();
- /* istanbul ignore next */
- return true;
- } catch(e) {
- if (required) throw new Error('es7 async functions not supported');
- }
- }
- function getRegenerator(opts, required) {
- try {
- if (!regenerator) {
- var name = 'regenerator';
- regenerator = require(name);
- regenerator.runtime();
- }
- if (!opts.async || opts.async === true)
- opts.async = 'es7';
- return regeneratorTranspile;
- } catch(e) {
- /* istanbul ignore next */
- if (required) throw new Error('regenerator not available');
- }
- }
- function regeneratorTranspile(code) {
- return regenerator.compile(code).code;
- }
- function getNodent(opts, required) {
- /* jshint evil: true */
- try {
- if (!nodent) {
- var name = 'nodent';
- nodent = require(name)({ log: false, dontInstallRequireHook: true });
- }
- if (opts.async != 'es7') {
- if (opts.async && opts.async !== true) console.warn('nodent transpiles only es7 async functions');
- opts.async = 'es7';
- }
- return nodentTranspile;
- } catch(e) {
- /* istanbul ignore next */
- if (required) throw new Error('nodent not available');
- }
- }
- function nodentTranspile(code) {
- return nodent.compile(code, '', { promises: true, sourcemap: false }).code;
- }
- /**
- * Creates validating function for passed schema with asynchronous loading of missing schemas.
- * `loadSchema` option should be a function that accepts schema uri and node-style callback.
- * @this Ajv
- * @param {Object} schema schema object
- * @param {Function} callback node-style callback, it is always called with 2 parameters: error (or null) and validating function.
- */
- function compileAsync(schema, callback) {
- /* eslint no-shadow: 0 */
- /* jshint validthis: true */
- var schemaObj;
- var self = this;
- try {
- schemaObj = this._addSchema(schema);
- } catch(e) {
- setTimeout(function() { callback(e); });
- return;
- }
- if (schemaObj.validate) {
- setTimeout(function() { callback(null, schemaObj.validate); });
- } else {
- if (typeof this._opts.loadSchema != 'function')
- throw new Error('options.loadSchema should be a function');
- _compileAsync(schema, callback, true);
- }
- function _compileAsync(schema, callback, firstCall) {
- var validate;
- try { validate = self.compile(schema); }
- catch(e) {
- if (e.missingSchema) loadMissingSchema(e);
- else deferCallback(e);
- return;
- }
- deferCallback(null, validate);
- function loadMissingSchema(e) {
- var ref = e.missingSchema;
- if (self._refs[ref] || self._schemas[ref])
- return callback(new Error('Schema ' + ref + ' is loaded but ' + e.missingRef + ' cannot be resolved'));
- var _callbacks = self._loadingSchemas[ref];
- if (_callbacks) {
- if (typeof _callbacks == 'function')
- self._loadingSchemas[ref] = [_callbacks, schemaLoaded];
- else
- _callbacks[_callbacks.length] = schemaLoaded;
- } else {
- self._loadingSchemas[ref] = schemaLoaded;
- self._opts.loadSchema(ref, function (err, sch) {
- var _callbacks = self._loadingSchemas[ref];
- delete self._loadingSchemas[ref];
- if (typeof _callbacks == 'function') {
- _callbacks(err, sch);
- } else {
- for (var i=0; i<_callbacks.length; i++)
- _callbacks[i](err, sch);
- }
- });
- }
- function schemaLoaded(err, sch) {
- if (err) return callback(err);
- if (!(self._refs[ref] || self._schemas[ref])) {
- try {
- self.addSchema(sch, ref);
- } catch(e) {
- callback(e);
- return;
- }
- }
- _compileAsync(schema, callback);
- }
- }
- function deferCallback(err, validate) {
- if (firstCall) setTimeout(function() { callback(err, validate); });
- else return callback(err, validate);
- }
- }
- }
|