electron-devtools-vendor
Version:
<div align="center"> <h2>electron-devtools-vendor</h2> <img alt="MIT" src="https://img.shields.io/github/license/BlackHole1/electron-devtools-vendor?color=9cf&style=flat-square"> <img alt="GitHub repo size" src="https://img.shields.io/github/r
463 lines (360 loc) • 13.6 kB
JavaScript
/**
* DEVELOPED BY
* GIL LOPES BUENO
* gilbueno.mail@gmail.com
*
* WORKS WITH:
* IE 9+, FF 4+, SF 5+, WebKit, CH 7+, OP 12+, BESEN, Rhino 1.7+
*
* FORK:
* https://github.com/melanke/Watch.JS
*/
/**
Version:
https://github.com/melanke/Watch.JS/blob/8220ccd0f4bb898daa4d31410b1c3d72431fd8cd/src/watch.js
*/
;
(function (factory) {
if (typeof exports === 'object') {
// Node. Does not work with strict CommonJS, but
// only CommonJS-like enviroments that support module.exports,
// like Node.
module.exports = factory();
} else if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(factory);
} else {
// Browser globals
window.WatchJS = factory();
window.watch = window.WatchJS.watch;
window.unwatch = window.WatchJS.unwatch;
window.callWatchers = window.WatchJS.callWatchers;
}
}(function () {
var WatchJS = {
noMore: false
},
lengthsubjects = [];
var isFunction = function (functionToCheck) {
var getType = {};
return functionToCheck && getType.toString.call(functionToCheck) == '[object Function]';
};
var isInt = function (x) {
return x % 1 === 0;
};
var isArray = function(obj) {
return Object.prototype.toString.call(obj) === '[object Array]';
};
var getObjDiff = function(a, b){
var aplus = [],
bplus = [];
if(!(typeof a == "string") && !(typeof b == "string")){
if (isArray(a)) {
for (var i=0; i<a.length; i++) {
if (b[i] === undefined) aplus.push(i);
}
} else {
for(var i in a){
if (a.hasOwnProperty(i)) {
if(b && !b.hasOwnProperty(i)) {
aplus.push(i);
}
}
}
}
if (isArray(b)) {
for (var j=0; j<b.length; j++) {
if (a[j] === undefined) bplus.push(j);
}
} else {
for(var j in b){
if (b.hasOwnProperty(j)) {
if(a && !a.hasOwnProperty(j)) {
bplus.push(j);
}
}
}
}
}
return {
added: aplus,
removed: bplus
}
};
var clone = function(obj){
if (null == obj || "object" != typeof obj) {
return obj;
}
var copy = obj.constructor();
for (var attr in obj) {
copy[attr] = obj[attr];
}
return copy;
}
var defineGetAndSet = function (obj, propName, getter, setter) {
try {
Object.defineProperty(obj, propName, {
get: getter,
set: setter,
enumerable: true,
configurable: true
});
} catch(e2) {
try{
Object.prototype.__defineGetter__.call(obj, propName, getter);
Object.prototype.__defineSetter__.call(obj, propName, setter);
} catch(e3) {
throw new Error("watchJS error: browser not supported :/")
}
}
};
var defineProp = function (obj, propName, value) {
try {
Object.defineProperty(obj, propName, {
enumerable: false,
configurable: true,
writable: false,
value: value
});
} catch(error) {
obj[propName] = value;
}
};
var watch = function () {
if (isFunction(arguments[1])) {
watchAll.apply(this, arguments);
} else if (isArray(arguments[1])) {
watchMany.apply(this, arguments);
} else {
watchOne.apply(this, arguments);
}
};
var watchAll = function (obj, watcher, level, addNRemove) {
if ((typeof obj == "string") || (!(obj instanceof Object) && !isArray(obj))) { //accepts only objects and array (not string)
return;
}
var props = [];
if(isArray(obj)) {
for (var prop = 0; prop < obj.length; prop++) { //for each item if obj is an array
props.push(prop); //put in the props
}
} else {
for (var prop2 in obj) { //for each attribute if obj is an object
if (prop2 == "$val") {
continue;
}
if (Object.prototype.hasOwnProperty.call(obj, prop2)) {
props.push(prop2); //put in the props
}
}
}
watchMany(obj, props, watcher, level, addNRemove); //watch all items of the props
if (addNRemove) {
pushToLengthSubjects(obj, "$$watchlengthsubjectroot", watcher, level);
}
};
var watchMany = function (obj, props, watcher, level, addNRemove) {
if ((typeof obj == "string") || (!(obj instanceof Object) && !isArray(obj))) { //accepts only objects and array (not string)
return;
}
for (var i=0; i<props.length; i++) { //watch each property
var prop = props[i];
watchOne(obj, prop, watcher, level, addNRemove);
}
};
var watchOne = function (obj, prop, watcher, level, addNRemove) {
if ((typeof obj == "string") || (!(obj instanceof Object) && !isArray(obj)) || prop instanceof Object) { //accepts only objects and array (not string)
return;
}
if(isFunction(obj[prop])) { //dont watch if it is a function
return;
}
if(obj[prop] != null && (level === undefined || level > 0)){
watchAll(obj[prop], watcher, level!==undefined? level-1 : level); //recursively watch all attributes of this
}
defineWatcher(obj, prop, watcher, level);
if(addNRemove && (level === undefined || level > 0)){
pushToLengthSubjects(obj, prop, watcher, level);
}
};
var unwatch = function () {
if (isFunction(arguments[1])) {
unwatchAll.apply(this, arguments);
} else if (isArray(arguments[1])) {
unwatchMany.apply(this, arguments);
} else {
unwatchOne.apply(this, arguments);
}
};
var unwatchAll = function (obj, watcher) {
if (obj instanceof String || (!(obj instanceof Object) && !isArray(obj))) { //accepts only objects and array (not string)
return;
}
if (isArray(obj)) {
var props = [];
for (var prop = 0; prop < obj.length; prop++) { //for each item if obj is an array
props.push(prop); //put in the props
}
unwatchMany(obj, props, watcher); //watch all itens of the props
} else {
var unwatchPropsInObject = function (obj2) {
var props = [];
for (var prop2 in obj2) { //for each attribute if obj is an object
if (obj2.hasOwnProperty(prop2)) {
if (obj2[prop2] instanceof Object) {
unwatchPropsInObject(obj2[prop2]); //recurs into object props
} else {
props.push(prop2); //put in the props
}
}
}
unwatchMany(obj2, props, watcher); //unwatch all of the props
};
unwatchPropsInObject(obj);
}
};
var unwatchMany = function (obj, props, watcher) {
for (var prop2 in props) { //watch each attribute of "props" if is an object
if (props.hasOwnProperty(prop2)) {
unwatchOne(obj, props[prop2], watcher);
}
}
};
var defineWatcher = function (obj, prop, watcher, level) {
var val = obj[prop];
watchFunctions(obj, prop);
if (!obj.watchers) {
defineProp(obj, "watchers", {});
}
var newWatcher = false;
if (!obj.watchers[prop]) {
obj.watchers[prop] = [];
newWatcher = true;
}
for (var i=0; i<obj.watchers[prop].length; i++) {
if(obj.watchers[prop][i] === watcher){
return;
}
}
obj.watchers[prop].push(watcher); //add the new watcher in the watchers array
if (newWatcher) {
var getter = function () {
return val;
};
var setter = function (newval) {
var oldval = val;
val = newval;
if (level !== 0 && obj[prop]){
// watch sub properties
watchAll(obj[prop], watcher, (level===undefined)?level:level-1);
}
watchFunctions(obj, prop);
if (!WatchJS.noMore){
//if (JSON.stringify(oldval) !== JSON.stringify(newval)) {
if (oldval !== newval) {
callWatchers(obj, prop, "set", newval, oldval);
WatchJS.noMore = false;
}
}
};
defineGetAndSet(obj, prop, getter, setter);
}
};
var callWatchers = function (obj, prop, action, newval, oldval) {
if (prop !== undefined) {
for (var wr=0; wr<obj.watchers[prop].length; wr++) {
obj.watchers[prop][wr].call(obj, prop, action, newval, oldval);
}
} else {
for (var prop in obj) {//call all
if (obj.hasOwnProperty(prop)) {
callWatchers(obj, prop, action, newval, oldval);
}
}
}
};
// @todo code related to "watchFunctions" is certainly buggy
var methodNames = ['pop', 'push', 'reverse', 'shift', 'sort', 'slice', 'unshift', 'splice'];
var defineArrayMethodWatcher = function (obj, prop, original, methodName) {
defineProp(obj[prop], methodName, function () {
var response = original.apply(obj[prop], arguments);
watchOne(obj, obj[prop]);
if (methodName !== 'slice') {
callWatchers(obj, prop, methodName,arguments);
}
return response;
});
};
var watchFunctions = function(obj, prop) {
if ((!obj[prop]) || (obj[prop] instanceof String) || (!isArray(obj[prop]))) {
return;
}
for (var i = methodNames.length, methodName; i--;) {
methodName = methodNames[i];
defineArrayMethodWatcher(obj, prop, obj[prop][methodName], methodName);
}
};
var unwatchOne = function (obj, prop, watcher) {
for (var i=0; i<obj.watchers[prop].length; i++) {
var w = obj.watchers[prop][i];
if(w == watcher) {
obj.watchers[prop].splice(i, 1);
}
}
removeFromLengthSubjects(obj, prop, watcher);
};
var loop = function(){
for(var i=0; i<lengthsubjects.length; i++) {
var subj = lengthsubjects[i];
if (subj.prop === "$$watchlengthsubjectroot") {
var difference = getObjDiff(subj.obj, subj.actual);
if(difference.added.length || difference.removed.length){
if(difference.added.length){
watchMany(subj.obj, difference.added, subj.watcher, subj.level - 1, true);
}
subj.watcher.call(subj.obj, "root", "differentattr", difference, subj.actual);
}
subj.actual = clone(subj.obj);
} else {
var difference = getObjDiff(subj.obj[subj.prop], subj.actual);
if(difference.added.length || difference.removed.length){
if(difference.added.length){
for (var j=0; j<subj.obj.watchers[subj.prop].length; j++) {
watchMany(subj.obj[subj.prop], difference.added, subj.obj.watchers[subj.prop][j], subj.level - 1, true);
}
}
callWatchers(subj.obj, subj.prop, "differentattr", difference, subj.actual);
}
subj.actual = clone(subj.obj[subj.prop]);
}
}
};
var pushToLengthSubjects = function(obj, prop, watcher, level){
var actual;
if (prop === "$$watchlengthsubjectroot") {
actual = clone(obj);
} else {
actual = clone(obj[prop]);
}
lengthsubjects.push({
obj: obj,
prop: prop,
actual: actual,
watcher: watcher,
level: level
});
};
var removeFromLengthSubjects = function(obj, prop, watcher){
for (var i=0; i<lengthsubjects.length; i++) {
var subj = lengthsubjects[i];
if (subj.obj == obj && subj.prop == prop && subj.watcher == watcher) {
lengthsubjects.splice(i, 1);
}
}
};
setInterval(loop, 50);
WatchJS.watch = watch;
WatchJS.unwatch = unwatch;
WatchJS.callWatchers = callWatchers;
return WatchJS;
}));