Skip to content

Commit

Permalink
Merge pull request #124 from andywer/feature/es-modules
Browse files Browse the repository at this point in the history
Build and publish ES module build
  • Loading branch information
andywer committed Dec 19, 2019
2 parents 4264ec9 + 8353347 commit 4d2acf6
Show file tree
Hide file tree
Showing 23 changed files with 2,731 additions and 1,680 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
docs/_site
docs/vendor
dist/*
dist-*/*
node_modules/
test/workers/*.js
test/rollup/dist/
test/webpack/dist*
test/workers/*.js
.DS_Store
Thumbs.db
*.log
1 change: 1 addition & 0 deletions observable.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./dist-esm/observable"
4,153 changes: 2,539 additions & 1,614 deletions package-lock.json

Large diffs are not rendered by default.

33 changes: 22 additions & 11 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,25 @@
"version": "1.0.0-beta.9",
"description": "Easy to use, yet powerful multi-threading library for node.js, web browsers and Electron",
"main": "dist/index.js",
"module": "dist-esm/index.js",
"scripts": {
"prebuild": "rimraf dist/",
"build": "tsc",
"prebuild": "rimraf dist/ dist-esm/",
"build": "run-p build:cjs build:es",
"build:cjs": "tsc -p tsconfig.json",
"build:es": "tsc -p tsconfig-esm.json",
"test": "run-s test:ava test:puppeteer:basic test:puppeteer:webpack",
"test:ava": "cross-env TS_NODE_FILES=true ava",
"test:puppeteer:basic": "puppet-run --plugin=mocha --bundle=./test/workers/:/workers/ ./test/*.chromium*.ts",
"test:puppeteer:webpack": "puppet-run --serve ./test/webpack/dist.web/0.worker.js --serve ./test/webpack/dist.web/1.worker.js --plugin=mocha ./test/webpack/webpack.chromium.mocha.ts",
"posttest": "tslint --project .",
"prepare": "run-s build"
},
"sideEffects": [
"./dist*/master/register.js",
"./dist*/worker/index.js",
"./register.*js",
"./worker.*js"
],
"repository": {
"type": "git",
"url": "git+https://github.com/andywer/threads.js.git"
Expand Down Expand Up @@ -40,32 +49,32 @@
"observable-fns": "^0.5.0"
},
"devDependencies": {
"@babel/cli": "^7.4.4",
"@babel/plugin-transform-modules-commonjs": "^7.4.4",
"@babel/plugin-transform-typescript": "^7.4.4",
"@types/callsites": "^3.0.0",
"@types/chai": "^4.1.7",
"@types/debug": "^4.1.4",
"@types/execa": "^0.9.0",
"@types/mocha": "^5.2.6",
"@types/node": "^11.13.8",
"@types/webpack": "^4.4.32",
"ava": "^1.4.1",
"ava": "^2.4.0",
"chai": "^4.2.0",
"cross-env": "^5.2.0",
"execa": "^2.0.3",
"execa": "^3.4.0",
"mocha": "^5.2.0",
"npm-run-all": "^4.1.5",
"puppet-run": "^0.10.0-alpha",
"puppet-run-plugin-mocha": "^0.10.0-alpha",
"rimraf": "^2.6.3",
"rollup": "^1.16.2",
"rollup-plugin-commonjs": "^10.0.1",
"rollup-plugin-node-resolve": "^5.1.0",
"threads-plugin": "^1.2.0",
"tiny-worker": "^2.2.0",
"ts-loader": "^6.0.1",
"ts-node": "^8.1.0",
"tslint": "^5.16.0",
"tslint-config-prettier": "^1.18.0",
"typescript": "^3.4.5",
"wavy": "^1.0.4",
"webpack": "^4.32.2",
"worker-plugin": "^3.1.0"
},
Expand All @@ -91,14 +100,16 @@
"ts-node": false,
"ts-node/register": false,
"worker_threads": false,
"./dist/master/implementation": "./dist/master/implementation.browser.js",
"./dist/master/implementation.node.js": false,
"./dist/worker/implementation": "./dist/worker/implementation.browser.js",
"./dist/worker/implementation.tiny-worker.js": false,
"./dist/worker/implementation.worker_threads.js": false
"./dist/worker/implementation.worker_threads.js": false,
"./dist-esm/master/implementation.node.js": false,
"./dist-esm/worker/implementation.tiny-worker.js": false,
"./dist-esm/worker/implementation.worker_threads.js": false
},
"files": [
"dist/**",
"dist-esm/**",
"*.js",
"*.ts"
]
Expand Down
1 change: 1 addition & 0 deletions register.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./dist-esm/master/register"
11 changes: 4 additions & 7 deletions src/master/implementation.browser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
import { ThreadsWorkerOptions, WorkerImplementation } from "../types/master"
import { getBundleURL } from "./get-bundle-url.browser"

