diff options
Diffstat (limited to 'addon-sdk/source/lib/method/core.js')
-rw-r--r-- | addon-sdk/source/lib/method/core.js | 225 |
1 files changed, 0 insertions, 225 deletions
diff --git a/addon-sdk/source/lib/method/core.js b/addon-sdk/source/lib/method/core.js deleted file mode 100644 index a6a5261e6..000000000 --- a/addon-sdk/source/lib/method/core.js +++ /dev/null @@ -1,225 +0,0 @@ -"use strict"; - -var defineProperty = Object.defineProperty || function(object, name, property) { - object[name] = property.value - return object -} - -// Shortcut for `Object.prototype.toString` for faster access. -var typefy = Object.prototype.toString - -// Map to for jumping from typeof(value) to associated type prefix used -// as a hash in the map of builtin implementations. -var types = { "function": "Object", "object": "Object" } - -// Array is used to save method implementations for the host objects in order -// to avoid extending them with non-primitive values that could cause leaks. -var host = [] -// Hash map is used to save method implementations for builtin types in order -// to avoid extending their prototypes. This also allows to share method -// implementations for types across diff contexts / frames / compartments. -var builtin = {} - -function Primitive() {} -function ObjectType() {} -ObjectType.prototype = new Primitive() -function ErrorType() {} -ErrorType.prototype = new ObjectType() - -var Default = builtin.Default = Primitive.prototype -var Null = builtin.Null = new Primitive() -var Void = builtin.Void = new Primitive() -builtin.String = new Primitive() -builtin.Number = new Primitive() -builtin.Boolean = new Primitive() - -builtin.Object = ObjectType.prototype -builtin.Error = ErrorType.prototype - -builtin.EvalError = new ErrorType() -builtin.InternalError = new ErrorType() -builtin.RangeError = new ErrorType() -builtin.ReferenceError = new ErrorType() -builtin.StopIteration = new ErrorType() -builtin.SyntaxError = new ErrorType() -builtin.TypeError = new ErrorType() -builtin.URIError = new ErrorType() - - -function Method(hint) { - /** - Private Method is a callable private name that dispatches on the first - arguments same named Method: - - method(object, ...rest) => object[method](...rest) - - Optionally hint string may be provided that will be used in generated names - to ease debugging. - - ## Example - - var foo = Method() - - // Implementation for any types - foo.define(function(value, arg1, arg2) { - // ... - }) - - // Implementation for a specific type - foo.define(BarType, function(bar, arg1, arg2) { - // ... - }) - **/ - - // Create an internal unique name if `hint` is provided it is used to - // prefix name to ease debugging. - var name = (hint || "") + "#" + Math.random().toString(32).substr(2) - - function dispatch(value) { - // Method dispatches on type of the first argument. - // If first argument is `null` or `void` associated implementation is - // looked up in the `builtin` hash where implementations for built-ins - // are stored. - var type = null - var method = value === null ? Null[name] : - value === void(0) ? Void[name] : - // Otherwise attempt to use method with a generated private - // `name` that is supposedly in the prototype chain of the - // `target`. - value[name] || - // Otherwise assume it's one of the built-in type instances, - // in which case implementation is stored in a `builtin` hash. - // Attempt to find a implementation for the given built-in - // via constructor name and method name. - ((type = builtin[(value.constructor || "").name]) && - type[name]) || - // Otherwise assume it's a host object. For host objects - // actual method implementations are stored in the `host` - // array and only index for the implementation is stored - // in the host object's prototype chain. This avoids memory - // leaks that otherwise could happen when saving JS objects - // on host object. - host[value["!" + name] || void(0)] || - // Otherwise attempt to lookup implementation for builtins by - // a type of the value. This basically makes sure that all - // non primitive values will delegate to an `Object`. - ((type = builtin[types[typeof(value)]]) && type[name]) - - - // If method implementation for the type is still not found then - // just fallback for default implementation. - method = method || Default[name] - - - // If implementation is still not found (which also means there is no - // default) just throw an error with a descriptive message. - if (!method) throw TypeError("Type does not implements method: " + name) - - // If implementation was found then just delegate. - return method.apply(method, arguments) - } - - // Make `toString` of the dispatch return a private name, this enables - // method definition without sugar: - // - // var method = Method() - // object[method] = function() { /***/ } - dispatch.toString = function toString() { return name } - - // Copy utility methods for convenient API. - dispatch.implement = implementMethod - dispatch.define = defineMethod - - return dispatch -} - -// Create method shortcuts form functions. -var defineMethod = function defineMethod(Type, lambda) { - return define(this, Type, lambda) -} -var implementMethod = function implementMethod(object, lambda) { - return implement(this, object, lambda) -} - -// Define `implement` and `define` polymorphic methods to allow definitions -// and implementations through them. -var implement = Method("implement") -var define = Method("define") - - -function _implement(method, object, lambda) { - /** - Implements `Method` for the given `object` with a provided `implementation`. - Calling `Method` with `object` as a first argument will dispatch on provided - implementation. - **/ - return defineProperty(object, method.toString(), { - enumerable: false, - configurable: false, - writable: false, - value: lambda - }) -} - -function _define(method, Type, lambda) { - /** - Defines `Method` for the given `Type` with a provided `implementation`. - Calling `Method` with a first argument of this `Type` will dispatch on - provided `implementation`. If `Type` is a `Method` default implementation - is defined. If `Type` is a `null` or `undefined` `Method` is implemented - for that value type. - **/ - - // Attempt to guess a type via `Object.prototype.toString.call` hack. - var type = Type && typefy.call(Type.prototype) - - // If only two arguments are passed then `Type` is actually an implementation - // for a default type. - if (!lambda) Default[method] = Type - // If `Type` is `null` or `void` store implementation accordingly. - else if (Type === null) Null[method] = lambda - else if (Type === void(0)) Void[method] = lambda - // If `type` hack indicates built-in type and type has a name us it to - // store a implementation into associated hash. If hash for this type does - // not exists yet create one. - else if (type !== "[object Object]" && Type.name) { - var Bulitin = builtin[Type.name] || (builtin[Type.name] = new ObjectType()) - Bulitin[method] = lambda - } - // If `type` hack indicates an object, that may be either object or any - // JS defined "Class". If name of the constructor is `Object`, assume it's - // built-in `Object` and store implementation accordingly. - else if (Type.name === "Object") - builtin.Object[method] = lambda - // Host objects are pain!!! Every browser does some crazy stuff for them - // So far all browser seem to not implement `call` method for host object - // constructors. If that is a case here, assume it's a host object and - // store implementation in a `host` array and store `index` in the array - // in a `Type.prototype` itself. This avoids memory leaks that could be - // caused by storing JS objects on a host objects. - else if (Type.call === void(0)) { - var index = host.indexOf(lambda) - if (index < 0) index = host.push(lambda) - 1 - // Prefix private name with `!` so it can be dispatched from the method - // without type checks. - implement("!" + method, Type.prototype, index) - } - // If Got that far `Type` is user defined JS `Class`. Define private name - // as hidden property on it's prototype. - else - implement(method, Type.prototype, lambda) -} - -// And provided implementations for a polymorphic equivalents. -_define(define, _define) -_define(implement, _implement) - -// Define exports on `Method` as it's only thing being exported. -Method.implement = implement -Method.define = define -Method.Method = Method -Method.method = Method -Method.builtin = builtin -Method.host = host - -module.exports = Method |