Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Build and publish ES module build #124

Merged
merged 10 commits into from
Dec 19, 2019
Merged
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
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