execjs-xtrn 1.1.3 → 1.1.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7006a7dbaff18583232a21dec541ac5aabbe990c
4
- data.tar.gz: 87fa10ad61fb6be63aca1f564c31d6bbad3de260
3
+ metadata.gz: c96df8410557171dfaf3c5943b31f5b098b2f8a8
4
+ data.tar.gz: 24ca85d50e1bdf4c7945385849bef1532091ae3e
5
5
  SHA512:
6
- metadata.gz: a69efc3cf4ac48d7dbd419fc11e36d456edb08f314c826b23890d0fa31e155f5167fa712b9517d6b66f74f6c095e1d6f0b2292b45978bcebda58382bf034cdca
7
- data.tar.gz: bbd08a8d11fcd3f8e6c341f8488ce31f8b791247ecf0ba8345f71b52acf3cd7f7d2cf00234345440d37b42ede81e67b2e36bc9cd03e1444acdcff5d195eb4df9
6
+ metadata.gz: ffb757e3b1d4f256916646dfa1139186da502e43ac277fc0b03342bd65dc2ad16c5ccc3367dec0b52d46fe78626e4cf6113eac5049ba7cd375093febdf62da56
7
+ data.tar.gz: 12426082a20e85dd543483f50d2535696bbb2ea072217f7b42d12aae45640bd9d647d72886478cca17d22985d54f60c9c9985b14e74b8911ea1f8500c9a629bb
@@ -0,0 +1,63 @@
1
+ //filter will reemit the data if cb(err,pass) pass is truthy
2
+
3
+ // reduce is more tricky
4
+ // maybe we want to group the reductions or emit progress updates occasionally
5
+ // the most basic reduce just emits one 'data' event after it has recieved 'end'
6
+
7
+
8
+ var through = require('through')
9
+ var Decoder = require('string_decoder').StringDecoder
10
+
11
+ module.exports = split
12
+
13
+ //TODO pass in a function to map across the lines.
14
+
15
+ function split (matcher, mapper, options) {
16
+ var decoder = new Decoder()
17
+ var soFar = ''
18
+ var maxLength = options && options.maxLength;
19
+ if('function' === typeof matcher)
20
+ mapper = matcher, matcher = null
21
+ if (!matcher)
22
+ matcher = /\r?\n/
23
+
24
+ function emit(stream, piece) {
25
+ if(mapper) {
26
+ try {
27
+ piece = mapper(piece)
28
+ }
29
+ catch (err) {
30
+ return stream.emit('error', err)
31
+ }
32
+ if('undefined' !== typeof piece)
33
+ stream.queue(piece)
34
+ }
35
+ else
36
+ stream.queue(piece)
37
+ }
38
+
39
+ function next (stream, buffer) {
40
+ var pieces = ((soFar != null ? soFar : '') + buffer).split(matcher)
41
+ soFar = pieces.pop()
42
+
43
+ if (maxLength && soFar.length > maxLength)
44
+ stream.emit('error', new Error('maximum buffer reached'))
45
+
46
+ for (var i = 0; i < pieces.length; i++) {
47
+ var piece = pieces[i]
48
+ emit(stream, piece)
49
+ }
50
+ }
51
+
52
+ return through(function (b) {
53
+ next(this, decoder.write(b))
54
+ },
55
+ function () {
56
+ if(decoder.end)
57
+ next(this, decoder.end())
58
+ if(soFar != null)
59
+ emit(this, soFar)
60
+ this.queue(null)
61
+ })
62
+ }
63
+
@@ -0,0 +1,108 @@
1
+ var Stream = require('stream')
2
+
3
+ // through
4
+ //
5
+ // a stream that does nothing but re-emit the input.
6
+ // useful for aggregating a series of changing but not ending streams into one stream)
7
+
8
+ exports = module.exports = through
9
+ through.through = through
10
+
11
+ //create a readable writable stream.
12
+
13
+ function through (write, end, opts) {
14
+ write = write || function (data) { this.queue(data) }
15
+ end = end || function () { this.queue(null) }
16
+
17
+ var ended = false, destroyed = false, buffer = [], _ended = false
18
+ var stream = new Stream()
19
+ stream.readable = stream.writable = true
20
+ stream.paused = false
21
+
22
+ // stream.autoPause = !(opts && opts.autoPause === false)
23
+ stream.autoDestroy = !(opts && opts.autoDestroy === false)
24
+
25
+ stream.write = function (data) {
26
+ write.call(this, data)
27
+ return !stream.paused
28
+ }
29
+
30
+ function drain() {
31
+ while(buffer.length && !stream.paused) {
32
+ var data = buffer.shift()
33
+ if(null === data)
34
+ return stream.emit('end')
35
+ else
36
+ stream.emit('data', data)
37
+ }
38
+ }
39
+
40
+ stream.queue = stream.push = function (data) {
41
+ // console.error(ended)
42
+ if(_ended) return stream
43
+ if(data === null) _ended = true
44
+ buffer.push(data)
45
+ drain()
46
+ return stream
47
+ }
48
+
49
+ //this will be registered as the first 'end' listener
50
+ //must call destroy next tick, to make sure we're after any
51
+ //stream piped from here.
52
+ //this is only a problem if end is not emitted synchronously.
53
+ //a nicer way to do this is to make sure this is the last listener for 'end'
54
+
55
+ stream.on('end', function () {
56
+ stream.readable = false
57
+ if(!stream.writable && stream.autoDestroy)
58
+ process.nextTick(function () {
59
+ stream.destroy()
60
+ })
61
+ })
62
+
63
+ function _end () {
64
+ stream.writable = false
65
+ end.call(stream)
66
+ if(!stream.readable && stream.autoDestroy)
67
+ stream.destroy()
68
+ }
69
+
70
+ stream.end = function (data) {
71
+ if(ended) return
72
+ ended = true
73
+ if(arguments.length) stream.write(data)
74
+ _end() // will emit or queue
75
+ return stream
76
+ }
77
+
78
+ stream.destroy = function () {
79
+ if(destroyed) return
80
+ destroyed = true
81
+ ended = true
82
+ buffer.length = 0
83
+ stream.writable = stream.readable = false
84
+ stream.emit('close')
85
+ return stream
86
+ }
87
+
88
+ stream.pause = function () {
89
+ if(stream.paused) return
90
+ stream.paused = true
91
+ return stream
92
+ }
93
+
94
+ stream.resume = function () {
95
+ if(stream.paused) {
96
+ stream.paused = false
97
+ stream.emit('resume')
98
+ }
99
+ drain()
100
+ //may have become paused again,
101
+ //as drain emits 'data'.
102
+ if(!stream.paused)
103
+ stream.emit('drain')
104
+ return stream
105
+ }
106
+ return stream
107
+ }
108
+
@@ -1,5 +1,5 @@
1
1
  module ExecJS
