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       * Returns the build in fetch polyfill.
44       *
45       * @return the build in fetch polyfill
46       * @throws IOException in case of error
47       */
48      public static Polyfill getFetchPolyfill() throws IOException {
49          return getPolyfill("fetch/fetch.umd.js");
50      }
51  
52      private static Polyfill getPolyfill(final String resouceName) throws IOException {
53          Polyfill poly = CACHE.get(resouceName);
54          if (poly != null) {
55              return poly;
56          }
57  
58          poly = new Polyfill();
59          poly.source_ = IOUtils.toString(poly.getClass().getResourceAsStream(resouceName), StandardCharsets.UTF_8);
60          poly.url_ = poly.getClass().getResource(resouceName).toExternalForm();
61  
62          CACHE.put(resouceName, poly);
63          return poly;
64      }
65  
66      /**
67       * Compile the script if needed and exec to setup the context.
68       *
69       * @param context the context
70       * @param scope the scope to execute relative to
71       * @param thisObject the value "this" should be set to
72       */
73      public void apply(final Context context, final VarScope scope, final Scriptable thisObject) {
74          if (script_ == null) {
75              script_ = context.compileString(source_, url_, 0, null);
76          }
77  
78          if (script_ != null) {
79              script_.exec(context, scope, thisObject);
80          }
81      }
82  }