Is there an easy way to list all callables from an imported JS package? It's a continuation of my previous question: the package is imported straight from the runtime; K6 authors changed something between v0.52 and v0.53 so whenever I run against a newer version, it errors out the function I'm calling is not there anymore. Changelog doesn't help, sources don't help - it should be there, and the source with the function definition hasn't been changed for quite some time. So I wanna look around what's actually available, and I can't quite understand how to do it. All I have working now is (:require ["k6/http" :as http]), and the call that broke is http/get.
kinda hard to say without knowing what the actual runtime is capable of
maybe (js/Object.keys http)?
also a quick check in the docs has this example JS bit import http from 'k6/http';
this does not translate to what you have above
see the examples in this section https://shadow-cljs.github.io/docs/UsersGuide.html#_using_npm_packages
basically should be (:require ["k6/http$default" :as http])
Ohhhh. Let me check quickly with both versions! The runtime is Grafana's own fork of goja engine, if that helps. Says to be fully compatible with ES5.
With v0.52, it gives everything as it should with an old require:
["TLS_1_0","TLS_1_1","TLS_1_2","TLS_1_3","OCSP_STATUS_GOOD","OCSP_STATUS_REVOKED","OCSP_STATUS_SERVER_FAILED","OCSP_STATUS_UNKNOWN","OCSP_REASON_UNSPECIFIED","OCSP_REASON_KEY_COMPROMISE","OCSP_REASON_CA_COMPROMISE","OCSP_REASON_AFFILIATION_CHANGED","OCSP_REASON_SUPERSEDED","OCSP_REASON_CESSATION_OF_OPERATION","OCSP_REASON_CERTIFICATE_HOLD","OCSP_REASON_REMOVE_FROM_CRL","OCSP_REASON_PRIVILEGE_WITHDRAWN","OCSP_REASON_AA_COMPROMISE","url","CookieJar","cookieJar","file","get","head","post","put","patch","del","options","request","asyncRequest","batch","setResponseCallback","expectedStatuses","default"]
v0.54 output is empty.
With $default require, v0.52 still works, while (js/Object.keys http) throws
TypeError: Cannot convert undefined or null to object
at keys (native)
guess they moved stuff to the default export then .. JS devs are always fun like that 😛
at least they documented it I guess https://grafana.com/docs/k6/latest/release-notes/v0.53.0/#breaking-changes
Could you explain please? %) I'm so new to the JavaScript game, I don't understand the intricacies and implications; I'm more used to the world where a symbol is either explicitly exported or not, and can be linked against or not :D
> they moved stuff to the default export then
But then (:reuqire ["k6/http$default" :as http]) should have worked as far as I understand, no?
not a clue. can't tell which version their docs reference 😛
(:require ["k6/http" :as http]) and listing all the properties should at least have a default property
..."expectedStatuses","default"] like that one
Sadly, no, this is literally the log line:
INFO[0000] [] source=consoleEmpty array.
hmm and just trying (js/Object.keys http/default)?
what does (type http) say? is it undefined or an actual object?
Throws just like with "k6/http$default" require:
ERRO[0000] TypeError: Cannot convert undefined or null to object
at keys (native)I guess it would be undefined, let me check for sure.
Yep, undefined.
INFO[0000] undefined source=consoleIf I try (type http) with $default require, it gives null .
hmm. don't know enough about the runtime to comment I guess. maybe just try a regular JS file and see what happens?
like import http from "k6/http"; console.log(http); and run that?
no clue how that all works, but if that gives you the actual object we can dig deeper on the CLJS side 😛
I have a TypeScript test that works (or at least USED TO work with old K6 version), let me try and run that against the new version.
I assume you added k6/http to the :keep-as-import set?
Correct, else it wouldn't build. 🙂
just checking 😉
Ah, okay, so from TypeScript:
here be dragons
{"TLS_1_0":"tls1.0","TLS_1_1":"tls1.1","TLS_1_2":"tls1.2","TLS_1_3":"tls1.3","OCSP_STATUS_GOOD":"good","OCSP_STATUS_REVOKED":"revoked","OCSP_STATUS_SERVER_FAILED":"server_failed","OCSP_STATUS_UNKNOWN":"unknown","OCSP_REASON_UNSPECIFIED":"unspecified","OCSP_REASON_KEY_COMPROMISE":"key_compromise","OCSP_REASON_CA_COMPROMISE":"ca_compromise","OCSP_REASON_AFFILIATION_CHANGED":"affiliation_changed","OCSP_REASON_SUPERSEDED":"superseded","OCSP_REASON_CESSATION_OF_OPERATION":"cessation_of_operation","OCSP_REASON_CERTIFICATE_HOLD":"certificate_hold","OCSP_REASON_REMOVE_FROM_CRL":"remove_from_crl","OCSP_REASON_PRIVILEGE_WITHDRAWN":"privilege_withdrawn","OCSP_REASON_AA_COMPROMISE":"aa_compromise"}
this is produced with
import http from "k6/http";
console.log("here be dragons");
console.log(http);
with latest k6:
$ k6 version
k6 v0.54.0 (commit/baba871c8a, go1.23.1, linux/amd64)
and import * as http from "k6/http";?
Seems like the same exact output:
{"TLS_1_0":"tls1.0","TLS_1_1":"tls1.1","TLS_1_2":"tls1.2","TLS_1_3":"tls1.3","OCSP_STATUS_GOOD":"good","OCSP_STATUS_REVOKED":"revoked","OCSP_STATUS_SERVER_FAILED":"server_failed","OCSP_STATUS_UNKNOWN":"unknown","OCSP_REASON_UNSPECIFIED":"unspecified","OCSP_REASON_KEY_COMPROMISE":"key_compromise","OCSP_REASON_CA_COMPROMISE":"ca_compromise","OCSP_REASON_AFFILIATION_CHANGED":"affiliation_changed","OCSP_REASON_SUPERSEDED":"superseded","OCSP_REASON_CESSATION_OF_OPERATION":"cessation_of_operation","OCSP_REASON_CERTIFICATE_HOLD":"certificate_hold","OCSP_REASON_REMOVE_FROM_CRL":"remove_from_crl","OCSP_REASON_PRIVILEGE_WITHDRAWN":"privilege_withdrawn","OCSP_REASON_AA_COMPROMISE":"aa_compromise"}hmm then I don't see why the CLJS version wouldn't work. there is no difference in the type of imports used
you can check the generated sources? maybe there is another mistake happening somewhere
The generated, you mean the CLJS compiled to JS ones?
I mean the printed object is still weird because its missing get and stuff, but that could just be the printer
yeah the :output-dir files
If I do Object.keys(), btw, I see the methods - get, head, post and all that; with both
import * as http from and import http from
just grep for k6/http in the :output-dir. that should find the import
import*as esm_import$k6$http from"k6/http";yeah ok. then that should be ok
That corresponds to
(:require ["k6/http$default" :as http]))nah that will just end up using esm_import$k6$http.default basically, so the same as (:require ["k6/http" :as http]) + http/default would
if they actually implement ESM correctly then that should be valid
Ah I see.
maybe try in the JS variant if that works there
import * as http from "k6/http"; and console.log(http.default)
I gotta go. be back in about 2 hours
I appreciate your help @thheller, I'll play around with it some more. I'm gonna be back myself in ~3.5 if you're still here, that'd be great.
import * as http from "k6/http";
console.log(http.default);
still works:
{"TLS_1_0":"tls1.0","TLS_1_1":"tls1.1","TLS_1_2":"tls1.2","TLS_1_3":"tls1.3","OCSP_STATUS_GOOD":"good","OCSP_STATUS_REVOKED":"revoked","OCSP_STATUS_SERVER_FAILED":"server_failed","OCSP_STATUS_UNKNOWN":"unknown","OCSP_REASON_UNSPECIFIED":"unspecified","OCSP_REASON_KEY_COMPROMISE":"key_compromise","OCSP_REASON_CA_COMPROMISE":"ca_compromise","OCSP_REASON_AFFILIATION_CHANGED":"affiliation_changed","OCSP_REASON_SUPERSEDED":"superseded","OCSP_REASON_CESSATION_OF_OPERATION":"cessation_of_operation","OCSP_REASON_CERTIFICATE_HOLD":"certificate_hold","OCSP_REASON_REMOVE_FROM_CRL":"remove_from_crl","OCSP_REASON_PRIVILEGE_WITHDRAWN":"privilege_withdrawn","OCSP_REASON_AA_COMPROMISE":"aa_compromise"}Another thing: with the old k6 version, with this import:
["k6/http" :as http]
both
(js/console.log (js/Object.keys http/default))
and
(js/console.log (js/Object.keys http))
print out correct keys:
["TLS_1_0","TLS_1_1","TLS_1_2","TLS_1_3","OCSP_STATUS_GOOD","OCSP_STATUS_REVOKED","OCSP_STATUS_SERVER_FAILED","OCSP_STATUS_UNKNOWN","OCSP_REASON_UNSPECIFIED","OCSP_REASON_KEY_COMPROMISE","OCSP_REASON_CA_COMPROMISE","OCSP_REASON_AFFILIATION_CHANGED","OCSP_REASON_SUPERSEDED","OCSP_REASON_CESSATION_OF_OPERATION","OCSP_REASON_CERTIFICATE_HOLD","OCSP_REASON_REMOVE_FROM_CRL","OCSP_REASON_PRIVILEGE_WITHDRAWN","OCSP_REASON_AA_COMPROMISE","url","CookieJar","cookieJar","file","get","head","post","put","patch","del","options","request","asyncRequest","batch","setResponseCallback","expectedStatuses"]
(as expected), BUT
(js/console.log (type http))
gives null , as well as (type http/default) ; same story with "k6/http$default" require.
Which is kind of mind-boggling, so http is null to CLJS but if it's passed to JS runtime the properties can be accessed?..There's no such thing as "passing to JS runtime" - it's all there already.
(type http) might return nil even when the object is not nil itself.
Ah, I see. Just seems strange that a call to Clojure's type's giving nil, but js/Object.keys shows it's definitely not nil.
Types in JS are weird.
I filed a bug for k6 and it's getting a fix it seems: https://github.com/grafana/k6/pull/4058
in clojure I can extend a protocol to Object to get a kind of default implementation, is there something like that in clojurescript?
https://github.com/clojure/clojurescript/blob/master/src/main/cljs/clojure/core/protocols.cljs#L19
perfect, thank you
are there any provisos, like it only works with extend-protocol and not extend-type? (getting errors still, might not be related, working on getting a big chunk of clojure code working in clojurescript)
dunno about extend-type. seems like default is not a type to me 😛
there is object but its kinda weird
yeah, I think maybe default is working, but I translated some interop incorrectly
actually I think what it is is the closure compiler not knowing about Promise.withResolvers and mangling it
(it was that)