on master help sign in
Properly escape strings and don't use infix op
0ff8a91Evan Czaplicki
src/Generate/JavaScript/Builder.hs+58−34
@@ -197,14 +197,6 @@ fromVarDecl indent (VarDecl _ (Id _ name) maybeExpr) =
197data Lines = One | Many deriving (Eq)
197data Lines = One | Many deriving (Eq)
198
198
199
199
200−{-# INLINE (!) #-}
201−(!) :: a -> b -> (a, b)
202−(!) a b =
203− (a, b)
204−
205−infix 0 !
206−
207−
208merge :: Lines -> Lines -> Lines
200merge :: Lines -> Lines -> Lines
209merge a b =
201merge a b =
210 if a == Many || b == Many then Many else One
202 if a == Many || b == Many then Many else One
@@ -238,28 +230,28 @@ fromExpr :: Builder -> Grouping -> Expression a -> (Lines, Builder)
238fromExpr indent grouping expression =
230fromExpr indent grouping expression =
239 case expression of
231 case expression of
240 StringLit _ string ->
232 StringLit _ string ->
241− One ! fromString (show string)
233+ (One, quoted string)
242
234
243 RegexpLit _ _ _ _ ->
235 RegexpLit _ _ _ _ ->
244 error "TODO"
236 error "TODO"
245
237
246 NumLit _ n ->
238 NumLit _ n ->
247− One ! realFloat n
239+ (One, realFloat n)
248
240
249 IntLit _ n ->
241 IntLit _ n ->
250− One ! decimal n
242+ (One, decimal n)
251
243
252 BoolLit _ True ->
244 BoolLit _ True ->
253− One ! "true"
245+ (One, "true")
254
246
255 BoolLit _ False ->
247 BoolLit _ False ->
256− One ! "false"
248+ (One, "false")
257
249
258 NullLit _ ->
250 NullLit _ ->
259− One ! "null"
251+ (One, "null")
260
252
261 ArrayLit _ exprs ->
253 ArrayLit _ exprs ->
262− Many !
254+ (,) Many $
263 let
255 let
264 (anyMany, builders) =
256 (anyMany, builders) =
265 linesMap (fromExpr indent Whatever) exprs
257 linesMap (fromExpr indent Whatever) exprs
@@ -274,7 +266,7 @@ fromExpr indent grouping expression =
274 "[" <> commaSep builders <> "]"
266 "[" <> commaSep builders <> "]"
275
267
276 ObjectLit _ fields ->
268 ObjectLit _ fields ->
277− Many !
269+ (,) Many $
278 let
270 let
279 deeperIndent =
271 deeperIndent =
280 deeper indent
272 deeper indent
@@ -292,10 +284,10 @@ fromExpr indent grouping expression =
292 "{" <> commaSep builders <> "}"
284 "{" <> commaSep builders <> "}"
293
285
294 ThisRef _ ->
286 ThisRef _ ->
295− One ! "this"
287+ (One, "this")
296
288
297 VarRef _ name ->
289 VarRef _ name ->
298− One ! fromId name
290+ (One, fromId name)
299
291
300 DotRef _ expr (Id _ name) ->
292 DotRef _ expr (Id _ name) ->
301 makeDot indent expr name
293 makeDot indent expr name
@@ -311,7 +303,9 @@ fromExpr indent grouping expression =
311 (lines, builder) =
303 (lines, builder) =
312 fromExpr indent Atomic expr
304 fromExpr indent Atomic expr
313 in
305 in
306+ ( lines
314− lines ! parensFor grouping (fromPrefix op <> builder)
307+ , parensFor grouping (fromPrefix op <> builder)
308+ )
315
309
316 UnaryAssignExpr _ _ _ ->
310 UnaryAssignExpr _ _ _ ->
317 error "TODO"
311 error "TODO"
@@ -324,8 +318,9 @@ fromExpr indent grouping expression =
324 (rightLines, right) =
318 (rightLines, right) =
325 fromExpr indent Atomic rightExpr
319 fromExpr indent Atomic rightExpr
326 in
320 in
327− merge leftLines rightLines !
321+ ( merge leftLines rightLines
328− parensFor grouping (left <> fromInfix op <> right)
322+ , parensFor grouping (left <> fromInfix op <> right)
323+ )
329
324
330 CondExpr _ condExpr thenExpr elseExpr ->
325 CondExpr _ condExpr thenExpr elseExpr ->
331 let
326 let
@@ -333,8 +328,9 @@ fromExpr indent grouping expression =
333 thenB = snd (fromExpr indent Atomic thenExpr)
328 thenB = snd (fromExpr indent Atomic thenExpr)
334 elseB = snd (fromExpr indent Atomic elseExpr)
329 elseB = snd (fromExpr indent Atomic elseExpr)
335 in
330 in
336− Many !
331+ ( Many
337− parensFor grouping (condB <> " ? " <> thenB <> " : " <> elseB)
332+ , parensFor grouping (condB <> " ? " <> thenB <> " : " <> elseB)
333+ )
338
334
339 AssignExpr _ op lValue expr ->
335 AssignExpr _ op lValue expr ->
340 let
336 let
@@ -344,14 +340,15 @@ fromExpr indent grouping expression =
344 (rightLines, right) =
340 (rightLines, right) =
345 fromExpr indent Whatever expr
341 fromExpr indent Whatever expr
346 in
342 in
347− merge leftLines rightLines !
343+ ( merge leftLines rightLines
348− parensFor grouping (left <> fromAssign op <> right)
344+ , parensFor grouping (left <> fromAssign op <> right)
345+ )
349
346
350 ListExpr _ _ ->
347 ListExpr _ _ ->
351 error "TODO"
348 error "TODO"
352
349
353 CallExpr _ function args ->
350 CallExpr _ function args ->
354− Many !
351+ (,) Many $
355 let
352 let
356 deeperIndent =
353 deeperIndent =
357 deeper indent
354 deeper indent
@@ -369,7 +366,7 @@ fromExpr indent grouping expression =
369 funcB <> "(" <> commaSep argsB <> ")"
366 funcB <> "(" <> commaSep argsB <> ")"
370
367
371 FuncExpr _ maybeName args stmts ->
368 FuncExpr _ maybeName args stmts ->
372− Many !
369+ (,) Many $
373 "function " <> maybe mempty fromId maybeName <> "(" <> commaSep (map fromId args) <> ") {\n"
370 "function " <> maybe mempty fromId maybeName <> "(" <> commaSep (map fromId args) <> ") {\n"
374 <>
371 <>
375 fromStmtBlock (deeper indent) stmts
372 fromStmtBlock (deeper indent) stmts
@@ -387,8 +384,9 @@ fromField indent (prop, expr) =
387 (lines, builder) =
384 (lines, builder) =
388 fromExpr indent Whatever expr
385 fromExpr indent Whatever expr
389 in
386 in
390− lines !
387+ ( lines
391− fromProp prop <> ": " <> builder
388+ , fromProp prop <> ": " <> builder
389+ )
392
390
393
391
394fromProp :: Prop a -> Builder
392fromProp :: Prop a -> Builder
@@ -398,13 +396,38 @@ fromProp prop =
398 fromId name
396 fromId name
399
397
400 PropString _ string ->
398 PropString _ string ->
401− fromString (show string)
399+ quoted string
402
400
403 PropNum _ n ->
401 PropNum _ n ->
404 decimal n
402 decimal n
405
403
406
404
407
405
406+-- STRINGS
407+
408+
409+quoted :: String -> Builder
410+quoted string =
411+ fromString ('\'' : foldr escapeCons "'" string)
412+
413+
414+-- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Grammar_and_types#String_literals
415+escapeCons :: Char -> String -> String
416+escapeCons char rest =
417+ case char of
418+ '\b' -> '\\' : 'b' : rest
419+ '\f' -> '\\' : 'f' : rest
420+ '\n' -> '\\' : 'n' : rest
421+ '\r' -> '\\' : 'r' : rest
422+ '\t' -> '\\' : 't' : rest
423+ '\v' -> '\\' : 'v' : rest
424+ '\"' -> '\\' : '"' : rest
425+ '\'' -> '\\' : '\'' : rest
426+ '\\' -> '\\' : '\\' : rest
427+ _ -> char : rest
428+
429+
430+
408-- VALUES
431-- VALUES
409
432
410
433
@@ -412,7 +435,7 @@ fromLValue :: Builder -> LValue a -> (Lines, Builder)
412fromLValue indent lValue =
435fromLValue indent lValue =
413 case lValue of
436 case lValue of
414 LVar _ name ->
437 LVar _ name ->
415− One ! fromString name
438+ (One, fromString name)
416
439
417 LDot _ expr field ->
440 LDot _ expr field ->
418 makeDot indent expr field
441 makeDot indent expr field
@@ -427,7 +450,7 @@ makeDot indent expr field =
427 (lines, builder) =
450 (lines, builder) =
428 fromExpr indent Atomic expr
451 fromExpr indent Atomic expr
429 in
452 in
430− lines ! builder <> "." <> fromString field
453+ (lines, builder <> "." <> fromString field)
431
454
432
455
433makeBracketed :: Builder -> Expression a -> Expression a -> (Lines, Builder)
456makeBracketed :: Builder -> Expression a -> Expression a -> (Lines, Builder)
@@ -439,8 +462,9 @@ makeBracketed indent expr bracketedExpr =
439 (bracketedLines, bracketedBuilder) =
462 (bracketedLines, bracketedBuilder) =
440 fromExpr indent Whatever bracketedExpr
463 fromExpr indent Whatever bracketedExpr
441 in
464 in
442− merge lines bracketedLines !
465+ ( merge lines bracketedLines
443− builder <> "[" <> bracketedBuilder <> "]"
466+ , builder <> "[" <> bracketedBuilder <> "]"
467+ )
444
468
445
469
446
470