Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ES6 tagged template literal escape hatch #4070

Closed
jfrolich opened this issue Dec 28, 2019 · 9 comments
Closed

ES6 tagged template literal escape hatch #4070

jfrolich opened this issue Dec 28, 2019 · 9 comments
Labels
enhancement stale Old issues that went stale

Comments

@jfrolich
Copy link

Some modern libraries rely on the tagged template literal (styled components, graphql libraries), and it is often necessary to use the tagged template literal to have good interop with these libraries.

My specific use-case at the moment is Gatsby. It's a static site generator, and it uses babel plugins to extract graphql queries and pre-render them. I think I am pretty far with getting this to work with the [%bs.raw] extension and a PPX, but it's a hack and not sure if my attempt will be successful.

Many libraries require the tagged template literal do do fancy compiler stuff. There are some Apollo utilities that extract all the queries in the source code into a manifest which can be used for several things. All of that is not possible when using Bucklescript 😢.

It would be great to have an escape hatch for this to allow the interop.

Option A:

Compile the current interpolation to the ES6 string literal:

{j|你好,$world|j} => `你好,${world}`

And then add something to the syntax to support the tagged string literal (or probably a better syntax variant to this):

{graphql|你好,$world|graphql} => graphql`你好,${world}`

The nice thing is that the functionality of the default interpolation will be the same, and the old transformation can be used for es5, but adds the tagged template literal functionality when on es6.

Option B:

An extension:

[%tagged_template_literal]
external graphql: (string) => parsedGraphql = "graphql"

The downside is that this removes the tagged (interpolation) part of the template literal, so it would not be great for things like styled components.

I guess with ES6 now pretty well supported in most browsers it would be good timing to encourage users of Bucklescript to use the ES6 target as the default.

@jfrolich
Copy link
Author

Another great upside of this solution is that the types are preserved (of the tagged template literal function)

@jfrolich
Copy link
Author

Hmm pretty hard to do it now with [%bs.raw]. Is there an easy way to get the name of a literal after it's compiled to javascript? (or a way to ensure the literal is the same in javascript) (as the bucklescript name and the javascript name often differs, like adding a $1).

@bobzhang
Copy link
Member

the thing is es6 tagged literal is completely untyped which is an unsafe feature. Why is hard to do with raw?

@jfrolich
Copy link
Author

jfrolich commented Jan 27, 2020

@bobzhang: Because if the template literal tag for instance is Gatsby.graphql, in raw I cannot indicate I'd like to use that reference for the template literal. So if Gatsby is not used anywhere else, it's not added as an import. So a way to pass a reference to a raw statement and get the name as in JavaScript (sometimes the name is also different in JS like Gatsby$1.graphql.) would be also a solution.

@bobzhang
Copy link
Member

it is not beautiful but doable:

let bq = [%raw"ql => ql `hello`"]

bq is a function, then you can bind Gatsby.graphql and pass it to bq

Note es6 tagged template literal can do arbitrary things in the runtime, it is an unsafe feature

@bobzhang
Copy link
Member

let bq = [%raw"(ql,x) => ql `hello $x `"]

This works too

@jfrolich
Copy link
Author

jfrolich commented Feb 12, 2020

@bobzhang: it needs to be static for most purposes I need it for, so it can't be the result of a function call. The feature you alluded to earlier that in the future there might be a raw that takes parameters and inlines the function call would be a solution though.

@jfrolich
Copy link
Author

Note es6 tagged template literal can do arbitrary things in the runtime, it is an unsafe feature

Isn't that true for all externals? There might be a way if tagged template literals are exposed within bucklescript without raw to restrict the types and make them typesafe?

@stale
Copy link

stale bot commented May 3, 2023

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale Old issues that went stale label May 3, 2023
@stale stale bot closed this as completed May 12, 2023
@zth zth mentioned this issue May 14, 2023
4 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement stale Old issues that went stale
Projects
None yet
Development

No branches or pull requests

2 participants