<commit_before>process.stdout.setMaxListeners(Math.pow(10, 6));
process.on(`beforeExit`, (code) => didAnyTestError && process.exit(code || 1));
process.on('unhandledRejection', (reason, p) => {
  console.error('Unhandled Rejection at:', p, 'reason:', reason);
  throw reason;
});

let didAnyTestError = false;

const del = require(`del`);
const gulp = require(`gulp`);
const path = require(`path`);
const pump = require(`pump`);
const chalk = require(`chalk`);
const webpack = require(`webpack`);
const ts = require(`gulp-typescript`);
const streamMerge = require(`merge2`);
const tapdiff = require(`tap-difflet`);
const gulpRename = require(`gulp-rename`);
const sourcemaps = require(`gulp-sourcemaps`);
const child_process = require(`child_process`);
const gulpJsonTransform = require(`gulp-json-transform`);
const UglifyJSPlugin = require(`uglifyjs-webpack-plugin`);
const { spawn: spawnRx, spawnDetached } = require(`spawn-rx`);
const closureCompiler = require(`google-closure-compiler`).gulp();
const esmRequire = require(`@std/esm`)(module, { cjs: true, esm: `js` });
const { Observable, Scheduler, Subject, ReplaySubject } = require(`rxjs`);

const releasesRootDir = `targets`;
const knownTargets = [`es5`, `es2015`, `esnext`];
const knownModules = [`cjs`, `esm`, `cls`, `umd`];
const moduleFormatsToSkipCombosOf = { cls: true };
const metadataFiles = [`LICENSE`, `readme.md`, `CHANGELOG.md`];
const packageJSONFields = [
  `version`, `license`, `description`,
  `author`, `homepage`, `repository`,
  `bugs`, `keywords`,  `dependencies`
];

const argv = require(`command-line-args`)([
  { name: `all`, alias: `a`, type: Boolean },
  { name: `target`, type: String, defaultValue: `` },
  { name: `module`, type: String, defaultValue: `` },
  { name: `loglvl`, alias: `l`, type: Number, defaultValue: 4 },
  { name: `targets`, alias: `t`, type: String, multiple: true, defaultValue: [] },
  { name: `modules`, alias: `m`, type: String, multiple: true, defaultValue: [] }
]);

// ES7+ keywords Uglify shouldn't mangle
// Hardcoded here since some are from ES7+, others are
// only defined in interfaces, so difficult to get by reflection.
const IxKeywords = [
  // GroupedIterable/GroupedAsyncIterable
  `key`,
  // IteratorResult, Symbol.asyncIterator
  `done`, `value`, `asyncIterator`,
  // AsyncObserver
  `values`, `hasError`, `hasCompleted`,`errorValue`, `closed`,
  // Observable/Subscription/Scheduler
  `next`, `error`, `complete`, `subscribe`, `unsubscribe`, `isUnsubscribed`,
  // EventTarget
  `addListener`, `removeListener`, `addEventListener`, `removeEventListener`,
];

// see: https://github.com/google/closure-compiler/blob/c1372b799d94582eaf4b507a4a22558ff26c403c/src/com/google/javascript/jscomp/CompilerOptions.java#L2988
const gCCLanguageNames = {
     es5: `ECMASCRIPT5`,
  es2015: `ECMASCRIPT_2015`,
  es2016: `ECMASCRIPT_2016`,
  es2017: `ECMASCRIPT_2017`,
  esnext: `ECMASCRIPT_NEXT`
};

const UMDSourceTargets = {
  es5: `es5`,
  es2015: `es2015`,
  es2016: `es2015`,
  es2017: `es2015`,
  esnext: `es2015`
};

const uglifyLanguageNames = {
  es5: 5, es2015: 6,
  es2016: 7, es2017: 8,
  esnext: 8 // <--- ?
};

Observable.prototype.logEverything = function(tag = `Observable`, loglevel = argv.loglvl) {
  return this.do({
    next(x) { loglevel <= 1 && console.log(`${tag} next:`, x) },
    error(e) { loglevel <= 3 && console.error(`${tag} error:`, e); },
    complete() { loglevel <= 2 && console.log(`${tag} complete`); }
  }).finally(() => loglevel <= 2 && console.log(`${tag} disposed`));
};

function _die(e) {
  if (e) {
    process.exit(1);
  }
}

