├── .github └── workflows │ └── node.js.yml ├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── index.js ├── package-lock.json ├── package.json └── test ├── fixtures ├── coffee │ └── fixture.coffee ├── data.json └── func │ ├── expected-with-sourcemap.js │ ├── expected.js │ ├── fixture.js │ └── no-assert.js └── test.js /.github/workflows/node.js.yml: -------------------------------------------------------------------------------- 1 | name: Node.js CI 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: ubuntu-latest 13 | 14 | strategy: 15 | matrix: 16 | node-version: [14.x, 16.x, 18.x] 17 | # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ 18 | 19 | steps: 20 | - uses: actions/checkout@v3 21 | - name: Use Node.js ${{ matrix.node-version }} 22 | uses: actions/setup-node@v1 23 | with: 24 | node-version: ${{ matrix.node-version }} 25 | - run: npm ci 26 | - run: npm test 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | npm-debug.log 3 | .idea/ 4 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ### [3.0.1](https://github.com/unassert-js/unassertify/releases/tag/v3.0.1) (2022-08-07) 2 | 3 | 4 | #### Bug Fixes 5 | 6 | * put `.cjs` back to `.js` since browserify ecosystem doesn't yet understand `.cjs` ([5419034a](https://github.com/unassert-js/unassertify/commit/5419034a982b6775b7403740f8bb3577d59ce413)) 7 | 8 | 9 | ## [3.0.0](https://github.com/unassert-js/unassertify/releases/tag/v3.0.0) (2022-08-07) 10 | 11 | 12 | #### Features 13 | 14 | * [Upgrade unassert to v2.0.0](https://github.com/unassert-js/unassertify/pull/9) 15 | * change .js to .cjs ([97c32f0b](https://github.com/unassert-js/unassertify/commit/97c32f0bf288787fed27d4abf285fe31c6864ec8)) 16 | 17 | #### Breaking Changes 18 | 19 | This release will not affect most users. This is a major release of "just in case" for unassert-v2 which is completely rewritten. 20 | 21 | 22 | ### [2.1.1](https://github.com/unassert-js/unassertify/releases/tag/v2.1.1) (2018-04-19) 23 | 24 | 25 | #### Performance Improvements 26 | 27 | * [Skip parsing if file doesn't contain assertions](https://github.com/unassert-js/unassertify/pull/6) by [@goto-bus-stop](https://github.com/goto-bus-stop) 28 | 29 | 30 | ## [2.1.0](https://github.com/unassert-js/unassertify/releases/tag/v2.1.0) (2017-10-23) 31 | 32 | 33 | #### Features 34 | 35 | * [Set `ecmaVersion: 2018` when parsing](https://github.com/unassert-js/unassertify/pull/4) by [@goto-bus-stop](https://github.com/goto-bus-stop) 36 | 37 | 38 | ### [2.0.5](https://github.com/unassert-js/unassertify/releases/tag/v2.0.5) (2017-10-17) 39 | 40 | 41 | #### Bug Fixes 42 | 43 | * [fix parsing code with hashbangs (#!)](https://github.com/unassert-js/unassertify/pull/3) by [@goto-bus-stop](https://github.com/goto-bus-stop) 44 | 45 | 46 | ### [2.0.4](https://github.com/unassert-js/unassertify/releases/tag/v2.0.4) (2016-12-28) 47 | 48 | 49 | #### Chore 50 | 51 | * transfer to unassert-js organization ([72ea9da](https://github.com/unassert-js/unassertify/commit/72ea9da397acb62d427a3efb1d62946ad236560a)) 52 | * switch to acorn ([c3f1785](https://github.com/unassert-js/unassertify/commit/c3f17856eca710794baafc9e0a8351434df0a8de)) 53 | 54 | 55 | ### [2.0.3](https://github.com/unassert-js/unassertify/releases/tag/v2.0.3) (2015-12-16) 56 | 57 | 58 | #### Bug Fixes 59 | 60 | * copy sourceRoot even if it is an empty string ([d687a4bc](https://github.com/unassert-js/unassertify/commit/d687a4bcc1514d030abd9170db04660dd861267e)) 61 | 62 | 63 | ### [2.0.2](https://github.com/unassert-js/unassertify/releases/tag/v2.0.2) (2015-09-27) 64 | 65 | 66 | #### Bug Fixes 67 | 68 | * should not transform JSON file ([6653d38c](https://github.com/unassert-js/unassertify/commit/6653d38c3cf69d4601a3f517226d8d403629f756)) 69 | 70 | 71 | ### [2.0.1](https://github.com/unassert-js/unassertify/releases/tag/v2.0.1) (2015-09-27) 72 | 73 | 74 | * add [SUPPORTED PATTERNS](https://github.com/unassert-js/unassertify#supported-patterns) section to README 75 | * linting and refactoring 76 | 77 | 78 | ## [2.0.0](https://github.com/unassert-js/unassertify/releases/tag/v2.0.0) (2015-09-25) 79 | 80 | 81 | #### Features 82 | 83 | * [remove assertions even if `debug` option is on](https://github.com/unassert-js/unassertify/pull/2) 84 | 85 | 86 | #### Breaking Changes 87 | 88 | * Since this release, assertions are always removed even if `debug` option is on. If you don't want to remove assertions when `debug` is on, simply do not add `unassertify` on that build configuration. 89 | 90 | 91 | ### [1.0.2](https://github.com/unassert-js/unassertify/releases/tag/v1.0.2) (2015-05-27) 92 | 93 | 94 | * extract [unassert](https://github.com/unassert-js/unassert) module out ([0e192a2d](https://github.com/unassert-js/unassertify/commit/0e192a2d0fdf31a0ffb410d57e779c446785f3bd)) 95 | 96 | 97 | ### [1.0.1](https://github.com/unassert-js/unassertify/releases/tag/v1.0.1) (2015-05-27) 98 | 99 | 100 | * skip traversing node to be deleted ([f936b632](https://github.com/unassert-js/unassertify/commit/f936b632d58a427d2c458a21d706e17f9b97b311)) 101 | 102 | 103 | ## [1.0.0](https://github.com/unassert-js/unassertify/releases/tag/v1.0.0) (2015-05-27) 104 | 105 | 106 | * The first release. 107 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015-2022 Takuto Wada, https://github.com/unassert-js/unassertify 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. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | unassertify 2 | ================================ 3 | 4 | [Browserify](http://browserify.org/) transform for [unassert](https://github.com/unassert-js/unassert): Encourages [programming with assertions](https://en.wikipedia.org/wiki/Assertion_(software_development)) by providing tools to compile them away. 5 | 6 | [![unassert][unassert-banner]][unassert-url] 7 | 8 | [![Build Status][ci-image]][ci-url] 9 | [![NPM version][npm-image]][npm-url] 10 | [![Code Style][style-image]][style-url] 11 | [![License][license-image]][license-url] 12 | 13 | 14 | #### RELATED MODULES 15 | 16 | - [unassert](https://github.com/unassert-js/unassert): Encourages programming with assertions by providing tools to compile them away. 17 | - [babel-plugin-unassert](https://github.com/unassert-js/babel-plugin-unassert): Babel plugin for unassert 18 | - [webpack-unassert-loader](https://github.com/unassert-js/webpack-unassert-loader): Webpack loader for unassert 19 | - [gulp-unassert](https://github.com/unassert-js/gulp-unassert): Gulp plugin for unassert 20 | - [unassert-cli](https://github.com/unassert-js/unassert-cli): CLI for unassert 21 | - [rollup-plugin-unassert](https://github.com/unassert-js/rollup-plugin-unassert): RollupJS plugin for unassert 22 | 23 | 24 | INSTALL 25 | --------------------------------------- 26 | 27 | ``` 28 | $ npm install --save-dev unassertify 29 | ``` 30 | 31 | 32 | HOW TO USE 33 | --------------------------------------- 34 | 35 | 36 | ### via CLI 37 | 38 | ``` 39 | $ $(npm bin)/browserify -t unassertify /path/to/src/target.js > /path/to/build/target.js 40 | ``` 41 | 42 | ### via API 43 | 44 | ```javascript 45 | const source = require('vinyl-source-stream'); 46 | const browserify = require('browserify'); 47 | const glob = require('glob'), 48 | 49 | gulp.task('production_build', function() { 50 | const files = glob.sync('./src/*.js'); 51 | const b = browserify({entries: files}); 52 | b.transform('unassertify'); 53 | return b.bundle() 54 | .pipe(source('bundle.js')) 55 | .pipe(gulp.dest('./dist')); 56 | }); 57 | ``` 58 | 59 | 60 | EXAMPLE 61 | --------------------------------------- 62 | 63 | For given `math.js` below, 64 | 65 | ```javascript 66 | 'use strict'; 67 | 68 | const assert = require('node:assert'); 69 | 70 | function add (a, b) { 71 | console.assert(typeof a === 'number'); 72 | assert(!isNaN(a)); 73 | assert.equal(typeof b, 'number'); 74 | assert.ok(!isNaN(b)); 75 | return a + b; 76 | } 77 | ``` 78 | 79 | Run `browserify` with `-t unassertify` to transform file. 80 | 81 | ``` 82 | $ $(npm bin)/browserify -t unassertify /path/to/demo/math.js > /path/to/build/math.js 83 | ``` 84 | 85 | You will see assert calls disappear. 86 | 87 | ```javascript 88 | 'use strict'; 89 | function add(a, b) { 90 | return a + b; 91 | } 92 | ``` 93 | 94 | 95 | SUPPORTED PATTERNS 96 | --------------------------------------- 97 | 98 | Assertion expressions are removed when they match patterns below. In other words, unassertify removes assertion calls that are compatible with Node.js standard [assert](https://nodejs.org/api/assert.html) API (and `console.assert`). 99 | 100 | * `assert(value, [message])` 101 | * `assert.ok(value, [message])` 102 | * `assert.equal(actual, expected, [message])` 103 | * `assert.notEqual(actual, expected, [message])` 104 | * `assert.strictEqual(actual, expected, [message])` 105 | * `assert.notStrictEqual(actual, expected, [message])` 106 | * `assert.deepEqual(actual, expected, [message])` 107 | * `assert.notDeepEqual(actual, expected, [message])` 108 | * `assert.deepStrictEqual(actual, expected, [message])` 109 | * `assert.notDeepStrictEqual(actual, expected, [message])` 110 | * `assert.match(string, regexp[, message])` 111 | * `assert.doesNotMatch(string, regexp[, message])` 112 | * `assert.throws(block, [error], [message])` 113 | * `assert.doesNotThrow(block, [message])` 114 | * `await assert.rejects(asyncFn, [error], [message])` 115 | * `await assert.doesNotReject(asyncFn, [error], [message])` 116 | * `assert.fail([message])` 117 | * `assert.fail(actual, expected, message, operator)` 118 | * `assert.ifError(value)` 119 | * `console.assert(value, [message])` 120 | 121 | unassertify also removes assert variable declarations, 122 | 123 | * `import assert from "assert"` 124 | * `import assert from "assert/strict"` 125 | * `import assert from "node:assert"` 126 | * `import assert from "node:assert/strict"` 127 | * `import * as assert from "assert"` 128 | * `import * as assert from "node:assert"` 129 | * `import * as assert from "assert/strict"` 130 | * `import * as assert from "node:assert/strict"` 131 | * `import { strict as assert } from "assert"` 132 | * `import { strict as assert } from "node:assert"` 133 | * `import { default as assert } from "assert"` 134 | * `import { default as assert } from "node:assert"` 135 | * `const assert = require("assert")` 136 | * `const assert = require("node:assert")` 137 | * `const assert = require("assert/strict")` 138 | * `const assert = require("node:assert/strict")` 139 | * `const assert = require("assert").strict` 140 | * `const assert = require("node:assert").strict` 141 | * `const { strict: assert } = require("assert")` 142 | * `const { strict: assert } = require("node:assert")` 143 | 144 | and assignments. 145 | 146 | * `assert = require("assert")` 147 | * `assert = require("node:assert")` 148 | * `assert = require("assert/strict")` 149 | * `assert = require("node:assert/strict")` 150 | * `assert = require("assert").strict` 151 | * `assert = require("node:assert").strict` 152 | 153 | 154 | #### Auto Variable Tracking 155 | 156 | unassert automatically removes assertion calls based on their imported variable names. 157 | 158 | So if import declaration is as follows, 159 | 160 | * `import strictAssert, { ok, equal as eq } from 'node:assert/strict';` 161 | 162 | unassert removes all `strictAssert`, `ok`, `eq` calls. 163 | 164 | 165 | AUTHOR 166 | --------------------------------------- 167 | * [Takuto Wada](https://github.com/twada) 168 | 169 | 170 | CONTRIBUTORS 171 | --------------------------------------- 172 | * [Renée Kooi](https://github.com/goto-bus-stop) 173 | 174 | 175 | OUR SUPPORT POLICY 176 | --------------------------------------- 177 | 178 | We support Node under maintenance. In other words, we stop supporting old Node version when [their maintenance ends](https://github.com/nodejs/LTS). 179 | 180 | This means that any other environment is not supported. 181 | 182 | NOTE: If unassertify works in any of the unsupported environments, it is purely coincidental and has no bearing on future compatibility. Use at your own risk. 183 | 184 | 185 | LICENSE 186 | --------------------------------------- 187 | Licensed under the [MIT](https://github.com/unassert-js/unassertify/blob/master/LICENSE) license. 188 | 189 | 190 | [unassert-url]: https://github.com/unassert-js/unassert 191 | [unassert-banner]: https://raw.githubusercontent.com/unassert-js/unassert-js-logo/master/banner/banner-official-fullcolor.png 192 | 193 | [npm-url]: https://npmjs.org/package/unassertify 194 | [npm-image]: https://badge.fury.io/js/unassertify.svg 195 | 196 | [ci-image]: https://github.com/unassert-js/unassertify/workflows/Node.js%20CI/badge.svg 197 | [ci-url]: https://github.com/unassert-js/unassertify/actions?query=workflow%3A%22Node.js+CI%22 198 | 199 | [license-url]: https://github.com/unassert-js/unassertify/blob/master/LICENSE 200 | [license-image]: https://img.shields.io/badge/license-MIT-brightgreen.svg 201 | 202 | [style-url]: https://github.com/standard/semistandard 203 | [style-image]: https://img.shields.io/badge/code%20style-semistandard-brightgreen.svg 204 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * unassertify 3 | * Browserify transform for unassert 4 | * Encourages programming with assertions by providing tools to compile them away. 5 | * 6 | * https://github.com/unassert-js/unassertify 7 | * 8 | * Copyright (c) 2015-2022 Takuto Wada 9 | * Licensed under the MIT license. 10 | * https://github.com/unassert-js/unassertify/blob/master/LICENSE 11 | */ 12 | 'use strict'; 13 | 14 | const path = require('path'); 15 | const through = require('through'); 16 | const acorn = require('acorn'); 17 | const escodegen = require('escodegen'); 18 | const convert = require('convert-source-map'); 19 | const { transfer } = require('multi-stage-sourcemap'); 20 | const { unassertAst, defaultOptions } = require('unassert'); 21 | const hasOwn = Object.prototype.hasOwnProperty; 22 | 23 | // add `power-assert` to target modules to avoid breaking change since unassertify is not configurable well 24 | function generateUnassertifyOptions () { 25 | const opts = defaultOptions(); 26 | opts.modules.push('power-assert'); 27 | return opts; 28 | } 29 | 30 | function mergeSourceMap (incomingSourceMap, outgoingSourceMap) { 31 | if (typeof outgoingSourceMap === 'string' || outgoingSourceMap instanceof String) { 32 | outgoingSourceMap = JSON.parse(outgoingSourceMap); 33 | } 34 | if (!incomingSourceMap) { 35 | return outgoingSourceMap; 36 | } 37 | return JSON.parse(transfer({ fromSourceMap: outgoingSourceMap, toSourceMap: incomingSourceMap })); 38 | } 39 | 40 | function overwritePropertyIfExists (name, from, to) { 41 | if (hasOwn.call(from, name)) { 42 | to.setProperty(name, from[name]); 43 | } 44 | } 45 | 46 | function reconnectSourceMap (inMap, outMap) { 47 | const mergedRawMap = mergeSourceMap(inMap, outMap.toObject()); 48 | const reMap = convert.fromObject(mergedRawMap); 49 | overwritePropertyIfExists('sources', inMap, reMap); 50 | overwritePropertyIfExists('sourceRoot', inMap, reMap); 51 | overwritePropertyIfExists('sourcesContent', inMap, reMap); 52 | return reMap; 53 | } 54 | 55 | function handleIncomingSourceMap (originalCode) { 56 | const commented = convert.fromSource(originalCode); 57 | if (commented) { 58 | return commented.toObject(); 59 | } 60 | return null; 61 | } 62 | 63 | function applyUnassertWithSourceMap (code, filepath, unassertOptions) { 64 | const ast = acorn.parse(code, { 65 | sourceType: 'module', 66 | ecmaVersion: 'latest', 67 | locations: true, 68 | allowHashBang: true 69 | }); 70 | const inMap = handleIncomingSourceMap(code); 71 | const instrumented = escodegen.generate(unassertAst(ast, unassertOptions), { 72 | sourceMap: filepath, 73 | sourceContent: code, 74 | sourceMapWithCode: true 75 | }); 76 | const outMap = convert.fromJSON(instrumented.map.toString()); 77 | if (inMap) { 78 | const reMap = reconnectSourceMap(inMap, outMap); 79 | return instrumented.code + '\n' + reMap.toComment() + '\n'; 80 | } else { 81 | return instrumented.code + '\n' + outMap.toComment() + '\n'; 82 | } 83 | } 84 | 85 | function applyUnassertWithoutSourceMap (code, unassertOptions) { 86 | const ast = acorn.parse(code, { 87 | sourceType: 'module', 88 | ecmaVersion: 'latest', 89 | allowHashBang: true 90 | }); 91 | return escodegen.generate(unassertAst(ast, unassertOptions)); 92 | } 93 | 94 | function shouldProduceSourceMap (options) { 95 | return (options && options._flags && options._flags.debug); 96 | } 97 | 98 | function containsAssertions (src) { 99 | // Matches 'assert','assert/strict','node:assert','node:assert/strict' and 'power-assert' 100 | return src.indexOf('assert') !== -1; 101 | } 102 | 103 | module.exports = function unassertify (filepath, options) { 104 | if (path.extname(filepath) === '.json') { 105 | return through(); 106 | } 107 | 108 | let data = ''; 109 | const stream = through(write, end); 110 | 111 | function write (buf) { 112 | data += buf; 113 | } 114 | 115 | function end () { 116 | if (!containsAssertions(data)) { 117 | stream.queue(data); 118 | } else if (shouldProduceSourceMap(options)) { 119 | stream.queue(applyUnassertWithSourceMap(data, filepath, generateUnassertifyOptions())); 120 | } else { 121 | stream.queue(applyUnassertWithoutSourceMap(data, generateUnassertifyOptions())); 122 | } 123 | stream.queue(null); 124 | } 125 | 126 | return stream; 127 | }; 128 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "unassertify", 3 | "description": "Browserify transform for unassert: Encourages programming with assertions by providing tools to compile them away", 4 | "version": "3.0.1", 5 | "author": { 6 | "name": "Takuto Wada", 7 | "email": "takuto.wada@gmail.com", 8 | "url": "https://github.com/twada" 9 | }, 10 | "bugs": "https://github.com/unassert-js/unassertify/issues", 11 | "contributors": [ 12 | { 13 | "name": "Renée Kooi", 14 | "url": "https://github.com/goto-bus-stop" 15 | } 16 | ], 17 | "dependencies": { 18 | "acorn": "^8.0.0", 19 | "convert-source-map": "^1.1.1", 20 | "escodegen": "^2.0.0", 21 | "multi-stage-sourcemap": "^0.3.1", 22 | "through": "^2.3.7", 23 | "unassert": "^2.0.0" 24 | }, 25 | "devDependencies": { 26 | "browserify": "^17.0.0", 27 | "coffeeify": "^3.0.0", 28 | "coffeescript": "^2.7.0", 29 | "event-stream": "^4.0.0", 30 | "intelli-espower-loader": "^1.0.1", 31 | "mocha": "^10.0.0", 32 | "power-assert": "^1.4.1", 33 | "semistandard": "^16.0.0", 34 | "snazzy": "^9.0.0" 35 | }, 36 | "files": [ 37 | "README.md", 38 | "CHANGELOG.md", 39 | "LICENSE", 40 | "index.js", 41 | "package.json" 42 | ], 43 | "homepage": "https://github.com/unassert-js/unassertify", 44 | "keywords": [ 45 | "DbC", 46 | "unassert", 47 | "assert", 48 | "assertion", 49 | "browserify", 50 | "browserify-transform" 51 | ], 52 | "license": "MIT", 53 | "main": "index.js", 54 | "repository": { 55 | "type": "git", 56 | "url": "https://github.com/unassert-js/unassertify.git" 57 | }, 58 | "scripts": { 59 | "fmt": "semistandard --fix index.js 'test/*.js'", 60 | "lint": "semistandard --verbose index.js 'test/*.js' | snazzy", 61 | "test": "npm run lint && mocha --require intelli-espower-loader" 62 | }, 63 | "semistandard": { 64 | "globals": [ 65 | "describe", 66 | "context", 67 | "beforeEach", 68 | "it" 69 | ] 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /test/fixtures/coffee/fixture.coffee: -------------------------------------------------------------------------------- 1 | assert = require('assert') 2 | 3 | add = (a, b) -> 4 | console.assert typeof a == 'number' 5 | assert !isNaN(a) 6 | assert.equal typeof b, 'number' 7 | assert.ok !isNaN(b) 8 | a + b 9 | -------------------------------------------------------------------------------- /test/fixtures/data.json: -------------------------------------------------------------------------------- 1 | { 2 | "foo": "baz", 3 | "hoge": "fuga" 4 | } 5 | -------------------------------------------------------------------------------- /test/fixtures/func/expected-with-sourcemap.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | function add(a, b) { 3 | return a + b; 4 | } 5 | //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9hYnNvbHV0ZS9wYXRoL3RvL3Rlc3QvZml4dHVyZXMvZnVuYy9maXh0dXJlLmpzIl0sIm5hbWVzIjpbImFkZCIsImEiLCJiIl0sIm1hcHBpbmdzIjoiQUFBQTtBQUlBLFNBQVNBLEdBQVQsQ0FBY0MsQ0FBZCxFQUFpQkMsQ0FBakIsRUFBb0I7QUFBQSxJQXFEaEIsT0FBT0QsQ0FBQSxHQUFJQyxDQUFYLENBckRnQjtBQUFBIiwic291cmNlc0NvbnRlbnQiOlsiJ3VzZSBzdHJpY3QnO1xuXG52YXIgYXNzZXJ0ID0gcmVxdWlyZSgnYXNzZXJ0Jyk7XG5cbmZ1bmN0aW9uIGFkZCAoYSwgYikge1xuICAgIGNvbnNvbGUuYXNzZXJ0KHR5cGVvZiBhID09PSAnbnVtYmVyJyk7XG5cbiAgICBhc3NlcnQoIWlzTmFOKGEpKTtcbiAgICBhc3NlcnQoIWlzTmFOKGEpLCAnYXNzZXJ0aW9uIG1lc3NhZ2UnKTtcblxuICAgIGFzc2VydC5vayghaXNOYU4oYikpO1xuICAgIGFzc2VydC5vayghaXNOYU4oYiksICdhc3NlcnRpb24gbWVzc2FnZScpO1xuXG4gICAgYXNzZXJ0LmVxdWFsKHR5cGVvZiBiLCAnbnVtYmVyJyk7XG4gICAgYXNzZXJ0LmVxdWFsKHR5cGVvZiBiLCAnbnVtYmVyJywgJ2Fzc2VydGlvbiBtZXNzYWdlJyk7XG5cbiAgICBhc3NlcnQuc3RyaWN0RXF1YWwodHlwZW9mIGIsICdudW1iZXInKTtcbiAgICBhc3NlcnQuc3RyaWN0RXF1YWwodHlwZW9mIGIsICdudW1iZXInLCAnYXNzZXJ0aW9uIG1lc3NhZ2UnKTtcblxuICAgIGFzc2VydC5kZWVwRXF1YWwodHlwZW9mIGIsICdudW1iZXInKTtcbiAgICBhc3NlcnQuZGVlcEVxdWFsKHR5cGVvZiBiLCAnbnVtYmVyJywgJ2Fzc2VydGlvbiBtZXNzYWdlJyk7XG5cbiAgICBhc3NlcnQuZGVlcFN0cmljdEVxdWFsKHR5cGVvZiBiLCAnbnVtYmVyJyk7XG4gICAgYXNzZXJ0LmRlZXBTdHJpY3RFcXVhbCh0eXBlb2YgYiwgJ251bWJlcicsICdhc3NlcnRpb24gbWVzc2FnZScpO1xuXG4gICAgYXNzZXJ0Lm5vdEVxdWFsKHR5cGVvZiBhLCAnb2JqZWN0Jyk7XG4gICAgYXNzZXJ0Lm5vdEVxdWFsKHR5cGVvZiBhLCAnb2JqZWN0JywgJ2Fzc2VydGlvbiBtZXNzYWdlJyk7XG5cbiAgICBhc3NlcnQubm90U3RyaWN0RXF1YWwodHlwZW9mIGEsICdvYmplY3QnKTtcbiAgICBhc3NlcnQubm90U3RyaWN0RXF1YWwodHlwZW9mIGEsICdvYmplY3QnLCAnYXNzZXJ0aW9uIG1lc3NhZ2UnKTtcblxuICAgIGFzc2VydC5ub3REZWVwRXF1YWwodHlwZW9mIGEsICdvYmplY3QnKTtcbiAgICBhc3NlcnQubm90RGVlcEVxdWFsKHR5cGVvZiBhLCAnb2JqZWN0JywgJ2Fzc2VydGlvbiBtZXNzYWdlJyk7XG5cbiAgICBhc3NlcnQubm90RGVlcFN0cmljdEVxdWFsKHR5cGVvZiBhLCAnb2JqZWN0Jyk7XG4gICAgYXNzZXJ0Lm5vdERlZXBTdHJpY3RFcXVhbCh0eXBlb2YgYSwgJ29iamVjdCcsICdhc3NlcnRpb24gbWVzc2FnZScpO1xuXG4gICAgYXNzZXJ0LnRocm93cyhmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhbGlkYXRlKGEpO1xuICAgIH0pO1xuICAgIGFzc2VydC50aHJvd3MoZnVuY3Rpb24gKCkge1xuICAgICAgICB2YWxpZGF0ZShhKTtcbiAgICB9LCAnYXNzZXJ0aW9uIG1lc3NhZ2UnKTtcbiAgICBhc3NlcnQudGhyb3dzKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFsaWRhdGUoYSk7XG4gICAgfSwgRXJyb3IsICdhc3NlcnRpb24gbWVzc2FnZScpO1xuXG4gICAgYXNzZXJ0LmRvZXNOb3RUaHJvdyhmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhbGlkYXRlKGIpO1xuICAgIH0sICdhc3NlcnRpb24gbWVzc2FnZScpO1xuICAgIGFzc2VydC5kb2VzTm90VGhyb3coZnVuY3Rpb24gKCkge1xuICAgICAgICB2YWxpZGF0ZShiKTtcbiAgICB9KTtcblxuICAgIGFzc2VydC5pZkVycm9yKGEpO1xuICAgIGFzc2VydC5mYWlsKGEsIGIsICdhc3NlcnRpb24gbWVzc2FnZScsICc9PScpO1xuXG4gICAgcmV0dXJuIGEgKyBiO1xufVxuIl19 6 | -------------------------------------------------------------------------------- /test/fixtures/func/expected.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | function add(a, b) { 3 | return a + b; 4 | } -------------------------------------------------------------------------------- /test/fixtures/func/fixture.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var assert = require('assert'); 4 | 5 | function add (a, b) { 6 | console.assert(typeof a === 'number'); 7 | 8 | assert(!isNaN(a)); 9 | assert(!isNaN(a), 'assertion message'); 10 | 11 | assert.ok(!isNaN(b)); 12 | assert.ok(!isNaN(b), 'assertion message'); 13 | 14 | assert.equal(typeof b, 'number'); 15 | assert.equal(typeof b, 'number', 'assertion message'); 16 | 17 | assert.strictEqual(typeof b, 'number'); 18 | assert.strictEqual(typeof b, 'number', 'assertion message'); 19 | 20 | assert.deepEqual(typeof b, 'number'); 21 | assert.deepEqual(typeof b, 'number', 'assertion message'); 22 | 23 | assert.deepStrictEqual(typeof b, 'number'); 24 | assert.deepStrictEqual(typeof b, 'number', 'assertion message'); 25 | 26 | assert.notEqual(typeof a, 'object'); 27 | assert.notEqual(typeof a, 'object', 'assertion message'); 28 | 29 | assert.notStrictEqual(typeof a, 'object'); 30 | assert.notStrictEqual(typeof a, 'object', 'assertion message'); 31 | 32 | assert.notDeepEqual(typeof a, 'object'); 33 | assert.notDeepEqual(typeof a, 'object', 'assertion message'); 34 | 35 | assert.notDeepStrictEqual(typeof a, 'object'); 36 | assert.notDeepStrictEqual(typeof a, 'object', 'assertion message'); 37 | 38 | assert.throws(function () { 39 | validate(a); 40 | }); 41 | assert.throws(function () { 42 | validate(a); 43 | }, 'assertion message'); 44 | assert.throws(function () { 45 | validate(a); 46 | }, Error, 'assertion message'); 47 | 48 | assert.doesNotThrow(function () { 49 | validate(b); 50 | }, 'assertion message'); 51 | assert.doesNotThrow(function () { 52 | validate(b); 53 | }); 54 | 55 | assert.ifError(a); 56 | assert.fail(a, b, 'assertion message', '=='); 57 | 58 | return a + b; 59 | } 60 | -------------------------------------------------------------------------------- /test/fixtures/func/no-assert.js: -------------------------------------------------------------------------------- 1 | contains some invalid code to make sure that this did not get parsed 2 | -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const unassertify = require('..'); 4 | const fs = require('fs'); 5 | const path = require('path'); 6 | const Stream = require('stream'); 7 | const assert = require('power-assert'); 8 | const browserify = require('browserify'); 9 | const coffeeify = require('coffeeify'); 10 | const es = require('event-stream'); 11 | const convert = require('convert-source-map'); 12 | 13 | describe('unassertify', function () { 14 | it('removes assert dependency', function (done) { 15 | const b = browserify(); 16 | b.add(path.normalize(path.join(__dirname, 'fixtures', 'func', 'fixture.js'))); 17 | b.transform(unassertify); 18 | b.bundle().pipe(es.wait(function (err, data) { 19 | assert(!err); 20 | const code = data.toString('utf-8'); 21 | // console.log(code); 22 | assert(!/assert/.test(code)); 23 | done(); 24 | })); 25 | }); 26 | it('produces sourcemap when debug: true', function (done) { 27 | const b = browserify({ debug: true }); 28 | const testFilepath = path.normalize(path.join(__dirname, 'fixtures', 'func', 'fixture.js')); 29 | b.add(testFilepath); 30 | b.transform(unassertify); 31 | b.bundle().pipe(es.wait(function (err, data) { 32 | assert(!err); 33 | const code = data.toString('utf-8'); 34 | // console.log(code); 35 | assert(!/assert/.test(code)); 36 | const inlineMap = convert.fromSource(code); 37 | assert(inlineMap); 38 | const sourceMap = inlineMap.toObject(); 39 | assert(sourceMap); 40 | // console.log(JSON.stringify(sourceMap, null, 2)); 41 | assert(sourceMap.sources.some(function (fpath) { return fpath === testFilepath; })); 42 | done(); 43 | })); 44 | }); 45 | it('skips files that do not contain assertions', function (done) { 46 | const filename = path.join(__dirname, 'fixtures', 'func', 'no-assert.js'); 47 | fs.createReadStream(filename) 48 | .pipe(unassertify(filename, {})) 49 | .pipe(es.wait(function (err, data) { 50 | assert(!err); 51 | const code = data.toString('utf-8'); 52 | assert(!/assert/.test(code)); 53 | done(); 54 | })); 55 | }); 56 | }); 57 | 58 | describe('with preceding transform', function () { 59 | it('just remove assertions and dependencies when debug: false', function (done) { 60 | const b = browserify(); 61 | b.add(path.normalize(path.join(__dirname, 'fixtures', 'coffee', 'fixture.coffee'))); 62 | b.transform(coffeeify); 63 | b.transform(unassertify); 64 | b.bundle().pipe(es.wait(function (err, data) { 65 | assert(!err); 66 | const code = data.toString('utf-8'); 67 | // console.log(code); 68 | const inlineMap = convert.fromSource(code); 69 | assert(!inlineMap); 70 | assert(!/require\('assert'\)/.test(code)); 71 | done(); 72 | })); 73 | }); 74 | it('adjust sourcemap if debug: true', function (done) { 75 | const b = browserify({ debug: true }); 76 | const testFilepath = path.normalize(path.join(__dirname, 'fixtures', 'coffee', 'fixture.coffee')); 77 | b.add(testFilepath); 78 | b.transform(coffeeify); 79 | b.transform(unassertify); 80 | b.bundle().pipe(es.wait(function (err, data) { 81 | assert(!err); 82 | const code = data.toString('utf-8'); 83 | // console.log(code); 84 | assert(!/require\('assert'\)/.test(code)); 85 | const inlineMap = convert.fromSource(code); 86 | assert(inlineMap); 87 | const sourceMap = inlineMap.toObject(); 88 | assert(sourceMap); 89 | // console.log(JSON.stringify(sourceMap, null, 2)); 90 | assert(sourceMap.sources.some(function (fpath) { return testFilepath.lastIndexOf(fpath) !== -1; })); 91 | const originalCode = fs.readFileSync(testFilepath, 'utf-8'); 92 | assert(sourceMap.sourcesContent.some(function (eachCode) { 93 | return eachCode === originalCode; 94 | })); 95 | done(); 96 | })); 97 | }); 98 | }); 99 | 100 | describe('adjust sourcemap if debug: true', function () { 101 | const stream = unassertify( 102 | '/absolute/path/to/test/fixtures/func/fixture.js', 103 | { 104 | _flags: { 105 | entries: [ 106 | './test/fixtures/func/fixture.js' 107 | ], 108 | debug: true 109 | } 110 | }); 111 | 112 | it('should return a stream', function () { 113 | assert(stream instanceof Stream); 114 | }); 115 | 116 | it('should not transform', function (done) { 117 | let output = ''; 118 | stream.on('data', function (buf) { 119 | output += buf; 120 | }); 121 | stream.on('end', function () { 122 | const expected = fs.readFileSync('test/fixtures/func/expected-with-sourcemap.js', 'utf8'); 123 | assert.equal(output, expected); 124 | done(); 125 | }); 126 | const file = fs.createReadStream('test/fixtures/func/fixture.js'); 127 | file.pipe(stream); 128 | }); 129 | }); 130 | 131 | describe('just remove assertions if debug: false', function () { 132 | const stream = unassertify( 133 | '/absolute/path/to/test/fixtures/func/fixture.js', 134 | { 135 | _flags: { 136 | entries: [ 137 | './test/fixtures/func/fixture.js' 138 | ], 139 | debug: false 140 | } 141 | }); 142 | 143 | it('should return a stream', function () { 144 | assert(stream instanceof Stream); 145 | }); 146 | 147 | it('should remove assertions', function (done) { 148 | let output = ''; 149 | stream.on('data', function (buf) { 150 | output += buf; 151 | }); 152 | stream.on('end', function () { 153 | const expected = fs.readFileSync('test/fixtures/func/expected.js', 'utf8'); 154 | assert.equal(output, expected); 155 | done(); 156 | }); 157 | const file = fs.createReadStream('test/fixtures/func/fixture.js'); 158 | file.pipe(stream); 159 | }); 160 | }); 161 | 162 | describe('when incoming code is JSON file', function () { 163 | const stream = unassertify( 164 | process.cwd() + '/test/fixtures/data.json', 165 | { 166 | _flags: { 167 | basedir: '/absolute/path/to', 168 | cache: {}, 169 | debug: true 170 | } 171 | } 172 | ); 173 | 174 | it('should return a stream', function () { 175 | assert(stream instanceof Stream); 176 | }); 177 | 178 | it('should not transform', function (done) { 179 | let output = ''; 180 | stream.on('data', function (buf) { 181 | output += buf; 182 | }); 183 | stream.on('end', function () { 184 | const expected = fs.readFileSync('test/fixtures/data.json', 'utf8'); 185 | assert.equal(output, expected); 186 | done(); 187 | }); 188 | const file = fs.createReadStream('test/fixtures/data.json'); 189 | file.pipe(stream); 190 | }); 191 | }); 192 | 193 | describe('when incoming code contains #! hash bang', function () { 194 | const stream = unassertify( 195 | '/tmp/JSONStream.js', 196 | { _flags: {} } 197 | ); 198 | 199 | it('should ignore hashbang', function (done) { 200 | stream.on('end', function () { 201 | // We didn't crash while parsing! 202 | done(); 203 | }); 204 | stream.end('#!/usr/bin/env node\n\nvar assert = require("assert"); assert(10 == 10);'); 205 | }); 206 | }); 207 | --------------------------------------------------------------------------------