sass-embedded 1.6.2 → 1.83.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +9 -3
  3. data/exe/sass +13 -0
  4. data/ext/sass/Rakefile +352 -76
  5. data/ext/sass/embedded_sass_pb.rb +61 -0
  6. data/ext/sass/expand-archive.ps1 +1 -0
  7. data/ext/sass/package.json +1 -1
  8. data/lib/sass/calculation_value/calculation_operation.rb +49 -0
  9. data/lib/sass/calculation_value.rb +22 -0
  10. data/lib/sass/canonicalize_context.rb +25 -0
  11. data/lib/sass/compile_result.rb +3 -2
  12. data/lib/sass/compiler/channel.rb +68 -0
  13. data/lib/sass/compiler/connection.rb +89 -0
  14. data/lib/sass/compiler/dispatcher.rb +116 -0
  15. data/lib/sass/{embedded → compiler}/host/function_registry.rb +31 -34
  16. data/lib/sass/compiler/host/importer_registry.rb +141 -0
  17. data/lib/sass/compiler/host/logger_registry.rb +80 -0
  18. data/lib/sass/compiler/host/protofier.rb +360 -0
  19. data/lib/sass/compiler/host/structifier.rb +37 -0
  20. data/lib/sass/compiler/host.rb +226 -0
  21. data/lib/sass/{embedded → compiler}/varint.rb +9 -5
  22. data/lib/sass/compiler.rb +212 -0
  23. data/lib/sass/elf.rb +222 -0
  24. data/lib/sass/embedded/version.rb +2 -2
  25. data/lib/sass/embedded.rb +76 -204
  26. data/lib/sass/embedded_protocol.rb +10 -0
  27. data/lib/sass/exception.rb +74 -0
  28. data/lib/sass/fork_tracker.rb +51 -0
  29. data/lib/sass/logger/silent.rb +5 -3
  30. data/lib/sass/logger/source_location.rb +6 -5
  31. data/lib/sass/logger/source_span.rb +8 -7
  32. data/lib/sass/node_package_importer.rb +17 -0
  33. data/lib/sass/serializer.rb +30 -0
  34. data/lib/sass/value/argument_list.rb +13 -6
  35. data/lib/sass/value/boolean.rb +1 -1
  36. data/lib/sass/value/calculation.rb +90 -0
  37. data/lib/sass/value/color/channel.rb +79 -0
  38. data/lib/sass/value/color/conversions.rb +473 -0
  39. data/lib/sass/value/color/gamut_map_method/clip.rb +45 -0
  40. data/lib/sass/value/color/gamut_map_method/local_minde.rb +94 -0
  41. data/lib/sass/value/color/gamut_map_method.rb +45 -0
  42. data/lib/sass/value/color/interpolation_method.rb +51 -0
  43. data/lib/sass/value/color/space/a98_rgb.rb +57 -0
  44. data/lib/sass/value/color/space/display_p3.rb +57 -0
  45. data/lib/sass/value/color/space/hsl.rb +65 -0
  46. data/lib/sass/value/color/space/hwb.rb +70 -0
  47. data/lib/sass/value/color/space/lab.rb +77 -0
  48. data/lib/sass/value/color/space/lch.rb +53 -0
  49. data/lib/sass/value/color/space/lms.rb +129 -0
  50. data/lib/sass/value/color/space/oklab.rb +66 -0
  51. data/lib/sass/value/color/space/oklch.rb +54 -0
  52. data/lib/sass/value/color/space/prophoto_rgb.rb +59 -0
  53. data/lib/sass/value/color/space/rec2020.rb +69 -0
  54. data/lib/sass/value/color/space/rgb.rb +52 -0
  55. data/lib/sass/value/color/space/srgb.rb +140 -0
  56. data/lib/sass/value/color/space/srgb_linear.rb +72 -0
  57. data/lib/sass/value/color/space/utils.rb +86 -0
  58. data/lib/sass/value/color/space/xyz_d50.rb +100 -0
  59. data/lib/sass/value/color/space/xyz_d65.rb +57 -0
  60. data/lib/sass/value/color/space.rb +198 -0
  61. data/lib/sass/value/color.rb +538 -163
  62. data/lib/sass/value/function.rb +11 -16
  63. data/lib/sass/value/fuzzy_math.rb +24 -21
  64. data/lib/sass/value/list.rb +7 -7
  65. data/lib/sass/value/map.rb +6 -6
  66. data/lib/sass/value/mixin.rb +34 -0
  67. data/lib/sass/value/null.rb +1 -1
  68. data/lib/sass/value/number/unit.rb +7 -6
  69. data/lib/sass/value/number.rb +34 -26
  70. data/lib/sass/value/string.rb +9 -3
  71. data/lib/sass/value.rb +20 -16
  72. metadata +67 -103
  73. data/ext/sass/unzip.vbs +0 -13
  74. data/lib/sass/compile_error.rb +0 -28
  75. data/lib/sass/embedded/async.rb +0 -65
  76. data/lib/sass/embedded/channel.rb +0 -61
  77. data/lib/sass/embedded/compiler.rb +0 -60
  78. data/lib/sass/embedded/dispatcher.rb +0 -90
  79. data/lib/sass/embedded/host/importer_registry.rb +0 -107
  80. data/lib/sass/embedded/host/logger_registry.rb +0 -50
  81. data/lib/sass/embedded/host/value_protofier.rb +0 -241
  82. data/lib/sass/embedded/host.rb +0 -139
  83. data/lib/sass/embedded/protofier.rb +0 -78
  84. data/lib/sass/embedded/structifier.rb +0 -36
  85. data/lib/sass/script_error.rb +0 -6
