Fix IE11 Support (#583)

- Revert ES6 changes to arithmetics.pegjs
- Use Array#forEach instead of for..of
- Don't use native Array#find & Array#findIndex
- Added util/arrays.js (find & findIndex)
- Use Function instead of eval
master
Futago-za Ryuu 6 years ago
parent e636ee654c
commit 616749377b

@ -5,17 +5,17 @@
Expression Expression
= head:Term tail:(_ @("+" / "-") _ @Term)* { = head:Term tail:(_ @("+" / "-") _ @Term)* {
return tail.reduce(function(result, [operator, factor]) { return tail.reduce(function(result, element) {
if (operator === "+") return result + factor; if (element[0] === "+") return result + element[1];
if (operator === "-") return result - factor; if (element[0] === "-") return result - element[1];
}, head); }, head);
} }
Term Term
= head:Factor tail:(_ @("*" / "/") _ @Factor)* { = head:Factor tail:(_ @("*" / "/") _ @Factor)* {
return tail.reduce(function(result, [operator, factor]) { return tail.reduce(function(result, element) {
if (operator === "*") return result * factor; if (element[0] === "*") return result * element[1];
if (operator === "/") return result / factor; if (element[0] === "/") return result / element[1];
}, head); }, head);
} }

@ -27,21 +27,13 @@ class Grammar extends Node {
findRule( name ) { findRule( name ) {
return this.rules.find( rule => rule.name === name ); return util.find( this.rules, rule => rule.name === name );
} }
indexOfRule( name ) { indexOfRule( name ) {
const rules = this.rules; return util.findIndex( this.rules, rule => rule.name === name );
for ( let i = 0; i < rules.length; ++i ) {
if ( rules[ i ].name === name ) return i;
}
return -1;
} }

@ -67,6 +67,9 @@ const compiler = {
trace: false trace: false
} ); } );
// We want `session.vm.runInContext` to return the parser
if ( options.output === "parser" ) options.format = "bare";
util.each( session.passes, stage => { util.each( session.passes, stage => {
stage.forEach( pass => { stage.forEach( pass => {

@ -222,7 +222,7 @@ function generateBytecode( ast, session ) {
ignoreCase: node.ignoreCase ignoreCase: node.ignoreCase
}; };
const pattern = JSON.stringify( cls ); const pattern = JSON.stringify( cls );
const index = classes.findIndex( c => JSON.stringify( c ) === pattern ); const index = util.findIndex( classes, c => JSON.stringify( c ) === pattern );
return index === -1 ? classes.push( cls ) - 1 : index; return index === -1 ? classes.push( cls ) - 1 : index;
} }
@ -230,7 +230,7 @@ function generateBytecode( ast, session ) {
function addExpectedConst( expected ) { function addExpectedConst( expected ) {
const pattern = JSON.stringify( expected ); const pattern = JSON.stringify( expected );
const index = expectations.findIndex( e => JSON.stringify( e ) === pattern ); const index = util.findIndex( expectations, e => JSON.stringify( e ) === pattern );
return index === -1 ? expectations.push( expected ) - 1 : index; return index === -1 ? expectations.push( expected ) - 1 : index;
} }
@ -239,7 +239,7 @@ function generateBytecode( ast, session ) {
const func = { predicate: predicate, params: params, body: code }; const func = { predicate: predicate, params: params, body: code };
const pattern = JSON.stringify( func ); const pattern = JSON.stringify( func );
const index = functions.findIndex( f => JSON.stringify( f ) === pattern ); const index = util.findIndex( functions, f => JSON.stringify( f ) === pattern );
return index === -1 ? functions.push( func ) - 1 : index; return index === -1 ? functions.push( func ) - 1 : index;
} }

@ -22,18 +22,18 @@ function removeProxyRules( ast, session, options ) {
const allowedStartRules = options.allowedStartRules; const allowedStartRules = options.allowedStartRules;
const rules = []; const rules = [];
for ( const rule of ast.rules ) { ast.rules.forEach( rule => {
if ( isProxyRule( rule ) ) { if ( isProxyRule( rule ) ) {
replaceRuleRefs( ast, rule.name, rule.expression.name ); replaceRuleRefs( ast, rule.name, rule.expression.name );
if ( allowedStartRules.indexOf( rule.name ) < 0 ) continue; if ( allowedStartRules.indexOf( rule.name ) < 0 ) return;
} }
rules.push( rule ); rules.push( rule );
} } );
ast.rules = rules; ast.rules = rules;

@ -3414,11 +3414,11 @@ function peg$parse(input, options) {
// Populate `RESERVED_WORDS` using the optional option `reservedWords` // Populate `RESERVED_WORDS` using the optional option `reservedWords`
const reservedWords = options.reservedWords || util.reservedWords; const reservedWords = options.reservedWords || util.reservedWords;
if ( Array.isArray( reservedWords ) ) { if ( Array.isArray( reservedWords ) ) reservedWords.forEach( word => {
for ( const word of reservedWords ) RESERVED_WORDS[ word ] = true; RESERVED_WORDS[ word ] = true;
} } );
// Helper to construct a new AST Node // Helper to construct a new AST Node
function createNode( type, details ) { function createNode( type, details ) {

@ -0,0 +1,33 @@
"use strict";
/**
* The `findIndex()` method returns the index of the first element in the array that satisfies the
* provided testing function, otherwise `-1` is returned.
*/
function findIndex( array, condition ) {
for ( let i = 0; i < array.length; ++i ) {
if ( condition( array[ i ], i ) ) return i;
}
return -1;
}
/**
* The `find()` method returns the value of the first element in the array that satisfies the
* provided testing function, otherwise `undefined` is returned.
*/
function find( array, condition ) {
const index = findIndex( array, condition );
return index < 0 ? void 0 : array[ index ];
}
// Exports
module.exports = { findIndex, find };

@ -1,9 +1,11 @@
"use strict"; "use strict";
const arrays = require( "./arrays" );
const js = require( "./js" ); const js = require( "./js" );
const objects = require( "./objects" ); const objects = require( "./objects" );
const vm = require( "./vm" ); const vm = require( "./vm" );
objects.extend( exports, arrays );
objects.extend( exports, js ); objects.extend( exports, js );
objects.extend( exports, objects ); objects.extend( exports, objects );
objects.extend( exports, vm ); objects.extend( exports, vm );

@ -1,58 +1,26 @@
"use strict"; "use strict";
const code = ( () => { /**
* `eval` the given source, using properties found in `context` as top-level variables.
*
* Based on `vm.runInContext` found in Node.js, this is a cross-env solution.
*/
function runInContext( source, context ) {
let preface = ""; const argumentKeys = Object.keys( context );
const MODULE_VARS = { const argumentValues = argumentKeys.map( argument => context[ argument ] );
"module": true, const object = {};
"process": true, argumentKeys.push( "_peg$object", `_peg$object.result = ${ source };` );
"code": true, argumentValues.push( object );
"runInContext": true,
"source": true,
"preface": true,
}; Function( ...argumentKeys )( ...argumentValues );
Object.keys( MODULE_VARS ).forEach( name => { return object.result;
preface += `var ${ name } = void 0;`;
} ); }
function generate( name ) { // Exports
return `${ ( MODULE_VARS[ name ] ? "" : "var " ) + name } = __context.${ name };`; module.exports = { runInContext };
}
return { generate, preface };
} )();
module.exports = {
// `eval` the given source, using properties found in `context` as top-level
// variables, while hiding some variables in this module from the source.
//
// Based on `vm.runInContext` found in Node.js, this is a cross-env solution.
runInContext( source, __context ) {
let preface = code.preface;
if ( typeof __context === "object" ) {
Object.keys( __context ).forEach( name => {
preface += code.generate( name );
} );
}
return eval( preface + source );
},
};

@ -435,7 +435,7 @@ declare namespace peg {
interface ISessionVM { interface ISessionVM {
runInContext( code: string, vm$context?: { [ name: string ]: any; } ): any; runInContext( code: string, context?: { [ name: string ]: any; } ): any;
} }
@ -537,6 +537,12 @@ declare namespace peg {
} }
interface IArrayUtils {
findIndex( array: any[], condition: IIterator ): number;
find( array: any[], condition: IIterator ): any;
}
interface IJavaScriptUtils { interface IJavaScriptUtils {
stringEscape( s: string ): string; stringEscape( s: string ): string;
@ -554,7 +560,7 @@ declare namespace peg {
enforceFastProperties( o: {} ): {}; enforceFastProperties( o: {} ): {};
} }
interface util extends IJavaScriptUtils, IObjectUtils, compiler.ISessionVM { interface util extends IArrayUtils, IJavaScriptUtils, IObjectUtils, compiler.ISessionVM {
noop(): void; noop(): void;
convertPasses( stages: IStageMap ): compiler.IPassesMap; convertPasses( stages: IStageMap ): compiler.IPassesMap;

@ -151,6 +151,13 @@ declare module "pegjs/lib/util" {
} }
declare module "pegjs/lib/util/arrays" {
const arrays: peg.IArrayUtils;
export default arrays;
}
declare module "pegjs/lib/util/index" { declare module "pegjs/lib/util/index" {
export default peg.util; export default peg.util;

@ -31,11 +31,11 @@
// Populate `RESERVED_WORDS` using the optional option `reservedWords` // Populate `RESERVED_WORDS` using the optional option `reservedWords`
const reservedWords = options.reservedWords || util.reservedWords; const reservedWords = options.reservedWords || util.reservedWords;
if ( Array.isArray( reservedWords ) ) { if ( Array.isArray( reservedWords ) ) reservedWords.forEach( word => {
for ( const word of reservedWords ) RESERVED_WORDS[ word ] = true; RESERVED_WORDS[ word ] = true;
} } );
// Helper to construct a new AST Node // Helper to construct a new AST Node
function createNode( type, details ) { function createNode( type, details ) {

Loading…
Cancel
Save