Class: Sass::Transport

Inherits:
Object
  • Object
show all
Includes:
Observable
Defined in:
lib/sass/transport.rb

Defined Under Namespace

Classes: MessageObserver

Constant Summary collapse

DART_SASS_EMBEDDED =
File.absolute_path(
  "../../ext/sass_embedded/dart-sass-embedded#{Sass::Platform::OS == 'windows' ? '.bat' : ''}", __dir__
)
PROTOCOL_ERROR_ID =
4_294_967_295

Instance Method Summary collapse

Constructor Details

#initializeTransport

Returns a new instance of Transport.



17
18
19
20
21
22
23
24
25
26
27
28
29
30
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
# File 'lib/sass/transport.rb', line 17

def initialize
  @stdin, @stdout, @stderr, @wait_thread = Open3.popen3(DART_SASS_EMBEDDED)
  @stdin_semaphore = Mutex.new
  @observerable_semaphore = Mutex.new

  Thread.new do
    loop do
      bits = length = 0
      loop do
        byte = @stdout.readbyte
        length += (byte & 0x7f) << bits
        bits += 7
        break if byte <= 0x7f
      end
      changed
      payload = @stdout.read length
      @observerable_semaphore.synchronize do
        notify_observers nil, Sass::EmbeddedProtocol::OutboundMessage.decode(payload)
      end
    rescue Interrupt
      break
    rescue IOError => e
      notify_observers e, nil
      close
      break
    end
  end

  Thread.new do
    loop do
      warn @stderr.read
    rescue Interrupt
      break
    rescue IOError => e
      @observerable_semaphore.synchronize do
        notify_observers e, nil
      end
      close
      break
    end
  end
end

Instance Method Details

#closeObject



93
94
95
96
97
98
99
# File 'lib/sass/transport.rb', line 93

def close
  delete_observers
  @stdin.close unless @stdin.closed?
  @stdout.close unless @stdout.closed?
  @stderr.close unless @stderr.closed?
  nil
end

#send(req, id) ⇒ Object



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
88
89
90
91
# File 'lib/sass/transport.rb', line 60

def send(req, id)
  mutex = Mutex.new
  resource = ConditionVariable.new

  req_name = req.class.name.split('::').last.gsub(/\B(?=[A-Z])/, '_').downcase

  message = Sass::EmbeddedProtocol::InboundMessage.new(req_name.to_sym => req)

  error = nil
  res = nil

  @observerable_semaphore.synchronize do
    MessageObserver.new self, id do |e, r|
      mutex.synchronize do
        error = e
        res = r

        resource.signal
      end
    end
  end

  mutex.synchronize do
    write message.to_proto

    resource.wait(mutex)
  end

  raise error if error

  res
end