@@ -0,0 +1,226 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'host/function_registry'
4
+ require_relative 'host/importer_registry'
5
+ require_relative 'host/logger_registry'
6
+ require_relative 'host/protofier'
7
+ require_relative 'host/structifier'
8
+
9
+ module Sass
10
+ class Compiler
11
+ # The {Host} class.
12
+ #
13
+ # It communicates with {Dispatcher} and handles the host logic.
14
+ class Host
15
+ def initialize(channel)
16
+ @channel = channel
17
+ end
18
+
19
+ def compile_request(path:,
20
+ source:,
21
+ importer:,
22
+ load_paths:,
23
+ syntax:,
24
+ url:,
25
+ charset:,
26
+ source_map:,
27
+ source_map_include_sources:,
28
+ style:,
29
+ functions:,
30
+ importers:,
31
+ alert_ascii:,
32
+ alert_color:,
33
+ fatal_deprecations:,
34
+ future_deprecations:,
35
+ logger:,
36
+ quiet_deps:,
37
+ silence_deprecations:,
38
+ verbose:)
39
+ alert_color = Exception.to_tty? if alert_color.nil?
40
+
41
+ @function_registry = FunctionRegistry.new(functions, alert_color:)
42
+ @importer_registry = ImporterRegistry.new(importers, load_paths, alert_color:)
43
+ @logger_registry = LoggerRegistry.new(logger)
44
+
45
+ compile_request = EmbeddedProtocol::InboundMessage::CompileRequest.new(
46
+ string: unless source.nil?
47
+ EmbeddedProtocol::InboundMessage::CompileRequest::StringInput.new(
48
+ source: source.to_str,
49
+ url: url&.to_s,
50
+ syntax: @importer_registry.syntax_to_proto(syntax),
51
+ importer: (@importer_registry.register(importer) unless importer.nil?)
52
+ )
53
+ end,
54
+ path: (File.absolute_path(path) unless path.nil?),
55
+ style: case style&.to_sym
56
+ when :expanded
57
+ EmbeddedProtocol::OutputStyle::EXPANDED
58
+ when :compressed
59
+ EmbeddedProtocol::OutputStyle::COMPRESSED
60
+ else
61
+ raise ArgumentError, 'style must be one of :expanded, :compressed'
62
+ end,
63
+ charset:,
64
+ source_map:,
65
+ source_map_include_sources:,
66
+ importers: @importer_registry.importers,
67
+ global_functions: @function_registry.global_functions,
68
+ alert_ascii:,
69
+ alert_color:,
70
+ fatal_deprecation: fatal_deprecations.map(&:to_s),
71
+ future_deprecation: future_deprecations.map(&:to_s),
72
+ quiet_deps:,
73
+ silent: logger == Logger.silent,
74
+ silence_deprecation: silence_deprecations.map(&:to_s),
75
+ verbose:
76
+ )
77
+
78
+ compile_response = await do
79
+ send_message(compile_request:)
80
+ end
81
+
82
+ oneof = compile_response.result
83
+ result = compile_response.public_send(oneof)
84
+ case oneof
85
+ when :failure
86
+ raise CompileError.new(
87
+ result.message,
88
+ result.formatted == '' ? nil : result.formatted,
89
+ result.stack_trace == '' ? nil : result.stack_trace,
90
+ result.span.nil? ? nil : Logger::SourceSpan.new(result.span),
91
+ compile_response.loaded_urls.to_a
92
+ )
93
+ when :success
94
+ CompileResult.new(
95
+ result.css,
96
+ result.source_map == '' ? nil : result.source_map,
97
+ compile_response.loaded_urls.to_a
98
+ )
99
+ else
100
+ raise ArgumentError, "Unknown CompileResponse.result #{result}"
101
+ end
102
+ end
103
+
104
+ def version_request
105
+ version_response = await0 do
106
+ send_message0(version_request: EmbeddedProtocol::InboundMessage::VersionRequest.new(
107
+ id:
108
+ ))
109
+ end
110
+
111
+ info = [
112
+ version_response.implementation_name,
113
+ version_response.implementation_version,
114
+ '(Sass Compiler)'
115
+ ]
116
+
117
+ case version_response.implementation_name
118
+ when 'dart-sass'
119
+ info << (CLI::COMMAND.first == 'node' ? '[JavaScript]' : '[Dart]')
120
+ end
121
+
122
+ info
123
+ end
124
+
125
+ def compile_response(message)
126
+ @result = message
127
+ @queue.close
128
+ end
129
+
130
+ def version_response(message)
131
+ @result = message
132
+ @queue.close
133
+ end
134
+
135
+ def error(message)
136
+ case message
137
+ when EmbeddedProtocol::ProtocolError
138
+ raise Errno::EPROTO, message.message
139
+ else
140
+ @error ||= message
141
+ @queue.close
142
+ end
143
+ end
144
+
145
+ def log_event(message)
146
+ @logger_registry.log(message)
147
+ end
148
+
149
+ def canonicalize_request(message)
150
+ send_message(canonicalize_response: @importer_registry.canonicalize(message))
151
+ end
152
+
153
+ def import_request(message)
154
+ send_message(import_response: @importer_registry.import(message))
155
+ end
156
+
157
+ def file_import_request(message)
158
+ send_message(file_import_response: @importer_registry.file_import(message))
159
+ end
160
+
161
+ def function_call_request(message)
162
+ send_message(function_call_response: @function_registry.function_call(message))
163
+ end
164
+
165
+ def receive_proto(proto)
166
+ @queue.push(proto)
167
+ end
168
+
169
+ private
170
+
171
+ def await0
172
+ listen do
173
+ yield
174
+
175
+ @queue.pop
176
+ end
177
+ end
178
+
179
+ def await
180
+ listen do
181
+ yield
182
+
183
+ while (proto = @queue.pop)
184
+ outbound_message = EmbeddedProtocol::OutboundMessage.decode(proto)
185
+ oneof = outbound_message.message
186
+ message = outbound_message.public_send(oneof)
187
+ public_send(oneof, message)
188
+ end
189
+ rescue Exception => e # rubocop:disable Lint/RescueException
190
+ @stream.error(e)
191
+ raise
192
+ end
193
+ end
194
+
195
+ def listen
196
+ @queue = Queue.new
197
+ @stream = @channel.stream(self)
198
+
199
+ yield
200
+
201
+ raise @error if @error
202
+
203
+ @result
204
+ ensure
205
+ @stream&.close
206
+ @queue&.close
207
+ end
208
+
209
+ def id
210
+ @stream.id
211
+ end
212
+
213
+ def send_message0(...)
214
+ inbound_message = EmbeddedProtocol::InboundMessage.new(...)
215
+ @stream.send_proto(0, EmbeddedProtocol::InboundMessage.encode(inbound_message))
216
+ end
217
+
218
+ def send_message(...)
219
+ inbound_message = EmbeddedProtocol::InboundMessage.new(...)
220
+ @stream.send_proto(id, EmbeddedProtocol::InboundMessage.encode(inbound_message))
221
+ end
222
+ end
223
+
224
+ private_constant :Host
225
+ end
226
+ end
@@ -1,13 +1,19 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Sass
4
- class Embedded
4
+ class Compiler
5
5
  # The {Varint} module.
