runtime.js 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const SortableSet = require("./SortableSet");
  7. /** @typedef {import("../Compilation")} Compilation */
  8. /** @typedef {import("../Entrypoint").EntryOptions} EntryOptions */
  9. /** @typedef {SortableSet<string>} RuntimeSpecSortableSet */
  10. /** @typedef {string | RuntimeSpecSortableSet | undefined} RuntimeSpec */
  11. /** @typedef {RuntimeSpec | boolean} RuntimeCondition */
  12. /**
  13. * Gets entry runtime.
  14. * @param {Compilation} compilation the compilation
  15. * @param {string} name name of the entry
  16. * @param {EntryOptions=} options optionally already received entry options
  17. * @returns {RuntimeSpec} runtime
  18. */
  19. const getEntryRuntime = (compilation, name, options) => {
  20. /** @type {EntryOptions["dependOn"]} */
  21. let dependOn;
  22. /** @type {EntryOptions["runtime"]} */
  23. let runtime;
  24. if (options) {
  25. ({ dependOn, runtime } = options);
  26. } else {
  27. const entry = compilation.entries.get(name);
  28. if (!entry) return name;
  29. ({ dependOn, runtime } = entry.options);
  30. }
  31. if (dependOn) {
  32. /** @type {RuntimeSpec} */
  33. let result;
  34. const queue = new Set(dependOn);
  35. for (const name of queue) {
  36. const dep = compilation.entries.get(name);
  37. if (!dep) continue;
  38. const { dependOn, runtime } = dep.options;
  39. if (dependOn) {
  40. for (const name of dependOn) {
  41. queue.add(name);
  42. }
  43. } else {
  44. result = mergeRuntimeOwned(result, runtime || name);
  45. }
  46. }
  47. return result || name;
  48. }
  49. return runtime || name;
  50. };
  51. /**
  52. * Processes the provided runtime.
  53. * @param {RuntimeSpec} runtime runtime
  54. * @param {(runtime: string | undefined) => void} fn functor
  55. * @param {boolean} deterministicOrder enforce a deterministic order
  56. * @returns {void}
  57. */
  58. const forEachRuntime = (runtime, fn, deterministicOrder = false) => {
  59. if (runtime === undefined) {
  60. fn(undefined);
  61. } else if (typeof runtime === "string") {
  62. fn(runtime);
  63. } else {
  64. if (deterministicOrder) runtime.sort();
  65. for (const r of runtime) {
  66. fn(r);
  67. }
  68. }
  69. };
  70. /**
  71. * Returns runtime key.
  72. * @template T
  73. * @param {Exclude<RuntimeSpec, undefined | string>} set set
  74. * @returns {string} runtime key
  75. */
  76. const getRuntimesKey = (set) => {
  77. set.sort();
  78. return [...set].join("\n");
  79. };
  80. /**
  81. * Returns key of runtimes.
  82. * @param {RuntimeSpec} runtime runtime(s)
  83. * @returns {string} key of runtimes
  84. */
  85. const getRuntimeKey = (runtime) => {
  86. if (runtime === undefined) return "*";
  87. if (typeof runtime === "string") return runtime;
  88. return runtime.getFromUnorderedCache(getRuntimesKey);
  89. };
  90. /**
  91. * Returns runtime(s).
  92. * @param {string} key key of runtimes
  93. * @returns {RuntimeSpec} runtime(s)
  94. */
  95. const keyToRuntime = (key) => {
  96. if (key === "*") return;
  97. const items = key.split("\n");
  98. if (items.length === 1) return items[0];
  99. return new SortableSet(items);
  100. };
  101. /**
  102. * Gets runtimes string.
  103. * @template T
  104. * @param {Exclude<RuntimeSpec, undefined | string>} set set
  105. * @returns {string} runtime string
  106. */
  107. const getRuntimesString = (set) => {
  108. set.sort();
  109. return [...set].join("+");
  110. };
  111. /**
  112. * Returns readable version.
  113. * @param {RuntimeSpec} runtime runtime(s)
  114. * @returns {string} readable version
  115. */
  116. const runtimeToString = (runtime) => {
  117. if (runtime === undefined) return "*";
  118. if (typeof runtime === "string") return runtime;
  119. return runtime.getFromUnorderedCache(getRuntimesString);
  120. };
  121. /**
  122. * Runtime condition to string.
  123. * @param {RuntimeCondition} runtimeCondition runtime condition
  124. * @returns {string} readable version
  125. */
  126. const runtimeConditionToString = (runtimeCondition) => {
  127. if (runtimeCondition === true) return "true";
  128. if (runtimeCondition === false) return "false";
  129. return runtimeToString(runtimeCondition);
  130. };
  131. /**
  132. * Returns true, when they are equal.
  133. * @param {RuntimeSpec} a first
  134. * @param {RuntimeSpec} b second
  135. * @returns {boolean} true, when they are equal
  136. */
  137. const runtimeEqual = (a, b) => {
  138. if (a === b) {
  139. return true;
  140. } else if (
  141. a === undefined ||
  142. b === undefined ||
  143. typeof a === "string" ||
  144. typeof b === "string"
  145. ) {
  146. return false;
  147. } else if (a.size !== b.size) {
  148. return false;
  149. }
  150. a.sort();
  151. b.sort();
  152. const aIt = a[Symbol.iterator]();
  153. const bIt = b[Symbol.iterator]();
  154. for (;;) {
  155. const aV = aIt.next();
  156. if (aV.done) return true;
  157. const bV = bIt.next();
  158. if (aV.value !== bV.value) return false;
  159. }
  160. };
  161. /**
  162. * Compares the provided values and returns their ordering.
  163. * @param {RuntimeSpec} a first
  164. * @param {RuntimeSpec} b second
  165. * @returns {-1 | 0 | 1} compare
  166. */
  167. const compareRuntime = (a, b) => {
  168. if (a === b) {
  169. return 0;
  170. } else if (a === undefined) {
  171. return -1;
  172. } else if (b === undefined) {
  173. return 1;
  174. }
  175. const aKey = getRuntimeKey(a);
  176. const bKey = getRuntimeKey(b);
  177. if (aKey < bKey) return -1;
  178. if (aKey > bKey) return 1;
  179. return 0;
  180. };
  181. /**
  182. * Merges the provided values into a single result.
  183. * @param {RuntimeSpec} a first
  184. * @param {RuntimeSpec} b second
  185. * @returns {RuntimeSpec} merged
  186. */
  187. const mergeRuntime = (a, b) => {
  188. if (a === undefined) {
  189. return b;
  190. } else if (b === undefined) {
  191. return a;
  192. } else if (a === b) {
  193. return a;
  194. } else if (typeof a === "string") {
  195. if (typeof b === "string") {
  196. /** @type {RuntimeSpecSortableSet} */
  197. const set = new SortableSet();
  198. set.add(a);
  199. set.add(b);
  200. return set;
  201. } else if (b.has(a)) {
  202. return b;
  203. }
  204. /** @type {RuntimeSpecSortableSet} */
  205. const set = new SortableSet(b);
  206. set.add(a);
  207. return set;
  208. }
  209. if (typeof b === "string") {
  210. if (a.has(b)) return a;
  211. /** @type {RuntimeSpecSortableSet} */
  212. const set = new SortableSet(a);
  213. set.add(b);
  214. return set;
  215. }
  216. /** @type {RuntimeSpecSortableSet} */
  217. const set = new SortableSet(a);
  218. for (const item of b) set.add(item);
  219. if (set.size === a.size) return a;
  220. return set;
  221. };
  222. /**
  223. * Merges runtime condition.
  224. * @param {RuntimeCondition} a first
  225. * @param {RuntimeCondition} b second
  226. * @param {RuntimeSpec} runtime full runtime
  227. * @returns {RuntimeCondition} result
  228. */
  229. const mergeRuntimeCondition = (a, b, runtime) => {
  230. if (a === false) return b;
  231. if (b === false) return a;
  232. if (a === true || b === true) return true;
  233. const merged = mergeRuntime(a, b);
  234. if (merged === undefined) return;
  235. if (typeof merged === "string") {
  236. if (typeof runtime === "string" && merged === runtime) return true;
  237. return merged;
  238. }
  239. if (typeof runtime === "string" || runtime === undefined) return merged;
  240. if (merged.size === runtime.size) return true;
  241. return merged;
  242. };
  243. /**
  244. * Merges runtime condition non false.
  245. * @param {RuntimeSpec | true} a first
  246. * @param {RuntimeSpec | true} b second
  247. * @param {RuntimeSpec} runtime full runtime
  248. * @returns {RuntimeSpec | true} result
  249. */
  250. const mergeRuntimeConditionNonFalse = (a, b, runtime) => {
  251. if (a === true || b === true) return true;
  252. const merged = mergeRuntime(a, b);
  253. if (merged === undefined) return;
  254. if (typeof merged === "string") {
  255. if (typeof runtime === "string" && merged === runtime) return true;
  256. return merged;
  257. }
  258. if (typeof runtime === "string" || runtime === undefined) return merged;
  259. if (merged.size === runtime.size) return true;
  260. return merged;
  261. };
  262. /**
  263. * Merges runtime owned.
  264. * @param {RuntimeSpec} a first (may be modified)
  265. * @param {RuntimeSpec} b second
  266. * @returns {RuntimeSpec} merged
  267. */
  268. const mergeRuntimeOwned = (a, b) => {
  269. if (b === undefined) {
  270. return a;
  271. } else if (a === b) {
  272. return a;
  273. } else if (a === undefined) {
  274. if (typeof b === "string") {
  275. return b;
  276. }
  277. /** @type {RuntimeSpecSortableSet} */
  278. return new SortableSet(b);
  279. } else if (typeof a === "string") {
  280. if (typeof b === "string") {
  281. /** @type {RuntimeSpecSortableSet} */
  282. const set = new SortableSet();
  283. set.add(a);
  284. set.add(b);
  285. return set;
  286. }
  287. /** @type {RuntimeSpecSortableSet} */
  288. const set = new SortableSet(b);
  289. set.add(a);
  290. return set;
  291. }
  292. if (typeof b === "string") {
  293. a.add(b);
  294. return a;
  295. }
  296. for (const item of b) a.add(item);
  297. return a;
  298. };
  299. /**
  300. * Returns merged.
  301. * @param {RuntimeSpec} a first
  302. * @param {RuntimeSpec} b second
  303. * @returns {RuntimeSpec} merged
  304. */
  305. const intersectRuntime = (a, b) => {
  306. if (a === undefined) {
  307. return b;
  308. } else if (b === undefined) {
  309. return a;
  310. } else if (a === b) {
  311. return a;
  312. } else if (typeof a === "string") {
  313. if (typeof b === "string") {
  314. return;
  315. } else if (b.has(a)) {
  316. return a;
  317. }
  318. return;
  319. }
  320. if (typeof b === "string") {
  321. if (a.has(b)) return b;
  322. return;
  323. }
  324. /** @type {RuntimeSpecSortableSet} */
  325. const set = new SortableSet();
  326. for (const item of b) {
  327. if (a.has(item)) set.add(item);
  328. }
  329. if (set.size === 0) return;
  330. if (set.size === 1) {
  331. const [item] = set;
  332. return item;
  333. }
  334. return set;
  335. };
  336. /**
  337. * Returns result.
  338. * @param {RuntimeSpec} a first
  339. * @param {RuntimeSpec} b second
  340. * @returns {RuntimeSpec} result
  341. */
  342. const subtractRuntime = (a, b) => {
  343. if (a === undefined) {
  344. return;
  345. } else if (b === undefined) {
  346. return a;
  347. } else if (a === b) {
  348. return;
  349. } else if (typeof a === "string") {
  350. if (typeof b === "string") {
  351. return a;
  352. } else if (b.has(a)) {
  353. return;
  354. }
  355. return a;
  356. }
  357. if (typeof b === "string") {
  358. if (!a.has(b)) return a;
  359. if (a.size === 2) {
  360. for (const item of a) {
  361. if (item !== b) return item;
  362. }
  363. }
  364. /** @type {RuntimeSpecSortableSet} */
  365. const set = new SortableSet(a);
  366. set.delete(b);
  367. return set;
  368. }
  369. /** @type {RuntimeSpecSortableSet} */
  370. const set = new SortableSet();
  371. for (const item of a) {
  372. if (!b.has(item)) set.add(item);
  373. }
  374. if (set.size === 0) return;
  375. if (set.size === 1) {
  376. const [item] = set;
  377. return item;
  378. }
  379. return set;
  380. };
  381. /**
  382. * Subtract runtime condition.
  383. * @param {RuntimeCondition} a first
  384. * @param {RuntimeCondition} b second
  385. * @param {RuntimeSpec} runtime runtime
  386. * @returns {RuntimeCondition} result
  387. */
  388. const subtractRuntimeCondition = (a, b, runtime) => {
  389. if (b === true) return false;
  390. if (b === false) return a;
  391. if (a === false) return false;
  392. const result = subtractRuntime(a === true ? runtime : a, b);
  393. return result === undefined ? false : result;
  394. };
  395. /**
  396. * Returns true/false if filter is constant for all runtimes, otherwise runtimes that are active.
  397. * @param {RuntimeSpec} runtime runtime
  398. * @param {(runtime?: RuntimeSpec) => boolean} filter filter function
  399. * @returns {boolean | RuntimeSpec} true/false if filter is constant for all runtimes, otherwise runtimes that are active
  400. */
  401. const filterRuntime = (runtime, filter) => {
  402. if (runtime === undefined) return filter();
  403. if (typeof runtime === "string") return filter(runtime);
  404. let some = false;
  405. let every = true;
  406. /** @type {RuntimeSpec} */
  407. let result;
  408. for (const r of runtime) {
  409. const v = filter(r);
  410. if (v) {
  411. some = true;
  412. result = mergeRuntimeOwned(result, r);
  413. } else {
  414. every = false;
  415. }
  416. }
  417. if (!some) return false;
  418. if (every) return true;
  419. return result;
  420. };
  421. /**
  422. * Defines the runtime spec map inner map type used by this module.
  423. * @template T
  424. * @typedef {Map<string, T>} RuntimeSpecMapInnerMap
  425. */
  426. /**
  427. * Represents RuntimeSpecMap.
  428. * @template T
  429. * @template [R=T]
  430. */
  431. class RuntimeSpecMap {
  432. /**
  433. * Creates an instance of RuntimeSpecMap.
  434. * @param {RuntimeSpecMap<T, R>=} clone copy form this
  435. */
  436. constructor(clone) {
  437. /** @type {0 | 1 | 2} */
  438. this._mode = clone ? clone._mode : 0; // 0 = empty, 1 = single entry, 2 = map
  439. /** @type {RuntimeSpec} */
  440. this._singleRuntime = clone ? clone._singleRuntime : undefined;
  441. /** @type {R | undefined} */
  442. this._singleValue = clone ? clone._singleValue : undefined;
  443. /** @type {RuntimeSpecMapInnerMap<R> | undefined} */
  444. this._map = clone && clone._map ? new Map(clone._map) : undefined;
  445. }
  446. /**
  447. * Returns value.
  448. * @param {RuntimeSpec} runtime the runtimes
  449. * @returns {R | undefined} value
  450. */
  451. get(runtime) {
  452. switch (this._mode) {
  453. case 0:
  454. return;
  455. case 1:
  456. return runtimeEqual(this._singleRuntime, runtime)
  457. ? this._singleValue
  458. : undefined;
  459. default:
  460. return /** @type {RuntimeSpecMapInnerMap<R>} */ (this._map).get(
  461. getRuntimeKey(runtime)
  462. );
  463. }
  464. }
  465. /**
  466. * Returns true, when the runtime is stored.
  467. * @param {RuntimeSpec} runtime the runtimes
  468. * @returns {boolean} true, when the runtime is stored
  469. */
  470. has(runtime) {
  471. switch (this._mode) {
  472. case 0:
  473. return false;
  474. case 1:
  475. return runtimeEqual(this._singleRuntime, runtime);
  476. default:
  477. return /** @type {RuntimeSpecMapInnerMap<R>} */ (this._map).has(
  478. getRuntimeKey(runtime)
  479. );
  480. }
  481. }
  482. /**
  483. * Updates default using the provided runtime.
  484. * @param {RuntimeSpec} runtime the runtimes
  485. * @param {R} value the value
  486. */
  487. set(runtime, value) {
  488. switch (this._mode) {
  489. case 0:
  490. this._mode = 1;
  491. this._singleRuntime = runtime;
  492. this._singleValue = value;
  493. break;
  494. case 1:
  495. if (runtimeEqual(this._singleRuntime, runtime)) {
  496. this._singleValue = value;
  497. break;
  498. }
  499. this._mode = 2;
  500. this._map = new Map();
  501. this._map.set(
  502. getRuntimeKey(this._singleRuntime),
  503. /** @type {R} */ (this._singleValue)
  504. );
  505. this._singleRuntime = undefined;
  506. this._singleValue = undefined;
  507. /* falls through */
  508. default:
  509. /** @type {RuntimeSpecMapInnerMap<R>} */
  510. (this._map).set(getRuntimeKey(runtime), value);
  511. }
  512. }
  513. /**
  514. * Returns the new value.
  515. * @param {RuntimeSpec} runtime the runtimes
  516. * @param {() => R} computer function to compute the value
  517. * @returns {R} the new value
  518. */
  519. provide(runtime, computer) {
  520. switch (this._mode) {
  521. case 0:
  522. this._mode = 1;
  523. this._singleRuntime = runtime;
  524. return (this._singleValue = computer());
  525. case 1: {
  526. if (runtimeEqual(this._singleRuntime, runtime)) {
  527. return /** @type {R} */ (this._singleValue);
  528. }
  529. this._mode = 2;
  530. this._map = new Map();
  531. this._map.set(
  532. getRuntimeKey(this._singleRuntime),
  533. /** @type {R} */
  534. (this._singleValue)
  535. );
  536. this._singleRuntime = undefined;
  537. this._singleValue = undefined;
  538. const newValue = computer();
  539. this._map.set(getRuntimeKey(runtime), newValue);
  540. return newValue;
  541. }
  542. default: {
  543. const key = getRuntimeKey(runtime);
  544. const value =
  545. /** @type {RuntimeSpecMapInnerMap<R>} */
  546. (this._map).get(key);
  547. if (value !== undefined) return value;
  548. const newValue = computer();
  549. /** @type {RuntimeSpecMapInnerMap<R>} */
  550. (this._map).set(key, newValue);
  551. return newValue;
  552. }
  553. }
  554. }
  555. /**
  556. * Processes the provided runtime.
  557. * @param {RuntimeSpec} runtime the runtimes
  558. */
  559. delete(runtime) {
  560. switch (this._mode) {
  561. case 0:
  562. return;
  563. case 1:
  564. if (runtimeEqual(this._singleRuntime, runtime)) {
  565. this._mode = 0;
  566. this._singleRuntime = undefined;
  567. this._singleValue = undefined;
  568. }
  569. return;
  570. default:
  571. /** @type {RuntimeSpecMapInnerMap<R>} */
  572. (this._map).delete(getRuntimeKey(runtime));
  573. }
  574. }
  575. /**
  576. * Processes the provided runtime.
  577. * @param {RuntimeSpec} runtime the runtimes
  578. * @param {(value: R | undefined) => R} fn function to update the value
  579. */
  580. update(runtime, fn) {
  581. switch (this._mode) {
  582. case 0:
  583. throw new Error("runtime passed to update must exist");
  584. case 1: {
  585. if (runtimeEqual(this._singleRuntime, runtime)) {
  586. this._singleValue = fn(this._singleValue);
  587. break;
  588. }
  589. const newValue = fn(undefined);
  590. if (newValue !== undefined) {
  591. this._mode = 2;
  592. this._map = new Map();
  593. this._map.set(
  594. getRuntimeKey(this._singleRuntime),
  595. /** @type {R} */
  596. (this._singleValue)
  597. );
  598. this._singleRuntime = undefined;
  599. this._singleValue = undefined;
  600. this._map.set(getRuntimeKey(runtime), newValue);
  601. }
  602. break;
  603. }
  604. default: {
  605. const key = getRuntimeKey(runtime);
  606. const oldValue =
  607. /** @type {RuntimeSpecMapInnerMap<R>} */
  608. (this._map).get(key);
  609. const newValue = fn(oldValue);
  610. if (newValue !== oldValue) {
  611. /** @type {RuntimeSpecMapInnerMap<R>} */
  612. (this._map).set(key, newValue);
  613. }
  614. }
  615. }
  616. }
  617. keys() {
  618. switch (this._mode) {
  619. case 0:
  620. return [];
  621. case 1:
  622. return [this._singleRuntime];
  623. default:
  624. return Array.from(
  625. /** @type {RuntimeSpecMapInnerMap<R>} */
  626. (this._map).keys(),
  627. keyToRuntime
  628. );
  629. }
  630. }
  631. /**
  632. * Returns values.
  633. * @returns {IterableIterator<R>} values
  634. */
  635. values() {
  636. switch (this._mode) {
  637. case 0:
  638. return [][Symbol.iterator]();
  639. case 1:
  640. return [/** @type {R} */ (this._singleValue)][Symbol.iterator]();
  641. default:
  642. return /** @type {RuntimeSpecMapInnerMap<R>} */ (this._map).values();
  643. }
  644. }
  645. get size() {
  646. if (/** @type {number} */ (this._mode) <= 1) {
  647. return /** @type {number} */ (this._mode);
  648. }
  649. return /** @type {RuntimeSpecMapInnerMap<R>} */ (this._map).size;
  650. }
  651. }
  652. class RuntimeSpecSet {
  653. /**
  654. * Creates an instance of RuntimeSpecSet.
  655. * @param {Iterable<RuntimeSpec>=} iterable iterable
  656. */
  657. constructor(iterable) {
  658. /** @type {Map<string, RuntimeSpec>} */
  659. this._map = new Map();
  660. if (iterable) {
  661. for (const item of iterable) {
  662. this.add(item);
  663. }
  664. }
  665. }
  666. /**
  667. * Processes the provided runtime.
  668. * @param {RuntimeSpec} runtime runtime
  669. */
  670. add(runtime) {
  671. this._map.set(getRuntimeKey(runtime), runtime);
  672. }
  673. /**
  674. * Returns true, when the runtime exists.
  675. * @param {RuntimeSpec} runtime runtime
  676. * @returns {boolean} true, when the runtime exists
  677. */
  678. has(runtime) {
  679. return this._map.has(getRuntimeKey(runtime));
  680. }
  681. /**
  682. * Returns iterable iterator.
  683. * @returns {IterableIterator<RuntimeSpec>} iterable iterator
  684. */
  685. [Symbol.iterator]() {
  686. return this._map.values();
  687. }
  688. get size() {
  689. return this._map.size;
  690. }
  691. }
  692. module.exports.RuntimeSpecMap = RuntimeSpecMap;
  693. module.exports.RuntimeSpecSet = RuntimeSpecSet;
  694. module.exports.compareRuntime = compareRuntime;
  695. module.exports.filterRuntime = filterRuntime;
  696. module.exports.forEachRuntime = forEachRuntime;
  697. module.exports.getEntryRuntime = getEntryRuntime;
  698. module.exports.getRuntimeKey = getRuntimeKey;
  699. module.exports.intersectRuntime = intersectRuntime;
  700. module.exports.keyToRuntime = keyToRuntime;
  701. module.exports.mergeRuntime = mergeRuntime;
  702. module.exports.mergeRuntimeCondition = mergeRuntimeCondition;
  703. module.exports.mergeRuntimeConditionNonFalse = mergeRuntimeConditionNonFalse;
  704. module.exports.mergeRuntimeOwned = mergeRuntimeOwned;
  705. module.exports.runtimeConditionToString = runtimeConditionToString;
  706. module.exports.runtimeEqual = runtimeEqual;
  707. module.exports.runtimeToString = runtimeToString;
  708. module.exports.subtractRuntime = subtractRuntime;
  709. module.exports.subtractRuntimeCondition = subtractRuntimeCondition;