[{:function <string>
:file <string>
:line <integer>
:column <integer>}*]
本頁記錄了對使用 cljs.repl 中提供的功能的自訂 REPL 的要求的最新變更。這些變更的目的是大幅縮短所有 ClojureScript REPL 的啟動時間,並簡化 REPL 狀態與已編譯原始碼的同步。這是透過重複使用全域可用的編譯快取基礎架構來實現的。事實上,目前可以啟動將 :output-dir
設定為現有編譯快取的 REPL,而無需進行任何分析或編譯。
在新的基礎架構下,所有內建 REPL 都可以在現代硬體上於一秒內或更短的時間內啟動。
為了盡快啟動 REPL,REPL 必須實作新的 2 個引數的 -setup
函數,該函數會採用典型的編譯器建置選項。在過去,-setup
允許是非同步的 - 現在不再支援此功能,REPL 現在必須在 -setup
期間編譯和載入 cljs.core 及其所有依賴項。在 -setup
中,REPL 應使用建置選項將編譯後的 JavaScript 和分析資訊快取到預期的位置。請注意,雖然可以串流使用者輸入的已編譯表單,但應盡一切可能避免載入命名空間 - REPL 應依賴目標環境來解釋 goog.require
。這有許多好處,包括精確的原始碼對應資訊。
新的 Node.js REPL 是新模式的一個很好的例子。Node.js REPL 很短,因為它依賴 Node.js 執行環境本身來解釋 goog.require
。
檢查 cljs.repl/load-file
和 cljs.repl/load-namespace
將闡明新方法
給定一個命名空間,確保它已編譯。
計算檔案的 goog.addDependency
字串並評估它。
為命名空間發出 goog.require
陳述式並評估它。
REPL 應該覆寫全域 CLOSURE_IMPORT_SCRIPT
函式以取得自訂的 goog.require
行為。
在新變更下,REPL 不需要再麻煩地直接在其 Clojure 實作中明確追蹤已載入的程式庫。相反,REPL 應安排確保 JavaScript 評估環境符合 cljs.core/loaded-libs
,必要時將所需的邏輯嵌入 CLOSURE_IMPORT_SCRIPT
中。
歷史:這以前只是因為如果已載入命名空間,goog.provide
會擲出例外。這是一個完全錯誤的錯誤,旨在教「初學者」。透過猴子修補 goog.isProvided_
使其成為永遠傳回 false 的函式,可以抑制該錯誤。同樣,Node.js REPL 也是這種修補以及在 CLOSURE_IMPORT_SCRIPT
實作中符合 loaded-libs
的一個很好的例子。
所有 REPL 都支援幾個「特殊函式」。特殊函式必須採用 REPL 環境、分析環境、表單和(選擇性)編譯器建置選項。開箱即用的提供了 in-ns
、require
、load-file
和 load-namespace
。
自訂 REPL 不應直接呼叫 println
、print
或 flush
,而應符合傳遞給 -setup
的 opts
(第二個引數)中與 :print
、:print-no-newline
和 :flush
相關聯的值。另請注意,與 :print
和 :print-no-newline
相關聯的函式只接受一個引數。
現在,所有 REPL 都可以實作一個新的協定,以便「免費」取得原始碼對應支援。如果評估的結果為 :exception
,則如果 REPL 評估環境符合 cljs.repl/IParseStacktrace
,則 REPL 基礎架構會叫用 -parse-stacktrace
。REPL 評估環境將會收到原始 JavaScript 堆疊追蹤字串、整個原始錯誤值以及所有傳遞給 REPL 的建置選項。然後,REPL 評估環境可以傳回規範的堆疊追蹤,其格式必須為
[{:function <string>
:file <string>
:line <integer>
:column <integer>}*]
:file
必須是相對於 :output-dir
的沒有 URI 協定的 URL 樣式路徑(正斜線)。
透過此提交,合約已稍微放寬以容納 REPL 定義的函式::file
值可以以 <
開頭,以表示不存在原始碼,且追蹤中將會發出 "NO_SOURCE_FILE"
。
自訂 REPL 可能仍然想要進一步自訂或控制堆疊追蹤的列印。提供了一個掛鉤,REPL 評估環境可以實作 cljs.repl/IPrintStacktrace
。-print-stacktrace
採用對應的規範堆疊追蹤、整個原始錯誤值以及所有傳遞給 REPL 的建置選項。
原始作者:David Nolen