From 7c857fad5bcc3018ae1203550ea969ef8ac8aced Mon Sep 17 00:00:00 2001 From: Artur Signell Date: Fri, 23 Jan 2015 11:35:59 +0200 Subject: Upgrading version 0.1.0 --- Object.observe.poly.js | 371 +++++++++++++++++++++++++++++++++++++++++++++++++ vaadin-components.html | 12 +- 2 files changed, 377 insertions(+), 6 deletions(-) create mode 100644 Object.observe.poly.js diff --git a/Object.observe.poly.js b/Object.observe.poly.js new file mode 100644 index 0000000..aeb7d8c --- /dev/null +++ b/Object.observe.poly.js @@ -0,0 +1,371 @@ +/* + Tested against Chromium build with Object.observe and acts EXACTLY the same, + though Chromium build is MUCH faster + + Trying to stay as close to the spec as possible, + this is a work in progress, feel free to comment/update + + Specification: + http://wiki.ecmascript.org/doku.php?id=harmony:observe + + Built using parts of: + https://github.com/tvcutsem/harmony-reflect/blob/master/examples/observer.js + + Limits so far; + Built using polling... Will update again with polling/getter&setters to make things better at some point + +TODO: + Add support for Object.prototype.watch -> https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/watch +*/ +if(!Object.observe){ + (function(extend, global){ + "use strict"; + var isCallable = (function(toString){ + var s = toString.call(toString), + u = typeof u; + return typeof global.alert === "object" ? + function isCallable(f){ + return s === toString.call(f) || (!!f && typeof f.toString == u && typeof f.valueOf == u && /^\s*\bfunction\b/.test("" + f)); + }: + function isCallable(f){ + return s === toString.call(f); + } + ; + })(extend.prototype.toString); + // isNode & isElement from http://stackoverflow.com/questions/384286/javascript-isdom-how-do-you-check-if-a-javascript-object-is-a-dom-object + //Returns true if it is a DOM node + var isNode = function isNode(o){ + return ( + typeof Node === "object" ? o instanceof Node : + o && typeof o === "object" && typeof o.nodeType === "number" && typeof o.nodeName==="string" + ); + } + //Returns true if it is a DOM element + var isElement = function isElement(o){ + return ( + typeof HTMLElement === "object" ? o instanceof HTMLElement : //DOM2 + o && typeof o === "object" && o !== null && o.nodeType === 1 && typeof o.nodeName==="string" + ); + } + var _isImmediateSupported = (function(){ + return !!global.setImmediate; + })(); + var _doCheckCallback = (function(){ + if(_isImmediateSupported){ + return function _doCheckCallback(f){ + return setImmediate(f); + }; + }else{ + return function _doCheckCallback(f){ + return setTimeout(f, 10); + }; + } + })(); + var _clearCheckCallback = (function(){ + if(_isImmediateSupported){ + return function _clearCheckCallback(id){ + clearImmediate(id); + }; + }else{ + return function _clearCheckCallback(id){ + clearTimeout(id); + }; + } + })(); + var isNumeric=function isNumeric(n){ + return !isNaN(parseFloat(n)) && isFinite(n); + }; + var sameValue = function sameValue(x, y){ + if(x===y){ + return x !== 0 || 1 / x === 1 / y; + } + return x !== x && y !== y; + }; + var isAccessorDescriptor = function isAccessorDescriptor(desc){ + if (typeof(desc) === 'undefined'){ + return false; + } + return ('get' in desc || 'set' in desc); + }; + var isDataDescriptor = function isDataDescriptor(desc){ + if (typeof(desc) === 'undefined'){ + return false; + } + return ('value' in desc || 'writable' in desc); + }; + + var validateArguments = function validateArguments(O, callback, accept){ + if(typeof(O)!=='object'){ + // Throw Error + throw new TypeError("Object.observeObject called on non-object"); + } + if(isCallable(callback)===false){ + // Throw Error + throw new TypeError("Object.observeObject: Expecting function"); + } + if(Object.isFrozen(callback)===true){ + // Throw Error + throw new TypeError("Object.observeObject: Expecting unfrozen function"); + } + if (accept !== undefined) { + if (!Array.isArray(accept)) { + throw new TypeError("Object.observeObject: Expecting acceptList in the form of an array"); + } + } + }; + + var Observer = (function Observer(){ + var wraped = []; + var Observer = function Observer(O, callback, accept){ + validateArguments(O, callback, accept); + if (!accept) { + accept = ["add", "update", "delete", "reconfigure", "setPrototype", "preventExtensions"]; + } + Object.getNotifier(O).addListener(callback, accept); + if(wraped.indexOf(O)===-1){ + wraped.push(O); + }else{ + Object.getNotifier(O)._checkPropertyListing(); + } + }; + + Observer.prototype.deliverChangeRecords = function Observer_deliverChangeRecords(O){ + Object.getNotifier(O).deliverChangeRecords(); + }; + + wraped.lastScanned = 0; + var f = (function f(wrapped){ + return function _f(){ + var i = 0, l = wrapped.length, startTime = new Date(), takingTooLong=false; + for(i=wrapped.lastScanned; (i -1){ + Object.getNotifier(wrapped[i])._checkPropertyListing(); + takingTooLong=((new Date())-startTime)>100; // make sure we don't take more than 100 milliseconds to scan all objects + }else{ + wrapped.splice(i, 1); + i--; + l--; + } + } + wrapped.lastScanned=i-1){ + _listeners.splice(idx, 1); + _acceptLists.splice(idx, 1); + } + }; + self.listeners = function Notifier_listeners(){ + return _listeners; + }; + self.queueUpdate = function Notifier_queueUpdate(what, prop, type, was){ + this.queueUpdates([{ + type: type, + object: what, + name: prop, + oldValue: was + }]); + }; + self.queueUpdates = function Notifier_queueUpdates(updates){ + var self = this, i = 0, l = updates.length||0, update; + for(i=0; i-1?_notifiers[idx]:false; + if(!notifier){ + idx = _indexes.length; + _indexes[idx] = O; + notifier = _notifiers[idx] = new Notifier(O); + } + return notifier; + }; + extend.observe = function Object_observe(O, callback, accept){ + // For Bug 4, can't observe DOM elements tested against canry implementation and matches + if(!isElement(O)){ + return new Observer(O, callback, accept); + } + }; + extend.unobserve = function Object_unobserve(O, callback){ + validateArguments(O, callback); + var idx = _indexes.indexOf(O), + notifier = idx>-1?_notifiers[idx]:false; + if (!notifier){ + return; + } + notifier.removeListener(callback); + if (notifier.listeners().length === 0){ + _indexes.splice(idx, 1); + _notifiers.splice(idx, 1); + } + }; + })(Object, this); +} diff --git a/vaadin-components.html b/vaadin-components.html index e1ac4be..41b306b 100644 --- a/vaadin-components.html +++ b/vaadin-components.html @@ -2,7 +2,7 @@