Class: Opal::Fragment

Inherits:
Object
  • Object
show all
Defined in:
opal/lib/opal/fragment.rb

Overview

A fragment holds a string of generated javascript that will be written to the destination. It also keeps hold of the original sexp from which it was generated. Using this sexp, when writing fragments in order, a mapping can be created of the original location => target location, aka, source-maps!

These are generated by nodes, so will not have to create directly.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(code, scope, sexp = nil) ⇒ Fragment

Create fragment with javascript code and optional original [Opal::Sexp].

Parameters:

  • code (String)

    javascript code

  • sexp (Opal::Sexp) (defaults to: nil)

    sexp used for creating fragment



20
21
22
23
24
# File 'opal/lib/opal/fragment.rb', line 20

def initialize(code, scope, sexp = nil)
  @code = code.to_s
  @sexp = sexp
  @scope = scope
end

Instance Attribute Details

#codeString (readonly)

String of javascript this fragment holds

Returns:

  • (String)


14
15
16
# File 'opal/lib/opal/fragment.rb', line 14

def code
  @code
end

Instance Method Details

#columnInteger?

Original column this fragment was created from

Returns:

  • (Integer, nil)


123
124
125
# File 'opal/lib/opal/fragment.rb', line 123

def column
  location&.column
end

#inspectObject

Inspect the contents of this fragment, f("fooo")



27
28
29
# File 'opal/lib/opal/fragment.rb', line 27

def inspect
  "f(#{@code.inspect})"
end

#lineInteger?

Original line this fragment was created from

Returns:

  • (Integer, nil)


117
118
119
# File 'opal/lib/opal/fragment.rb', line 117

def line
  location&.line
end

#locationObject



95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'opal/lib/opal/fragment.rb', line 95

def location
  case
  when !@sexp
    nil
  when @sexp.type == :send
    loc = @sexp.loc
    if loc.respond_to? :dot # a>.b || a>+b / >a / a>[b]
      loc.dot || loc.selector
    elsif loc.respond_to? :operator # a >|= b
      loc.operator
    else
      @sexp
    end
  when @sexp.type == :iter
    @sexp.loc.begin # [1,2].each >{ }
  else
    @sexp
  end
end

#skip_source_map?Boolean

Returns:

  • (Boolean)


127
128
129
# File 'opal/lib/opal/fragment.rb', line 127

def skip_source_map?
  @sexp == false
end

#source_map_nameObject



89
90
91
92
93
# File 'opal/lib/opal/fragment.rb', line 89

def source_map_name
  return nil unless @sexp

  source_map_name_for(@sexp)
end

#source_map_name_for(sexp) ⇒ Object



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'opal/lib/opal/fragment.rb', line 31

def source_map_name_for(sexp)
  case sexp.type
  when :top
    case sexp.meta[:kind]
    when :require
      '<top (required)>'
    when :eval
      '(eval)'
    when :main
      '<main>'
    end
  when :begin, :newline, :js_return
    source_map_name_for(@scope.sexp) if @scope
  when :iter
    scope = @scope
    iters = 1
    while scope
      if scope.class == Nodes::IterNode
        iters += 1
        scope = scope.parent
      else
        break
      end
    end
    level = " (#{iters} levels)" if iters > 1
    "block#{level} in #{source_map_name_for(scope.sexp)}"
  when :self
    'self'
  when :module
    const, = *sexp
    "<module:#{source_map_name_for(const)}>"
  when :class
    const, = *sexp
    "<class:#{source_map_name_for(const)}>"
  when :const
    scope, name = *sexp
    if !scope || scope.type == :cbase
      name.to_s
    else
      "#{source_map_name_for(scope)}::#{name}"
    end
  when :int
    sexp.children.first
  when :def
    sexp.children.first
  when :defs
    sexp.children[1]
  when :send
    sexp.children[1]
  when :lvar, :lvasgn, :lvdeclare, :ivar, :ivasgn, :gvar, :cvar, :cvasgn, :gvars, :gvasgn, :arg
    sexp.children.first
  when :str, :xstr # Inside xstr - JS calls
    source_map_name_for(@scope.sexp)
  else
    # nil
  end
end