6
6
  #
7
7
  # It reads and writes varints.
8
8
  module Varint
9
9
  module_function
10
10
 
11
+ def length(value)
12
+ return 1 if value < 128
13
+
14
+ (value.bit_length + 6) / 7
15
+ end
16
+
11
17
  def read(readable)
12
18
  value = bits = 0
13
19
  loop do
@@ -20,13 +26,11 @@ module Sass
20
26
  end
21
27
 
22
28
  def write(writeable, value)
23
- bytes = []
24
29
  until value < 0x80
25
- bytes << (0x80 | (value & 0x7f))
30
+ writeable << ((value & 0x7f) | 0x80)
26
31
  value >>= 7
27
32
  end
28
- bytes << value
29
- writeable.write bytes.pack('C*')
33
+ writeable << value
30
34
  end
31
35
  end
32
36
 
@@ -0,0 +1,212 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'canonicalize_context'
4
+ require_relative 'compile_result'
5
+ require_relative 'compiler/channel'
6
+ require_relative 'compiler/connection'
7
+ require_relative 'compiler/dispatcher'
8
+ require_relative 'compiler/host'
9
+ require_relative 'compiler/varint'
10
+ require_relative 'embedded/version'
11
+ require_relative 'embedded_protocol'
12
+ require_relative 'exception'
13
+ require_relative 'fork_tracker'
14
+ require_relative 'logger/silent'
15
+ require_relative 'logger/source_location'
16
+ require_relative 'logger/source_span'
17
+ require_relative 'node_package_importer'
18
+ require_relative 'serializer'
19
+ require_relative 'value'
20
+
21
+ module Sass
22
+ # A synchronous {Compiler}.
23
+ # Each compiler instance exposes the {#compile} and {#compile_string} methods within the lifespan of the compiler.
24
+ #
25
+ # @example
26
+ # sass = Sass::Compiler.new
27
+ # result = sass.compile_string('h1 { font-size: 40px; }')
28
+ # result = sass.compile('style.scss')
29
+ # sass.close
30
+ # @see https://sass-lang.com/documentation/js-api/classes/compiler/
31
+ class Compiler
32
+ def initialize
33
+ @channel = Channel.new(Dispatcher)
34
+ end
35
+
36
+ # Compiles the Sass file at +path+ to CSS.
37
+ # @param path [String]
38
+ # @param load_paths [Array<String>] Paths in which to look for stylesheets loaded by rules like
39
+ # {@use}[https://sass-lang.com/documentation/at-rules/use/] and {@import}[https://sass-lang.com/documentation/at-rules/import/].
40
+ # @param charset [Boolean] By default, if the CSS document contains non-ASCII characters, Sass adds a +@charset+
41
+ # declaration (in expanded output mode) or a byte-order mark (in compressed mode) to indicate its encoding to
42
+ # browsers or other consumers. If +charset+ is +false+, these annotations are omitted.
43
+ # @param source_map [Boolean] Whether or not Sass should generate a source map.
44
+ # @param source_map_include_sources [Boolean] Whether Sass should include the sources in the generated source map.
45
+ # @param style [Symbol] The OutputStyle of the compiled CSS.
46
+ # @param functions [Hash<String, Proc>] Additional built-in Sass functions that are available in all stylesheets.
47
+ # @param importers [Array<Object>] Custom importers that control how Sass resolves loads from rules like
48
+ # {@use}[https://sass-lang.com/documentation/at-rules/use/] and {@import}[https://sass-lang.com/documentation/at-rules/import/].
49
+ # @param alert_ascii [Boolean] If this is +true+, the compiler will exclusively use ASCII characters in its error
50
+ # and warning messages. Otherwise, it may use non-ASCII Unicode characters as well.
51
+ # @param alert_color [Boolean] If this is +true+, the compiler will use ANSI color escape codes in its error and
52
+ # warning messages. If it's +false+, it won't use these. If it's +nil+, the compiler will determine whether or
53
+ # not to use colors depending on whether the user is using an interactive terminal.
54
+ # @param fatal_deprecations [Array<String>] A set of deprecations to treat as fatal.
55
+ # @param future_deprecations [Array<String>] A set of future deprecations to opt into early.
56
+ # @param logger [Object] An object to use to handle warnings and/or debug messages from Sass.
57
+ # @param quiet_deps [Boolean] If this option is set to +true+, Sass won’t print warnings that are caused by
58
+ # dependencies. A “dependency” is defined as any file that’s loaded through +load_paths+ or +importer+.
59
+ # Stylesheets that are imported relative to the entrypoint are not considered dependencies.
60
+ # @param silence_deprecations [Array<String>] A set of active deprecations to ignore.
61
+ # @param verbose [Boolean] By default, Dart Sass will print only five instances of the same deprecation warning per
62
+ # compilation to avoid deluging users in console noise. If you set verbose to +true+, it will instead print every
63
+ # deprecation warning it encounters.
64
+ # @return [CompileResult]
65
+ # @raise [ArgumentError, CompileError, IOError]
66
+ # @see https://sass-lang.com/documentation/js-api/functions/compile/
67
+ def compile(path,
68
+ load_paths: [],
69
+
70
+ charset: true,
71
+ source_map: false,
72
+ source_map_include_sources: false,
73
+ style: :expanded,
74
+
75
+ functions: {},
76
+ importers: [],
77
+
78
+ alert_ascii: false,
79
+ alert_color: nil,
80
+ fatal_deprecations: [],
81
+ future_deprecations: [],
82
+ logger: nil,
83
+ quiet_deps: false,
84
+ silence_deprecations: [],
85
+ verbose: false)
86
+ raise ArgumentError, 'path must be set' if path.nil?
87
+
88
+ Host.new(@channel).compile_request(
89
+ path:,
90
+ source: nil,
91
+ importer: nil,
92
+ load_paths:,
93
+ syntax: nil,
94
+ url: nil,
95
+ charset:,
96
+ source_map:,
97
+ source_map_include_sources:,
98
+ style:,
99
+ functions:,
100
+ importers:,
101
+ alert_color:,
102
+ alert_ascii:,
103
+ fatal_deprecations:,
104
+ future_deprecations:,
105
+ logger:,
106
+ quiet_deps:,
107
+ silence_deprecations:,
108
+ verbose:
109
+ )
110
+ end
111
+
112
+ # Compiles a stylesheet whose contents is +source+ to CSS.
113
+ # @param source [String]
114
+ # @param importer [Object] The importer to use to handle loads that are relative to the entrypoint stylesheet.
115
+ # @param load_paths [Array<String>] Paths in which to look for stylesheets loaded by rules like
116
+ # {@use}[https://sass-lang.com/documentation/at-rules/use/] and {@import}[https://sass-lang.com/documentation/at-rules/import/].
117
+ # @param syntax [Symbol] The Syntax to use to parse the entrypoint stylesheet.
118
+ # @param url [String] The canonical URL of the entrypoint stylesheet. If this is passed along with +importer+, it's
119
+ # used to resolve relative loads in the entrypoint stylesheet.
120
+ # @param charset [Boolean] By default, if the CSS document contains non-ASCII characters, Sass adds a +@charset+
121
+ # declaration (in expanded output mode) or a byte-order mark (in compressed mode) to indicate its encoding to
122
+ # browsers or other consumers. If +charset+ is +false+, these annotations are omitted.
123
+ # @param source_map [Boolean] Whether or not Sass should generate a source map.
124
+ # @param source_map_include_sources [Boolean] Whether Sass should include the sources in the generated source map.
125
+ # @param style [Symbol] The OutputStyle of the compiled CSS.
126
+ # @param functions [Hash<String, Proc>] Additional built-in Sass functions that are available in all stylesheets.
127
+ # @param importers [Array<Object>] Custom importers that control how Sass resolves loads from rules like
128
+ # {@use}[https://sass-lang.com/documentation/at-rules/use/] and {@import}[https://sass-lang.com/documentation/at-rules/import/].
129
+ # @param alert_ascii [Boolean] If this is +true+, the compiler will exclusively use ASCII characters in its error
130
+ # and warning messages. Otherwise, it may use non-ASCII Unicode characters as well.
131
+ # @param alert_color [Boolean] If this is +true+, the compiler will use ANSI color escape codes in its error and
132
+ # warning messages. If it's +false+, it won't use these. If it's +nil+, the compiler will determine whether or
133
+ # not to use colors depending on whether the user is using an interactive terminal.
134
+ # @param fatal_deprecations [Array<String>] A set of deprecations to treat as fatal.
135
+ # @param future_deprecations [Array<String>] A set of future deprecations to opt into early.
136
+ # @param logger [Object] An object to use to handle warnings and/or debug messages from Sass.
137
+ # @param quiet_deps [Boolean] If this option is set to +true+, Sass won’t print warnings that are caused by
138
+ # dependencies. A “dependency” is defined as any file that’s loaded through +load_paths+ or +importer+.
139
+ # Stylesheets that are imported relative to the entrypoint are not considered dependencies.
140
+ # @param silence_deprecations [Array<String>] A set of active deprecations to ignore.
141
+ # @param verbose [Boolean] By default, Dart Sass will print only five instances of the same deprecation warning per
142
+ # compilation to avoid deluging users in console noise. If you set verbose to +true+, it will instead print every
143
+ # deprecation warning it encounters.
144
+ # @return [CompileResult]
145
+ # @raise [ArgumentError, CompileError, IOError]
146
+ # @see https://sass-lang.com/documentation/js-api/functions/compilestring/
147
+ def compile_string(source,
148
+ importer: nil,
149
+ load_paths: [],
150
+ syntax: :scss,
151
+ url: nil,
152
+
153
+ charset: true,
154
+ source_map: false,
155
+ source_map_include_sources: false,
156
+ style: :expanded,
157
+
158
+ functions: {},
159
+ importers: [],
160
+
161
+ alert_ascii: false,
162
+ alert_color: nil,
163
+ fatal_deprecations: [],
164
+ future_deprecations: [],
165
+ logger: nil,
166
+ quiet_deps: false,
167
+ silence_deprecations: [],
168
+ verbose: false)
169
+ raise ArgumentError, 'source must be set' if source.nil?
170
+
171
+ Host.new(@channel).compile_request(
172
+ path: nil,
173
+ source:,
174
+ importer:,
175
+ load_paths:,
176
+ syntax:,
177
+ url:,
178
+ charset:,
179
+ source_map:,
180
+ source_map_include_sources:,
181
+ style:,
182
+ functions:,
183
+ importers:,
184
+ alert_color:,
185
+ alert_ascii:,
186
+ fatal_deprecations:,
187
+ future_deprecations:,
188
+ logger:,
189
+ quiet_deps:,
190
+ silence_deprecations:,
191
+ verbose:
192
+ )
193
+ end
194
+
195
+ # @return [String] Information about the Sass implementation.
196
+ # @see https://sass-lang.com/documentation/js-api/variables/info/
197
+ def info
198
+ @info ||= [
199
+ ['sass-embedded', Embedded::VERSION, '(Embedded Host)', '[Ruby]'].join("\t"),
200
+ Host.new(@channel).version_request.join("\t")
201
+ ].join("\n").freeze
202
+ end
203
+
204
+ def close
205
+ @channel.close
206
+ end
207
+
208
+ def closed?
209
+ @channel.closed?
210
+ end
211
+ end
212
+ end
data/lib/sass/elf.rb ADDED
@@ -0,0 +1,222 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sass
4
+ # The {ELF} class.
5
+ #
6
+ # It parses ELF header to extract interpreter.
7
+ # @see https://github.com/torvalds/linux/blob/HEAD/include/uapi/linux/elf.h
8
+ # @see https://github.com/torvalds/linux/blob/HEAD/kernel/kexec_elf.c
9
+ class ELF
10
+ module PackInfo
11
+ PACK_MAP = {
12
+ Elf32_Ehdr: 'S<2L<5S<6',
13
+ Elf64_Ehdr: 'S<2L<Q<3L<S<6',
14
+ Elf32_Phdr: 'L<8',
15
+ Elf64_Phdr: 'L<2Q<6'
16
+ }.freeze
17
+
18
+ SIZE_MAP = {
19
+ Elf32_Ehdr: 36,
20
+ Elf64_Ehdr: 48,
21
+ Elf32_Phdr: 32,
22
+ Elf64_Phdr: 56
23
+ }.freeze
24
+
25
+ STRUCT_MAP = {
26
+ Elf32_Ehdr: %i[
27
+ e_type
28
+ e_machine
29
+ e_version
30
+ e_entry
31
+ e_phoff
32
+ e_shoff
33
+ e_flags
34
+ e_ehsize
35
+ e_phentsize
36
+ e_phnum
37
+ e_shentsize
38
+ e_shnum
39
+ e_shstrndx
40
+ ].freeze,
41
+ Elf64_Ehdr: %i[
42
+ e_type
43
+ e_machine
44
+ e_version
45
+ e_entry
46
+ e_phoff
47
+ e_shoff
48
+ e_flags
49
+ e_ehsize
50
+ e_phentsize
51
+ e_phnum
52
+ e_shentsize
53
+ e_shnum
54
+ e_shstrndx
55
+ ].freeze,
56
+ Elf32_Phdr: %i[
57
+ p_type
58
+ p_offset
59
+ p_vaddr
60
+ p_paddr
61
+ p_filesz
62
+ p_memsz
63
+ p_flags
64
+ p_align
65
+ ].freeze,
66
+ Elf64_Phdr: %i[
67
+ p_type
68
+ p_flags
69
+ p_offset
70
+ p_vaddr
71
+ p_paddr
72
+ p_filesz
73
+ p_memsz
74
+ p_align
75
+ ].freeze
76
+ }.freeze
77
+ end
78
+
79
+ private_constant :PackInfo
80
+
81
+ # These constants are for the segment types stored in the image headers
82
+ PT_NULL = 0
83
+ PT_LOAD = 1
84
+ PT_DYNAMIC = 2
85
+ PT_INTERP = 3
86
+ PT_NOTE = 4
87
+ PT_SHLIB = 5
88
+ PT_PHDR = 6
89
+ PT_TLS = 7
90
+ PT_LOOS = 0x60000000
91
+ PT_HIOS = 0x6fffffff
92
+ PT_LOPROC = 0x70000000
93
+ PT_HIPROC = 0x7fffffff
94
+
95
+ # These constants define the different elf file types
96
+ ET_NONE = 0
97
+ ET_REL = 1
98
+ ET_EXEC = 2
99
+ ET_DYN = 3
100
+ ET_CORE = 4
101
+ ET_LOPROC = 0xff00
102
+ ET_HIPROC = 0xffff
103
+
104
+ EI_NIDENT = 16
105
+
106
+ # e_ident[] indexes
107
+ EI_MAG0 = 0
108
+ EI_MAG1 = 1
109
+ EI_MAG2 = 2
110
+ EI_MAG3 = 3
111
+ EI_CLASS = 4
112
+ EI_DATA = 5
113
+ EI_VERSION = 6
114
+ EI_OSABI = 7
115
+ EI_PAD = 8
116
+
117
+ # EI_MAG
118
+ ELFMAG0 = 0x7f
119
+ ELFMAG1 = 0x45
120
+ ELFMAG2 = 0x4c
121
+ ELFMAG3 = 0x46
122
+ ELFMAG = [ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3].pack('C*')
123
+ SELFMAG = 4
124
+
125
+ # e_ident[EI_CLASS]
126
+ ELFCLASSNONE = 0
127
+ ELFCLASS32 = 1
128
+ ELFCLASS64 = 2
129
+ ELFCLASSNUM = 3
130
+
131
+ # e_ident[EI_DATA]
132
+ ELFDATANONE = 0
133
+ ELFDATA2LSB = 1
134
+ ELFDATA2MSB = 2
135
+
136
+ def initialize(buffer)
137
+ @buffer = buffer
138
+
139
+ @ehdr = { e_ident: @buffer.read(EI_NIDENT).unpack('C*') }
140
+ raise ArgumentError unless @ehdr[:e_ident].slice(EI_MAG0, SELFMAG).pack('C*') == ELFMAG
141
+
142
+ case @ehdr[:e_ident][EI_CLASS]
143
+ when ELFCLASS32
144
+ elf_ehdr = :Elf32_Ehdr
145
+ elf_phdr = :Elf32_Phdr
146
+ when ELFCLASS64
147
+ elf_ehdr = :Elf64_Ehdr
148
+ elf_phdr = :Elf64_Phdr
149
+ else
150
+ raise EncodingError
151
+ end
152
+
153
+ case @ehdr[:e_ident][EI_DATA]
154
+ when ELFDATA2LSB
155
+ little_endian = true
156
+ when ELFDATA2MSB
157
+ little_endian = false
158
+ else
159
+ raise EncodingError
160
+ end
161
+
162
+ @ehdr.merge!(read(elf_ehdr, little_endian))
163
+
164
+ @buffer.seek(@ehdr[:e_phoff], IO::SEEK_SET)
165
+ @proghdrs = Array.new(@ehdr[:e_phnum]) do
166
+ read(elf_phdr, little_endian)
167
+ end
168
+ end
169
+
170
+ def relocatable?
171
+ @ehdr[:e_type] == ET_REL
172
+ end
173
+
174
+ def executable?
175
+ @ehdr[:e_type] == ET_EXEC
176
+ end
177
+
178
+ def shared_object?
179
+ @ehdr[:e_type] == ET_DYN
180
+ end
181
+
182
+ def core?
183
+ @ehdr[:e_type] == ET_CORE
184
+ end
185
+
186
+ def interpreter
187
+ phdr = @proghdrs.find { |p| p[:p_type] == PT_INTERP }
188
+ return if phdr.nil?
189
+
190
+ @buffer.seek(phdr[:p_offset], IO::SEEK_SET)
191
+ interpreter = @buffer.read(phdr[:p_filesz])
192
+ raise EncodingError unless interpreter.end_with?("\0")
193
+
194
+ interpreter.chomp!("\0")
195
+ end
196
+
197
+ private
198
+
199
+ def read(type, little_endian)
200
+ size = PackInfo::SIZE_MAP[type]
201
+ format = little_endian ? PackInfo::PACK_MAP[type] : PackInfo::PACK_MAP[type].tr('<', '>')
202
+ [PackInfo::STRUCT_MAP[type], @buffer.read(size).unpack(format)].transpose.to_h
203
+ end
204
+
205
+ INTERPRETER = begin
206
+ proc_self_exe = '/proc/self/exe'
207
+ if File.exist?(proc_self_exe)
208
+ File.open(proc_self_exe, 'rb') do |file|
209
+ elf = ELF.new(file)
210
+ interpreter = elf.interpreter
211
+ if interpreter.nil? && elf.shared_object?
212
+ File.readlink(proc_self_exe)
213
+ else
214
+ interpreter
215
+ end
216
+ end
217
+ end
218
+ end.freeze
219
+ end
220
+
221
+ private_constant :ELF
222
+ end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Sass
4
- class Embedded
5
- VERSION = '1.6.2'
4
+ module Embedded
5
+ VERSION = '1.83.1'
6
6
  end
7
7
  end