From abdb061a1818e4f03226597a20d020acd649dfea Mon Sep 17 00:00:00 2001 From: ALANVF Date: Tue, 18 Jun 2024 22:12:32 +0200 Subject: [PATCH 1/5] [js] Use native maps when ES6 is enabled. --- std/js/_std/haxe/ds/IntMap.hx | 61 ++++++++++++++++++++++++++++++++ std/js/_std/haxe/ds/ObjectMap.hx | 61 ++++++++++++++++++++++++++++++++ std/js/_std/haxe/ds/StringMap.hx | 61 +++++++++++++++++++++++++++++++- 3 files changed, 182 insertions(+), 1 deletion(-) diff --git a/std/js/_std/haxe/ds/IntMap.hx b/std/js/_std/haxe/ds/IntMap.hx index 64dddedfdc9..225c9b5a8aa 100644 --- a/std/js/_std/haxe/ds/IntMap.hx +++ b/std/js/_std/haxe/ds/IntMap.hx @@ -22,6 +22,66 @@ package haxe.ds; +#if (js_es >= 6) +@:coreApi class IntMap implements haxe.Constraints.IMap { + private var m:js.lib.Map; + + public inline function new(map = new js.lib.Map()):Void { + m = map; + } + + public inline function set(key:Int, value:T):Void { + m.set(key, value); + } + + public inline function get(key:Int):Null { + return m.get(key); + } + + public inline function exists(key:Int):Bool { + return m.has(key); + } + + public inline function remove(key:Int):Bool { + return m.delete(key); + } + + public inline function keys():Iterator { + return new js.lib.HaxeIterator(m.keys()); + } + + public inline function iterator():Iterator { + return m.iterator(); + } + + public inline function keyValueIterator():KeyValueIterator { + return m.keyValueIterator(); + } + + public inline function copy():IntMap { + return new IntMap(new js.lib.Map(m)); + } + + public function toString():String { + var s = new StringBuf(); + s.add("{"); + var it = keyValueIterator(); + for (i in it) { + s.add(i.key); + s.add(" => "); + s.add(Std.string(i.value)); + if (it.hasNext()) + s.add(", "); + } + s.add("}"); + return s.toString(); + } + + public inline function clear():Void { + m.clear(); + } +} +#else @:coreApi class IntMap implements haxe.Constraints.IMap { private var h:Dynamic; @@ -98,3 +158,4 @@ package haxe.ds; h = {}; } } +#end diff --git a/std/js/_std/haxe/ds/ObjectMap.hx b/std/js/_std/haxe/ds/ObjectMap.hx index c46b2cee5dd..b7be2e8bcb6 100644 --- a/std/js/_std/haxe/ds/ObjectMap.hx +++ b/std/js/_std/haxe/ds/ObjectMap.hx @@ -25,9 +25,69 @@ package haxe.ds; import js.Syntax; import js.Lib; +#if (js_es >= 6) @:coreApi class ObjectMap implements haxe.Constraints.IMap { + private var m:js.lib.Map; + public inline function new(map = new js.lib.Map()):Void { + m = map; + } + + public inline function set(key:K, value:V):Void { + m.set(key, value); + } + + public inline function get(key:K):Null { + return m.get(key); + } + + public inline function exists(key:K):Bool { + return m.has(key); + } + + public inline function remove(key:K):Bool { + return m.delete(key); + } + + public inline function keys():Iterator { + return new js.lib.HaxeIterator(m.keys()); + } + + public inline function iterator():Iterator { + return m.iterator(); + } + + public inline function keyValueIterator():KeyValueIterator { + return m.keyValueIterator(); + } + + public inline function copy():ObjectMap { + return new ObjectMap(new js.lib.Map(m)); + } + + public function toString():String { + var s = new StringBuf(); + s.add("{"); + var it = keyValueIterator(); + for (i in it) { + s.add(Std.string(i.key)); + s.add(" => "); + s.add(Std.string(i.value)); + if (it.hasNext()) + s.add(", "); + } + s.add("}"); + return s.toString(); + } + + public inline function clear():Void { + m.clear(); + } +} +#else +@:coreApi +class ObjectMap implements haxe.Constraints.IMap { static inline function assignId(obj:{}):Int { return Syntax.code('({0}.__id__ = {1})', obj, Lib.getNextHaxeUID()); } @@ -123,3 +183,4 @@ class ObjectMap implements haxe.Constraints.IMap { h = {__keys__: {}}; } } +#end diff --git a/std/js/_std/haxe/ds/StringMap.hx b/std/js/_std/haxe/ds/StringMap.hx index 3bb72dfb3e2..86bf3006477 100644 --- a/std/js/_std/haxe/ds/StringMap.hx +++ b/std/js/_std/haxe/ds/StringMap.hx @@ -26,7 +26,66 @@ import js.lib.Object; import haxe.Constraints.IMap; import haxe.DynamicAccess; -#if (js_es >= 5) +#if (js_es >= 6) +@:coreApi class StringMap implements IMap { + private var m:js.lib.Map; + + public inline function new(map = new js.lib.Map()):Void { + m = map; + } + + public inline function set(key:String, value:T):Void { + m.set(key, value); + } + + public inline function get(key:String):Null { + return m.get(key); + } + + public inline function exists(key:String):Bool { + return m.has(key); + } + + public inline function remove(key:String):Bool { + return m.delete(key); + } + + public inline function keys():Iterator { + return new js.lib.HaxeIterator(m.keys()); + } + + public inline function iterator():Iterator { + return m.iterator(); + } + + public inline function keyValueIterator():KeyValueIterator { + return m.keyValueIterator(); + } + + public inline function copy():StringMap { + return new StringMap(new js.lib.Map(m)); + } + + public function toString():String { + var s = new StringBuf(); + s.add("{"); + var it = keyValueIterator(); + for (i in it) { + s.add(i.key); + s.add(" => "); + s.add(Std.string(i.value)); + if (it.hasNext()) + s.add(", "); + } + s.add("}"); + return s.toString(); + } + + public inline function clear():Void { + m.clear(); + } +} +#elseif (js_es == 5) @:coreApi class StringMap implements IMap { var h:Dynamic; From f60d3b142c10411d29e20d81331050b0d38bd883 Mon Sep 17 00:00:00 2001 From: Apprentice-Alchemist <53486764+Apprentice-Alchemist@users.noreply.github.com> Date: Wed, 19 Jun 2024 11:16:05 +0200 Subject: [PATCH 2/5] [js] Use square brackets in ES6 map toString. --- std/js/_std/haxe/ds/IntMap.hx | 4 ++-- std/js/_std/haxe/ds/ObjectMap.hx | 4 ++-- std/js/_std/haxe/ds/StringMap.hx | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/std/js/_std/haxe/ds/IntMap.hx b/std/js/_std/haxe/ds/IntMap.hx index 225c9b5a8aa..8ee7377fb0e 100644 --- a/std/js/_std/haxe/ds/IntMap.hx +++ b/std/js/_std/haxe/ds/IntMap.hx @@ -64,7 +64,7 @@ package haxe.ds; public function toString():String { var s = new StringBuf(); - s.add("{"); + s.add("["); var it = keyValueIterator(); for (i in it) { s.add(i.key); @@ -73,7 +73,7 @@ package haxe.ds; if (it.hasNext()) s.add(", "); } - s.add("}"); + s.add("]"); return s.toString(); } diff --git a/std/js/_std/haxe/ds/ObjectMap.hx b/std/js/_std/haxe/ds/ObjectMap.hx index b7be2e8bcb6..65c14f76725 100644 --- a/std/js/_std/haxe/ds/ObjectMap.hx +++ b/std/js/_std/haxe/ds/ObjectMap.hx @@ -68,7 +68,7 @@ class ObjectMap implements haxe.Constraints.IMap { public function toString():String { var s = new StringBuf(); - s.add("{"); + s.add("["); var it = keyValueIterator(); for (i in it) { s.add(Std.string(i.key)); @@ -77,7 +77,7 @@ class ObjectMap implements haxe.Constraints.IMap { if (it.hasNext()) s.add(", "); } - s.add("}"); + s.add("]"); return s.toString(); } diff --git a/std/js/_std/haxe/ds/StringMap.hx b/std/js/_std/haxe/ds/StringMap.hx index 86bf3006477..e4ffd6b2f3c 100644 --- a/std/js/_std/haxe/ds/StringMap.hx +++ b/std/js/_std/haxe/ds/StringMap.hx @@ -68,7 +68,7 @@ import haxe.DynamicAccess; public function toString():String { var s = new StringBuf(); - s.add("{"); + s.add("["); var it = keyValueIterator(); for (i in it) { s.add(i.key); @@ -77,7 +77,7 @@ import haxe.DynamicAccess; if (it.hasNext()) s.add(", "); } - s.add("}"); + s.add("]"); return s.toString(); } From f3b1b5391501b5cefdf907819e44266673e01954 Mon Sep 17 00:00:00 2001 From: Apprentice-Alchemist <53486764+Apprentice-Alchemist@users.noreply.github.com> Date: Wed, 19 Jun 2024 11:16:40 +0200 Subject: [PATCH 3/5] [js] make the ES6 map conform to the public API. --- std/js/_std/haxe/ds/IntMap.hx | 17 +++++++++++++---- std/js/_std/haxe/ds/ObjectMap.hx | 17 +++++++++++++---- std/js/_std/haxe/ds/StringMap.hx | 17 +++++++++++++---- 3 files changed, 39 insertions(+), 12 deletions(-) diff --git a/std/js/_std/haxe/ds/IntMap.hx b/std/js/_std/haxe/ds/IntMap.hx index 8ee7377fb0e..ab6ea2f7286 100644 --- a/std/js/_std/haxe/ds/IntMap.hx +++ b/std/js/_std/haxe/ds/IntMap.hx @@ -26,8 +26,8 @@ package haxe.ds; @:coreApi class IntMap implements haxe.Constraints.IMap { private var m:js.lib.Map; - public inline function new(map = new js.lib.Map()):Void { - m = map; + public inline function new():Void { + m = new js.lib.Map(); } public inline function set(key:Int, value:T):Void { @@ -55,11 +55,20 @@ package haxe.ds; } public inline function keyValueIterator():KeyValueIterator { - return m.keyValueIterator(); + final iter = m.keyValueIterator(); + return { + hasNext: iter.hasNext, + next: () -> { + var val = iter.next(); + return {key: val.key, value: val.value} + } + } } public inline function copy():IntMap { - return new IntMap(new js.lib.Map(m)); + var copied = new IntMap(); + copied.m = new js.lib.Map(m); + return copied; } public function toString():String { diff --git a/std/js/_std/haxe/ds/ObjectMap.hx b/std/js/_std/haxe/ds/ObjectMap.hx index 65c14f76725..0bb376fef6a 100644 --- a/std/js/_std/haxe/ds/ObjectMap.hx +++ b/std/js/_std/haxe/ds/ObjectMap.hx @@ -30,8 +30,8 @@ import js.Lib; class ObjectMap implements haxe.Constraints.IMap { private var m:js.lib.Map; - public inline function new(map = new js.lib.Map()):Void { - m = map; + public inline function new():Void { + m = new js.lib.Map(); } public inline function set(key:K, value:V):Void { @@ -59,11 +59,20 @@ class ObjectMap implements haxe.Constraints.IMap { } public inline function keyValueIterator():KeyValueIterator { - return m.keyValueIterator(); + final iter = m.keyValueIterator(); + return { + hasNext: iter.hasNext, + next: () -> { + var val = iter.next(); + return {key: val.key, value: val.value} + } + } } public inline function copy():ObjectMap { - return new ObjectMap(new js.lib.Map(m)); + var copied = new ObjectMap(); + copied.m = new js.lib.Map(m); + return copied; } public function toString():String { diff --git a/std/js/_std/haxe/ds/StringMap.hx b/std/js/_std/haxe/ds/StringMap.hx index e4ffd6b2f3c..877de48804c 100644 --- a/std/js/_std/haxe/ds/StringMap.hx +++ b/std/js/_std/haxe/ds/StringMap.hx @@ -30,8 +30,8 @@ import haxe.DynamicAccess; @:coreApi class StringMap implements IMap { private var m:js.lib.Map; - public inline function new(map = new js.lib.Map()):Void { - m = map; + public inline function new():Void { + m = new js.lib.Map(); } public inline function set(key:String, value:T):Void { @@ -59,11 +59,20 @@ import haxe.DynamicAccess; } public inline function keyValueIterator():KeyValueIterator { - return m.keyValueIterator(); + final iter = m.keyValueIterator(); + return { + hasNext: iter.hasNext, + next: () -> { + var val = iter.next(); + return {key: val.key, value: val.value} + } + } } public inline function copy():StringMap { - return new StringMap(new js.lib.Map(m)); + var copied = new StringMap(); + copied.m = new js.lib.Map(m); + return copied; } public function toString():String { From 3b016b36c29d3416388aebf24bc114b2d25e7eba Mon Sep 17 00:00:00 2001 From: Apprentice-Alchemist <53486764+Apprentice-Alchemist@users.noreply.github.com> Date: Wed, 19 Jun 2024 15:38:12 +0200 Subject: [PATCH 4/5] [js] better key value iterator for ES6 maps --- std/js/_std/haxe/ds/IntMap.hx | 9 +----- std/js/_std/haxe/ds/ObjectMap.hx | 9 +----- std/js/_std/haxe/ds/StringMap.hx | 9 +----- std/js/lib/HaxeKeyValueIterator.hx | 51 ++++++++++++++++++++++++++++++ std/js/lib/Map.hx | 4 +-- 5 files changed, 56 insertions(+), 26 deletions(-) create mode 100644 std/js/lib/HaxeKeyValueIterator.hx diff --git a/std/js/_std/haxe/ds/IntMap.hx b/std/js/_std/haxe/ds/IntMap.hx index ab6ea2f7286..4804006cc53 100644 --- a/std/js/_std/haxe/ds/IntMap.hx +++ b/std/js/_std/haxe/ds/IntMap.hx @@ -55,14 +55,7 @@ package haxe.ds; } public inline function keyValueIterator():KeyValueIterator { - final iter = m.keyValueIterator(); - return { - hasNext: iter.hasNext, - next: () -> { - var val = iter.next(); - return {key: val.key, value: val.value} - } - } + return m.keyValueIterator(); } public inline function copy():IntMap { diff --git a/std/js/_std/haxe/ds/ObjectMap.hx b/std/js/_std/haxe/ds/ObjectMap.hx index 0bb376fef6a..2c25bc7ad8c 100644 --- a/std/js/_std/haxe/ds/ObjectMap.hx +++ b/std/js/_std/haxe/ds/ObjectMap.hx @@ -59,14 +59,7 @@ class ObjectMap implements haxe.Constraints.IMap { } public inline function keyValueIterator():KeyValueIterator { - final iter = m.keyValueIterator(); - return { - hasNext: iter.hasNext, - next: () -> { - var val = iter.next(); - return {key: val.key, value: val.value} - } - } + return m.keyValueIterator(); } public inline function copy():ObjectMap { diff --git a/std/js/_std/haxe/ds/StringMap.hx b/std/js/_std/haxe/ds/StringMap.hx index 877de48804c..9e906491ad9 100644 --- a/std/js/_std/haxe/ds/StringMap.hx +++ b/std/js/_std/haxe/ds/StringMap.hx @@ -59,14 +59,7 @@ import haxe.DynamicAccess; } public inline function keyValueIterator():KeyValueIterator { - final iter = m.keyValueIterator(); - return { - hasNext: iter.hasNext, - next: () -> { - var val = iter.next(); - return {key: val.key, value: val.value} - } - } + return m.keyValueIterator(); } public inline function copy():StringMap { diff --git a/std/js/lib/HaxeKeyValueIterator.hx b/std/js/lib/HaxeKeyValueIterator.hx new file mode 100644 index 00000000000..b393ffa0fc7 --- /dev/null +++ b/std/js/lib/HaxeKeyValueIterator.hx @@ -0,0 +1,51 @@ +/* + * Copyright (C)2005-2024 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package js.lib; + +class HaxeKeyValueIterator { + final jsIterator:js.lib.Iterator>; + var lastStep:js.lib.Iterator.IteratorStep>; + + public inline function new(jsIterator:js.lib.Iterator>) { + this.jsIterator = jsIterator; + lastStep = jsIterator.next(); + } + + public inline function hasNext():Bool { + return !lastStep.done; + } + + public inline function next():{key:K, value:V} { + var v = lastStep.value; + lastStep = jsIterator.next(); + if (v == null) { + return null; + } else { + return {key: v.key, value: v.value}; + } + } + + public static inline function keyValueIterator(jsIterator:js.lib.Iterator>) { + return new HaxeKeyValueIterator(jsIterator); + } +} diff --git a/std/js/lib/Map.hx b/std/js/lib/Map.hx index f7b1f4d42d9..17d498db500 100644 --- a/std/js/lib/Map.hx +++ b/std/js/lib/Map.hx @@ -104,8 +104,8 @@ extern class Map { return new HaxeIterator(this.values()); } - inline function keyValueIterator():HaxeIterator> { - return new HaxeIterator(this.entries()); + inline function keyValueIterator():HaxeKeyValueIterator { + return new HaxeKeyValueIterator(this.entries()); } } From 619ab5d2caad74d9e35d5f997dc86e9129de6a1a Mon Sep 17 00:00:00 2001 From: Apprentice-Alchemist <53486764+Apprentice-Alchemist@users.noreply.github.com> Date: Wed, 19 Jun 2024 15:42:46 +0200 Subject: [PATCH 5/5] [js] remove technically unrequired null check in HaxeKeyValueIterator for better inlining --- std/js/lib/HaxeKeyValueIterator.hx | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/std/js/lib/HaxeKeyValueIterator.hx b/std/js/lib/HaxeKeyValueIterator.hx index b393ffa0fc7..a04e636aef5 100644 --- a/std/js/lib/HaxeKeyValueIterator.hx +++ b/std/js/lib/HaxeKeyValueIterator.hx @@ -38,11 +38,7 @@ class HaxeKeyValueIterator { public inline function next():{key:K, value:V} { var v = lastStep.value; lastStep = jsIterator.next(); - if (v == null) { - return null; - } else { - return {key: v.key, value: v.value}; - } + return {key: v.key, value: v.value}; } public static inline function keyValueIterator(jsIterator:js.lib.Iterator>) {