execjs-xtrn 1.1.3 → 1.1.4

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.
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