sass-embedded 1.77.5 → 1.86.3

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 (54) hide show
  1. checksums.yaml +4 -4
  2. data/exe/sass +1 -9
  3. data/ext/sass/Rakefile +407 -89
  4. data/ext/sass/embedded_sass_pb.rb +2 -4
  5. data/ext/sass/package.json +1 -1
  6. data/lib/sass/compiler/channel.rb +6 -4
  7. data/lib/sass/compiler/connection.rb +15 -20
  8. data/lib/sass/compiler/dispatcher.rb +27 -1
  9. data/lib/sass/compiler/host/function_registry.rb +6 -6
  10. data/lib/sass/compiler/host/importer_registry.rb +17 -11
  11. data/lib/sass/compiler/host/logger_registry.rb +17 -20
  12. data/lib/sass/compiler/host/protofier.rb +59 -73
  13. data/lib/sass/compiler/host/struct.rb +36 -0
  14. data/lib/sass/compiler/host.rb +2 -2
  15. data/lib/sass/compiler.rb +3 -3
  16. data/lib/sass/elf.rb +283 -170
  17. data/lib/sass/embedded/version.rb +1 -1
  18. data/lib/sass/embedded.rb +2 -41
  19. data/lib/sass/exception.rb +7 -2
  20. data/lib/sass/serializer.rb +5 -11
  21. data/lib/sass/value/argument_list.rb +0 -8
  22. data/lib/sass/value/color/channel.rb +79 -0
  23. data/lib/sass/value/color/conversions.rb +473 -0
  24. data/lib/sass/value/color/gamut_map_method/clip.rb +45 -0
  25. data/lib/sass/value/color/gamut_map_method/local_minde.rb +94 -0
  26. data/lib/sass/value/color/gamut_map_method.rb +45 -0
  27. data/lib/sass/value/color/interpolation_method.rb +51 -0
  28. data/lib/sass/value/color/space/a98_rgb.rb +57 -0
  29. data/lib/sass/value/color/space/display_p3.rb +57 -0
  30. data/lib/sass/value/color/space/hsl.rb +65 -0
  31. data/lib/sass/value/color/space/hwb.rb +70 -0
  32. data/lib/sass/value/color/space/lab.rb +77 -0
  33. data/lib/sass/value/color/space/lch.rb +53 -0
  34. data/lib/sass/value/color/space/lms.rb +129 -0
  35. data/lib/sass/value/color/space/oklab.rb +66 -0
  36. data/lib/sass/value/color/space/oklch.rb +54 -0
  37. data/lib/sass/value/color/space/prophoto_rgb.rb +59 -0
  38. data/lib/sass/value/color/space/rec2020.rb +69 -0
  39. data/lib/sass/value/color/space/rgb.rb +52 -0
  40. data/lib/sass/value/color/space/srgb.rb +140 -0
  41. data/lib/sass/value/color/space/srgb_linear.rb +72 -0
  42. data/lib/sass/value/color/space/utils.rb +86 -0
  43. data/lib/sass/value/color/space/xyz_d50.rb +100 -0
  44. data/lib/sass/value/color/space/xyz_d65.rb +57 -0
  45. data/lib/sass/value/color/space.rb +198 -0
  46. data/lib/sass/value/color.rb +537 -162
  47. data/lib/sass/value/function.rb +9 -6
  48. data/lib/sass/value/fuzzy_math.rb +23 -19
  49. data/lib/sass/value/mixin.rb +5 -2
  50. data/lib/sass/value/number/unit.rb +5 -4
  51. data/lib/sass/value/number.rb +8 -10
  52. data/lib/sass/value/string.rb +1 -1
  53. metadata +34 -19
  54. data/lib/sass/compiler/host/structifier.rb +0 -37
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 631464c3270dfeddd024e782fed7e3354594b03afa25ca5b9efc0509ccd70af4
4
- data.tar.gz: bd6224dff05c20e442feee188d1ae9f9b0066db7c1ad0725c253ccb25c3b6aa0
3
+ metadata.gz: 16ad6e7bdf2e7314d688d0942f5455d6cfaaf411516710e3847f164ce84855d4
4
+ data.tar.gz: 714fbb69aaf672c0229fe81abb1a5e6de6ff0300a9ab4b07e9b1e73ea625cd6a
5
5
  SHA512:
