From 5b7063791ca874db31bdd9cd335a2bcfb2246d82 Mon Sep 17 00:00:00 2001 From: Colin Alworth Date: Sun, 15 Dec 2024 14:40:50 -0600 Subject: [PATCH] Remove GWT's Map polyfill Fixes #10062 --- .../emul/java/util/InternalHashCodeMap.java | 2 +- .../gwt/emul/java/util/InternalJsMap.java | 35 +--- .../emul/java/util/InternalJsMapFactory.java | 168 ------------------ .../gwt/emul/java/util/InternalStringMap.java | 2 +- 4 files changed, 11 insertions(+), 196 deletions(-) delete mode 100644 user/super/com/google/gwt/emul/java/util/InternalJsMapFactory.java diff --git a/user/super/com/google/gwt/emul/java/util/InternalHashCodeMap.java b/user/super/com/google/gwt/emul/java/util/InternalHashCodeMap.java index abefed8acd9..0fc4ac46505 100644 --- a/user/super/com/google/gwt/emul/java/util/InternalHashCodeMap.java +++ b/user/super/com/google/gwt/emul/java/util/InternalHashCodeMap.java @@ -32,7 +32,7 @@ */ class InternalHashCodeMap implements Iterable> { - private final InternalJsMap backingMap = InternalJsMapFactory.newJsMap(); + private final InternalJsMap backingMap = new InternalJsMap<>(); private AbstractHashMap host; private int size; diff --git a/user/super/com/google/gwt/emul/java/util/InternalJsMap.java b/user/super/com/google/gwt/emul/java/util/InternalJsMap.java index 8149274fa11..83cff79334c 100644 --- a/user/super/com/google/gwt/emul/java/util/InternalJsMap.java +++ b/user/super/com/google/gwt/emul/java/util/InternalJsMap.java @@ -22,7 +22,7 @@ import jsinterop.annotations.JsType; @JsType(isNative = true, name = "Map", namespace = JsPackage.GLOBAL) -interface InternalJsMap { +class InternalJsMap { @JsType(isNative = true, name = "IteratorIterable", namespace = JsPackage.GLOBAL) interface Iterator { @@ -47,31 +47,14 @@ interface IteratorEntry { default V getValue() { return JsUtils.uncheckedCast(getValueInternal()[1]); } } - V get(int key); - V get(String key); - void set(int key, V value); - void set(String key, V value); - Iterator entries(); - - @JsOverlay - default void delete(int key) { - // Calls delete without map.delete in order to be compatible with old browsers where delete is a - // keyword. - DeleteFunction fn = JsUtils.getProperty(this, "delete"); - fn.call(this, key); - } - - @JsOverlay - default void delete(String key) { - // Calls delete without map.delete in order to be compatible with old browsers where delete is a - // keyword. - DeleteFunction fn = JsUtils.getProperty(this, "delete"); - fn.call(this, key); + InternalJsMap() { } - @JsType(isNative = true, name = "Function", namespace = JsPackage.GLOBAL) - interface DeleteFunction { - void call(InternalJsMap thisArg, String key); - void call(InternalJsMap thisArg, int key); - } + native V get(int key); + native V get(String key); + native void set(int key, V value); + native void set(String key, V value); + native Iterator entries(); + native void delete(String key); + native void delete(int key); } diff --git a/user/super/com/google/gwt/emul/java/util/InternalJsMapFactory.java b/user/super/com/google/gwt/emul/java/util/InternalJsMapFactory.java deleted file mode 100644 index ba8c6d45e49..00000000000 --- a/user/super/com/google/gwt/emul/java/util/InternalJsMapFactory.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright 2014 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package java.util; - -import com.google.gwt.core.client.JavaScriptObject; - -/** - * A factory to create JavaScript Map instances. - */ -class InternalJsMapFactory { - - private static final JavaScriptObject jsMapCtor = getJsMapConstructor(); - - private static native JavaScriptObject getJsMapConstructor() /*-{ - // Firefox 24 & 25 throws StopIteration to signal the end of iteration. - function isCorrectIterationProtocol() { - try { - return new Map().entries().next().done; - } catch(e) { - return false; - } - } - - if (typeof Map === 'function' && Map.prototype.entries && isCorrectIterationProtocol()) { - return Map; - } else { - return @InternalJsMapFactory::getJsMapPolyFill()(); - } - }-*/; - - public static native InternalJsMap newJsMap() /*-{ - return new @InternalJsMapFactory::jsMapCtor; - }-*/; - - /** - * Returns a partial polyfill for Map that can handle String keys. - *

