From bfb0235fc6cc1b121edbae3e6b243b5c01fa05c7 Mon Sep 17 00:00:00 2001 From: Giovanni Campagna Date: Tue, 14 Jan 2014 23:49:47 +0100 Subject: [PATCH] Remove our custom hashmap implementation gjs uses Spidermonkey 24, which implements Map from the ES6 specification, so we can use that instead. https://bugzilla.gnome.org/show_bug.cgi?id=722210 --- js/js-resources.gresource.xml | 1 - js/misc/hash.js | 144 ---------------------------------- js/ui/messageTray.js | 10 +-- js/ui/screenShield.js | 8 +- js/ui/screencast.js | 8 +- js/ui/shellDBus.js | 10 +-- js/ui/status/network.js | 20 +++-- 7 files changed, 24 insertions(+), 177 deletions(-) delete mode 100644 js/misc/hash.js diff --git a/js/js-resources.gresource.xml b/js/js-resources.gresource.xml index 339fc0aae..036970885 100644 --- a/js/js-resources.gresource.xml +++ b/js/js-resources.gresource.xml @@ -15,7 +15,6 @@ misc/extensionUtils.js misc/fileUtils.js misc/gnomeSession.js - misc/hash.js misc/history.js misc/jsParse.js misc/loginManager.js diff --git a/js/misc/hash.js b/js/misc/hash.js deleted file mode 100644 index db70d6542..000000000 --- a/js/misc/hash.js +++ /dev/null @@ -1,144 +0,0 @@ -// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- - -const Lang = imports.lang; -const System = imports.system; - -const Params = imports.misc.params; - -// This is an implementation of EcmaScript SameValue algorithm, -// which returns true if two values are not observably distinguishable. -// It was taken from http://wiki.ecmascript.org/doku.php?id=harmony:egal -// -// In the future, we may want to use the 'is' operator instead. -function _sameValue(x, y) { - if (x === y) { - // 0 === -0, but they are not identical - return x !== 0 || 1 / x === 1 / y; - } - - // NaN !== NaN, but they are identical. - // NaNs are the only non-reflexive value, i.e., if x !== x, - // then x is a NaN. - // isNaN is broken: it converts its argument to number, so - // isNaN("foo") => true - return x !== x && y !== y; -} - -const _hashers = { - object: function(o) { return o ? System.addressOf(o) : 'null'; }, - function: function(f) { return System.addressOf(f); }, - string: function(s) { return s; }, - number: function(n) { return String(n); }, - undefined: function() { return 'undefined'; }, -}; - -/* Map is meant to be similar in usage to ES6 Map, which is - described at http://wiki.ecmascript.org/doku.php?id=harmony:simple_maps_and_sets, - without requiring more than ES5 + Gjs extensions. - - Known differences from other implementations: - Polyfills around the web usually implement HashMaps for - primitive values and reversed WeakMaps for object keys, - but we want real maps with real O(1) semantics in all cases, - and the easiest way is to have different hashers for different - types. - - Known differences from the ES6 specification: - - Map is a Lang.Class, not a ES6 class, so inheritance, - prototype, sealing, etc. work differently. - - items(), keys() and values() don't return iterators, - they return actual arrays, so they incur a full copy everytime - they're called, and they don't see changes if you mutate - the table while iterating - (admittedly, the ES6 spec is a bit unclear on this, and - the reference code would just blow up) -*/ -const Map = new Lang.Class({ - Name: 'Map', - - _init: function(iterable) { - this._pool = { }; - this._size = 0; - - if (iterable) { - for (let i = 0; i < iterable.length; i++) { - let [key, value] = iterable[i]; - this.set(key, value); - } - } - }, - - _hashKey: function(key) { - let type = typeof(key); - return type + ':' + _hashers[type](key); - }, - - _internalGet: function(key) { - let hash = this._hashKey(key); - let node = this._pool[hash]; - - if (node && _sameValue(node.key, key)) - return [true, node.value]; - else - return [false, null]; - }, - - get: function(key) { - return this._internalGet(key)[1]; - }, - - has: function(key) { - return this._internalGet(key)[0]; - }, - - set: function(key, value) { - let hash = this._hashKey(key); - let node = this._pool[hash]; - - if (node) { - node.key = key; - node.value = value; - } else { - this._pool[hash] = { key: key, value: value }; - this._size++; - } - }, - - delete: function(key) { - let hash = this._hashKey(key); - let node = this._pool[hash]; - - if (node && _sameValue(node.key, key)) { - delete this._pool[hash]; - this._size--; - return [node.key, node.value]; - } else { - return [null, null]; - } - }, - - keys: function() { - let pool = this._pool; - return Object.getOwnPropertyNames(pool).map(function(hash) { - return pool[hash].key; - }); - }, - - values: function() { - let pool = this._pool; - return Object.getOwnPropertyNames(pool).map(function(hash) { - return pool[hash].value; - }); - }, - - items: function() { - let pool = this._pool; - return Object.getOwnPropertyNames(pool).map(function(hash) { - return [pool[hash].key, pool[hash].value]; - }); - }, - - size: function() { - return this._size; - }, -}); diff --git a/js/ui/messageTray.js b/js/ui/messageTray.js index 06609c580..650361115 100644 --- a/js/ui/messageTray.js +++ b/js/ui/messageTray.js @@ -19,7 +19,6 @@ const BoxPointer = imports.ui.boxpointer; const CtrlAltTab = imports.ui.ctrlAltTab; const GnomeSession = imports.misc.gnomeSession; const GrabHelper = imports.ui.grabHelper; -const Hash = imports.misc.hash; const Lightbox = imports.ui.lightbox; const Main = imports.ui.main; const PointerWatcher = imports.ui.pointerWatcher; @@ -1899,7 +1898,7 @@ const MessageTray = new Lang.Class({ Shell.KeyBindingMode.OVERVIEW, Lang.bind(this, this._expandActiveNotification)); - this._sources = new Hash.Map(); + this._sources = new Map(); this._chatSummaryItemsCount = 0; this._trayDwellTimeoutId = 0; @@ -1936,7 +1935,7 @@ const MessageTray = new Lang.Class({ }, _updateNoMessagesLabel: function() { - this._noMessages.visible = this._sources.size() == 0; + this._noMessages.visible = this._sources.size == 0; }, _sessionUpdated: function() { @@ -2099,7 +2098,8 @@ const MessageTray = new Lang.Class({ }, _removeSource: function(source) { - let [, obj] = this._sources.delete(source); + let obj = this._sources.get(source); + this._sources.delete(source); let summaryItem = obj.summaryItem; if (source.isChat) @@ -2120,7 +2120,7 @@ const MessageTray = new Lang.Class({ }, getSources: function() { - return this._sources.keys(); + return [k for (k of this._sources.keys())]; }, _onSourceEnableChanged: function(policy, source) { diff --git a/js/ui/screenShield.js b/js/ui/screenShield.js index 0ce15285e..93dc81269 100644 --- a/js/ui/screenShield.js +++ b/js/ui/screenShield.js @@ -17,7 +17,6 @@ const TweenerEquations = imports.tweener.equations; const Background = imports.ui.background; const GnomeSession = imports.misc.gnomeSession; -const Hash = imports.misc.hash; const Layout = imports.ui.layout; const OVirt = imports.gdm.oVirt; const LoginManager = imports.misc.loginManager; @@ -115,7 +114,7 @@ const NotificationsBox = new Lang.Class({ this.actor.add(this._musicBin); this.actor.add(this._scrollView, { x_fill: true, x_align: St.Align.START }); - this._sources = new Hash.Map(); + this._sources = new Map(); Main.messageTray.getSources().forEach(Lang.bind(this, function(source) { this._sourceAdded(Main.messageTray, source, true); })); @@ -130,9 +129,8 @@ const NotificationsBox = new Lang.Class({ this._sourceAddedId = 0; } - let items = this._sources.items(); - for (let i = 0; i < items.length; i++) { - let [source, obj] = items[i]; + let items = this._sources.entries(); + for (let [source, obj] of items) { this._removeSource(source, obj); } diff --git a/js/ui/screencast.js b/js/ui/screencast.js index 7908ff166..e2fb8c8de 100644 --- a/js/ui/screencast.js +++ b/js/ui/screencast.js @@ -6,7 +6,6 @@ const Lang = imports.lang; const Shell = imports.gi.Shell; const Signals = imports.signals; -const Hash = imports.misc.hash; const Main = imports.ui.main; const ScreencastIface = ' \ @@ -42,13 +41,13 @@ const ScreencastService = new Lang.Class({ Gio.DBus.session.own_name('org.gnome.Shell.Screencast', Gio.BusNameOwnerFlags.REPLACE, null, null); - this._recorders = new Hash.Map(); + this._recorders = new Map(); Main.sessionMode.connect('updated', Lang.bind(this, this._sessionUpdated)); }, get isRecording() { - return this._recorders.size() > 0; + return this._recorders.size > 0; }, _ensureRecorderForSender: function(sender) { @@ -69,8 +68,7 @@ const ScreencastService = new Lang.Class({ if (Main.sessionMode.allowScreencast) return; - for (let sender in this._recorders.keys()) - this._recorders.delete(sender); + this._recorders.clear(); this.emit('updated'); }, diff --git a/js/ui/shellDBus.js b/js/ui/shellDBus.js index 4049095a9..2bc149c62 100644 --- a/js/ui/shellDBus.js +++ b/js/ui/shellDBus.js @@ -10,7 +10,6 @@ const Config = imports.misc.config; const ExtensionSystem = imports.ui.extensionSystem; const ExtensionDownloader = imports.ui.extensionDownloader; const ExtensionUtils = imports.misc.extensionUtils; -const Hash = imports.misc.hash; const Main = imports.ui.main; const Screenshot = imports.ui.screenshot; const ViewSelector = imports.ui.viewSelector; @@ -83,8 +82,8 @@ const GnomeShell = new Lang.Class({ this._extensionsService = new GnomeShellExtensions(); this._screenshotService = new Screenshot.ScreenshotService(); - this._grabbedAccelerators = new Hash.Map(); - this._grabbers = new Hash.Map(); + this._grabbedAccelerators = new Map(); + this._grabbers = new Map(); global.display.connect('accelerator-activated', Lang.bind(this, function(display, action, deviceid, timestamp) { @@ -228,9 +227,8 @@ const GnomeShell = new Lang.Class({ }, _onGrabberBusNameVanished: function(connection, name) { - let grabs = this._grabbedAccelerators.items(); - for (let i = 0; i < grabs.length; i++) { - let [action, sender] = grabs[i]; + let grabs = this._grabbedAccelerators.entries(); + for (let [action, sender] of grabs) { if (sender == name) this._ungrabAccelerator(action); } diff --git a/js/ui/status/network.js b/js/ui/status/network.js index 1df01b691..c3212cc3b 100644 --- a/js/ui/status/network.js +++ b/js/ui/status/network.js @@ -11,7 +11,6 @@ const NMGtk = imports.gi.NMGtk; const Signals = imports.signals; const St = imports.gi.St; -const Hash = imports.misc.hash; const Main = imports.ui.main; const PanelMenu = imports.ui.panelMenu; const PopupMenu = imports.ui.popupMenu; @@ -176,7 +175,7 @@ const NMConnectionSection = new Lang.Class({ _init: function(client) { this._client = client; - this._connectionItems = new Hash.Map(); + this._connectionItems = new Map(); this._connections = []; this._labelSection = new PopupMenu.PopupMenuSection(); @@ -194,7 +193,7 @@ const NMConnectionSection = new Lang.Class({ }, _sync: function() { - let nItems = this._connectionItems.size(); + let nItems = this._connectionItems.size; this._switchSection.actor.visible = (nItems > 1); this._labelSection.actor.visible = (nItems == 1); @@ -213,8 +212,7 @@ const NMConnectionSection = new Lang.Class({ _getStatus: function() { let values = this._connectionItems.values(); - for (let i = 0; i < values.length; i++) { - let item = values[i]; + for (let item of values) { if (item.isActive()) return item.getName(); } @@ -365,7 +363,7 @@ const NMConnectionDevice = new Lang.Class({ }, _sync: function() { - let nItems = this._connectionItems.size(); + let nItems = this._connectionItems.size; this._autoConnectItem.actor.visible = (nItems == 0); this.parent(); }, @@ -1217,7 +1215,7 @@ const NMVPNSection = new Lang.Class({ }, _sync: function() { - let nItems = this._connectionItems.size(); + let nItems = this._connectionItems.size; this.item.actor.visible = (nItems > 0); this.parent(); }, @@ -1239,9 +1237,10 @@ const NMVPNSection = new Lang.Class({ }, setActiveConnections: function(vpnConnections) { - this._connectionItems.values().forEach(function(item) { + let connections = this._connectionItems.values(); + for (let item of connections) { item.setActiveConnection(null); - }); + } vpnConnections.forEach(Lang.bind(this, function(a) { let item = this._connectionItems.get(a._connection.get_uuid()); item.setActiveConnection(a); @@ -1254,8 +1253,7 @@ const NMVPNSection = new Lang.Class({ getIndicatorIcon: function() { let items = this._connectionItems.values(); - for (let i = 0; i < items.length; i++) { - let item = items[i]; + for (let item of items) { let icon = item.getIndicatorIcon(); if (icon) return icon;