6
- metadata.gz: 6292f26854e7d873b7168d6e172fab1044eb7ca75754b2dc6b3ca158462abdaf49cc351a2cf58cb6da71bb81a1854b1da06267d76b2a779c67c9bd513a8736a1
7
- data.tar.gz: '0958f5d6cd79525a5ba9d591e540bd2eb23e31a2acaa59a74f0a896c0596ad6709e6332d7f7d328bfa95835b6f3262797f321958c88ef83d17d8f6de78284713'
6
+ metadata.gz: 4d8a7b51668022e4a81db26522190d398100d2d581737ea5261cefc23a27bd25eb3a996dfc907e6309793a6be0bc668a5803177a505ec5a32b926aac1781a340
7
+ data.tar.gz: 60a050686e1f88bf2c9c9c4b2ba0db78bff5d41fd47f84d5dddf0844665a7a9f856360a3d1503b1483e7cb4d5e5af992618fe5b0b0abc89e319ececeaaf74365
data/exe/sass CHANGED
@@ -6,15 +6,7 @@ require_relative '../ext/sass/cli'
6
6
  module Sass
7
7
  # The `sass` command line interface
8
8
  module CLI
9
- begin
10
- Kernel.exec(*COMMAND, *ARGV)
11
- rescue Errno::ENOENT
12
- require_relative '../lib/sass/elf'
13
-
14
- raise if ELF::INTERPRETER.nil?
15
-
16
- Kernel.exec(ELF::INTERPRETER, *COMMAND, *ARGV)
17
- end
9
+ Kernel.exec(*COMMAND, *ARGV)
18
10
  end
19
11
 
20
12
  private_constant :CLI
data/ext/sass/Rakefile CHANGED
@@ -2,75 +2,289 @@
2
2
 
3
3
  require 'rake/clean'
4
4
 
5
+ require_relative '../../lib/sass/elf'
6
+
7
+ ELF = Sass.const_get(:ELF)
8
+
5
9
  task default: %i[install clean]
6
10
 
7
11
  task install: %w[cli.rb] do
8
12
  Rake::Task['embedded_sass_pb.rb'].invoke unless File.exist?('embedded_sass_pb.rb')
9
13
  end
10
14
 
11
- CLEAN.include %w[protoc.exe ruby *.proto *.tar.gz *.zip]
12
-
13
- CLOBBER.include %w[dart-sass cli.rb embedded_sass_pb.rb]
15
+ CLEAN.include %w[
16
+ protoc.exe
17
+ ruby
18
+ true
19
+ *.proto
20
+ *.tar.gz
21
+ *.zip
22
+ ]
23
+
24
+ CLOBBER.include %w[
25
+ dart-sass
26
+ cli.rb
27
+ embedded_sass_pb.rb
28
+ node_modules
29
+ bun.lockb
30
+ package-lock.json
31
+ pnpm-lock.yaml
32
+ yarn.lock
33
+ ]
14
34
 
15
35
  file 'protoc.exe' do |t|
16
- fetch(ENV.fetch('PROTOC_BIN') { SassConfig.default_protoc }, t.name)
36
+ fetch(SassConfig.protoc, t.name)
37
+ chmod 'a+x', t.name
38
+ rescue NotImplementedError
39
+ File.write(t.name, <<~PROTOC_EXE)
40
+ #!#{RbConfig.ruby}
41
+ # frozen_string_literal: true
42
+ Kernel.exec('protoc', *ARGV)
43
+ PROTOC_EXE
17
44
  chmod 'a+x', t.name
18
45
  end
19
46
 