Implementation notes: - *

String keys are mapped to their values via a JS associative map. String keys could collide - * with intrinsic properties (like watch, constructor). To avoid that; the polyfill uses - * {@code Object.create(null)} so it doesn't inherit any properties. - *

For legacy browsers where {@code Object.create} is not available or handling of - * {@code __proto__} is broken, the polyfill is patched to prepend each key with a ':' while - * storing. - */ - private static native JavaScriptObject getJsMapPolyFill() /*-{ - function Stringmap() { - this.obj = this.createObject(); - }; - - Stringmap.prototype.createObject = function(key) { - return Object.create(null); - } - - Stringmap.prototype.get = function(key) { - return this.obj[key]; - }; - - Stringmap.prototype.set = function(key, value) { - this.obj[key] = value; - }; - - Stringmap.prototype['delete'] = function(key) { - delete this.obj[key]; - }; - - Stringmap.prototype.keys = function() { - return Object.getOwnPropertyNames(this.obj); - }; - - Stringmap.prototype.entries = function() { - var keys = this.keys(); - var map = this; - var nextIndex = 0; - return { - next: function() { - if (nextIndex >= keys.length) return {done: true}; - var key = keys[nextIndex++]; - return {value: [key, map.get(key)], done: false}; - } - }; - }; - - if (!@InternalJsMapFactory::canHandleObjectCreateAndProto()()) { - // Patches the polyfill to drop Object.create(null) and prefix each key with ':" so it will - // not interfere with intrinsic fields. - - Stringmap.prototype.createObject = function() { return {}; }; - - Stringmap.prototype.get = function(key) { - return this.obj[':' + key]; - }; - - Stringmap.prototype.set = function(key, value) { - this.obj[':' + key] = value; - }; - - Stringmap.prototype['delete'] = function(key) { - delete this.obj[':' + key]; - }; - - Stringmap.prototype.keys = function() { - var result = []; - for (var key in this.obj) { - // char code for ':' is 58 - if (key.charCodeAt(0) == 58) { - result.push(key.substring(1)); - } - } - return result; - }; - } - - return Stringmap; - }-*/; - - /** - * Return {@code true} if the browser is modern enough to handle Object.create and also properly - * handles '__proto__' field with Object.create(null). (Safari 5, Android, old Firefox) - */ - private static native boolean canHandleObjectCreateAndProto() /*-{ - if (!Object.create || !Object.getOwnPropertyNames) { - return false; - } - - var protoField = "__proto__"; - - var map = Object.create(null); - if (map[protoField] !== undefined) { - return false; - } - - var keys = Object.getOwnPropertyNames(map); - if (keys.length != 0) { - return false; - } - - map[protoField] = 42; - if (map[protoField] !== 42) { - return false; - } - - // For old Firefox version who doesn't have native Map. See the Firefox bug: - // https://bugzilla.mozilla.org/show_bug.cgi?id=837630 - if (Object.getOwnPropertyNames(map).length == 0) { - return false; - } - - // Looks like the browser has a workable handling of proto field. - return true; - }-*/; - - private InternalJsMapFactory() { - // Hides the constructor. - } -} diff --git a/user/super/com/google/gwt/emul/java/util/InternalStringMap.java b/user/super/com/google/gwt/emul/java/util/InternalStringMap.java index 52fe42d74da..cdc2503ae09 100644 --- a/user/super/com/google/gwt/emul/java/util/InternalStringMap.java +++ b/user/super/com/google/gwt/emul/java/util/InternalStringMap.java @@ -23,7 +23,7 @@ */ class InternalStringMap implements Iterable> { - private final InternalJsMap backingMap = InternalJsMapFactory.newJsMap(); + private final InternalJsMap backingMap = new InternalJsMap<>(); private AbstractHashMap host; private int size;