sweedworks

← all sources

checkjs.py

Compiles the site's JavaScript with a real engine

49 lines. This is the file the build actually runs, copied verbatim at build time.

  1. 1"""Syntax-check the site's JavaScript with a real engine.
  2. 2 
  3. 3I have no browser here, so this is the cheapest honest check available: compile
  4. 4the source with QuickJS (parse, don't run) so a typo can't reach the page.
  5. 5It does not prove the script behaves correctly in a browser.
  6. 6"""
  7. 7 
  8. 8import os
  9. 9import sys
  10. 10 
  11. 11HERE = os.path.dirname(os.path.abspath(__file__))
  12. 12sys.path.insert(0, os.path.join(HERE, "pylib"))
  13. 13ROOT = os.path.abspath(os.path.join(HERE, ".."))
  14. 14 
  15. 15import quickjs # noqa: E402
  16. 16 
  17. 17SCRIPTS = ["permalink.js", "tokens/app.js", "vocabulary/bpe.js", "vocabulary/app.js",
  18. 18 "predict/ngram.js", "predict/app.js", "cost/app.js", "learn/mlp.js", "learn/app.js",
  19. 19 "attention/attn.js", "attention/app.js", "checking/app.js"]
  20. 20 
  21. 21 
  22. 22def main():
  23. 23 bad = 0
  24. 24 for rel in SCRIPTS:
  25. 25 src = open(os.path.join(ROOT, rel), encoding="utf-8").read()
  26. 26 ctx = quickjs.Context()
  27. 27 ctx.set("__src", src)
  28. 28 try:
  29. 29 # new Function() parses the body without executing it.
  30. 30 ctx.eval("new Function(__src)")
  31. 31 print(f"PASS {rel:<20} parses ({len(src):,} bytes)")
  32. 32 except Exception as e:
  33. 33 print(f"FAIL {rel:<20} {str(e)[:200]}")
  34. 34 bad += 1
  35. 35 
  36. 36 for banned, why in [("innerHTML", "use DOM nodes, not markup injection"),
  37. 37 ("eval(", "no eval in shipped script"),
  38. 38 ("fetch(", "the page must make no network requests"),
  39. 39 ("XMLHttpRequest", "the page must make no network requests")]:
  40. 40 if banned in src:
  41. 41 print(f"FAIL {rel:<20} contains {banned!r} — {why}")
  42. 42 bad += 1
  43. 43 
  44. 44 return 1 if bad else 0
  45. 45 
  46. 46 
  47. 47if __name__ == "__main__":
  48. 48 sys.exit(main())