View Javadoc
1   /*
2    * Copyright (c) 2002-2026 Gargoyle Software Inc.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * https://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software
10   * distributed under the License is distributed on an "AS IS" BASIS,
11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   * See the License for the specific language governing permissions and
13   * limitations under the License.
14   */
15  package org.htmlunit.javascript.polyfill;
16  
17  import java.io.IOException;
18  import java.nio.charset.StandardCharsets;
19  import java.util.HashMap;
20  import java.util.Map;
21  
22  import org.apache.commons.io.IOUtils;
23  import org.htmlunit.corejs.javascript.Context;
24  import org.htmlunit.corejs.javascript.Script;
25  import org.htmlunit.corejs.javascript.Scriptable;
26  import org.htmlunit.corejs.javascript.VarScope;
27  
28  /**
29   * Support to use polyfills for js features not implemented so far
30   * (idea from Colin Alworth).
31   *
32   * @author Ronald Brill
33   */
34  public class Polyfill {
35  
36      private static final Map<String, Polyfill> CACHE = new HashMap<>();
37  
38      private String url_;
39      private String source_;
40      private Script script_;
41  
42      /**
43       * @return the build in fetch polyfill
44       * @throws IOException in case of error
45       */
46      public static Polyfill getFetchPolyfill() throws IOException {
47          return getPolyfill("fetch/fetch.umd.js");
48      }
49  
50      private static Polyfill getPolyfill(final String resouceName) throws IOException {
51          Polyfill poly = CACHE.get(resouceName);
52          if (poly != null) {
53              return poly;
54          }
55  
56          poly = new Polyfill();
57          poly.source_ = IOUtils.toString(poly.getClass().getResourceAsStream(resouceName), StandardCharsets.UTF_8);
58          poly.url_ = poly.getClass().getResource(resouceName).toExternalForm();
59  
60          CACHE.put(resouceName, poly);
61          return poly;
62      }
63  
64      /**
65       * Compile the script if needed and exec to setup the context.
66       *
67       * @param context the context
68       * @param scope the scope to execute relative to
69       * @param thisObject the value "this" should be set to
70       */
71      public void apply(final Context context, final VarScope scope, final Scriptable thisObject) {
72          if (script_ == null) {
73              script_ = context.compileString(source_, url_, 0, null);
74          }
75  
76          if (script_ != null) {
77              script_.exec(context, scope, thisObject);
78          }
79      }
80  }