diff --git a/.gitignore b/.gitignore index 560bd6d..6e042c2 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ npm-debug.log api.json dist package-lock.json +.parcel-cache diff --git a/.npmignore b/.npmignore index d4c42e7..84a16ea 100644 --- a/.npmignore +++ b/.npmignore @@ -6,3 +6,4 @@ src npm-debug.log .travis.yml .pairs +.parcel-cache diff --git a/README.md b/README.md index 520e490..f4a73ec 100644 --- a/README.md +++ b/README.md @@ -75,8 +75,15 @@ const {Disposable} = require('event-kit') const disposable = new Disposable(() => this.destroyResource()) ``` -### Using ES6 Code -You can use the ES6 style classes from `lib` directory. +### ES6 Classes +For backward compatibility, the main entry of this package uses prototypical functions instead of classes. To use the version of the code that use classes, there are two options: + +- The bundled code: +``` +const {Disposable, Emitter, CompositeDisposable} = require('event-kit/dist/event-kit.bundle') +``` + +- The source code: ``` -const {Disposable} = require('event-kit/lib/event-kit') +const {Disposable, Emitter, CompositeDisposable} = require('event-kit/lib/event-kit') ``` diff --git a/appveyor.yml b/appveyor.yml index f2985be..bf78a44 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,3 +1,5 @@ +image: Visual Studio 2017 + environment: matrix: - nodejs_version: "10" diff --git a/babel.config.js b/babel.config.js index 873b92c..e37886e 100644 --- a/babel.config.js +++ b/babel.config.js @@ -1,6 +1,8 @@ let presets = ["babel-preset-atomic"]; -let plugins = ["@babel/plugin-transform-classes"] // this is needed so Disposabale can be extended by ES5-style classes +let plugins = process.env.PARCEL_ENV + ? [] // the optimized bundle uses ES6 class + : ["@babel/plugin-transform-classes"] // this is needed so Disposabale can be extended by ES5-style classes module.exports = { presets: presets, diff --git a/lib/composite-disposable.js b/lib/composite-disposable.js index 495ec5e..b257ac2 100644 --- a/lib/composite-disposable.js +++ b/lib/composite-disposable.js @@ -1,5 +1,4 @@ -let CompositeDisposable -let Disposable +import Disposable from "./disposable" // Essential: An object that aggregates multiple {Disposable} instances together // into a single disposable, so they can all be disposed as a group. @@ -24,18 +23,15 @@ let Disposable // } // } // ``` -module.exports = class CompositeDisposable { +export default class CompositeDisposable { /* Section: Construction and Destruction */ // Public: Construct an instance, optionally with one or more disposables - constructor() { + constructor(...args) { this.disposed = false - this.disposables = new Set() - for (let disposable of arguments) { - this.add(disposable) - } + this.disposables = new Set(args) } // Public: Dispose all disposables added to this composite disposable. @@ -44,7 +40,11 @@ module.exports = class CompositeDisposable { dispose() { if (!this.disposed) { this.disposed = true - this.disposables.forEach(disposable => disposable.dispose()) + // traditional for is faster: https://jsbench.me/67kgn473ko/1 + const disposablesArray = [...this.disposables] + for (let i = 0, len = disposablesArray.length; i < len; i++) { + disposablesArray[i].dispose(); + } this.disposables = null } } @@ -59,10 +59,14 @@ module.exports = class CompositeDisposable { // // * `...disposables` {Disposable} instances or any objects with `.dispose()` // methods. - add() { + add(...args) { if (!this.disposed) { - for (const disposable of arguments) { - assertDisposable(disposable) + for (const disposable of args) { + if (!Disposable.isDisposable(disposable)) { + throw new TypeError( + "Arguments to CompositeDisposable.add must have a .dispose() method" + ) + } this.disposables.add(disposable) } } @@ -91,15 +95,3 @@ module.exports = class CompositeDisposable { } } } - -function assertDisposable(disposable) { - if (Disposable == null) { - Disposable = require("./disposable") - } - - if (!Disposable.isDisposable(disposable)) { - throw new TypeError( - "Arguments to CompositeDisposable.add must have a .dispose() method" - ) - } -} diff --git a/lib/disposable.js b/lib/disposable.js index 2737597..e28c8df 100644 --- a/lib/disposable.js +++ b/lib/disposable.js @@ -1,6 +1,6 @@ // Essential: A handle to a resource that can be disposed. For example, // {Emitter::on} returns disposables representing subscriptions. -module.exports = class Disposable { +export default class Disposable { // Public: Ensure that `object` correctly implements the `Disposable` // contract. // @@ -8,7 +8,7 @@ module.exports = class Disposable { // // Returns a {Boolean} indicating whether `object` is a valid `Disposable`. static isDisposable(object) { - return typeof (object != null ? object.dispose : undefined) === "function" + return Boolean(object) && (typeof object.dispose === "function") } /* diff --git a/lib/emitter.js b/lib/emitter.js index 1c7a253..5b109a6 100644 --- a/lib/emitter.js +++ b/lib/emitter.js @@ -1,5 +1,5 @@ -const Disposable = require("./disposable") -const CompositeDisposable = require("./composite-disposable") +import Disposable from "./disposable" +import CompositeDisposable from "./composite-disposable" // Essential: Utility class to be used when implementing event-based APIs that // allows for handlers registered via `::on` to be invoked with calls to @@ -28,7 +28,7 @@ const CompositeDisposable = require("./composite-disposable") // } // } // ``` -class Emitter { +export default class Emitter { static onEventHandlerException(exceptionHandler) { if (this.exceptionHandlers.length === 0) { this.dispatch = this.exceptionHandlingDispatch @@ -212,22 +212,20 @@ class Emitter { // for the same name will be invoked. // * `value` Callbacks will be invoked with this value as an argument. emit(eventName, value) { - const handlers = - this.handlersByEventName && this.handlersByEventName[eventName] + const handlers = this.handlersByEventName?.[eventName] if (handlers) { // create a copy of `handlers` so that if any handler mutates `handlers` // (e.g. by calling `on` on this same emitter), this does not result in // changing the handlers being called during this same `emit`. const handlersCopy = handlers.slice() - for (let i = 0; i < handlersCopy.length; i++) { + for (let i = 0, len = handlersCopy.length; i < len; i++) { this.constructor.dispatch(handlersCopy[i], value) } } } emitAsync(eventName, value) { - const handlers = - this.handlersByEventName && this.handlersByEventName[eventName] + const handlers = this.handlersByEventName?.[eventName] if (handlers) { const promises = handlers.map(handler => this.constructor.dispatch(handler, value) @@ -243,13 +241,14 @@ class Emitter { listenerCountForEventName(eventName) { const handlers = this.handlersByEventName[eventName] - return handlers == null ? 0 : handlers.length + return handlers?.length ?? 0 } getTotalListenerCount() { let result = 0 - for (let eventName of Object.keys(this.handlersByEventName)) { - result += this.handlersByEventName[eventName].length + const eventNames = Object.keys(this.handlersByEventName) + for (let i = 0, len = eventNames.length; i < len; i++) { + result += this.handlersByEventName[eventNames[i]].length } return result } @@ -257,4 +256,3 @@ class Emitter { Emitter.dispatch = Emitter.simpleDispatch Emitter.exceptionHandlers = [] -module.exports = Emitter diff --git a/lib/event-kit.js b/lib/event-kit.js index 56b201d..aaea4cc 100644 --- a/lib/event-kit.js +++ b/lib/event-kit.js @@ -1,3 +1,3 @@ -exports.Emitter = require("./emitter") -exports.Disposable = require("./disposable") -exports.CompositeDisposable = require("./composite-disposable") +export { default as Emitter } from "./emitter"; +export { default as Disposable } from "./disposable" +export { default as CompositeDisposable } from "./composite-disposable" diff --git a/package.json b/package.json index 5efa0a5..3f75a55 100644 --- a/package.json +++ b/package.json @@ -3,8 +3,11 @@ "version": "2.5.3", "description": "Simple library for implementing and consuming evented APIs", "main": "./dist/event-kit", + "bundle": "./dist/event-kit.bundle.js", "scripts": { - "build": "cross-env BABEL_KEEP_MODULES=false babel lib --out-dir dist --delete-dir-on-start", + "babel": "cross-env BABEL_KEEP_MODULES=false babel lib --out-dir dist --delete-dir-on-start", + "bundle": "cross-env PARCEL_ENV=true cross-env NODE_ENV=production parcel build --target bundle lib/event-kit.js", + "build": "npm run babel && npm run bundle", "docs": "joanna-tello -o api.json package.json lib", "prepublish": "npm run build && npm run docs", "test": "jasmine-focused --captureExceptions --forceexit spec" @@ -23,6 +26,17 @@ "babel-preset-atomic": "^3.0.1", "cross-env": "^7.0.3", "jasmine-focused": "^1.0.7", - "joanna": "https://github.com/aminya/joanna" + "joanna": "https://github.com/aminya/joanna", + "parcel": "2.0.0-nightly.495" + }, + "targets": { + "bundle": { + "context": "electron-renderer", + "engines": { + "electron": ">=6.x" + }, + "outputFormat": "commonjs", + "isLibrary": true + } } }