binaryage / cljs-oops

ClojureScript macros for convenient native Javascript object access.
Other
351 stars 13 forks source link

Can't call methods on strings #13

Closed cogwheel closed 7 years ago

cogwheel commented 7 years ago

This case of (. doesn't work when converted to use ocall:

(.contains "foobar" "foo")

This returns true as expected. When I do this:

(ocall "foobar" "contains" "foo")

I get "Oops, Unexpected object value (string)"

darwin commented 7 years ago

Yes, this is by design. cljs-oops does more strict validation of target object[1] and emits warnings when operating on numbers, booleans, strings or cljs instances. Using cljs-oops on strings is likely a mistake, because you can do it using clojure.string, goog.string or using the dot notation (., because string API is 100% covered by default externs.

[1] https://github.com/binaryage/cljs-oops/blob/a356c548077bf499409f3485569147663a5793bd/src/lib/oops/codegen.clj#L35-L51

darwin commented 7 years ago

Actually thinking about this more. I should allow it when you change config:runtime-unexpected-object-value. Right now it does not work, because failed validation does not generate proper code.

Will fix it in the next release. So people can opt-out from validation.

cogwheel commented 7 years ago

Fair points. It was just an unexpected moment where every problem we had in our production build was fixed by converting to ocall except this one. I ended up using clojure.string as you noted.

Engelberg commented 6 years ago

Is this the same reasoning for why cljs-oops won't let you call methods on Date objects? It's hard to know what things are covered by default externs, so I tend to use cljs-oops for any calls to the js world, so I was caught off-guard when I got an error using (ocall date "getTime").

darwin commented 6 years ago

Here is the current dev-mode validation code: https://github.com/binaryage/cljs-oops/blob/b8a2e8b3d8b9b2740e85ef7bcb0a1a4dc2b72276/src/lib/oops/codegen.clj#L57

goog/isDateLike is a special case there

I'm open to relaxing those rules, because that won't require changes to existing code.

Engelberg commented 6 years ago

Sounds like this is just my own ignorance -- is there some list somewhere of all the js classes and methods that clojurescript already knows about and won't mangle in advanced mode?

darwin commented 6 years ago

AFAIK default externs is a Google Closure Compiler thing. ClojureScript compiler does not add any of their own (but I might be wrong here).

Default externs are evolving with each new revision of Closure Compiler: https://github.com/google/closure-compiler/tree/master/externs