opal-webpack-loader 0.11.1 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,219 +1,219 @@
1
- require 'ffi'
2
-
3
- module OpalWebpackLoader
4
- module WindowsyThings
5
- extend FFI::Library
6
-
7
- ffi_lib :kernel32, :user32
8
-
9
- ERROR_IO_PENDING = 997
10
- ERROR_PIPE_CONNECTED = 535
11
- ERROR_SUCCESS = 0
12
-
13
- FILE_FLAG_OVERLAPPED = 0x40000000
14
-
15
- INFINITE = 0xFFFFFFFF
16
- INVALID_HANDLE_VALUE = FFI::Pointer.new(-1).address
17
-
18
- PIPE_ACCESS_DUPLEX = 0x00000003
19
- PIPE_READMODE_BYTE = 0x00000000
20
- PIPE_READMODE_MESSAGE = 0x00000002
21
- PIPE_TYPE_BYTE = 0x00000000
22
- PIPE_TYPE_MESSAGE = 0x00000004
23
- PIPE_WAIT = 0x00000000
24
-
25
- QS_ALLINPUT = 0x04FF
26
-
27
- typedef :uintptr_t, :handle
28
-
29
- attach_function :ConnectNamedPipe, [:handle, :pointer], :ulong
30
- attach_function :CreateEvent, :CreateEventA, [:pointer, :ulong, :ulong, :string], :handle
31
- attach_function :CreateNamedPipe, :CreateNamedPipeA, [:string, :ulong, :ulong, :ulong, :ulong, :ulong, :ulong, :pointer], :handle
32
- attach_function :DisconnectNamedPipe, [:handle], :bool
33
- attach_function :FlushFileBuffers, [:handle], :bool
34
- attach_function :GetLastError, [], :ulong
35
- attach_function :GetOverlappedResult, [:handle, :pointer, :pointer, :bool], :bool
36
- attach_function :MsgWaitForMultipleObjects, [:ulong, :pointer, :ulong, :ulong, :ulong], :ulong
37
- attach_function :ReadFile, [:handle, :buffer_out, :ulong, :pointer, :pointer], :bool
38
- attach_function :SetEvent, [:handle], :bool
39
- attach_function :WaitForMultipleObjects, [:ulong, :pointer, :ulong, :ulong], :ulong
40
- attach_function :WriteFile, [:handle, :buffer_in, :ulong, :pointer, :pointer], :bool
41
- end
42
-
43
- class PipeServer
44
- include OpalWebpackLoader::WindowsyThings
45
-
46
- CONNECTING_STATE = 0
47
- READING_STATE = 1
48
- WRITING_STATE = 2
49
- INSTANCES = 4
50
- PIPE_TIMEOUT = 5000
51
- BUFFER_SIZE = 65536
52
-
53
- class Overlapped < FFI::Struct
54
- layout(
55
- :Internal, :uintptr_t,
56
- :InternalHigh, :uintptr_t,
57
- :Offset, :ulong,
58
- :OffsetHigh, :ulong,
59
- :hEvent, :uintptr_t
60
- )
61
- end
62
-
63
- def initialize(pipe_name, instances = 4, &block)
64
- @run_block = block
65
- @full_pipe_name = "\\\\.\\pipe\\#{pipe_name}"
66
- @instances = instances
67
- @events = []
68
- @events_pointer = FFI::MemoryPointer.new(:uintptr_t, @instances)
69
- @pipes = []
70
- end
71
-
72
- def run
73
- create_instances
74
- while_loop
75
- end
76
-
77
- private
78
-
79
- def create_instances
80
- (0...@instances).each do |i|
81
- @events[i] = CreateEvent(nil, 1, 1, nil)
82
- raise "CreateEvent failed with #{GetLastError()}" unless @events[i]
83
-
84
- overlap = Overlapped.new
85
- overlap[:hEvent] = @events[i]
86
-
87
- @pipes[i] = { overlap: overlap, instance: nil, request: FFI::Buffer.new(1, BUFFER_SIZE), bytes_read: 0, reply: FFI::Buffer.new(1, BUFFER_SIZE), bytes_to_write: 0, state: nil, pending_io: false }
88
- @pipes[i][:instance] = CreateNamedPipe(@full_pipe_name,
89
- PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
90
- PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
91
- @instances,
92
- BUFFER_SIZE,
93
- BUFFER_SIZE,
94
- PIPE_TIMEOUT,
95
- nil)
96
-
97
- raise "CreateNamedPipe failed with #{GetLastError()}" if @pipes[i][:instance] == INVALID_HANDLE_VALUE
98
- @pipes[i][:pending_io] = connect_to_new_client(i)
99
- @pipes[i][:state] = @pipes[i][:pending_io] ? CONNECTING_STATE : READING_STATE
100
- end
101
- @events_pointer.write_array_of_ulong_long(@events)
102
- nil
103
- end
104
-
105
- def while_loop
106
- while true
107
- i = MsgWaitForMultipleObjects(@instances, @events_pointer, 0, INFINITE, QS_ALLINPUT)
108
- # Having this STDOUT.putc is essential, otherwise there is a tendency to block within MsgWaitForMultipleObjects ...
109
- STDOUT.putc "."
110
- # ... because the ruby interpreter is waiting for objects too on Windows. Thats why we wait for QS_ALLINPUT and
111
- # with STDOUT.putc give back control to the ruby interpreter that it can handle its things.
112
- if i < 0 || i > (@instances - 1)
113
- STDERR.puts "Pipe index out of range. Maybe a error occured."
114
- next
115
- end
116
-
117
- if @pipes[i][:pending_io]
118
- bytes_transferred = FFI::MemoryPointer.new(:ulong)
119
- success = GetOverlappedResult(@pipes[i][:instance], @pipes[i][:overlap], bytes_transferred, false)
120
-
121
- case @pipes[i][:state]
122
- when CONNECTING_STATE
123
- raise "Error #{GetLastError()}" unless success
124
- @pipes[i][:state] = READING_STATE
125
- when READING_STATE
126
- if !success || bytes_transferred.read_ulong == 0
127
- disconnect_and_reconnect(i)
128
- next
129
- else
130
- @pipes[i][:bytes_read] = bytes_transferred.read_ulong
131
- @pipes[i][:state] = WRITING_STATE
132
- end
133
- when WRITING_STATE
134
- if !success || bytes_transferred.read_ulong != @pipes[i][:bytes_to_write]
135
- disconnect_and_reconnect(i)
136
- next
137
- else
138
- @pipes[i][:state] = READING_STATE
139
- end
140
- else
141
- raise "Invalid pipe state."
142
- end
143
- end
144
-
145
- case @pipes[i][:state]
146
- when READING_STATE
147
- bytes_read = FFI::MemoryPointer.new(:ulong)
148
- success = ReadFile(@pipes[i][:instance], @pipes[i][:request], BUFFER_SIZE, bytes_read, @pipes[i][:overlap].to_ptr)
149
- if success && bytes_read.read_ulong != 0
150
- @pipes[i][:pending_io] = false
151
- @pipes[i][:state] = WRITING_STATE
152
- next
153
- end
154
-
155
- err = GetLastError()
156
- if !success && err == ERROR_IO_PENDING
157
- @pipes[i][:pending_io] = true
158
- next
159
- end
160
-
161
- disconnect_and_reconnect(i)
162
- when WRITING_STATE
163
- @pipes[i][:reply] = @run_block.call(@pipes[i][:request].get_string(0))
164
- @pipes[i][:bytes_to_write] = @pipes[i][:reply].bytesize
165
- bytes_written = FFI::MemoryPointer.new(:ulong)
166
- success = WriteFile(@pipes[i][:instance], @pipes[i][:reply], @pipes[i][:bytes_to_write], bytes_written, @pipes[i][:overlap].to_ptr)
167
-
168
- if success && bytes_written.read_ulong == @pipes[i][:bytes_to_write]
169
- @pipes[i][:pending_io] = false
170
- @pipes[i][:state] = READING_STATE
171
- next
172
- end
173
-
174
- err = GetLastError()
175
-
176
- if !success && err == ERROR_IO_PENDING
177
- @pipes[i][:pending_io] = true
178
- next
179
- end
180
-
181
- disconnect_and_reconnect(i)
182
- else
183
- raise "Invalid pipe state."
184
- end
185
- end
186
- end
187
-
188
- def disconnect_and_reconnect(i)
189
- FlushFileBuffers(@pipes[i][:instance])
190
- STDERR.puts("DisconnectNamedPipe failed with #{GetLastError()}") if !DisconnectNamedPipe(@pipes[i][:instance])
191
-
192
- @pipes[i][:pending_io] = connect_to_new_client(i)
193
-
194
- @pipes[i][:state] = @pipes[i][:pending_io] ? CONNECTING_STATE : READING_STATE
195
- end
196
-
197
- def connect_to_new_client(i)
198
- pending_io = false
199
- @pipes[i][:request].clear
200
- @pipes[i][:reply].clear
201
- connected = ConnectNamedPipe(@pipes[i][:instance], @pipes[i][:overlap].to_ptr)
202
- last_error = GetLastError()
203
- raise "ConnectNamedPipe failed with #{last_error} - #{connected}" if connected != 0
204
-
205
- case last_error
206
- when ERROR_IO_PENDING
207
- pending_io = true
208
- when ERROR_PIPE_CONNECTED
209
- SetEvent(@pipes[i][:overlap][:hEvent])
210
- when ERROR_SUCCESS
211
- pending_io = true
212
- else
213
- raise "ConnectNamedPipe failed with error #{last_error}"
214
- end
215
-
216
- pending_io
217
- end
218
- end
219
- end
1
+ require 'ffi'
2
+
3
+ module OpalWebpackLoader
4
+ module WindowsyThings
5
+ extend FFI::Library
6
+
7
+ ffi_lib :kernel32, :user32
8
+
9
+ ERROR_IO_PENDING = 997
10
+ ERROR_PIPE_CONNECTED = 535
11
+ ERROR_SUCCESS = 0
12
+
13
+ FILE_FLAG_OVERLAPPED = 0x40000000
14
+
15
+ INFINITE = 0xFFFFFFFF
16
+ INVALID_HANDLE_VALUE = FFI::Pointer.new(-1).address
17
+
18
+ PIPE_ACCESS_DUPLEX = 0x00000003
19
+ PIPE_READMODE_BYTE = 0x00000000
20
+ PIPE_READMODE_MESSAGE = 0x00000002
21
+ PIPE_TYPE_BYTE = 0x00000000
22
+ PIPE_TYPE_MESSAGE = 0x00000004
23
+ PIPE_WAIT = 0x00000000
24
+
25
+ QS_ALLINPUT = 0x04FF
26
+
27
+ typedef :uintptr_t, :handle
28
+
29
+ attach_function :ConnectNamedPipe, [:handle, :pointer], :ulong
30
+ attach_function :CreateEvent, :CreateEventA, [:pointer, :ulong, :ulong, :string], :handle
31
+ attach_function :CreateNamedPipe, :CreateNamedPipeA, [:string, :ulong, :ulong, :ulong, :ulong, :ulong, :ulong, :pointer], :handle
32
+ attach_function :DisconnectNamedPipe, [:handle], :bool
33
+ attach_function :FlushFileBuffers, [:handle], :bool
34
+ attach_function :GetLastError, [], :ulong
35
+ attach_function :GetOverlappedResult, [:handle, :pointer, :pointer, :bool], :bool
36
+ attach_function :MsgWaitForMultipleObjects, [:ulong, :pointer, :ulong, :ulong, :ulong], :ulong
37
+ attach_function :ReadFile, [:handle, :buffer_out, :ulong, :pointer, :pointer], :bool
38
+ attach_function :SetEvent, [:handle], :bool
39
+ attach_function :WaitForMultipleObjects, [:ulong, :pointer, :ulong, :ulong], :ulong
40
+ attach_function :WriteFile, [:handle, :buffer_in, :ulong, :pointer, :pointer], :bool
41
+ end
42
+
43
+ class PipeServer
44
+ include OpalWebpackLoader::WindowsyThings
45
+
46
+ CONNECTING_STATE = 0
47
+ READING_STATE = 1
48
+ WRITING_STATE = 2
49
+ INSTANCES = 4
50
+ PIPE_TIMEOUT = 5000
51
+ BUFFER_SIZE = 65536
52
+
53
+ class Overlapped < FFI::Struct
54
+ layout(
55
+ :Internal, :uintptr_t,
56
+ :InternalHigh, :uintptr_t,
57
+ :Offset, :ulong,
58
+ :OffsetHigh, :ulong,
59
+ :hEvent, :uintptr_t
60
+ )
61
+ end
62
+
63
+ def initialize(pipe_name, instances = 4, &block)
64
+ @run_block = block
65
+ @full_pipe_name = "\\\\.\\pipe\\#{pipe_name}"
66
+ @instances = instances
67
+ @events = []
68
+ @events_pointer = FFI::MemoryPointer.new(:uintptr_t, @instances)
69
+ @pipes = []
70
+ end
71
+
72
+ def run
73
+ create_instances
74
+ while_loop
75
+ end
76
+
77
+ private
78
+
79
+ def create_instances
80
+ (0...@instances).each do |i|
81
+ @events[i] = CreateEvent(nil, 1, 1, nil)
82
+ raise "CreateEvent failed with #{GetLastError()}" unless @events[i]
83
+
84
+ overlap = Overlapped.new
85
+ overlap[:hEvent] = @events[i]
86
+
87
+ @pipes[i] = { overlap: overlap, instance: nil, request: FFI::Buffer.new(1, BUFFER_SIZE), bytes_read: 0, reply: FFI::Buffer.new(1, BUFFER_SIZE), bytes_to_write: 0, state: nil, pending_io: false }
88
+ @pipes[i][:instance] = CreateNamedPipe(@full_pipe_name,
89
+ PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
90
+ PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
91
+ @instances,
92
+ BUFFER_SIZE,
93
+ BUFFER_SIZE,
94
+ PIPE_TIMEOUT,
95
+ nil)
96
+
97
+ raise "CreateNamedPipe failed with #{GetLastError()}" if @pipes[i][:instance] == INVALID_HANDLE_VALUE
98
+ @pipes[i][:pending_io] = connect_to_new_client(i)
99
+ @pipes[i][:state] = @pipes[i][:pending_io] ? CONNECTING_STATE : READING_STATE
100
+ end
101
+ @events_pointer.write_array_of_ulong_long(@events)
102
+ nil
103
+ end
104
+
105
+ def while_loop
106
+ while true
107
+ i = MsgWaitForMultipleObjects(@instances, @events_pointer, 0, INFINITE, QS_ALLINPUT)
108
+ # Having this STDOUT.putc is essential, otherwise there is a tendency to block within MsgWaitForMultipleObjects ...
109
+ STDOUT.putc "."
110
+ # ... because the ruby interpreter is waiting for objects too on Windows. Thats why we wait for QS_ALLINPUT and
111
+ # with STDOUT.putc give back control to the ruby interpreter that it can handle its things.
112
+ if i < 0 || i > (@instances - 1)
113
+ STDERR.puts "Pipe index out of range. Maybe a error occured."
114
+ next
115
+ end
116
+
117
+ if @pipes[i][:pending_io]
118
+ bytes_transferred = FFI::MemoryPointer.new(:ulong)
119
+ success = GetOverlappedResult(@pipes[i][:instance], @pipes[i][:overlap], bytes_transferred, false)
120
+
121
+ case @pipes[i][:state]
122
+ when CONNECTING_STATE
123
+ raise "Error #{GetLastError()}" unless success
124
+ @pipes[i][:state] = READING_STATE
125
+ when READING_STATE
126
+ if !success || bytes_transferred.read_ulong == 0
127
+ disconnect_and_reconnect(i)
128
+ next
129
+ else
130
+ @pipes[i][:bytes_read] = bytes_transferred.read_ulong
131
+ @pipes[i][:state] = WRITING_STATE
132
+ end
133
+ when WRITING_STATE
134
+ if !success || bytes_transferred.read_ulong != @pipes[i][:bytes_to_write]
135
+ disconnect_and_reconnect(i)
136
+ next
137
+ else
138
+ @pipes[i][:state] = READING_STATE
139
+ end
140
+ else
141
+ raise "Invalid pipe state."
142
+ end
143
+ end
144
+
145
+ case @pipes[i][:state]
146
+ when READING_STATE
147
+ bytes_read = FFI::MemoryPointer.new(:ulong)
148
+ success = ReadFile(@pipes[i][:instance], @pipes[i][:request], BUFFER_SIZE, bytes_read, @pipes[i][:overlap].to_ptr)
149
+ if success && bytes_read.read_ulong != 0
150
+ @pipes[i][:pending_io] = false
151
+ @pipes[i][:state] = WRITING_STATE
152
+ next
153
+ end
154
+
155
+ err = GetLastError()
156
+ if !success && err == ERROR_IO_PENDING
157
+ @pipes[i][:pending_io] = true
158
+ next
159
+ end
160
+
161
+ disconnect_and_reconnect(i)
162
+ when WRITING_STATE
163
+ @pipes[i][:reply] = @run_block.call(@pipes[i][:request].get_string(0))
164
+ @pipes[i][:bytes_to_write] = @pipes[i][:reply].bytesize
165
+ bytes_written = FFI::MemoryPointer.new(:ulong)
166
+ success = WriteFile(@pipes[i][:instance], @pipes[i][:reply], @pipes[i][:bytes_to_write], bytes_written, @pipes[i][:overlap].to_ptr)
167
+
168
+ if success && bytes_written.read_ulong == @pipes[i][:bytes_to_write]
169
+ @pipes[i][:pending_io] = false
170
+ @pipes[i][:state] = READING_STATE
171
+ next
172
+ end
173
+
174
+ err = GetLastError()
175
+
176
+ if !success && err == ERROR_IO_PENDING
177
+ @pipes[i][:pending_io] = true
178
+ next
179
+ end
180
+
181
+ disconnect_and_reconnect(i)
182
+ else
183
+ raise "Invalid pipe state."
184
+ end
185
+ end
186
+ end
187
+
188
+ def disconnect_and_reconnect(i)
189
+ FlushFileBuffers(@pipes[i][:instance])
190
+ STDERR.puts("DisconnectNamedPipe failed with #{GetLastError()}") if !DisconnectNamedPipe(@pipes[i][:instance])
191
+
192
+ @pipes[i][:pending_io] = connect_to_new_client(i)
193
+
194
+ @pipes[i][:state] = @pipes[i][:pending_io] ? CONNECTING_STATE : READING_STATE
195
+ end
196
+
197
+ def connect_to_new_client(i)
198
+ pending_io = false
199
+ @pipes[i][:request].clear
200
+ @pipes[i][:reply].clear
201
+ connected = ConnectNamedPipe(@pipes[i][:instance], @pipes[i][:overlap].to_ptr)
202
+ last_error = GetLastError()
203
+ raise "ConnectNamedPipe failed with #{last_error} - #{connected}" if connected != 0
204
+
205
+ case last_error
206
+ when ERROR_IO_PENDING
207
+ pending_io = true
208
+ when ERROR_PIPE_CONNECTED
209
+ SetEvent(@pipes[i][:overlap][:hEvent])
210
+ when ERROR_SUCCESS
211
+ pending_io = true
212
+ else
213
+ raise "ConnectNamedPipe failed with error #{last_error}"
214
+ end
215
+
216
+ pending_io
217
+ end
218
+ end
219
+ end
@@ -99,26 +99,25 @@ const common_config = {
99
99
  devServer: {
100
100
  <%= dev_server_before %>
101
101
  open: false,
102
- lazy: false,
103
102
  port: 3035,
104
103
  hot: true,
105
- // hotOnly: true,
106
- inline: true,
107
104
  https: false,
108
- disableHostCheck: true,
105
+ allowedHosts: 'all',
109
106
  headers: {
110
107
  "Access-Control-Allow-Origin": "*",
111
108
  "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, PATCH, OPTIONS",
112
109
  "Access-Control-Allow-Headers": "X-Requested-With, content-type, Authorization"
113
110
  },
114
- watchOptions: {
115
- // in case of problems with hot reloading uncomment the following two lines:
116
- // aggregateTimeout: 250,
117
- // poll: 50,
111
+ static: {
112
+ directory: path.resolve(__dirname, 'public'),
113
+ watch: {
114
+ // in case of problems with hot reloading uncomment the following two lines:
115
+ // aggregateTimeout: 250,
116
+ // poll: 50,
118
117
  ignored: /\bnode_modules\b/
118
+ }
119
119
  },
120
- contentBase: path.resolve(__dirname, 'public'),
121
- useLocalIp: false
120
+ host: 'localhost'
122
121
  }
123
122
  };
124
123