Module: Dommy::Internal::GlobalFunctions

Defined in:
lib/dommy/internal/global_functions.rb

Overview

Stateless global functions exposed on the JS global (Window) that don't depend on any window state.

Class Method Summary collapse

Class Method Details

.atob(value) ⇒ Object

JS atob: decode base64 to a binary (Latin1) string. ASCII whitespace is ignored; an invalid alphabet/length is an InvalidCharacterError. The decoded bytes are returned as a string whose code units equal the bytes.



55
56
57
58
59
60
61
62
63
# File 'lib/dommy/internal/global_functions.rb', line 55

def atob(value)
  data = value.to_s.gsub(/[\t\n\f\r ]/, "")
  invalid_atob! if data.length % 4 == 1 || !data.match?(%r{\A[A-Za-z0-9+/]*={0,2}\z})

  padded = data + ("=" * ((-data.length) % 4))
  Base64.strict_decode64(padded).bytes.map { |byte| byte.chr(Encoding::UTF_8) }.join
rescue ArgumentError
  invalid_atob!
end

.btoa(value) ⇒ Object

JS btoa: base64-encode a binary (Latin1) string. Each code unit must be 0..255; anything beyond Latin1 is an InvalidCharacterError (per spec).



41
42
43
44
45
46
47
48
49
50
# File 'lib/dommy/internal/global_functions.rb', line 41

def btoa(value)
  codepoints = js_domstring(value).codepoints
  if codepoints.any? { |c| c > 0xFF }
    raise DOMException::InvalidCharacterError.new(
      "Failed to execute 'btoa': characters outside the Latin1 range cannot be base64-encoded."
    )
  end

  Base64.strict_encode64(codepoints.pack("C*"))
end

.decode_uri_component(value) ⇒ Object

JS decodeURIComponent: percent-decode only — unlike form-urlencoded decoding, "+" stays a literal "+". Malformed UTF-8 becomes U+FFFD (a real engine throws URIError; nothing downstream relies on that).



35
36
37
# File 'lib/dommy/internal/global_functions.rb', line 35

def decode_uri_component(value)
  UrlParser.percent_decode(value.to_s).force_encoding(Encoding::UTF_8).scrub("\u{FFFD}")
end

.encode_uri_component(value) ⇒ Object

JS encodeURIComponent: UTF-8 percent-encode everything except the unreserved marks A-Za-z0-9 - _ . ! ~ * ' ( ). (Neither ERB::Util.url_encode nor CGI.escape matches this set — the former encodes !~*'(), the latter uses + for space.)



28
29
30
# File 'lib/dommy/internal/global_functions.rb', line 28

def encode_uri_component(value)
  value.to_s.b.gsub(/[^A-Za-z0-9\-_.!~*'()]/n) { |c| format("%%%02X", c.ord) }
end

.invalid_atob!Object



65
66
67
68
69
# File 'lib/dommy/internal/global_functions.rb', line 65

def invalid_atob!
  raise DOMException::InvalidCharacterError.new(
    "Failed to execute 'atob': the string to be decoded is not correctly base64-encoded."
  )
end

.js_domstring(value) ⇒ Object

WebIDL DOMString conversion of a JS value: null → "null", undefined → "undefined", booleans → "true"/"false", everything else its string form. (Ruby's nil.to_s is "", which would silently drop a btoa(null) arg.)



17
18
19
20
21
22
# File 'lib/dommy/internal/global_functions.rb', line 17

def js_domstring(value)
  return "null" if value.nil?
  return "undefined" if defined?(Bridge::UNDEFINED) && value.equal?(Bridge::UNDEFINED)

  value.to_s
end