mini_racer 0.1.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,14 +1,20 @@
1
1
  # MiniRacer
2
2
 
3
- [![Build Status](https://travis-ci.org/discourse/mini_racer.svg?branch=master)](https://travis-ci.org/discourse/mini_racer)
3
+ [![Build Status](https://travis-ci.org/rubyjs/mini_racer.svg?branch=master)](https://travis-ci.org/rubyjs/mini_racer)
4
4
 
5
5
  Minimal, modern embedded V8 for Ruby.
6
6
 
7
7
  MiniRacer provides a minimal two way bridge between the V8 JavaScript engine and Ruby.
8
8
 
9
- It was created as an alternative to the excellent [therubyracer](https://github.com/cowboyd/therubyracer). Unlike therubyracer, mini_racer only implements a minimal bridge. This reduces the surface area making upgrading v8 much simpler and exahustive testing simpler.
9
+ It was created as an alternative to the excellent [therubyracer](https://github.com/cowboyd/therubyracer). Unlike therubyracer, mini_racer only implements a minimal bridge. This reduces the surface area making upgrading v8 much simpler and exhaustive testing simpler.
10
10
 
11
- MiniRacer has an adapter for [execjs](https://github.com/sstephenson/execjs) so it can be used directly with Rails projects to minify assets, run babel or compile CoffeeScript.
11
+ MiniRacer has an adapter for [execjs](https://github.com/rails/execjs) so it can be used directly with Rails projects to minify assets, run babel or compile CoffeeScript.
12
+
13
+ ### A note about Ruby version Support
14
+
15
+ MiniRacer only supports non-EOL versions of Ruby. See [Ruby](https://www.ruby-lang.org/en/downloads) to see the list of non-EOL Rubies.
16
+
17
+ If you require support for older versions of Ruby install an older version of the gem.
12
18
 
13
19
  ## Features
14
20
 
@@ -29,11 +35,18 @@ You can attach one or many ruby proc that can be accessed via JavaScript
29
35
 
30
36
  ```ruby
31
37
  context = MiniRacer::Context.new
32
- context.attach("adder", proc{|a,b| a+b})
33
- puts context.eval 'adder(20,22)'
38
+ context.attach("math.adder", proc{|a,b| a+b})
39
+ puts context.eval 'math.adder(20,22)'
34
40
  # => 42
35
41
  ```
36
42
 
43
+ ```ruby
44
+ context = MiniRacer::Context.new
45
+ context.attach("array_and_hash", proc{{a: 1, b: [1, {a: 1}]}})
46
+ puts context.eval 'array_and_hash()'
47
+ # => {"a" => 1, "b" => [1, {"a" => 1}]}
48
+ ```
49
+
37
50
  ### GIL free JavaScript execution
38
51
 
39
52
  The Ruby Global interpreter lock is released when scripts are executing
@@ -61,6 +74,64 @@ context.eval 'while(true){}'
61
74
  # => exception is raised
62
75
  ```
63
76
 
77
+ ### Memory softlimit support
78
+
79
+ Contexts can specify a memory softlimit for scripts
80
+
81
+ ```ruby
82
+ # terminates script if heap usage exceeds 200mb after V8 garbage collection has run
83
+ context = MiniRacer::Context.new(max_memory: 200000000)
84
+ context.eval 'var a = new Array(10000); while(true) {a = a.concat(new Array(10000)); print("loop " + a.length);}'
85
+ # => V8OutOfMemoryError is raised
86
+ ```
87
+
88
+ ### Object marshal max stackdepth support
89
+
90
+ Contexts can specify a stack depth limit for object marshalling. Max depth is unbounded by default.
91
+
92
+ ```ruby
93
+ # terminates script if stack depth exceeds max during marshal
94
+ context = MiniRacer::Context.new(marshal_stack_depth: 500)
95
+ context.attach("a", proc{|a| a})
96
+
97
+ context.eval("let arr = []; arr.push(arr); a(arr)")
98
+ # => RuntimeError is raised
99
+ ```
100
+
101
+ ### Rich debugging with "filename" support
102
+
103
+ ```ruby
104
+
105
+ context = MiniRacer::Context.new
106
+ context.eval('var foo = function() {bar();}', filename: 'a/foo.js')
107
+ context.eval('bar()', filename: 'a/bar.js')
108
+
109
+ # MiniRacer::RuntimeError is raised containing the filenames you specified for evals in backtrace
110
+
111
+ ```
112
+
113
+ ### Fork safety
114
+
115
+ Some Ruby web servers employ forking (for example unicorn or puma in clustered mode). V8 is not fork safe.
116
+ Sadly Ruby does not have support for fork notifications per [#5446](https://bugs.ruby-lang.org/issues/5446).
117
+
118
+ If you want to ensure your application does not leak memory after fork either:
119
+
120
+ 1. Ensure no MiniRacer::Context objects are created in the master process
121
+
122
+ Or
123
+
124
+ 2. Dispose manually of all MiniRacer::Context objects prior to forking
125
+
126
+ ```ruby
127
+ # before fork
128
+
129
+ require 'objspace'
130
+ ObjectSpace.each_object(MiniRacer::Context){|c| c.dispose}
131
+
132
+ # fork here
133
+ ```
134
+
64
135
  ### Threadsafe
65
136
 
66
137
  Context usage is threadsafe
@@ -81,28 +152,239 @@ puts context.eval("counter")
81
152
 
82
153
  ```
83
154
 
155
+ ### Snapshots
156
+
157
+ Contexts can be created with pre-loaded snapshots:
158
+
159
+ ```ruby
160
+
161
+ snapshot = MiniRacer::Snapshot.new('function hello() { return "world!"; }')
162
+
163
+ context = MiniRacer::Context.new(snapshot: snapshot)
164
+
165
+ context.eval("hello()")
166
+ # => "world!"
167
+
168
+ ```
169
+
170
+ Snapshots can come in handy for example if you want your contexts to be pre-loaded for effiency. It uses [V8 snapshots](http://v8project.blogspot.com/2015/09/custom-startup-snapshots.html) under the hood; see [this link](http://v8project.blogspot.com/2015/09/custom-startup-snapshots.html) for caveats using these, in particular:
171
+
172
+ ```
173
+ There is an important limitation to snapshots: they can only capture V8’s
174
+ heap. Any interaction from V8 with the outside is off-limits when creating the
175
+ snapshot. Such interactions include:
176
+
177
+ * defining and calling API callbacks (i.e. functions created via v8::FunctionTemplate)
178
+ * creating typed arrays, since the backing store may be allocated outside of V8
179
+
180
+ And of course, values derived from sources such as `Math.random` or `Date.now`
181
+ are fixed once the snapshot has been captured. They are no longer really random
182
+ nor reflect the current time.
183
+ ```
184
+
185
+ Also note that snapshots can be warmed up, using the `warmup!` method, which allows you to call functions which are otherwise lazily compiled to get them to compile right away; any side effect of your warm up code being then dismissed. [More details on warming up here](https://github.com/electron/electron/issues/169#issuecomment-76783481), and a small example:
186
+
187
+ ```ruby
188
+
189
+ snapshot = MiniRacer::Snapshot.new('var counter = 0; function hello() { counter++; return "world! "; }')
190
+
191
+ snapshot.warmup!('hello()')
192
+
193
+ context = MiniRacer::Context.new(snapshot: snapshot)
194
+
195
+ context.eval('hello()')
196
+ # => "world! 1"
197
+ context.eval('counter')
198
+ # => 1
199
+
200
+ ```
201
+
202
+ ### Shared isolates
203
+
204
+ By default, MiniRacer's contexts each have their own isolate (V8 runtime). For efficiency, it is possible to re-use an isolate across contexts:
205
+
206
+ ```ruby
207
+
208
+ isolate = MiniRacer::Isolate.new
209
+
210
+ context1 = MiniRacer::Context.new(isolate: isolate)
211
+ context2 = MiniRacer::Context.new(isolate: isolate)
212
+
213
+ context1.isolate == context2.isolate
214
+ # => true
215
+ ```
216
+
217
+ The main benefit of this is avoiding creating/destroying isolates when not needed (for example if you use a lot of contexts).
218
+
219
+ The caveat with this is that a given isolate can only execute one context at a time, so don't share isolates across contexts that you want to run concurrently.
220
+
221
+ Also, note that if you want to use shared isolates together with snapshots, you need to first create an isolate with that snapshot, and then create contexts from that isolate:
222
+
223
+ ```ruby
224
+ snapshot = MiniRacer::Snapshot.new('function hello() { return "world!"; }')
225
+
226
+ isolate = MiniRacer::Isolate.new(snapshot)
227
+
228
+ context = MiniRacer::Context.new(isolate: isolate)
229
+
230
+ context.eval("hello()")
231
+ # => "world!"
232
+ ```
233
+
234
+ Re-using the same isolate over and over again means V8's garbage collector will have to run to clean it up every now and then; it's possible to trigger a _blocking_ V8 GC run inside your isolate by running the `idle_notification` method on it, which takes a single argument: the amount of time (in milliseconds) that V8 should use at most for garbage collecting:
235
+
236
+ ```ruby
237
+ isolate = MiniRacer::Isolate.new
238
+
239
+ context = MiniRacer::Context.new(isolate: isolate)
240
+
241
+ # do stuff with that context...
242
+
243
+ # give up to 100ms for V8 garbage collection
244
+ isolate.idle_notification(100)
245
+
246
+ # force V8 to perform a full GC
247
+ isolate.low_memory_notification
248
+
249
+ ```
250
+
251
+ This can come in handy to force V8 GC runs for example in between requests if you use MiniRacer on a web application.
252
+
253
+ Note that this method maps directly to [`v8::Isolate::IdleNotification`](http://bespin.cz/~ondras/html/classv8_1_1Isolate.html#aea16cbb2e351de9a3ae7be2b7cb48297), and that in particular its return value is the same (true if there is no further garbage to collect, false otherwise) and the same caveats apply, in particular that `there is no guarantee that the [call will return] within the time limit.`
254
+
255
+ Additionally you may automate this process on a context by defining it with `MiniRacer::Content.new(ensure_gc_after_idle: 1000)`. Using this will ensure V8 will run a full GC using `context.isolate.low_memory_notification` 1 second after the last eval on the context. Low memory notification is both slower and more aggressive than an idle_notification and will ensure long living isolates use minimal amounts of memory.
256
+
257
+ ### V8 Runtime flags
258
+
259
+ It is possible to set V8 Runtime flags:
260
+
261
+ ```ruby
262
+ MiniRacer::Platform.set_flags! :noconcurrent_recompilation, max_inlining_levels: 10
263
+ ```
264
+
265
+ This can come in handy if you want to use MiniRacer with Unicorn, which doesn't seem to always appreciate V8's liberal use of threading:
266
+ ```ruby
267
+ MiniRacer::Platform.set_flags! :noconcurrent_recompilation, :noconcurrent_sweeping
268
+ ```
269
+
270
+ Or else to unlock experimental features in V8, for example tail recursion optimization:
271
+ ```ruby
272
+ MiniRacer::Platform.set_flags! :harmony
273
+
274
+ js = <<-JS
275
+ 'use strict';
276
+ var f = function f(n){
277
+ if (n <= 0) {
278
+ return 'foo';
279
+ }
280
+ return f(n - 1);
281
+ }
282
+
283
+ f(1e6);
284
+ JS
285
+
286
+ context = MiniRacer::Context.new
287
+
288
+ context.eval js
289
+ # => "foo"
290
+ ```
291
+ The same code without the harmony runtime flag results in a `MiniRacer::RuntimeError: RangeError: Maximum call stack size exceeded` exception.
292
+ Please refer to http://node.green/ as a reference on other harmony features.
293
+
294
+ A list of all V8 runtime flags can be found using `node --v8-options`, or else by perusing [the V8 source code for flags (make sure to use the right version of V8)](https://github.com/v8/v8/blob/master/src/flags/flag-definitions.h).
295
+
296
+ Note that runtime flags must be set before any other operation (e.g. creating a context, a snapshot or an isolate), otherwise an exception will be thrown.
297
+
298
+ Flags:
299
+
300
+ - :expose_gc : Will expose `gc()` which you can run in JavaScript to issue a gc
301
+ - :max_old_space_size : defaults to 1400 (megs) on 64 bit, you can restric memory usage by limiting this.
302
+ - **NOTE TO READER** our documentation could be awesome we could be properly documenting all the flags, they are hugely useful, if you feel like documenting a few more, PLEASE DO, PRs are welcome.
303
+
304
+ ## Controlling memory
305
+
306
+ When hosting v8 you may want to keep track of memory usage, use #heap_stats to get memory usage:
307
+
308
+ ```ruby
309
+ context = MiniRacer::Context.new(timeout: 5)
310
+ context.eval("let a='testing';")
311
+ p context.heap_stats
312
+ # {:total_physical_size=>1280640,
313
+ # :total_heap_size_executable=>4194304,
314
+ # :total_heap_size=>3100672,
315
+ # :used_heap_size=>1205376,
316
+ # :heap_size_limit=>1501560832}
317
+ ```
318
+
319
+ If you wish to dispose of a context before waiting on the GC use
320
+
321
+ ```ruby
322
+ context = MiniRacer::Context.new(timeout: 5)
323
+ context.eval("let a='testing';")
324
+ context.dispose
325
+ context.eval("a = 2")
326
+ # MiniRacer::ContextDisposedError
327
+
328
+ # nothing works on the context from now on, its a shell waiting to be disposed
329
+ ```
330
+
331
+ A MiniRacer context can also be dumped in a heapsnapshot file using `#write_heap_snapshot(file_or_io)`
332
+
333
+ ```ruby
334
+ context = MiniRacer::Context.new(timeout: 5)
335
+ context.eval("let a='testing';")
336
+ context.write_heap_snapshot("test.heapsnapshot")
337
+ ```
338
+
339
+ This file can then be loaded in the memory tab of the chrome dev console.
340
+
341
+ ### Function call
342
+
343
+ This calls the function passed as first argument:
344
+
345
+ ```ruby
346
+ context = MiniRacer::Context.new
347
+ context.eval('function hello(name) { return "Hello, " + name + "!" }')
348
+ context.call('hello', 'George')
349
+ # "Hello, George!"
350
+ ```
351
+
352
+ Performance is slightly better than running `eval('hello("George")')` since:
353
+
354
+ - compilation of eval'd string is avoided
355
+ - function arguments don't need to be converted to JSON
356
+
84
357
  ## Performance
85
358
 
86
359
  The `bench` folder contains benchmark.
87
360
 
88
361
  ### Benchmark minification of Discourse application.js (both minified and unminified)
89
362
 
90
- - MiniRacer version 0.1 (unreleased)
363
+ MiniRacer outperforms node when minifying assets via execjs.
364
+
365
+ - MiniRacer version 0.1.9
366
+ - node version 6.10
91
367
  - therubyracer version 0.12.2
92
368
 
93
- ```
94
- $ ruby bench_uglify.rb
95
- Benching with MiniRacer
96
- MiniRacer minify discourse_app.js 13813.36ms
97
- MiniRacer minify discourse_app_minified.js 18271.19ms
98
- MiniRacer minify discourse_app.js twice (2 threads) 13587.21ms
99
369
  ```
100
370
 
101
- ```
371
+ $ bundle exec ruby bench.rb mini_racer
372
+ Benching with mini_racer
373
+ mini_racer minify discourse_app.js 9292.72063ms
374
+ mini_racer minify discourse_app_minified.js 11799.850171ms
375
+ mini_racer minify discourse_app.js twice (2 threads) 10269.570797ms
376
+
377
+ sam@ubuntu exec_js_uglify % bundle exec ruby bench.rb node
378
+ Benching with node
379
+ node minify discourse_app.js 13302.715484ms
380
+ node minify discourse_app_minified.js 18100.761243ms
381
+ node minify discourse_app.js twice (2 threads) 14383.600207000001ms
382
+
383
+ sam@ubuntu exec_js_uglify % bundle exec ruby bench.rb therubyracer
102
384
  Benching with therubyracer
103
- MiniRacer minify discourse_app.js 151467.164ms
104
- MiniRacer minify discourse_app_minified.js 158172.097ms
105
- MiniRacer minify discourse_app.js twice (2 threads) - DOES NOT FINISH
385
+ therubyracer minify discourse_app.js 171683.01867700001ms
386
+ therubyracer minify discourse_app_minified.js 143138.88492ms
387
+ therubyracer minify discourse_app.js twice (2 threads) NEVER FINISH
106
388
 
107
389
  Killed: 9
108
390
  ```
@@ -111,6 +393,12 @@ The huge performance disparity (MiniRacer is 10x faster) is due to MiniRacer run
111
393
 
112
394
  Note how the global interpreter lock release leads to 2 threads doing the same work taking the same wall time as 1 thread.
113
395
 
396
+ As a rule MiniRacer strives to always support and depend on the latest stable version of libv8.
397
+
398
+ ## Source Maps
399
+
400
+ MiniRacer can fully support source maps but must be configured correctly to do so. [Check out this example](./examples/source-map-support/) for a working implementation.
401
+
114
402
  ## Installation
115
403
 
116
404
  Add this line to your application's Gemfile:
@@ -128,18 +416,32 @@ Or install it yourself as:
128
416
  $ gem install mini_racer
129
417
 
130
418
 
131
- **Note** using v8.h and compiling MiniRacer requires a C++11 standard compiler, more specifically clang 3.5 (or later) or gcc 4.8 (or later).
419
+ **Note** using v8.h and compiling MiniRacer requires a C++11 standard compiler, more specifically clang 3.5 (or later) or GCC 6.3 (or later).
420
+
421
+
422
+ ## Travis-ci
423
+
424
+ To install `mini-racer` you will need a version of GCC that supports C++11 (GCC 6.3) this is included by default in ubuntu trusty based images.
425
+
426
+ Travis today ships by default with a precise based image. Precise Pangolin (12.04 LTS) was first released in August 2012. Even though you can install GCC 6.3 on precise the simpler approach is to opt for the trusty based image.
427
+
428
+ Add this to your .travis.yml file:
429
+
430
+ ```
431
+ - sudo: required
432
+ - dist: trusty
433
+ ```
132
434
 
133
435
  ## Similar Projects
134
436
 
135
- ###therubyracer
437
+ ### therubyracer
136
438
 
137
439
  - https://github.com/cowboyd/therubyracer
138
440
  - Most comprehensive bridge available
139
441
  - Provides the ability to "eval" JavaScript
140
442
  - Provides the ability to invoke Ruby code from JavaScript
141
- - Hold refrences to JavaScript objects and methods in your Ruby code
142
- - Hold refrences to Ruby objects and methods in JavaScript code
443
+ - Hold references to JavaScript objects and methods in your Ruby code
444
+ - Hold references to Ruby objects and methods in JavaScript code
143
445
  - Uses libv8, so installation is fast
144
446
  - Supports timeouts for JavaScript execution
145
447
  - Does not release global interpreter lock, so performance is constrained to a single thread
@@ -147,7 +449,7 @@ Or install it yourself as:
147
449
  - Supports execjs
148
450
 
149
451
 
150
- ###v8eval
452
+ ### v8eval
151
453
 
152
454
  - https://github.com/sony/v8eval
153
455
  - Provides the ability to "eval" JavaScript using the latest V8 engine
@@ -160,7 +462,7 @@ Or install it yourself as:
160
462
  - No support for execjs (can not be used with Rails uglifier and coffeescript gems)
161
463
 
162
464
 
163
- ###therubyrhino
465
+ ### therubyrhino
164
466
 
165
467
  - https://github.com/cowboyd/therubyrhino
166
468
  - API compatible with therubyracer
@@ -173,7 +475,7 @@ Or install it yourself as:
173
475
 
174
476
  ## Contributing
175
477
 
176
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/mini_racer. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
478
+ Bug reports and pull requests are welcome on GitHub at https://github.com/rubyjs/mini_racer. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
177
479
 
178
480
 
179
481
  ## License
data/Rakefile CHANGED
@@ -11,11 +11,28 @@ end
11
11
  task :default => [:compile, :test]
12
12
 
13
13
  gem = Gem::Specification.load( File.dirname(__FILE__) + '/mini_racer.gemspec' )
14
+ Rake::ExtensionTask.new( 'mini_racer_loader', gem )
14
15
  Rake::ExtensionTask.new( 'mini_racer_extension', gem )
15
16
 
16
17
 
17
18
  # via http://blog.flavorjon.es/2009/06/easily-valgrind-gdb-your-ruby-c.html
18
19
  namespace :test do
20
+ desc "run test suite with Address Sanitizer"
21
+ task :asan do
22
+ ENV["CONFIGURE_ARGS"] = [ENV["CONFIGURE_ARGS"], '--enable-asan'].compact.join(' ')
23
+ Rake::Task['compile'].invoke
24
+
25
+ asan_path = `ldconfig -N -p |grep libasan | grep -v 32 | sed 's/.* => \\(.*\\)$/\\1/'`.chomp.split("\n")[-1]
26
+
27
+
28
+ cmdline = "env LD_PRELOAD=\"#{asan_path}\" ruby test/test_leak.rb"
29
+ puts cmdline
30
+ system cmdline
31
+
32
+ cmdline = "env LD_PRELOAD=\"#{asan_path}\" rake test"
33
+ puts cmdline
34
+ system cmdline
35
+ end
19
36
  # partial-loads-ok and undef-value-errors necessary to ignore
20
37
  # spurious (and eminently ignorable) warnings from the ruby
21
38
  # interpreter
@@ -52,3 +69,28 @@ namespace :test do
52
69
  end
53
70
  end
54
71
  end
72
+
73
+ desc 'run clang-tidy linter on mini_racer_extension.cc'
74
+ task :lint do
75
+ require 'mkmf'
76
+ require 'libv8'
77
+
78
+ Libv8.configure_makefile
79
+
80
+ conf = RbConfig::CONFIG.merge('hdrdir' => $hdrdir.quote, 'srcdir' => $srcdir.quote,
81
+ 'arch_hdrdir' => $arch_hdrdir.quote,
82
+ 'top_srcdir' => $top_srcdir.quote)
83
+ if $universal and (arch_flag = conf['ARCH_FLAG']) and !arch_flag.empty?
84
+ conf['ARCH_FLAG'] = arch_flag.gsub(/(?:\G|\s)-arch\s+\S+/, '')
85
+ end
86
+
87
+ checks = %W(bugprone-*
88
+ cert-*
89
+ cppcoreguidelines-*
90
+ clang-analyzer-*
91
+ performance-*
92
+ portability-*
93
+ readability-*).join(',')
94
+
95
+ sh RbConfig::expand("clang-tidy -checks='#{checks}' ext/mini_racer_extension/mini_racer_extension.cc -- #$INCFLAGS #$CXXFLAGS", conf)
96
+ end
@@ -1,32 +1,78 @@
1
1
  require 'mkmf'
2
- require 'libv8'
2
+ require_relative '../../lib/mini_racer/version'
3
+ gem 'libv8-node', MiniRacer::LIBV8_NODE_VERSION
4
+ require 'libv8-node'
5
+
6
+ IS_DARWIN = RUBY_PLATFORM =~ /darwin/
3
7
 
4
8
  have_library('pthread')
5
- have_library('objc') if RUBY_PLATFORM =~ /darwin/
6
- $CPPFLAGS += " -Wall" unless $CPPFLAGS.split.include? "-Wall"
7
- $CPPFLAGS += " -g" unless $CPPFLAGS.split.include? "-g"
8
- $CPPFLAGS += " -rdynamic" unless $CPPFLAGS.split.include? "-rdynamic"
9
- $CPPFLAGS += " -fPIC" unless $CPPFLAGS.split.include? "-rdynamic" or RUBY_PLATFORM =~ /darwin/
10
- $CPPFLAGS += " -std=c++0x"
11
- $CPPFLAGS += " -fpermissive"
9
+ have_library('objc') if IS_DARWIN
10
+ $CXXFLAGS += " -Wall" unless $CXXFLAGS.split.include? "-Wall"
11
+ $CXXFLAGS += " -g" unless $CXXFLAGS.split.include? "-g"
12
+ $CXXFLAGS += " -rdynamic" unless $CXXFLAGS.split.include? "-rdynamic"
13
+ $CXXFLAGS += " -fPIC" unless $CXXFLAGS.split.include? "-rdynamic" or IS_DARWIN
14
+ $CXXFLAGS += " -std=c++14"
15
+ $CXXFLAGS += " -fpermissive"
16
+ #$CXXFLAGS += " -DV8_COMPRESS_POINTERS"
17
+ $CXXFLAGS += " -fvisibility=hidden "
18
+
19
+ # __declspec gets used by clang via ruby 3.x headers...
20
+ $CXXFLAGS += " -fms-extensions"
21
+
22
+ $CXXFLAGS += " -Wno-reserved-user-defined-literal" if IS_DARWIN
23
+
24
+ if IS_DARWIN
25
+ $LDFLAGS.insert(0, " -stdlib=libc++ ")
26
+ else
27
+ $LDFLAGS.insert(0, " -lstdc++ ")
28
+ end
12
29
 
13
- $LDFLAGS.insert 0, " -stdlib=libstdc++ " if RUBY_PLATFORM =~ /darwin/
30
+ # check for missing symbols at link time
31
+ # $LDFLAGS += " -Wl,--no-undefined " unless IS_DARWIN
32
+ # $LDFLAGS += " -Wl,-undefined,error " if IS_DARWIN
14
33
 
15
34
  if ENV['CXX']
16
35
  puts "SETTING CXX"
17
36
  CONFIG['CXX'] = ENV['CXX']
18
37
  end
19
38
 
20
- CONFIG['LDSHARED'] = '$(CXX) -shared' unless RUBY_PLATFORM =~ /darwin/
39
+ CXX11_TEST = <<EOS
40
+ #if __cplusplus <= 199711L
41
+ # error A compiler that supports at least C++11 is required in order to compile this project.
42
+ #endif
43
+ EOS
44
+
45
+ `echo "#{CXX11_TEST}" | #{CONFIG['CXX']} -std=c++0x -x c++ -E -`
46
+ unless $?.success?
47
+ warn <<EOS
48
+
49
+
50
+ WARNING: C++11 support is required for compiling mini_racer. Please make sure
51
+ you are using a compiler that supports at least C++11. Examples of such
52
+ compilers are GCC 4.7+ and Clang 3.2+.
53
+
54
+ If you are using Travis, consider either migrating your build to Ubuntu Trusty or
55
+ installing GCC 4.8. See mini_racer's README.md for more information.
56
+
57
+
58
+ EOS
59
+ end
60
+
61
+ CONFIG['LDSHARED'] = '$(CXX) -shared' unless IS_DARWIN
21
62
  if CONFIG['warnflags']
22
63
  CONFIG['warnflags'].gsub!('-Wdeclaration-after-statement', '')
23
64
  CONFIG['warnflags'].gsub!('-Wimplicit-function-declaration', '')
24
65
  end
25
66
 
26
- if enable_config('debug')
67
+ if enable_config('debug') || enable_config('asan')
27
68
  CONFIG['debugflags'] << ' -ggdb3 -O0'
28
69
  end
29
70
 
30
- Libv8.configure_makefile
71
+ Libv8::Node.configure_makefile
72
+
73
+ if enable_config('asan')
74
+ $CXXFLAGS.insert(0, " -fsanitize=address ")
75
+ $LDFLAGS.insert(0, " -fsanitize=address ")
76
+ end
31
77
 
32
78
  create_makefile 'mini_racer_extension'