stomper 1.0.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (152) hide show
  1. data/.gitignore +5 -0
  2. data/{spec/spec.opts → .rspec} +0 -2
  3. data/Gemfile +4 -0
  4. data/LICENSE +201 -201
  5. data/README.md +130 -0
  6. data/Rakefile +5 -0
  7. data/examples/basic.rb +38 -0
  8. data/examples/events.rb +54 -0
  9. data/features/acking_messages.feature +147 -0
  10. data/features/disconnecting.feature +12 -0
  11. data/features/establish_connection.feature +44 -0
  12. data/features/protocol_version_negotiation.feature +61 -0
  13. data/features/receipts.feature +72 -0
  14. data/features/scopes.feature +32 -0
  15. data/features/secure_connections.feature +38 -0
  16. data/features/send_and_message.feature +28 -0
  17. data/features/steps/acking_messages_steps.rb +39 -0
  18. data/features/steps/disconnecting_steps.rb +8 -0
  19. data/features/steps/establish_connection_steps.rb +74 -0
  20. data/features/steps/frame_transmission_steps.rb +35 -0
  21. data/features/steps/protocol_version_negotiation_steps.rb +15 -0
  22. data/features/steps/receipts_steps.rb +79 -0
  23. data/features/steps/scopes_steps.rb +52 -0
  24. data/features/steps/secure_connections_steps.rb +41 -0
  25. data/features/steps/send_and_message_steps.rb +35 -0
  26. data/features/steps/subscribing_steps.rb +36 -0
  27. data/features/steps/threaded_receiver_steps.rb +8 -0
  28. data/features/steps/transactions_steps.rb +0 -0
  29. data/features/subscribing.feature +151 -0
  30. data/features/support/env.rb +11 -0
  31. data/features/support/header_helpers.rb +12 -0
  32. data/features/support/ssl/README +6 -0
  33. data/features/support/ssl/broker_cert.csr +17 -0
  34. data/features/support/ssl/broker_cert.pem +72 -0
  35. data/features/support/ssl/broker_key.pem +27 -0
  36. data/features/support/ssl/client_cert.csr +17 -0
  37. data/features/support/ssl/client_cert.pem +72 -0
  38. data/features/support/ssl/client_key.pem +27 -0
  39. data/features/support/ssl/demoCA/cacert.pem +17 -0
  40. data/features/support/ssl/demoCA/index.txt +2 -0
  41. data/features/support/ssl/demoCA/index.txt.attr +1 -0
  42. data/features/support/ssl/demoCA/index.txt.attr.old +1 -0
  43. data/features/support/ssl/demoCA/index.txt.old +1 -0
  44. data/features/support/ssl/demoCA/newcerts/01.pem +72 -0
  45. data/features/support/ssl/demoCA/newcerts/02.pem +72 -0
  46. data/features/support/ssl/demoCA/private/cakey.pem +17 -0
  47. data/features/support/ssl/demoCA/serial +1 -0
  48. data/features/support/ssl/demoCA/serial.old +1 -0
  49. data/features/support/test_stomp_server.rb +150 -0
  50. data/features/threaded_receiver.feature +11 -0
  51. data/features/transactions.feature +66 -0
  52. data/lib/stomper.rb +30 -20
  53. data/lib/stomper/connection.rb +442 -102
  54. data/lib/stomper/errors.rb +59 -0
  55. data/lib/stomper/extensions.rb +10 -0
  56. data/lib/stomper/extensions/common.rb +258 -0
  57. data/lib/stomper/extensions/events.rb +213 -0
  58. data/lib/stomper/extensions/heartbeat.rb +101 -0
  59. data/lib/stomper/extensions/scoping.rb +56 -0
  60. data/lib/stomper/frame.rb +54 -0
  61. data/lib/stomper/frame_serializer.rb +217 -0
  62. data/lib/stomper/headers.rb +15 -0
  63. data/lib/stomper/receipt_manager.rb +36 -0
  64. data/lib/stomper/receivers.rb +7 -0
  65. data/lib/stomper/receivers/threaded.rb +71 -0
  66. data/lib/stomper/scopes.rb +9 -0
  67. data/lib/stomper/scopes/header_scope.rb +49 -0
  68. data/lib/stomper/scopes/receipt_scope.rb +44 -0
  69. data/lib/stomper/scopes/transaction_scope.rb +109 -0
  70. data/lib/stomper/sockets.rb +66 -28
  71. data/lib/stomper/subscription_manager.rb +79 -0
  72. data/lib/stomper/support.rb +68 -0
  73. data/lib/stomper/support/1.8/frame_serializer.rb +53 -0
  74. data/lib/stomper/support/1.8/headers.rb +183 -0
  75. data/lib/stomper/support/1.9/frame_serializer.rb +64 -0
  76. data/lib/stomper/support/1.9/headers.rb +172 -0
  77. data/lib/stomper/support/ruby.rb +13 -0
  78. data/lib/stomper/uris.rb +49 -0
  79. data/lib/stomper/version.rb +7 -0
  80. data/spec/spec_helper.rb +13 -9
  81. data/spec/stomper/connection_spec.rb +712 -0
  82. data/spec/stomper/extensions/common_spec.rb +187 -0
  83. data/spec/stomper/extensions/events_spec.rb +78 -0
  84. data/spec/stomper/extensions/heartbeat_spec.rb +103 -0
  85. data/spec/stomper/extensions/scoping_spec.rb +21 -0
  86. data/spec/stomper/frame_serializer_1.8_spec.rb +318 -0
  87. data/spec/stomper/frame_serializer_spec.rb +316 -0
  88. data/spec/stomper/frame_spec.rb +36 -0
  89. data/spec/stomper/headers_spec.rb +224 -0
  90. data/spec/stomper/receipt_manager_spec.rb +91 -0
  91. data/spec/stomper/receivers/threaded_spec.rb +116 -0
  92. data/spec/stomper/scopes/header_scope_spec.rb +42 -0
  93. data/spec/stomper/scopes/receipt_scope_spec.rb +51 -0
  94. data/spec/stomper/scopes/transaction_scope_spec.rb +183 -0
  95. data/spec/stomper/sockets_spec.rb +113 -0
  96. data/spec/stomper/subscription_manager_spec.rb +107 -0
  97. data/spec/stomper/support_spec.rb +69 -0
  98. data/spec/stomper/uris_spec.rb +54 -0
  99. data/spec/stomper_spec.rb +9 -0
  100. data/spec/support/custom_argument_matchers.rb +57 -0
  101. data/spec/support/existential_frame_matchers.rb +19 -0
  102. data/spec/support/frame_header_matchers.rb +10 -0
  103. data/stomper.gemspec +30 -0
  104. metadata +272 -97
  105. data/AUTHORS +0 -21
  106. data/CHANGELOG +0 -20
  107. data/README.rdoc +0 -120
  108. data/lib/stomper/client.rb +0 -34
  109. data/lib/stomper/frame_reader.rb +0 -73
  110. data/lib/stomper/frame_writer.rb +0 -21
  111. data/lib/stomper/frames.rb +0 -39
  112. data/lib/stomper/frames/abort.rb +0 -10
  113. data/lib/stomper/frames/ack.rb +0 -25
  114. data/lib/stomper/frames/begin.rb +0 -11
  115. data/lib/stomper/frames/client_frame.rb +0 -89
  116. data/lib/stomper/frames/commit.rb +0 -10
  117. data/lib/stomper/frames/connect.rb +0 -10
  118. data/lib/stomper/frames/connected.rb +0 -30
  119. data/lib/stomper/frames/disconnect.rb +0 -10
  120. data/lib/stomper/frames/error.rb +0 -21
  121. data/lib/stomper/frames/message.rb +0 -48
  122. data/lib/stomper/frames/receipt.rb +0 -19
  123. data/lib/stomper/frames/send.rb +0 -10
  124. data/lib/stomper/frames/server_frame.rb +0 -38
  125. data/lib/stomper/frames/subscribe.rb +0 -42
  126. data/lib/stomper/frames/unsubscribe.rb +0 -19
  127. data/lib/stomper/open_uri_interface.rb +0 -41
  128. data/lib/stomper/receipt_handlers.rb +0 -23
  129. data/lib/stomper/receiptor.rb +0 -38
  130. data/lib/stomper/subscriber.rb +0 -76
  131. data/lib/stomper/subscription.rb +0 -128
  132. data/lib/stomper/subscriptions.rb +0 -95
  133. data/lib/stomper/threaded_receiver.rb +0 -59
  134. data/lib/stomper/transaction.rb +0 -185
  135. data/lib/stomper/transactor.rb +0 -50
  136. data/lib/stomper/uri.rb +0 -55
  137. data/spec/client_spec.rb +0 -29
  138. data/spec/connection_spec.rb +0 -22
  139. data/spec/frame_reader_spec.rb +0 -37
  140. data/spec/frame_writer_spec.rb +0 -27
  141. data/spec/frames/client_frame_spec.rb +0 -66
  142. data/spec/frames/indirect_frame_spec.rb +0 -45
  143. data/spec/frames/server_frame_spec.rb +0 -85
  144. data/spec/open_uri_interface_spec.rb +0 -132
  145. data/spec/receiptor_spec.rb +0 -35
  146. data/spec/shared_connection_examples.rb +0 -79
  147. data/spec/subscriber_spec.rb +0 -77
  148. data/spec/subscription_spec.rb +0 -157
  149. data/spec/subscriptions_spec.rb +0 -145
  150. data/spec/threaded_receiver_spec.rb +0 -33
  151. data/spec/transaction_spec.rb +0 -139
  152. data/spec/transactor_spec.rb +0 -46