20
- file 'dart-sass' do |t|
21
- raise if ENV.key?('DART_SASS')
22
-
23
- gem_install 'sass-embedded', SassConfig.gem_version, SassConfig.gem_platform do |dir|
24
- mv File.absolute_path("ext/sass/#{t.name}", dir), t.name
47
+ file 'dart-sass/sass' do
48
+ gem_install 'sass-embedded', SassConfig.gem_version, SassConfig.gem_platform do |installer|
49
+ gh_attestation_verify(installer.gem, repo: 'sass-contrib/sass-embedded-host-ruby')
50
+ mv File.absolute_path('ext/sass/dart-sass', installer.gem_dir), 'dart-sass'
25
51
  end
26
52
  rescue StandardError
27
- archive = fetch(ENV.fetch('DART_SASS') { SassConfig.default_dart_sass })
53
+ archive = fetch(SassConfig.dart_sass)
54
+ gh_attestation_verify(archive, repo: 'sass/dart-sass')
28
55
  unarchive archive
29
56
  rm archive
30
57
  end
31
58
 
59
+ file 'node_modules/sass' do
60
+ sh 'npm', 'install'
61
+ rescue StandardError
62
+ begin
63
+ sh 'yarn', 'install'
64
+ rescue StandardError
65
+ begin
66
+ sh 'pnpm', 'install'
67
+ rescue StandardError
68
+ sh 'bun', 'install'
69
+ end
70
+ end
71
+ end
72
+
73
+ task 'dart-sass' do
74
+ Rake::Task['dart-sass/sass'].invoke
75
+ rescue NotImplementedError
76
+ Rake::Task['node_modules/sass'].invoke
77
+ end
78
+
32
79
  file 'cli.rb' => %w[dart-sass] do |t|