2
2
  module Xtrn
3
- VERSION = "1.1.3"
3
+ VERSION = "1.1.4"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: execjs-xtrn
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.3
4
+ version: 1.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stas Ukolov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-08-19 00:00:00.000000000 Z
11
+ date: 2016-08-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json
@@ -115,15 +115,6 @@ executables: []
115
115
  extensions: []
116
116
  extra_rdoc_files: []
117
117
  files:
118
- - ".gitignore"
119
- - ".travis.yml"
120
- - FarMenu.ini
121
- - Gemfile
122
- - LICENSE.txt
123
- - README.md
124
- - Rakefile
125
- - appveyor.yml
126
- - execjs-xtrn.gemspec
127
118
  - lib/execjs/node/index.js
128
119
  - lib/execjs/node/node_modules/split/index.js
129
120
  - lib/execjs/node/node_modules/through/index.js
@@ -141,12 +132,6 @@ files:
141
132
  - lib/execjs/xtrn/routing.rb
142
133
  - lib/execjs/xtrn/version.rb
143
134
  - lib/execjs/xtrn/wsh.rb
144
- - test/child.rb
145
- - test/engine.rb
146
- - test/load.js
147
- - test/nvm.rb
148
- - test/shagi.rb
149
- - test/top.rb
150
135
  homepage: https://github.com/ukoloff/execjs-xtrn
151
136
  licenses:
152
137
  - MIT
@@ -171,10 +156,4 @@ rubygems_version: 2.2.3
171
156
  signing_key:
172
157
  specification_version: 4
173
158
  summary: 'Proof-of-concept: make ExecJS fast even without therubyracer'