Observable.fromStream = function observableFromStreams(...streams) {
  const pumped = streams.length <= 1 ? streams[0] : pump(...streams, _die);
  const fromEvent = Observable.fromEvent.bind(null, pumped);
  const streamObs = fromEvent(`data`)
             .merge(fromEvent(`error`).flatMap((e) => Observable.throw(e)))
         .takeUntil(fromEvent(`end`).merge(fromEvent(`close`)))
         .defaultIfEmpty(`empty stream`)
         .logEverything(`fromStream`)
         .multicast(new ReplaySubject()).refCount();
  streamObs.stream = pumped;
  streamObs.observable = streamObs;
  return streamObs;
};

const memoizeTask = ((cache, taskFn) => ((target, format, ...args) => {
  // Give the memoized fn a displayName so gulp's output is easier to follow.
  const fn = () => (
    cache[_taskHash(target, format, ...args)] || (
    cache[_taskHash(target, format, ...args)] = taskFn(target, format, ...args)
                                               .logEverything(fn.displayName)));
  fn.displayName = `${taskFn.name || ``}:${_taskHash(target, format, ...args)}:task`;
  return fn;
}));

const cleanTask = ((cache) => memoizeTask(cache, function clean(target, format) {
  return Observable.from(del(`${_dir(target, format)}/**`)).multicast(new ReplaySubject()).refCount();
}))({});

const buildTask = ((cache) => memoizeTask(cache, function build(target, format, ...args) {
  return target === `ts`  ? copyTSSources(target, format, ...args)()
       : target === `ix`  ? copyIxTargets(target, format, ...args)()
       : format === `umd` ? target === `es5` 
                          ?  compileClosure(target, format, ...args)()
                          : compileUglifyJS(target, format, ...args)()
       : format === `cls` && target === `es5`
                          ?  compileTsickle(target, format, ...args)()
                          : compileTypescript(target, format, ...args)();
}))({});

const bundleTask = ((cache) => memoizeTask(cache, function bundle(target, format) {
  const out = _dir(target, format);
  const jsonTransform = gulpJsonTransform(target === `ix` ? createIxPackageJson(target, format) :
                                          target === `ts` ? createTsPackageJson(target, format) :
                                                            createScopedPackage(target, format) ,
                                          2);
  return Observable.forkJoin(
    Observable.fromStream(gulp.src(metadataFiles), gulp.dest(out)), // copy metadata files
    Observable.fromStream(gulp.src(`package.json`), jsonTransform, gulp.dest(out)) // write packageJSONs
  );
}))({});

const tapePath = require.resolve(`tape/bin/tape`);
const tsNodePath = require.resolve(`ts-node/dist/bin`);
const tapDiffPath = require.resolve(`tap-difflet/bin/tap-difflet`);
const testsTask = ((cache, execArgv, testOptions) => memoizeTask(cache, function tests(target, format, debug) {
  const opts = { ...testOptions };
  const args = !debug ? execArgv : [...execArgv, `--inspect-brk`];
  opts.env = { ...opts.env, IX_TARGET: target, IX_MODULE: format };
  // do it this way instead once https://github.com/paulcbetts/spawn-rx/pull/18 is merged and published
  // return spawnDetached(tapDiffPath, [`-p`], {
  // stdin: spawnDetached(tsNodePath, [...args, `spec/index.ts`], opts)
  // })
  return Observable.create((subscriber) => {
    const taps = new Subject();
    const diff = spawnDetached(tapDiffPath, [`-p`], { stdin: taps });
    const tape = spawnDetached(tsNodePath, [...args, `spec/index.ts`], opts);
    return subscriber.add(
      diff.subscribe(subscriber),
      tape.subscribe({
        next: taps.next.bind(taps),
        error: taps.complete.bind(taps),
        complete: taps.complete.bind(taps),
      })
    );
  })
  .filter((x) => x && x.trim())
  .map((x) => x.replace(`\n`, ``))
  .materialize().toArray()
  .flatMap((out) => {
    let res = Observable.of;
    let last = out[out.length - 2];
    let terminator = out[out.length - 1];
    let message = last && last.value || ``;
    if (terminator.kind === `E`) {
      didAnyTestError = true;
      res = Observable.throw;
      message = chalk.red(`\n${
        out.slice(0, -1).map(({ value }) => value).join(`\n`)
      }\n`);
    } else if (message) {
      process.stdout.write(chalk.green(message) + `\n`);
    }
    return res({ stack: message });
  })
  .multicast(new ReplaySubject()).refCount();
}))({},
  [`--disableWarnings`, `--harmony_async_iteration`],
  {
    env: {
      ...process.env,
      TS_NODE_TYPE_CHECK: false,
      TS_NODE_CACHE: false, TS_NODE_FAST: true,
      TS_NODE_PROJECT:  `./spec/tsconfig.json`,
    }
  }
);

