diff --git a/content/treestyletab/res/tabsDragUtils.js b/content/treestyletab/res/tabsDragUtils.js index 562c536e..e498276b 100644 --- a/content/treestyletab/res/tabsDragUtils.js +++ b/content/treestyletab/res/tabsDragUtils.js @@ -13,9 +13,12 @@ original: http://github.com/piroor/fxaddonlib-tabs-drag-utils + + depends on: + https://github.com/clear-code/js-extended-immutable */ (function() { - const currentRevision = 36; + const currentRevision = 37; if (!('piro.sakura.ne.jp' in window)) window['piro.sakura.ne.jp'] = {}; @@ -34,6 +37,9 @@ const Ci = Components.interfaces; const TAB_DROP_TYPE = 'application/x-moz-tabbrowser-tab'; + // fix path to extended-immutable.js + var { ExtendedImmutable } = Components.utils.import('resource://treestyletab-modules/lib/extended-immutable.js', {}); + var tabsDragUtils = { revision : currentRevision, @@ -142,16 +148,26 @@ this.updatedTabDNDObservers.push(aObserver); if (typeof aObserver._getDropEffectForTabDrag === 'function' && - aObserver._getDropEffectForTabDrag.toSource().indexOf('tabsDragUtils') < 0) { - let original = aObserver._getDropEffectForTabDrag; - aObserver.__TabsDragUtils_original__getDropEffectForTabDrag = original; - eval('aObserver._getDropEffectForTabDrag = '+ - original.toSource().replace( - 'dt.mozItemCount > 1', - '$& && !window["piro.sakura.ne.jp"].tabsDragUtils.isTabsDragging(arguments[0])' - ) - ); - aObserver.__TabsDragUtils_updated__getDropEffectForTabDrag = aObserver._getDropEffectForTabDrag; + !aObserver.__tabsDragUtils__getDropEffectForTabDrag) { + aObserver.__tabsDragUtils__getDropEffectForTabDrag = aObserver._getDropEffectForTabDrag; + aObserver._getDropEffectForTabDrag = function(aEvent, ...aArgs) { + var fakeItemCount = window["piro.sakura.ne.jp"].tabsDragUtils.isTabsDragging(aEvent) ? 1 : null ; + var fakeDataTransfer = new ExtendedImmutable(aEvent.dataTransfer, { + get mozItemCount() { + if (fakeItemCount) { + fakeItemCount = null; + return fakeItemCount; + } + return aEvent.dataTransfer.mozItemCount; + } + }); + var fakeEvent = new ExtendedImmutable(aEvent, { + get dataTransfer() { + return fakeDataTransfer; + } + }); + return aObserver.__tabsDragUtils__getDropEffectForTabDrag(fakeEvent, ...aArgs); + }; } if ('_animateTabMove' in aObserver && diff --git a/modules/lib/extended-immutable.js b/modules/lib/extended-immutable.js new file mode 100644 index 00000000..cd7ff3c7 --- /dev/null +++ b/modules/lib/extended-immutable.js @@ -0,0 +1,80 @@ +// Original author: ClearCode Inc. +// License: MIT +// Repository: https://github.com/clear-code/js-extended-immutable + +var EXPORTED_SYMBOLS = ['ExtendedImmutable']; + +function ExtendedImmutable(aImmutable, aExtraProperties) { + var descriptors = {}; + Object.keys(aExtraProperties).forEach(function(aName) { + descriptors[aName] = Object.getOwnPropertyDescriptor(aExtraProperties, aName); + }); + + var base = Object.create({}, descriptors); + return new Proxy(base, { + getPrototypeOf: function(aTarget) { + return Object.getPrototypeOf(aImmutable); + }, + setPrototypeOf: function(aTarget, aPrototype) { + return Object.setPrototypeOf(aImmutable, aPrototype); + }, + isExtensible: function(aTarget) { + return Object.isExtensible(aImmutable); + }, + preventExtensions: function(aTarget) { + return Object.preventExtensions(aImmutable); + }, + getOwnPropertyDescriptor: function(aTarget, aProperty) { + return Object.getOwnPropertyDescriptor(aImmutable, aProperty); + }, + defineProperty: function(aTarget, aProperty, aDescriptor) { + return Object.defineProperty(aImmutable, aProperty, aDescriptor); + }, + has: function(aTarget, aProperty) { + return aProperty in aImmutable; + }, + get: function(aTarget, aName, aReceiver) { + if (descriptors.hasOwnProperty(aName)) { + let value; + if (typeof descriptors[aName].get == 'function') + value = descriptors[aName].get.call(base); + else + value = descriptors[aName].value; + + if (typeof value == 'function') + return value.bind(base); + else + return value; + } + var value = aImmutable[aName]; + if (typeof value == 'function') + return value.bind(aImmutable); + else + return value; + }, + set: function(aTarget, aName, aValue, aReceiver) { + if (descriptors.hasOwnProperty(aName)) { + if (typeof descriptors[aName].set == 'function') + return descriptors[aName].set.call(base, aValue); + else + return descriptors[aName].value = aValue; + } + return aImmutable[aName] = aValue; + }, + deleteProperty: function(aTarget, aProperty) { + delete aImmutable[aProperty]; + }, + enumerate: function(aTarget) { + return Reflect.enumerate(aImmutable); + }, + ownKeys: function(aTarget) { + return Object.getOwnPropertyNames(aImmutable); + }, + apply: function(aTarget, aThis, aArgs) { + return aImmutable.apply(aThis, aArgs); + }, + construct: function(aTarget, aArgs) { + return new aImmutable(...aArgs); + } + }); +}