data/CHANGELOG DELETED
@@ -1,20 +0,0 @@
1
- == 1.0 2010-09-24
2
-
3
- * Major additions to api including open-uri style interface.
4
-
5
-
6
- == 0.4 2010-04-23
7
-
8
- * Incremented minor version, beginning expansion.
9
- * Need to make a list of changes I want to make.
10
-
11
-
12
- == 0.3 2010-03-04
13
-
14
- * Added sleep to receive loop to prevent it from running "too tightly", not ideal.
15
- * Bit of cleanup in response to reek report.
16
-
17
-
18
- == 0.2 2009-11-20
19
-
20
- * Officially moved to "stomper" library.
data/README.rdoc DELETED
@@ -1,120 +0,0 @@
1
- =README
2
-
3
- Stomper is a library for connecting to and interacting with a message broker
4
- service that supports the Stomp 1.0 Protocol
5
-
6
- @see http://stomp.github.com/stomp-specification-1-0.html Stomp 1.0 Specification
7
-
8
-
9
- == OpenURI Example Usage
10
-
11
- # A contrived example: Send two messages, receive them back
12
- open("stomp://localhost/queue/testing") do |s|
13
- s.puts "Hello World"
14
- s.write "You may disagree, but I find this useful!"
15
- messages = s.first(2) # => [ Message("Hello World"), Message("You may disagree...") ]
16
- end
17
-
18
- # Another example: connect, send a message to a destination and disconnect
19
- open("stomp://localhost/topic/whatever") do |s|
20
- s.put "PING!"
21
- end
22
-
23
- # Another example: connect, subscribe and process indefinitely
24
- open("stomp://localhost/queue/worker") do |s|
25
- s.each do |m|
26
- logger.info "Received a message: #{m.body}"
27
- # Do important work based on message
28
- end
29
- end
30
-
31
- # Final example: connect, get a single message, and disconnect
32
- open("stomp+ssl://localhost/queue/odd_jobs") do |s|
33
- # you can use get, gets, read or first, they're all the same at
34
- # this time and for the foreseeable future.
35
- incoming_message = s.get
36
- # Do some work on incoming_message
37
- end
38
-
39
- This interface has been a goal of mine for this library for some time now. I
40
- understand the value in a more typical socket object approach, and to that end
41
- the client interface still exists (albeit there's been quite a lot of refractoring.)
42
- However,
43
-
44
- stomp = Stomper::Connection.new("stomp://localhost/")
45
- stomp.subscribe("/queue/blather") do |m|
46
- # ...
47
- end
48
- stomp.send("/topic/other", "Hello")
49
-
50
- just doesn't feel very Ruby-esque to me. While the two methods for interacting with
51
- Stomper connections appear very different, +s+ in the OpenURI examples above
52
- really is a Stomper::Connection, but with some added extensions for handling
53
- +put+, +get+, +each+, and so forth. One note: +read+, +get+ and +gets+ are
54
- all aliases for +first+. Similarly, +puts+ is an alias for +put+. However,
55
- +write+ is slightly different. The message broker I most often use the
56
- STOMP protocol with is Apache ActiveMQ which, at the time of this writing, uses
57
- the absence or presence of a `content-length` header to discriminate between a
58
- JMS TextMessage and a BytesMessage. The +put+ and +puts+ methods will force
59
- Stomper to omit that header, while +write+ will force its presence.
60
-
61
- == Example Usage
62
-
63
- client = Stomper::Client.new("stomp://my_username:s3cr3tz@localhost:61613")
64
- # Clients must be explicitly started to automatically receive incoming
65
- # messages.
66
- client.start
67
-
68
- client.subscribe("/queue/hello") do |msg|
69
- puts msg.body
70
- end
71
-
72
- # Send a simple message
73
- client.send("/queue/hello", "hello world!")
74
-
75
- # Send a message within a transaction. This usage is new to stomper
76
- # however, one can manually manage transactions as well.
77
- client.transaction do |t|
78
- t.send("/queue/hello", "a transactioned message")
79
- end
80
-
81
- # If the block provided to #transaction accepts a single parameter,
82
- # the client yields the Transaction object to the block, otherwise
83
- # the block is instance_eval'd within the Transaction object.
84
- client.transaction do
85
- send("/queue/hello", "a message you will never receive")
86
- # Nested transactions, failures percolate up to parent transactions.
87
- transaction do
88
- send("/queue/hello", "because I am about to fail!")
89
- raise "by forcing an error in a nested transaction"
90
- end
91
- end
92
-
93
- # Later ...
94
- client.stop
95
- client.close
96
-
97
- == To-Do
98
- * Provide other methods for handling the receiver.
99
- * Provide the `pipe` method on Stomper::Client
100
- * Allow SSL verification if requested (option :verify_ssl?)
101
- * Re-evaluate how to handle a 'reliable' connection.
102
-
103
- == License
104
-
105
- Stomper is released under the Apache License 2.0
106
-
107
- == Pointless Backstory
108
-
109
- Stomper began its life as a mere fork of the stomp gem.
110
- However, as changes were made and desires grew, the fork began breaking
111
- API compatibility with the original gem, and thus Stomper was conceived.
112
-
113
- @see http://github.com/js/stomp Stomp
114
-
115
- == Other Stuff
116
-
117
- Primary Author:: Ian D. Eccles
118
- Source Repository:: http://github.com/iande/stomper
119
- Current Version:: 1.0.0
120
- Last Updated:: 2010-09-25
@@ -1,34 +0,0 @@
1
- module Stomper
2
- module Client
3
- # Sends a string message specified by +body+ to the appropriate stomp
4
- # broker destination given by +destination+. Additional headers for the
5
- # message may be specified by the +headers+ hash where the key is the header
6
- # property and the value is the corresponding property's value. The
7
- # keys of +headers+ may be symbols or strings.
8
- #
9
- # Examples:
10
- #
11
- # client.send("/topic/whatever", "hello world")
12
- #
13
- # client.send("/queue/some/destination", "hello world", { :persistent => true })
14
- #
15
- def send(destination, body, headers={})
16
- transmit(Stomper::Frames::Send.new(destination, body, headers))
17
- end
18
-
19
- # Acknowledge to the stomp broker that a given message was received.
20
- # The +id_or_frame+ parameter may be either the message-id header of
21
- # the received message, or an actual instance of Stomper::Frames::Message.
22
- # Additional headers may be specified through the +headers+ hash.
23
- #
24
- # Examples:
25
- #
26
- # client.ack(received_message)
27
- #
28
- # client.ack("message-0001-00451-003031")
29
- #
30
- def ack(id_or_frame, headers={})
31
- transmit(Stomper::Frames::Ack.ack_for(id_or_frame, headers))
32
- end
33
- end
34
- end
@@ -1,73 +0,0 @@
1
- module Stomper
2
- # Deserializes Stomp Frames from an input stream.
3
- # Any object that responds appropriately to +getc+, +gets+
4
- # and +read+ can be used as the input stream.
5
- module FrameReader
6
- # Receives the next Stomp Frame from the socket stream
7
- def receive_frame
8
- command = read_command
9
- headers = read_headers
10
- body = read_body(headers[:'content-length'])
11
- Stomper::Frames::ServerFrame.build(command, headers, body)
12
- end
13
-
14
- private
15
- def read_command
16
- command = ''
17
- while(command.size == 0)
18
- command = gets(Stomper::Frames::LINE_DELIMITER).chomp!
19
- end
20
- command
21
- end
22
-
23
- def read_headers
24
- headers = {}
25
- loop do
26
- line = gets(Stomper::Frames::LINE_DELIMITER).chomp!
27
- break if line.size == 0
28
- if (delim = line.index(':'))
29
- headers[ line[0..(delim-1)].to_sym ] = line[(delim+1)..-1]
30
- end
31
- end
32
- headers
33
- end
34
-
35
- def read_body(body_len)
36
- body_len &&= body_len.strip.to_i
37
- if body_len
38
- read_fixed_body(body_len)
39
- else
40
- read_null_terminated_body
41
- end
42
- end
43
-
44
- def read_null_terminated_body
45
- body = ''
46
- while next_byte = get_body_byte
47
- body << next_byte.chr
48
- end
49
- body
50
- end
51
-
52
- def read_fixed_body(num_bytes)
53
- body = read(num_bytes)
54
- raise MalformedFrameError if get_body_byte
55
- body
56
- end
57
-
58
- def get_body_byte
59
- next_byte = get_ord
60
- (next_byte == Stomper::Frames::TERMINATOR) ? nil : next_byte
61
- end
62
-
63
- if String.method_defined?(:ord)
64
- def get_ord
65
- getc.ord
66
- end
67
- else
68
- def get_ord
69
- getc
70
- end
71
- end
72
- end
73
- end
@@ -1,21 +0,0 @@
1
- module Stomper
2
- # Serializes Stomp Frames to an output stream.
3
- # Any object that responds appropriately to +write+
4
- # can be used as the input stream.
5
- module FrameWriter
6
- # Writes a Stomp Frame to the underlying output stream.
7
- def transmit_frame(frame)
8
- write([ frame.command, Stomper::Frames::LINE_DELIMITER,
9
- serialize_headers(frame.headers), Stomper::Frames::LINE_DELIMITER,
10
- frame.body, Stomper::Frames::TERMINATOR.chr].join)
11
- end
12
-
13
- private
14
- def serialize_headers(headers)
15
- headers.inject("") do |acc, (key, val)|
16
- acc << "#{key}#{Stomper::Frames::HEADER_DELIMITER}#{val}#{Stomper::Frames::LINE_DELIMITER}"
17
- acc
18
- end
19
- end
20
- end
21
- end
@@ -1,39 +0,0 @@
1
- module Stomper
2
- # This module holds all known encapsulations of
3
- # frames that are part of the Stomp Protocol specification.
4
- module Frames
5
- HEADER_DELIMITER = ':'
6
- TERMINATOR = 0
7
- LINE_DELIMITER = "\n"
8
-
9
- class IndirectFrame #:nodoc:
10
- attr_reader :headers, :body
11
-
12
- def initialize(headers={}, body=nil, command=nil)
13
- @command = command && command.to_s.upcase
14
- @headers = headers.dup
15
- @body = body
16
- end
17
-
18
- def command
19
- @command ||= self.class.name.split("::").last.upcase
20
- end
21
- end
22
- end
23
- end
24
-
25
- require 'stomper/frames/client_frame'
26
- require 'stomper/frames/server_frame'
27
- require 'stomper/frames/abort'
28
- require 'stomper/frames/ack'
29
- require 'stomper/frames/begin'
30
- require 'stomper/frames/commit'
31
- require 'stomper/frames/connect'
32
- require 'stomper/frames/connected'
33
- require 'stomper/frames/disconnect'
34
- require 'stomper/frames/error'
35
- require 'stomper/frames/message'
36
- require 'stomper/frames/receipt'
37
- require 'stomper/frames/send'
38
- require 'stomper/frames/subscribe'
39
- require 'stomper/frames/unsubscribe'
@@ -1,10 +0,0 @@
1
- module Stomper
2
- module Frames
3
- # Encapsulates an "ABORT" frame from the Stomp Protocol.
4
- class Abort < Stomper::Frames::ClientFrame
5
- def initialize(transaction_id, headers={})
6
- super(headers.merge(:transaction => transaction_id))
7
- end
8
- end
9
- end
10
- end
@@ -1,25 +0,0 @@
1
- module Stomper
2
- module Frames
3
- # Encapsulates an "ACK" frame from the Stomp Protocol.
4
- class Ack < Stomper::Frames::ClientFrame
5
- def initialize(message_id, headers={})
6
- super(headers.merge({ :'message-id' => message_id }))
7
- end
8
-
9
- # Creates a new Ack instance that corresponds to an acknowledgement
10
- # of the supplied +message+, with any additional +headers+. The
11
- # +message+ parameter may be an instance of Stomper::Frames::Message, or
12
- # a message id. If +message+ is an instance of Stomper::Frames::Message
13
- # and was exchanged as part of a transaction, the transaction header from
14
- # +message+ will be injected into the newly created Ack object's headers.
15
- def self.ack_for(message, headers = {})
16
- if message.is_a?(Message)
17
- headers[:transaction] = message.headers[:transaction] if message.headers[:transaction]
18
- new(message.id, headers)
19
- else
20
- new(message.to_s)
21
- end
22
- end
23
- end
24
- end
25
- end
@@ -1,11 +0,0 @@
1
- module Stomper
2
- module Frames
3
- # Encapsulates a "BEGIN" frame from the Stomp Protocol.
4
- class Begin < Stomper::Frames::ClientFrame
5
- def initialize(transaction_id, headers={})
6
- super(headers.merge(:transaction => transaction_id))
7
- @headers[:transaction] = transaction_id
8
- end
9
- end
10
- end
11
- end
@@ -1,89 +0,0 @@
1
- module Stomper
2
- module Frames
3
- # Encapsulates a client side frame for the Stomp Protocol.
4
- class ClientFrame < IndirectFrame
5
-
6
- # Creates a new ClientFrame instance with the specified +command+,
7
- # +headers+ and +body+.
8
- # If +headers+ includes a key of :generate_content_length, the
9
- # associated value will determine if a 'content-length' header is automatically
10
- # generated for this particular frame instance. This key can be
11
- # specified in the +headers+ parameter of any of the subclasses of ClientFrame,
12
- # and it will be interpretted in the same fashion.
13
- def initialize(headers={}, body=nil, command = nil)
14
- @generate_content_length = headers.delete(:generate_content_length)
15
- super(headers, body, command)
16
- end
17
-
18
- # If +bool+ is false or nil, this frame instance will not attempt to
19
- # automatically generate a content-length header. This is useful when
20
- # dealing with ActiveMQ as a stomp message broker, which will treat incoming
21
- # messages lacking a content-length header as +TextMessage+s and
22
- # +BytesMessage+s if the header is present. For more information see:
23
- # {Apache ActiveMQ - Stomp}[http://activemq.apache.org/stomp.html]
24
- def generate_content_length=(bool)
25
- @generate_content_length=bool
26
- end
27
-
28
- # If generate_content_length= has been called on this instance, then the
29
- # value supplied there is returned here. Otherwise, we defer to the
30
- # class method of the same name.
31
- def generate_content_length?
32
- @generate_content_length.nil? ? self.class.generate_content_length? : @generate_content_length
33
- end
34
-
35
-
36
- # Returns the headers for this frame, including a +content-length+ header
37
- # set to the size of the current body, if +generate_content_length?+ is
38
- # not false.
39
- def headers
40
- if generate_content_length? && @body && !@body.empty?
41
- @headers[:'content-length'] ||= body_size
42
- end
43
- @headers
44
- end
45
-
46
- class << self
47
- # Sets a class level setting for determining if a content-length header
48
- # should automatically be generated.
49
- def generate_content_length=(bool)
50
- @generate_content_length = bool
51
- end
52
-
53
- # Returns the value passed to the class level generate_content_length=
54
- # method, or true if no value has been set (thus, defaults to true.)
55
- #
56
- # The precedence for resolving whether or not a content-length header
57
- # is generated by the +headers+ method is:
58
- # check the instance setting,
59
- # if it has not been set, defer to the class setting, if it hasn't
60
- # been set, default to true.
61
- def generate_content_length?
62
- if @generate_content_length.nil?
63
- @generate_content_length = true
64
- end
65
- @generate_content_length
66
- end
67
-
68
- def inherited(client_frame) #:nodoc:
69
- declared_frames << { :class => client_frame, :command => client_frame.name.split("::").last.downcase.to_sym }
70
- end
71
-
72
- def declared_frames
73
- @declared_frames ||= []
74
- end
75
- end
76
-
77
- private
78
- if String.method_defined?(:bytesize)
79
- def body_size
80
- @body.bytesize
81
- end
82
- else
83
- def body_size
84
- @body.size
85
- end
86
- end
87
- end
88
- end
89
- end