欢迎!请参阅关于页面以了解更多关于其工作方式的信息。
Dirac DevTools REPL依赖于适当的源映射(链接:1)。当我将"#js {}"输入到REPL提示符时,评估会工作,但生成的JavaScript代码片段的源映射是错误的。关联的源映射的sourcesContent类似于#object(link: cljs.tagged_literals.JSValue 0x34d692f3 "cljs.tagged_literals.JSValue@34d692f3")。而这并非用户输入的内容。而且这不是我可以再次解析的有效cljs源代码,用于代码补全。
问题有些微妙。在生成源映射信息时,REPL代码会尝试查看:source元数据(链接:2),如果不存在,它会简单地使用pr打印表单。我们得到Clojure样式的打印,因为JSValue没有实现ClojureScript打印,如CLJS-733中报道的。
而不是实现CLJS-733中拒绝的观点。我专注于第一个带有:source元数据的代码路径。结果发现,如果给定的形式支持元数据协议,则会添加:source。最容易的想法是将JSValue从deftype更改为defrecord。
我确认这修复了Dirac中的REPL问题。现在我得到了用户输入的原始源代码。
请注意,类似的問題也存在于#uuid和#inst标签中。它们主要是因为它们的打印机兼容Clojure和ClojureScript,所以大多数工作。但从本质上讲,用户可能会收到与在REPL中输入的内容不同的源映射源。例如,将缺少空格。这可能会引起困惑,因为读者报告的行/列信息可能与由打印产生的这个人为的源映射内容不匹配。
我相信修复方法是将来跨标签值创建类似JSValue的对象,并使用这个包裹值进行操作。这与#queue相同。这将使cljs.tagged-literal代码保持一致,因为来自数据读者的每个形式都会在包裹器内部。它将使包裹器上的任意元数据成为可能。
作为备注我注意到读者元数据丢失了。它们没有从读者产生的表单转移到生成的标签值表单中。我的第二个目标是复制读者的元数据。不幸的是,当前的工具.reader实现无法实现这一点。我可以从传递的形式中获取读者元数据,但这并不是全景,它只描述了在标签已消费后内容的元数据。我需要从标签本身获取元数据,这个标签通过数据读者调用传入(链接:3)。
我不知道缺少了标签值上的读者元数据是否导致了任何实际的这个问题,但我认为理想情况下应该修复。例如,在实现cljs-oops中的错误报告时,我必须处理这个边缘情况(链接:4),因为在某些边缘情况下缺少行/列元数据。
(链接:1) https://github.com/binaryage/dirac/releases/tag/v0.8.0(链接:2) https://github.com/clojure/clojurescript/blob/960bb9b778190aa7359acb2f74cc61d452cef2ae/src/main/clojure/cljs/repl.cljc#L476(链接:3) https://github.com/clojure/tools.reader/blob/3f36a18a6c5d53a4fc718822131ee75625fd44dc/src/main/cljs/cljs/tools/reader.cljs#L834(链接:4) https://github.com/binaryage/cljs-oops/blob/d530a3cdf8cbab39bd2699c36caded4414224c50/src/lib/oops/reporting.clj#L29
评论者:darwin
我刚刚注意到,由于defrecord的改变,一些测试失败了。我最初实现使用的是带有clojure.lang.IObj实现的deftype。但这有一个缺点,就是重用val作为存储元数据的目标。这在一般情况下可能不是IObj。而且还需要为bootstrapped进行单独的实现。而且我也不想将另一个字段添加到deftype中。我希望您能提出建议,如何正确实施这一点。
对它的又一次尝试——这次我依赖于val字段必须是向量或映射。因此,可以在不向deftype添加新字段的情况下为JSValue携带元数据。
测试通过。