123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190 |
- 'use strict'
- const pathUtil = require('path')
- class DetailedError extends Error {
- constructor (message /* :string */, details /* :Object */) {
- Object.keys(details).forEach(function (key) {
- const data = details[key]
- const value = require('util').inspect(data.stack || data.message || data)
- message += `\n${key}: ${value}`
- })
- super(message)
- }
- }
- const blacklist = process && process.env && process.env.EDITIONS_SYNTAX_BLACKLIST && process.env.EDITIONS_SYNTAX_BLACKLIST.split(',')
- const syntaxFailedCombitions = {}
- const syntaxBlacklist = {}
- syntaxBlacklist.import = new Error('The import syntax is skipped as the module package.json field eliminates the need for autoloader support')
- syntaxBlacklist.coffeescript = new Error('The coffeescript syntax is skipped as we want to use a precompiled edition rather than compiling at runtime')
- syntaxBlacklist.typescript = new Error('The typescript syntax is skipped as we want to use a precompiled edition rather than compiling at runtime')
- if ( process && process.versions && process.versions.node ) {
- const EARLIEST_ESNEXT_NODE_VERSION = [0, 12]
- const NODE_VERSION = process.versions.node.split('.').map((n) => parseInt(n, 10))
- const ESNEXT_UNSUPPORTED = NODE_VERSION[0] < EARLIEST_ESNEXT_NODE_VERSION[0] || (
- NODE_VERSION[0] === EARLIEST_ESNEXT_NODE_VERSION[0] &&
- NODE_VERSION[1] < EARLIEST_ESNEXT_NODE_VERSION[1]
- )
- if ( ESNEXT_UNSUPPORTED ) syntaxBlacklist.esnext = new Error('The esnext syntax is skipped on early node versions as attempting to use esnext features will output debugging information on these node versions')
- }
- if ( blacklist ) {
- for ( let i = 0; i < blacklist.length; ++i ) {
- const syntax = blacklist[i].trim().toLowerCase()
- syntaxBlacklist[syntax] = new DetailedError('The EDITIONS_SYNTAX_BLACKLIST environment variable has blacklisted an edition syntax:', {syntax, blacklist})
- }
- }
- function requireEdition ( edition , opts ) /* :any */ {
-
- Object.defineProperty(opts, 'require', {value: opts.require, enumerable: false})
-
-
- const cwd = opts.cwd || ''
- const dir = edition.directory || ''
- let entry = opts.entry || edition.entry || ''
- if ( dir && entry && entry.indexOf(dir + '/') === 0 ) entry = entry.substring(dir.length + 1)
-
-
-
-
-
-
- if ( !dir && !entry ) {
- const editionFailure = new DetailedError('Skipped edition due to no entry or directory being specified:', {edition, cwd, dir, entry})
- throw editionFailure
- }
- const entryPath = pathUtil.resolve(cwd, dir, entry)
-
-
- const syntaxes = edition.syntaxes && edition.syntaxes.map((i) => i.toLowerCase()).sort()
- const syntaxCombination = syntaxes && syntaxes.join(', ')
- if ( syntaxes && syntaxCombination ) {
-
- const unsupportedSyntaxes = syntaxes.filter((i) => syntaxBlacklist[i.toLowerCase()])
- if ( unsupportedSyntaxes.length ) {
- const editionFailure = new DetailedError('Skipped edition due to it containing an unsupported syntax:', {edition, unsupportedSyntaxes})
- throw editionFailure
- }
-
- else if ( syntaxFailedCombitions[syntaxCombination] ) {
- const previousCombinationFailure = syntaxFailedCombitions[syntaxCombination]
- const editionFailure = new DetailedError('Skipped edition due to its syntax combinatiom failing previously:', {edition, previousCombinationFailure})
- throw editionFailure
- }
- }
-
- try {
- return opts.require(entryPath)
- }
- catch ( error ) {
-
- const editionFailure = new DetailedError('Failed to load the edition due to a load error:', {edition, error: error.stack})
-
-
- if ( syntaxCombination ) syntaxFailedCombitions[syntaxCombination] = editionFailure
-
- throw editionFailure
- }
- }
- function requireEditions ( editions , opts ) /* :any */ {
-
- if ( opts.package == null ) opts.package = 'custom runtime package'
-
- if ( !editions || editions.length === 0 ) {
- throw new DetailedError('No editions were specified:', {opts})
- }
-
- const editionFailures = []
-
- for ( let i = 0; i < editions.length; ++i ) {
- const edition = editions[i]
- try {
- return requireEdition(edition, opts)
- }
- catch ( err ) {
- editionFailures.push(err)
- }
- }
-
- throw new DetailedError('There are no suitable editions for this environment:', {opts, editions, failures: editionFailures})
- }
- function requirePackage (cwd , require , entry ) /* :any */ {
-
- const packagePath = pathUtil.resolve(cwd, 'package.json')
- const {name, editions} = require(packagePath)
- const opts = {cwd, require}
- if ( name ) opts.package = name
- if ( entry ) opts.entry = entry
- return requireEditions(editions, opts)
- }
- module.exports = {requireEdition, requireEditions, requirePackage}
|