The proxy object only works because I specifically wrote the Proxy’s getOwnPropertyDescriptor
trap to lie and say it’s a value instead of a getter
Yeah, that was a clever hack I’m just saying RunKit should not be triggering your trap at all, because triggering it violate the constraint of not running code that could result in side effects.
For point (1), by “serialization format,” I assume you mean the format used to serialize the object being rendered, not to serialize the the render function? Either way, I’ll take your word for it since I don’t know anything about this
Yeah that value serialization format. It’s just a developer experience issue that we’d have to solve. We’re serializing every field of your value, including preserving circular references, metadata about the fields like if their getters/setters/enumerable, etc. It’s just not the most friendly format to work with, so we’d want to expose something a little better. Not a showstopper for this though.
In point (3), I assume those asynchronous edge cases are things like window.alert()
? There has to be a way to sidestep that…
Not exactly, so at a high level: the render function will need to be sandboxed in an iframe. We already do this with rendered HTML in a secure way. But the iframe still needs to be able to communicate back to the parent window to let it know things like “hey, I’m done rendering”, “hey, my height changed”, or “whoops, I crashed”. So the iframe will postMessage() back to the parent window with those messages. (RunKit will control the messages).
maybe running it in a promise and racing it against a timeout of some kind? It’s an interesting problem, but since you have the standard viewers to fall back on, hopefully it shouldn’t have to be a showstopper
So (with the architecture I described above) from RunKit’s perspective all render() functions will be asynchronous. Currently all our value viewer stuff is written in a way that assumes the render will never crash (since they’re 1st party viewers) and that they can be rendered synchronously (because they’re being rendered in the main window’s context). So it’s not trivial for us to just fallback to our 1st party viewers. These concerns kind of already exist for the “simple viewers” since you can still run JS in them too, but since they’re geared more towards just providing static HTML, we didn’t build in some of those checks (they’re just being rendered as a special kind of “rendered html” viewer). So yeah, I agree, this should not be a showstopper either.
And while we’re on the topic we’ve talked about two other related things. We think it would be really nice if we could give 3rd party developers access to our own built in viewers. So you could render part of your value in a custom way, but then for the less interesting parts of your object, you could just revert to our 1st party viewers. Unsure how useful that would actually be, and it’s got it’s own usability issue too. Also we think it would be cool if the objects themselves didn’t have to have the custom symbol. So instead a package could “register” a viewer and describe the shape of the value it would match. We think this would be useful because it now lets your API return non-object values and still be match. For example, our built in coordinate viewer will match on an array of numbers that look like lat-long values. If you had a list of Dog objects, you might want to render that list as a whole rather than each individual Dog object. Anyway, that’s a whole separate issue.
Instead of avoiding calling user functions at all costs, could you just fork the environment to run them in?
Yeah, this is also something we’ve considered. Also for letting the user trigger getters. It has a ton of advantages like giving you access to all of npm. The second point you made about disappearing side effects would be my main concern. I could imagine a bunch of ways that could end up with some confusing behavior. But I think it’s potentially a good strategy.
Sorry for the long post, I wanted to kind of lay out the constraints on our end and the weighed concerns/advantages. I appreciate your thoughts and insights here!
- Randy