contracts.coffee
contracts.coffee copied to clipboard
CoffeeScript classes supported?
Are CoffeeScript classes supported? I didn't have any luck while trying to put a contract on a class in various ways. Maybe i'm doing something wrong?
Contract for a whole class:
NodeAddr = ? {
port: Num
host: Str
}
Node :: (NodeAddr, Any, Any) -> {
address: (NodeAddr) -> Any
}
Node = class
constructor: (address, services, next) ->
address: (addr) ->
Results in
TypeError: Object.getOwnPropertyDescriptor called on non-object
at Function.getOwnPropertyDescriptor (native)
at Object.getPropertyDescriptor (...node_modules/contracts.js/lib/contracts.js:410:23)
at Contract.handler (...node_modules/contracts.js/lib/contracts.js:853:25)
at Contract.check (...node_modules/contracts.js/lib/contracts.js:597:21)
at ...node_modules/contracts.js/lib/contracts.js:742:29
at <error: illegal access>
at <error: illegal access>
at Object.<anonymous> (...prototypes/contracts/foo.coffee:71:9)
at Object.<anonymous> (...prototypes/contracts/foo.coffee:86:4)
at Object.<anonymous> (...prototypes/contracts/foo.coffee:87:4)
Contract for a specific method:
NodeAddr = ? {
port: Num
host: Str
}
class Node
constructor :: (NodeAddr, Any, Any) -> Any
constructor: (address, services, next) -> yes
address: (addr) ->
Results in "Error: In foo.coffee, Parse error on line 29: Unexpected 'OUTDENT'".
An unfortunate and glaring omission, we don't have explicit grammar support for putting contracts on classes yet. I really should have added them before, it's now at the top of my stack.
Interestingly enough, your first example of putting a whole contract on the class should have worked since Node
compiles to a normal constructor and contracts work fine on them. Not sure yet what is causing the problem but I'll look into it.
Thats a pity as my app is OO and classes was first place where i wanted to put the contracts. I'll be looking forward for them.
Thanks for a great library and idea. It'll be really powerful once used.
BTW tested on node 0.7.0 and 0.5.10, same results.
After deeper checking there an issue with two things here:
- The -> wont work for classes, ==> need to be used.
- The following line:
address: (NodeAddr) -> Any
Changing NodeAddr to Any makes it all passing and class is initialized correctly.
Interesting...
- The -> wont work for classes, ==> need to be used.
This is definitely a bug. The ==>
contract is supposed to restrict the function it is guarding to only be used with new
but ->
should work for both new
and non-new
calls.
I needed to use ==> because -> doens't trigger options.newSafe, thanks to which proxy returns new instance instead of a return value of the constructor.
Additionally, to have a class contracted fully, you have to do 2 things:
- Apply contract in the same file.
- Divide class contract to 2 custom ones: constructor and the instance body (object).
- Apply all instance body contracts onto the prototype, possibly using the following code:
# TServer is a contract
# Server is a class
for prop, Tcontr of TServer.oc
continue if not Server::[prop] or
prop is 'constructor'
Server::[prop] :: Tcontr
Server::[prop] = Server::[prop]
Has there been any movement on this issue?
Sorry, no. Haven't had time to work on this project in a while.
+1 for this
:+1: for class suppport!