Plato on Github
Report Home
node_modules/wire/lib/WireProxy.js
Maintainability
71.15
Lines of code
198
Difficulty
34.14
Estimated Errors
0.75
Function weight
By Complexity
By SLOC
/** @license MIT License (c) copyright B Cavalier & J Hann */ /** * Licensed under the MIT License at: * http://www.opensource.org/licenses/mit-license.php */ (function(define){ 'use strict'; define(function(require) { var object, array; object = require('./object'); array = require('./array'); /** * A base proxy for all components that wire creates. It allows wire's * internals and plugins to work with components using a standard interface. * WireProxy instances may be extended to specialize the behavior of the * interface for a particular type of component. For example, there is a * specialized version for DOM Nodes. * @param {*} target value to be proxied * @constructor */ function WireProxy(target) { // read-only target Object.defineProperty(this, 'target', { value: target }); } WireProxy.prototype = { /** * Get the value of the named property. Sub-types should * override to get properties from their targets in whatever * specialized way is necessary. * @param {string} property * @returns {*} the value or undefined */ get: function (property) { return this.target[property]; }, /** * Set the value of the named property. Sub-types should * override to set properties on their targets in whatever * specialized way is necessary. * @param {string} property * @param {*} value * @returns {*} */ set: function (property, value) { this.target[property] = value; return value; }, /** * Invoke the method, with the supplied args, on the proxy's * target. Sub-types should override to invoke methods their * targets in whatever specialized way is necessary. * @param {string|function} method name of method to invoke or * a function to call using proxy's target as the thisArg * @param {array} args arguments to pass to method * @returns {*} the method's return value */ invoke: function (method, args) { var target = this.target; if (typeof method === 'string') { method = target[method]; } return method.apply(target, array.fromArguments(args)); }, /** * Add an aspect to the proxy's target. Sub-types should * override to add aspects in whatever specialized way is * necessary. * @param {String|Array|RegExp|Function} pointcut * expression matching methods to be advised * @param {Object} aspect aspect to add * @returns {{remove:function}} object with remove() that * will remove the aspect. */ advise: function(pointcut, aspect) { /*jshint unused:false*/ throw new TypeError('Advice not supported on component type: ' + this.target); }, /** * Destroy the proxy's target. Sub-types should override * to destroy their targets in whatever specialized way is * necessary. */ destroy: function() {}, /** * Attempt to clone this proxy's target. Sub-types should * override to clone their targets in whatever specialized * way is necessary. * @param {object|array|function} thing thing to clone * @param {object} options * @param {boolean} options.deep if true and thing is an Array, try to deep clone its contents * @param {boolean} options.inherited if true and thing is an object, clone inherited and own properties. * @returns {*} */ clone: function (options) { // don't try to clone a primitive var target = this.target; if (typeof target == 'function') { // cloneThing doesn't clone functions, so clone here: return target.bind(); } else if (typeof target != 'object') { return target; } return cloneThing(target, options || {}); } }; WireProxy.isProxy = isProxy; WireProxy.getTarget = getTarget; WireProxy.extend = extendProxy; return WireProxy; /** * Returns a new WireProxy, whose prototype is proxy, with extensions * as own properties. This is the "official" way to extend the functionality * of an existing WireProxy. * @param {WireProxy} proxy proxy to extend * @param extensions * @returns {*} */ function extendProxy(proxy, extensions) { if(!isProxy(proxy)) { throw new Error('Cannot extend non-WireProxy'); } return object.extend(proxy, extensions); } /** * Returns true if it is a WireProxy * @param {*} it * @returns {boolean} */ function isProxy(it) { return it instanceof WireProxy; } /** * If it is a WireProxy (see isProxy), returns it's target. Otherwise, * returns it; * @param {*} it * @returns {*} */ function getTarget(it) { return isProxy(it) ? it.target : it; } /** * Try to clone thing, which can be an object, Array, or Function * @param {object|array|function} thing thing to clone * @param {object} options * @param {boolean} options.deep if true and thing is an Array, try to deep clone its contents * @param {boolean} options.inherited if true and thing is an object, clone inherited and own properties. * @returns {array|object|function} cloned thing */ function cloneThing (thing, options) { var deep, inherited, clone, prop; deep = options.deep; inherited = options.inherited; // Note: this filters out primitive properties and methods if (typeof thing != 'object') { return thing; } else if (thing instanceof Date) { return new Date(thing.getTime()); } else if (thing instanceof RegExp) { return new RegExp(thing); } else if (Array.isArray(thing)) { return deep ? thing.map(function (i) { return cloneThing(i, options); }) : thing.slice(); } else { clone = thing.constructor ? new thing.constructor() : {}; for (prop in thing) { if (inherited || object.hasOwn(thing, prop)) { clone[prop] = deep ? cloneThing(thing[prop], options) : thing[prop]; } } return clone; } } }); })(typeof define == 'function' && define.amd ? define : function(factory) { module.exports = factory(require); } );