const copyTSSources = ((cache) => memoizeTask(cache, function copyTS(target, format) {
  return Observable.fromStream(gulp.src(`src/**/*`), gulp.dest(_dir(target, format)));
}))({});

const copyIxTargets = ((cache) => memoizeTask(cache, function copyIx(target, format) {
  const out = _dir(target), srcGlob = `src/**/*`;
  const es5Glob = `${_dir(`es5`, `cjs`)}/**/*.js`;
  const esmGlob = `${_dir(`es2015`, `esm`)}/**/*.js`;
  const es5UmdGlob = `${_dir(`es5`, `umd`)}/**/*.js`;
  const es5UmdMaps = `${_dir(`es5`, `umd`)}/**/*.map`;
  const es2015UmdGlob = `${_dir(`es2015`, `umd`)}/**/*.js`;
  const es2015UmdMaps = `${_dir(`es2015`, `umd`)}/**/*.map`;
  const ch_ext = (ext) => gulpRename((p) => { p.extname = ext; });
  const append = (ap) => gulpRename((p) => { p.basename += ap; });
  return Observable.forkJoin(
    Observable.fromStream(gulp.src(srcGlob), gulp.dest(out)), // copy src ts files
    Observable.fromStream(gulp.src(es5Glob), gulp.dest(out)), // copy es5 cjs files
    Observable.fromStream(gulp.src(esmGlob), ch_ext(`.mjs`), gulp.dest(out)), // copy es2015 esm files and rename to `.mjs`
    Observable.fromStream(gulp.src(es5UmdGlob), append(`.es5.min`), gulp.dest(out)), // copy es5 umd files and add `.min`
    Observable.fromStream(gulp.src(es5UmdMaps),                     gulp.dest(out)), // copy es5 umd sourcemap files, but don't rename
    Observable.fromStream(gulp.src(es2015UmdGlob), append(`.es2015.min`), gulp.dest(out)), // copy es2015 umd files and add `.es6.min`
    Observable.fromStream(gulp.src(es2015UmdMaps),                        gulp.dest(out)), // copy es2015 umd sourcemap files, but don't rename
  );
}))({});

const compileTsickle = ((cache, tsicklePath) => memoizeTask(cache, function tsickle(target, format) {
  return spawnRx(tsicklePath,
    [
      `--typed`, `--externs`,
        `${_dir(target, format)}/Ix.externs.js`,
      `--`, `-p`, `tsconfig/${_tsconfig(target, format)}`
    ],
    { stdio: [`ignore`, `inherit`, `inherit`] }
  ).multicast(new ReplaySubject()).refCount();
}))({}, require.resolve(`tsickle/built/src/main`));
  
const compileTypescript = ((cache) => memoizeTask(cache, function typescript(target, format) {
  const out = _dir(target, format);
  const tsconfigFile = `tsconfig.${_tsconfig(target, format)}.json`;
  const tsProject = ts.createProject(path.join(`tsconfig`, tsconfigFile));
  const { observable: compilation, stream: { js, dts } } = Observable.fromStream(
    tsProject.src(), sourcemaps.init(),
    tsProject(ts.reporter.fullReporter(true))
  );
  const writeDTypes = Observable.fromStream(dts, gulp.dest(out));
  const writeJS = Observable.fromStream(js, sourcemaps.write(), gulp.dest(out));
  return Observable.forkJoin(compilation, writeDTypes, writeJS);
}))({});

