Rework Map object (#2760)
This patch reworks the core of the builtin Map object. Advantages: - Provide sublinear access time for the elements via Lcache and property hashmap - This implementation is suitable for the builtin Set object as well Also add the missing 'forEach' routine for the builtin object as well. JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik frobert@inf.u-szeged.hu
This commit is contained in:
committed by
László Langó
parent
bc9efb07a5
commit
d2931c6e40
@@ -0,0 +1,108 @@
|
||||
/* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
var map = new Map();
|
||||
|
||||
/* Test when the map object keys are strings */
|
||||
for (var i = 0; i < 15; i++) {
|
||||
map.set ("foo" + i, i);
|
||||
assert (map.size === i + 1);
|
||||
}
|
||||
|
||||
var counter = 0;
|
||||
|
||||
map.forEach (function (value, key) {
|
||||
assert (typeof key === "string");
|
||||
assert (key === "foo" + counter);
|
||||
assert (typeof value === "number");
|
||||
assert (value === counter);
|
||||
counter++;
|
||||
});
|
||||
|
||||
map.clear ();
|
||||
assert (map.size === 0);
|
||||
counter = 0;
|
||||
|
||||
/* Test when the map object keys are numbers */
|
||||
for (var i = 0; i < 15; i++) {
|
||||
map.set (i + 0.5, "foo" + i);
|
||||
assert (map.size === i + 1);
|
||||
}
|
||||
|
||||
map.forEach (function (value, key) {
|
||||
assert (typeof key === "number");
|
||||
assert (key === counter + 0.5);
|
||||
assert (typeof value === "string");
|
||||
assert (value === "foo" + counter);
|
||||
counter++;
|
||||
});
|
||||
|
||||
map.clear ();
|
||||
assert (map.size === 0);
|
||||
counter = 0;
|
||||
|
||||
var objectList = [];
|
||||
|
||||
/* Test when the map object keys are objects */
|
||||
for (var i = 0; i < 15; i++) {
|
||||
objectList[i] = { index : i };
|
||||
map.set (objectList[i], "foo" + i);
|
||||
assert (map.size === i + 1);
|
||||
}
|
||||
|
||||
map.forEach (function (value, key) {
|
||||
assert (typeof key === "object");
|
||||
assert (key === objectList[counter]);
|
||||
assert (key.index === objectList[counter].index);
|
||||
assert (typeof value === "string");
|
||||
assert (value === "foo" + counter);
|
||||
counter++;
|
||||
});
|
||||
|
||||
/* Test when the this argument is not a map object */
|
||||
try {
|
||||
Map.prototype.forEach.call ({});
|
||||
assert (false);
|
||||
} catch (e) {
|
||||
assert (e instanceof TypeError);
|
||||
}
|
||||
|
||||
/* Test when the 1st argument is not callable */
|
||||
try {
|
||||
map.forEach (5);
|
||||
assert (false);
|
||||
} catch (e) {
|
||||
assert (e instanceof TypeError);
|
||||
}
|
||||
|
||||
/* Test when the the callback function throws error */
|
||||
try {
|
||||
map.forEach (function (value, key) {
|
||||
throw new ReferenceError ("foo");
|
||||
});
|
||||
assert (false);
|
||||
} catch (e) {
|
||||
assert (e instanceof ReferenceError);
|
||||
assert (e.message === "foo");
|
||||
}
|
||||
|
||||
/* Test when the 2nd optional argument is present */
|
||||
var object = {
|
||||
_secret : 42
|
||||
}
|
||||
|
||||
map.forEach (function (value, key) {
|
||||
assert (this._secret === 42);
|
||||
}, object);
|
||||
@@ -73,6 +73,43 @@ assert(m.get(1) === 8);
|
||||
assert(m.get(2) === 8);
|
||||
assert(m.get(3) === 8);
|
||||
|
||||
m.set(NaN, "not a number");
|
||||
assert(m.size === 4);
|
||||
assert(m.get(NaN) === "not a number");
|
||||
assert(m.get(Number("foo")) === "not a number")
|
||||
|
||||
m.set(0, "PosZero");
|
||||
assert(m.size === 5);
|
||||
m.set(-0, "NegZero");
|
||||
assert(m.size === 5);
|
||||
assert(m.get (0) === "NegZero");
|
||||
assert(m.get (-0) === "NegZero");
|
||||
|
||||
var symbolFoo = Symbol ("foo");
|
||||
m.set (symbolFoo, "SymbolFoo");
|
||||
assert(m.size === 6);
|
||||
assert(m.get(symbolFoo) === "SymbolFoo");
|
||||
|
||||
var object = {};
|
||||
m.set (object, "object");
|
||||
assert(m.size === 7);
|
||||
assert(m.get(object) === "object");
|
||||
assert(m.get({}) === undefined);
|
||||
|
||||
var myObj = { o : 4 };
|
||||
m.set("foo", myObj);
|
||||
assert(m.size === 8);
|
||||
assert(m.get ("foo") === myObj);
|
||||
assert(m.get ("foo").o === 4);
|
||||
|
||||
m.clear();
|
||||
assert(m.size === 0);
|
||||
|
||||
m.set("foo", myObj);
|
||||
assert(m.size === 1);
|
||||
assert(m.get ("foo") === myObj);
|
||||
assert(m.get ("foo").o === 4);
|
||||
|
||||
var mapNameDesc = Object.getOwnPropertyDescriptor (Map, 'name');
|
||||
assert(mapNameDesc.value === "Map");
|
||||
assert(mapNameDesc.writable === false);
|
||||
|
||||
Reference in New Issue
Block a user