mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-08 16:58:38 +09:00
Move Add-on SDK source to toolkit/jetpack
This commit is contained in:
parent
0a03067ee3
commit
23b67db438
993 changed files with 484 additions and 100663 deletions
5
toolkit/jetpack/method/.travis.yml
Normal file
5
toolkit/jetpack/method/.travis.yml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
language: node_js
|
||||
node_js:
|
||||
- 0.4
|
||||
- 0.5
|
||||
- 0.6
|
||||
55
toolkit/jetpack/method/History.md
Normal file
55
toolkit/jetpack/method/History.md
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
# Changes
|
||||
|
||||
## 1.0.2 / 2012-12-26
|
||||
|
||||
- Delegate to polymorphic methods from `.define` and `.implement` so, they
|
||||
can be overidden.
|
||||
|
||||
## 1.0.1 / 2012-11-11
|
||||
|
||||
- Fix issues with different `Error` types as they all inherit from
|
||||
`Error`.
|
||||
|
||||
## 1.0.0 / 2012-11-09
|
||||
|
||||
- Add browser test integration.
|
||||
- Fix cross-browser incompatibilities & test failures.
|
||||
- Add support for host objects.
|
||||
- Add optional `hint` argument for method to ease debugging.
|
||||
- Remove default implementation at definition time.
|
||||
|
||||
## 0.1.1 / 2012-10-15
|
||||
|
||||
- Fix regression causing custom type implementation to be stored on objects.
|
||||
|
||||
## 0.1.0 / 2012-10-15
|
||||
|
||||
- Remove dependency on name module.
|
||||
- Implement fallback for engines that do not support ES5.
|
||||
- Add support for built-in type extensions without extending their prototypes.
|
||||
- Make API for default definitions more intuitive.
|
||||
Skipping type argument now defines default:
|
||||
|
||||
isFoo.define(function(value) {
|
||||
return false
|
||||
})
|
||||
|
||||
- Make exposed `define` and `implement` polymorphic.
|
||||
- Removed dev dependency on swank-js.
|
||||
- Primitive types `string, number, boolean` no longer inherit method
|
||||
implementations from `Object`.
|
||||
|
||||
## 0.0.3 / 2012-07-17
|
||||
|
||||
- Remove module boilerplate
|
||||
|
||||
## 0.0.2 / 2012-06-26
|
||||
|
||||
- Name changes to make it less conflicting with other library conventions.
|
||||
- Expose function version of `define` & `implement` methods.
|
||||
- Expose `Null` and `Undefined` object holding implementations for an
|
||||
associated types.
|
||||
|
||||
## 0.0.1 / 2012-06-25
|
||||
|
||||
- Initial release
|
||||
18
toolkit/jetpack/method/License.md
Normal file
18
toolkit/jetpack/method/License.md
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
Copyright 2012 Irakli Gozalishvili. All rights reserved.
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to
|
||||
deal in the Software without restriction, including without limitation the
|
||||
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
sell copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
IN THE SOFTWARE.
|
||||
117
toolkit/jetpack/method/Readme.md
Normal file
117
toolkit/jetpack/method/Readme.md
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
# method
|
||||
|
||||
[](http://travis-ci.org/Gozala/method)
|
||||
|
||||
Library provides an API for defining polymorphic methods that dispatch on the
|
||||
first argument type. This provides a powerful way for decouple abstraction
|
||||
interface definition from an actual implementation per type, without risks
|
||||
of interference with other libraries.
|
||||
|
||||
### Motivation
|
||||
|
||||
- Provide a high-performance, dynamic polymorphism construct as an
|
||||
alternative to existing object methods that does not provides any
|
||||
mechanics for guarding against name conflicts.
|
||||
- Allow independent extension of types, and implementations of methods
|
||||
on types, by different parties.
|
||||
|
||||
## Install
|
||||
|
||||
npm install method
|
||||
|
||||
## Use
|
||||
|
||||
```js
|
||||
var method = require("method")
|
||||
|
||||
// Define `isWatchable` method that can be implemented for any type.
|
||||
var isWatchable = method("isWatchable")
|
||||
|
||||
// If you call it on any object it will
|
||||
// throw as nothing implements that method yet.
|
||||
//isWatchable({}) // => Exception: method is not implemented
|
||||
|
||||
// If you define private method on `Object.prototype`
|
||||
// all objects will inherit it.
|
||||
Object.prototype[isWatchable] = function() {
|
||||
return false;
|
||||
}
|
||||
|
||||
isWatchable({}) // => false
|
||||
|
||||
|
||||
// Although `isWatchable` property above will be enumerable and there for
|
||||
// may damage some assumbtions made by other libraries. There for it"s
|
||||
// recomended to use built-in helpers methods that will define extension
|
||||
// without breaking assumbtions made by other libraries:
|
||||
|
||||
isWatchable.define(Object, function() { return false })
|
||||
|
||||
|
||||
// There are primitive types in JS that won"t inherit methods from Object:
|
||||
isWatchable(null) // => Exception: method is not implemented
|
||||
|
||||
// One could either implement methods for such types:
|
||||
isWatchable.define(null, function() { return false })
|
||||
isWatchable.define(undefined, function() { return false })
|
||||
|
||||
// Or simply define default implementation:
|
||||
isWatchable.define(function() { return false })
|
||||
|
||||
// Alternatively default implementation may be provided at creation:
|
||||
isWatchable = method(function() { return false })
|
||||
|
||||
// Method dispatches on an first argument type. That allows us to create
|
||||
// new types with an alternative implementations:
|
||||
function Watchable() {}
|
||||
isWatchable.define(Watchable, function() { return true })
|
||||
|
||||
// This will make all `Watchable` instances watchable!
|
||||
isWatchable(new Watchable()) // => true
|
||||
|
||||
// Arbitrary objects can also be extended to implement given method. For example
|
||||
// any object can simply made watchable:
|
||||
function watchable(object) {
|
||||
return isWatchable.implement(objct, function() { return true })
|
||||
}
|
||||
|
||||
isWatchable(watchable({})) // => true
|
||||
|
||||
// Full protocols can be defined with such methods:
|
||||
var observers = "observers@" + module.filename
|
||||
var watchers = method("watchers")
|
||||
var watch = method("watch")
|
||||
var unwatch = method("unwatch")
|
||||
|
||||
watchers.define(Watchable, function(target) {
|
||||
return target[observers] || (target[observers] = [])
|
||||
})
|
||||
|
||||
watch.define(Watchable, function(target, watcher) {
|
||||
var observers = watchers(target)
|
||||
if (observers.indexOf(watcher) < 0) observers.push(watcher)
|
||||
return target
|
||||
})
|
||||
unwatch.define(Watchable, function(target, watcher) {
|
||||
var observers = watchers(target)
|
||||
var index = observers.indexOf(watcher)
|
||||
if (observers.indexOf(watcher) >= 0) observers.unshift(watcher)
|
||||
return target
|
||||
})
|
||||
|
||||
// Define type Port that inherits form Watchable
|
||||
|
||||
function Port() {}
|
||||
Port.prototype = Object.create(Watchable.prototype)
|
||||
|
||||
var emit = method("emit")
|
||||
emit.define(Port, function(port, message) {
|
||||
watchers(port).slice().forEach(function(watcher) {
|
||||
watcher(message)
|
||||
})
|
||||
})
|
||||
|
||||
var p = new Port()
|
||||
watch(p, console.log)
|
||||
emit(p, "hello world") // => info: "hello world"
|
||||
```
|
||||
225
toolkit/jetpack/method/core.js
Normal file
225
toolkit/jetpack/method/core.js
Normal file
|
|
@ -0,0 +1,225 @@
|
|||
"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
|
||||
41
toolkit/jetpack/method/package.json
Normal file
41
toolkit/jetpack/method/package.json
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
{
|
||||
"name": "method",
|
||||
"id": "method",
|
||||
"version": "1.0.2",
|
||||
"description": "Functional polymorphic method dispatch",
|
||||
"keywords": [
|
||||
"method",
|
||||
"dispatch",
|
||||
"protocol",
|
||||
"polymorphism",
|
||||
"type dispatch"
|
||||
],
|
||||
"author": "Irakli Gozalishvili <rfobic@gmail.com> (http://jeditoolkit.com)",
|
||||
"homepage": "https://github.com/Gozala/method",
|
||||
"main": "./core.js",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Gozala/method.git",
|
||||
"web": "https://github.com/Gozala/method"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "http://github.com/Gozala/method/issues/"
|
||||
},
|
||||
"devDependencies": {
|
||||
"test": "~0.x.0",
|
||||
"repl-utils": "~2.0.1",
|
||||
"phantomify": "~0.1.0"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "npm run test-node && npm run test-browser",
|
||||
"test-browser": "node ./node_modules/phantomify/bin/cmd.js ./test/browser.js",
|
||||
"test-node": "node ./test/common.js",
|
||||
"repl": "node node_modules/repl-utils"
|
||||
},
|
||||
"licenses": [
|
||||
{
|
||||
"type": "MIT",
|
||||
"url": "https://github.com/Gozala/method/License.md"
|
||||
}
|
||||
]
|
||||
}
|
||||
20
toolkit/jetpack/method/test/browser.js
Normal file
20
toolkit/jetpack/method/test/browser.js
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
"use strict";
|
||||
|
||||
exports["test common"] = require("./common")
|
||||
|
||||
var Method = require("../core")
|
||||
|
||||
exports["test host objects"] = function(assert) {
|
||||
var isElement = Method("is-element")
|
||||
isElement.define(function() { return false })
|
||||
|
||||
isElement.define(Element, function() { return true })
|
||||
|
||||
assert.notDeepEqual(typeof(Element.prototype[isElement]), "number",
|
||||
"Host object's prototype is extended with a number value")
|
||||
|
||||
assert.ok(!isElement({}), "object is not an Element")
|
||||
assert.ok(document.createElement("div"), "Element is an element")
|
||||
}
|
||||
|
||||
require("test").run(exports)
|
||||
272
toolkit/jetpack/method/test/common.js
Normal file
272
toolkit/jetpack/method/test/common.js
Normal file
|
|
@ -0,0 +1,272 @@
|
|||
"use strict";
|
||||
|
||||
var Method = require("../core")
|
||||
|
||||
function type(value) {
|
||||
return Object.prototype.toString.call(value).
|
||||
split(" ").
|
||||
pop().
|
||||
split("]").
|
||||
shift().
|
||||
toLowerCase()
|
||||
}
|
||||
|
||||
var values = [
|
||||
null, // 0
|
||||
undefined, // 1
|
||||
Infinity, // 2
|
||||
NaN, // 3
|
||||
5, // 4
|
||||
{}, // 5
|
||||
Object.create({}), // 6
|
||||
Object.create(null), // 7
|
||||
[], // 8
|
||||
/foo/, // 9
|
||||
new Date(), // 10
|
||||
Function, // 11
|
||||
function() {}, // 12
|
||||
true, // 13
|
||||
false, // 14
|
||||
"string" // 15
|
||||
]
|
||||
|
||||
function True() { return true }
|
||||
function False() { return false }
|
||||
|
||||
var trues = values.map(True)
|
||||
var falses = values.map(False)
|
||||
|
||||
exports["test throws if not implemented"] = function(assert) {
|
||||
var method = Method("nope")
|
||||
|
||||
assert.throws(function() {
|
||||
method({})
|
||||
}, /not implement/i, "method throws if not implemented")
|
||||
|
||||
assert.throws(function() {
|
||||
method(null)
|
||||
}, /not implement/i, "method throws on null")
|
||||
}
|
||||
|
||||
exports["test all types inherit from default"] = function(assert) {
|
||||
var isImplemented = Method("isImplemented")
|
||||
isImplemented.define(function() { return true })
|
||||
|
||||
values.forEach(function(value) {
|
||||
assert.ok(isImplemented(value),
|
||||
type(value) + " inherits deafult implementation")
|
||||
})
|
||||
}
|
||||
|
||||
exports["test default can be implemented later"] = function(assert) {
|
||||
var isImplemented = Method("isImplemented")
|
||||
isImplemented.define(function() {
|
||||
return true
|
||||
})
|
||||
|
||||
values.forEach(function(value) {
|
||||
assert.ok(isImplemented(value),
|
||||
type(value) + " inherits deafult implementation")
|
||||
})
|
||||
}
|
||||
|
||||
exports["test dispatch not-implemented"] = function(assert) {
|
||||
var isDefault = Method("isDefault")
|
||||
values.forEach(function(value) {
|
||||
assert.throws(function() {
|
||||
isDefault(value)
|
||||
}, /not implement/, type(value) + " throws if not implemented")
|
||||
})
|
||||
}
|
||||
|
||||
exports["test dispatch default"] = function(assert) {
|
||||
var isDefault = Method("isDefault")
|
||||
|
||||
// Implement default
|
||||
isDefault.define(True)
|
||||
assert.deepEqual(values.map(isDefault), trues,
|
||||
"all implementation inherit from default")
|
||||
|
||||
}
|
||||
|
||||
exports["test dispatch null"] = function(assert) {
|
||||
var isNull = Method("isNull")
|
||||
|
||||
// Implement default
|
||||
isNull.define(False)
|
||||
isNull.define(null, True)
|
||||
assert.deepEqual(values.map(isNull),
|
||||
[ true ].
|
||||
concat(falses.slice(1)),
|
||||
"only null gets methods defined for null")
|
||||
}
|
||||
|
||||
exports["test dispatch undefined"] = function(assert) {
|
||||
var isUndefined = Method("isUndefined")
|
||||
|
||||
// Implement default
|
||||
isUndefined.define(False)
|
||||
isUndefined.define(undefined, True)
|
||||
assert.deepEqual(values.map(isUndefined),
|
||||
[ false, true ].
|
||||
concat(falses.slice(2)),
|
||||
"only undefined gets methods defined for undefined")
|
||||
}
|
||||
|
||||
exports["test dispatch object"] = function(assert) {
|
||||
var isObject = Method("isObject")
|
||||
|
||||
// Implement default
|
||||
isObject.define(False)
|
||||
isObject.define(Object, True)
|
||||
assert.deepEqual(values.map(isObject),
|
||||
[ false, false, false, false, false ].
|
||||
concat(trues.slice(5, 13)).
|
||||
concat([false, false, false]),
|
||||
"all values except primitives inherit Object methods")
|
||||
|
||||
}
|
||||
|
||||
exports["test dispatch number"] = function(assert) {
|
||||
var isNumber = Method("isNumber")
|
||||
isNumber.define(False)
|
||||
isNumber.define(Number, True)
|
||||
|
||||
assert.deepEqual(values.map(isNumber),
|
||||
falses.slice(0, 2).
|
||||
concat(true, true, true).
|
||||
concat(falses.slice(5)),
|
||||
"all numbers inherit from Number method")
|
||||
}
|
||||
|
||||
exports["test dispatch string"] = function(assert) {
|
||||
var isString = Method("isString")
|
||||
isString.define(False)
|
||||
isString.define(String, True)
|
||||
|
||||
assert.deepEqual(values.map(isString),
|
||||
falses.slice(0, 15).
|
||||
concat(true),
|
||||
"all strings inherit from String method")
|
||||
}
|
||||
|
||||
exports["test dispatch function"] = function(assert) {
|
||||
var isFunction = Method("isFunction")
|
||||
isFunction.define(False)
|
||||
isFunction.define(Function, True)
|
||||
|
||||
assert.deepEqual(values.map(isFunction),
|
||||
falses.slice(0, 11).
|
||||
concat(true, true).
|
||||
concat(falses.slice(13)),
|
||||
"all functions inherit from Function method")
|
||||
}
|
||||
|
||||
exports["test dispatch date"] = function(assert) {
|
||||
var isDate = Method("isDate")
|
||||
isDate.define(False)
|
||||
isDate.define(Date, True)
|
||||
|
||||
assert.deepEqual(values.map(isDate),
|
||||
falses.slice(0, 10).
|
||||
concat(true).
|
||||
concat(falses.slice(11)),
|
||||
"all dates inherit from Date method")
|
||||
}
|
||||
|
||||
exports["test dispatch RegExp"] = function(assert) {
|
||||
var isRegExp = Method("isRegExp")
|
||||
isRegExp.define(False)
|
||||
isRegExp.define(RegExp, True)
|
||||
|
||||
assert.deepEqual(values.map(isRegExp),
|
||||
falses.slice(0, 9).
|
||||
concat(true).
|
||||
concat(falses.slice(10)),
|
||||
"all regexps inherit from RegExp method")
|
||||
}
|
||||
|
||||
exports["test redefine for descendant"] = function(assert) {
|
||||
var isFoo = Method("isFoo")
|
||||
var ancestor = {}
|
||||
isFoo.implement(ancestor, function() { return true })
|
||||
var descendant = Object.create(ancestor)
|
||||
isFoo.implement(descendant, function() { return false })
|
||||
|
||||
assert.ok(isFoo(ancestor), "defined on ancestor")
|
||||
assert.ok(!isFoo(descendant), "overrided for descendant")
|
||||
}
|
||||
|
||||
exports["test on custom types"] = function(assert) {
|
||||
function Bar() {}
|
||||
var isBar = Method("isBar")
|
||||
|
||||
isBar.define(function() { return false })
|
||||
isBar.define(Bar, function() { return true })
|
||||
|
||||
assert.ok(!isBar({}), "object is get's default implementation")
|
||||
assert.ok(isBar(new Bar()), "Foo type objects get own implementation")
|
||||
|
||||
var isObject = Method("isObject")
|
||||
isObject.define(function() { return false })
|
||||
isObject.define(Object, function() { return true })
|
||||
|
||||
assert.ok(isObject(new Bar()), "foo inherits implementation from object")
|
||||
|
||||
|
||||
isObject.define(Bar, function() { return false })
|
||||
|
||||
assert.ok(!isObject(new Bar()),
|
||||
"implementation inherited form object can be overrided")
|
||||
}
|
||||
|
||||
|
||||
exports["test error types"] = function(assert) {
|
||||
var isError = Method("isError")
|
||||
isError.define(function() { return false })
|
||||
isError.define(Error, function() { return true })
|
||||
|
||||
assert.ok(isError(Error("boom")), "error is error")
|
||||
assert.ok(isError(TypeError("boom")), "type error is an error")
|
||||
assert.ok(isError(EvalError("boom")), "eval error is an error")
|
||||
assert.ok(isError(RangeError("boom")), "range error is an error")
|
||||
assert.ok(isError(ReferenceError("boom")), "reference error is an error")
|
||||
assert.ok(isError(SyntaxError("boom")), "syntax error is an error")
|
||||
assert.ok(isError(URIError("boom")), "URI error is an error")
|
||||
}
|
||||
|
||||
exports["test override define polymorphic method"] = function(assert) {
|
||||
var define = Method.define
|
||||
var implement = Method.implement
|
||||
|
||||
var fn = Method("fn")
|
||||
var methods = {}
|
||||
implement(define, fn, function(method, label, implementation) {
|
||||
methods[label] = implementation
|
||||
})
|
||||
|
||||
function foo() {}
|
||||
|
||||
define(fn, "foo-case", foo)
|
||||
|
||||
assert.equal(methods["foo-case"], foo, "define set property")
|
||||
}
|
||||
|
||||
exports["test override define via method API"] = function(assert) {
|
||||
var define = Method.define
|
||||
var implement = Method.implement
|
||||
|
||||
var fn = Method("fn")
|
||||
var methods = {}
|
||||
define.implement(fn, function(method, label, implementation) {
|
||||
methods[label] = implementation
|
||||
})
|
||||
|
||||
function foo() {}
|
||||
|
||||
define(fn, "foo-case", foo)
|
||||
|
||||
assert.equal(methods["foo-case"], foo, "define set property")
|
||||
}
|
||||
|
||||
require("test").run(exports)
|
||||
Loading…
Add table
Add a link
Reference in a new issue