frida 16.2.1 → 16.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (386) hide show
  1. package/BSDmakefile +6 -0
  2. package/Makefile +16 -0
  3. package/README.md +14 -11
  4. package/configure +18 -0
  5. package/configure.bat +22 -0
  6. package/dist/native.js +0 -8
  7. package/lib/application.ts +98 -0
  8. package/lib/authentication.ts +3 -0
  9. package/lib/build.py +50 -0
  10. package/lib/bus.ts +30 -0
  11. package/lib/cancellable.ts +33 -0
  12. package/lib/child.ts +15 -0
  13. package/lib/crash.ts +11 -0
  14. package/lib/device.ts +329 -0
  15. package/lib/device_manager.ts +69 -0
  16. package/lib/endpoint_parameters.ts +56 -0
  17. package/lib/icon.ts +15 -0
  18. package/lib/index.ts +311 -0
  19. package/lib/iostream.ts +78 -0
  20. package/lib/meson.build +53 -0
  21. package/lib/native.ts +9 -0
  22. package/lib/portal_membership.ts +10 -0
  23. package/lib/portal_service.ts +105 -0
  24. package/lib/process.ts +57 -0
  25. package/lib/relay.ts +44 -0
  26. package/lib/script.ts +352 -0
  27. package/lib/session.ts +113 -0
  28. package/lib/signals.ts +45 -0
  29. package/lib/socket_address.ts +35 -0
  30. package/lib/spawn.ts +4 -0
  31. package/lib/system_parameters.ts +78 -0
  32. package/make.bat +23 -0
  33. package/meson.build +160 -0
  34. package/meson.options +11 -0
  35. package/package.json +27 -6
  36. package/releng/deps.py +1133 -0
  37. package/releng/deps.toml +391 -0
  38. package/releng/devkit-assets/frida-core-example-unix.c +188 -0
  39. package/releng/devkit-assets/frida-core-example-windows.c +197 -0
  40. package/releng/devkit-assets/frida-core-example.sln +28 -0
  41. package/releng/devkit-assets/frida-core-example.vcxproj +157 -0
  42. package/releng/devkit-assets/frida-core-example.vcxproj.filters +27 -0
  43. package/releng/devkit-assets/frida-gum-example-unix.c +122 -0
  44. package/releng/devkit-assets/frida-gum-example-windows.c +132 -0
  45. package/releng/devkit-assets/frida-gum-example.sln +28 -0
  46. package/releng/devkit-assets/frida-gum-example.vcxproj +157 -0
  47. package/releng/devkit-assets/frida-gum-example.vcxproj.filters +27 -0
  48. package/releng/devkit-assets/frida-gumjs-example-unix.c +84 -0
  49. package/releng/devkit-assets/frida-gumjs-example-windows.c +91 -0
  50. package/releng/devkit-assets/frida-gumjs-example.sln +28 -0
  51. package/releng/devkit-assets/frida-gumjs-example.vcxproj +157 -0
  52. package/releng/devkit-assets/frida-gumjs-example.vcxproj.filters +27 -0
  53. package/releng/devkit.py +535 -0
  54. package/releng/env.py +420 -0
  55. package/releng/env_android.py +150 -0
  56. package/releng/env_apple.py +176 -0
  57. package/releng/env_generic.py +373 -0
  58. package/releng/frida_version.py +69 -0
  59. package/releng/machine_file.py +44 -0
  60. package/releng/machine_spec.py +290 -0
  61. package/releng/meson/meson.py +27 -0
  62. package/releng/meson/mesonbuild/__init__.py +0 -0
  63. package/releng/meson/mesonbuild/_pathlib.py +63 -0
  64. package/releng/meson/mesonbuild/_typing.py +69 -0
  65. package/releng/meson/mesonbuild/arglist.py +321 -0
  66. package/releng/meson/mesonbuild/ast/__init__.py +23 -0
  67. package/releng/meson/mesonbuild/ast/interpreter.py +441 -0
  68. package/releng/meson/mesonbuild/ast/introspection.py +374 -0
  69. package/releng/meson/mesonbuild/ast/postprocess.py +109 -0
  70. package/releng/meson/mesonbuild/ast/printer.py +620 -0
  71. package/releng/meson/mesonbuild/ast/visitor.py +161 -0
  72. package/releng/meson/mesonbuild/backend/__init__.py +0 -0
  73. package/releng/meson/mesonbuild/backend/backends.py +2047 -0
  74. package/releng/meson/mesonbuild/backend/ninjabackend.py +3808 -0
  75. package/releng/meson/mesonbuild/backend/nonebackend.py +26 -0
  76. package/releng/meson/mesonbuild/backend/vs2010backend.py +2078 -0
  77. package/releng/meson/mesonbuild/backend/vs2012backend.py +35 -0
  78. package/releng/meson/mesonbuild/backend/vs2013backend.py +34 -0
  79. package/releng/meson/mesonbuild/backend/vs2015backend.py +35 -0
  80. package/releng/meson/mesonbuild/backend/vs2017backend.py +59 -0
  81. package/releng/meson/mesonbuild/backend/vs2019backend.py +54 -0
  82. package/releng/meson/mesonbuild/backend/vs2022backend.py +54 -0
  83. package/releng/meson/mesonbuild/backend/xcodebackend.py +1781 -0
  84. package/releng/meson/mesonbuild/build.py +3249 -0
  85. package/releng/meson/mesonbuild/cargo/__init__.py +5 -0
  86. package/releng/meson/mesonbuild/cargo/builder.py +238 -0
  87. package/releng/meson/mesonbuild/cargo/cfg.py +274 -0
  88. package/releng/meson/mesonbuild/cargo/interpreter.py +733 -0
  89. package/releng/meson/mesonbuild/cargo/manifest.py +227 -0
  90. package/releng/meson/mesonbuild/cargo/version.py +95 -0
  91. package/releng/meson/mesonbuild/cmake/__init__.py +28 -0
  92. package/releng/meson/mesonbuild/cmake/common.py +331 -0
  93. package/releng/meson/mesonbuild/cmake/data/__init__.py +0 -0
  94. package/releng/meson/mesonbuild/cmake/data/preload.cmake +82 -0
  95. package/releng/meson/mesonbuild/cmake/executor.py +241 -0
  96. package/releng/meson/mesonbuild/cmake/fileapi.py +324 -0
  97. package/releng/meson/mesonbuild/cmake/generator.py +186 -0
  98. package/releng/meson/mesonbuild/cmake/interpreter.py +1267 -0
  99. package/releng/meson/mesonbuild/cmake/toolchain.py +248 -0
  100. package/releng/meson/mesonbuild/cmake/traceparser.py +814 -0
  101. package/releng/meson/mesonbuild/cmake/tracetargets.py +161 -0
  102. package/releng/meson/mesonbuild/compilers/__init__.py +86 -0
  103. package/releng/meson/mesonbuild/compilers/asm.py +307 -0
  104. package/releng/meson/mesonbuild/compilers/c.py +788 -0
  105. package/releng/meson/mesonbuild/compilers/c_function_attributes.py +143 -0
  106. package/releng/meson/mesonbuild/compilers/compilers.py +1388 -0
  107. package/releng/meson/mesonbuild/compilers/cpp.py +1035 -0
  108. package/releng/meson/mesonbuild/compilers/cs.py +136 -0
  109. package/releng/meson/mesonbuild/compilers/cuda.py +806 -0
  110. package/releng/meson/mesonbuild/compilers/cython.py +91 -0
  111. package/releng/meson/mesonbuild/compilers/d.py +861 -0
  112. package/releng/meson/mesonbuild/compilers/detect.py +1396 -0
  113. package/releng/meson/mesonbuild/compilers/fortran.py +523 -0
  114. package/releng/meson/mesonbuild/compilers/java.py +113 -0
  115. package/releng/meson/mesonbuild/compilers/mixins/__init__.py +0 -0
  116. package/releng/meson/mesonbuild/compilers/mixins/arm.py +167 -0
  117. package/releng/meson/mesonbuild/compilers/mixins/ccrx.py +113 -0
  118. package/releng/meson/mesonbuild/compilers/mixins/clang.py +170 -0
  119. package/releng/meson/mesonbuild/compilers/mixins/clike.py +1330 -0
  120. package/releng/meson/mesonbuild/compilers/mixins/compcert.py +117 -0
  121. package/releng/meson/mesonbuild/compilers/mixins/elbrus.py +93 -0
  122. package/releng/meson/mesonbuild/compilers/mixins/emscripten.py +89 -0
  123. package/releng/meson/mesonbuild/compilers/mixins/gnu.py +629 -0
  124. package/releng/meson/mesonbuild/compilers/mixins/intel.py +167 -0
  125. package/releng/meson/mesonbuild/compilers/mixins/islinker.py +120 -0
  126. package/releng/meson/mesonbuild/compilers/mixins/metrowerks.py +279 -0
  127. package/releng/meson/mesonbuild/compilers/mixins/pgi.py +88 -0
  128. package/releng/meson/mesonbuild/compilers/mixins/ti.py +130 -0
  129. package/releng/meson/mesonbuild/compilers/mixins/visualstudio.py +458 -0
  130. package/releng/meson/mesonbuild/compilers/mixins/xc16.py +111 -0
  131. package/releng/meson/mesonbuild/compilers/objc.py +120 -0
  132. package/releng/meson/mesonbuild/compilers/objcpp.py +102 -0
  133. package/releng/meson/mesonbuild/compilers/rust.py +230 -0
  134. package/releng/meson/mesonbuild/compilers/swift.py +131 -0
  135. package/releng/meson/mesonbuild/compilers/vala.py +121 -0
  136. package/releng/meson/mesonbuild/coredata.py +1532 -0
  137. package/releng/meson/mesonbuild/dependencies/__init__.py +252 -0
  138. package/releng/meson/mesonbuild/dependencies/base.py +663 -0
  139. package/releng/meson/mesonbuild/dependencies/boost.py +1083 -0
  140. package/releng/meson/mesonbuild/dependencies/cmake.py +656 -0
  141. package/releng/meson/mesonbuild/dependencies/coarrays.py +80 -0
  142. package/releng/meson/mesonbuild/dependencies/configtool.py +163 -0
  143. package/releng/meson/mesonbuild/dependencies/cuda.py +295 -0
  144. package/releng/meson/mesonbuild/dependencies/data/CMakeLists.txt +102 -0
  145. package/releng/meson/mesonbuild/dependencies/data/CMakeListsLLVM.txt +204 -0
  146. package/releng/meson/mesonbuild/dependencies/data/CMakePathInfo.txt +31 -0
  147. package/releng/meson/mesonbuild/dependencies/data/__init__.py +0 -0
  148. package/releng/meson/mesonbuild/dependencies/detect.py +225 -0
  149. package/releng/meson/mesonbuild/dependencies/dev.py +707 -0
  150. package/releng/meson/mesonbuild/dependencies/dub.py +424 -0
  151. package/releng/meson/mesonbuild/dependencies/factory.py +146 -0
  152. package/releng/meson/mesonbuild/dependencies/framework.py +111 -0
  153. package/releng/meson/mesonbuild/dependencies/hdf5.py +168 -0
  154. package/releng/meson/mesonbuild/dependencies/misc.py +618 -0
  155. package/releng/meson/mesonbuild/dependencies/mpi.py +231 -0
  156. package/releng/meson/mesonbuild/dependencies/pkgconfig.py +570 -0
  157. package/releng/meson/mesonbuild/dependencies/platform.py +52 -0
  158. package/releng/meson/mesonbuild/dependencies/python.py +431 -0
  159. package/releng/meson/mesonbuild/dependencies/qt.py +484 -0
  160. package/releng/meson/mesonbuild/dependencies/scalapack.py +142 -0
  161. package/releng/meson/mesonbuild/dependencies/ui.py +281 -0
  162. package/releng/meson/mesonbuild/depfile.py +82 -0
  163. package/releng/meson/mesonbuild/envconfig.py +480 -0
  164. package/releng/meson/mesonbuild/environment.py +987 -0
  165. package/releng/meson/mesonbuild/interpreter/__init__.py +47 -0
  166. package/releng/meson/mesonbuild/interpreter/compiler.py +900 -0
  167. package/releng/meson/mesonbuild/interpreter/dependencyfallbacks.py +386 -0
  168. package/releng/meson/mesonbuild/interpreter/interpreter.py +3595 -0
  169. package/releng/meson/mesonbuild/interpreter/interpreterobjects.py +1096 -0
  170. package/releng/meson/mesonbuild/interpreter/kwargs.py +479 -0
  171. package/releng/meson/mesonbuild/interpreter/mesonmain.py +487 -0
  172. package/releng/meson/mesonbuild/interpreter/primitives/__init__.py +29 -0
  173. package/releng/meson/mesonbuild/interpreter/primitives/array.py +108 -0
  174. package/releng/meson/mesonbuild/interpreter/primitives/boolean.py +52 -0
  175. package/releng/meson/mesonbuild/interpreter/primitives/dict.py +88 -0
  176. package/releng/meson/mesonbuild/interpreter/primitives/integer.py +86 -0
  177. package/releng/meson/mesonbuild/interpreter/primitives/range.py +38 -0
  178. package/releng/meson/mesonbuild/interpreter/primitives/string.py +247 -0
  179. package/releng/meson/mesonbuild/interpreter/type_checking.py +853 -0
  180. package/releng/meson/mesonbuild/interpreterbase/__init__.py +126 -0
  181. package/releng/meson/mesonbuild/interpreterbase/_unholder.py +25 -0
  182. package/releng/meson/mesonbuild/interpreterbase/baseobjects.py +174 -0
  183. package/releng/meson/mesonbuild/interpreterbase/decorators.py +806 -0
  184. package/releng/meson/mesonbuild/interpreterbase/disabler.py +35 -0
  185. package/releng/meson/mesonbuild/interpreterbase/exceptions.py +22 -0
  186. package/releng/meson/mesonbuild/interpreterbase/helpers.py +67 -0
  187. package/releng/meson/mesonbuild/interpreterbase/interpreterbase.py +665 -0
  188. package/releng/meson/mesonbuild/interpreterbase/operator.py +32 -0
  189. package/releng/meson/mesonbuild/linkers/__init__.py +20 -0
  190. package/releng/meson/mesonbuild/linkers/base.py +39 -0
  191. package/releng/meson/mesonbuild/linkers/detect.py +229 -0
  192. package/releng/meson/mesonbuild/linkers/linkers.py +1614 -0
  193. package/releng/meson/mesonbuild/mcompile.py +380 -0
  194. package/releng/meson/mesonbuild/mconf.py +368 -0
  195. package/releng/meson/mesonbuild/mdevenv.py +234 -0
  196. package/releng/meson/mesonbuild/mdist.py +376 -0
  197. package/releng/meson/mesonbuild/mesondata.py +38 -0
  198. package/releng/meson/mesonbuild/mesonlib.py +23 -0
  199. package/releng/meson/mesonbuild/mesonmain.py +289 -0
  200. package/releng/meson/mesonbuild/minit.py +204 -0
  201. package/releng/meson/mesonbuild/minstall.py +864 -0
  202. package/releng/meson/mesonbuild/mintro.py +667 -0
  203. package/releng/meson/mesonbuild/mlog.py +542 -0
  204. package/releng/meson/mesonbuild/modules/__init__.py +270 -0
  205. package/releng/meson/mesonbuild/modules/cmake.py +442 -0
  206. package/releng/meson/mesonbuild/modules/cuda.py +377 -0
  207. package/releng/meson/mesonbuild/modules/dlang.py +117 -0
  208. package/releng/meson/mesonbuild/modules/external_project.py +306 -0
  209. package/releng/meson/mesonbuild/modules/fs.py +323 -0
  210. package/releng/meson/mesonbuild/modules/gnome.py +2215 -0
  211. package/releng/meson/mesonbuild/modules/hotdoc.py +487 -0
  212. package/releng/meson/mesonbuild/modules/i18n.py +405 -0
  213. package/releng/meson/mesonbuild/modules/icestorm.py +123 -0
  214. package/releng/meson/mesonbuild/modules/java.py +112 -0
  215. package/releng/meson/mesonbuild/modules/keyval.py +65 -0
  216. package/releng/meson/mesonbuild/modules/modtest.py +33 -0
  217. package/releng/meson/mesonbuild/modules/pkgconfig.py +744 -0
  218. package/releng/meson/mesonbuild/modules/python.py +556 -0
  219. package/releng/meson/mesonbuild/modules/python3.py +85 -0
  220. package/releng/meson/mesonbuild/modules/qt.py +621 -0
  221. package/releng/meson/mesonbuild/modules/qt4.py +23 -0
  222. package/releng/meson/mesonbuild/modules/qt5.py +23 -0
  223. package/releng/meson/mesonbuild/modules/qt6.py +22 -0
  224. package/releng/meson/mesonbuild/modules/rust.py +355 -0
  225. package/releng/meson/mesonbuild/modules/simd.py +114 -0
  226. package/releng/meson/mesonbuild/modules/sourceset.py +291 -0
  227. package/releng/meson/mesonbuild/modules/wayland.py +151 -0
  228. package/releng/meson/mesonbuild/modules/windows.py +207 -0
  229. package/releng/meson/mesonbuild/mparser.py +1114 -0
  230. package/releng/meson/mesonbuild/msetup.py +365 -0
  231. package/releng/meson/mesonbuild/msubprojects.py +764 -0
  232. package/releng/meson/mesonbuild/mtest.py +2201 -0
  233. package/releng/meson/mesonbuild/munstable_coredata.py +107 -0
  234. package/releng/meson/mesonbuild/optinterpreter.py +276 -0
  235. package/releng/meson/mesonbuild/programs.py +367 -0
  236. package/releng/meson/mesonbuild/rewriter.py +1075 -0
  237. package/releng/meson/mesonbuild/scripts/__init__.py +10 -0
  238. package/releng/meson/mesonbuild/scripts/clangformat.py +55 -0
  239. package/releng/meson/mesonbuild/scripts/clangtidy.py +30 -0
  240. package/releng/meson/mesonbuild/scripts/cleantrees.py +35 -0
  241. package/releng/meson/mesonbuild/scripts/cmake_run_ctgt.py +103 -0
  242. package/releng/meson/mesonbuild/scripts/cmd_or_ps.ps1 +17 -0
  243. package/releng/meson/mesonbuild/scripts/copy.py +19 -0
  244. package/releng/meson/mesonbuild/scripts/coverage.py +214 -0
  245. package/releng/meson/mesonbuild/scripts/delwithsuffix.py +27 -0
  246. package/releng/meson/mesonbuild/scripts/depfixer.py +495 -0
  247. package/releng/meson/mesonbuild/scripts/depscan.py +198 -0
  248. package/releng/meson/mesonbuild/scripts/dirchanger.py +20 -0
  249. package/releng/meson/mesonbuild/scripts/env2mfile.py +402 -0
  250. package/releng/meson/mesonbuild/scripts/externalproject.py +106 -0
  251. package/releng/meson/mesonbuild/scripts/gettext.py +86 -0
  252. package/releng/meson/mesonbuild/scripts/gtkdochelper.py +286 -0
  253. package/releng/meson/mesonbuild/scripts/hotdochelper.py +40 -0
  254. package/releng/meson/mesonbuild/scripts/itstool.py +77 -0
  255. package/releng/meson/mesonbuild/scripts/meson_exe.py +115 -0
  256. package/releng/meson/mesonbuild/scripts/msgfmthelper.py +29 -0
  257. package/releng/meson/mesonbuild/scripts/pycompile.py +54 -0
  258. package/releng/meson/mesonbuild/scripts/python_info.py +121 -0
  259. package/releng/meson/mesonbuild/scripts/regen_checker.py +55 -0
  260. package/releng/meson/mesonbuild/scripts/run_tool.py +58 -0
  261. package/releng/meson/mesonbuild/scripts/scanbuild.py +57 -0
  262. package/releng/meson/mesonbuild/scripts/symbolextractor.py +322 -0
  263. package/releng/meson/mesonbuild/scripts/tags.py +44 -0
  264. package/releng/meson/mesonbuild/scripts/test_loaded_modules.py +14 -0
  265. package/releng/meson/mesonbuild/scripts/uninstall.py +41 -0
  266. package/releng/meson/mesonbuild/scripts/vcstagger.py +35 -0
  267. package/releng/meson/mesonbuild/scripts/yasm.py +24 -0
  268. package/releng/meson/mesonbuild/templates/__init__.py +0 -0
  269. package/releng/meson/mesonbuild/templates/cpptemplates.py +143 -0
  270. package/releng/meson/mesonbuild/templates/cstemplates.py +90 -0
  271. package/releng/meson/mesonbuild/templates/ctemplates.py +126 -0
  272. package/releng/meson/mesonbuild/templates/cudatemplates.py +143 -0
  273. package/releng/meson/mesonbuild/templates/dlangtemplates.py +109 -0
  274. package/releng/meson/mesonbuild/templates/fortrantemplates.py +101 -0
  275. package/releng/meson/mesonbuild/templates/javatemplates.py +94 -0
  276. package/releng/meson/mesonbuild/templates/mesontemplates.py +70 -0
  277. package/releng/meson/mesonbuild/templates/objcpptemplates.py +126 -0
  278. package/releng/meson/mesonbuild/templates/objctemplates.py +126 -0
  279. package/releng/meson/mesonbuild/templates/rusttemplates.py +79 -0
  280. package/releng/meson/mesonbuild/templates/samplefactory.py +41 -0
  281. package/releng/meson/mesonbuild/templates/sampleimpl.py +160 -0
  282. package/releng/meson/mesonbuild/templates/valatemplates.py +82 -0
  283. package/releng/meson/mesonbuild/utils/__init__.py +0 -0
  284. package/releng/meson/mesonbuild/utils/core.py +166 -0
  285. package/releng/meson/mesonbuild/utils/platform.py +27 -0
  286. package/releng/meson/mesonbuild/utils/posix.py +32 -0
  287. package/releng/meson/mesonbuild/utils/universal.py +2445 -0
  288. package/releng/meson/mesonbuild/utils/vsenv.py +126 -0
  289. package/releng/meson/mesonbuild/utils/win32.py +29 -0
  290. package/releng/meson/mesonbuild/wrap/__init__.py +59 -0
  291. package/releng/meson/mesonbuild/wrap/wrap.py +846 -0
  292. package/releng/meson/mesonbuild/wrap/wraptool.py +198 -0
  293. package/releng/meson-scripts/BSDmakefile +6 -0
  294. package/releng/meson-scripts/Makefile +16 -0
  295. package/releng/meson-scripts/configure +18 -0
  296. package/releng/meson-scripts/configure.bat +22 -0
  297. package/releng/meson-scripts/make.bat +23 -0
  298. package/releng/meson_configure.py +506 -0
  299. package/releng/meson_make.py +131 -0
  300. package/releng/mkdevkit.py +107 -0
  301. package/releng/mkfatmacho.py +54 -0
  302. package/releng/post-process-oabi.py +97 -0
  303. package/releng/progress.py +14 -0
  304. package/releng/sync-from-upstream.py +185 -0
  305. package/releng/tomlkit/tomlkit/__init__.py +59 -0
  306. package/releng/tomlkit/tomlkit/_compat.py +22 -0
  307. package/releng/tomlkit/tomlkit/_types.py +83 -0
  308. package/releng/tomlkit/tomlkit/_utils.py +158 -0
  309. package/releng/tomlkit/tomlkit/api.py +308 -0
  310. package/releng/tomlkit/tomlkit/container.py +875 -0
  311. package/releng/tomlkit/tomlkit/exceptions.py +227 -0
  312. package/releng/tomlkit/tomlkit/items.py +1967 -0
  313. package/releng/tomlkit/tomlkit/parser.py +1141 -0
  314. package/releng/tomlkit/tomlkit/py.typed +0 -0
  315. package/releng/tomlkit/tomlkit/source.py +180 -0
  316. package/releng/tomlkit/tomlkit/toml_char.py +52 -0
  317. package/releng/tomlkit/tomlkit/toml_document.py +7 -0
  318. package/releng/tomlkit/tomlkit/toml_file.py +58 -0
  319. package/releng/winenv.py +140 -0
  320. package/scripts/adjust-version.py +19 -0
  321. package/scripts/detect-version.py +40 -0
  322. package/scripts/fetch-abi-bits.py +343 -0
  323. package/scripts/install.js +23 -0
  324. package/scripts/package.py +15 -0
  325. package/src/addon.cc +76 -0
  326. package/src/application.cc +148 -0
  327. package/src/application.h +31 -0
  328. package/src/authentication.cc +174 -0
  329. package/src/authentication.h +24 -0
  330. package/src/bus.cc +167 -0
  331. package/src/bus.h +33 -0
  332. package/src/cancellable.cc +117 -0
  333. package/src/cancellable.h +31 -0
  334. package/src/child.cc +150 -0
  335. package/src/child.h +32 -0
  336. package/src/crash.cc +122 -0
  337. package/src/crash.h +30 -0
  338. package/src/device.cc +1302 -0
  339. package/src/device.h +55 -0
  340. package/src/device_manager.cc +362 -0
  341. package/src/device_manager.h +35 -0
  342. package/src/endpoint_parameters.cc +171 -0
  343. package/src/endpoint_parameters.h +28 -0
  344. package/src/glib_context.cc +62 -0
  345. package/src/glib_context.h +29 -0
  346. package/src/glib_object.cc +25 -0
  347. package/src/glib_object.h +37 -0
  348. package/src/iostream.cc +247 -0
  349. package/src/iostream.h +30 -0
  350. package/src/meson.build +26 -0
  351. package/src/operation.h +94 -0
  352. package/src/portal_membership.cc +100 -0
  353. package/src/portal_membership.h +26 -0
  354. package/src/portal_service.cc +401 -0
  355. package/src/portal_service.h +40 -0
  356. package/src/process.cc +135 -0
  357. package/src/process.h +30 -0
  358. package/src/relay.cc +139 -0
  359. package/src/relay.h +31 -0
  360. package/src/runtime.cc +443 -0
  361. package/src/runtime.h +64 -0
  362. package/src/script.cc +301 -0
  363. package/src/script.h +36 -0
  364. package/src/session.cc +860 -0
  365. package/src/session.h +42 -0
  366. package/src/signals.cc +334 -0
  367. package/src/signals.h +47 -0
  368. package/src/spawn.cc +95 -0
  369. package/src/spawn.h +27 -0
  370. package/src/usage_monitor.h +117 -0
  371. package/src/uv_context.cc +118 -0
  372. package/src/uv_context.h +40 -0
  373. package/src/win_delay_load_hook.cc +63 -0
  374. package/subprojects/frida-core.wrap +8 -0
  375. package/subprojects/nan.wrap +9 -0
  376. package/subprojects/packagefiles/nan.patch +13 -0
  377. package/test/data/index.ts +13 -0
  378. package/test/data/unixvictim-linux-x86 +0 -0
  379. package/test/data/unixvictim-linux-x86_64 +0 -0
  380. package/test/data/unixvictim-macos +0 -0
  381. package/test/device.ts +27 -0
  382. package/test/device_manager.ts +16 -0
  383. package/test/labrat.ts +32 -0
  384. package/test/script.ts +176 -0
  385. package/test/session.ts +73 -0
  386. package/tsconfig.json +18 -0