33
- exe = 'dart-sass/sass'
34
- exe = "#{exe}#{['', '.bat', '.exe'].find { |ext| File.exist?("#{exe}#{ext}") }}"
35
-
36
- raise "#{exe} not found" unless File.exist?(exe)
37
-
38
- runtime = 'dart-sass/src/dart'
39
- runtime = "#{runtime}#{['', '.exe'].find { |ext| File.exist?("#{runtime}#{ext}") }}"
40
- snapshot = 'dart-sass/src/sass.snapshot'
41
-
42
- command = if File.exist?(runtime) && File.exist?(snapshot)
43
- "
44
- File.absolute_path('#{runtime}', __dir__).freeze,
45
- File.absolute_path('#{snapshot}', __dir__).freeze
46
- "
47
- else
48
- "
49
- File.absolute_path('#{exe}', __dir__).freeze
50
- "
51
- end
52
-
53
- File.write(t.name, <<~CLI_RB)
54
- # frozen_string_literal: true
80
+ begin
81
+ exe = 'dart-sass/sass'
82
+ exe = "#{exe}#{['', '.bat', '.exe'].find { |ext| File.exist?("#{exe}#{ext}") }}"
83
+
84
+ raise Errno::ENOENT, exe unless File.exist?(exe)
85
+
86
+ runtime = 'dart-sass/src/dart'
87
+ runtime = "#{runtime}#{['', '.exe'].find { |ext| File.exist?("#{runtime}#{ext}") }}"
88
+ snapshot = 'dart-sass/src/sass.snapshot'
89
+
90
+ command = if File.exist?(runtime) && File.exist?(snapshot)
91
+ [runtime, snapshot]
92
+ else
93
+ [exe]
94
+ end
95
+
96
+ interpreter = File.open(command[0], 'rb') do |file|
97
+ ELF.new(file).interpreter
98
+ rescue ArgumentError
99
+ nil
100
+ end
101
+
102
+ command_source = command.map do |argument|
103
+ "File.absolute_path('#{argument}', __dir__).freeze"
104
+ end.join(',
105
+ ')
106
+ rescue Errno::ENOENT
107
+ package = 'node_modules/sass'
108
+
109
+ script = File.join(package, SassConfig.package_json(package)['bin']['sass'])
110
+
111
+ interpreter = nil
112
+
113
+ command_source = [
114
+ "'node'",
115
+ "File.absolute_path('#{script}', __dir__).freeze"
116
+ ].join(',
117
+ ')
118
+ end
55
119
 
56
- module Sass
57
- module CLI
58
- COMMAND = [#{command}].freeze
120
+ if interpreter.nil?
121
+ File.write(t.name, <<~CLI_RB)
122
+ # frozen_string_literal: true
123
+
124
+ module Sass
125
+ module CLI
126
+ COMMAND = [
127
+ #{command_source}
128
+ ].freeze
129
+ end
130
+
131
+ private_constant :CLI
59
132
  end
133
+ CLI_RB
134
+ else
135
+ File.write(t.name, <<~CLI_RB)
136
+ # frozen_string_literal: true
60
137
 
61
- private_constant :CLI
62
- end
63
- CLI_RB
138
+ require_relative '../../lib/sass/elf'
139
+
140
+ module Sass
141
+ module CLI
142
+ INTERPRETER = '#{interpreter}'
143
+
144
+ INTERPRETER_SUFFIX = '/#{File.basename(interpreter)}'
145
+
146
+ COMMAND = [
147
+ *(ELF::INTERPRETER if ELF::INTERPRETER != INTERPRETER && ELF::INTERPRETER&.end_with?(INTERPRETER_SUFFIX)),
148
+ #{command_source}
149
+ ].freeze
150
+ end
151
+
152
+ private_constant :CLI
153
+ end
154
+ CLI_RB
155
+ end
64
156
  end
65
157
 
66
158
  file 'embedded_sass.proto' => %w[cli.rb] do |t|
67
- fetch(ENV.fetch('EMBEDDED_SASS_PROTOCOL') { SassConfig.default_embedded_sass_protocol }, t.name)
159
+ fetch(SassConfig.embedded_sass_protocol, t.name)
68
160
  end
69
161
 
70
162
  rule '_pb.rb' => %w[.proto protoc.exe] do |t|
71
163
  sh './protoc.exe', '--proto_path=.', '--ruby_out=.', t.source
72
164
  end
73
165
 
166
+ file 'true' do |t|
167
+ case Platform::CPU
168
+ when 'aarch64'
169
+ ei_class = ELF::ELFCLASS64
170
+ ei_data = ELF::ELFDATA2LSB
171
+ e_machine = 0xb7
172
+ e_flags = 0
173
+
174
+ # 0000000000400078 <PT_LOAD#0>:
175
+ # 400078: d2800ba8 mov x8, #0x5d // =93
176
+ # 40007c: d2800000 mov x0, #0x0 // =0
177
+ # 400080: d4000001 svc #0
178
+ entry_point = [0xd2800ba8, 0xd2800000, 0xd4000001].pack('L<3')
179
+ when 'arm'
180
+ ei_class = ELF::ELFCLASS32
181
+ ei_data = ELF::ELFDATA2LSB
182
+ e_machine = 0x28
183
+ e_flags = 0x5000400
184
+
185
+ # 00400054 <PT_LOAD#0>:
186
+ # 400054: 2701 movs r7, #0x1
187
+ # 400056: 2000 movs r0, #0x0
188
+ # 400058: df00 svc #0x0
189
+ entry_point = [0x2701, 0x2000, 0xdf00].pack('S<3')
190
+ when 'riscv64'
191
+ ei_class = ELF::ELFCLASS64
192
+ ei_data = ELF::ELFDATA2LSB
193
+ e_machine = 0xf3
194
+ e_flags = 0x5
195
+
196
+ # 0000000000400078 <PT_LOAD#0>:
197
+ # 400078: 05d00893 li a7, 0x5d
198
+ # 40007c: 4501 li a0, 0x0
199
+ # 40007e: 00000073 ecall
200
+ entry_point = [0x05d00893, 0x4501, 0x00000073].pack('L<S<L<')
201
+ when 'x86_64'
202
+ ei_class = ELF::ELFCLASS64
203
+ ei_data = ELF::ELFDATA2LSB
204
+ e_machine = 0x3e
205
+ e_flags = 0
206
+
207
+ # 0000000000400078 <PT_LOAD#0>:
208
+ # 400078: 31 ff xorl %edi, %edi
209
+ # 40007a: b8 3c 00 00 00 movl $0x3c, %eax
210
+ # 40007f: 0f 05 syscall
211
+ entry_point = %w[31ffb83c0000000f05].pack('H*')
212
+ when 'i386'
213
+ ei_class = ELF::ELFCLASS32
214
+ ei_data = ELF::ELFDATA2LSB
215
+ e_machine = 0x03
216
+ e_flags = 0
217
+
218
+ # 00400054 <PT_LOAD#0>:
219
+ # 400054: 31 db xorl %ebx, %ebx
220
+ # 400056: b8 01 00 00 00 movl $0x1, %eax
221
+ # 40005b: cd 80 int $0x80
222
+ entry_point = %w[31dbb801000000cd80].pack('H*')
223
+ else
224
+ raise NotImplementedError
225
+ end
226
+
227
+ case ei_class
228
+ when ELF::ELFCLASS32
229
+ e_ehsize = ELF::Elf32_Ehdr.sizeof
230
+ e_phentsize = ELF::Elf32_Phdr.sizeof
231
+ e_shentsize = ELF::Elf32_Shdr.sizeof
232
+ when ELF::ELFCLASS64
233
+ e_ehsize = ELF::Elf64_Ehdr.sizeof
234
+ e_phentsize = ELF::Elf64_Phdr.sizeof
235
+ e_shentsize = ELF::Elf64_Shdr.sizeof
236
+ else
237
+ raise EncodingError
238
+ end
239
+
240
+ e_phoff = e_ehsize
241
+
242
+ p_offset = e_phoff + e_phentsize
243
+ p_vaddr = (2**22) + p_offset
244
+ p_filesz = entry_point.length
245
+ p_memsz = p_filesz
246
+
247
+ e_entry = p_vaddr
248
+ e_entry += 1 if Platform::CPU == 'arm'
249
+
250
+ ELF.allocate.instance_eval do
251
+ @ehdr = {
252
+ e_ident: [127, 69, 76, 70, ei_class, ei_data, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
253
+ e_type: ELF::ET_EXEC,
254
+ e_machine:,
255
+ e_version: 1,
256
+ e_entry:,
257
+ e_phoff:,
258
+ e_shoff: 0,
259
+ e_flags:,
260
+ e_ehsize:,
261
+ e_phentsize:,
262
+ e_phnum: 1,
263
+ e_shentsize:,
264
+ e_shnum: 0,
265
+ e_shstrndx: 0
266
+ }
267
+ @phdrs = [
268
+ {
269
+ p_type: ELF::PT_LOAD,
270
+ p_flags: ELF::PF_R | ELF::PF_X,
271
+ p_offset:,
272
+ p_vaddr:,
273
+ p_paddr: 0,
274
+ p_filesz:,
275
+ p_memsz:,
276
+ p_align: 4096
277
+ }
278
+ ]
279
+ @shdrs = []
280
+
281
+ File.open(t.name, 'wb', 0o755) do |file|
282
+ dump(file)
283
+ file.write(entry_point)
284
+ end
285
+ end
286
+ end
287
+
74
288
  # This is a FileUtils extension that defines several additional commands to be
75
289
  # added to the FileUtils utility functions.
76
290
  module FileUtils
@@ -102,7 +316,7 @@ module FileUtils
102
316
  entry = entries.nextElement
103
317
  name = entry.getName
104
318
  path = dest_path.resolve(name).normalize
105
- raise unless path.startsWith(dest_path)
319
+ raise SecurityError unless path.startsWith(dest_path)
106
320
 
107
321
  Rake.rake_output_message " inflating: #{name}" if Rake::FileUtilsExt.verbose_flag
108
322
 
@@ -138,7 +352,7 @@ module FileUtils
138
352
  def fetch(source_uri, dest_path = nil)
139
353
  require 'rubygems/remote_fetcher'
140
354
 
141
- source_uri = "/#{source_uri}" if File.absolute_path?(source_uri) && !source_uri.start_with?('/')
355
+ source_uri = "/#{source_uri}" if !source_uri.start_with?('/') && File.absolute_path?(source_uri)
142
356
 
143
357
  source_uri = begin
144
358
  Gem::Uri.parse!(source_uri)
@@ -198,7 +412,7 @@ module FileUtils
198
412
  s.platform == platform
199
413
  end
200
414
 
201
- raise if resolver_spec.nil?
415
+ raise Gem::UnsatisfiableDependencyError, dependency_request if resolver_spec.nil?
202
416
 
203
417
  options = { force: true, install_dir: }
204
418
  if Rake::FileUtilsExt.nowrite_flag
@@ -209,63 +423,165 @@ module FileUtils
209
423
  installer.install
210
424
  end
211
425
 
212
- yield installer.dir
426
+ yield installer
213
427
  ensure
214
428
  rm_rf install_dir unless Rake::FileUtilsExt.nowrite_flag
215
429
  end
430
+
431
+ def gh_attestation_verify(path, repo:, hostname: 'github.com')
432
+ if SassConfig.development? && system('gh', 'auth', 'status', '--hostname', hostname, %i[out err] => File::NULL)
433
+ sh 'gh', 'attestation', 'verify', path, '--hostname', hostname, '--repo', repo
434
+ end
435
+ end
216
436
  end
217
437
 
218
- # The {SassConfig} module.
219
- module SassConfig
220
- module Platform
221
- OS = case RbConfig::CONFIG['host_os'].downcase
222
- when /darwin/
223
- 'darwin'
224
- when /linux-android/
225
- 'linux-android'
226
- when /linux-musl/
227
- 'linux-musl'
228
- when /linux-uclibc/
229
- 'linux-uclibc'
230
- when /linux/
231
- 'linux'
232
- when *Gem::WIN_PATTERNS
233
- 'windows'
234
- else
235
- RbConfig::CONFIG['host_os'].downcase
236
- end
438
+ # The {Platform} module.
439
+ module Platform
440
+ # @see https://docs.freebsd.org/en/articles/linux-emulation/
441
+ # @see https://docs.freebsd.org/en/books/handbook/linuxemu/
442
+ module Linuxulator
443
+ module_function
237
444
 
238
- CPU = case RbConfig::CONFIG['host_cpu'].downcase
239
- when /amd64|x86_64|x64/
240
- 'x86_64'
241
- when /i\d86|x86|i86pc/
242
- 'x86'
243
- when /arm64|aarch64/
244
- 'aarch64'
245
- when /arm/
246
- 'arm'
247
- when /ppc64le|powerpc64le/
248
- 'powerpc64le'
249
- else
250
- RbConfig::CONFIG['host_cpu']
251
- end
445
+ def enabled?
446
+ return false unless RbConfig::CONFIG['host_os'].include?('freebsd')
447
+
448
+ return true if defined?(Platform::OS) && Platform::OS.include?('linux')
449
+
450
+ begin
451
+ Rake::Task['true'].invoke unless File.exist?('true')
452
+ rescue NotImplementedError
453
+ return false
454
+ end
252
455
 
253
- ARCH = "#{CPU}-#{OS}".freeze
456
+ system('./true', %i[out err] => File::NULL) == true
457
+ end
458
+
459
+ def host_os(root = compat_linux_emul_path)
460
+ return 'linux-none' unless File.symlink?(File.absolute_path('proc/self/exe', root))
461
+
462
+ if (Platform::CPU == 'aarch64' &&
463
+ File.exist?(File.absolute_path('lib/ld-linux-aarch64.so.1', root))) ||
464
+ (Platform::CPU == 'riscv64' &&
465
+ File.exist?(File.absolute_path('lib/ld-linux-riscv64-lp64d.so.1', root))) ||
466
+ (Platform::CPU == 'x86_64' &&
467
+ File.exist?(File.absolute_path('lib64/ld-linux-x86-64.so.2', root))) ||
468
+ (Platform::CPU == 'i386' &&
469
+ File.exist?(File.absolute_path('lib/ld-linux.so.2', root)))
470
+ return 'linux-gnu'
471
+ end
472
+
473
+ if Platform::CPU == 'arm' &&
474
+ File.exist?(File.absolute_path('lib/ld-linux-armhf.so.3', root))
475
+ return 'linux-gnueabihf'
476
+ end
477
+
478
+ if %w[aarch64 riscv64 x86_64 i386].include?(Platform::CPU) &&
479
+ File.exist?(File.absolute_path("lib/ld-musl-#{Platform::CPU}.so.1", root))
480
+ return 'linux-musl'
481
+ end
482
+
483
+ if Platform::CPU == 'arm' &&
484
+ File.exist?(File.absolute_path('lib/ld-musl-armhf.so.1', root))
485
+ return 'linux-musleabihf'
486
+ end
487
+
488
+ if (%w[aarch64 riscv64 x86_64].include?(Platform::CPU) &&
489
+ File.exist?(File.absolute_path('system/bin/linker64', root))) ||
490
+ (Platform::CPU == 'i386' &&
491
+ File.exist?(File.absolute_path('system/bin/linker', root)))
492
+ return 'linux-android'
493
+ end
494
+
495
+ if Platform::CPU == 'arm' &&
496
+ File.exist?(File.absolute_path('system/bin/linker', root))
497
+ return 'linux-androideabi'
498
+ end
499
+
500
+ 'linux-none'
501
+ end
502
+
503
+ def compat_linux_emul_path
504
+ require 'fiddle'
505
+
506
+ lib = Fiddle.dlopen(nil)
507
+ sysctlbyname = Fiddle::Function.new(
508
+ lib['sysctlbyname'],
509
+ [Fiddle::TYPE_VOIDP, Fiddle::TYPE_VOIDP, Fiddle::TYPE_VOIDP, Fiddle::TYPE_VOIDP, Fiddle::TYPE_SIZE_T],
510
+ Fiddle::TYPE_INT
511
+ )
512
+
513
+ name = Fiddle::Pointer.to_ptr('compat.linux.emul_path')
514
+ oldp = Fiddle::NULL
515
+ oldlenp = Fiddle::Pointer.malloc(Fiddle::SIZEOF_SIZE_T, Fiddle::RUBY_FREE)
516
+ newp = Fiddle::NULL
517
+ newlen = 0
518
+ raise SystemCallError.new(nil, Fiddle.last_error) if sysctlbyname.call(name, oldp, oldlenp, newp, newlen) == -1
519
+
520
+ oldp = Fiddle::Pointer.malloc(oldlenp.ptr.to_i, Fiddle::RUBY_FREE)
521
+ raise SystemCallError.new(nil, Fiddle.last_error) if sysctlbyname.call(name, oldp, oldlenp, newp, newlen) == -1
522
+
523
+ oldp.to_s
524
+ rescue SystemCallError
525
+ nil
526
+ end
254
527
  end
255
528
 
256
- private_constant :Platform
529
+ HOST_CPU = RbConfig::CONFIG['host_cpu'].downcase
530
+
531
+ CPU = case HOST_CPU
532
+ when /amd64|x86_64|x64/
533
+ 'x86_64'
534
+ when /i\d86|x86|i86pc/
535
+ 'i386'
536
+ when /arm64|aarch64/
537
+ 'aarch64'
538
+ when /arm/
539
+ 'arm'
540
+ when /ppc64le|powerpc64le/
541
+ 'ppc64le'
542
+ else
543
+ HOST_CPU
544
+ end
545
+
546
+ HOST_OS = (Linuxulator.enabled? ? Linuxulator.host_os : RbConfig::CONFIG['host_os']).downcase
547
+
548
+ OS = case HOST_OS
549
+ when /darwin/
550
+ 'darwin'
551
+ when /linux-android/
552
+ 'linux-android'
553
+ when /linux-musl/
554
+ 'linux-musl'
555
+ when /linux-none/
556
+ 'linux-none'
557
+ when /linux-uclibc/
558
+ 'linux-uclibc'
559
+ when /linux/
560
+ 'linux'
561
+ when *Gem::WIN_PATTERNS
562
+ 'windows'
563
+ else
564
+ HOST_OS
565
+ end
566
+
567
+ ARCH = "#{CPU}-#{OS}".freeze
568
+ end
257
569
 
570
+ # The {SassConfig} module.
571
+ module SassConfig
258
572
  module_function
259
573
 
260
- def dart_sass_version
574
+ def package_json(path = '.')
261
575
  require 'json'
262
576
 
263
- spec = JSON.parse(File.read(File.absolute_path('package.json', __dir__)))
577
+ JSON.parse(File.read(File.absolute_path('package.json', path)))
578
+ end
264
579
 
265
- spec['dependencies']['sass']
580
+ def dart_sass_version
581
+ package_json['dependencies']['sass']
266
582
  end
267
583
 
268
- def default_dart_sass
584
+ def dart_sass
269
585
  repo = 'https://github.com/sass/dart-sass'
270
586
 
271
587
  tag_name = dart_sass_version
@@ -291,7 +607,7 @@ module SassConfig
291
607
  end
292
608
 
293
609
  cpu = case Platform::CPU
294
- when 'x86'
610
+ when 'i386'
295
611
  'ia32'
296
612
  when 'x86_64'
297
613
  'x64'
@@ -310,7 +626,7 @@ module SassConfig
310
626
  "#{repo}/releases/download/#{tag_name}/dart-sass-#{tag_name}-#{os}-#{cpu}#{env}.#{ext}"
311
627
  end
312
628
 
313
- def default_protoc
629
+ def protoc
314
630
  require 'rubygems/remote_fetcher'
315
631
 
316
632
  repo = 'https://repo.maven.apache.org/maven2/com/google/protobuf/protoc'
@@ -326,7 +642,7 @@ module SassConfig
326
642
  os = case Platform::OS
327
643
  when 'darwin'
328
644
  'osx'
329
- when 'linux'
645
+ when 'linux', 'linux-android', 'linux-musl', 'linux-none', 'linux-uclibc'
330
646
  'linux'
331
647
  when 'windows'
332
648
  'windows'
@@ -335,13 +651,13 @@ module SassConfig
335
651
  end
336
652
 
337
653
  cpu = case Platform::CPU
338
- when 'x86'
654
+ when 'i386'
339
655
  'x86_32'
340
656
  when 'x86_64'
341
657
  'x86_64'
342
658
  when 'aarch64'
343
659
  'aarch_64'
344
- when 'powerpc64le'
660
+ when 'ppc64le'
345
661
  'ppcle_64'
346
662
  when 's390x'
347
663
  's390_64'
@@ -374,7 +690,7 @@ module SassConfig
374
690
  raise NotImplementedError, message
375
691
  end
376
692
 
377
- def default_embedded_sass_protocol
693
+ def embedded_sass_protocol
378
694
  require 'json'
379
695
  require 'open3'
380
696
 
@@ -388,6 +704,8 @@ module SassConfig
388
704
  tag_name = JSON.parse(stdout)['protocolVersion']
389
705
 
390
706
  "https://github.com/sass/sass/raw/embedded-protocol-#{tag_name}/spec/embedded_sass.proto"
707
+ rescue StandardError # TODO: remove after https://github.com/sass/dart-sass/pull/2413
708
+ 'https://github.com/sass/sass/raw/HEAD/spec/embedded_sass.proto'
391
709
  end
392
710
 
393
711
  def development?
@@ -401,7 +719,7 @@ module SassConfig
401
719
  end
402
720
 
403
721
  def gem_platform
404
- platform = Gem::Platform.new("#{Platform::CPU}-#{RbConfig::CONFIG['host_os']}")
722
+ platform = Gem::Platform.new("#{Platform::CPU}-#{Platform::HOST_OS}")
405
723
  case Platform::OS
406
724
  when 'darwin'
407
725
  case platform.cpu