const defaultPoolSize = navigator.hardwareConcurrency || 4
export const defaultPoolSize = typeof navigator !== "undefined" && navigator.hardwareConcurrency
? navigator.hardwareConcurrency
: 4

const isAbsoluteURL = (value: string) => /^(file|https?:)?\/\//i.test(value)

Expand All @@ -16,7 +18,7 @@ function createSourceBlobURL(code: string): string {
}


function selectWorkerImplementation(): typeof WorkerImplementation {
export function selectWorkerImplementation(): typeof WorkerImplementation {
if (typeof Worker === "undefined") {
// Might happen on Safari, for instance
// The idea is to only fail if the constructor is actually used
Expand Down Expand Up @@ -44,8 +46,3 @@ function selectWorkerImplementation(): typeof WorkerImplementation {
}
}
}

export default {
defaultPoolSize,
selectWorkerImplementation
}
10 changes: 3 additions & 7 deletions src/master/implementation.node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ declare const __non_webpack_require__: typeof require
type WorkerEventName = "error" | "message"

let tsNodeAvailable: boolean | undefined
const defaultPoolSize = cpus().length

export const defaultPoolSize = cpus().length

function detectTsNode() {
if (typeof __non_webpack_require__ === "function") {
Expand Down Expand Up @@ -167,7 +168,7 @@ function initTinyWorker(): typeof WorkerImplementation {
return Worker as any
}

function selectWorkerImplementation(): typeof WorkerImplementation {
export function selectWorkerImplementation(): typeof WorkerImplementation {
try {
return initWorkerThreadsWorker()
} catch(error) {
Expand All @@ -176,8 +177,3 @@ function selectWorkerImplementation(): typeof WorkerImplementation {
return initTinyWorker()
}
}

export default {
defaultPoolSize,
selectWorkerImplementation
}
19 changes: 10 additions & 9 deletions src/master/implementation.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
// tslint:disable no-var-requires
/*
* This file is only a stub to make './implementation' resolve to the right module.
*/

import { WorkerImplementation } from "../types/master"
// We alias `src/master/implementation` to `src/master/implementation.browser` for web
// browsers already in the package.json, so if get here, it's safe to pass-through the
// node implementation

interface ImplementationExports {
defaultPoolSize: number
selectWorkerImplementation(): typeof WorkerImplementation
}
import * as BrowserImplementation from "./implementation.browser"
import * as NodeImplementation from "./implementation.node"

export default typeof process !== 'undefined' && process.arch !== 'browser' && 'pid' in process
? require('./implementation.node').default as ImplementationExports
: require('./implementation.browser').default as ImplementationExports
const runningInNode = typeof process !== 'undefined' && process.arch !== 'browser' && 'pid' in process
const implementation = runningInNode ? NodeImplementation : BrowserImplementation

export const defaultPoolSize = implementation.defaultPoolSize
export const selectWorkerImplementation = implementation.selectWorkerImplementation
4 changes: 2 additions & 2 deletions src/master/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Worker as WorkerType } from "../types/master"
import Implementation from "./implementation"
import { selectWorkerImplementation } from "./implementation"

export { FunctionThread, ModuleThread } from "../types/master"
export { Pool } from "./pool"
Expand All @@ -9,4 +9,4 @@ export { Thread } from "./thread"
export type Worker = WorkerType

/** Worker implementation. Either web worker or a node.js Worker class. */
export const Worker = Implementation.selectWorkerImplementation()
export const Worker = selectWorkerImplementation()
4 changes: 2 additions & 2 deletions src/master/pool.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import DebugLogger from "debug"
import { multicast, Observable, Subject } from "observable-fns"
import Implementation from "./implementation"
import { defaultPoolSize } from "./implementation"
import {
PoolEvent,
PoolEventType,
Expand Down Expand Up @@ -120,7 +120,7 @@ class WorkerPool<ThreadType extends Thread> implements Pool<ThreadType> {
? { size: optionsOrSize }
: optionsOrSize || {}

const { size = Implementation.defaultPoolSize } = options
const { size = defaultPoolSize } = options

this.debug = DebugLogger(`threads:pool:${slugify(options.name || String(nextPoolID++))}`)
this.options = options
Expand Down
4 changes: 2 additions & 2 deletions src/master/spawn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ import { WorkerFunction, WorkerModule } from "../types/worker"
import { createProxyFunction, createProxyModule } from "./invocation-proxy"

type ArbitraryWorkerInterface = WorkerFunction & WorkerModule<string> & { somekeythatisneverusedinproductioncode123: "magicmarker123" }
type ArbitraryFunctionOrModuleThread = FunctionThread<any, any> & ModuleThread<any>
type ArbitraryThreadType = FunctionThread<any, any> & ModuleThread<any>

type ExposedToThreadType<Exposed extends WorkerFunction | WorkerModule<any>> =
Exposed extends ArbitraryWorkerInterface
? ArbitraryFunctionOrModuleThread
? ArbitraryThreadType
: Exposed extends WorkerFunction
? FunctionThread<Parameters<Exposed>, StripAsync<ReturnType<Exposed>>>
: Exposed extends WorkerModule<any>
Expand Down
14 changes: 10 additions & 4 deletions src/worker/implementation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,21 @@
*/

import { AbstractedWorkerAPI } from "../types/worker"
import WebWorkerImplementation from "./implementation.browser"
import TinyWorkerImplementation from "./implementation.tiny-worker"
import WorkerThreadsImplementation from "./implementation.worker_threads"

const runningInNode = typeof process !== 'undefined' && process.arch !== 'browser' && 'pid' in process

function selectNodeImplementation(): AbstractedWorkerAPI {
try {
return require("./implementation.worker_threads").default
WorkerThreadsImplementation.testImplementation()
return WorkerThreadsImplementation
} catch (error) {
return require("./implementation.tiny-worker").default
return TinyWorkerImplementation
}
}

export default typeof process !== 'undefined' && process.arch !== 'browser' && 'pid' in process
export default runningInNode
? selectNodeImplementation()
: require('./implementation.browser').default as AbstractedWorkerAPI
: WebWorkerImplementation
22 changes: 15 additions & 7 deletions src/worker/implementation.worker_threads.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// tslint:disable no-shadowed-variable
import { MessagePort } from "worker_threads"
import { AbstractedWorkerAPI } from "../types/worker"
import * as WorkerThreads from "../worker_threads"
import WorkerThreads from "../worker_threads"

function assertMessagePort(port: MessagePort | null | undefined): MessagePort {
if (!port) {
Expand All @@ -11,29 +11,37 @@ function assertMessagePort(port: MessagePort | null | undefined): MessagePort {
}

const isWorkerRuntime: AbstractedWorkerAPI["isWorkerRuntime"] = function isWorkerRuntime() {
return !WorkerThreads.isMainThread
return !WorkerThreads().isMainThread
}

const postMessageToMaster: AbstractedWorkerAPI["postMessageToMaster"] = function postMessageToMaster(data, transferList) {
assertMessagePort(WorkerThreads.parentPort).postMessage(data, transferList as any)
assertMessagePort(WorkerThreads().parentPort).postMessage(data, transferList as any)
}

const subscribeToMasterMessages: AbstractedWorkerAPI["subscribeToMasterMessages"] = function subscribeToMasterMessages(onMessage) {
if (!WorkerThreads.parentPort) {
const parentPort = WorkerThreads().parentPort

if (!parentPort) {
throw Error("Invariant violation: MessagePort to parent is not available.")
}
const messageHandler = (message: any) => {
onMessage(message)
}
const unsubscribe = () => {
assertMessagePort(WorkerThreads.parentPort).off("message", messageHandler)
assertMessagePort(parentPort).off("message", messageHandler)
}
assertMessagePort(WorkerThreads.parentPort).on("message", messageHandler)
assertMessagePort(parentPort).on("message", messageHandler)
return unsubscribe
}

function testImplementation() {
// Will throw if `worker_threads` are not available
WorkerThreads()
}

export default {
isWorkerRuntime,
postMessageToMaster,
subscribeToMasterMessages
subscribeToMasterMessages,
testImplementation
}
28 changes: 22 additions & 6 deletions src/worker_threads.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,26 @@

declare function __non_webpack_require__(module: string): any

const workerThreads = typeof __non_webpack_require__ === "function"
? __non_webpack_require__("worker_threads")
: eval("require")("worker_threads")
// FIXME
type MessagePort = any

export const MessagePort = workerThreads.MessagePort
export const isMainThread = workerThreads.isMainThread
export const parentPort = workerThreads.parentPort
interface WorkerThreadsModule {
MessagePort: typeof MessagePort
isMainThread: boolean
parentPort: MessagePort
}

let implementation: WorkerThreadsModule | undefined

function selectImplementation(): WorkerThreadsModule {
return typeof __non_webpack_require__ === "function"
? __non_webpack_require__("worker_threads")
: eval("require")("worker_threads")
}

export default function getImplementation(): WorkerThreadsModule {
if (!implementation) {
implementation = selectImplementation()
}
return implementation
}
Loading

0 comments on commit 4d2acf6

Please sign in to comment.