New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

can-reflect

Package Overview
Dependencies
Maintainers
3
Versions
86
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

can-reflect - npm Package Compare versions

Comparing version 1.0.0-pre.2 to 1.0.0-pre.3

1

can-reflect.md
@page can-reflect
@parent can-infrastructure

@@ -3,0 +4,0 @@ # can-reflect

2

package.json
{
"name": "can-reflect",
"version": "1.0.0-pre.2",
"version": "1.0.0-pre.3",
"description": "reflection on unknown data types",

@@ -5,0 +5,0 @@ "homepage": "http://canjs.com",

var canSymbol = require("can-symbol");
var typeReflections = require("../type/type");
/**
* @module can-reflect/call Call
* @parent can-reflect
*
* @description a set of functions that deal with callable objects. Generally these are functions, but other
* object types can implement these to make them callable with [can-reflect]
*/
module.exports = {
/**
* @function {function(...), Object, ...} can-reflect/call.call call
* @parent can-reflect/call
* @description Call a callable, with a context object and parameters
*
* @signature `call(func, context, ...rest)`
*
* Call the callable `func` as if it were a function, bound to `context` and with any additional parameters
* occurring after `context` set to the positional parameters.
*
* Note that `func` *must* either be natively callable, implement [can-symbol/symbols/apply @@@@can.apply],
* or have a callable `apply` property to work with `canReflect.call`
*
* ```
* var compute = canCompute("foo");
*
* canReflect.call(compute, null, "bar");
* canReflect.call(compute, null); // -> "bar"
* ```
*
* @param {function(...)} func the function to call with the supplied arguments
* @param {Object} context the context object to set as `this` on the function call
* @param {*} rest any arguments after `context` will be passed to the function call
* @return {*} return types and values are determined by the call to `func`
*/
call: function(func, context){

@@ -14,2 +46,27 @@ var args = [].slice.call(arguments, 2);

},
/**
* @function {function(...), Object, ...} can-reflect/call.apply apply
* @parent can-reflect/call
* @description Call a callable, with a context object and a list of parameters
*
* @signature `apply(func, context, args)`
*
* Call the callable `func` as if it were a function, bound to `context` and with any additional parameters
* contained in the Array-like `args`
*
* Note that `func` *must* either be natively callable, implement [can-symbol/symbols/apply @@@@can.apply],
* or have a callable `apply` property to work with `canReflect.apply`
*
* ```
* var compute = canCompute("foo");
*
* canReflect.apply(compute, null, ["bar"]);
* canReflect.apply(compute, null, []); // -> "bar"
* ```
*
* @param {function(...)} func the function to call
* @param {Object} context the context object to set as `this` on the function call
* @param {*} args arguments to be passed to the function call
* @return {*} return types and values are determined by the call to `func`
*/
apply: function(func, context, args){

@@ -23,2 +80,23 @@ var apply = func[canSymbol.for("can.apply")];

},
/**
* @function {function(...), ...} can-reflect/call.new new
* @parent can-reflect/call
* @description Construct a new instance of a callable constructor
*
* @signature `new(func, ...rest)`
*
* Call the callable `func` as if it were a function, bound to a new instance of `func`, and with any additional
* parameters occurring after `func` set to the positional parameters.
*
* Note that `func` *must* either implement [can-symbol/symbols/new @@@@can.new],
* or have a callable `apply` property *and* a prototype to work with `canReflect.new`
*
* ```
* canReflect.new(DefineList, ["foo"]); // -> ["foo"]<DefineList>
* ```
*
* @param {function(...)} func a constructor
* @param {*} rest arguments to be passed to the constructor
* @return {Object} if `func` returns an Object, that returned Object; otherwise a new instance of `func`
*/
"new": function(func){

@@ -25,0 +103,0 @@ var args = [].slice.call(arguments, 1);

@@ -9,3 +9,29 @@ var canSymbol = require("can-symbol");

/**
* @module can-reflect/get-set Get/Set
* @parent can-reflect
* @description Reflection functions for getters and setters on MapLikes, ListLikes, and ValueLikes.
*/
var reflections = {
/**
* @function {Object, String, *} can-reflect/get-set.setKeyValue setKeyValue
* @parent can-reflect/get-set
* @description Set the value of a named property on a MapLike object.
*
* @signature `setKeyValue(obj, key, value)`
*
* Set the property on Map-like `obj`, identified by the String or Symbol value `key`, to the value `value`.
* The default behavior can be overridden on `obj` by implementing [can-symbol/symbols/setKeyValue @@@@can.setKeyValue],
* otherwise native named property access is used for string keys, and `Object.defineProperty` is used to set symbols.
*
* ```
* var foo = new DefineMap({ bar: "baz" });
*
* canReflect.setKeyValue(foo, "bar", "quux");
* foo[bar]; // -> "quux"
* ```
* @param {Object} obj the object to set on
* @param {String} key the key for the property to set
* @param {*} value the value to set on the object
*/
setKeyValue: function(obj, key, value){

@@ -31,2 +57,22 @@ if(typeof key === "symbol") {

},
/**
* @function {Object, String} can-reflect/get-set.getKeyValue getKeyValue
* @parent can-reflect/get-set
* @description Get the value of a named property on a MapLike object.
*
* @signature `getKeyValue(obj, key)`
*
* Retrieve the property on Map-like `obj` identified by the String or Symbol value `key`. The default behavior
* can be overridden on `obj` by implementing [can-symbol/symbols/getKeyValue @@@@can.getKeyValue],
* otherwise native named property access is used.
*
* ```
* var foo = new DefineMap({ bar: "baz" });
*
* canReflect.getKeyValue(foo, "bar"); // -> "baz"
* ```
*
* @param {Object} obj the object to get from
* @param {String} key the key of the property to get
*/
getKeyValue: function(obj, key) {

@@ -39,2 +85,31 @@ var getKeyValue = obj[getKeyValueSymbol];

},
/**
* @function {Object, String} can-reflect/get-set.deleteKeyValue deleteKeyValue
* @parent can-reflect/get-set
* @description Delete a named property from a MapLike object.
*
* @signature `deleteKeyValue(obj, key)`
*
* Remove the property identified by the String or Symbol `key` from the Map-like object `obj`, if possible.
* Property definitions may interfere with deleting key values; the behavior on `obj` if `obj[key]` cannot
* be deleted is undefined. The default use of the native `delete` keyword can be overridden by `obj` if it
* implements [can-symbol/symbols/deleteKeyValue @@@@can.deleteKeyValue].
*
* ```
* var foo = new DefineMap({ bar: "baz" });
* var quux = new CanMap({ thud: "jeek" });
*
* canReflect.deleteKeyValue(foo, "bar");
* canReflect.deleteKeyValue(quux, "thud");
*
* "bar" in foo; // -> true -- DefineMaps use property defs which cannot be un-defined
* foo.bar // -> undefined -- but set values to undefined when deleting
*
* "thud" in quux; // -> false
* quux.thud; // -> undefined
* ```
*
* @param {Object} obj the object to delete on
* @param {String} key the key for the property to delete
*/
deleteKeyValue: function(obj, key) {

@@ -47,2 +122,25 @@ var deleteKeyValue = obj[canSymbol.for("can.deleteKeyValue")];

},
/**
* @function {Object} can-reflect/get-set.getValue getValue
* @parent can-reflect/get-set
* @description Get the value of an object with a gettable value
*
* @signature `getValue(obj)`
*
* Return the value of the Value-like object `obj`. Unless `obj` implements
* [can-symbol/symbols/getValue @@@@can.getValue], the result of `getValue` on
* `obj` will always be `obj`. Observable Map-like objects may want to implement
* `@@@@can.getValue` to return non-observable or plain representations of themselves.
*
* ```
* var compute = canCompute("foo");
* var primitive = "bar";
*
* canReflect.getValue(compute); // -> "foo"
* canReflect.getValue(primitive); // -> "bar"
* ```
*
* @param {Object} obj the object to get from
* @return {*} the value of the object via `@@can.getValue`, or the value itself.
*/
getValue: function(value){

@@ -58,2 +156,27 @@ if(typeReflections.isPrimitive(value)) {

},
/**
* @function {Object, *} can-reflect/get-set.setValue setValue
* @parent can-reflect/get-set
* @description Set the value of a mutable object.
*
* @signature `setValue(obj, value)`
*
* Set the value of a Value-like object `obj` to the value `value`. `obj` *must* implement
* [can-symbol/symbols/setValue @@@@can.setValue] to be used with `canReflect.setValue`.
* Map-like objects may want to implement `@@@@can.setValue` to merge objects of properties
* into themselves.
*
* ```
* var compute = canCompute("foo");
* var plain = {};
*
* canReflect.setValue(compute, "bar");
* compute(); // -> bar
*
* canReflect.setValue(plain, { quux: "thud" }); // throws "can-reflect.setValue - Can not set value."
* ```
*
* @param {Object} obj the object to set on
* @param {*} value the value to set for the object
*/
setValue: function(item, value){

@@ -68,6 +191,18 @@ var setValue = item && item[setValueSymbol];

};
/**
* @function {Object, String} can-reflect/get-set.get get
* @description an alias for [can-reflect/get-set.getKeyValue getKeyValue]
*/
reflections.get = reflections.getKeyValue;
/**
* @function {Object, String} can-reflect/get-set.set set
* @description an alias for [can-reflect/get-set.setKeyValue setKeyValue]
*/
reflections.set = reflections.setKeyValue;
reflections.delete = reflections.deleteKeyValue;
/**
* @function {Object, String} can-reflect/get-set.delete delete
* @description an alias for [can-reflect/get-set.deleteKeyValue deleteKeyValue]
*/
reflections["delete"] = reflections.deleteKeyValue;
module.exports = reflections;

@@ -25,16 +25,219 @@ var canSymbol = require("can-symbol");

/**
* @module can-reflect/observe Observe
* @parent can-reflect
*
* The `Observe` suite of reflections covers event binding for key values on observable MapLike objects, and for
* the values of observable ValueLike objects.
*/
module.exports = {
// KEY
/**
* @function {Object, String, function(*, *)} can-reflect/observe.onKeyValue onKeyValue
* @parent can-reflect/observe
* @description Register an event handler on a MapLike object, based on a key change
*
* @signature `onKeyValue(obj, key, handler)`
*
* Register a handler on the Map-like object `obj` to trigger when the property key `key` changes.
* `obj` *must* implement [can-symbol/symbols/onKeyValue @@@@can.onKeyValue] to be compatible with
* can-reflect.onKeyValue. The function passed as `handler` will receive the new value of the property
* as the first argument, and the previous value of the property as the second argument.
*
* ```
* var obj = new DefineMap({ foo: "bar" });
* canReflect.onKeyValue(obj, "foo", function(newVal, oldVal) {
* console.log("foo is now", newVal, ", was", oldVal);
* });
*
* obj.foo = "baz"; // -> logs "foo is now baz , was bar"
* ```
*
* @param {Object} obj an observable MapLike that can listen to changes in named properties.
* @param {String} key the key to listen to
* @param {function(*, *)} handler a callback function that recieves the new value
*/
onKeyValue: makeFallback("can.onKeyValue", "onEvent"),
/**
* @function {Object, String, function(*)} can-reflect/observe.offKeyValue offKeyValue
* @parent can-reflect/observe
* @description Unregister an event handler on a MapLike object, based on a key change
*
* @signature `offKeyValue(obj, key, handler)`
*
* Unregister a handler from the Map-like object `obj` that had previously been registered with
* [can-reflect/observe.onKeyValue onKeyValue]. The function passed as `handler` will no longer be called
* when the value of `key` on `obj` changes.
*
* ```
* var obj = new DefineMap({ foo: "bar" });
* var handler = function(newVal, oldVal) {
* console.log("foo is now", newVal, ", was", oldVal);
* };
*
* canReflect.onKeyValue(obj, "foo", handler);
* canReflect.offKeyValue(obj, "foo", handler);
*
* obj.foo = "baz"; // -> nothing is logged
* ```
*
* @param {Object} obj an observable MapLike that can listen to changes in named properties.
* @param {String} key the key to stop listening to
* @param {function(*)} handler the callback function that should be removed from the event handlers for `key`
*/
offKeyValue: makeFallback("can.offKeyValue","offEvent"),
/**
* @function {Object, function(Array)} can-reflect/observe.onKeys onKeys
* @parent can-reflect/observe
* @description Register an event handler on a MapLike object, triggered on the key set changing
*
* @signature `onKeys(obj, handler)`
*
* Register an event handler on the Map-like object `obj` to trigger when `obj`'s keyset changes.
* `obj` *must* implement [can-symbol/symbols/onKeys @@@@can.onKeys] to be compatible with
* can-reflect.onKeys. The function passed as `handler` will receive an Array of object diffs (see
* [can-util/js/diff-object/diff-object diffObject] for the format) as its one argument.
*
* ```
* var obj = new DefineMap({ foo: "bar" });
* canReflect.onKeys(obj, function(diffs) {
* console.log(diffs);
* });
*
* obj.set("baz", "quux"); // -> logs '[{"property": "baz", "type": "add", "value": "quux"}]'
* ```
*
* @param {Object} obj an observable MapLike that can listen to changes in named properties.
* @param {function(Array)} handler the callback function to receive the diffs in the key set
*/
// any key change (diff would normally happen)
onKeys: makeErrorIfMissing("can.onKeys","can-reflect: can not observe an onKeys event"),
/**
* @function {Object, function(Array)} can-reflect/observe.onKeysAdded onKeysAdded
* @parent can-reflect/observe
* @description Register an event handler on a MapLike object, triggered on new keys being added.
*
* @signature `onKeysAdded(obj, handler)`
*
* Register an event handler on the Map-like object `obj` to trigger when a new key or keys are set on
* `obj`. `obj` *must* implement [can-symbol/symbols/onKeysAdded @@@@can.onKeysAdded] to be compatible with
* can-reflect.onKeysAdded. The function passed as `handler` will receive an Array of Strings as its one
* argument.
*
* ```
* var obj = new DefineMap({ foo: "bar" });
* canReflect.onKeysAded(obj, function(newKeys) {
* console.log(newKeys);
* });
*
* foo.set("baz", "quux"); // -> logs '["baz"]'
* ```
*
* @param {Object} obj an observable MapLike that can listen to changes in named properties.
* @param {function(Array)} handler the callback function to receive the array of added keys
*/
// keys added at a certain point {key: 1}, index
onKeysAdded: makeErrorIfMissing("can.onKeysAdded","can-reflect: can not observe an onKeysAdded event"),
/**
* @function {Object, function(Array)} can-reflect/observe.onKeysRemoved onKeysRemoved
* @parent can-reflect/observe
* @description Register an event handler on a MapLike object, triggered on keys being deleted.
*
* @signature `onKeysRemoved(obj, handler)`
*
* Register an event handler on the Map-like object `obj` to trigger when a key or keys are removed from
* `obj`'s keyset. `obj` *must* implement [can-symbol/symbols/onKeysRemoved @@@@can.onKeysRemoved] to be
* compatible with can-reflect.onKeysAdded. The function passed as `handler` will receive an Array of
* Strings as its one argument.
*
* ```
* var obj = new CanMap({ foo: "bar" });
* canReflect.onKeys(obj, function(diffs) {
* console.log(JSON.stringify(diffs));
* });
*
* foo.removeAttr("foo"); // -> logs '["foo"]'
* ```
*
* @param {Object} obj an observable MapLike that can listen to changes in named properties.
* @param {function(Array)} handler the callback function to receive the array of removed keys
*/
onKeysRemoved: makeErrorIfMissing("can.onKeysRemoved","can-reflect: can not unobserve an onKeysRemoved event"),
/**
* @function {Object, String} can-reflect/observe.getKeyDependencies getKeyDependencies
* @parent can-reflect/observe
* @description Return the observable objects that compute to the value of a named property on an object
*
* @signature `getKeyDependencies(obj, key)`
*
* Return the observable objects that provide input values to generate the computed value of the
* property `key` on Map-like object `obj`. If `key` does not have dependencies on `obj`, returns `undefined`.
* Otherwise returns an object with up to two keys: `keyDependencies` is a [can-util/js/cid-map/cid-map CIDMap] that
* maps each Map-like object providing keyed values to an Array of the relevant keys; `valueDependencies` is a
* [can-util/js/cid-set/cid-set CIDSet] that contains all Value-like dependencies providing their own values.
*
* `obj` *must* implement [can-symbol/symbols/getKeyDependencies @@@@can.getKeyDependencies] to work with
* `canReflect.getKeyDependencies`.
*
*
* ```
* var foo = new DefineMap({ "bar": "baz" })
* var obj = new (DefineMap.extend({
* baz: {
* get: function() {
* return foo.bar;
* }
* }
* }))();
*
* canReflect.getKeyDependencies(obj, "baz"); // -> { valueDependencies: CIDSet }
* ```
*
* @param {Object} obj the object to check for key dependencies
* @param {String} key the key on the object to check
* @return {Object} the observable values that this keyed value depends on
*/
getKeyDependencies: makeErrorIfMissing("can.getKeyDependencies","can-reflect: can not determine dependencies"),
/**
* @function {Object, String} can-reflect/observe.keyHasDependencies keyHasDependencies
* @parent can-reflect/observe
* @description Determine whether the value for a named property on an object is bound to other events
*
* @signature `keyHasDependencies(obj, key)`
*
* Returns `true` if the computed value of the property `key` on Map-like object `obj` derives from other values.
* Returns `false` if `key` is computed on `obj` but does not have dependencies on other objects. If `key` is not
* a computed value on `obj`, returns `undefined`.
*
* `obj` *must* implement [can-symbol/symbols/keyHasDependencies @@@@can.keyHasDependencies] to work with
* `canReflect.keyHasDependencies`.
*
* ```
* var foo = new DefineMap({ "bar": "baz" })
* var obj = new (DefineMap.extend({
* baz: {
* get: function() {
* return foo.bar;
* }
* },
* quux: {
* get: function() {
* return "thud";
* }
* }
* }))();
*
* canReflect.keyHasDependencies(obj, "baz"); // -> true
* canReflect.keyHasDependencies(obj, "quux"); // -> false
* canReflect.keyHasDependencies(foo, "bar"); // -> undefined
* ```
*
* @param {Object} obj the object to check for key dependencies
* @param {String} key the key on the object to check
* @return {Boolean} `true` if there are other objects that may update the keyed value; `false` otherwise
*
*/
// TODO: use getKeyDeps once we know what that needs to look like

@@ -44,11 +247,155 @@ keyHasDependencies: makeErrorIfMissing("can.keyHasDependencies","can-reflect: can not determine if this has key dependencies"),

// VALUE
/**
* @function {Object, function(*)} can-reflect/observe.onValue onValue
* @parent can-reflect/observe
* @description Register an event handler on an observable ValueLike object, based on a change in its value
*
* @signature `onValue(handler)`
*
* Register an event handler on the Value-like object `obj` to trigger when its value changes.
* `obj` *must* implement [can-symbol/symbols/onValue @@@@can.onValue] to be compatible with
* can-reflect.onKeyValue. The function passed as `handler` will receive the new value of `obj`
* as the first argument, and the previous value of `obj` as the second argument.
*
* ```
* var obj = canCompute("foo");
* canReflect.onValue(obj, function(newVal, oldVal) {
* console.log("compute is now", newVal, ", was", oldVal);
* });
*
* obj("bar"); // -> logs "compute is now bar , was foo"
* ```
*
* @param {*} obj any object implementing @@can.onValue
* @param {function(*, *)} handler a callback function that receives the new and old values
*/
onValue: makeErrorIfMissing("can.onValue","can-reflect: can not observe value change"),
/**
* @function {Object, function(*)} can-reflect/observe.offValue offValue
* @parent can-reflect/observe
* @description Unregister an value change handler from an observable ValueLike object
*
* @signature `offValue(handler)`
*
* Unregister an event handler from the Value-like object `obj` that had previously been registered with
* [can-reflect/observe.onValue onValue]. The function passed as `handler` will no longer be called
* when the value of `obj` changes.
*
* ```
* var obj = canCompute( "foo" );
* var handler = function(newVal, oldVal) {
* console.log("compute is now", newVal, ", was", oldVal);
* };
*
* canReflect.onKeyValue(obj, handler);
* canReflect.offKeyValue(obj, handler);
*
* obj("baz"); // -> nothing is logged
* ```
*
* @param {*} obj
* @param {function(*)} handler
*/
offValue: makeErrorIfMissing("can.offValue","can-reflect: can not unobserve value change"),
/**
* @function {Object} can-reflect/observe.getValueDependencies getValueDependencies
* @parent can-reflect/observe
* @description Return all the events that bind to the value of an observable, Value-like object
*
* @signature `getValueDependencies(obj)`
*
* Return the observable objects that provide input values to generate the computed value of the
* Value-like object `obj`. If `obj` does not have dependencies, returns `undefined`.
* Otherwise returns an object with up to two keys: `keyDependencies` is a [can-util/js/cid-map/cid-map CIDMap] that
* maps each Map-like object providing keyed values to an Array of the relevant keys; `valueDependencies` is a
* [can-util/js/cid-set/cid-set CIDSet] that contains all Value-like dependencies providing their own values.
*
* `obj` *must* implement [can-symbol/symbols/getValueDependencies @@@@can.getValueDependencies] to work with
* `canReflect.getValueDependencies`.
*
*
* ```
* var foo = new DefineMap({ "bar": "baz" })
* var obj = canCompute(function() {
* return foo.bar;
* });
*
* canReflect.getValueDependencies(obj); // -> { valueDependencies: CIDSet } because `obj` is internally backed by
* a [can-observation]
* ```
*
* @param {Object} obj the object to check for value dependencies
* @return {Object} the observable objects that `obj`'s value depends on
*
*/
getValueDependencies: makeErrorIfMissing("can.getValueDependencies","can-reflect: can not determine dependencies"),
/**
* @function {Object} can-reflect/observe.valueHasDependencies valueHasDependencies
* @parent can-reflect/observe
* @description Determine whether the value of an observable object is bound to other events
*
* @signature `valueHasDependencies(obj)`
*
* Returns `true` if the computed value of the Value-like object `obj` derives from other values.
* Returns `false` if `obj` is computed but does not have dependencies on other objects. If `obj` is not
* a computed value, returns `undefined`.
*
* `obj` *must* implement [can-symbol/symbols/valueHasDependencies @@@@can.valueHasDependencies] to work with
* `canReflect.valueHasDependencies`.
*
* ```
* var foo = canCompute( "bar" );
* var baz = canCompute(function() {
* return foo();
* });
* var quux = "thud";
* var jeek = canCompute(function(plonk) {
* if(argument.length) {
* quux = plonk;
* }
* return quux;
* });
*
* canReflect.valueHasDependencies(baz); // -> true
* canReflect.valueHasDependencies(jeek); // -> false
* canReflect.valueHasDependencies(foo); // -> undefined
* ```
*
* @param {Object} obj the object to check for dependencies
* @return {Boolean} `true` if there are other dependencies that may update the object's value; `false` otherwise
*
*/
// TODO: use getValueDeps once we know what that needs to look like
valueHasDependencies: makeErrorIfMissing("can.valueHasDependencies","can-reflect: can not determine if value has dependencies"),
// EVENT
/**
* @function {Object, String, function(*)} can-reflect/observe.onEvent onEvent
* @parent can-reflect/observe
* @description Register a named event handler on an observable object
*
* @signature `onEvent(obj, eventName, callback)`
*
*
* Register an event handler on the object `obj` to trigger when the event `eventName` is dispatched.
* `obj` *must* implement [can-symbol/symbols/onKeyValue @@@@can.onEvent] or `.addEventListener()` to be compatible
* with can-reflect.onKeyValue. The function passed as `callback` will receive the event descriptor as the first
* argument, and any data passed to the event dispatch as subsequent arguments.
*
* ```
* var obj = new DefineMap({ foo: "bar" });
* canReflect.onEvent(obj, "foo", function(ev, newVal, oldVal) {
* console.log("foo is now", newVal, ", was", oldVal);
* });
*
* canEvent.dispatch.call(obj, "foo", ["baz", "quux"]); // -> logs "foo is now baz , was quux"
* ```
*
* @param {Object} obj the object to bind a new event handler to
* @param {String} eventName the name of the event to bind the handler to
* @param {function(*)} callback the handler function to bind to the event
*/
onEvent: function(obj, eventName, callback){

@@ -64,2 +411,29 @@ if(obj) {

},
/**
* @function {Object, String, function(*)} can-reflect/observe.offValue offEvent
* @parent can-reflect/observe
* @description Unregister an event handler on a MapLike object, based on a key change
*
* @signature `offKeyValue(obj, eventName, callback)`
*
* Unregister an event handler from the object `obj` that had previously been registered with
* [can-reflect/observe.onEvent onEvent]. The function passed as `callback` will no longer be called
* when the event named `eventName` is dispatched on `obj`.
*
* ```
* var obj = new DefineMap({ foo: "bar" });
* var handler = function(ev, newVal, oldVal) {
* console.log("foo is now", newVal, ", was", oldVal);
* };
*
* canReflect.onEvent(obj, "foo", handler);
* canReflect.offKeyValue(obj, "foo", handler);
*
* canEvent.dispatch.call(obj, "foo", ["baz", "quux"]); // -> nothing is logged
* ```
*
* @param {Object} obj the object to unbind an event handler from
* @param {String} eventName the name of the event to unbind the handler from
* @param {function(*)} callback the handler function to unbind from the event
*/
offEvent: function(obj, eventName, callback){

@@ -66,0 +440,0 @@ if(obj) {

@@ -5,3 +5,36 @@ var canSymbol = require("can-symbol");

/**
* @module can-reflect/shape Shape
* @type {Object}
* @description Reflections based on available and enumerable keys on an object
*
*/
var shapeReflections = {
/**
* @function {Object, function(*), [Object]} can-reflect/shape.each each
* @parent can-reflect/shape
* @description Iterate a List-like or Map-like, calling `callback` on each keyed or indexed property
*
* @signature `each(obj, callback, context)`
*
* If `obj` is a List-like or an Iterator-like, `each` functions as [can-reflect/shape.eachIndex eachIndex],
* iterating over numeric indexes from 0 to `obj.length - 1` and calling `callback` with each property and
* index, optionally with `context` as `this` (defaulting to `obj`). If not, `each` functions as
* [can-reflect/shape.eachKey eachKey],
* iterating over every Number and String key on `obj` and calling `callback` on each one.
*
* ```
* var foo = new DefineMap({ bar: "baz" });
* var quux = new DefineList([ "thud", "jeek" ]);
*
* canReflect.each(foo, console.log, console); // -> logs 'baz bar {foo}'
* canReflect.each(quux, console.log, console); // -> logs 'thud 0 {quux}'; logs 'jeek 1 {quux}'
* ```
*
* @param {Object} obj The object to iterate over
* @param {Function(*, ValueLike)} callback a function that receives each item in the ListLike or MapLike
* @param {[Object]} context an optional `this` context for calling the callback
* @return {Array} the result of calling [can-reflect/shape.eachIndex `eachIndex`] if `obj` is a ListLike,
* or [can-reflect/shape.eachKey `eachKey`] if a MapLike.
*/
each: function(obj, callback, context){

@@ -17,4 +50,26 @@

// each index in something list-like. Uses iterator if it has it.
/**
* @function {ListLike, function(*), [Object]} can-reflect/shape.eachIndex eachIndex
* @parent can-reflect/shape
* @description Iterate a ListLike calling `callback` on each numerically indexed element
*
* @signature `eachIndex(list, callback, context)`
*
* For each numeric index from 0 to `list.length - 1`, call `callback`, passing the current
* property value, the current index, and `list`, and optionally setting `this` as `context`
* if specified (otherwise use the current property value).
*
* ```
* var foo = new DefineList([ "bar", "baz" ]);
*
* canReflect.eachIndex(foo, console.log, console); // -> logs 'bar 0 {foo}'; logs 'baz 1 {foo}'
* ```
*
* @param {ListLike} list The list to iterate over
* @param {Function(*, Number)} callback a function that receives each item
* @param {[Object]} context an optional `this` context for calling the callback
* @return {ListLike} the original list
*/
eachIndex: function(list, callback, context){
// each index in something list-like. Uses iterator if it has it.
var iter, iterator = list[canSymbol.iterator];

@@ -48,2 +103,23 @@ if(Array.isArray(list)) {

},
/**
* @function can-reflect/shape.toArray toArray
* @parent can-reflect/shape
* @description convert the values of any MapLike or ListLike into an array
*
* @signature `toArray(obj)`
*
* Convert the values of any Map-like or List-like into a JavaScript Array. If a Map-like,
* key data is discarded and only value data is preserved.
*
* ```
* var foo = new DefineList(["bar", "baz"]);
* var quux = new DefineMap({ thud: "jeek" });
* ```
*
* canReflect.toArray(foo); // -> ["bar", "baz"]
* canReflect.toArray(quux): // -> ["jeek"]
*
* @param {Object} obj Any object, whether MapLike or ListLike
* @return {Array} an array of the values of `obj`
*/
toArray: function(obj){

@@ -56,5 +132,28 @@ var arr = [];

},
// each key in something map like
// eachOwnEnumerableKey
/**
* @function can-reflect/shape.eachKey eachKey
* @parent can-reflect/shape
* @description Iterate over a MapLike, calling `callback` on each enumerable property
*
* @signature `eachKey(obj, callback, context)`
*
* Iterate all own enumerable properties on Map-like `obj`
* (using [can-reflect/shape/getOwnEnumerableKeys canReflect.getOwnEnumerableKeys]), and call
* `callback` with the property value, the property key, and `obj`, and optionally setting
* `this` on the callback as `context` if provided, `obj` otherwise.
*
* ```
* var foo = new DefineMap({ bar: "baz" });
*
* canReflect.eachKey(foo, console.log, console); // logs 'baz bar {foo}'
* ```
*
* @param {Object} obj The object to iterate over
* @param {Function(*, String)} callback The callback to call on each enumerable property value
* @param {[Object]} context an optional `this` context for calling `callback`
* @return {Array} the enumerable keys of `obj` as an Array
*/
eachKey: function(obj, callback, context){
// each key in something map like
// eachOwnEnumerableKey
var enumerableKeys = this.getOwnEnumerableKeys(obj);

@@ -66,5 +165,30 @@ return this.eachIndex(enumerableKeys, function(key){

},
// if a key or index
// like has own property
/**
* @function can-reflect/shape.hasOwnKey hasOwnKey
* @parent can-reflect/shape
* @description Determine whether an object contains a key on itself, not only on its prototype chain
*
* @signature `hasOwnKey(obj, key)`
*
* Return `true` if an object's own properties include the property key `key`, `false` otherwise.
* An object may implement [can-symbol/symbols/hasOwnKey @@@@can.hasOWnKey] to override default behavior.
* By default, `canReflect.hasOwnKey` will first look for
* [can-symbol/symbols/getOwnKey @@@@can.getOwnKey] on `obj`. If present, it will call `@@@@can.getOwnKey` and
* test `key` against the returned Array of keys. If absent, `Object.prototype.hasOwnKey()` is used.
*
* ```
* var foo = new DefineMap({ "bar": "baz" });
*
* canReflect.hasOwnKey(foo, "bar"); // -> true
* canReflect.hasOwnKey(foo, "each"); // -> false
* foo.each // -> function each() {...}
* ```
*
* @param {Object} obj Any MapLike object
* @param {String} key The key to look up on `obj`
* @return {Boolean} `true` if `obj`'s key set contains `key`, `false` otherwise
*/
"hasOwnKey": function(obj, key){
// if a key or index
// like has own property
var hasOwnKey = obj[canSymbol.for("can.hasOwnKey")];

@@ -87,5 +211,36 @@ if(hasOwnKey) {

},
// own enumerable keys (aliased as keys)
/**
* @function can-reflect/shape.getOwnEnumerableKeys getOwnEnumerableKeys
* @parent can-reflect/shape
* @description Return the list of keys which can be iterated over on an object
*
* @signature `getOwnEnumerableKeys(obj)`
*
* Return all keys on `obj` which have been defined as enumerable, either from explicitly setting
* `enumerable` on the property descriptor, or by using `=` to set the value of the property without
* a key descriptor, but excluding properties that only exist on `obj`'s prototype chaing. The
* default behavior can be overridden by implementing
* [can-symbol/symbols/getOwnEnumerableKeys @@@@can.getOwnEnumerableKeys] on `obj`. By default,
* `canReflect.getOwnEnumerableKeys` will use [can-symbol/symbols/getOwnKeys @@@@can.getOwnKeys] to
* retrieve the set of keys and [can-symbol/symbols/getOwnKeyDescriptor @@@@can.getOwnKeyDescriptor]
* to filter for those which are enumerable. If either symbol is absent from `obj`, `Object.keys`
* is used.
*
* ```
* var foo = new DefineMap({ bar: "baz", [canSymbol.for("quux")]: "thud" });
* Object.defineProperty(foo, "jeek", {
* enumerable: true,
* value: "plonk"
* });
*
* canReflect.getOwnEnumerableKeys(foo); // -> ["bar", "jeek"]
* ```
*
* @param {Object} obj Any Map-like object
* @return {Array} the Array of all enumerable keys from the object, either using
* [can-symbol/symbols/getOwnEnumerableKeys `@@@@can.getOwnEnumerableKeys`] from `obj`, or filtering
* `obj`'s own keys for those which are enumerable.
*/
getOwnEnumerableKeys: function(obj){
// own enumerable keys (aliased as keys)
var getOwnEnumerableKeys = obj[canSymbol.for("can.getOwnEnumerableKeys")];

@@ -125,4 +280,28 @@ if(getOwnEnumerableKeys) {

},
// own enumerable&non-enumerable keys (Object.getOwnPropertyNames)
/**
* @function can-reflect/shape.getOwnKeys getOwnKeys
* @parent can-reflect/shape
* @description Return the list of keys on an object, whether or not they can be iterated over
*
* @signature `getOwnKeys(obj)`
*
* Return the Array of all String (not Symbol) keys from `obj`, whether they are enumerable or not. If
* [can-symbol/symbols/getOwnKeys @@@@can.getOwnKeys] exists on `obj`, it is called to return
* the keys; otherwise, `Object.getOwnPropertyNames()` is used.
*
* ```
* var foo = new DefineMap({ bar: "baz", [canSymbol.for("quux")]: "thud" });
* Object.defineProperty(foo, "jeek", {
* enumerable: false,
* value: "plonk"
* });
*
* canReflect.getOwnKeys(foo); // -> ["bar", "jeek"]
* ```
*
* @param {Object} obj Any MapLike object
* @return {Array} the Array of all String keys from the object.
*/
getOwnKeys: function(obj){
// own enumerable&non-enumerable keys (Object.getOwnPropertyNames)
var getOwnKeys = obj[canSymbol.for("can.getOwnKeys")];

@@ -135,2 +314,26 @@ if(getOwnKeys) {

},
/**
* @function can-reflect/shape.getOwnKeyDescriptor getOwnKeyDescriptor
* @parent can-reflect/shape
* @description Return a property descriptor for a named property on an object.
*
* @signature `getOwnKeyDescriptor(obj, key)`
*
* Return the key descriptor for the property key `key` on the Map-like object `obj`. A key descriptor
* is specified in ECMAScript 5 and contains keys for the property's `configurable` and `enumerable` states,
* as well as either `value` and `writable` for value properties, or `get` and `set` for getter/setter properties.
*
* The default behavior can be overridden by implementing [can-symbol/symbols/getOwnKeyDescriptor @@@@can.getOwnKeyDescriptor]
* on `obj`; otherwise the default is to call `Object.getOwnKeyDescriptor()`.
*
* ```
* var foo = new DefineMap({ bar: "baz" });
*
* getOwnKeyDescriptor(foo, "bar"); // -> {configurable: true, writable: true, enumerable: true, value: "baz"}
* ```
*
* @param {Object} obj Any object with named properties
* @param {String} key The property name to look up on `obj`
* @return {Object} A key descriptor object
*/
getOwnKeyDescriptor: function(obj, key){

@@ -137,0 +340,0 @@ var getOwnKeyDescriptor = obj[canSymbol.for("can.getOwnKeyDescriptor")];

@@ -25,4 +25,17 @@ var QUnit = require('steal-qunit');

QUnit.test("isFunctionLike", function(){
ok(!typeReflections.isFunctionLike({}));
ok(typeReflections.isFunctionLike(function(){}));
ok(!typeReflections.isFunctionLike({}), 'object is not function like');
ok(typeReflections.isFunctionLike(function(){}), 'function is function like');
var nonFunctionFunction = function() {};
getSetReflections.setKeyValue(nonFunctionFunction, canSymbol.for("can.isFunctionLike"), false);
ok(!typeReflections.isFunctionLike(nonFunctionFunction), 'function with can.isFunctionLike set to false is not function like');
var obj = {};
var func = function() {};
getSetReflections.setKeyValue(obj, canSymbol.for("can.new"), func);
getSetReflections.setKeyValue(obj, canSymbol.for("can.apply"), func);
ok(typeReflections.isFunctionLike(obj), 'object with can.new and can.apply symbols is function like');
getSetReflections.setKeyValue(obj, canSymbol.for("can.isFunctionLike"), false);
ok(!typeReflections.isFunctionLike(obj), 'object with can.new, can.apply, and can.isFunctionLike set to false is not function like');
});

@@ -29,0 +42,0 @@

@@ -12,2 +12,25 @@ var canSymbol = require("can-symbol");

/**
* @function can-reflect/type.isConstructorLike isConstructorLike
* @parent can-reflect/type
*
* @signature `isConstructorLike(func)`
*
* Return `true` if `func` is a function and has a non-empty prototype, or implements
* [can-symbol/symbols/new `@@@@can.new`]; `false` otherwise.
*
* ```
* canReflect.isConstructorLike(function() {}); // -> false
*
* function Construct() {}
* Construct.prototype = { foo: "bar" };
* canReflect.isConstructorLike(Construct); // -> true
*
* canReflect.isConstructorLike({}); // -> false
* !!canReflect.isConstructorLike({ [canSymbol.for("can.new")]: function() {} }); // -> true
* ```
*
* @param {*} func maybe a function
* @return {Boolean}
*/
function isConstructorLike(func){

@@ -31,10 +54,57 @@ /* jshint unused: false */

/**
* @function can-reflect/type.isFunctionLike isFunctionLike
* @parent can-reflect/type
* @signature `isFunctionLike(obj)`
*
* Return `true` if `func` is a function, or implements
* [can-symbol/symbols/new `@@@@can.new`] or [can-symbol/symbols/apply `@@@@can.apply`]; `false` otherwise.
*
* ```
* canReflect.isFunctionLike(function() {}); // -> true
* canReflect.isFunctionLike({}); // -> false
* canReflect.isFunctionLike({ [canSymbol.for("can.apply")]: function() {} }); // -> true
* ```
*
* @param {*} obj maybe a function
* @return {Boolean}
*/
function isFunctionLike(obj){
var result = check(["can.new","can.apply"], obj);
var result,
symbolValue = obj[canSymbol.for("can.isFunctionLike")];
if (symbolValue !== undefined) {
return symbolValue;
}
result = check(["can.new","can.apply"], obj);
if(result !== undefined) {
return !!result;
}
return typeof obj === "function";
}
/**
* @function can-reflect/type.isPrimitive isPrimitive
* @parent can-reflect/type
*
* @signature `isPrimitive(obj)`
*
* Return `true` if `obj` is not a function nor an object via `typeof`, or is null; `false` otherwise.
*
* ```
* canReflect.isPrimitive(null); // -> true
* canReflect.isPrimitive({}); // -> false
* canReflect.isPrimitive(undefined); // -> true
* canReflect.isPrimitive(1); // -> true
* canReflect.isPrimitive([]); // -> false
* canReflect.isPrimitive(function() {}); // -> false
* canReflect.isPrimitive("foo"); // -> true
*
* ```
*
* @param {*} obj maybe a primitive value
* @return {Boolean}
*/
function isPrimitive(obj){

@@ -49,2 +119,25 @@ var type = typeof obj;

/**
* @function can-reflect/type.isValueLike isValueLike
* @parent can-reflect/type
*
* @signature `isValueLike(obj)`
*
* Return `true` if `obj` is a primitive or implements [can-symbol/symbols/getValue `@@can.getValue`],
* `false` otherwise.
*
* ```
* canReflect.isValueLike(null); // -> true
* canReflect.isValueLike({}); // -> false
* canReflect.isValueLike(function() {}); // -> false
* canReflect.isValueLike({ [canSymbol.for("can.isValueLike")]: true}); // -> true
* canReflect.isValueLike({ [canSymbol.for("can.getValue")]: function() {} }); // -> true
* canReflect.isValueLike(canCompute()); // -> true
* canReflect.isValueLike(new DefineMap()); // -> false
*
* ```
*
* @param {*} obj maybe a primitive or an object that yields a value
* @return {Boolean}
*/
function isValueLike(obj) {

@@ -65,10 +158,36 @@ var symbolValue;

/**
* @function can-reflect/type.isMapLike isMapLike
* @parent can-reflect/type
*
* @signature `isMapLike(obj)`
*
* Return `true` if `obj` is _not_ a primitive, does _not_ have a falsy value for
* [can-symbol/symbols/isMapLike `@@@@can.isMapLike`], or alternately implements
* [can-symbol/symbols/getKeyValue `@@@@can.getKeyValue`]; `false` otherwise.
*
* ```
* canReflect.isMapLike(null); // -> false
* canReflect.isMapLike(1); // -> false
* canReflect.isMapLike("foo"); // -> false
* canReflect.isMapLike({}); // -> true
* canReflect.isMapLike(function() {}); // -> true
* canReflect.isMapLike([]); // -> false
* canReflect.isMapLike({ [canSymbol.for("can.isMapLike")]: false }); // -> false
* canReflect.isMapLike({ [canSymbol.for("can.getKeyValue")]: null }); // -> false
* canReflect.isMapLike(canCompute()); // -> false
* canReflect.isMapLike(new DefineMap()); // -> true
*
* ```
*
* @param {*} obj maybe a Map-like
* @return {Boolean}
*/
function isMapLike(obj) {
var symbolValue;
if(isPrimitive(obj)) {
return false;
}
symbolValue = obj[canSymbol.for("can.isMapLike")];
if( typeof symbolValue !== "undefined") {
return symbolValue;
var isMapLike = obj[canSymbol.for("can.isMapLike")];
if(typeof isMapLike !== "undefined") {
return !!isMapLike;
}

@@ -83,2 +202,27 @@ var value = obj[canSymbol.for("can.getKeyValue")];

/**
* @function can-reflect/type.isObservableLike isObservableLike
* @parent can-reflect/type
*
* @signature `isObservableLike(obj)`
*
* Return `true` if `obj` is _not_ a primitive and implements any of
* [can-symbol/symbols/onValue `@@@@can.onValue`], [can-symbol/symbols/onKeyValue `@@@@can.onKeyValue`],
* [can-symbol/symbols/onKeys `@@@@can.onKeys`],
* or [can-symbol/symbols/onKeysAdded `@@@@can.onKeysAdded`]; `false` otherwise.
*
* ```
* canReflect.isObservableLike(null); // -> false
* canReflect.isObservableLike({}); // -> false
* canReflect.isObservableLike([]); // -> false
* canReflect.isObservableLike(function() {}); // -> false
* canReflect.isObservableLike({ [canSymbol.for("can.onValue")]: function() {} }); // -> true
* canReflect.isObservableLike({ [canSymbol.for("can.onKeyValue")]: function() {} }); // -> true
* canReflect.isObservableLike(canCompute())); // -> true
* canReflect.isObservableLike(new DefineMap())); // -> true
* ```
*
* @param {*} obj maybe an observable
* @return {Boolean}
*/
function isObservableLike( obj ) {

@@ -94,2 +238,30 @@ if(isPrimitive(obj)) {

/**
* @function can-reflect/type.isListLike isListLike
* @parent can-reflect/type
*
* @signature `isListLike(list)`
*
* Return `true` if `list` is a `String`, <br>OR `list` is _not_ a primitive and implements `@@@@iterator`,
* <br>OR `list` is _not_ a primitive and returns `true` for `Array.isArray()`, <br>OR `list` is _not_ a primitive and has a
* numerical length and is either empty (`length === 0`) or has a last element at index `length - 1`; <br>`false` otherwise
*
* ```
* canReflect.isListLike(null); // -> false
* canReflect.isListLike({}); // -> false
* canReflect.isListLike([]); // -> true
* canReflect.isListLike("foo"); // -> true
* canReflect.isListLike(1); // -> false
* canReflect.isListLike({ [canSymbol.for("can.isListLike")]: true }); // -> true
* canReflect.isListLike({ [canSymbol.iterator]: function() {} }); // -> true
* canReflect.isListLike({ length: 0 }); // -> true
* canReflect.isListLike({ length: 3 }); // -> false
* canReflect.isListLike({ length: 3, "2": true }); // -> true
* canReflect.isListLike(new DefineMap()); // -> false
* canReflect.isListLike(new DefineList()); // -> true
* ```
*
* @param {*} list maybe a List-like
* @return {Boolean}
*/
function isListLike( list ) {

@@ -126,2 +298,26 @@ var symbolValue,

}
/**
* @function can-reflect/type.isSymbolLike isSymbolLike
* @parent can-reflect/type
*
* @signature `isSymbolLike(symbol)`
*
* Return `true` if `symbol` is a native Symbol, or evaluates to a String with a prefix
* equal to that of CanJS's symbol polyfill; `false` otherwise.
*
* ```
* /* ES6 *\/ canReflect.isSymbolLike(Symbol.iterator); // -> true
* canReflect.isSymbolLike(canSymbol.for("foo")); // -> true
* canReflect.isSymbolLike("@@symbol.can.isSymbol"); // -> true (due to polyfill for non-ES6)
* canReflect.isSymbolLike("foo"); // -> false
* canReflect.isSymbolLike(null); // -> false
* canReflect.isSymbolLike(1); // -> false
* canReflect.isSymbolLike({}); // -> false
* canReflect.isSymbolLike({ toString: function() { return "@@symbol.can.isSymbol"; } }); // -> true
* ```
*
* @param {*} symbol maybe a symbol
* @return {Boolean}
*/
var symbolStart = "@@symbol";

@@ -136,2 +332,9 @@ function isSymbolLike( symbol ) {

/**
* @module can-reflect/type Type
* @parent can-reflect
*
* The `type` module deals with how to determine if a given object matches any of the familiar types to CanJS:
* constructors, functions, lists, maps, observables (which are also lists and maps), primitives, values, and symbols.
*/
module.exports = {

@@ -146,2 +349,23 @@ isConstructorLike: isConstructorLike,

isSymbolLike: isSymbolLike,
/**
* @function can-reflect/type.isMoreListLikeThanMapLike isMoreListLikeThanMapLike
* @parent can-reflect/type
*
* @signature `isMoreListLikeThanMapLike(obj)`
*
* Return `true` if `obj` is an Array, declares itself to be more ListLike with
* `@@@@can.isMoreListLikeThanMapLike`, or self-reports as ListLike but not as MapLike; `false` otherwise.
*
* ```
* canReflect.isMoreListLikeThanMapLike([]); // -> true
* canReflect.isMoreListLikeThanMapLike(null); // -> undefined
* canReflect.isMoreListLikeThanMapLike({}); // -> false
* canReflect.isMoreListLikeThanMapLike(new DefineList()); // -> true
* canReflect.isMoreListLikeThanMapLike(new DefineMap()); // -> false
* canReflect.isMoreListLikeThanMapLike(function() {}); // -> false
* ```
*
* @param {Object} obj the object to test for ListLike against MapLike traits.
* @return {Boolean}
*/
isMoreListLikeThanMapLike: function(obj){

@@ -163,2 +387,22 @@ if(Array.isArray(obj)) {

},
/**
* @function can-reflect/type.isIteratorLike isIteratorLike
* @parent can-reflect/type
*
* @signature `isIteratorLike(obj)`
*
* Return `true` if `obj` has a key `"next"` pointing to a zero-argument function; `false` otherwise
*
* ```
* canReflect.isIteratorLike([][Symbol.iterator]()); // -> true
* canReflect.isIteratorLike(new DefineList()[canSymbol.iterator]()); // -> true
* canReflect.isIteratorLike(new DefineMap()[canSymbol.iterator]()); // -> true
* canReflect.isIteratorLike(null); // -> false
* canReflect.isIteratorLike({ next: function() {} }); // -> true
* canReflect.isIteratorLike({ next: function(foo) {} }); // -> false (iterator nexts do not take arguments)
* ```
*
* @param {Object} obj the object to test for Iterator traits
* @return {Boolean}
*/
isIteratorLike: function(obj){

@@ -165,0 +409,0 @@ return obj &&

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc