ghcjs / ghcjs-base

base library for GHCJS for JavaScript interaction and marshalling, used by higher level libraries like JSC
MIT License
45 stars 67 forks source link

How do I convert a JSVal to an Object? #53

Closed chadaustin closed 7 years ago

chadaustin commented 8 years ago

I'm exposing an API to JavaScript that takes a JavaScript Object and sets some properties on it. syncCallback2 gives me the JSVals passed by the caller, but I cannot figure out how to convert it to a JavaScript.Object.Object so I can pass it to setProp. Seems every useful conversion function is hidden in an internal model. I ended up simply using unsafeCoerce, which is not very satisfactory of course.

jamesthompson commented 8 years ago

:+1: I too am struggling with this - I can't resolve setProp from GHCJS.Foreign either - which is weird on the latest stack definition: ghcjs-0.2.0.20151230.3_ghc-7.10.2

An up-to-date example of how to do haskell API -> javascript caller would be awesome, particularly with an error first callback node style. Seems there's quite a lot of interest in this from the community:

http://stackoverflow.com/questions/29967135/how-to-call-haskell-from-javascript-with-ghcjs/34348005?noredirect=1#comment57252240_34348005

mgsloan commented 8 years ago

ghcjs-base still needs quite a bit of work done around marshaling and other utilities related to newtype wrappers around JSVal. Technically the right thing to do is use JavaScript.Cast.cast, but I don't see many instances of Cast in ghcjs-base, and you'd need one for Object. Note that not all JSVal are objects, due to primitive types:

x = 1
// 1
x["foo"] = "wat"
// "wat"
x["foo"]
// undefined

For now I'd use coerce, which still gives up type safety, but at least ensures you are coercing something that has the same representation.

crocket commented 8 years ago

Where do I find coerce? I could find only unsafeCoerce on http://hackage.haskell.org/package/base-4.9.0.0/docs/Unsafe-Coerce.html

hamishmack commented 7 years ago

@crocket, I am guessing you found it by now, but it is here https://hackage.haskell.org/package/base-4.9.1.0/docs/Data-Coerce.html

hamishmack commented 7 years ago

Oh I think the other key thing here is to do import JavaScript.Object.Internal (Object(..)) as JavaScript.Object does not export the constructor (needed for coerce to work).

benjamin-hodgson commented 7 years ago

@hamishmack Am I really supposed to import the Object constructor from JavaScript.Object.Internal in order to convert Objects to and from JSVals? I feel dirty doing so. Why aren't there ToJSVal/FromJSVal instances? Would you accept a pull request with those instances?