16
16
17
17
package com .google .javascript .jscomp ;
18
18
19
+ import static com .google .common .base .Preconditions .checkNotNull ;
20
+ import static com .google .common .base .Preconditions .checkState ;
21
+ import static com .google .common .collect .ImmutableList .toImmutableList ;
22
+
19
23
import com .google .common .annotations .VisibleForTesting ;
24
+ import com .google .common .collect .ImmutableList ;
25
+ import com .google .javascript .jscomp .CompilerOptions .LanguageMode ;
20
26
import com .google .javascript .jscomp .PolyfillUsageFinder .Polyfill ;
21
27
import com .google .javascript .jscomp .PolyfillUsageFinder .PolyfillUsage ;
22
28
import com .google .javascript .jscomp .PolyfillUsageFinder .Polyfills ;
23
29
import com .google .javascript .jscomp .parsing .parser .FeatureSet ;
24
- import com .google .javascript .jscomp .parsing .parser .FeatureSet .Feature ;
25
30
import com .google .javascript .jscomp .resources .ResourceLoader ;
26
31
import com .google .javascript .rhino .IR ;
27
32
import com .google .javascript .rhino .Node ;
@@ -53,6 +58,7 @@ public class RewritePolyfills implements CompilerPass {
53
58
private final boolean injectPolyfills ;
54
59
private final boolean isolatePolyfills ;
55
60
private Set <String > libraries ;
61
+ private final LanguageMode injectPolyfillsNewerThan ;
56
62
57
63
/**
58
64
* @param injectPolyfills if true, injects $jscomp.polyfill initializations into the first input.
@@ -61,25 +67,31 @@ public class RewritePolyfills implements CompilerPass {
61
67
* IsolatePolyfills} to prevent their deletion.
62
68
*/
63
69
public RewritePolyfills (
64
- AbstractCompiler compiler , boolean injectPolyfills , boolean isolatePolyfills ) {
70
+ AbstractCompiler compiler ,
71
+ boolean injectPolyfills ,
72
+ boolean isolatePolyfills ,
73
+ LanguageMode injectPolyfillsNewerThan ) {
65
74
this (
66
75
compiler ,
67
76
Polyfills .fromTable (
68
77
ResourceLoader .loadTextResource (RewritePolyfills .class , "js/polyfills.txt" )),
69
78
injectPolyfills ,
70
- isolatePolyfills );
79
+ isolatePolyfills ,
80
+ injectPolyfillsNewerThan );
71
81
}
72
82
73
83
@ VisibleForTesting
74
84
RewritePolyfills (
75
85
AbstractCompiler compiler ,
76
86
Polyfills polyfills ,
77
87
boolean injectPolyfills ,
78
- boolean isolatePolyfills ) {
88
+ boolean isolatePolyfills ,
89
+ LanguageMode injectPolyfillsNewerThan ) {
79
90
this .compiler = compiler ;
80
91
this .polyfills = polyfills ;
81
92
this .injectPolyfills = injectPolyfills ;
82
93
this .isolatePolyfills = isolatePolyfills ;
94
+ this .injectPolyfillsNewerThan = injectPolyfillsNewerThan ;
83
95
}
84
96
85
97
@ Override
@@ -96,22 +108,42 @@ public void process(Node externs, Node root) {
96
108
compiler .reportChangeToEnclosingScope (jscompLookupMethodDecl );
97
109
}
98
110
99
- if (!this .injectPolyfills ) {
111
+ if (!this .injectPolyfills && this . injectPolyfillsNewerThan == null ) {
100
112
// Nothing left to do. Probably this pass only needed to run because --isolate_polyfills is
101
113
// enabled but not --rewrite_polyfills.
102
114
return ;
103
115
}
116
+ if (this .injectPolyfills ) {
117
+ this .libraries = new LinkedHashSet <>();
118
+ new PolyfillUsageFinder (compiler , polyfills ).traverseExcludingGuarded (root , this ::inject );
119
+ }
104
120
105
- this .libraries = new LinkedHashSet <>();
106
- new PolyfillUsageFinder (compiler , polyfills ).traverseExcludingGuarded (root , this ::inject );
107
-
108
- if (libraries .isEmpty ()) {
109
- return ;
121
+ final ImmutableList <String > librariesToInject ;
122
+ if (this .injectPolyfillsNewerThan != null ) {
123
+ ImmutableList <Polyfill > polyfillsToInject =
124
+ polyfills .getPolyfillsNewerThan (this .injectPolyfillsNewerThan );
125
+ librariesToInject =
126
+ polyfillsToInject .stream ()
127
+ // Skip polyfills that have no associated library. This is true for language
128
+ // features like `Proxy` and `String.raw` that have no associated polyfill, hence
129
+ // there's
130
+ // nothing to inject here.
131
+ .filter (p -> !p .library .isEmpty ())
132
+ .map (p -> p .library )
133
+ .collect (toImmutableList ());
134
+ } else {
135
+ librariesToInject = ImmutableList .copyOf (this .libraries );
110
136
}
111
137
138
+ this .injectAll (librariesToInject , /* forceInjection= */ this .injectPolyfillsNewerThan != null );
139
+ }
140
+
141
+ private void injectAll (Iterable <String > librariesToInject , boolean forceInjection ) {
112
142
Node lastNode = null ;
113
- for (String library : libraries ) {
114
- lastNode = compiler .ensureLibraryInjected (library , false );
143
+ for (String library : librariesToInject ) {
144
+ checkNotNull (library );
145
+ checkState (!library .isEmpty (), "unexpected empty library" );
146
+ lastNode = compiler .ensureLibraryInjected (library , forceInjection );
115
147
}
116
148
if (lastNode != null ) {
117
149
Node parent = lastNode .getParent ();
@@ -153,20 +185,8 @@ private void removeUnneededPolyfills(Node parent, Node runtimeEnd) {
153
185
if (JSCOMP_POLYFILL .matches (name )) {
154
186
final String nativeVersionStr = name .getNext ().getNext ().getNext ().getString ();
155
187
polyfillSupportFeatureSet = FeatureSet .valueOf (nativeVersionStr );
156
- // Safari has been really slow to implement these regex features, even though it has
157
- // kept on top of the features we polyfill, so we want to ignore the regex features
158
- // when deciding whether the polyfill should be considered "already supported" in the
159
- // target environment.
160
- // NOTE: This special case seems reasonable for now, but if further divergence occurs
161
- // we should consider doing a more direct solution by having the polyfill definitions
162
- // report names of `FeatureSet` values representing browser `FeatureSet` year instead of
163
- // spec release year.
164
188
polyfillSupportFeatureSet =
165
- polyfillSupportFeatureSet .without (
166
- Feature .REGEXP_FLAG_S ,
167
- Feature .REGEXP_LOOKBEHIND ,
168
- Feature .REGEXP_NAMED_GROUPS ,
169
- Feature .REGEXP_UNICODE_PROPERTY_ESCAPE );
189
+ PolyfillUsageFinder .getPolyfillSupportedFeatureSet (nativeVersionStr );
170
190
}
171
191
}
172
192
return polyfillSupportFeatureSet ;
0 commit comments