From f7e4257745ccd44b8d24555f0ef787429d6e472c Mon Sep 17 00:00:00 2001 From: Valerio Virgillito Date: Tue, 5 Jun 2012 00:11:03 -0700 Subject: adding the latest v0.10 montage Signed-off-by: Valerio Virgillito --- node_modules/montage/core/change-notification.js | 82 +++++++-- .../montage/core/converter/bytes-converter.js | 3 +- node_modules/montage/core/converter/converter.js | 3 +- .../montage/core/converter/currency-converter.js | 9 +- .../montage/core/converter/date-converter.js | 12 +- .../montage/core/converter/number-converter.js | 28 ++- .../montage/core/converter/upper-case-converter.js | 2 +- node_modules/montage/core/core.js | 32 ++-- node_modules/montage/core/deserializer.js | 29 ++- .../montage/core/event/action-event-listener.js | 6 +- node_modules/montage/core/event/binding.js | 202 ++++++--------------- node_modules/montage/core/extras/object.js | 41 ++--- 12 files changed, 215 insertions(+), 234 deletions(-) (limited to 'node_modules/montage/core') diff --git a/node_modules/montage/core/change-notification.js b/node_modules/montage/core/change-notification.js index bfe5ff2d..3f6d884e 100644 --- a/node_modules/montage/core/change-notification.js +++ b/node_modules/montage/core/change-notification.js @@ -205,6 +205,7 @@ var ChangeNotificationDescriptor = Montage.create(Montage, { dependentDescriptorsIndex: {value: null}, mutationDependencyIndex: {value: null}, mutationListenersCount: {value: 0}, + observedDependentProperties: {value: null}, initWithTargetPath: { value: function(target, path) { @@ -216,7 +217,8 @@ var ChangeNotificationDescriptor = Montage.create(Montage, { }, registerListener: { value: function(listener, beforeChange, mutation) { - var listenerKey = listener.uuid; + var listenerKey = listener.uuid, + listeners; if (beforeChange) { listeners = this.willChangeListeners; @@ -247,7 +249,8 @@ var ChangeNotificationDescriptor = Montage.create(Montage, { }, unregisterListener: { value: function(listener, beforeChange) { - var listenerKey = listener.uuid; + var listenerKey = listener.uuid, + listeners; if (beforeChange) { listeners = this.willChangeListeners; @@ -533,7 +536,14 @@ var ChangeNotificationDescriptor = Montage.create(Montage, { var listener, dependentDescriptorsIndex = this.dependentDescriptorsIndex, dependenciesIndex = notification._dependenciesIndex, - isMutationNotification; + isMutationNotification, + uuid = this.uuid; + + // we need to stop circular property dependencies. + // e.g.: object.foo depends on object.bar and object.bar depends on object.foo. + if (notification[uuid]) { + return; + } // TODO: maybe I should replicate this if (arguments.length < 2) { @@ -563,7 +573,9 @@ var ChangeNotificationDescriptor = Montage.create(Montage, { if (dependentDescriptorsIndex) { notification._dependenciesIndex = dependentDescriptorsIndex[key]; } + notification[uuid] = true; listener.listenerFunction.call(listener.listenerTarget, notification); + notification[uuid] = false; } } notification._dependenciesIndex = dependenciesIndex; @@ -681,12 +693,14 @@ var ObjectPropertyChangeDispatcherManager = Object.create(null, { notification; if (!descriptor) { + originalSetter.apply(this, arguments); return; } previousValue = this[propertyName]; if (previousValue === value) { - // Nothing to do here + originalSetter.apply(this, arguments); + // Nothing more to do here return; } @@ -756,12 +770,13 @@ Object.defineProperty(Object.prototype, "dispatchPropertyChange", { for (i = 0; i < callbackArgumentIndex; i++) { iProperty = arguments[i]; descriptor = ChangeNotification.getPropertyChangeDescriptor(this, iProperty); - if (descriptor) { + if (descriptor && !descriptor.isActive) { notification = Object.create(PropertyChangeNotification); observedProperties.push(iProperty, descriptor, notification); notification.target = this; notification.minus = this.getProperty(iProperty); + descriptor.isActive = true; descriptor.handleWillChange(notification); } } @@ -775,6 +790,7 @@ Object.defineProperty(Object.prototype, "dispatchPropertyChange", { notification.plus = this.getProperty(iProperty); descriptor.handleChange(notification); + descriptor.isActive = false; } } @@ -818,9 +834,19 @@ Object.defineProperty(Object.prototype, "addPropertyChangeListener", { // TODO should adding a dispatcher on a dependent property also be subjected to checking for // automaticDispatchPropertyChangeListener, probably if (dependentPropertyPaths) { + + if (!descriptor.observedDependentProperties) { + descriptor.observedDependentProperties = {}; + } + for (i = 0; (iPath = dependentPropertyPaths[i]); i++) { - this.addPropertyChangeListener(iPath, descriptor, beforeChange, false); - descriptor.registerDependency(this, iPath, null); + + if (!descriptor.observedDependentProperties[iPath]) { + descriptor.observedDependentProperties[iPath] = true; + + this.addPropertyChangeListener(iPath, descriptor, beforeChange, false); + descriptor.registerDependency(this, iPath, null); + } } } } @@ -861,16 +887,16 @@ var PrefixedPropertyDescriptor = { configurable: true }; -var PropertyChangeNotification = exports.PropertyChangeNotification = Object.create(null, { - phase: {writable: true, value: null}, - target: {writable: true, value: null}, - propertyPath: {writable: true, value: null}, - minus: {writable: true, value: null}, - plus: {writable: true, value: null}, - currentTarget: {writable: true, value: null}, - currentPropertyPath: {writable: true, value: null}, - isMutation: {writable: true, value: false} -}); +var PropertyChangeNotification = exports.PropertyChangeNotification = { + phase: null, + target: null, + propertyPath: null, + minus: null, + plus: null, + currentTarget: null, + currentPropertyPath: null, + isMutation: false +}; var ChangeNotificationDispatchingArray = exports.ChangeNotificationDispatchingArray = []; var _index_array_regexp = /^[0-9]+$/; @@ -878,13 +904,15 @@ var _unobservable_array_property_regexp = /^length$/; Object.defineProperty(Array.prototype, "addPropertyChangeListener", { value: function(path, listener, beforeChange, ignoreMutation) { var listenChange, listenIndexChange, listenFunctionChange, - descriptor; + descriptor, + dotIndex; if (!listener) { return; } - if (path == null || path.indexOf(".") == -1) { + if (path == null || (dotIndex = path.indexOf(".")) == -1) { + if (_unobservable_array_property_regexp.test(path)) { return; @@ -909,6 +937,12 @@ Object.defineProperty(Array.prototype, "addPropertyChangeListener", { } } else { Object.prototype.addPropertyChangeListener.apply(this, arguments); + // We need to do this because the Object.prototype.addPropertyChangeListener doesn't create dependencies + // for no-dot paths, but in array array.path will have dependencies when path is not an index or null. + if (dotIndex == -1) { + descriptor = ChangeNotification.getPropertyChangeDescriptor(this, path); + descriptor.setupDependencies(this, path, beforeChange, !ignoreMutation); + } } } }); @@ -918,6 +952,7 @@ Object.defineProperty(ChangeNotificationDispatchingArray, "_dispatchArrayChangeN configurable: false, value: function(methodName, methodArguments, index, howManyToRemove, newValues) { var descriptor = ChangeNotification.getPropertyChangeDescriptor(this, null), + result, notification, indexNotification = Object.create(PropertyChangeNotification), delta, @@ -1235,6 +1270,7 @@ Object.defineProperty(ChangeNotificationDispatchingArray, "sort", { indexNotification, oldValue, newValue, + indexArray, _sortIndexArray, _sortIndexArrayLength; @@ -1340,6 +1376,7 @@ Object.defineProperty(Object.prototype, "__debugChangeNotifications__", { configurable: false, value: function() { var registry = ChangeNotification._descriptorsRegistry[this.uuid], + path, log = []; if (registry) { @@ -1367,7 +1404,12 @@ Object.defineProperty(Object.prototype, "__debugChangeNotifications__", { var listenerFunctionName = changeListeners[key].listenerFunctionName; var info = Montage.getInfoForObject(listenerTarget); if (info.objectName === "PropertyChangeBindingListener") { - bindings.push("\"" + listenerTarget.bindingPropertyPath + "\" @ " + Montage.getInfoForObject(listenerTarget.bindingOrigin).objectName + "(", listenerTarget.bindingOrigin, ")"); + if (listenerTarget.bindingOrigin === this && listenerTarget.bindingPropertyPath === path) { + bindings.push("\"" + listenerTarget.targetPropertyPath + "\" @ " + (Montage.getInfoForObject(listenerTarget.target).objectName || "") + "(", listenerTarget.target, ")"); + } else { + bindings.push("\"" + listenerTarget.bindingPropertyPath + "\" @ " + (Montage.getInfoForObject(listenerTarget.bindingOrigin).objectName || "") + "(", listenerTarget.bindingOrigin, ")"); + } + bindings.push("\n\t "); } } diff --git a/node_modules/montage/core/converter/bytes-converter.js b/node_modules/montage/core/converter/bytes-converter.js index 1626f352..605d8546 100755 --- a/node_modules/montage/core/converter/bytes-converter.js +++ b/node_modules/montage/core/converter/bytes-converter.js @@ -78,7 +78,8 @@ exports.BytesConverter = Montage.create(Converter, /** @lends module:montage/cor @default {Number} 2 */ decimals: { - value: 2 + value: 2, + serializable: true }, /** Converts the specified value to byte format. diff --git a/node_modules/montage/core/converter/converter.js b/node_modules/montage/core/converter/converter.js index a23d2702..97e1a5f2 100755 --- a/node_modules/montage/core/converter/converter.js +++ b/node_modules/montage/core/converter/converter.js @@ -111,7 +111,8 @@ var Converter = exports.Converter = Montage.create(Montage, /** @lends module:mo @default {Boolean} true */ allowPartialConversion: { - value: true + value: true, + serializable: true }, /** diff --git a/node_modules/montage/core/converter/currency-converter.js b/node_modules/montage/core/converter/currency-converter.js index bba81dc1..10f6f068 100755 --- a/node_modules/montage/core/converter/currency-converter.js +++ b/node_modules/montage/core/converter/currency-converter.js @@ -44,7 +44,8 @@ exports.CurrencyConverter = Montage.create(NumberConverter, /** @lends module:mo @default {String} '$' */ currency: { - value: '$' + value: '$', + serializable: true }, /** @@ -52,7 +53,8 @@ exports.CurrencyConverter = Montage.create(NumberConverter, /** @lends module:mo @default {Number} 2 */ decimals: { - value: 2 + value: 2, + serializable: true }, /** @@ -60,7 +62,8 @@ exports.CurrencyConverter = Montage.create(NumberConverter, /** @lends module:mo @default {Boolean} false */ useParensForNegative: { - value: false + value: false, + serializable: true }, /** diff --git a/node_modules/montage/core/converter/date-converter.js b/node_modules/montage/core/converter/date-converter.js index 7b062925..e200333b 100755 --- a/node_modules/montage/core/converter/date-converter.js +++ b/node_modules/montage/core/converter/date-converter.js @@ -2539,7 +2539,8 @@ var DateValidator = exports.DateValidator = Montage.create(Validator,/** @lends @default {Date} 'MM/dd/yyyy' */ pattern: { - value: 'MM/dd/yyyy' + value: 'MM/dd/yyyy', + serializable: true }, /** @function @@ -2576,7 +2577,8 @@ var DateConverter = exports.DateConverter = Montage.create(Converter,/** @lends @default {Boolean} true */ allowPartialConversion: { - value: false + value: false, + serializable: true }, /** @@ -2584,7 +2586,8 @@ var DateConverter = exports.DateConverter = Montage.create(Converter,/** @lends @default {Function} Montage.create(DateValidator) */ validator: { - value: Montage.create(DateValidator) + value: Montage.create(DateValidator), + serializable: true }, // valid fn values are: @@ -2593,7 +2596,8 @@ var DateConverter = exports.DateConverter = Montage.create(Converter,/** @lends @default {Date} 'MM/dd/yyyy' */ pattern: { - value: 'MM/dd/yyyy' + value: 'MM/dd/yyyy', + serializable: true }, /** @function diff --git a/node_modules/montage/core/converter/number-converter.js b/node_modules/montage/core/converter/number-converter.js index f440f9a2..3eb3af64 100755 --- a/node_modules/montage/core/converter/number-converter.js +++ b/node_modules/montage/core/converter/number-converter.js @@ -212,7 +212,8 @@ var NumberValidator = exports.NumberValidator = Montage.create(Validator, /** @l @default {Boolean} true */ allowFloat: { - value: true + value: true, + serializable: true }, /** @@ -220,7 +221,8 @@ var NumberValidator = exports.NumberValidator = Montage.create(Validator, /** @l @default {Boolean} true */ allowNegative: { - value: true + value: true, + serializable: true }, /** @@ -265,7 +267,8 @@ var NumberConverter = exports.NumberConverter = Montage.create(Converter, /** @l */ // do not allow partial conversion allowPartialConversion: { - value: false + value: false, + serializable: true }, /** @type {Function} @@ -281,14 +284,16 @@ var NumberConverter = exports.NumberConverter = Montage.create(Converter, /** @l */ // valid fn values are: shorten: { - value: null + value: null, + serializable: true }, /** @type {Property} @default {Number} 2 */ decimals: { - value: 2 + value: 2, + serializable: true }, /** @@ -296,7 +301,8 @@ var NumberConverter = exports.NumberConverter = Montage.create(Converter, /** @l @default {Number} null */ round: { - value: null + value: null, + serializable: true }, /** @@ -306,19 +312,21 @@ var NumberConverter = exports.NumberConverter = Montage.create(Converter, /** @l value: /(\d+)(\d{3})/ }, - /** + /** @type {Property} @default {Boolean} true */ allowFloat: { - value: true + value: true, + serializable: true }, - /** + /** @type {Property} @default {Boolean} true */ allowNegative: { - value: true + value: true, + serializable: true }, // credit: sugar.js - https://github.com/andrewplummer/Sugar diff --git a/node_modules/montage/core/converter/upper-case-converter.js b/node_modules/montage/core/converter/upper-case-converter.js index 33ec0055..f421fd6d 100755 --- a/node_modules/montage/core/converter/upper-case-converter.js +++ b/node_modules/montage/core/converter/upper-case-converter.js @@ -4,7 +4,7 @@ (c) Copyright 2011 Motorola Mobility, Inc. All Rights Reserved. */ /** - @module montage/core/converter/upper-case-converter + @module montage/core/converter/upper-case-converter @requires montage/core/core @requires montage/core/converter/converter */ diff --git a/node_modules/montage/core/core.js b/node_modules/montage/core/core.js index 80597dce..26733c94 100755 --- a/node_modules/montage/core/core.js +++ b/node_modules/montage/core/core.js @@ -21,6 +21,7 @@ var ATTRIBUTE_PROPERTIES = "AttributeProperties", PROTO = "__proto__", VALUE = "value", ENUMERABLE = "enumerable", + DISTINCT = "distinct", SERIALIZABLE = "serializable", MODIFY = "modify"; @@ -63,10 +64,6 @@ Object.defineProperty(Montage, "create", { var newObject = Object.create(typeof aPrototype === "undefined" ? this : aPrototype); - if (newObject._dependenciesForProperty) { - newObject._dependencyListeners = {}; - } - if (typeof newObject.didCreate === "function") { newObject.didCreate(); } @@ -80,7 +77,7 @@ Object.defineProperty(Montage, "create", { } }); -var extendedPropertyAttributes = [SERIALIZABLE, MODIFY]; +var extendedPropertyAttributes = [SERIALIZABLE]; // Extended property attributes, the property name format is "_" + attributeName + "AttributeProperties" /** @@ -112,13 +109,21 @@ extendedPropertyAttributes.forEach(function(name) { Object.defineProperty(Montage, "defineProperty", { value: function(obj, prop, descriptor) { - var dependencies = descriptor.dependencies; + + var dependencies = descriptor.dependencies, + isValueDescriptor = (VALUE in descriptor); + + if (DISTINCT in descriptor && !isValueDescriptor) { + throw ("Cannot use distinct attribute on non-value property '" + prop + "'"); + } + + //reset defaults appropriately for framework. if (PROTO in descriptor) { - descriptor.__proto__ = (VALUE in descriptor ? (typeof descriptor.value === "function" ? _defaultFunctionValueProperty : _defaultObjectValueProperty) : _defaultAccessorProperty); + descriptor.__proto__ = (isValueDescriptor ? (typeof descriptor.value === "function" ? _defaultFunctionValueProperty : _defaultObjectValueProperty) : _defaultAccessorProperty); } else { var defaults; - if (VALUE in descriptor) { + if (isValueDescriptor) { if (typeof descriptor.value === "function") { defaults = _defaultFunctionValueProperty; } else { @@ -153,10 +158,6 @@ Object.defineProperty(Montage, "defineProperty", { getAttributeProperties(obj, SERIALIZABLE)[prop] = descriptor.serializable; } - if (MODIFY in descriptor) { - getAttributeProperties(obj, MODIFY)[prop] = descriptor.modify; - } - //this is added to enable value properties with [] or Objects that are new for every instance if (descriptor.distinct === true && typeof descriptor.value === "object") { (function(prop,internalProperty, value, obj) { @@ -587,6 +588,11 @@ Object.defineProperty(Object.prototype, "uuid", { } }); +Montage.defineProperty(Montage, "identifier", { + value: null, + serializable: true +}); + /** Returns true if two objects are equal, otherwise returns false. @function module:montage/core/core.Montage#equals @@ -599,6 +605,8 @@ Object.defineProperty(Montage, "equals", { } }); + + /* * If it exists this method calls the method named with the identifier prefix. * Example: If the name parameter is "shouldDoSomething" and the caller's identifier is "bob", then diff --git a/node_modules/montage/core/deserializer.js b/node_modules/montage/core/deserializer.js index 2b3ed64e..3c0aa049 100755 --- a/node_modules/montage/core/deserializer.js +++ b/node_modules/montage/core/deserializer.js @@ -246,7 +246,7 @@ var Deserializer = Montage.create(Montage, /** @lends module:montage/core/deseri object = stack[ix-1], desc = stack[ix]; - this._deserializeProperties(object, desc.properties); + this._deserializeProperties(object, desc.properties, true); } }, @@ -331,9 +331,22 @@ var Deserializer = Montage.create(Montage, /** @lends module:montage/core/deseri @param {Object} object The target of the properties. @param {Array} properties The property names to be deserialized. */ - deserializePropertiesForObject: {value: function(object, properties) { - for (var key in properties) { - object[key] = properties[key]; + deserializePropertiesForObject: {value: function(object, properties, checkSerializableAttribute) { + if (checkSerializableAttribute) { + for (var key in properties) { + if (!Montage.getPropertyAttribute(object, key, "serializable")) { + if (Object.getPropertyDescriptor(object, key)) { + console.warn("Unserializable property \"" + key + "\" found in the serialization of " + (object._montage_metadata ? object._montage_metadata.objectName : object) + " (" + (this._origin || window.location) + ")"); + } else { + console.warn("Nonexistent (and therefore unserializable) property \"" + key + "\" found in the serialization of " + (object._montage_metadata ? object._montage_metadata.objectName : object) + " (" + (this._origin || window.location) + ")"); + } + }; + object[key] = properties[key]; + } + } else { + for (var key in properties) { + object[key] = properties[key]; + } } }}, @@ -760,7 +773,7 @@ var Deserializer = Montage.create(Montage, /** @lends module:montage/core/deseri desc._units = {}; self._customDeserialization(object, desc); } else { - self._deserializeProperties(object, desc.properties); + self._deserializeProperties(object, desc.properties, true); } } @@ -784,7 +797,7 @@ var Deserializer = Montage.create(Montage, /** @lends module:montage/core/deseri } else if ("@" in value) { type = "reference"; value = value["@"]; - } else if (typeof value["->"] === "object") { + } else if ("->" in value) { type = "function"; value = value["->"]; } else if ("." in value && Object.keys(value).length === 1) { @@ -1089,13 +1102,13 @@ var Deserializer = Montage.create(Montage, /** @lends module:montage/core/deseri /** @private */ - _deserializeProperties: {value: function(object, properties) { + _deserializeProperties: {value: function(object, properties, checkSerializableAttribute) { if (object.deserializeProperties) { this._pushContextObject(properties); object.deserializeProperties(this); this._popContextObject(); } else { - this.deserializePropertiesForObject(object, properties); + this.deserializePropertiesForObject(object, properties, checkSerializableAttribute); } }}, diff --git a/node_modules/montage/core/event/action-event-listener.js b/node_modules/montage/core/event/action-event-listener.js index 4fc75f64..c8981f1d 100755 --- a/node_modules/montage/core/event/action-event-listener.js +++ b/node_modules/montage/core/event/action-event-listener.js @@ -21,7 +21,8 @@ var ActionEventListener = exports.ActionEventListener = Montage.create(Montage, @default {Event handler} null */ handler: { - value: null + value: null, + serializable: true }, /** @@ -30,7 +31,8 @@ var ActionEventListener = exports.ActionEventListener = Montage.create(Montage, @default {Event handler} null */ action: { - value: null + value: null, + serializable: true }, /** diff --git a/node_modules/montage/core/event/binding.js b/node_modules/montage/core/event/binding.js index 2e226372..c31ee7f9 100755 --- a/node_modules/montage/core/event/binding.js +++ b/node_modules/montage/core/event/binding.js @@ -82,91 +82,57 @@ var PropertyChangeBindingListener = exports.PropertyChangeBindingListener = Obje this.deferredValueTarget = ""; } }, - handleChange: {value: function(event) { - var targetPropertyPath = this.targetPropertyPath, - target = this.target, - localNewValue = event.plus, - localPrevValue = event.minus, - localTarget = event.target, - boundObjectValue, - sourceObjectValue, - dotIndex, - nextPathComponent, - atSignIndex, - baseType, - bindingDescriptor, - bindingOrigin = this.bindingOrigin, - leftOriginated, - changeOriginPropertyPath = null, - exploredPath, - valueChanged; - - if (target !== bindingOrigin) { - //the left and the right are different objects; easy enough - leftOriginated = event.target === bindingOrigin; - } else { - //otherwise, they're the same object; time to try and figure out which "side" the event came from - // TODO this is a very weak check that relies on the bindingOrigin using a property and not a full propertyPath - leftOriginated = event.propertyName === this.bindingPropertyPath; - } - - if (leftOriginated) { - // This change event targeted the left side of the binding; try to push to the right side + handleChange:{ + value:function (notification) { + + var bindingOriginTriggeredChange, + // Left + bindingOrigin = this.bindingOrigin, + bindingOriginPropertyPath = this.bindingPropertyPath, + bindingOriginValue = bindingOrigin.getProperty(bindingOriginPropertyPath), + // Right + boundObject = this.target, + boundObjectPropertyPath = this.targetPropertyPath, + boundObjectValue; + + // Determine if binding triggered by change on bindingOrigin + if (boundObject !== bindingOrigin) { + // the origin and bound object are different objects; easy enough + bindingOriginTriggeredChange = notification.currentTarget === bindingOrigin; + } else { + // otherwise, if the objects are the same the propertyPaths must differ + bindingOriginTriggeredChange = notification.currentPropertyPath === bindingOriginPropertyPath; + } - if (!bindingOrigin.setProperty.changeEvent) { + if (bindingOriginTriggeredChange) { + // This change notification targeted the left side of the binding; try to push to the right side - sourceObjectValue = localNewValue; + // If this notification was triggered by the right-to-left value push; don't bother setting + // the value on the left side, that's where all this value changing started + // (The original right-to-left push installs this changeEvent key on the setProperty function) + if (bindingOrigin.setProperty.changeEvent) { + return; + } + // TODO should not assume revert is available if (this.bindingDescriptor.converter) { - sourceObjectValue = this.bindingDescriptor.converter.revert(sourceObjectValue); + bindingOriginValue = this.bindingDescriptor.converter.revert(bindingOriginValue); } - // If this event was triggered by the right-to-left- value push; don't bother setting - // the value on the left side, that's where all this value changing started - // (The original right-to-left push installs this changeEvent key on the setProperty function) if (this.bindingOriginValueDeferred === true || bindingOrigin._bindingsDisabled) { - this.deferredValue = sourceObjectValue; + this.deferredValue = bindingOriginValue; this.deferredValueTarget = "target"; } else { this.bindingOriginChangeTriggered = true; // Set the value on the RIGHT side now - this.target.setProperty(this.targetPropertyPath, sourceObjectValue); + boundObject.setProperty(boundObjectPropertyPath, bindingOriginValue); this.bindingOriginChangeTriggered = false; } - } - - } else if (!this.bindingOriginChangeTriggered) { - - // If we're handling the event at this point we know the right side triggered it, from somewhere inside the observed propertyPath - // the event target, which just changed, could be any of the objects along the path, but from here on we want to - // treat the event as "change@fullTargetPropertyPath" so adjust the event we have to reflect that - if (this.target && targetPropertyPath) { - event.target = target; - event.propertyPath = targetPropertyPath; - - event.plus = target.getProperty(targetPropertyPath); - - // If the newValue and the storedPreviousValue are the same, this was a mutation on that object - // we want to show the prevValue that came along from the event lest we point - // somebody a reference to the same array as the prevValue and newValue - if (!Array.isArray(this.previousTargetPropertyPathValue) && event.plus !== this.previousTargetPropertyPathValue) { - event.minus = this.previousTargetPropertyPathValue; - } - - } else { - // TODO I'm not sure when this would happen.. - event.target = this; - } - - // The binding listener detected some change along the property path it cared about - // make sure the event we "dispatch" has the full change@propertyPath eventType - event.type = this.targetPropertyPath; - //For bindings, start the right-to-left value push - if (event.target === this.target && this.bindingPropertyPath && bindingOrigin) { - //console.log("@ % @ % @ % @ % @ % Binding Worked!!"); + } else if (!this.bindingOriginChangeTriggered) { - boundObjectValue = event.plus; + // Start the right-to-left value push + boundObjectValue = boundObject.getProperty(boundObjectPropertyPath); if (this.bindingDescriptor.boundValueMutator) { boundObjectValue = this.bindingDescriptor.boundValueMutator(boundObjectValue); @@ -174,75 +140,23 @@ var PropertyChangeBindingListener = exports.PropertyChangeBindingListener = Obje boundObjectValue = this.bindingDescriptor.converter.convert(boundObjectValue); } - // If the the value about to be pushed over to the bindingOrigin is already there don't call the setter - valueChanged = boundObjectValue !== event.plus ? - (this.bindingOrigin.getProperty(this.bindingPropertyPath) !== boundObjectValue) : true; - - if (valueChanged) { + if (boundObjectValue !== bindingOriginValue) { if (this.bindingOriginValueDeferred === true || bindingOrigin._bindingsDisabled) { this.deferredValue = boundObjectValue; this.deferredValueTarget = "bound"; } else { - // Make the original event available to the setter - this.bindingOrigin.setProperty.changeEvent = event; + // Make the original notification available to the setter + bindingOrigin.setProperty.changeEvent = notification; // Set the value on the LEFT side now - this.bindingOrigin.setProperty(this.bindingPropertyPath, boundObjectValue); - this.bindingOrigin.setProperty.changeEvent = null; + bindingOrigin.setProperty(bindingOriginPropertyPath, boundObjectValue); + bindingOrigin.setProperty.changeEvent = null; } } - } - // Otherwise, there was probably a listener for a change at this path that was not a part of some binding - // so distribute the event to the original listener - // TODO this is not as full featured as the EventManager event distribution so it may differ, which is bad - else if (this.originalListener) { - if (this.originalListenerIsFunction) { - this.originalListener.call(this.target, event); - } else { - this.originalListener.handleEvent(event); - } - } - - // Update the stored value of the propertyPath - this.previousTargetPropertyPathValue = event.plus; - - // TODO I'm not exactly sure why this happens here, or really why it does in general - event.minus = localPrevValue; - event.plus = localNewValue; - event.target = localTarget; - if (localPrevValue) { - - // Determine where along the property path the change originated from so we know how to build the path - // to stop observing on things that were removed - //TODO extract this into a "obj.getPathOfObjectAlongPropertyPath" method or something with proper tests - exploredPath = ""; - this.target.getProperty(this.targetPropertyPath, null, null, function(value, currentPathComponent, result) { - - if (changeOriginPropertyPath) { - return; - } - - exploredPath += "." + currentPathComponent; - - if (result === event.target) { - changeOriginPropertyPath = exploredPath.replace(/^\./, ""); - } - }); + // Update the stored value of the propertyPath + this.previousTargetPropertyPathValue = boundObjectValue; } } - - targetPropertyPath = null; - target = null; - localNewValue = null; - localPrevValue = null; - localTarget = null; - dotIndex = null; - nextPathComponent = null; - atSignIndex = null; - baseType = null; - bindingDescriptor = null; - bindingOrigin = null; - } } }); @@ -334,7 +248,7 @@ var BindingDescriptor = exports.BindingDescriptor = Montage.create(Montage, /** var serialization = {}; serializer.addObjectReference(this.boundObject); - serialization[this.oneway ? "<-" : "<<->"] = "@" + serializer.getObjectLabel(this.boundObject) + "." + this.boundObjectPropertyPath; + serialization[this.oneway ? "<-" : "<->"] = "@" + serializer.getObjectLabel(this.boundObject) + "." + this.boundObjectPropertyPath; serialization.deferred = this.deferred; serialization.converter = this.converter; @@ -356,26 +270,26 @@ Deserializer.defineDeserializationUnit("bindings", function(object, bindings, de dotIndex; if (!("boundObject" in binding)) { - var targetPath = binding["<-"] || binding["->"] || binding["<->>"] || binding["<<->"]; + var targetPath = binding["<-"] || binding["<->"] || binding["<<->"]; - if (targetPath[0] !== "@") { - logger.error("Invalid binding syntax '" + targetPath + "', should be in the form of '@label.path'."); - throw "Invalid binding syntax '" + targetPath + "'"; + if ("<<->" in binding) { + console.warn("WARNING: <<-> in bindings is deprectated, use <-> only, please update now.") } - if ("->" in binding || "<->>" in binding) { - binding.boundObject = object; - binding.boundObjectPropertyPath = sourcePath; - dotIndex = targetPath.indexOf("."); - object = deserializer.getObjectByLabel(targetPath.slice(1, dotIndex)); - sourcePath = targetPath.slice(dotIndex+1); + if (targetPath) { + if (targetPath[0] !== "@") { + logger.error("Invalid binding syntax '" + targetPath + "', should be in the form of '@label.path'."); + throw "Invalid binding syntax '" + targetPath + "'"; + } } else { - dotIndex = targetPath.indexOf("."); - binding.boundObject = deserializer.getObjectByLabel(targetPath.slice(1, dotIndex)); - binding.boundObjectPropertyPath = targetPath.slice(dotIndex+1); + logger.error("Invalid binding syntax '" + JSON.stringify(binding) + "'."); + throw "Invalid binding syntax '" + JSON.stringify(binding) + "'"; } - if ("<-" in binding || "->" in binding) { + dotIndex = targetPath.indexOf("."); + binding.boundObject = deserializer.getObjectByLabel(targetPath.slice(1, dotIndex)); + binding.boundObjectPropertyPath = targetPath.slice(dotIndex+1); + if ("<-" in binding) { binding.oneway = true; } } diff --git a/node_modules/montage/core/extras/object.js b/node_modules/montage/core/extras/object.js index 0281240f..d20b57fa 100644 --- a/node_modules/montage/core/extras/object.js +++ b/node_modules/montage/core/extras/object.js @@ -113,42 +113,27 @@ Object.defineProperty(Object.prototype, "setProperty", { // TODO clean up some of the duplicated code here if (lastObjectAtPath && Array.isArray(lastObjectAtPath)) { - if (lastObjectAtPath !== value) { - // if the value does not match the object described by this propertyPath; set it as the new value - - if (Array.isArray(setObject)) { - // If the setObject is an array itself; splice (typically called by set) to trigger bindings, do it here to save time - propertyToSetOnArray = parseInt(aPropertyPath, 10); - if (!isNaN(propertyToSetOnArray)) { - if (setObject.length < propertyToSetOnArray) { - // TODO while I could set the value here I'm setting null and letting the splice, - // which we need to do anyway to trigger bindings, do the actual setting - setObject[propertyToSetOnArray] = null; - } - - setObject.splice(propertyToSetOnArray, 1, value); - - } else { - setObject[aPropertyPath] = value; + + if (Array.isArray(setObject)) { + // If the setObject is an array itself; splice (typically called by set) to trigger bindings, do it here to save time + propertyToSetOnArray = parseInt(aPropertyPath, 10); + if (!isNaN(propertyToSetOnArray)) { + if (setObject.length < propertyToSetOnArray) { + // TODO while I could set the value here I'm setting null and letting the splice, + // which we need to do anyway to trigger bindings, do the actual setting + setObject[propertyToSetOnArray] = null; } + setObject.splice(propertyToSetOnArray, 1, value); + } else { setObject[aPropertyPath] = value; } } else { - // Otherwise, they are the same object, a mutation event probably happened - - // If the object at the property we're "setting" is itself an array, see if there was an event passed along - // as part of a change and whether we need to call the setObject's changeProperty method - var changeEvent = this.setProperty.changeEvent, modify; - - // For these mutation/addition/removal events, use the 'modify' attribute of this property's descriptor - if (changeEvent && (changeEvent.currentTarget.getProperty(changeEvent.currentPropertyPath) === lastObjectAtPath) && - (modify = M.Montage.getPropertyAttribute(setObject, aPropertyPath, MODIFY))) { - modify.call(setObject, changeEvent.type, changeEvent.newValue, changeEvent.prevValue); - } + setObject[aPropertyPath] = value; } + } else if (Array.isArray(setObject)) { // If the setObject is an array itself; splice (typically called by set) to trigger bindings, do it here to save time propertyToSetOnArray = parseInt(aPropertyPath, 10); -- cgit v1.2.3 From 5c976cc4bbaa40315e77e6889b43fc7d7156e26f Mon Sep 17 00:00:00 2001 From: Valerio Virgillito Date: Tue, 12 Jun 2012 22:36:25 -0700 Subject: disabling the warnings Signed-off-by: Valerio Virgillito --- node_modules/montage/core/deserializer.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'node_modules/montage/core') diff --git a/node_modules/montage/core/deserializer.js b/node_modules/montage/core/deserializer.js index 3c0aa049..86cdc560 100755 --- a/node_modules/montage/core/deserializer.js +++ b/node_modules/montage/core/deserializer.js @@ -246,7 +246,7 @@ var Deserializer = Montage.create(Montage, /** @lends module:montage/core/deseri object = stack[ix-1], desc = stack[ix]; - this._deserializeProperties(object, desc.properties, true); + this._deserializeProperties(object, desc.properties, false); } }, @@ -773,7 +773,7 @@ var Deserializer = Montage.create(Montage, /** @lends module:montage/core/deseri desc._units = {}; self._customDeserialization(object, desc); } else { - self._deserializeProperties(object, desc.properties, true); + self._deserializeProperties(object, desc.properties, false); } } -- cgit v1.2.3