Skip to content
This repository has been archived by the owner on Dec 15, 2022. It is now read-only.

Optimizations (Parcel + CompositeDisposable + Disposable + Emitter) #52

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ npm-debug.log
api.json
dist
package-lock.json
.parcel-cache
1 change: 1 addition & 0 deletions .npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ src
npm-debug.log
.travis.yml
.pairs
.parcel-cache
13 changes: 10 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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')
```
2 changes: 2 additions & 0 deletions appveyor.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
image: Visual Studio 2017

environment:
matrix:
- nodejs_version: "10"
Expand Down
4 changes: 3 additions & 1 deletion babel.config.js
Original file line number Diff line number Diff line change
@@ -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,
Expand Down
40 changes: 16 additions & 24 deletions lib/composite-disposable.js
Original file line number Diff line number Diff line change
@@ -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.
Expand All @@ -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.
Expand All @@ -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
}
}
Expand All @@ -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)
}
}
Expand Down Expand Up @@ -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"
)
}
}
4 changes: 2 additions & 2 deletions lib/disposable.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
// 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.
//
// * `object` An {Object} you want to perform the check against.
//
// 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")
}

/*
Expand Down
22 changes: 10 additions & 12 deletions lib/emitter.js
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand All @@ -243,18 +241,18 @@ 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
}
}

Emitter.dispatch = Emitter.simpleDispatch
Emitter.exceptionHandlers = []
module.exports = Emitter
6 changes: 3 additions & 3 deletions lib/event-kit.js
Original file line number Diff line number Diff line change
@@ -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"
18 changes: 16 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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
}
}
}