2016-01-04 4 views
0

У меня есть программа (написанная в Clojure), которая вводит некоторый JS-код в JS-функцию, а затем оценивает ее через Nashorn. У меня нет контроля над прохождением кода (он может содержать кавычки, простые кавычки ...).хранить произвольный код JavaScript в строковой переменной

Это выглядит следующим образом:

;; Clojure 
(eval-str (str "print(evaluateCode(\"" s " \"))")) 

// equivalent code in pseudo-js just for those not reading Clojure fluently 
evalJS("println(evaluateCode(" + arbitraryJS + "))") 

evaluateCode функция уже загружена.

// already loaded in Nashorn 
function evaluateCode(code) { 
    // do something with the code 
    //... 
    eval(code); 
} 

Это хорошо работает для простых программ, например. если arbitraryJS = "var a=123; print(a); return a;".

Но как только программа содержит кавычки, она ломается. ех. "var a = 123; print("a is now", a);"

Примечание: фактический код - there.

+1

А как насчет того, чтобы избегать цитат типа « – Berger

+0

», используйте другие кавычки? '' ', Потому что я думаю, что вы создаете новые строковые литералы таким образом –

+0

@Berger Я думаю, что могут быть угловые случаи (строки шаблонов приходят на ум, возможно комментарии) – nha

ответ

2

Вам нужно избежать строки. поместите \ перед каждым» Если вам нужно \ сам использовать его в два раза \\

К сожалению, я не имею права комментировать еще ....:/

+0

Я ответил на @Berger то же самое, но как бы вы обращались в угловые случаи (если они есть)? комментарии для комментариев, строки шаблонов, но могут быть и другие. – nha

+0

комментарии используют обычные косые черты и не должны быть проблемой. Для разрыва строки с помощью \ n: строки шаблонов, похоже, тоже работают. Yust попробуйте: 'var n = var x = 0; // устанавливает var \ n console.log (x); var b = \ 'Hi \ n $ {2 + 13}! \'; console.log (b)/* stuff stuff */";' – MisteriosM

+0

Для комментариев я думал о чем-то больше: 'var a =" abc ", b = 'ABC;/*" a "и' b ' обе переменные */\ n''. Или, может быть, '' 'var a =" abc ", b = 'ABC;' Это строка шаблона. Могу ли я содержать "кавычки", и должны ли они снова цитироваться? '' ''. – nha

1

Я хотел бы предложить, чтобы избежать кавычки и обратные слэши . Я хотел бы пойти на одинарные кавычки, как JS разделители строк, как в Clojure вы обязаны использовать двойные кавычки используются для обозначения строк:.

;; Clojure 
(eval-str (str "print(evaluateCode('" 
       (clojure.string/replace s #"(['\\\\])" "\\\\$1") 
       "'))")) 

поиска и замены узоров каждая из которых имеет четыре обратных слэша Как и в Clojure обратной косой черты побег символа, они фактически обозначают только две обратные косые черты. В регулярных выражениях обратная косая черта - также escape-символ, поэтому в конце они просто обозначают один, буквальный обратный слэш каждый. Таким образом, это означает, что «префикс любого вхождения обратной косой черты или цитаты с обратной косой чертой».

Вы не должны беспокоиться о комментариях и шаблонах и т. Д., Поскольку escape-символы существуют только в Clojure (после замены), но решаются в момент, когда полная строка обрабатывается механизмом Javascript. Функция valuCode никогда не увидит escape-символы, но простое значение s.

Пример

;; Clojure 
(def s "a = 'test'; // 'test' used here") 
(eval-str (str "print(evaluateCode('" 
       (clojure.string/replace s #"(['\\\\])" "\\\\$1") 
       "'))")) 

Это будет оценивать на:

(eval-str "print(evaluateCode('a = \\'test\\'; // \\'test\\' used here'))") 

Обратите внимание, что обратные косые удваиваются в вышеупомянутом представлении, но это потому, что Clojure нуждается. Фактическая строка имеет только однократное появление обратных косых черт.Если вместо вызова eval-str, вы могли бы назвать println с теми же аргументами, вы получите этот результат:

печати (evaluateCode ('а = \' Test \ '; // \' \ 'тест, используемый здесь'))

это строка интерпретируется движком Javascript, поэтому он интерпретирует обратную косую черту, как экранирующих символов, передавая чистую строку evaluateCode.

Так что если evaluateCode выглядел следующим образом:

function evaluateCode(code) { 
    alert(code); 
} 

Он будет производить это предупреждение:

а = 'тест'; // 'test', используемый здесь

Таким образом, экранирующие обратные косые черты вообще отсутствуют в Javascript. Он увидит то же самое значение, что и символ Clojure s.