OverviewFilesCommitsIssuesDocsReleasesPeers

mirall-cli / node_modules / bare-thread / index.js

145 lines · javascript ref:
const Bundle = require('bare-bundle')
const traverse = require('bare-module-traverse')
const { startsWithWindowsDriveLetter } = require('bare-module-resolve')
const { pathToFileURL } = require('bare-url')
const constants = require('./lib/constants')
const binding = require('./binding')

const { protocol, imports, resolutions } = module

module.exports = exports = class Thread {
  constructor(entry, opts = {}) {
    let source

    if (Buffer.isBuffer(entry)) source = entry
    else source = Thread.prepare(entry, { shared: true })

    this._thread = new Bare.Thread('bare:/thread.bundle', { ...opts, source })
  }

  get joined() {
    return this._thread.joined
  }

  join() {
    this._thread.join()
  }

  suspend(linger) {
    this._thread.suspend(linger)
  }

  wakeup(deadline) {
    this._thread.wakeup(deadline)
  }

  resume() {
    this._thread.resume()
  }

  terminate() {
    this._thread.terminate()
  }

  [Symbol.for('bare.inspect')]() {
    return {
      __proto__: { constructor: Thread },

      joined: this.joined
    }
  }

  static get cpu() {
    return binding.getCPU()
  }

  static get id() {
    return binding.getID()
  }

  static get name() {
    return binding.getName()
  }

  static set name(name) {
    if (typeof name !== 'string') name = name.toString()

    binding.setName(name)
  }

  static get priority() {
    return binding.getPriority()
  }

  static set priority(priority) {
    binding.setPriority(priority)
  }
}

exports.isMainThread = Bare.Thread.isMainThread

exports.self = Bare.Thread.self

exports.prepare = function prepare(entry, opts) {
  if (startsWithWindowsDriveLetter(entry)) entry = '/' + entry

  let base = pathToFileURL('./')

  // If `bare-thread` itself was loaded from within a bundle, its module URL
  // contains a `.bundle` segment. When the entry resolves to a location inside
  // that same bundle, prepare it relative to the bundle so that its sources are
  // read back out of the bundle rather than from disk.
  const root = bundleURL(module.url)

  if (root !== null) {
    const resolved = new URL(entry, root)

    if (resolved.href.startsWith(root.href)) base = root
  }

  entry = new URL(entry, base)

  const bundle = new Bundle()

  for (const dependency of traverse(
    entry,
    {
      imports,
      resolutions,
      resolve: traverse.resolve.bare
    },
    readModule
  )) {
    const { url, source, imports } = dependency

    bundle.write(url.href, source, {
      main: url.href === entry.href,
      imports
    })
  }

  return bundle.toBuffer(opts)
}

function readModule(url) {
  if (protocol.exists(url)) return protocol.read(url)

  return null
}

function bundleURL(url) {
  const segments = url.pathname.split('/')

  let i = -1

  for (let j = 0; j < segments.length; j++) {
    if (segments[j].endsWith('.bundle')) i = j
  }

  if (i === -1) return null

  return new URL(segments.slice(0, i + 1).join('/') + '/', url)
}

exports.constants = constants