const compileUglifyJS = ((cache, commonConfig) => memoizeTask(cache, function uglifyJS(target, format) {

  const sourceTarget = UMDSourceTargets[target];
  const PublicNames = reservePublicNames(sourceTarget, `cls`);
  const InternalNames = reserveInternalNames(sourceTarget, `cls`);
  const out = _dir(target, format), src = _dir(sourceTarget, `cls`);

  const targetConfig = {
              ...commonConfig,
    output: { ...commonConfig.output,
       path: path.join(process.cwd(), `${out}/`) } };

  const webpackConfigs = [
    [`Ix`, PublicNames],
    [`Ix.Internal`, InternalNames]
  ].map(([entry, reserved]) => ({
    ...targetConfig, 
    entry: { [entry]: path.resolve(`${src}/${entry}.js`) },
    plugins: [
      ...(targetConfig.plugins || []),
      new webpack.SourceMapDevToolPlugin({
        filename: `[name].${target}.min.js.map`,
        moduleFilenameTemplate: ({ resourcePath }) =>
          resourcePath
            .replace(/\s/, `_`)
            .replace(/\.\/node_modules\//, '')
      }),
      new UglifyJSPlugin({
        sourceMap: true,
        uglifyOptions: {
          ecma: uglifyLanguageNames[target],
          compress: { unsafe: true, },
          output: { comments: false, beautify: false },
          mangle: { eval: true, safari10: true, // <-- Works around a Safari 10 bug: // https://github.com/mishoo/UglifyJS2/issues/1753
              properties: { reserved }, reserved,
          }
        },
      })
    ]
  }));

  const compilers = webpack(webpackConfigs);

  return Observable
    .bindNodeCallback(compilers.run.bind(compilers))()
    .multicast(new ReplaySubject()).refCount();

}))({}, {
  resolve: { mainFields: [`module`, `main`] },
  output: { filename: '[name].js', library: `Ix`, libraryTarget: `umd`, },
  module: { rules: [{ test: /\.js$/, enforce: `pre`, use: [`source-map-loader`] }] }
});

const compileClosure = ((cache) => memoizeTask(cache, function closure(target, format) {
  const src = _dir(target, `cls`), out = _dir(target, format);
  const closureStreams = [
             [`Ix`, `Ix.internal`],
             [`Ix.internal`, `Ix`]
      ].map(([entry, otherEntryFile]) => [
    gulp.src([
  /*   tslib comes first, --> */`scripts/tslib.js`,  
 /*   then sources glob, --> */ `${src}/**/*.js`,
/*  and exclusions last --> */ `!${src}/Ix.externs.js`,
                               `!${src}/${otherEntryFile}.js`
    ], { base: `./` }), sourcemaps.init(),
    closureCompiler(createClosureArgs(target, entry, `${src}/Ix.externs.js`)),
    // rename the sourcemaps from *.js.map files to *.min.js.map
    sourcemaps.write('.', { mapFile: (mapPath) => mapPath.replace(`.js.map`, `.${target}.min.js.map`) }),
    gulp.dest(out)
  ]);
  return Observable.forkJoin(closureStreams.map((streams) => Observable.fromStream(...streams)));
}))({});

const createIxPackageJson = (target, format) => (orig) => ({
  ...createTsPackageJson(target, format)(orig),
  name: orig.name,
  main: `Ix.js`,
  module: `Ix.mjs`,
  browser: `Ix.min.js`,
  [`@std/esm`]: { esm: `mjs` }
});

const createTsPackageJson = (target, format) => (orig) => ({
  ...createScopedPackage(target, format)(orig),
  main: `Ix.ts`, types: `Ix.ts`
});

const createScopedPackage = (target, format) => (({ name, ...orig }) =>
  conditionallyAddStandardESMEntry(target, format)(
    packageJSONFields.reduce(
      (xs, key) => ({ ...xs, [key]: xs[key] || orig[key] }),
      { name: `@reactivex/${name}-${_name(target, format)}`,
        version: undefined, main: `Ix.js`, types: `Ix.d.ts`,
        module: undefined, browser: undefined, [`@std/esm`]: undefined }
    )
  )
);

const conditionallyAddStandardESMEntry = (target, format) => (packageJSON) => (
  format !== `esm`
    ? packageJSON
    : { ...packageJSON, [`@std/esm`]: { esm: `js` } }
);

const createClosureArgs = (target, entry, externs) => ({<commit_msg>build(package.json): remove .js extension so node selects its desired main file<commit_after>process.stdout.setMaxListeners(Math.pow(10, 6));
process.on(`beforeExit`, (code) => didAnyTestError && process.exit(code || 1));
process.on('unhandledRejection', (reason, p) => {
  console.error('Unhandled Rejection at:', p, 'reason:', reason);
  throw reason;
});

let didAnyTestError = false;

const del = require(`del`);
const gulp = require(`gulp`);
const path = require(`path`);
const pump = require(`pump`);
const chalk = require(`chalk`);
const webpack = require(`webpack`);
const ts = require(`gulp-typescript`);
const streamMerge = require(`merge2`);
const tapdiff = require(`tap-difflet`);
const gulpRename = require(`gulp-rename`);
const sourcemaps = require(`gulp-sourcemaps`);
const child_process = require(`child_process`);
const gulpJsonTransform = require(`gulp-json-transform`);
const UglifyJSPlugin = require(`uglifyjs-webpack-plugin`);
const { spawn: spawnRx, spawnDetached } = require(`spawn-rx`);
const closureCompiler = require(`google-closure-compiler`).gulp();
const esmRequire = require(`@std/esm`)(module, { cjs: true, esm: `js` });
const { Observable, Scheduler, Subject, ReplaySubject } = require(`rxjs`);

const releasesRootDir = `targets`;
const knownTargets = [`es5`, `es2015`, `esnext`];
const knownModules = [`cjs`, `esm`, `cls`, `umd`];
const moduleFormatsToSkipCombosOf = { cls: true };
const metadataFiles = [`LICENSE`, `readme.md`, `CHANGELOG.md`];
const packageJSONFields = [
  `version`, `license`, `description`,
  `author`, `homepage`, `repository`,
  `bugs`, `keywords`,  `dependencies`
];

const argv = require(`command-line-args`)([
  { name: `all`, alias: `a`, type: Boolean },
  { name: `target`, type: String, defaultValue: `` },
  { name: `module`, type: String, defaultValue: `` },
  { name: `loglvl`, alias: `l`, type: Number, defaultValue: 4 },
  { name: `targets`, alias: `t`, type: String, multiple: true, defaultValue: [] },
  { name: `modules`, alias: `m`, type: String, multiple: true, defaultValue: [] }
]);

// ES7+ keywords Uglify shouldn't mangle
// Hardcoded here since some are from ES7+, others are
// only defined in interfaces, so difficult to get by reflection.
const IxKeywords = [
  // GroupedIterable/GroupedAsyncIterable
  `key`,
  // IteratorResult, Symbol.asyncIterator
  `done`, `value`, `asyncIterator`,
  // AsyncObserver
  `values`, `hasError`, `hasCompleted`,`errorValue`, `closed`,
  // Observable/Subscription/Scheduler
  `next`, `error`, `complete`, `subscribe`, `unsubscribe`, `isUnsubscribed`,
  // EventTarget
  `addListener`, `removeListener`, `addEventListener`, `removeEventListener`,
];

// see: https://github.com/google/closure-compiler/blob/c1372b799d94582eaf4b507a4a22558ff26c403c/src/com/google/javascript/jscomp/CompilerOptions.java#L2988
const gCCLanguageNames = {
     es5: `ECMASCRIPT5`,
  es2015: `ECMASCRIPT_2015`,
  es2016: `ECMASCRIPT_2016`,
  es2017: `ECMASCRIPT_2017`,
  esnext: `ECMASCRIPT_NEXT`
};

const UMDSourceTargets = {
  es5: `es5`,
  es2015: `es2015`,
  es2016: `es2015`,
  es2017: `es2015`,
  esnext: `es2015`
};

const uglifyLanguageNames = {
  es5: 5, es2015: 6,
  es2016: 7, es2017: 8,
  esnext: 8 // <--- ?
};

Observable.prototype.logEverything = function(tag = `Observable`, loglevel = argv.loglvl) {
  return this.do({
    next(x) { loglevel <= 1 && console.log(`${tag} next:`, x) },
    error(e) { loglevel <= 3 && console.error(`${tag} error:`, e); },
    complete() { loglevel <= 2 && console.log(`${tag} complete`); }
  }).finally(() => loglevel <= 2 && console.log(`${tag} disposed`));
};

function _die(e) {
  if (e) {
    process.exit(1);
  }
}

Observable.fromStream = function observableFromStreams(...streams) {
  const pumped = streams.length <= 1 ? streams[0] : pump(...streams, _die);
  const fromEvent = Observable.fromEvent.bind(null, pumped);
  const streamObs = fromEvent(`data`)
             .merge(fromEvent(`error`).flatMap((e) => Observable.throw(e)))
         .takeUntil(fromEvent(`end`).merge(fromEvent(`close`)))
         .defaultIfEmpty(`empty stream`)
         .logEverything(`fromStream`)
         .multicast(new ReplaySubject()).refCount();
  streamObs.stream = pumped;
  streamObs.observable = streamObs;
  return streamObs;
};

const memoizeTask = ((cache, taskFn) => ((target, format, ...args) => {
  // Give the memoized fn a displayName so gulp's output is easier to follow.
  const fn = () => (
    cache[_taskHash(target, format, ...args)] || (
    cache[_taskHash(target, format, ...args)] = taskFn(target, format, ...args)
                                               .logEverything(fn.displayName)));
  fn.displayName = `${taskFn.name || ``}:${_taskHash(target, format, ...args)}:task`;
  return fn;
}));

const cleanTask = ((cache) => memoizeTask(cache, function clean(target, format) {
  return Observable.from(del(`${_dir(target, format)}/**`)).multicast(new ReplaySubject()).refCount();
}))({});

const buildTask = ((cache) => memoizeTask(cache, function build(target, format, ...args) {
  return target === `ts`  ? copyTSSources(target, format, ...args)()
       : target === `ix`  ? copyIxTargets(target, format, ...args)()
       : format === `umd` ? target === `es5` 
                          ?  compileClosure(target, format, ...args)()
                          : compileUglifyJS(target, format, ...args)()
       : format === `cls` && target === `es5`
                          ?  compileTsickle(target, format, ...args)()
                          : compileTypescript(target, format, ...args)();
}))({});

const bundleTask = ((cache) => memoizeTask(cache, function bundle(target, format) {
  const out = _dir(target, format);
  const jsonTransform = gulpJsonTransform(target === `ix` ? createIxPackageJson(target, format) :
                                          target === `ts` ? createTsPackageJson(target, format) :
                                                            createScopedPackage(target, format) ,
                                          2);
  return Observable.forkJoin(
    Observable.fromStream(gulp.src(metadataFiles), gulp.dest(out)), // copy metadata files
    Observable.fromStream(gulp.src(`package.json`), jsonTransform, gulp.dest(out)) // write packageJSONs
  );
}))({});

const tapePath = require.resolve(`tape/bin/tape`);
const tsNodePath = require.resolve(`ts-node/dist/bin`);
const tapDiffPath = require.resolve(`tap-difflet/bin/tap-difflet`);
const testsTask = ((cache, execArgv, testOptions) => memoizeTask(cache, function tests(target, format, debug) {
  const opts = { ...testOptions };
  const args = !debug ? execArgv : [...execArgv, `--inspect-brk`];
  opts.env = { ...opts.env, IX_TARGET: target, IX_MODULE: format };
  // do it this way instead once https://github.com/paulcbetts/spawn-rx/pull/18 is merged and published
  // return spawnDetached(tapDiffPath, [`-p`], {
  // stdin: spawnDetached(tsNodePath, [...args, `spec/index.ts`], opts)
  // })
  return Observable.create((subscriber) => {
    const taps = new Subject();
    const diff = spawnDetached(tapDiffPath, [`-p`], { stdin: taps });
    const tape = spawnDetached(tsNodePath, [...args, `spec/index.ts`], opts);
    return subscriber.add(
      diff.subscribe(subscriber),
      tape.subscribe({
        next: taps.next.bind(taps),
        error: taps.complete.bind(taps),
        complete: taps.complete.bind(taps),
      })
    );
  })
  .filter((x) => x && x.trim())
  .map((x) => x.replace(`\n`, ``))
  .materialize().toArray()
  .flatMap((out) => {
    let res = Observable.of;
    let last = out[out.length - 2];
    let terminator = out[out.length - 1];
    let message = last && last.value || ``;
    if (terminator.kind === `E`) {
      didAnyTestError = true;
      res = Observable.throw;
      message = chalk.red(`\n${
        out.slice(0, -1).map(({ value }) => value).join(`\n`)
      }\n`);
    } else if (message) {
      process.stdout.write(chalk.green(message) + `\n`);
    }
    return res({ stack: message });
  })
  .multicast(new ReplaySubject()).refCount();
}))({},
  [`--disableWarnings`, `--harmony_async_iteration`],
  {
    env: {
      ...process.env,
      TS_NODE_TYPE_CHECK: false,
      TS_NODE_CACHE: false, TS_NODE_FAST: true,
      TS_NODE_PROJECT:  `./spec/tsconfig.json`,
    }
  }
);

const copyTSSources = ((cache) => memoizeTask(cache, function copyTS(target, format) {
  return Observable.fromStream(gulp.src(`src/**/*`), gulp.dest(_dir(target, format)));
}))({});

const copyIxTargets = ((cache) => memoizeTask(cache, function copyIx(target, format) {
  const out = _dir(target), srcGlob = `src/**/*`;
  const es5Glob = `${_dir(`es5`, `cjs`)}/**/*.js`;
  const esmGlob = `${_dir(`es2015`, `esm`)}/**/*.js`;
  const es5UmdGlob = `${_dir(`es5`, `umd`)}/**/*.js`;
  const es5UmdMaps = `${_dir(`es5`, `umd`)}/**/*.map`;
  const es2015UmdGlob = `${_dir(`es2015`, `umd`)}/**/*.js`;
  const es2015UmdMaps = `${_dir(`es2015`, `umd`)}/**/*.map`;
  const ch_ext = (ext) => gulpRename((p) => { p.extname = ext; });
  const append = (ap) => gulpRename((p) => { p.basename += ap; });
  return Observable.forkJoin(
    Observable.fromStream(gulp.src(srcGlob), gulp.dest(out)), // copy src ts files
    Observable.fromStream(gulp.src(es5Glob), gulp.dest(out)), // copy es5 cjs files
    Observable.fromStream(gulp.src(esmGlob), ch_ext(`.mjs`), gulp.dest(out)), // copy es2015 esm files and rename to `.mjs`
    Observable.fromStream(gulp.src(es5UmdGlob), append(`.es5.min`), gulp.dest(out)), // copy es5 umd files and add `.min`
    Observable.fromStream(gulp.src(es5UmdMaps),                     gulp.dest(out)), // copy es5 umd sourcemap files, but don't rename
    Observable.fromStream(gulp.src(es2015UmdGlob), append(`.es2015.min`), gulp.dest(out)), // copy es2015 umd files and add `.es6.min`
    Observable.fromStream(gulp.src(es2015UmdMaps),                        gulp.dest(out)), // copy es2015 umd sourcemap files, but don't rename
  );
}))({});

const compileTsickle = ((cache, tsicklePath) => memoizeTask(cache, function tsickle(target, format) {
  return spawnRx(tsicklePath,
    [
      `--typed`, `--externs`,
        `${_dir(target, format)}/Ix.externs.js`,
      `--`, `-p`, `tsconfig/${_tsconfig(target, format)}`
    ],
    { stdio: [`ignore`, `inherit`, `inherit`] }
  ).multicast(new ReplaySubject()).refCount();
}))({}, require.resolve(`tsickle/built/src/main`));
  
const compileTypescript = ((cache) => memoizeTask(cache, function typescript(target, format) {
  const out = _dir(target, format);
  const tsconfigFile = `tsconfig.${_tsconfig(target, format)}.json`;
  const tsProject = ts.createProject(path.join(`tsconfig`, tsconfigFile));
  const { observable: compilation, stream: { js, dts } } = Observable.fromStream(
    tsProject.src(), sourcemaps.init(),
    tsProject(ts.reporter.fullReporter(true))
  );
  const writeDTypes = Observable.fromStream(dts, gulp.dest(out));
  const writeJS = Observable.fromStream(js, sourcemaps.write(), gulp.dest(out));
  return Observable.forkJoin(compilation, writeDTypes, writeJS);
}))({});

const compileUglifyJS = ((cache, commonConfig) => memoizeTask(cache, function uglifyJS(target, format) {

  const sourceTarget = UMDSourceTargets[target];
  const PublicNames = reservePublicNames(sourceTarget, `cls`);
  const InternalNames = reserveInternalNames(sourceTarget, `cls`);
  const out = _dir(target, format), src = _dir(sourceTarget, `cls`);

  const targetConfig = {
              ...commonConfig,
    output: { ...commonConfig.output,
       path: path.join(process.cwd(), `${out}/`) } };

  const webpackConfigs = [
    [`Ix`, PublicNames],
    [`Ix.Internal`, InternalNames]
  ].map(([entry, reserved]) => ({
    ...targetConfig, 
    entry: { [entry]: path.resolve(`${src}/${entry}.js`) },
    plugins: [
      ...(targetConfig.plugins || []),
      new webpack.SourceMapDevToolPlugin({
        filename: `[name].${target}.min.js.map`,
        moduleFilenameTemplate: ({ resourcePath }) =>
          resourcePath
            .replace(/\s/, `_`)
            .replace(/\.\/node_modules\//, '')
      }),
      new UglifyJSPlugin({
        sourceMap: true,
        uglifyOptions: {
          ecma: uglifyLanguageNames[target],
          compress: { unsafe: true, },
          output: { comments: false, beautify: false },
          mangle: { eval: true, safari10: true, // <-- Works around a Safari 10 bug: // https://github.com/mishoo/UglifyJS2/issues/1753
              properties: { reserved }, reserved,
          }
        },
      })
    ]
  }));

  const compilers = webpack(webpackConfigs);

  return Observable
    .bindNodeCallback(compilers.run.bind(compilers))()
    .multicast(new ReplaySubject()).refCount();

}))({}, {
  resolve: { mainFields: [`module`, `main`] },
  output: { filename: '[name].js', library: `Ix`, libraryTarget: `umd`, },
  module: { rules: [{ test: /\.js$/, enforce: `pre`, use: [`source-map-loader`] }] }
});

const compileClosure = ((cache) => memoizeTask(cache, function closure(target, format) {
  const src = _dir(target, `cls`), out = _dir(target, format);
  const closureStreams = [
             [`Ix`, `Ix.internal`],
             [`Ix.internal`, `Ix`]
      ].map(([entry, otherEntryFile]) => [
    gulp.src([
  /*   tslib comes first, --> */`scripts/tslib.js`,  
 /*   then sources glob, --> */ `${src}/**/*.js`,
/*  and exclusions last --> */ `!${src}/Ix.externs.js`,
                               `!${src}/${otherEntryFile}.js`
    ], { base: `./` }), sourcemaps.init(),
    closureCompiler(createClosureArgs(target, entry, `${src}/Ix.externs.js`)),
    // rename the sourcemaps from *.js.map files to *.min.js.map
    sourcemaps.write('.', { mapFile: (mapPath) => mapPath.replace(`.js.map`, `.${target}.min.js.map`) }),
    gulp.dest(out)
  ]);
  return Observable.forkJoin(closureStreams.map((streams) => Observable.fromStream(...streams)));
}))({});

const createIxPackageJson = (target, format) => (orig) => ({
  ...createTsPackageJson(target, format)(orig),
  name: orig.name,
  main: `Ix`,
  module: `Ix.mjs`,
  browser: `Ix.es5.min.js`,
  [`@std/esm`]: { esm: `mjs` },
  [`browser:es2015`]: `Ix.es2015.min.js`,
});

const createTsPackageJson = (target, format) => (orig) => ({
  ...createScopedPackage(target, format)(orig),
  main: `Ix.ts`, types: `Ix.ts`
});

const createScopedPackage = (target, format) => (({ name, ...orig }) =>
  conditionallyAddStandardESMEntry(target, format)(
    packageJSONFields.reduce(
      (xs, key) => ({ ...xs, [key]: xs[key] || orig[key] }),
      { name: `@reactivex/${name}-${_name(target, format)}`,
        version: undefined, main: `Ix.js`, types: `Ix.d.ts`,
        browser: undefined, [`browser:es2015`]: undefined,
        module: undefined, [`@std/esm`]: undefined }
    )
  )
);

const conditionallyAddStandardESMEntry = (target, format) => (packageJSON) => (
  format !== `esm`
    ? packageJSON
    : { ...packageJSON, [`@std/esm`]: { esm: `js` } }
);

const createClosureArgs = (target, entry, externs) => ({
{'fraction_non_alphanumeric': 0.1905735644128591, 'fraction_numerical': 0.01391170259126412, 'mean_word_length': 3.5145278450363198, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 91, 'https://': 6, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 16, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6904120', 'n_tokens_mistral': 10229, 'n_tokens_neox': 9939, 'n_words': 2052}