(src)
| 625 | * }>} |
| 626 | */ |
| 627 | export async function parseScript(src) { |
| 628 | const { meta, errors } = src.meta ? src : parseMetaWithErrors(src); |
| 629 | if (!meta.name) throw `${i18n('msgInvalidScript')}\n${i18n('labelNoName')}`; |
| 630 | const update = { |
| 631 | message: src.message == null ? i18n('msgUpdated') : src.message || '', |
| 632 | }; |
| 633 | const result = { errors, update }; |
| 634 | const { [S_CODE]: code, update: srcUpdate } = src; |
| 635 | const now = Date.now(); |
| 636 | let { id } = src; |
| 637 | let script; |
| 638 | let oldScript = getScript({ id, meta }); |
| 639 | if (oldScript) { |
| 640 | script = oldScript; |
| 641 | id = script.props.id; |
| 642 | } else { |
| 643 | ({ script } = newScript()); |
| 644 | maxScriptId++; |
| 645 | id = script.props.id = maxScriptId; |
| 646 | result.isNew = true; |
| 647 | update.message = i18n('msgInstalled'); |
| 648 | aliveScripts.push(script); |
| 649 | } |
| 650 | const { config, custom, props } = script; |
| 651 | const uri = getNameURI({ meta, props: {id} }); |
| 652 | if (oldScript) { |
| 653 | // Do not allow script with same name and namespace |
| 654 | if (src.isNew || id && aliveScripts.some(({ props: p }) => uri === p.uri && id !== p.id)) { |
| 655 | throw i18n('msgNamespaceConflict'); |
| 656 | } |
| 657 | delete script[INFERRED]; |
| 658 | } |
| 659 | props.lastModified = now; |
| 660 | props.uuid = props.uuid || getUUID(); |
| 661 | // Overwriting inner data by `src`, deleting keys for which `src` specifies `null` |
| 662 | for (const key of ['config', 'custom', 'props']) { |
| 663 | const dst = script[key]; |
| 664 | src[key]::forEachEntry(([srcKey, srcVal]) => { |
| 665 | if (srcVal == null) delete dst[srcKey]; |
| 666 | else dst[srcKey] = srcVal; |
| 667 | }); |
| 668 | } |
| 669 | const pos = +src.position; |
| 670 | if (pos) { |
| 671 | props.position = pos; |
| 672 | maxScriptPosition = Math.max(maxScriptPosition, pos); |
| 673 | } else if (!oldScript) { |
| 674 | maxScriptPosition++; |
| 675 | props.position = maxScriptPosition; |
| 676 | } |
| 677 | config.enabled = getInt(config.enabled); |
| 678 | config.removed = 0; // force-resetting `removed` since this is an installation |
| 679 | config.shouldUpdate = getInt(config.shouldUpdate); |
| 680 | script.meta = meta; |
| 681 | props.uri = getNameURI(script); // DANGER! Must be after props.position and meta assignments. |
| 682 | delete custom.from; // remove the old installation URL if any |
| 683 | if (!getScriptHome(script) && isRemote(src.from)) { |
| 684 | custom.from = src.from; // to avoid overriding script's `meta` for homepage in a future version |
no test coverage detected