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
This commit is contained in:
Giovanni Campagna 2014-01-14 23:49:47 +01:00
parent 6dcc3d637f
commit bfb0235fc6
7 changed files with 24 additions and 177 deletions

View File

@ -15,7 +15,6 @@
<file>misc/extensionUtils.js</file> <file>misc/extensionUtils.js</file>
<file>misc/fileUtils.js</file> <file>misc/fileUtils.js</file>
<file>misc/gnomeSession.js</file> <file>misc/gnomeSession.js</file>
<file>misc/hash.js</file>
<file>misc/history.js</file> <file>misc/history.js</file>
<file>misc/jsParse.js</file> <file>misc/jsParse.js</file>
<file>misc/loginManager.js</file> <file>misc/loginManager.js</file>

View File

@ -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;
},
});

View File

@ -19,7 +19,6 @@ const BoxPointer = imports.ui.boxpointer;
const CtrlAltTab = imports.ui.ctrlAltTab; const CtrlAltTab = imports.ui.ctrlAltTab;
const GnomeSession = imports.misc.gnomeSession; const GnomeSession = imports.misc.gnomeSession;
const GrabHelper = imports.ui.grabHelper; const GrabHelper = imports.ui.grabHelper;
const Hash = imports.misc.hash;
const Lightbox = imports.ui.lightbox; const Lightbox = imports.ui.lightbox;
const Main = imports.ui.main; const Main = imports.ui.main;
const PointerWatcher = imports.ui.pointerWatcher; const PointerWatcher = imports.ui.pointerWatcher;
@ -1899,7 +1898,7 @@ const MessageTray = new Lang.Class({
Shell.KeyBindingMode.OVERVIEW, Shell.KeyBindingMode.OVERVIEW,
Lang.bind(this, this._expandActiveNotification)); Lang.bind(this, this._expandActiveNotification));
this._sources = new Hash.Map(); this._sources = new Map();
this._chatSummaryItemsCount = 0; this._chatSummaryItemsCount = 0;
this._trayDwellTimeoutId = 0; this._trayDwellTimeoutId = 0;
@ -1936,7 +1935,7 @@ const MessageTray = new Lang.Class({
}, },
_updateNoMessagesLabel: function() { _updateNoMessagesLabel: function() {
this._noMessages.visible = this._sources.size() == 0; this._noMessages.visible = this._sources.size == 0;
}, },
_sessionUpdated: function() { _sessionUpdated: function() {
@ -2099,7 +2098,8 @@ const MessageTray = new Lang.Class({
}, },
_removeSource: function(source) { _removeSource: function(source) {
let [, obj] = this._sources.delete(source); let obj = this._sources.get(source);
this._sources.delete(source);
let summaryItem = obj.summaryItem; let summaryItem = obj.summaryItem;
if (source.isChat) if (source.isChat)
@ -2120,7 +2120,7 @@ const MessageTray = new Lang.Class({
}, },
getSources: function() { getSources: function() {
return this._sources.keys(); return [k for (k of this._sources.keys())];
}, },
_onSourceEnableChanged: function(policy, source) { _onSourceEnableChanged: function(policy, source) {

View File

@ -17,7 +17,6 @@ const TweenerEquations = imports.tweener.equations;
const Background = imports.ui.background; const Background = imports.ui.background;
const GnomeSession = imports.misc.gnomeSession; const GnomeSession = imports.misc.gnomeSession;
const Hash = imports.misc.hash;
const Layout = imports.ui.layout; const Layout = imports.ui.layout;
const OVirt = imports.gdm.oVirt; const OVirt = imports.gdm.oVirt;
const LoginManager = imports.misc.loginManager; const LoginManager = imports.misc.loginManager;
@ -115,7 +114,7 @@ const NotificationsBox = new Lang.Class({
this.actor.add(this._musicBin); this.actor.add(this._musicBin);
this.actor.add(this._scrollView, { x_fill: true, x_align: St.Align.START }); 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) { Main.messageTray.getSources().forEach(Lang.bind(this, function(source) {
this._sourceAdded(Main.messageTray, source, true); this._sourceAdded(Main.messageTray, source, true);
})); }));
@ -130,9 +129,8 @@ const NotificationsBox = new Lang.Class({
this._sourceAddedId = 0; this._sourceAddedId = 0;
} }
let items = this._sources.items(); let items = this._sources.entries();
for (let i = 0; i < items.length; i++) { for (let [source, obj] of items) {
let [source, obj] = items[i];
this._removeSource(source, obj); this._removeSource(source, obj);
} }

View File

@ -6,7 +6,6 @@ const Lang = imports.lang;
const Shell = imports.gi.Shell; const Shell = imports.gi.Shell;
const Signals = imports.signals; const Signals = imports.signals;
const Hash = imports.misc.hash;
const Main = imports.ui.main; const Main = imports.ui.main;
const ScreencastIface = '<node> \ const ScreencastIface = '<node> \
@ -42,13 +41,13 @@ const ScreencastService = new Lang.Class({
Gio.DBus.session.own_name('org.gnome.Shell.Screencast', Gio.BusNameOwnerFlags.REPLACE, null, null); 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)); Main.sessionMode.connect('updated', Lang.bind(this, this._sessionUpdated));
}, },
get isRecording() { get isRecording() {
return this._recorders.size() > 0; return this._recorders.size > 0;
}, },
_ensureRecorderForSender: function(sender) { _ensureRecorderForSender: function(sender) {
@ -69,8 +68,7 @@ const ScreencastService = new Lang.Class({
if (Main.sessionMode.allowScreencast) if (Main.sessionMode.allowScreencast)
return; return;
for (let sender in this._recorders.keys()) this._recorders.clear();
this._recorders.delete(sender);
this.emit('updated'); this.emit('updated');
}, },

View File

@ -10,7 +10,6 @@ const Config = imports.misc.config;
const ExtensionSystem = imports.ui.extensionSystem; const ExtensionSystem = imports.ui.extensionSystem;
const ExtensionDownloader = imports.ui.extensionDownloader; const ExtensionDownloader = imports.ui.extensionDownloader;
const ExtensionUtils = imports.misc.extensionUtils; const ExtensionUtils = imports.misc.extensionUtils;
const Hash = imports.misc.hash;
const Main = imports.ui.main; const Main = imports.ui.main;
const Screenshot = imports.ui.screenshot; const Screenshot = imports.ui.screenshot;
const ViewSelector = imports.ui.viewSelector; const ViewSelector = imports.ui.viewSelector;
@ -83,8 +82,8 @@ const GnomeShell = new Lang.Class({
this._extensionsService = new GnomeShellExtensions(); this._extensionsService = new GnomeShellExtensions();
this._screenshotService = new Screenshot.ScreenshotService(); this._screenshotService = new Screenshot.ScreenshotService();
this._grabbedAccelerators = new Hash.Map(); this._grabbedAccelerators = new Map();
this._grabbers = new Hash.Map(); this._grabbers = new Map();
global.display.connect('accelerator-activated', Lang.bind(this, global.display.connect('accelerator-activated', Lang.bind(this,
function(display, action, deviceid, timestamp) { function(display, action, deviceid, timestamp) {
@ -228,9 +227,8 @@ const GnomeShell = new Lang.Class({
}, },
_onGrabberBusNameVanished: function(connection, name) { _onGrabberBusNameVanished: function(connection, name) {
let grabs = this._grabbedAccelerators.items(); let grabs = this._grabbedAccelerators.entries();
for (let i = 0; i < grabs.length; i++) { for (let [action, sender] of grabs) {
let [action, sender] = grabs[i];
if (sender == name) if (sender == name)
this._ungrabAccelerator(action); this._ungrabAccelerator(action);
} }

View File

@ -11,7 +11,6 @@ const NMGtk = imports.gi.NMGtk;
const Signals = imports.signals; const Signals = imports.signals;
const St = imports.gi.St; const St = imports.gi.St;
const Hash = imports.misc.hash;
const Main = imports.ui.main; const Main = imports.ui.main;
const PanelMenu = imports.ui.panelMenu; const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu; const PopupMenu = imports.ui.popupMenu;
@ -176,7 +175,7 @@ const NMConnectionSection = new Lang.Class({
_init: function(client) { _init: function(client) {
this._client = client; this._client = client;
this._connectionItems = new Hash.Map(); this._connectionItems = new Map();
this._connections = []; this._connections = [];
this._labelSection = new PopupMenu.PopupMenuSection(); this._labelSection = new PopupMenu.PopupMenuSection();
@ -194,7 +193,7 @@ const NMConnectionSection = new Lang.Class({
}, },
_sync: function() { _sync: function() {
let nItems = this._connectionItems.size(); let nItems = this._connectionItems.size;
this._switchSection.actor.visible = (nItems > 1); this._switchSection.actor.visible = (nItems > 1);
this._labelSection.actor.visible = (nItems == 1); this._labelSection.actor.visible = (nItems == 1);
@ -213,8 +212,7 @@ const NMConnectionSection = new Lang.Class({
_getStatus: function() { _getStatus: function() {
let values = this._connectionItems.values(); let values = this._connectionItems.values();
for (let i = 0; i < values.length; i++) { for (let item of values) {
let item = values[i];
if (item.isActive()) if (item.isActive())
return item.getName(); return item.getName();
} }
@ -365,7 +363,7 @@ const NMConnectionDevice = new Lang.Class({
}, },
_sync: function() { _sync: function() {
let nItems = this._connectionItems.size(); let nItems = this._connectionItems.size;
this._autoConnectItem.actor.visible = (nItems == 0); this._autoConnectItem.actor.visible = (nItems == 0);
this.parent(); this.parent();
}, },
@ -1217,7 +1215,7 @@ const NMVPNSection = new Lang.Class({
}, },
_sync: function() { _sync: function() {
let nItems = this._connectionItems.size(); let nItems = this._connectionItems.size;
this.item.actor.visible = (nItems > 0); this.item.actor.visible = (nItems > 0);
this.parent(); this.parent();
}, },
@ -1239,9 +1237,10 @@ const NMVPNSection = new Lang.Class({
}, },
setActiveConnections: function(vpnConnections) { setActiveConnections: function(vpnConnections) {
this._connectionItems.values().forEach(function(item) { let connections = this._connectionItems.values();
for (let item of connections) {
item.setActiveConnection(null); item.setActiveConnection(null);
}); }
vpnConnections.forEach(Lang.bind(this, function(a) { vpnConnections.forEach(Lang.bind(this, function(a) {
let item = this._connectionItems.get(a._connection.get_uuid()); let item = this._connectionItems.get(a._connection.get_uuid());
item.setActiveConnection(a); item.setActiveConnection(a);
@ -1254,8 +1253,7 @@ const NMVPNSection = new Lang.Class({
getIndicatorIcon: function() { getIndicatorIcon: function() {
let items = this._connectionItems.values(); let items = this._connectionItems.values();
for (let i = 0; i < items.length; i++) { for (let item of items) {
let item = items[i];
let icon = item.getIndicatorIcon(); let icon = item.getIndicatorIcon();
if (icon) if (icon)
return icon; return icon;