byebug 1.0.2 → 1.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +11 -0
- data/README.md +1 -1
- data/bin/byebug +1 -2
- data/byebug.gemspec +1 -1
- data/ext/byebug/byebug.c +50 -35
- data/ext/byebug/context.c +99 -45
- data/lib/byebug.rb +5 -10
- data/lib/byebug/command.rb +20 -12
- data/lib/byebug/commands/breakpoints.rb +1 -1
- data/lib/byebug/commands/control.rb +14 -21
- data/lib/byebug/commands/display.rb +4 -4
- data/lib/byebug/commands/enable.rb +20 -19
- data/lib/byebug/commands/eval.rb +1 -1
- data/lib/byebug/commands/finish.rb +4 -5
- data/lib/byebug/commands/info.rb +118 -116
- data/lib/byebug/commands/list.rb +72 -48
- data/lib/byebug/commands/reload.rb +4 -3
- data/lib/byebug/commands/set.rb +7 -16
- data/lib/byebug/commands/show.rb +2 -2
- data/lib/byebug/commands/threads.rb +7 -6
- data/lib/byebug/context.rb +10 -2
- data/lib/byebug/helper.rb +3 -3
- data/lib/byebug/processor.rb +1 -1
- data/lib/byebug/version.rb +1 -1
- data/old_doc/byebug.texi +45 -51
- data/test/breakpoints_test.rb +180 -195
- data/test/display_test.rb +59 -53
- data/test/eval_test.rb +0 -2
- data/test/examples/info.rb +5 -5
- data/test/examples/info_threads.rb +1 -1
- data/test/finish_test.rb +16 -15
- data/test/info_test.rb +9 -10
- data/test/irb_test.rb +64 -65
- data/test/list_test.rb +76 -50
- data/test/method_test.rb +10 -5
- data/test/post_mortem_test.rb +27 -25
- data/test/reload_test.rb +31 -31
- data/test/restart_test.rb +106 -110
- data/test/show_test.rb +8 -16
- data/test/stepping_test.rb +4 -2
- data/test/support/test_dsl.rb +37 -76
- data/test/test_helper.rb +0 -1
- data/test/variables_test.rb +9 -12
- metadata +4 -4
@@ -22,7 +22,7 @@ module Byebug
|
|
22
22
|
if expr
|
23
23
|
if expr !~ /^\s*if\s+(.+)/
|
24
24
|
if file or line
|
25
|
-
errmsg "Expecting
|
25
|
+
errmsg "Expecting \"if\" in breakpoint condition; got: #{expr}.\n"
|
26
26
|
else
|
27
27
|
errmsg "Invalid breakpoint location: #{expr}.\n"
|
28
28
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module Byebug
|
2
2
|
|
3
|
-
class RestartCommand < Command
|
3
|
+
class RestartCommand < Command
|
4
4
|
self.allow_in_control = true
|
5
5
|
|
6
6
|
def regexp
|
@@ -12,28 +12,24 @@ module Byebug
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def execute
|
15
|
-
|
16
|
-
|
17
|
-
return
|
18
|
-
end
|
15
|
+
return errmsg "Don't know name of debugged program\n" unless
|
16
|
+
defined? Byebug::PROG_SCRIPT
|
19
17
|
|
20
|
-
|
21
|
-
|
22
|
-
return
|
23
|
-
end
|
18
|
+
return errmsg "Ruby program #{Byebug::PROG_SCRIPT} doesn't exist\n" unless
|
19
|
+
File.exist?(File.expand_path(Byebug::PROG_SCRIPT))
|
24
20
|
|
25
|
-
if not defined? Byebug::
|
21
|
+
if not defined? Byebug::BYEBUG_SCRIPT
|
26
22
|
print "Byebug was not called from the outset...\n"
|
27
23
|
if not File.executable?(Byebug::PROG_SCRIPT)
|
28
24
|
print "Ruby program #{Byebug::PROG_SCRIPT} not executable... " \
|
29
25
|
"We'll add a call to Ruby.\n"
|
30
26
|
ruby = begin defined?(Gem) ? Gem.ruby : "ruby" rescue "ruby" end
|
31
|
-
|
27
|
+
cmd = "#{ruby} -I#{$:.join(' -I')} #{Byebug::PROG_SCRIPT}"
|
32
28
|
else
|
33
|
-
|
29
|
+
cmd = Byebug::PROG_SCRIPT
|
34
30
|
end
|
35
31
|
else
|
36
|
-
|
32
|
+
cmd = Byebug::BYEBUG_SCRIPT
|
37
33
|
end
|
38
34
|
|
39
35
|
begin
|
@@ -43,16 +39,13 @@ module Byebug
|
|
43
39
|
end
|
44
40
|
|
45
41
|
if @match[1]
|
46
|
-
|
42
|
+
cmd += " #{@match[1]}"
|
43
|
+
elsif not defined? Command.settings[:argv]
|
44
|
+
return errmsg "Arguments not set. Use 'set args' to set them.\n"
|
47
45
|
else
|
48
|
-
|
49
|
-
|
50
|
-
return
|
51
|
-
else
|
52
|
-
argv = Command.settings[:argv]
|
53
|
-
end
|
46
|
+
require 'shellwords'
|
47
|
+
cmd += " #{Command.settings[:argv].compact.shelljoin}"
|
54
48
|
end
|
55
|
-
cmd = "#{byebug_script} #{argv.compact.join(' ')}"
|
56
49
|
|
57
50
|
# An execv would be preferable to the "exec" below.
|
58
51
|
print "Re exec'ing:\n\t#{cmd}\n"
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module Byebug
|
2
2
|
|
3
|
-
module DisplayFunctions
|
3
|
+
module DisplayFunctions
|
4
4
|
|
5
5
|
def display_expression(exp)
|
6
6
|
print "%s = %s\n", exp, debug_silent_eval(exp).to_s
|
@@ -22,7 +22,7 @@ module Byebug
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
-
class AddDisplayCommand < Command
|
25
|
+
class AddDisplayCommand < Command
|
26
26
|
def regexp
|
27
27
|
/^\s*disp(?:lay)?\s+(.+)$/
|
28
28
|
end
|
@@ -47,7 +47,7 @@ module Byebug
|
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
50
|
-
class DisplayCommand < Command
|
50
|
+
class DisplayCommand < Command
|
51
51
|
def self.always_run
|
52
52
|
Byebug.annotate = 0 unless Byebug.annotate
|
53
53
|
if Byebug.annotate > 1
|
@@ -78,7 +78,7 @@ module Byebug
|
|
78
78
|
end
|
79
79
|
end
|
80
80
|
|
81
|
-
class DeleteDisplayCommand < Command
|
81
|
+
class DeleteDisplayCommand < Command
|
82
82
|
|
83
83
|
def regexp
|
84
84
|
/^\s* undisp(?:lay)? \s* (?:(\S+))?$/x
|
@@ -16,14 +16,15 @@ module Byebug
|
|
16
16
|
return nil unless pos
|
17
17
|
breakpoints.each do |b|
|
18
18
|
if b.id == pos
|
19
|
-
enabled = (
|
19
|
+
enabled = ('Enable' == is_enable)
|
20
20
|
if enabled
|
21
21
|
unless syntax_valid?(b.expr)
|
22
|
-
errmsg
|
22
|
+
errmsg "Expression \"#{b.expr}\" syntactically incorrect; " \
|
23
|
+
"breakpoint remains disabled.\n"
|
23
24
|
break
|
24
25
|
end
|
25
26
|
end
|
26
|
-
b.enabled = (
|
27
|
+
b.enabled = ('Enable' == is_enable)
|
27
28
|
break
|
28
29
|
end
|
29
30
|
end
|
@@ -38,7 +39,7 @@ module Byebug
|
|
38
39
|
args.each do |pos|
|
39
40
|
pos = get_int(pos, "#{is_enable} display", 1, @state.display.size)
|
40
41
|
return nil unless pos
|
41
|
-
@state.display[pos-1][0] = (
|
42
|
+
@state.display[pos-1][0] = ('Enable' == is_enable)
|
42
43
|
end
|
43
44
|
end
|
44
45
|
|
@@ -49,11 +50,11 @@ module Byebug
|
|
49
50
|
[
|
50
51
|
['breakpoints', 2, 'Enable specified breakpoints',
|
51
52
|
'Give breakpoint numbers (separated by spaces) as arguments. This is ' \
|
52
|
-
'used to cancel the effect of the
|
53
|
+
'used to cancel the effect of the "disable" command.'],
|
53
54
|
['display', 2,
|
54
55
|
'Enable some expressions to be displayed when program stops',
|
55
56
|
'Arguments are the code numbers of the expressions to resume ' \
|
56
|
-
'displaying. Do
|
57
|
+
'displaying. Do "info display" to see the current list of code ' \
|
57
58
|
'numbers.'],
|
58
59
|
].map do |name, min, short_help, long_help|
|
59
60
|
SubcmdStruct.new(name, min, short_help, long_help)
|
@@ -65,8 +66,8 @@ module Byebug
|
|
65
66
|
|
66
67
|
def execute
|
67
68
|
if not @match[1]
|
68
|
-
errmsg "\"enable\" must be followed \"display\", \"breakpoints\""
|
69
|
-
|
69
|
+
errmsg "\"enable\" must be followed by \"display\", \"breakpoints\" " \
|
70
|
+
"or breakpoint numbers.\n"
|
70
71
|
else
|
71
72
|
args = @match[1].split(/[ \t]+/)
|
72
73
|
param = args.shift
|
@@ -74,17 +75,17 @@ module Byebug
|
|
74
75
|
if subcmd
|
75
76
|
send("enable_#{subcmd.name}", args)
|
76
77
|
else
|
77
|
-
send(
|
78
|
+
send('enable_breakpoints', args.unshift(param))
|
78
79
|
end
|
79
80
|
end
|
80
81
|
end
|
81
82
|
|
82
83
|
def enable_breakpoints(args)
|
83
|
-
enable_disable_breakpoints(
|
84
|
+
enable_disable_breakpoints('Enable', args)
|
84
85
|
end
|
85
86
|
|
86
87
|
def enable_display(args)
|
87
|
-
enable_disable_display(
|
88
|
+
enable_disable_display('Enable', args)
|
88
89
|
end
|
89
90
|
|
90
91
|
class << self
|
@@ -99,7 +100,7 @@ module Byebug
|
|
99
100
|
return "Invalid \"enable\" subcommand \"#{args[1]}\"." unless subcmd
|
100
101
|
|
101
102
|
str = subcmd.short_help + '.'
|
102
|
-
str +=
|
103
|
+
str += '\n' + subcmd.long_help if subcmd.long_help
|
103
104
|
return str
|
104
105
|
end
|
105
106
|
|
@@ -127,7 +128,7 @@ module Byebug
|
|
127
128
|
'breakpoint is not forgotten, but has no effect until reenabled.'],
|
128
129
|
['display', 1, 'Disable some display expressions when program stops',
|
129
130
|
'Arguments are the code numbers of the expressions to stop ' \
|
130
|
-
'displaying. Do
|
131
|
+
'displaying. Do "info display" to see the current list of code ' \
|
131
132
|
'numbers.'],
|
132
133
|
].map do |name, min, short_help, long_help|
|
133
134
|
SubcmdStruct.new(name, min, short_help, long_help)
|
@@ -139,8 +140,8 @@ module Byebug
|
|
139
140
|
|
140
141
|
def execute
|
141
142
|
if not @match[1]
|
142
|
-
errmsg "\"disable\" must be followed \"display\", \"breakpoints\""
|
143
|
-
|
143
|
+
errmsg "\"disable\" must be followed by \"display\", \"breakpoints\" " \
|
144
|
+
"or breakpoint numbers.\n"
|
144
145
|
else
|
145
146
|
args = @match[1].split(/[ \t]+/)
|
146
147
|
param = args.shift
|
@@ -148,17 +149,17 @@ module Byebug
|
|
148
149
|
if subcmd
|
149
150
|
send("disable_#{subcmd.name}", args)
|
150
151
|
else
|
151
|
-
send(
|
152
|
+
send('disable_breakpoints', args.unshift(param))
|
152
153
|
end
|
153
154
|
end
|
154
155
|
end
|
155
156
|
|
156
157
|
def disable_breakpoints(args)
|
157
|
-
enable_disable_breakpoints(
|
158
|
+
enable_disable_breakpoints('Disable', args)
|
158
159
|
end
|
159
160
|
|
160
161
|
def disable_display(args)
|
161
|
-
enable_disable_display(
|
162
|
+
enable_disable_display('Disable', args)
|
162
163
|
end
|
163
164
|
|
164
165
|
class << self
|
@@ -173,7 +174,7 @@ module Byebug
|
|
173
174
|
return "Invalid \"disable\" subcommand \"#{args[1]}\"." unless subcmd
|
174
175
|
|
175
176
|
str = subcmd.short_help + '.'
|
176
|
-
str +=
|
177
|
+
str += '\n' + subcmd.long_help if subcmd.long_help
|
177
178
|
return str
|
178
179
|
end
|
179
180
|
|
data/lib/byebug/commands/eval.rb
CHANGED
@@ -31,11 +31,10 @@ module Byebug
|
|
31
31
|
%{
|
32
32
|
fin[ish] [frame-number]\tExecute until selected stack frame returns.
|
33
33
|
|
34
|
-
If no frame number is given, we run until the currently selected frame
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
returns.
|
34
|
+
If no frame number is given, we run until the currently selected frame returns.
|
35
|
+
The currently selected frame starts out the most-recent frame or 0 if no frame
|
36
|
+
positioning (e.g "up", "down" or "frame") has been performed. If a frame number
|
37
|
+
is given we run until that frame returns.
|
39
38
|
}
|
40
39
|
end
|
41
40
|
end
|
data/lib/byebug/commands/info.rb
CHANGED
@@ -41,18 +41,18 @@ module Byebug
|
|
41
41
|
['locals', 2, 'Local variables of the current stack frame'],
|
42
42
|
['program', 2, 'Execution status of the program'],
|
43
43
|
['stack', 2, 'Backtrace of the stack'],
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
44
|
+
['thread', 6, 'List info about thread NUM',
|
45
|
+
'If no thread number is given, we list info for all threads. "terse"' \
|
46
|
+
' and "verbose" options are possible. If "terse", just give summary ' \
|
47
|
+
'thread name information. See "help info threads" for more detail ' \
|
48
|
+
'about this summary information. If "verbose" is appended to the end' \
|
49
|
+
' of the command, then the entire stack trace is given for each ' \
|
50
|
+
'thread.'],
|
51
|
+
['threads', 7, 'information of currently-known threads',
|
52
|
+
'This information includes whether the thread is the current thread ' \
|
53
|
+
'(+), it\'s suspended ($) or it\'s ignored (!), plus the thread ' \
|
54
|
+
'number and the top stack item. If "verbose" is given then the ' \
|
55
|
+
'entire stack frame is shown.'],
|
56
56
|
['variables', 1,
|
57
57
|
'Local and instance variables of the current stack frame']
|
58
58
|
].map do |name, min, short_help, long_help|
|
@@ -114,37 +114,30 @@ module Byebug
|
|
114
114
|
end
|
115
115
|
|
116
116
|
def info_breakpoints(*args)
|
117
|
-
unless
|
118
|
-
|
119
|
-
|
117
|
+
return print "\"info breakpoints\" not available here.\n" unless
|
118
|
+
@state.context
|
119
|
+
|
120
|
+
return print "No breakpoints.\n" if Byebug.breakpoints.empty?
|
121
|
+
|
122
|
+
brkpts = Byebug.breakpoints.sort_by{|b| b.id}
|
123
|
+
unless args.empty?
|
124
|
+
indices = args.map{|a| a.to_i}
|
125
|
+
brkpts = brkpts.select{|b| indices.member?(b.id)}
|
126
|
+
return errmsg "No breakpoints found among list given.\n" if
|
127
|
+
brkpts.empty?
|
120
128
|
end
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
129
|
+
print "Num Enb What\n"
|
130
|
+
brkpts.each do |b|
|
131
|
+
print "%-3d %-3s at %s:%s%s\n", b.id,
|
132
|
+
b.enabled? ? 'y' : 'n',
|
133
|
+
b.source,
|
134
|
+
b.pos,
|
135
|
+
b.expr.nil? ? '' : " if #{b.expr}"
|
136
|
+
hits = b.hit_count
|
137
|
+
if hits > 0
|
138
|
+
s = (hits > 1) ? 's' : ''
|
139
|
+
print "\tbreakpoint already hit #{hits} time#{s}\n"
|
130
140
|
end
|
131
|
-
print "Num Enb What\n"
|
132
|
-
brkpts.each do |b|
|
133
|
-
if b.expr.nil?
|
134
|
-
print "%3d %s at %s:%s\n",
|
135
|
-
b.id, (b.enabled? ? 'y' : 'n'), b.source, b.pos
|
136
|
-
else
|
137
|
-
print "%3d %s at %s:%s if %s\n",
|
138
|
-
b.id, (b.enabled? ? 'y' : 'n'), b.source, b.pos, b.expr
|
139
|
-
end
|
140
|
-
hits = b.hit_count
|
141
|
-
if hits > 0
|
142
|
-
s = (hits > 1) ? 's' : ''
|
143
|
-
print "\tbreakpoint already hit #{hits} time#{s}\n"
|
144
|
-
end
|
145
|
-
end
|
146
|
-
else
|
147
|
-
print "No breakpoints.\n"
|
148
141
|
end
|
149
142
|
end
|
150
143
|
|
@@ -167,6 +160,35 @@ module Byebug
|
|
167
160
|
end
|
168
161
|
end
|
169
162
|
|
163
|
+
def info_file_path(file)
|
164
|
+
path = LineCache.path(file)
|
165
|
+
if path != file
|
166
|
+
print " - #{path}"
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
def info_file_lines(file)
|
171
|
+
lines = LineCache.size(file)
|
172
|
+
print "\t %d lines\n", lines if lines
|
173
|
+
end
|
174
|
+
|
175
|
+
def info_file_breakpoints(file)
|
176
|
+
breakpoints = LineCache.trace_line_numbers(file)
|
177
|
+
if breakpoints
|
178
|
+
print "\tbreakpoint line numbers:\n"
|
179
|
+
print columnize(breakpoints.to_a.sort, self.class.settings[:width])
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
def info_file_mtime(file)
|
184
|
+
stat = LineCache.stat(file)
|
185
|
+
print "\t%s\n", stat.mtime if stat
|
186
|
+
end
|
187
|
+
|
188
|
+
def info_file_sha1(file)
|
189
|
+
print "\t%s\n", LineCache.sha1(file)
|
190
|
+
end
|
191
|
+
|
170
192
|
def info_file(*args)
|
171
193
|
return info_files unless args[0]
|
172
194
|
file = args[0]
|
@@ -184,33 +206,13 @@ module Byebug
|
|
184
206
|
end
|
185
207
|
|
186
208
|
print "File #{file}"
|
187
|
-
|
188
|
-
if %w(all basic path).member?(subcmd.name) and path != file
|
189
|
-
print " - #{path}"
|
190
|
-
end
|
209
|
+
info_file_path(file) if %w(all basic path).member?(subcmd.name)
|
191
210
|
print "\n"
|
192
211
|
|
193
|
-
if %w(all basic lines).member?(subcmd.name)
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
if %w(all breakpoints).member?(subcmd.name)
|
199
|
-
breakpoints = LineCache.trace_line_numbers(file)
|
200
|
-
if breakpoints
|
201
|
-
print "\tbreakpoint line numbers:\n"
|
202
|
-
print columnize(breakpoints.to_a.sort, self.class.settings[:width])
|
203
|
-
end
|
204
|
-
end
|
205
|
-
|
206
|
-
if %w(all mtime).member?(subcmd.name)
|
207
|
-
stat = LineCache.stat(file)
|
208
|
-
print "\t%s\n", stat.mtime if stat
|
209
|
-
end
|
210
|
-
|
211
|
-
if %w(all sha1).member?(subcmd.name)
|
212
|
-
print "\t%s\n", LineCache.sha1(file)
|
213
|
-
end
|
212
|
+
info_file_lines(file) if %w(all basic lines).member?(subcmd.name)
|
213
|
+
info_file_breakpoints(file) if %w(all breakpoints).member?(subcmd.name)
|
214
|
+
info_file_mtime(file) if %w(all mtime).member?(subcmd.name)
|
215
|
+
info_file_sha1(file) if %w(all sha1).member?(subcmd.name)
|
214
216
|
end
|
215
217
|
|
216
218
|
def info_files(*args)
|
@@ -301,56 +303,56 @@ module Byebug
|
|
301
303
|
print_backtrace
|
302
304
|
end
|
303
305
|
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
306
|
+
def info_thread_preamble(arg)
|
307
|
+
if not @state.context
|
308
|
+
errmsg "info threads not available here.\n"
|
309
|
+
return false, false
|
310
|
+
end
|
311
|
+
verbose = if arg
|
312
|
+
subcmd = find(InfoThreadSubcommands, arg)
|
313
|
+
unless subcmd
|
314
|
+
errmsg "'terse' or 'verbose' expected. Got '#{arg}'\n"
|
315
|
+
return false, false
|
316
|
+
end
|
317
|
+
'verbose' == subcmd.name
|
318
|
+
else
|
319
|
+
false
|
320
|
+
end
|
321
|
+
return true, verbose
|
322
|
+
end
|
323
|
+
private :info_thread_preamble
|
324
|
+
|
325
|
+
def info_threads(*args)
|
326
|
+
ok, verbose = info_thread_preamble(args[0])
|
327
|
+
return unless ok
|
328
|
+
threads = Byebug.contexts.sort_by{|c| c.thnum}.each do |c|
|
329
|
+
display_context(c, !verbose)
|
330
|
+
if verbose and not c.ignored?
|
331
|
+
(0...c.stack_size).each do |idx|
|
332
|
+
print "\t"
|
333
|
+
print_frame(idx, false, c)
|
334
|
+
end
|
335
|
+
end
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
339
|
+
def info_thread(*args)
|
340
|
+
unless args[0]
|
341
|
+
info_threads(args[0])
|
342
|
+
return
|
343
|
+
end
|
344
|
+
ok, verbose = info_thread_preamble(args[1])
|
345
|
+
return unless ok
|
346
|
+
c = parse_thread_num("info thread" , args[0])
|
347
|
+
return unless c
|
348
|
+
display_context(c, !verbose)
|
349
|
+
if verbose and not c.ignored?
|
350
|
+
(0...c.stack_size).each do |idx|
|
351
|
+
print "\t"
|
352
|
+
print_frame(idx, false, c)
|
353
|
+
end
|
354
|
+
end
|
355
|
+
end
|
354
356
|
|
355
357
|
def info_global_variables(*args)
|
356
358
|
unless @state.context
|