-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
141 lines (125 loc) · 5.59 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
const esprima = require( 'esprima' );
const estraverse = require( 'estraverse' );
const polyfills = require( __dirname + '/polyfills.json' );
module.exports = process;
function process( source, opt_options ){
const options = opt_options || {};
const RESULT_OBJECT = options.resultObject || {};
const minIEVersion = options.minIEVersion || 5.5;
const minOperaVersion = options.minOperaVersion || 8;
const minGeckoVersion = options.minGeckoVersion || 0.9;
// polyfill
const EMBED_ARRAY_PROTOTYPE_INDXOF = minIEVersion < 9 || minOperaVersion < 9.6 || minGeckoVersion < 1.8;
const EMBED_POLYFILLS_FOR_IE_LTE_5 = minIEVersion < 5.5;
if( !EMBED_POLYFILLS_FOR_IE_LTE_5 && !EMBED_ARRAY_PROTOTYPE_INDXOF ){
return source;
};
const BUILTIN_OBJECTS = {};
const SKIP_TO_EMBED_POLYFILLS = options.skipEmbedPolyfills || [];
const FORCE_TO_EMBED_POLYFILLS = options.forceEmbedPolyfills || [];
const REQUIRED_POLYFILLS = [];
const EMBEDDED_POLYFILLS = [];
let polyfillCodesOnlyForIE = '';
let polyfillCodesNotOnlyIE = '';
while( FORCE_TO_EMBED_POLYFILLS.length ){
BUILTIN_OBJECTS[ FORCE_TO_EMBED_POLYFILLS.shift() ] = true;
};
const ast = esprima.parse( source );
estraverse.traverse(
ast,
{
enter : function( astNode, parent ){
if( astNode.type === esprima.Syntax.CallExpression && astNode.callee ){
switch( astNode.callee.name ){
case 'decodeURI' :
case 'decodeURIComponent' :
BUILTIN_OBJECTS[ 'decodeURIComponent' ] = true;
break;
case 'encodeURI' :
case 'encodeURIComponent' :
BUILTIN_OBJECTS[ 'encodeURIComponent' ] = true;
break;
};
};
if( astNode.type === esprima.Syntax.Identifier ){
switch( astNode.name ){
case 'decodeURI' :
case 'decodeURIComponent' :
if( EMBED_POLYFILLS_FOR_IE_LTE_5 ){
BUILTIN_OBJECTS[ 'decodeURIComponent' ] = true;
};
break;
case 'encodeURI' :
case 'encodeURIComponent' :
if( EMBED_POLYFILLS_FOR_IE_LTE_5 ){
BUILTIN_OBJECTS[ 'encodeURIComponent' ] = true;
};
break;
case 'indexOf' :
if( !EMBED_ARRAY_PROTOTYPE_INDXOF ) break;
case 'shift' :
case 'pop' :
case 'push' :
case 'splice' :
case 'unshift' :
if( EMBED_POLYFILLS_FOR_IE_LTE_5 ){
BUILTIN_OBJECTS[ 'Array.prototype.' + astNode.name ] = true;
};
break;
case 'call' :
if( EMBED_POLYFILLS_FOR_IE_LTE_5 ){
BUILTIN_OBJECTS[ 'Function.prototype.apply' ] = true;
};
case 'apply' :
if( EMBED_POLYFILLS_FOR_IE_LTE_5 ){
BUILTIN_OBJECTS[ 'Function.prototype.' + astNode.name ] = true;
};
break;
};
};
}
}
);
for( let builtinName in BUILTIN_OBJECTS ){
REQUIRED_POLYFILLS.push( builtinName );
if( SKIP_TO_EMBED_POLYFILLS !== '*' && SKIP_TO_EMBED_POLYFILLS.indexOf( builtinName ) === -1 ){
if( !polyfills[ builtinName ] ){
throw new Error( builtinName + ' Polyfill Not Found!' );
};
if( builtinName === 'Array.prototype.indexOf' ){
polyfillCodesNotOnlyIE += polyfills[ builtinName ] + '\n';
} else {
if( polyfillCodesOnlyForIE ) polyfillCodesOnlyForIE += '\n';
polyfillCodesOnlyForIE += polyfills[ builtinName ]
};
EMBEDDED_POLYFILLS.push( builtinName );
};
};
RESULT_OBJECT.requiredPolyfills = REQUIRED_POLYFILLS;
RESULT_OBJECT.embeddedPolyfills = EMBEDDED_POLYFILLS;
return ( polyfillCodesOnlyForIE ? '/*@cc_on ' + polyfillCodesOnlyForIE + ' @*/\n' : '' ) + polyfillCodesNotOnlyIE + source;
};
process.gulp = function( _options ){
const PluginError = require( 'plugin-error' ),
through = require( 'through2' ),
pluginName = 'gulp-es2-to-es2';
return through.obj(
function( file, encoding, callback ){
if( file.isNull() ) return callback();
if( file.isStream() ){
this.emit( 'error', new PluginError( pluginName, 'Streaming not supported' ) );
return callback();
};
if( file.extname === '.js' ){
try {
let contents = file.contents.toString( encoding );
file.contents = Buffer.from( process( contents, _options ) );
this.push( file );
} catch(O_o){
this.emit( 'error', new PluginError( pluginName, O_o ) );
};
};
callback();
}
);
};