@@ -0,0 +1,1141 @@
1
+ from __future__ import annotations
2
+
3
+ import datetime
4
+ import re
5
+ import string
6
+
7
+ from tomlkit._compat import decode
8
+ from tomlkit._utils import RFC_3339_LOOSE
9
+ from tomlkit._utils import _escaped
10
+ from tomlkit._utils import parse_rfc3339
11
+ from tomlkit.container import Container
12
+ from tomlkit.exceptions import EmptyKeyError
13
+ from tomlkit.exceptions import EmptyTableNameError
14
+ from tomlkit.exceptions import InternalParserError
15
+ from tomlkit.exceptions import InvalidCharInStringError
16
+ from tomlkit.exceptions import InvalidControlChar
17
+ from tomlkit.exceptions import InvalidDateError
18
+ from tomlkit.exceptions import InvalidDateTimeError
19
+ from tomlkit.exceptions import InvalidNumberError
20
+ from tomlkit.exceptions import InvalidTimeError
21
+ from tomlkit.exceptions import InvalidUnicodeValueError
22
+ from tomlkit.exceptions import ParseError
23
+ from tomlkit.exceptions import UnexpectedCharError
24
+ from tomlkit.exceptions import UnexpectedEofError
25
+ from tomlkit.items import AoT
26
+ from tomlkit.items import Array
27
+ from tomlkit.items import Bool
28
+ from tomlkit.items import BoolType
29
+ from tomlkit.items import Comment
30
+ from tomlkit.items import Date
31
+ from tomlkit.items import DateTime
32
+ from tomlkit.items import Float
33
+ from tomlkit.items import InlineTable
34
+ from tomlkit.items import Integer
35
+ from tomlkit.items import Item
36
+ from tomlkit.items import Key
37
+ from tomlkit.items import KeyType
38
+ from tomlkit.items import Null
39
+ from tomlkit.items import SingleKey
40
+ from tomlkit.items import String
41
+ from tomlkit.items import StringType
42
+ from tomlkit.items import Table
43
+ from tomlkit.items import Time
44
+ from tomlkit.items import Trivia
45
+ from tomlkit.items import Whitespace
46
+ from tomlkit.source import Source
47
+ from tomlkit.toml_char import TOMLChar
48
+ from tomlkit.toml_document import TOMLDocument
49
+
50
+
51
+ CTRL_I = 0x09 # Tab
52
+ CTRL_J = 0x0A # Line feed
53
+ CTRL_M = 0x0D # Carriage return
54
+ CTRL_CHAR_LIMIT = 0x1F
55
+ CHR_DEL = 0x7F
56
+
57
+
58
+ class Parser:
59
+ """
60
+ Parser for TOML documents.
61
+ """
62
+
63
+ def __init__(self, string: str | bytes) -> None:
64
+ # Input to parse
65
+ self._src = Source(decode(string))
66
+
67
+ self._aot_stack: list[Key] = []
68
+
69
+ @property
70
+ def _state(self):
71
+ return self._src.state
72
+
73
+ @property
74
+ def _idx(self):
75
+ return self._src.idx
76
+
77
+ @property
78
+ def _current(self):
79
+ return self._src.current
80
+
81
+ @property
82
+ def _marker(self):
83
+ return self._src.marker
84
+
85
+ def extract(self) -> str:
86
+ """
87
+ Extracts the value between marker and index
88
+ """
89
+ return self._src.extract()
90
+
91
+ def inc(self, exception: type[ParseError] | None = None) -> bool:
92
+ """
93
+ Increments the parser if the end of the input has not been reached.
94
+ Returns whether or not it was able to advance.
95
+ """
96
+ return self._src.inc(exception=exception)
97
+
98
+ def inc_n(self, n: int, exception: type[ParseError] | None = None) -> bool:
99
+ """
100
+ Increments the parser by n characters
101
+ if the end of the input has not been reached.
102
+ """
103
+ return self._src.inc_n(n=n, exception=exception)
104
+
105
+ def consume(self, chars, min=0, max=-1):
106
+ """
107
+ Consume chars until min/max is satisfied is valid.
108
+ """
109
+ return self._src.consume(chars=chars, min=min, max=max)
110
+
111
+ def end(self) -> bool:
112
+ """
113
+ Returns True if the parser has reached the end of the input.
114
+ """
115
+ return self._src.end()
116
+
117
+ def mark(self) -> None:
118
+ """
119
+ Sets the marker to the index's current position
120
+ """
121
+ self._src.mark()
122
+
123
+ def parse_error(self, exception=ParseError, *args, **kwargs):
124
+ """
125
+ Creates a generic "parse error" at the current position.
126
+ """
127
+ return self._src.parse_error(exception, *args, **kwargs)
128
+
129
+ def parse(self) -> TOMLDocument:
130
+ body = TOMLDocument(True)
131
+
132
+ # Take all keyvals outside of tables/AoT's.
133
+ while not self.end():
134
+ # Break out if a table is found
135
+ if self._current == "[":
136
+ break
137
+
138
+ # Otherwise, take and append one KV
139
+ item = self._parse_item()
140
+ if not item:
141
+ break
142
+
143
+ key, value = item
144
+ if (key is not None and key.is_multi()) or not self._merge_ws(value, body):
145
+ # We actually have a table
146
+ try:
147
+ body.append(key, value)
148
+ except Exception as e:
149
+ raise self.parse_error(ParseError, str(e)) from e
150
+
151
+ self.mark()
152
+
153
+ while not self.end():
154
+ key, value = self._parse_table()
155
+ if isinstance(value, Table) and value.is_aot_element():
156
+ # This is just the first table in an AoT. Parse the rest of the array
157
+ # along with it.
158
+ value = self._parse_aot(value, key)
159
+
160
+ try:
161
+ body.append(key, value)
162
+ except Exception as e:
163
+ raise self.parse_error(ParseError, str(e)) from e
164
+
165
+ body.parsing(False)
166
+
167
+ return body
168
+
169
+ def _merge_ws(self, item: Item, container: Container) -> bool:
170
+ """
171
+ Merges the given Item with the last one currently in the given Container if
172
+ both are whitespace items.
173
+
174
+ Returns True if the items were merged.
175
+ """
176
+ last = container.last_item()
177
+ if not last:
178
+ return False
179
+
180
+ if not isinstance(item, Whitespace) or not isinstance(last, Whitespace):
181
+ return False
182
+
183
+ start = self._idx - (len(last.s) + len(item.s))
184
+ container.body[-1] = (
185
+ container.body[-1][0],
186
+ Whitespace(self._src[start : self._idx]),
187
+ )
188
+
189
+ return True
190
+
191
+ def _is_child(self, parent: Key, child: Key) -> bool:
192
+ """
193
+ Returns whether a key is strictly a child of another key.
194
+ AoT siblings are not considered children of one another.
195
+ """
196
+ parent_parts = tuple(parent)
197
+ child_parts = tuple(child)
198
+
199
+ if parent_parts == child_parts:
200
+ return False
201
+
202
+ return parent_parts == child_parts[: len(parent_parts)]
203
+
204
+ def _parse_item(self) -> tuple[Key | None, Item] | None:
205
+ """
206
+ Attempts to parse the next item and returns it, along with its key
207
+ if the item is value-like.
208
+ """
209
+ self.mark()
210
+ with self._state as state:
211
+ while True:
212
+ c = self._current
213
+ if c == "\n":
214
+ # Found a newline; Return all whitespace found up to this point.
215
+ self.inc()
216
+
217
+ return None, Whitespace(self.extract())
218
+ elif c in " \t\r":
219
+ # Skip whitespace.
220
+ if not self.inc():
221
+ return None, Whitespace(self.extract())
222
+ elif c == "#":
223
+ # Found a comment, parse it
224
+ indent = self.extract()
225
+ cws, comment, trail = self._parse_comment_trail()
226
+
227
+ return None, Comment(Trivia(indent, cws, comment, trail))
228
+ elif c == "[":
229
+ # Found a table, delegate to the calling function.
230
+ return
231
+ else:
232
+ # Beginning of a KV pair.
233
+ # Return to beginning of whitespace so it gets included
234
+ # as indentation for the KV about to be parsed.
235
+ state.restore = True
236
+ break
237
+
238
+ return self._parse_key_value(True)
239
+
240
+ def _parse_comment_trail(self, parse_trail: bool = True) -> tuple[str, str, str]:
241
+ """
242
+ Returns (comment_ws, comment, trail)
243
+ If there is no comment, comment_ws and comment will
244
+ simply be empty.
245
+ """
246
+ if self.end():
247
+ return "", "", ""
248
+
249
+ comment = ""
250
+ comment_ws = ""
251
+ self.mark()
252
+
253
+ while True:
254
+ c = self._current
255
+
256
+ if c == "\n":
257
+ break
258
+ elif c == "#":
259
+ comment_ws = self.extract()
260
+
261
+ self.mark()
262
+ self.inc() # Skip #
263
+
264
+ # The comment itself
265
+ while not self.end() and not self._current.is_nl():
266
+ code = ord(self._current)
267
+ if code == CHR_DEL or code <= CTRL_CHAR_LIMIT and code != CTRL_I:
268
+ raise self.parse_error(InvalidControlChar, code, "comments")
269
+
270
+ if not self.inc():
271
+ break
272
+
273
+ comment = self.extract()
274
+ self.mark()
275
+
276
+ break
277
+ elif c in " \t\r":
278
+ self.inc()
279
+ else:
280
+ raise self.parse_error(UnexpectedCharError, c)
281
+
282
+ if self.end():
283
+ break
284
+
285
+ trail = ""
286
+ if parse_trail:
287
+ while self._current.is_spaces() and self.inc():
288
+ pass
289
+
290
+ if self._current == "\r":
291
+ self.inc()
292
+
293
+ if self._current == "\n":
294
+ self.inc()
295
+
296
+ if self._idx != self._marker or self._current.is_ws():
297
+ trail = self.extract()
298
+
299
+ return comment_ws, comment, trail
300
+
301
+ def _parse_key_value(self, parse_comment: bool = False) -> tuple[Key, Item]:
302
+ # Leading indent
303
+ self.mark()
304
+
305
+ while self._current.is_spaces() and self.inc():
306
+ pass
307
+
308
+ indent = self.extract()
309
+
310
+ # Key
311
+ key = self._parse_key()
312
+
313
+ self.mark()
314
+
315
+ found_equals = self._current == "="
316
+ while self._current.is_kv_sep() and self.inc():
317
+ if self._current == "=":
318
+ if found_equals:
319
+ raise self.parse_error(UnexpectedCharError, "=")
320
+ else:
321
+ found_equals = True
322
+ if not found_equals:
323
+ raise self.parse_error(UnexpectedCharError, self._current)
324
+
325
+ if not key.sep:
326
+ key.sep = self.extract()
327
+ else:
328
+ key.sep += self.extract()
329
+
330
+ # Value
331
+ val = self._parse_value()
332
+ # Comment
333
+ if parse_comment:
334
+ cws, comment, trail = self._parse_comment_trail()
335
+ meta = val.trivia
336
+ if not meta.comment_ws:
337
+ meta.comment_ws = cws
338
+
339
+ meta.comment = comment
340
+ meta.trail = trail
341
+ else:
342
+ val.trivia.trail = ""
343
+
344
+ val.trivia.indent = indent
345
+
346
+ return key, val
347
+
348
+ def _parse_key(self) -> Key:
349
+ """
350
+ Parses a Key at the current position;
351
+ WS before the key must be exhausted first at the callsite.
352
+ """
353
+ self.mark()
354
+ while self._current.is_spaces() and self.inc():
355
+ # Skip any leading whitespace
356
+ pass
357
+ if self._current in "\"'":
358
+ return self._parse_quoted_key()
359
+ else:
360
+ return self._parse_bare_key()
361
+
362
+ def _parse_quoted_key(self) -> Key:
363
+ """
364
+ Parses a key enclosed in either single or double quotes.
365
+ """
366
+ # Extract the leading whitespace
367
+ original = self.extract()
368
+ quote_style = self._current
369
+ key_type = next((t for t in KeyType if t.value == quote_style), None)
370
+
371
+ if key_type is None:
372
+ raise RuntimeError("Should not have entered _parse_quoted_key()")
373
+
374
+ key_str = self._parse_string(
375
+ StringType.SLB if key_type == KeyType.Basic else StringType.SLL
376
+ )
377
+ if key_str._t.is_multiline():
378
+ raise self.parse_error(UnexpectedCharError, key_str._t.value)
379
+ original += key_str.as_string()
380
+ self.mark()
381
+ while self._current.is_spaces() and self.inc():
382
+ pass
383
+ original += self.extract()
384
+ key = SingleKey(str(key_str), t=key_type, sep="", original=original)
385
+ if self._current == ".":
386
+ self.inc()
387
+ key = key.concat(self._parse_key())
388
+
389
+ return key
390
+
391
+ def _parse_bare_key(self) -> Key:
392
+ """
393
+ Parses a bare key.
394
+ """
395
+ while (
396
+ self._current.is_bare_key_char() or self._current.is_spaces()
397
+ ) and self.inc():
398
+ pass
399
+
400
+ original = self.extract()
401
+ key = original.strip()
402
+ if not key:
403
+ # Empty key
404
+ raise self.parse_error(EmptyKeyError)
405
+
406
+ if " " in key:
407
+ # Bare key with spaces in it
408
+ raise self.parse_error(ParseError, f'Invalid key "{key}"')
409
+
410
+ key = SingleKey(key, KeyType.Bare, "", original)
411
+
412
+ if self._current == ".":
413
+ self.inc()
414
+ key = key.concat(self._parse_key())
415
+
416
+ return key
417
+
418
+ def _parse_value(self) -> Item:
419
+ """
420
+ Attempts to parse a value at the current position.
421
+ """
422
+ self.mark()
423
+ c = self._current
424
+ trivia = Trivia()
425
+
426
+ if c == StringType.SLB.value:
427
+ return self._parse_basic_string()
428
+ elif c == StringType.SLL.value:
429
+ return self._parse_literal_string()
430
+ elif c == BoolType.TRUE.value[0]:
431
+ return self._parse_true()
432
+ elif c == BoolType.FALSE.value[0]:
433
+ return self._parse_false()
434
+ elif c == "[":
435
+ return self._parse_array()
436
+ elif c == "{":
437
+ return self._parse_inline_table()
438
+ elif c in "+-" or self._peek(4) in {
439
+ "+inf",
440
+ "-inf",
441
+ "inf",
442
+ "+nan",
443
+ "-nan",
444
+ "nan",
445
+ }:
446
+ # Number
447
+ while self._current not in " \t\n\r#,]}" and self.inc():
448
+ pass
449
+
450
+ raw = self.extract()
451
+
452
+ item = self._parse_number(raw, trivia)
453
+ if item is not None:
454
+ return item
455
+
456
+ raise self.parse_error(InvalidNumberError)
457
+ elif c in string.digits:
458
+ # Integer, Float, Date, Time or DateTime
459
+ while self._current not in " \t\n\r#,]}" and self.inc():
460
+ pass
461
+
462
+ raw = self.extract()
463
+
464
+ m = RFC_3339_LOOSE.match(raw)
465
+ if m:
466
+ if m.group(1) and m.group(5):
467
+ # datetime
468
+ try:
469
+ dt = parse_rfc3339(raw)
470
+ assert isinstance(dt, datetime.datetime)
471
+ return DateTime(
472
+ dt.year,
473
+ dt.month,
474
+ dt.day,
475
+ dt.hour,
476
+ dt.minute,
477
+ dt.second,
478
+ dt.microsecond,
479
+ dt.tzinfo,
480
+ trivia,
481
+ raw,
482
+ )
483
+ except ValueError:
484
+ raise self.parse_error(InvalidDateTimeError)
485
+
486
+ if m.group(1):
487
+ try:
488
+ dt = parse_rfc3339(raw)
489
+ assert isinstance(dt, datetime.date)
490
+ date = Date(dt.year, dt.month, dt.day, trivia, raw)
491
+ self.mark()
492
+ while self._current not in "\t\n\r#,]}" and self.inc():
493
+ pass
494
+
495
+ time_raw = self.extract()
496
+ time_part = time_raw.rstrip()
497
+ trivia.comment_ws = time_raw[len(time_part) :]
498
+ if not time_part:
499
+ return date
500
+
501
+ dt = parse_rfc3339(raw + time_part)
502
+ assert isinstance(dt, datetime.datetime)
503
+ return DateTime(
504
+ dt.year,
505
+ dt.month,
506
+ dt.day,
507
+ dt.hour,
508
+ dt.minute,
509
+ dt.second,
510
+ dt.microsecond,
511
+ dt.tzinfo,
512
+ trivia,
513
+ raw + time_part,
514
+ )
515
+ except ValueError:
516
+ raise self.parse_error(InvalidDateError)
517
+
518
+ if m.group(5):
519
+ try:
520
+ t = parse_rfc3339(raw)
521
+ assert isinstance(t, datetime.time)
522
+ return Time(
523
+ t.hour,
524
+ t.minute,
525
+ t.second,
526
+ t.microsecond,
527
+ t.tzinfo,
528
+ trivia,
529
+ raw,
530
+ )
531
+ except ValueError:
532
+ raise self.parse_error(InvalidTimeError)
533
+
534
+ item = self._parse_number(raw, trivia)
535
+ if item is not None:
536
+ return item
537
+
538
+ raise self.parse_error(InvalidNumberError)
539
+ else:
540
+ raise self.parse_error(UnexpectedCharError, c)
541
+
542
+ def _parse_true(self):
543
+ return self._parse_bool(BoolType.TRUE)
544
+
545
+ def _parse_false(self):
546
+ return self._parse_bool(BoolType.FALSE)
547
+
548
+ def _parse_bool(self, style: BoolType) -> Bool:
549
+ with self._state:
550
+ style = BoolType(style)
551
+
552
+ # only keep parsing for bool if the characters match the style
553
+ # try consuming rest of chars in style
554
+ for c in style:
555
+ self.consume(c, min=1, max=1)
556
+
557
+ return Bool(style, Trivia())
558
+
559
+ def _parse_array(self) -> Array:
560
+ # Consume opening bracket, EOF here is an issue (middle of array)
561
+ self.inc(exception=UnexpectedEofError)
562
+
563
+ elems: list[Item] = []
564
+ prev_value = None
565
+ while True:
566
+ # consume whitespace
567
+ mark = self._idx
568
+ self.consume(TOMLChar.SPACES + TOMLChar.NL)
569
+ indent = self._src[mark : self._idx]
570
+ newline = set(TOMLChar.NL) & set(indent)
571
+ if newline:
572
+ elems.append(Whitespace(indent))
573
+ continue
574
+
575
+ # consume comment
576
+ if self._current == "#":
577
+ cws, comment, trail = self._parse_comment_trail(parse_trail=False)
578
+ elems.append(Comment(Trivia(indent, cws, comment, trail)))
579
+ continue
580
+
581
+ # consume indent
582
+ if indent:
583
+ elems.append(Whitespace(indent))
584
+ continue
585
+
586
+ # consume value
587
+ if not prev_value:
588
+ try:
589
+ elems.append(self._parse_value())
590
+ prev_value = True
591
+ continue
592
+ except UnexpectedCharError:
593
+ pass
594
+
595
+ # consume comma
596
+ if prev_value and self._current == ",":
597
+ self.inc(exception=UnexpectedEofError)
598
+ elems.append(Whitespace(","))
599
+ prev_value = False
600
+ continue
601
+
602
+ # consume closing bracket
603
+ if self._current == "]":
604
+ # consume closing bracket, EOF here doesn't matter
605
+ self.inc()
606
+ break
607
+
608
+ raise self.parse_error(UnexpectedCharError, self._current)
609
+
610
+ try:
611
+ res = Array(elems, Trivia())
612
+ except ValueError:
613
+ pass
614
+ else:
615
+ return res
616
+
617
+ def _parse_inline_table(self) -> InlineTable:
618
+ # consume opening bracket, EOF here is an issue (middle of array)
619
+ self.inc(exception=UnexpectedEofError)
620
+
621
+ elems = Container(True)
622
+ trailing_comma = None
623
+ while True:
624
+ # consume leading whitespace
625
+ mark = self._idx
626
+ self.consume(TOMLChar.SPACES)
627
+ raw = self._src[mark : self._idx]
628
+ if raw:
629
+ elems.add(Whitespace(raw))
630
+
631
+ if not trailing_comma:
632
+ # None: empty inline table
633
+ # False: previous key-value pair was not followed by a comma
634
+ if self._current == "}":
635
+ # consume closing bracket, EOF here doesn't matter
636
+ self.inc()
637
+ break
638
+
639
+ if (
640
+ trailing_comma is False
641
+ or trailing_comma is None
642
+ and self._current == ","
643
+ ):
644
+ # Either the previous key-value pair was not followed by a comma
645
+ # or the table has an unexpected leading comma.
646
+ raise self.parse_error(UnexpectedCharError, self._current)
647
+ else:
648
+ # True: previous key-value pair was followed by a comma
649
+ if self._current == "}" or self._current == ",":
650
+ raise self.parse_error(UnexpectedCharError, self._current)
651
+
652
+ key, val = self._parse_key_value(False)
653
+ elems.add(key, val)
654
+
655
+ # consume trailing whitespace
656
+ mark = self._idx
657
+ self.consume(TOMLChar.SPACES)
658
+ raw = self._src[mark : self._idx]
659
+ if raw:
660
+ elems.add(Whitespace(raw))
661
+
662
+ # consume trailing comma
663
+ trailing_comma = self._current == ","
664
+ if trailing_comma:
665
+ # consume closing bracket, EOF here is an issue (middle of inline table)
666
+ self.inc(exception=UnexpectedEofError)
667
+
668
+ return InlineTable(elems, Trivia())
669
+
670
+ def _parse_number(self, raw: str, trivia: Trivia) -> Item | None:
671
+ # Leading zeros are not allowed
672
+ sign = ""
673
+ if raw.startswith(("+", "-")):
674
+ sign = raw[0]
675
+ raw = raw[1:]
676
+
677
+ if len(raw) > 1 and (
678
+ raw.startswith("0")
679
+ and not raw.startswith(("0.", "0o", "0x", "0b", "0e"))
680
+ or sign
681
+ and raw.startswith(".")
682
+ ):
683
+ return None
684
+
685
+ if raw.startswith(("0o", "0x", "0b")) and sign:
686
+ return None
687
+
688
+ digits = "[0-9]"
689
+ base = 10
690
+ if raw.startswith("0b"):
691
+ digits = "[01]"
692
+ base = 2
693
+ elif raw.startswith("0o"):
694
+ digits = "[0-7]"
695
+ base = 8
696
+ elif raw.startswith("0x"):
697
+ digits = "[0-9a-f]"
698
+ base = 16
699
+
700
+ # Underscores should be surrounded by digits
701
+ clean = re.sub(f"(?i)(?<={digits})_(?={digits})", "", raw).lower()
702
+
703
+ if "_" in clean:
704
+ return None
705
+
706
+ if (
707
+ clean.endswith(".")
708
+ or not clean.startswith("0x")
709
+ and clean.split("e", 1)[0].endswith(".")
710
+ ):
711
+ return None
712
+
713
+ try:
714
+ return Integer(int(sign + clean, base), trivia, sign + raw)
715
+ except ValueError:
716
+ try:
717
+ return Float(float(sign + clean), trivia, sign + raw)
718
+ except ValueError:
719
+ return None
720
+
721
+ def _parse_literal_string(self) -> String:
722
+ with self._state:
723
+ return self._parse_string(StringType.SLL)
724
+
725
+ def _parse_basic_string(self) -> String:
726
+ with self._state:
727
+ return self._parse_string(StringType.SLB)
728
+
729
+ def _parse_escaped_char(self, multiline):
730
+ if multiline and self._current.is_ws():
731
+ # When the last non-whitespace character on a line is
732
+ # a \, it will be trimmed along with all whitespace
733
+ # (including newlines) up to the next non-whitespace
734
+ # character or closing delimiter.
735
+ # """\
736
+ # hello \
737
+ # world"""
738
+ tmp = ""
739
+ while self._current.is_ws():
740
+ tmp += self._current
741
+ # consume the whitespace, EOF here is an issue
742
+ # (middle of string)
743
+ self.inc(exception=UnexpectedEofError)
744
+ continue
745
+
746
+ # the escape followed by whitespace must have a newline
747
+ # before any other chars
748
+ if "\n" not in tmp:
749
+ raise self.parse_error(InvalidCharInStringError, self._current)
750
+
751
+ return ""
752
+
753
+ if self._current in _escaped:
754
+ c = _escaped[self._current]
755
+
756
+ # consume this char, EOF here is an issue (middle of string)
757
+ self.inc(exception=UnexpectedEofError)
758
+
759
+ return c
760
+
761
+ if self._current in {"u", "U"}:
762
+ # this needs to be a unicode
763
+ u, ue = self._peek_unicode(self._current == "U")
764
+ if u is not None:
765
+ # consume the U char and the unicode value
766
+ self.inc_n(len(ue) + 1)
767
+
768
+ return u
769
+
770
+ raise self.parse_error(InvalidUnicodeValueError)
771
+
772
+ raise self.parse_error(InvalidCharInStringError, self._current)
773
+
774
+ def _parse_string(self, delim: StringType) -> String:
775
+ # only keep parsing for string if the current character matches the delim
776
+ if self._current != delim.unit:
777
+ raise self.parse_error(
778
+ InternalParserError,
779
+ f"Invalid character for string type {delim}",
780
+ )
781
+
782
+ # consume the opening/first delim, EOF here is an issue
783
+ # (middle of string or middle of delim)
784
+ self.inc(exception=UnexpectedEofError)
785
+
786
+ if self._current == delim.unit:
787
+ # consume the closing/second delim, we do not care if EOF occurs as
788
+ # that would simply imply an empty single line string
789
+ if not self.inc() or self._current != delim.unit:
790
+ # Empty string
791
+ return String(delim, "", "", Trivia())
792
+
793
+ # consume the third delim, EOF here is an issue (middle of string)
794
+ self.inc(exception=UnexpectedEofError)
795
+
796
+ delim = delim.toggle() # convert delim to multi delim
797
+
798
+ self.mark() # to extract the original string with whitespace and all
799
+ value = ""
800
+
801
+ # A newline immediately following the opening delimiter will be trimmed.
802
+ if delim.is_multiline():
803
+ if self._current == "\n":
804
+ # consume the newline, EOF here is an issue (middle of string)
805
+ self.inc(exception=UnexpectedEofError)
806
+ else:
807
+ cur = self._current
808
+ with self._state(restore=True):
809
+ if self.inc():
810
+ cur += self._current
811
+ if cur == "\r\n":
812
+ self.inc_n(2, exception=UnexpectedEofError)
813
+
814
+ escaped = False # whether the previous key was ESCAPE
815
+ while True:
816
+ code = ord(self._current)
817
+ if (
818
+ delim.is_singleline()
819
+ and not escaped
820
+ and (code == CHR_DEL or code <= CTRL_CHAR_LIMIT and code != CTRL_I)
821
+ ) or (
822
+ delim.is_multiline()
823
+ and not escaped
824
+ and (
825
+ code == CHR_DEL
826
+ or code <= CTRL_CHAR_LIMIT
827
+ and code not in [CTRL_I, CTRL_J, CTRL_M]
828
+ )
829
+ ):
830
+ raise self.parse_error(InvalidControlChar, code, "strings")
831
+ elif not escaped and self._current == delim.unit:
832
+ # try to process current as a closing delim
833
+ original = self.extract()
834
+
835
+ close = ""
836
+ if delim.is_multiline():
837
+ # Consume the delimiters to see if we are at the end of the string
838
+ close = ""
839
+ while self._current == delim.unit:
840
+ close += self._current
841
+ self.inc()
842
+
843
+ if len(close) < 3:
844
+ # Not a triple quote, leave in result as-is.
845
+ # Adding back the characters we already consumed
846
+ value += close
847
+ continue
848
+
849
+ if len(close) == 3:
850
+ # We are at the end of the string
851
+ return String(delim, value, original, Trivia())
852
+
853
+ if len(close) >= 6:
854
+ raise self.parse_error(InvalidCharInStringError, self._current)
855
+
856
+ value += close[:-3]
857
+ original += close[:-3]
858
+
859
+ return String(delim, value, original, Trivia())
860
+ else:
861
+ # consume the closing delim, we do not care if EOF occurs as
862
+ # that would simply imply the end of self._src
863
+ self.inc()
864
+
865
+ return String(delim, value, original, Trivia())
866
+ elif delim.is_basic() and escaped:
867
+ # attempt to parse the current char as an escaped value, an exception
868
+ # is raised if this fails
869
+ value += self._parse_escaped_char(delim.is_multiline())
870
+
871
+ # no longer escaped
872
+ escaped = False
873
+ elif delim.is_basic() and self._current == "\\":
874
+ # the next char is being escaped
875
+ escaped = True
876
+
877
+ # consume this char, EOF here is an issue (middle of string)
878
+ self.inc(exception=UnexpectedEofError)
879
+ else:
880
+ # this is either a literal string where we keep everything as is,
881
+ # or this is not a special escaped char in a basic string
882
+ value += self._current
883
+
884
+ # consume this char, EOF here is an issue (middle of string)
885
+ self.inc(exception=UnexpectedEofError)
886
+
887
+ def _parse_table(
888
+ self, parent_name: Key | None = None, parent: Table | None = None
889
+ ) -> tuple[Key, Table | AoT]:
890
+ """
891
+ Parses a table element.
892
+ """
893
+ if self._current != "[":
894
+ raise self.parse_error(
895
+ InternalParserError, "_parse_table() called on non-bracket character."
896
+ )
897
+
898
+ indent = self.extract()
899
+ self.inc() # Skip opening bracket
900
+
901
+ if self.end():
902
+ raise self.parse_error(UnexpectedEofError)
903
+
904
+ is_aot = False
905
+ if self._current == "[":
906
+ if not self.inc():
907
+ raise self.parse_error(UnexpectedEofError)
908
+
909
+ is_aot = True
910
+ try:
911
+ key = self._parse_key()
912
+ except EmptyKeyError:
913
+ raise self.parse_error(EmptyTableNameError) from None
914
+ if self.end():
915
+ raise self.parse_error(UnexpectedEofError)
916
+ elif self._current != "]":
917
+ raise self.parse_error(UnexpectedCharError, self._current)
918
+
919
+ key.sep = ""
920
+ full_key = key
921
+ name_parts = tuple(key)
922
+ if any(" " in part.key.strip() and part.is_bare() for part in name_parts):
923
+ raise self.parse_error(
924
+ ParseError, f'Invalid table name "{full_key.as_string()}"'
925
+ )
926
+
927
+ missing_table = False
928
+ if parent_name:
929
+ parent_name_parts = tuple(parent_name)
930
+ else:
931
+ parent_name_parts = ()
932
+
933
+ if len(name_parts) > len(parent_name_parts) + 1:
934
+ missing_table = True
935
+
936
+ name_parts = name_parts[len(parent_name_parts) :]
937
+
938
+ values = Container(True)
939
+
940
+ self.inc() # Skip closing bracket
941
+ if is_aot:
942
+ # TODO: Verify close bracket
943
+ self.inc()
944
+
945
+ cws, comment, trail = self._parse_comment_trail()
946
+
947
+ result = Null()
948
+ table = Table(
949
+ values,
950
+ Trivia(indent, cws, comment, trail),
951
+ is_aot,
952
+ name=name_parts[0].key if name_parts else key.key,
953
+ display_name=full_key.as_string(),
954
+ is_super_table=False,
955
+ )
956
+
957
+ if len(name_parts) > 1:
958
+ if missing_table:
959
+ # Missing super table
960
+ # i.e. a table initialized like this: [foo.bar]
961
+ # without initializing [foo]
962
+ #
963
+ # So we have to create the parent tables
964
+ table = Table(
965
+ Container(True),
966
+ Trivia("", cws, comment, trail),
967
+ is_aot and name_parts[0] in self._aot_stack,
968
+ is_super_table=True,
969
+ name=name_parts[0].key,
970
+ )
971
+
972
+ result = table
973
+ key = name_parts[0]
974
+
975
+ for i, _name in enumerate(name_parts[1:]):
976
+ child = table.get(
977
+ _name,
978
+ Table(
979
+ Container(True),
980
+ Trivia(indent, cws, comment, trail),
981
+ is_aot and i == len(name_parts) - 2,
982
+ is_super_table=i < len(name_parts) - 2,
983
+ name=_name.key,
984
+ display_name=full_key.as_string()
985
+ if i == len(name_parts) - 2
986
+ else None,
987
+ ),
988
+ )
989
+
990
+ if is_aot and i == len(name_parts) - 2:
991
+ table.raw_append(_name, AoT([child], name=table.name, parsed=True))
992
+ else:
993
+ table.raw_append(_name, child)
994
+
995
+ table = child
996
+ values = table.value
997
+ else:
998
+ if name_parts:
999
+ key = name_parts[0]
1000
+
1001
+ while not self.end():
1002
+ item = self._parse_item()
1003
+ if item:
1004
+ _key, item = item
1005
+ if not self._merge_ws(item, values):
1006
+ table.raw_append(_key, item)
1007
+ else:
1008
+ if self._current == "[":
1009
+ _, key_next = self._peek_table()
1010
+
1011
+ if self._is_child(full_key, key_next):
1012
+ key_next, table_next = self._parse_table(full_key, table)
1013
+
1014
+ table.raw_append(key_next, table_next)
1015
+
1016
+ # Picking up any sibling
1017
+ while not self.end():
1018
+ _, key_next = self._peek_table()
1019
+
1020
+ if not self._is_child(full_key, key_next):
1021
+ break
1022
+
1023
+ key_next, table_next = self._parse_table(full_key, table)
1024
+
1025
+ table.raw_append(key_next, table_next)
1026
+
1027
+ break
1028
+ else:
1029
+ raise self.parse_error(
1030
+ InternalParserError,
1031
+ "_parse_item() returned None on a non-bracket character.",
1032
+ )
1033
+ table.value._validate_out_of_order_table()
1034
+ if isinstance(result, Null):
1035
+ result = table
1036
+
1037
+ if is_aot and (not self._aot_stack or full_key != self._aot_stack[-1]):
1038
+ result = self._parse_aot(result, full_key)
1039
+
1040
+ return key, result
1041
+
1042
+ def _peek_table(self) -> tuple[bool, Key]:
1043
+ """
1044
+ Peeks ahead non-intrusively by cloning then restoring the
1045
+ initial state of the parser.
1046
+
1047
+ Returns the name of the table about to be parsed,
1048
+ as well as whether it is part of an AoT.
1049
+ """
1050
+ # we always want to restore after exiting this scope
1051
+ with self._state(save_marker=True, restore=True):
1052
+ if self._current != "[":
1053
+ raise self.parse_error(
1054
+ InternalParserError,
1055
+ "_peek_table() entered on non-bracket character",
1056
+ )
1057
+
1058
+ # AoT
1059
+ self.inc()
1060
+ is_aot = False
1061
+ if self._current == "[":
1062
+ self.inc()
1063
+ is_aot = True
1064
+ try:
1065
+ return is_aot, self._parse_key()
1066
+ except EmptyKeyError:
1067
+ raise self.parse_error(EmptyTableNameError) from None
1068
+
1069
+ def _parse_aot(self, first: Table, name_first: Key) -> AoT:
1070
+ """
1071
+ Parses all siblings of the provided table first and bundles them into
1072
+ an AoT.
1073
+ """
1074
+ payload = [first]
1075
+ self._aot_stack.append(name_first)
1076
+ while not self.end():
1077
+ is_aot_next, name_next = self._peek_table()
1078
+ if is_aot_next and name_next == name_first:
1079
+ _, table = self._parse_table(name_first)
1080
+ payload.append(table)
1081
+ else:
1082
+ break
1083
+
1084
+ self._aot_stack.pop()
1085
+
1086
+ return AoT(payload, parsed=True)
1087
+
1088
+ def _peek(self, n: int) -> str:
1089
+ """
1090
+ Peeks ahead n characters.
1091
+
1092
+ n is the max number of characters that will be peeked.
1093
+ """
1094
+ # we always want to restore after exiting this scope
1095
+ with self._state(restore=True):
1096
+ buf = ""
1097
+ for _ in range(n):
1098
+ if self._current not in " \t\n\r#,]}" + self._src.EOF:
1099
+ buf += self._current
1100
+ self.inc()
1101
+ continue
1102
+
1103
+ break
1104
+ return buf
1105
+
1106
+ def _peek_unicode(self, is_long: bool) -> tuple[str | None, str | None]:
1107
+ """
1108
+ Peeks ahead non-intrusively by cloning then restoring the
1109
+ initial state of the parser.
1110
+
1111
+ Returns the unicode value is it's a valid one else None.
1112
+ """
1113
+ # we always want to restore after exiting this scope
1114
+ with self._state(save_marker=True, restore=True):
1115
+ if self._current not in {"u", "U"}:
1116
+ raise self.parse_error(
1117
+ InternalParserError, "_peek_unicode() entered on non-unicode value"
1118
+ )
1119
+
1120
+ self.inc() # Dropping prefix
1121
+ self.mark()
1122
+
1123
+ if is_long:
1124
+ chars = 8
1125
+ else:
1126
+ chars = 4
1127
+
1128
+ if not self.inc_n(chars):
1129
+ value, extracted = None, None
1130
+ else:
1131
+ extracted = self.extract()
1132
+
1133
+ if extracted[0].lower() == "d" and extracted[1].strip("01234567"):
1134
+ return None, None
1135
+
1136
+ try:
1137
+ value = chr(int(extracted, 16))
1138
+ except (ValueError, OverflowError):
1139
+ value = None
1140
+
1141
+ return value, extracted