174
- test_files:
175
- - test/child.rb
176
- - test/engine.rb
177
- - test/load.js
178
- - test/nvm.rb
179
- - test/shagi.rb
180
- - test/top.rb
159
+ test_files: []
data/.gitignore DELETED
@@ -1,18 +0,0 @@
1
- *.gem
2
- *.rbc
3
- .bundle
4
- .config
5
- .yardoc
6
- Gemfile.lock
7
- InstalledFiles
8
- _yardoc
9
- coverage
10
- doc/
11
- lib/bundler/man
12
- pkg
13
- rdoc
14
- spec/reports
15
- test/tmp
16
- test/version_tmp
17
- tmp
18
- node_modules
@@ -1,19 +0,0 @@
1
- sudo: false
2
-
3
- language: ruby
4
-
5
- rvm:
6
- - '2.2'
7
- - '2.1'
8
- - '2.0'
9
- - 1.9.3
10
-
11
- env:
12
- - NODEV=node
13
- - NODEV=0
14
-
15
- install:
16
- - nvm install $NODEV
17
- - gem install bundler
18
- - bundle install
19
- - bundle exec rake npm
@@ -1,11 +0,0 @@
1
- I: Install dependencies
2
- bundle install
3
- bundle exec rake npm
4
- --:
5
- T: Run tests
6
- bundle exec rake -new_console:c
7
- C: Console
8
- bundle console -new_console
9
- --:
10
- B: Build
11
- bundle exec rake build -new_console:c
data/Gemfile DELETED
@@ -1,6 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- # Specify your gem's dependencies in execjs-xtrn.gemspec
4
- gemspec
5
-
6
- gem 'json', "#{/^1[.]/.match(RUBY_VERSION)? '~>' : '>='} 1.8"
@@ -1,22 +0,0 @@
1
- Copyright (c) 2014 Stas Ukolov
2
-
3
- MIT License
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining
6
- a copy of this software and associated documentation files (the
7
- "Software"), to deal in the Software without restriction, including
8
- without limitation the rights to use, copy, modify, merge, publish,
9
- distribute, sublicense, and/or sell copies of the Software, and to
10
- permit persons to whom the Software is furnished to do so, subject to
11
- the following conditions:
12
-
13
- The above copyright notice and this permission notice shall be
14
- included in all copies or substantial portions of the Software.
15
-
16
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md DELETED
@@ -1,235 +0,0 @@
1
- # ExecJS::Xtrn
2
-
3
- [![Build Status](https://travis-ci.org/ukoloff/execjs-xtrn.svg?branch=master)](https://travis-ci.org/ukoloff/execjs-xtrn)
4
- [![Build status](https://ci.appveyor.com/api/projects/status/tw7av89nj591fg8w?svg=true)](https://ci.appveyor.com/project/ukoloff/execjs-xtrn)
5
- [![Gem Version](https://badge.fury.io/rb/execjs-xtrn.svg)](http://badge.fury.io/rb/execjs-xtrn)
6
-
7
- Drop-in replacement for ExecJS. The latter spawns separate process for every JavaScript compilation
8
- (when using external runtime),
9
- while ExecJS::Xtrn spawn long running JavaScript process and communicates with it via stdin & stderr.
10
-
11
- This is just proof of concept, not suitable for production.
12
-
13
- When not on MS Windows, one definitely should use ExecJS with excellent `therubyracer` gem instead.
14
-
15
- ## Installation
16
-
17
- Add this line to your application's Gemfile:
18
-
19
- gem 'execjs-xtrn'
20
-
21
- And then execute:
22
-
23
- $ bundle
24
-
25
- Or install it yourself as:
26
-
27
- $ gem install execjs-xtrn
28
-
29
- ## Usage
30
-
31
- Just add/require this gem after/instead (implicit) `execjs` gem.
32
- The latter will be monkey-patched.
33
-
34
- ## Engines
35
-
36
- ExecJS::Xtrn uses two external JavaScript runners:
37
-
38
- * Windows Script Host
39
- * Node.js in two modes:
40
- - Simple (1 execution context = 1 external process)
41
- - Nvm (all execution contexts share single external process using [vm API](http://nodejs.org/api/vm.html))
42
-
43
- Nvm engine has nothing common with [nvm](https://github.com/creationix/nvm).
44
-
45
- So, there exist *four* engines:
46
-
47
- * Engine - absctract engine (smart enough to execute blank lines)
48
- * Wsh - engine using WSH (CScript)
49
- * Node - engine using Node.js (separate process for every execution context)
50
- * Nvm - engine using Node.js and vm API (single process)
51
-
52
- All engines autodetect their availability at startup (on `require 'execjs/xtrn'`) and sets `Valid` constants.
53
- Eg on MS Windows ExecJS::Xtrn::Wsh::Valid = true, on Linux - false
54
-
55
- One of available engines is made default engine for ExecJS.
56
- If Node.js is available it is Nvm.
57
- Else, if running on Windows it is Wsh.
58
- Else it is Engine, so ExecJS is made unusable.
59
-
60
- Default engine can be shown/changed at any moment with `ExecJS::Xtrn.engine` accessor, eg
61
-
62
- ```ruby
63
- ExecJS::Xtrn.engine=ExecJS::Xtrn::Node
64
- ```
65
-
66
- ## API
67
-
68
- ExecJS::Xtrn is primarily designed to power other gems that use popular ExecJS.
69
-
70
- But it has his own API (similar to ExecJS' API) and can be used itself.
71
-
72
- In general one should create instance of an Engine and then feed it with JavaScript code:
73
-
74
- ```ruby
75
- ctx=ExecJS::Xtrn::Wsh.new
76
- ctx.exec 'fact = function(n){return n>1 ? n*fact(n-1) : 1}'
77
- puts "10! = #{ctx.call 'fact', 10}"
78
- ```
79
- Every execution context has four methods:
80
- * exec(`code`) - executes arbitrary JavaScript code. To get result `return` must be called
81
- * load(`code`) or load(`path`) - exec that can load its code from file
82
- * eval(`expression`) - evaluate JavaScript expression. `return` is not needed
83
- * call(`function`, arguments...) - special form of eval for function call
84
-
85
- There are `exec` and `eval` methods in Engine class,
86
- they just create brand new execution context,
87
- pass argument to it, destroy that context and return its result.
88
- Using these class methods is not recommended, since it's just what ExecJS does
89
- (except for Nvm engine).
90
-
91
- Engine class also has `compile` method that combines `new` and `exec`
92
- and returns execution context.
93
- This is how ExecJS is used in most cases.
94
-
95
- ```ruby
96
- ctx=ExecJS::Xtrn::Wsh.compile 'fact = function(n){return n>1 ? n*fact(n-1) : 1}'
97
- puts "10! = #{ctx.call 'fact', 10}"
98
- ```
99
- And `load` methods is likewise combination of `new`+`load`,
100
- it is `compile` that can load its code from file.
101
-
102
- `load` method (class' or instance's) detects whether its argument
103
- is code or path by first symbols of it. So, start path with `/`, `./`
104
- or `../` (but not from `//`). On Windows `\` and `C:` can be also used.
105
-
106
- Finally ExecJS::Xtrn patches ExecJS and installs those 4 class methods
107
- (`exec`, `eval`, `compile` and `load`) in it.
108
- So, `ExecJS.compile` is `ExecJS::Xtrn::Nvm.compile` if Nvm engine is available.
109
-
110
- ## Preloading
111
-
112
- Sometimes it's neccesary to initialize all execution contexts before passing
113
- code to them.
114
- For instance, add some standard JavaScript methods missing in Wsh engine.
115
-
116
- It can be done by setting Preload constant on engine class.
117
-
118
- ```ruby
119
- ExecJS::Xtrn::Wsh::Preload='./lib/js/map.js'
120
- ```
121
- or maybe
122
-
123
- ```ruby
124
- ExecJS::Xtrn::Wsh::Preload=[
125
- './lib/js/map.js',
126
- './lib/js/keys.js',
127
- 'console={log: function(){WScript.Echo([].slice.call(arguments).join(" "))}}'
128
- ]
129
- # Yes, console.log is avaialable in Wsh now!
130
- # And yes, console.log can be used in ExecJS::Xtrn!
131
- ```
132
- You can add preload scripts to any engine or to Engine base class.
133
- They will be loaded according to inheritance:
134
- Engine::Preload will be used by all engines,
135
- Node::Preload is for Node and Nvm, while Nvm::Preload is for Nvm only.
136
-
137
- ## Overriding ExecJS
138
-
139
- Sometimes ExecJS is required after ExecJS::Xtrn. In that case you can call ExecJS::Xtrn.init and
140
- it will overwrite ExecJS' methods again.
141
-
142
- To test whether JavaScript is served by ExecJS::Xtrn, it's convenient to look at ExecJS::Xtrn statistics.
143
-
144
- ## Statistics
145
-
146
- Every engine gathers it's own usage statistics. Eg:
147
-
148
- ```ruby
149
- > ExecJS::Xtrn::Node.stats # or ExecJS::Xtrn::Nvm.stats or ExecJS::Xtrn::Wsh.stats
150
- => {:c=>2, :n=>2, :o=>8, :i=>6, :t=>0.131013}
151
- ```
152
- Here:
153
- * c = number of child processes spawned (for Nvm c should always be 1)
154
- * n = number of request made
155
- * o = bytes sent to child process(es)
156
- * i = bytes got from child process(es)
157
- * t = seconds spent communicating with child process(es)
158
- * m = number of VMs created (Nvm only)
159
- * x = number of VMs destroyed (Nvm only)
160
-
161
- ExecJS::Xtrn.stats combines statistics for all its engines, even unused.
162
-
163
- ExecJS.stats shows statistics for current engine only.
164
-
165
- Every execution context has his own statistics too. Eg
166
-
167
- ```ruby
168
- s=ExecJS::Xtrn::Nvm.compile '...'
169
- s.exec '...'
170
- s.stats
171
- ```
172
- but c (and m, x) fields are omitted there.
173
-
174
- If ExecJS::Xtrn detects it is run under Ruby on Rails,
175
- it installs additional path `/rails/jsx' to display its statistics
176
- (you can see that route in sextant, for example).
177
-
178
- It is one more reason not to use ExecJS::Xtrn in production mode ;-)
179
-
180
- By default statistics is output in YAML format, but you can
181
- get `/rails/jsx.json` or `/rails/jsx.html`.
182
-
183
- ## Compatibilty
184
-
185
- Not every JavaScript code behaves identically in ExecJS and ExecJS::Xtrn. In most cases it depends on how
186
- global JavaScript variables are used. For most modern code it is the same though.
187
-
188
- As a rule of thumb, JavaScript code must survive after wrapping in anonymous function (`(function(){...})()`).
189
-
190
- For instance, old versions of `handlebars_assets` didn't work
191
- in ExecJS::Xtrn (and worked in ExecJS).
192
-
193
- The following packages have been tested to run under ExecJS::Xtrn out-of-box:
194
-
195
- * [CoffeeScript](http://coffeescript.org/) via [coffee-script](https://rubygems.org/gems/coffee-script) and [coffee-rails](https://rubygems.org/gems/coffee-rails) gems
196
- * [UglifyJS2](https://github.com/mishoo/UglifyJS2) via [uglifier](https://github.com/lautis/uglifier)
197
- * [Handlebars](http://handlebarsjs.com/) via [handlebars_assets](https://github.com/leshill/handlebars_assets) gem
198
-
199
- CoffeeScript since v1.9.0 introduces new incompatibility:
200
- it uses `Object.create` that is missing from WSH.
201
- To fix it, `Object.create` was manually defined in ExecJS::Xtrn::Wsh
202
- (sort of [ExecJS::Xtrn::Wsh::Preload](#preloading)).
203
- Path to this polyfill is available as `ExecJS::Xtrn::Wsh::ES5` constant.
204
-
205
- Gem [coffee-script](https://rubygems.org/gems/coffee-script) since v2.4.0 introduces another incompatibility:
206
- it silently creates global function. This approach works in regular ExecJS but fails in ExecJS::Xtrn.
207
- As a workaround pin `coffee-script` gem version to 2.3.0.
208
-
209
- Later [uglifier](https://github.com/lautis/uglifier) from v3 started to use globals either. Pin it to '~> 2'.
210
-
211
- ## Testing
212
-
213
- After git checkout, required NPM modules must be installed. Simply run:
214
-
215
- ```
216
- bundle install
217
- bundle exec rake npm
218
- ```
219
-
220
- The testing itself is
221
-
222
- ```
223
- bundle exec rake
224
- ```
225
-
226
- And `bundle exec` may be ommited in most cases.
227
-
228
- ## Credits
229
-
230
- * [ExecJS](https://github.com/sstephenson/execjs)
231
- * [therubyracer](https://github.com/cowboyd/therubyracer)
232
- * [Node.js](http://nodejs.org/)
233
- * [Windows Script Host](http://en.wikipedia.org/wiki/Windows_Script_Host)
234
- * [Travis CI](https://travis-ci.org/)
235
- * [AppVeyor](http://www.appveyor.com/)
data/Rakefile DELETED
@@ -1,17 +0,0 @@
1
- require "bundler/gem_tasks"
2
-
3
- desc 'Install NPM modules'
4
- task :npm do
5
- system "npm", "install", chdir: "lib/execjs/node"
6
- end
7
-
8
- desc 'Run tests'
9
- task :test do
10
- require "minitest/autorun"
11
-
12
- require 'execjs/xtrn'
13
-
14
- Dir.glob('./test/*.rb'){|f| require f}
15
- end
16
-
17
- task default: :test
@@ -1,36 +0,0 @@
1
- version: 1.0.{build}-{branch}
2
-
3
- cache:
4
- - vendor/bundle
5
-
6
- environment:
7
- matrix:
8
- - RUBY_VERSION: 23
9
- - RUBY_VERSION: 22
10
- - RUBY_VERSION: 21
11
- - RUBY_VERSION: 200
12
- - RUBY_VERSION: 193
13
-
14
- install:
15
- - set PATH=C:\Ruby%RUBY_VERSION%\bin;%PATH%
16
- - bundle config --local path vendor/bundle
17
- - bundle install
18
- - bundle exec rake npm
19
-
20
- build: off
21
-
22
- before_test:
23
- - ruby -v
24
- - gem -v
25
- - bundle -v
26
- - node -v
27
-
28
- test_script:
29
- - bundle exec rake
30
-
31
- after_test:
32
- - bundle exec rake build
33
-
34
- artifacts:
35
- - path: pkg/*.gem
36
- name: Gem
@@ -1,30 +0,0 @@
1
- # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
3
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'execjs/xtrn/version'
5
-
6
- Gem::Specification.new do |spec|
7
- spec.name = "execjs-xtrn"
8
- spec.version = ExecJS::Xtrn::VERSION
9
- spec.authors = ["Stas Ukolov"]
10
- spec.email = ["ukoloff@gmail.com"]
11
- spec.description = "Drop-in replacement for ExecJS with persistent external runtime"
12
- spec.summary = "Proof-of-concept: make ExecJS fast even without therubyracer"
13
- spec.homepage = "https://github.com/ukoloff/execjs-xtrn"
14
- spec.license = "MIT"
15
-
16
- spec.files = `git ls-files`.split($/)+
17
- Dir.glob('**/node_modules/*/*.js')
18
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
- spec.require_paths = ["lib"]
21
-
22
- spec.add_dependency "json"
23
-
24
- spec.add_development_dependency "bundler", "~> 1.3"
25
- spec.add_development_dependency "rake"
26
- spec.add_development_dependency "minitest"
27
- spec.add_development_dependency "coffee-script", '2.3.0'
28
- spec.add_development_dependency "uglifier", '~> 2'
29
- spec.add_development_dependency "appveyor-worker"
30
- end
@@ -1,32 +0,0 @@
1
- require_relative 'shagi'
2
-
3
- class TestChild < Shagi
4
-
5
- Children=[M::Node, M::Wsh]
6
-
7
- def say(code)
8
- @child.say code
9
- end
10
-
11
- def children
12
- (1..Spawn).map do
13
- Children.map{|k| k::Valid ? M::Child.new(k::Run) : nil }
14
- end
15
- end
16
-
17
- def self.build
18
- ancestors[1].instance_methods(false).grep(/^shag_/).each do |m|
19
- Children.each_with_index do |klass, idx|
20
- (1..Spawn).each do |n|
21
- define_method("test_#{m.to_s.sub(/.*?_/, '')}_#{klass.name.split(/\W+/).last}_#{n}")do
22
- skip unless @child=(@@children||=children)[n-1][idx]
23
- send m
24
- end
25
- end
26
- end
27
- end
28
- end
29
-
30
- build
31
-
32
- end
@@ -1,127 +0,0 @@
1
- require 'coffee_script/source'
2
-
3
- class TestEngine < Minitest::Test
4
-
5
- M=ExecJS::Xtrn
6
-
7
- Spawn=5
8
- Engines=M::Engines
9
- Engines.each{|e| e::Preload=[]}
10
- M::Engine::Preload=[]
11
-
12
- def shag_methods
13
- refute @engine.exec <<-EOJ
14
- fib = function(n)
15
- {
16
- return n<2 ? 1 : fib(n-1)+fib(n-2)
17
- }
18
- EOJ
19
- assert_equal 89, @engine.eval('fib(10)')
20
- assert_equal 8, @engine.call('fib', 5)
21
- assert_equal 79, @engine.call('Math.max', 44, 27, 79, 73, 42, 4, 23, 24, 36, 13)
22
-
23
- assert_raises(M::Error){ @engine.eval '_load' }
24
- @engine.load File.expand_path '../load.js', __FILE__
25
- assert_equal ({}), @engine.eval('_load')
26
- @engine.load '_load.a=108'
27
- assert_equal ({"a"=>108}), @engine.eval('_load')
28
- end
29
-
30
- def shag_vars
31
- assert_raises(M::Error){ @engine.eval 'localVar' }
32
- refute @engine.exec 'var localVar=1'
33
- assert_raises(M::Error){ @engine.eval 'localVar' }
34
-
35
- assert_raises(M::Error){ @engine.eval 'globalVar' }
36
- refute @engine.exec "globalVar=#{v=rand 1000}"
37
- assert_equal v, @engine.eval('globalVar')
38
- end
39
-
40
- def shag_coffee
41
- @engine.exec File.read CoffeeScript::Source.bundled_path
42
- assert_equal 3, @engine.call('CoffeeScript.compile', "->").split(/\Wfunction\W/).length
43
- r=rand 100
44
- assert_equal [r], @engine.eval(@engine.call 'CoffeeScript.compile', "do->[#{r}]", bare: true)
45
- assert_equal 3, @engine.call('CoffeeScript.eval', 'Math.round Math.PI')
46
- end
47
-
48
- def shag_stats
49
- @engine.exec '//'
50
- s=@engine.stats
51
- @engine.exec ' '
52
- assert_equal s[:n], @engine.stats[:n]
53
- @engine.exec '[]'
54
- assert_equal s[:n]+1, @engine.stats[:n]
55
- assert_equal 1, M::Nvm.stats[:c]||1
56
- end
57
-
58
- def klas_methods
59
- assert_equal 4, @class.exec('return 2*2')
60
- assert_equal 6, @class.eval('({x: 1+2+3}).x')
61
- end
62
-
63
- def klas_compile
64
- x=@class.compile <<-EOJ
65
- inc = function(x)
66
- {
67
- return x+1
68
- }
69
- EOJ
70
- assert_equal 6, x.call('inc', 5)
71
- end
72
-
73
- def klas_load
74
- z=@class.load File.expand_path '../load.js', __FILE__
75
- assert_equal ({}), z.eval('_load')
76
- end
77
-
78
- def klas_preload
79
- res=@class.name[-1]
80
- res='em' if 'm'==res
81
-
82
- Spawn.times do
83
- begin
84
- Engines.shuffle.each{|e| e::Preload << "_preload.#{e.name[-1]}=1"}
85
- M::Engine::Preload << '!function(){this._preload={}}()'
86
-
87
- assert_equal res, @class.eval('_preload').keys*''
88
-
89
- ensure
90
- Engines.each{|e| e::Preload.clear}
91
- M::Engine::Preload.clear
92
- end
93
- end
94
- end
95
-
96
- def engines
97
- (1..Spawn).map do
98
- Engines.map{|k| k::Valid ? k.compile : nil }
99
- end
100
- end
101
-
102
- def self.build
103
- instance_methods(false).grep(/^shag_/).each do |m|
104
- Engines.each_with_index do |klass, idx|
105
- (1..Spawn).each do |n|
106
- define_method("test_#{m.to_s.sub(/.*?_/, '')}_#{klass.name.split(/\W+/).last}_#{n}")do
107
- skip unless @engine=(@@engines||=engines)[n-1][idx]
108
- send m
109
- end
110
- end
111
- end
112
- end
113
-
114
- instance_methods(false).grep(/^klas_/).each do |m|
115
- Engines.each do |klass|
116
- define_method("test_#{m.to_s.sub(/.*?_/, '')}_#{klass.name.split(/\W+/).last}_class")do
117
- skip unless klass::Valid
118
- @class=klass
119
- send m
120
- end
121
- end
122
- end
123
- end
124
-
125
- build
126
-
127
- end
@@ -1,5 +0,0 @@
1
- // Test .load method
2
- !function()
3
- {
4
- this._load={}
5
- }()
@@ -1,33 +0,0 @@
1
- require_relative 'shagi'
2
-
3
- class TestNvm < Shagi
4
-
5
- Child=M::Nvm
6
-
7
- def say(code)
8
- @child.say vm: @vm, js: code
9
- end
10
-
11
- def buildVMs
12
- @@child=child=M::Child.new(Child::Run)
13
- (1..Spawn).map do
14
- child.say(vm: 0)['vm']
15
- end
16
- end
17
-
18
- def self.build
19
- ancestors[1].instance_methods(false).grep(/^shag_/).each do |m|
20
- (1..Spawn).each do |n|
21
- define_method("test_#{m.to_s.sub(/.*?_/, '')}_#{n}")do
22
- skip unless Child::Valid
23
- @vm=(@@vms||=buildVMs)[n-1]
24
- @child=@@child
25
- send m
26
- end
27
- end
28
- end
29
- end
30
-
31
- build
32
-
33
- end
@@ -1,81 +0,0 @@
1
- # encoding: utf-8
2
- class Shagi < Minitest::Test
3
-
4
- Spawn=5
5
- M=ExecJS::Xtrn
6
-
7
- def say(code)
8
- raise NotImplementedError, self.class.name
9
- end
10
-
11
- def assert_ok(result, code)
12
- r=say code
13
- refute r.key? 'err'
14
- assert_equal r, {'ok'=>result}
15
- end
16
-
17
- def assert_err(code)
18
- assert say(code)['err']
19
- end
20
-
21
- def shag_math
22
- assert_ok 42, 'return 6*7'
23
- assert_ok 3, 'return Math.round(Math.PI)'
24
- end
25
-
26
- Chars='Япония, 中华, Russia'
27
- Codes=[1071, 1087, 1086, 1085, 1080, 1103, 44, 32, 20013, 21326, 44, 32, 82, 117, 115, 115, 105, 97]
28
-
29
- def shag_intl
30
- assert_ok Codes, <<-EOJ
31
- var s='#{Chars}'
32
- var r=[]
33
- for(var i=0; i<s.length; i++) r.push(s.charCodeAt(i))
34
- return r
35
- EOJ
36
-
37
- assert_ok Chars, <<-EOJ
38
- var c=#{Codes}
39
- var s=''
40
- for(var i=0; i<c.length; i++) s+=String.fromCharCode(c[i])
41
- return s
42
- EOJ
43
- end
44
-
45
- def shag_error
46
- assert_err '#' # Syntax
47
- assert_err 'none' # Runtime
48
- assert_err false # Argument
49
- assert_err key: 2 # the same
50
- end
51
-
52
- def shag_null
53
- assert_equal say(''), {}
54
- assert_ok nil, 'return null'
55
- end
56
-
57
- def shag_vars
58
- assert_err 'localVar'
59
- say 'var localVar=1'
60
- assert_err 'localVar'
61
-
62
- assert_err 'globalVar'
63
- say "globalVar=#{v=rand 1000}"
64
- assert_ok v, 'return globalVar'
65
- end
66
-
67
- def shag_stats
68
- @child.stats r={}
69
- say '//'
70
- assert_equal r[:n], 1
71
- ri=@child.stats
72
- rc=@child.class.stats
73
- say ''
74
- assert_equal r[:n], 2
75
- assert_equal ri[:n]+1, @child.stats[:n]
76
- assert_equal rc[:n]+1, @child.class.stats[:n]
77
- [r, ri, rc].each{|rec| %w(i o t).each{|sym| assert rec[sym.to_sym]}}
78
- assert_operator rc[:c], :>, 0
79
- end
80
-
81
- end
@@ -1,97 +0,0 @@
1
- require 'coffee-script'
2
- require 'uglifier'
3
-
4
- ExecJS::Xtrn.init
5
-
6
- class TestTop < Minitest::Test
7
-
8
- def test_exec
9
- assert_equal 42, ExecJS.exec('return 6*7')
10
- end
11
-
12
- def test_eval
13
- assert_equal 42, ExecJS.eval('6*7')
14
- end
15
-
16
- def test_compile
17
- ctx=ExecJS.compile <<-EOJ
18
- dec = function(i)
19
- {
20
- return i-1
21
- }
22
- EOJ
23
- assert_equal 8, ctx.call('dec', 9)
24
- end
25
-
26
- def test_stats
27
- ctx=ExecJS.compile <<-EOJ
28
- summa = function(n)
29
- {
30
- var r=0
31
- for(var i = 1; i<=n; i++)
32
- {
33
- r+=i
34
- for(var t = ms() ; t>=ms(); );
35
- }
36
- return r
37
- }
38
- function ms()
39
- {
40
- return new Date().getTime()
41
- }
42
- EOJ
43
- s=ctx.stats
44
- %w(i o n t).each{|sym| assert s[sym.to_sym]}
45
- ctx.exec ' '
46
- assert_equal s, ctx.stats
47
- assert_equal 5050, ctx.call('summa', 100)
48
- assert_equal s[:n]+1, ctx.stats[:n]
49
- %w(i o t).each{|sym| assert_operator s[sym.to_sym], :<, ctx.stats[sym.to_sym]}
50
- end
51
-
52
- def test_coffee
53
- assert CoffeeScript.compile('->', header: true)[CoffeeScript.version]
54
- assert CoffeeScript.compile('a b c', bare: true)['a(b(c))']
55
- end
56
-
57
- def test_uglify
58
- u=Uglifier.new
59
- assert u.compile('a( 1 + 2 * 3 )')['a(7)']
60
- assert u.compile('b( 1 ? x : y )')['b(x)']
61
- end
62
-
63
- def test_switch
64
- assert_equal 42, ExecJS.eval('7*6')
65
- e=ExecJS::Xtrn.engine
66
- ExecJS::Xtrn.engine=FakeEngine
67
- assert_equal 1, ExecJS.exec('A')
68
- assert_equal 2, ExecJS.eval('B')
69
- assert_equal 4, ExecJS.compile.eval('C')
70
- ExecJS::Xtrn.engine=e
71
- assert_equal 42, ExecJS.eval('21*2')
72
- end
73
-
74
- def test_info
75
- at_exit do
76
- puts "Statistics:"
77
- s=ExecJS::Xtrn.stats
78
- len=s.keys.map(&:length).max+1
79
- z = s.map do |k, v|
80
- "#{' '*(len-k.length)}#{k}: "+
81
- v.map do |kx, vx|
82
- "#{kx}=#{vx.round(3).to_s.sub(/[.]?0*$/, '')}"
83
- end * ', '
84
- end * "\n"
85
- puts z
86
- AppVeyor::Worker.message "Compilations: #{s['Engine'][:n]}", z
87
- end
88
- end
89
-
90
- end
91
-
92
- class FakeEngine < ExecJS::Xtrn::Engine
93
- def exec(s='')
94
- @@n||=0
95
- @@n+=1
96
- end
97
- end