|
| 1 | +# frozen_string_literal: true |
| 2 | + |
| 3 | +require "rbconfig" |
| 4 | +require "tmpdir" |
| 5 | + |
| 6 | +module Singed |
| 7 | + module Speedscope |
| 8 | + # Take latest version from https://github.com/jlfwong/speedscope/releases |
| 9 | + # that have ZIP archive with self-contained version published |
| 10 | + VERSION = "1.24.0" |
| 11 | + |
| 12 | + class << self |
| 13 | + def bundled_index_html |
| 14 | + File.join(File.expand_path("../..", __dir__), "vendor", "speedscope", "index.html") |
| 15 | + end |
| 16 | + |
| 17 | + def open_command(profile_path) |
| 18 | + if File.exist?(bundled_index_html) |
| 19 | + "#{os_open_command} file://#{bundled_index_html}#localProfilePath=#{profile_path}" |
| 20 | + else |
| 21 | + "npx speedscope #{profile_path}" |
| 22 | + end |
| 23 | + end |
| 24 | + |
| 25 | + def open(profile_path) |
| 26 | + profile_path = profile_path.to_s |
| 27 | + |
| 28 | + if File.exist?(bundled_index_html) |
| 29 | + open_with_bundled_speedscope(profile_path) |
| 30 | + else |
| 31 | + open_with_npx(profile_path) |
| 32 | + end |
| 33 | + end |
| 34 | + |
| 35 | + private |
| 36 | + |
| 37 | + def open_with_npx(profile_path) |
| 38 | + system("npx", "speedscope", profile_path) |
| 39 | + end |
| 40 | + |
| 41 | + # Based on speedscope CLI code (MIT license) |
| 42 | + # See https://github.com/jlfwong/speedscope/blob/3613918de0dd55a263d0d04f85b0c8c2039c7bee/bin/cli.mjs |
| 43 | + def open_with_bundled_speedscope(profile_path) |
| 44 | + source_buffer = File.binread(profile_path) |
| 45 | + filename = File.basename(profile_path) |
| 46 | + |
| 47 | + source_base64 = [source_buffer].pack("m0") |
| 48 | + js_source = "speedscope.loadFileFromBase64(#{filename.inspect}, #{source_base64.inspect})" |
| 49 | + |
| 50 | + file_prefix = "speedscope-#{Time.now.to_i}-#{Process.pid}" |
| 51 | + js_path = File.join(Dir.tmpdir, "#{file_prefix}.js") |
| 52 | + File.write(js_path, js_source) |
| 53 | + |
| 54 | + url_to_open = "file://#{File.expand_path(bundled_index_html)}#localProfilePath=#{js_path}" |
| 55 | + |
| 56 | + # See https://github.com/jlfwong/speedscope/blob/3613918de0dd55a263d0d04f85b0c8c2039c7bee/bin/cli.mjs#L96-L105 |
| 57 | + host_os = RbConfig::CONFIG["host_os"] |
| 58 | + if host_os =~ /mswin|mingw|cygwin/ || host_os =~ /darwin/ |
| 59 | + html_path = File.join(Dir.tmpdir, "#{file_prefix}.html") |
| 60 | + File.write(html_path, "<script>window.location=#{url_to_open.inspect}</script>") |
| 61 | + url_to_open = "file://#{html_path}" |
| 62 | + end |
| 63 | + |
| 64 | + system os_open_command, url_to_open |
| 65 | + end |
| 66 | + |
| 67 | + def os_open_command |
| 68 | + case host_os = RbConfig::CONFIG["host_os"] |
| 69 | + when /mswin|mingw|cygwin/ |
| 70 | + "start" |
| 71 | + when /darwin/ |
| 72 | + "open" |
| 73 | + when /linux|bsd/ |
| 74 | + "xdg-open" |
| 75 | + else |
| 76 | + raise "Unsupported OS to open browser: #{host_os}" |
| 77 | + end |
| 78 | + end |
| 79 | + end |
| 80 | + end |
| 81 | +end |
0 commit comments