@stencil/core 4.43.2 → 5.0.0-next.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/stencil.mjs +2 -0
- package/dist/chunk-ClPoSABd.mjs +21 -0
- package/dist/client-DR9zhmKG.mjs +4449 -0
- package/dist/compiler/index.d.mts +187 -0
- package/dist/compiler/index.mjs +9 -0
- package/dist/compiler/utils/index.d.mts +3 -0
- package/dist/compiler/utils/index.mjs +5 -0
- package/dist/declarations/stencil-public-compiler.d.ts +4401 -0
- package/dist/declarations/stencil-public-compiler.js +53 -0
- package/dist/declarations/stencil-public-runtime.d.ts +1857 -0
- package/dist/index-Bxo2jCf6.d.mts +77 -0
- package/dist/index-szczUd2l.d.mts +6851 -0
- package/{internal/stencil-core/index.d.ts → dist/index.d.mts} +7 -3
- package/dist/index.mjs +4 -0
- package/dist/mock-doc.d.mts +1 -0
- package/dist/mock-doc.mjs +3 -0
- package/dist/node-sys-BGURUNOZ.mjs +1954 -0
- package/{internal → dist/runtime}/app-data/index.d.ts +11 -7
- package/dist/runtime/app-data/index.js +100 -0
- package/dist/runtime/app-globals/index.d.ts +5 -0
- package/dist/runtime/app-globals/index.js +6 -0
- package/dist/runtime/client/index.d.ts +2286 -0
- package/dist/runtime/client/index.js +4839 -0
- package/dist/runtime/index.d.ts +221 -0
- package/dist/runtime/index.js +4819 -0
- package/dist/runtime/server/index.d.mts +1277 -0
- package/dist/runtime/server/index.mjs +5376 -0
- package/dist/runtime/server/runner.d.mts +298 -0
- package/dist/runtime/server/runner.mjs +1976 -0
- package/dist/serialize-BJvhE9aQ.mjs +775 -0
- package/dist/stencil-private-Cgcr414u.d.ts +1893 -0
- package/dist/sys/node/index.d.mts +33 -0
- package/dist/sys/node/index.mjs +7 -0
- package/dist/sys/node/worker.d.mts +1 -0
- package/dist/sys/node/worker.mjs +60 -0
- package/dist/testing/index.d.mts +207 -0
- package/dist/testing/index.mjs +1188 -0
- package/dist/transpile-CJQcQEVa.mjs +21854 -0
- package/dist/validation-BdcPruW_.mjs +1451 -0
- package/package.json +88 -232
- package/bin/stencil +0 -57
- package/cli/config-flags.d.ts +0 -132
- package/cli/index.cjs +0 -5816
- package/cli/index.d.ts +0 -19
- package/cli/index.js +0 -5809
- package/cli/package.json +0 -14
- package/compiler/lib.d.ts +0 -22
- package/compiler/lib.decorators.d.ts +0 -384
- package/compiler/lib.decorators.legacy.d.ts +0 -22
- package/compiler/lib.dom.asynciterable.d.ts +0 -41
- package/compiler/lib.dom.d.ts +0 -29610
- package/compiler/lib.dom.iterable.d.ts +0 -493
- package/compiler/lib.es2015.collection.d.ts +0 -147
- package/compiler/lib.es2015.core.d.ts +0 -597
- package/compiler/lib.es2015.d.ts +0 -28
- package/compiler/lib.es2015.generator.d.ts +0 -77
- package/compiler/lib.es2015.iterable.d.ts +0 -605
- package/compiler/lib.es2015.promise.d.ts +0 -81
- package/compiler/lib.es2015.proxy.d.ts +0 -128
- package/compiler/lib.es2015.reflect.d.ts +0 -144
- package/compiler/lib.es2015.symbol.d.ts +0 -46
- package/compiler/lib.es2015.symbol.wellknown.d.ts +0 -326
- package/compiler/lib.es2016.array.include.d.ts +0 -116
- package/compiler/lib.es2016.d.ts +0 -21
- package/compiler/lib.es2016.full.d.ts +0 -23
- package/compiler/lib.es2016.intl.d.ts +0 -31
- package/compiler/lib.es2017.arraybuffer.d.ts +0 -21
- package/compiler/lib.es2017.d.ts +0 -26
- package/compiler/lib.es2017.date.d.ts +0 -31
- package/compiler/lib.es2017.full.d.ts +0 -23
- package/compiler/lib.es2017.intl.d.ts +0 -44
- package/compiler/lib.es2017.object.d.ts +0 -49
- package/compiler/lib.es2017.sharedmemory.d.ts +0 -135
- package/compiler/lib.es2017.string.d.ts +0 -45
- package/compiler/lib.es2017.typedarrays.d.ts +0 -53
- package/compiler/lib.es2018.asyncgenerator.d.ts +0 -77
- package/compiler/lib.es2018.asynciterable.d.ts +0 -53
- package/compiler/lib.es2018.d.ts +0 -24
- package/compiler/lib.es2018.full.d.ts +0 -24
- package/compiler/lib.es2018.intl.d.ts +0 -83
- package/compiler/lib.es2018.promise.d.ts +0 -30
- package/compiler/lib.es2018.regexp.d.ts +0 -37
- package/compiler/lib.es2019.array.d.ts +0 -79
- package/compiler/lib.es2019.d.ts +0 -24
- package/compiler/lib.es2019.full.d.ts +0 -24
- package/compiler/lib.es2019.intl.d.ts +0 -23
- package/compiler/lib.es2019.object.d.ts +0 -33
- package/compiler/lib.es2019.string.d.ts +0 -37
- package/compiler/lib.es2019.symbol.d.ts +0 -24
- package/compiler/lib.es2020.bigint.d.ts +0 -765
- package/compiler/lib.es2020.d.ts +0 -27
- package/compiler/lib.es2020.date.d.ts +0 -42
- package/compiler/lib.es2020.full.d.ts +0 -24
- package/compiler/lib.es2020.intl.d.ts +0 -474
- package/compiler/lib.es2020.number.d.ts +0 -28
- package/compiler/lib.es2020.promise.d.ts +0 -47
- package/compiler/lib.es2020.sharedmemory.d.ts +0 -99
- package/compiler/lib.es2020.string.d.ts +0 -44
- package/compiler/lib.es2020.symbol.wellknown.d.ts +0 -41
- package/compiler/lib.es2021.d.ts +0 -23
- package/compiler/lib.es2021.full.d.ts +0 -24
- package/compiler/lib.es2021.intl.d.ts +0 -166
- package/compiler/lib.es2021.promise.d.ts +0 -48
- package/compiler/lib.es2021.string.d.ts +0 -33
- package/compiler/lib.es2021.weakref.d.ts +0 -78
- package/compiler/lib.es2022.array.d.ts +0 -121
- package/compiler/lib.es2022.d.ts +0 -25
- package/compiler/lib.es2022.error.d.ts +0 -75
- package/compiler/lib.es2022.full.d.ts +0 -24
- package/compiler/lib.es2022.intl.d.ts +0 -121
- package/compiler/lib.es2022.object.d.ts +0 -26
- package/compiler/lib.es2022.regexp.d.ts +0 -39
- package/compiler/lib.es2022.string.d.ts +0 -25
- package/compiler/lib.es2023.array.d.ts +0 -924
- package/compiler/lib.es2023.collection.d.ts +0 -21
- package/compiler/lib.es2023.d.ts +0 -22
- package/compiler/lib.es2023.full.d.ts +0 -24
- package/compiler/lib.es2023.intl.d.ts +0 -56
- package/compiler/lib.es2024.arraybuffer.d.ts +0 -65
- package/compiler/lib.es2024.collection.d.ts +0 -29
- package/compiler/lib.es2024.d.ts +0 -26
- package/compiler/lib.es2024.full.d.ts +0 -24
- package/compiler/lib.es2024.object.d.ts +0 -29
- package/compiler/lib.es2024.promise.d.ts +0 -35
- package/compiler/lib.es2024.regexp.d.ts +0 -25
- package/compiler/lib.es2024.sharedmemory.d.ts +0 -68
- package/compiler/lib.es2024.string.d.ts +0 -29
- package/compiler/lib.es5.d.ts +0 -4594
- package/compiler/lib.es6.d.ts +0 -23
- package/compiler/lib.esnext.array.d.ts +0 -35
- package/compiler/lib.esnext.collection.d.ts +0 -96
- package/compiler/lib.esnext.d.ts +0 -27
- package/compiler/lib.esnext.decorators.d.ts +0 -28
- package/compiler/lib.esnext.disposable.d.ts +0 -193
- package/compiler/lib.esnext.float16.d.ts +0 -443
- package/compiler/lib.esnext.full.d.ts +0 -24
- package/compiler/lib.esnext.intl.d.ts +0 -21
- package/compiler/lib.esnext.iterator.d.ts +0 -148
- package/compiler/lib.esnext.promise.d.ts +0 -34
- package/compiler/lib.scripthost.d.ts +0 -322
- package/compiler/lib.webworker.asynciterable.d.ts +0 -41
- package/compiler/lib.webworker.d.ts +0 -9894
- package/compiler/lib.webworker.importscripts.d.ts +0 -23
- package/compiler/lib.webworker.iterable.d.ts +0 -287
- package/compiler/package.json +0 -8
- package/compiler/stencil.d.ts +0 -73
- package/compiler/stencil.js +0 -287816
- package/compiler/sys/in-memory-fs.d.ts +0 -227
- package/compiler/transpile.d.ts +0 -32
- package/dev-server/client/app-error.d.ts +0 -20
- package/dev-server/client/events.d.ts +0 -6
- package/dev-server/client/hmr-components.d.ts +0 -12
- package/dev-server/client/hmr-external-styles.d.ts +0 -1
- package/dev-server/client/hmr-images.d.ts +0 -1
- package/dev-server/client/hmr-inline-styles.d.ts +0 -1
- package/dev-server/client/hmr-util.d.ts +0 -39
- package/dev-server/client/hmr-window.d.ts +0 -10
- package/dev-server/client/index.d.ts +0 -6
- package/dev-server/client/index.js +0 -793
- package/dev-server/client/logger.d.ts +0 -6
- package/dev-server/client/package.json +0 -8
- package/dev-server/client/progress.d.ts +0 -3
- package/dev-server/client/status.d.ts +0 -4
- package/dev-server/client/test/hmr-util.spec.d.ts +0 -1
- package/dev-server/client/test/status.spec.d.ts +0 -1
- package/dev-server/connector.html +0 -6
- package/dev-server/index.d.ts +0 -3
- package/dev-server/index.js +0 -247
- package/dev-server/package.json +0 -8
- package/dev-server/server-process.js +0 -12095
- package/dev-server/server-worker-thread.js +0 -39
- package/dev-server/static/favicon.ico +0 -0
- package/dev-server/templates/directory-index.html +0 -176
- package/dev-server/templates/initial-load.html +0 -168
- package/dev-server/visualstudio.vbs +0 -82
- package/dev-server/xdg-open +0 -1066
- package/internal/app-data/index.cjs +0 -119
- package/internal/app-data/index.js +0 -92
- package/internal/app-data/package.json +0 -15
- package/internal/app-globals/index.d.ts +0 -2
- package/internal/app-globals/index.js +0 -14
- package/internal/app-globals/package.json +0 -14
- package/internal/child_process.d.ts +0 -7
- package/internal/client/index.js +0 -4736
- package/internal/client/package.json +0 -10
- package/internal/client/patch-browser.js +0 -45
- package/internal/client/polyfills/core-js.js +0 -11
- package/internal/client/polyfills/dom.js +0 -79
- package/internal/client/polyfills/es5-html-element.js +0 -1
- package/internal/client/polyfills/index.js +0 -34
- package/internal/client/polyfills/system.js +0 -6
- package/internal/client/shadow-css.js +0 -414
- package/internal/hydrate/index.js +0 -6671
- package/internal/hydrate/package.json +0 -7
- package/internal/hydrate/runner.d.ts +0 -287
- package/internal/hydrate/runner.js +0 -17950
- package/internal/index.d.ts +0 -4
- package/internal/index.js +0 -2
- package/internal/package.json +0 -9
- package/internal/stencil-core/index.cjs +0 -1
- package/internal/stencil-core/index.js +0 -18
- package/internal/stencil-core/jsx-dev-runtime.cjs +0 -7
- package/internal/stencil-core/jsx-dev-runtime.d.ts +0 -41
- package/internal/stencil-core/jsx-dev-runtime.js +0 -2
- package/internal/stencil-core/jsx-runtime.cjs +0 -8
- package/internal/stencil-core/jsx-runtime.d.ts +0 -40
- package/internal/stencil-core/jsx-runtime.js +0 -2
- package/internal/stencil-private.d.ts +0 -2549
- package/internal/stencil-public-compiler.d.ts +0 -2867
- package/internal/stencil-public-runtime.d.ts +0 -1860
- package/internal/testing/index.js +0 -6528
- package/internal/testing/jsx-dev-runtime.d.ts +0 -2
- package/internal/testing/jsx-dev-runtime.js +0 -8
- package/internal/testing/jsx-runtime.d.ts +0 -2
- package/internal/testing/jsx-runtime.js +0 -9
- package/internal/testing/package.json +0 -7
- package/internal/utils/index.d.ts +0 -1
- package/internal/utils/result.d.ts +0 -112
- package/mock-doc/index.cjs +0 -10165
- package/mock-doc/index.d.ts +0 -1172
- package/mock-doc/index.js +0 -10144
- package/mock-doc/package.json +0 -15
- package/readme.md +0 -94
- package/screenshot/compare/assets/favicon.ico +0 -0
- package/screenshot/compare/assets/logo.png +0 -0
- package/screenshot/compare/build/app.css +0 -1
- package/screenshot/compare/build/app.esm.js +0 -1
- package/screenshot/compare/build/app.js +0 -33
- package/screenshot/compare/build/p-081b0641.js +0 -1
- package/screenshot/compare/build/p-227a1e18.entry.js +0 -1
- package/screenshot/compare/build/p-2c298727.entry.js +0 -1
- package/screenshot/compare/build/p-5479268c.entry.js +0 -1
- package/screenshot/compare/build/p-573ec8a4.entry.js +0 -1
- package/screenshot/compare/build/p-6ba08604.entry.js +0 -1
- package/screenshot/compare/build/p-6bc63295.entry.js +0 -1
- package/screenshot/compare/build/p-7a3759fd.entry.js +0 -1
- package/screenshot/compare/build/p-7b4e3ba7.js +0 -1
- package/screenshot/compare/build/p-988eb362.css +0 -1
- package/screenshot/compare/build/p-9b6a9315.js +0 -1
- package/screenshot/compare/build/p-b4cc611c.entry.js +0 -1
- package/screenshot/compare/build/p-d1bf53f5.entry.js +0 -1
- package/screenshot/compare/build/p-e2efe0df.js +0 -1
- package/screenshot/compare/build/p-e8ca6d97.entry.js +0 -1
- package/screenshot/compare/build/p-ec2f13e0.entry.js +0 -1
- package/screenshot/compare/build/p-f0b99977.entry.js +0 -1
- package/screenshot/compare/build/p-f4745c2f.entry.js +0 -1
- package/screenshot/compare/build/p-fbbae598.js +0 -1
- package/screenshot/compare/host.config.json +0 -15
- package/screenshot/compare/index.html +0 -1
- package/screenshot/compare/manifest.json +0 -13
- package/screenshot/connector-base.d.ts +0 -42
- package/screenshot/connector-local.d.ts +0 -7
- package/screenshot/connector.js +0 -2
- package/screenshot/index.d.ts +0 -3
- package/screenshot/index.js +0 -2433
- package/screenshot/local-connector.js +0 -2
- package/screenshot/package.json +0 -15
- package/screenshot/pixel-match.d.ts +0 -1
- package/screenshot/pixel-match.js +0 -2315
- package/screenshot/screenshot-compare.d.ts +0 -20
- package/screenshot/screenshot-fs.d.ts +0 -14
- package/sys/node/460.node-fetch.js +0 -451
- package/sys/node/autoprefixer.js +0 -9
- package/sys/node/glob.js +0 -1
- package/sys/node/graceful-fs.js +0 -1
- package/sys/node/index.d.ts +0 -39
- package/sys/node/index.js +0 -64
- package/sys/node/node-fetch.js +0 -12
- package/sys/node/package.json +0 -8
- package/sys/node/prompts.js +0 -1
- package/sys/node/worker.js +0 -4
- package/testing/index.d.ts +0 -9
- package/testing/index.js +0 -13064
- package/testing/jest/jest-27-and-under/jest-config.d.ts +0 -16
- package/testing/jest/jest-27-and-under/jest-environment.d.ts +0 -2
- package/testing/jest/jest-27-and-under/jest-facade.d.ts +0 -155
- package/testing/jest/jest-27-and-under/jest-preprocessor.d.ts +0 -59
- package/testing/jest/jest-27-and-under/jest-preset.d.ts +0 -3
- package/testing/jest/jest-27-and-under/jest-runner.d.ts +0 -11
- package/testing/jest/jest-27-and-under/jest-screenshot.d.ts +0 -2
- package/testing/jest/jest-27-and-under/jest-serializer.d.ts +0 -4
- package/testing/jest/jest-27-and-under/jest-setup-test-framework.d.ts +0 -9
- package/testing/jest/jest-27-and-under/matchers/attributes.d.ts +0 -14
- package/testing/jest/jest-27-and-under/matchers/class-list.d.ts +0 -12
- package/testing/jest/jest-27-and-under/matchers/events.d.ts +0 -25
- package/testing/jest/jest-27-and-under/matchers/html.d.ts +0 -13
- package/testing/jest/jest-27-and-under/matchers/index.d.ts +0 -24
- package/testing/jest/jest-27-and-under/matchers/screenshot.d.ts +0 -5
- package/testing/jest/jest-27-and-under/matchers/text.d.ts +0 -4
- package/testing/jest/jest-27-and-under/test/jest-config.spec.d.ts +0 -1
- package/testing/jest/jest-27-and-under/test/jest-preprocessor.spec.d.ts +0 -1
- package/testing/jest/jest-27-and-under/test/jest-runner.spec.d.ts +0 -1
- package/testing/jest/jest-27-and-under/test/jest-serializer.spec.d.ts +0 -1
- package/testing/jest/jest-27-and-under/test/jest-setup-test-framework.spec.d.ts +0 -1
- package/testing/jest/jest-28/jest-config.d.ts +0 -16
- package/testing/jest/jest-28/jest-environment.d.ts +0 -2
- package/testing/jest/jest-28/jest-facade.d.ts +0 -134
- package/testing/jest/jest-28/jest-preprocessor.d.ts +0 -35
- package/testing/jest/jest-28/jest-preset.d.ts +0 -3
- package/testing/jest/jest-28/jest-runner.d.ts +0 -11
- package/testing/jest/jest-28/jest-screenshot.d.ts +0 -2
- package/testing/jest/jest-28/jest-serializer.d.ts +0 -4
- package/testing/jest/jest-28/jest-setup-test-framework.d.ts +0 -9
- package/testing/jest/jest-28/matchers/attributes.d.ts +0 -14
- package/testing/jest/jest-28/matchers/class-list.d.ts +0 -12
- package/testing/jest/jest-28/matchers/events.d.ts +0 -25
- package/testing/jest/jest-28/matchers/html.d.ts +0 -13
- package/testing/jest/jest-28/matchers/index.d.ts +0 -24
- package/testing/jest/jest-28/matchers/screenshot.d.ts +0 -5
- package/testing/jest/jest-28/matchers/text.d.ts +0 -4
- package/testing/jest/jest-28/test/jest-config.spec.d.ts +0 -1
- package/testing/jest/jest-28/test/jest-preprocessor.spec.d.ts +0 -1
- package/testing/jest/jest-28/test/jest-runner.spec.d.ts +0 -1
- package/testing/jest/jest-28/test/jest-serializer.spec.d.ts +0 -1
- package/testing/jest/jest-28/test/jest-setup-test-framework.spec.d.ts +0 -1
- package/testing/jest/jest-29/jest-config.d.ts +0 -16
- package/testing/jest/jest-29/jest-environment.d.ts +0 -2
- package/testing/jest/jest-29/jest-facade.d.ts +0 -136
- package/testing/jest/jest-29/jest-preprocessor.d.ts +0 -35
- package/testing/jest/jest-29/jest-preset.d.ts +0 -3
- package/testing/jest/jest-29/jest-runner.d.ts +0 -11
- package/testing/jest/jest-29/jest-screenshot.d.ts +0 -2
- package/testing/jest/jest-29/jest-serializer.d.ts +0 -4
- package/testing/jest/jest-29/jest-setup-test-framework.d.ts +0 -9
- package/testing/jest/jest-29/matchers/attributes.d.ts +0 -14
- package/testing/jest/jest-29/matchers/class-list.d.ts +0 -12
- package/testing/jest/jest-29/matchers/events.d.ts +0 -25
- package/testing/jest/jest-29/matchers/html.d.ts +0 -13
- package/testing/jest/jest-29/matchers/index.d.ts +0 -24
- package/testing/jest/jest-29/matchers/screenshot.d.ts +0 -5
- package/testing/jest/jest-29/matchers/text.d.ts +0 -4
- package/testing/jest/jest-29/test/jest-config.spec.d.ts +0 -1
- package/testing/jest/jest-29/test/jest-preprocessor.spec.d.ts +0 -1
- package/testing/jest/jest-29/test/jest-runner.spec.d.ts +0 -1
- package/testing/jest/jest-29/test/jest-serializer.spec.d.ts +0 -1
- package/testing/jest/jest-29/test/jest-setup-test-framework.spec.d.ts +0 -1
- package/testing/jest/jest-apis.d.ts +0 -86
- package/testing/jest/jest-facade.d.ts +0 -74
- package/testing/jest/jest-stencil-connector.d.ts +0 -65
- package/testing/jest/test/jest-stencil-connector.spec.d.ts +0 -1
- package/testing/jest-environment.js +0 -3
- package/testing/jest-preprocessor.js +0 -3
- package/testing/jest-preset.js +0 -2
- package/testing/jest-runner.js +0 -3
- package/testing/jest-setuptestframework.js +0 -3
- package/testing/mock-fetch.d.ts +0 -11
- package/testing/mocks.d.ts +0 -56
- package/testing/package.json +0 -8
- package/testing/puppeteer/index.d.ts +0 -2
- package/testing/puppeteer/puppeteer-browser.d.ts +0 -6
- package/testing/puppeteer/puppeteer-declarations.d.ts +0 -414
- package/testing/puppeteer/puppeteer-element.d.ts +0 -67
- package/testing/puppeteer/puppeteer-emulate.d.ts +0 -2
- package/testing/puppeteer/puppeteer-events.d.ts +0 -21
- package/testing/puppeteer/puppeteer-page.d.ts +0 -2
- package/testing/puppeteer/puppeteer-screenshot.d.ts +0 -27
- package/testing/puppeteer/test/puppeteer-screenshot.spec.d.ts +0 -1
- package/testing/reset-build-conditionals.d.ts +0 -12
- package/testing/spec-page.d.ts +0 -7
- package/testing/test/testing-utils.spec.d.ts +0 -1
- package/testing/test-transpile.d.ts +0 -2
- package/testing/testing-logger.d.ts +0 -26
- package/testing/testing-sys.d.ts +0 -6
- package/testing/testing-utils.d.ts +0 -80
- package/testing/testing.d.ts +0 -2
- /package/{internal → dist/declarations}/stencil-ext-modules.d.ts +0 -0
- /package/{internal → dist/declarations}/stencil-public-docs.d.ts +0 -0
- /package/{screenshot/compare/build/index.esm.js → dist/declarations/stencil-public-runtime.js} +0 -0
|
@@ -0,0 +1,4449 @@
|
|
|
1
|
+
import { D as CMP_FLAGS, E as queryNonceMetaTagContent, G as EVENT_FLAGS, J as HTML_NS, X as MEMBER_FLAGS, Y as LISTENER_FLAGS, Z as NODE_TYPES, a as escapeRegExpSpecialCharacters, d as isComplexType, et as SERIALIZED_PREFIX, f as isDef, nt as SVG_NS, ot as WATCH_FLAGS, q as HOST_FLAGS, t as deserializeProperty } from "./serialize-BJvhE9aQ.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/app-data/index.ts
|
|
4
|
+
/**
|
|
5
|
+
* A collection of default build flags for a Stencil project.
|
|
6
|
+
*
|
|
7
|
+
* This collection can be found throughout the Stencil codebase, often imported from the `virtual:app-data` module like so:
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { BUILD } from 'virtual:app-data';
|
|
10
|
+
* ```
|
|
11
|
+
* and is used to determine if a portion of the output of a Stencil _project_'s compilation step can be eliminated.
|
|
12
|
+
*
|
|
13
|
+
* e.g. When `BUILD.allRenderFn` evaluates to `false`, the compiler will eliminate conditional statements like:
|
|
14
|
+
* ```ts
|
|
15
|
+
* if (BUILD.allRenderFn) {
|
|
16
|
+
* // some code that will be eliminated if BUILD.allRenderFn is false
|
|
17
|
+
* }
|
|
18
|
+
* ```
|
|
19
|
+
*
|
|
20
|
+
* `virtual:app-data`, the module that `BUILD` is imported from, is an alias for the `@stencil/core/runtime/app-data`, and is
|
|
21
|
+
* partially referenced by {@link STENCIL_APP_DATA_ID}. The `src/compiler/bundle/app-data-plugin.ts` references
|
|
22
|
+
* `STENCIL_APP_DATA_ID` uses it to replace these defaults with {@link BuildConditionals} that are derived from a
|
|
23
|
+
* Stencil project's contents (i.e. metadata from the components). This replacement happens at a Stencil project's
|
|
24
|
+
* compile time. Such code can be found at `src/compiler/app-core/app-data.ts`.
|
|
25
|
+
*/
|
|
26
|
+
const BUILD = {
|
|
27
|
+
allRenderFn: false,
|
|
28
|
+
element: true,
|
|
29
|
+
event: true,
|
|
30
|
+
hasRenderFn: true,
|
|
31
|
+
hostListener: true,
|
|
32
|
+
hostListenerTargetWindow: true,
|
|
33
|
+
hostListenerTargetDocument: true,
|
|
34
|
+
hostListenerTargetBody: true,
|
|
35
|
+
hostListenerTargetParent: false,
|
|
36
|
+
hostListenerTarget: true,
|
|
37
|
+
member: true,
|
|
38
|
+
method: true,
|
|
39
|
+
mode: true,
|
|
40
|
+
observeAttribute: true,
|
|
41
|
+
prop: true,
|
|
42
|
+
propMutable: true,
|
|
43
|
+
reflect: true,
|
|
44
|
+
scoped: true,
|
|
45
|
+
shadowDom: true,
|
|
46
|
+
slot: true,
|
|
47
|
+
cssAnnotations: true,
|
|
48
|
+
state: true,
|
|
49
|
+
style: true,
|
|
50
|
+
formAssociated: false,
|
|
51
|
+
svg: true,
|
|
52
|
+
updatable: true,
|
|
53
|
+
vdomAttribute: true,
|
|
54
|
+
vdomXlink: true,
|
|
55
|
+
vdomClass: true,
|
|
56
|
+
vdomFunctional: true,
|
|
57
|
+
vdomKey: true,
|
|
58
|
+
vdomListener: true,
|
|
59
|
+
vdomRef: true,
|
|
60
|
+
vdomPropOrAttr: true,
|
|
61
|
+
vdomRender: true,
|
|
62
|
+
vdomStyle: true,
|
|
63
|
+
vdomText: true,
|
|
64
|
+
propChangeCallback: true,
|
|
65
|
+
taskQueue: true,
|
|
66
|
+
hotModuleReplacement: false,
|
|
67
|
+
isDebug: false,
|
|
68
|
+
isDev: false,
|
|
69
|
+
isTesting: false,
|
|
70
|
+
hydrateServerSide: false,
|
|
71
|
+
hydrateClientSide: false,
|
|
72
|
+
lifecycleDOMEvents: false,
|
|
73
|
+
lazyLoad: false,
|
|
74
|
+
profile: false,
|
|
75
|
+
slotRelocation: true,
|
|
76
|
+
appendChildSlotFix: false,
|
|
77
|
+
cloneNodeFix: false,
|
|
78
|
+
hydratedAttribute: false,
|
|
79
|
+
hydratedClass: true,
|
|
80
|
+
scopedSlotTextContentFix: false,
|
|
81
|
+
shadowDomShim: false,
|
|
82
|
+
slotChildNodesFix: false,
|
|
83
|
+
invisiblePrehydration: true,
|
|
84
|
+
propBoolean: true,
|
|
85
|
+
propNumber: true,
|
|
86
|
+
propString: true,
|
|
87
|
+
constructableCSS: true,
|
|
88
|
+
devTools: false,
|
|
89
|
+
shadowDelegatesFocus: true,
|
|
90
|
+
shadowSlotAssignmentManual: false,
|
|
91
|
+
initializeNextTick: false,
|
|
92
|
+
asyncLoading: true,
|
|
93
|
+
asyncQueue: false,
|
|
94
|
+
transformTagName: false,
|
|
95
|
+
attachStyles: true,
|
|
96
|
+
experimentalSlotFixes: false
|
|
97
|
+
};
|
|
98
|
+
const Env = {};
|
|
99
|
+
const NAMESPACE = "app";
|
|
100
|
+
|
|
101
|
+
//#endregion
|
|
102
|
+
//#region src/client/client-build.ts
|
|
103
|
+
const Build = {
|
|
104
|
+
isDev: BUILD.isDev ? true : false,
|
|
105
|
+
isBrowser: true,
|
|
106
|
+
isServer: false,
|
|
107
|
+
isTesting: BUILD.isTesting ? true : false
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
//#endregion
|
|
111
|
+
//#region src/utils/get-prop-descriptor.ts
|
|
112
|
+
/**
|
|
113
|
+
* Walks up a prototype chain to find a property descriptor.
|
|
114
|
+
* Stops before reaching native DOM prototypes (HTMLElement, etc.) to avoid
|
|
115
|
+
* treating native properties like `hidden` as component-defined getters.
|
|
116
|
+
* @param obj - The object to search on.
|
|
117
|
+
* @param memberName - The name of the member to find.
|
|
118
|
+
* @param getOnly - If true, only returns descriptors with a getter (i.e. ignores properties that are only fields or have setters without getters).
|
|
119
|
+
* @returns The property descriptor if found, otherwise undefined.
|
|
120
|
+
*/
|
|
121
|
+
function getPropertyDescriptor(obj, memberName, getOnly) {
|
|
122
|
+
const stopAt = typeof HTMLElement !== "undefined" ? HTMLElement.prototype : null;
|
|
123
|
+
while (obj && obj !== stopAt) {
|
|
124
|
+
const desc = Object.getOwnPropertyDescriptor(obj, memberName);
|
|
125
|
+
if (desc && (!getOnly || desc.get)) return desc;
|
|
126
|
+
obj = Object.getPrototypeOf(obj);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
//#endregion
|
|
131
|
+
//#region src/utils/es2022-rewire-class-members.ts
|
|
132
|
+
/**
|
|
133
|
+
* - Re-wires component prototype `get` / `set` with instance `@State` / `@Prop` decorated fields.
|
|
134
|
+
* - Makes sure the initial value from the `Element` is synced to the instance `@Prop` decorated fields.
|
|
135
|
+
*
|
|
136
|
+
* Background:
|
|
137
|
+
* During component init, Stencil loops through any `@Prop()` or `@State()` decorated properties
|
|
138
|
+
* and sets up getters and setters for each (within `src/runtime/proxy-component.ts`) on a component prototype.
|
|
139
|
+
*
|
|
140
|
+
* These accessors sync-up class instances with their `Element` and controls re-renders.
|
|
141
|
+
* With modern JS, compiled classes (e.g. `target: 'es2022'`) compiled Stencil components went from:
|
|
142
|
+
*
|
|
143
|
+
* ```ts
|
|
144
|
+
* class MyComponent {
|
|
145
|
+
* constructor() {
|
|
146
|
+
* this.prop1 = 'value1';
|
|
147
|
+
* }
|
|
148
|
+
* }
|
|
149
|
+
* ```
|
|
150
|
+
* To:
|
|
151
|
+
* ```ts
|
|
152
|
+
* class MyComponent {
|
|
153
|
+
* prop1 = 'value2';
|
|
154
|
+
* // ^^ These override the accessors originally set on the prototype
|
|
155
|
+
* }
|
|
156
|
+
* ```
|
|
157
|
+
*
|
|
158
|
+
* @param instance - class instance to re-wire
|
|
159
|
+
* @param hostRef - component reference meta
|
|
160
|
+
*/
|
|
161
|
+
const reWireGetterSetter = (instance, hostRef) => {
|
|
162
|
+
const cmpMeta = hostRef.$cmpMeta$;
|
|
163
|
+
Object.entries(cmpMeta.$members$ ?? {}).map(([memberName, [memberFlags]]) => {
|
|
164
|
+
if ((BUILD.state || BUILD.prop) && (memberFlags & MEMBER_FLAGS.Prop || memberFlags & MEMBER_FLAGS.State)) {
|
|
165
|
+
const ogValue = instance[memberName];
|
|
166
|
+
const ogDescriptor = getPropertyDescriptor(Object.getPrototypeOf(instance), memberName, true) || Object.getOwnPropertyDescriptor(instance, memberName);
|
|
167
|
+
if (ogDescriptor) Object.defineProperty(instance, memberName, {
|
|
168
|
+
get() {
|
|
169
|
+
return ogDescriptor.get.call(this);
|
|
170
|
+
},
|
|
171
|
+
set(newValue) {
|
|
172
|
+
ogDescriptor.set.call(this, newValue);
|
|
173
|
+
},
|
|
174
|
+
configurable: true,
|
|
175
|
+
enumerable: true
|
|
176
|
+
});
|
|
177
|
+
if (hostRef.$instanceValues$.has(memberName)) instance[memberName] = hostRef.$instanceValues$.get(memberName);
|
|
178
|
+
else if (ogValue !== void 0) instance[memberName] = ogValue;
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
//#endregion
|
|
184
|
+
//#region src/client/client-host-ref.ts
|
|
185
|
+
/**
|
|
186
|
+
* Given a {@link d.RuntimeRef} retrieve the corresponding {@link d.HostRef}
|
|
187
|
+
*
|
|
188
|
+
* @param ref the runtime ref of interest
|
|
189
|
+
* @returns the Host reference (if found) or undefined
|
|
190
|
+
*/
|
|
191
|
+
const getHostRef = (ref) => {
|
|
192
|
+
if (ref.__stencil__getHostRef) return ref.__stencil__getHostRef();
|
|
193
|
+
};
|
|
194
|
+
/**
|
|
195
|
+
* Register a host element for a Stencil component, setting up various metadata
|
|
196
|
+
* and callbacks based on {@link BUILD} flags as well as the component's runtime
|
|
197
|
+
* metadata.
|
|
198
|
+
*
|
|
199
|
+
* @param hostElement the host element to register
|
|
200
|
+
* @param cmpMeta runtime metadata for that component
|
|
201
|
+
* @returns a reference to the host ref WeakMap
|
|
202
|
+
*/
|
|
203
|
+
const registerHost = (hostElement, cmpMeta) => {
|
|
204
|
+
const hostRef = {
|
|
205
|
+
$flags$: 0,
|
|
206
|
+
$hostElement$: hostElement,
|
|
207
|
+
$cmpMeta$: cmpMeta,
|
|
208
|
+
$instanceValues$: /* @__PURE__ */ new Map(),
|
|
209
|
+
$serializerValues$: /* @__PURE__ */ new Map()
|
|
210
|
+
};
|
|
211
|
+
if (BUILD.isDev) hostRef.$renderCount$ = 0;
|
|
212
|
+
if (BUILD.method && BUILD.lazyLoad) hostRef.$onInstancePromise$ = new Promise((r) => hostRef.$onInstanceResolve$ = r);
|
|
213
|
+
if (BUILD.asyncLoading) {
|
|
214
|
+
hostRef.$onReadyPromise$ = new Promise((r) => hostRef.$onReadyResolve$ = r);
|
|
215
|
+
hostElement["s-p"] = [];
|
|
216
|
+
hostElement["s-rc"] = [];
|
|
217
|
+
}
|
|
218
|
+
if (BUILD.lazyLoad) hostRef.$fetchedCbList$ = [];
|
|
219
|
+
const ref = hostRef;
|
|
220
|
+
hostElement.__stencil__getHostRef = () => ref;
|
|
221
|
+
if (!BUILD.lazyLoad && cmpMeta.$flags$ & CMP_FLAGS.hasModernPropertyDecls && (BUILD.state || BUILD.prop)) reWireGetterSetter(hostElement, hostRef);
|
|
222
|
+
return ref;
|
|
223
|
+
};
|
|
224
|
+
const isMemberInElement = (elm, memberName) => memberName in elm;
|
|
225
|
+
|
|
226
|
+
//#endregion
|
|
227
|
+
//#region src/client/client-log.ts
|
|
228
|
+
let customError;
|
|
229
|
+
const consoleError = (e, el) => (customError || console.error)(e, el);
|
|
230
|
+
const STENCIL_DEV_MODE = BUILD.isTesting ? ["STENCIL:"] : ["%cstencil", "color: white;background:#4c47ff;font-weight: bold; font-size:10px; padding:2px 6px; border-radius: 5px"];
|
|
231
|
+
const consoleDevError = (...m) => console.error(...STENCIL_DEV_MODE, ...m);
|
|
232
|
+
const consoleDevWarn = (...m) => console.warn(...STENCIL_DEV_MODE, ...m);
|
|
233
|
+
const setErrorHandler = (handler) => customError = handler;
|
|
234
|
+
|
|
235
|
+
//#endregion
|
|
236
|
+
//#region src/client/client-load-module.ts
|
|
237
|
+
const cmpModules = /* @__PURE__ */ new Map();
|
|
238
|
+
/**
|
|
239
|
+
* We need to separate out this prefix so that Esbuild doesn't try to resolve
|
|
240
|
+
* the below, but instead retains a dynamic `import()` statement in the
|
|
241
|
+
* emitted code.
|
|
242
|
+
*
|
|
243
|
+
* See here for details https://esbuild.github.io/api/#non-analyzable-imports
|
|
244
|
+
*
|
|
245
|
+
* We need to do this in order to prevent Esbuild from analyzing / transforming
|
|
246
|
+
* the input. However some _other_ bundlers will _not_ work with such an import
|
|
247
|
+
* if it _lacks_ a leading `"./"`, so we thus we have to do a little dance
|
|
248
|
+
* where here in the source code it must be like this, so that an undesirable
|
|
249
|
+
* transformation that Esbuild would otherwise carry out doesn't occur, but we
|
|
250
|
+
* actually need to then manually edit the bundled Esbuild code later on to fix
|
|
251
|
+
* that. We do this with plugins in the Esbuild and Rollup bundles which
|
|
252
|
+
* include this file.
|
|
253
|
+
*/
|
|
254
|
+
const MODULE_IMPORT_PREFIX = "./";
|
|
255
|
+
const loadModule = (cmpMeta, hostRef, hmrVersionId) => {
|
|
256
|
+
const exportName = cmpMeta.$tagName$.replace(/-/g, "_");
|
|
257
|
+
const bundleId = cmpMeta.$lazyBundleId$;
|
|
258
|
+
if (BUILD.isDev && typeof bundleId !== "string") {
|
|
259
|
+
consoleDevError(`Trying to lazily load component <${cmpMeta.$tagName$}> with style mode "${hostRef.$modeName$}", but it does not exist.`);
|
|
260
|
+
return;
|
|
261
|
+
} else if (!bundleId) return;
|
|
262
|
+
const module = !BUILD.hotModuleReplacement ? cmpModules.get(bundleId) : false;
|
|
263
|
+
if (module) return module[exportName];
|
|
264
|
+
/*!__STENCIL_STATIC_IMPORT_SWITCH__*/
|
|
265
|
+
return import(
|
|
266
|
+
/* @vite-ignore */
|
|
267
|
+
/* webpackInclude: /\.entry\.js$/ */
|
|
268
|
+
/* webpackExclude: /\.system\.entry\.js$/ */
|
|
269
|
+
/* webpackMode: "lazy" */
|
|
270
|
+
`${MODULE_IMPORT_PREFIX}${bundleId}.entry.js${BUILD.hotModuleReplacement && hmrVersionId ? "?s-hmr=" + hmrVersionId : ""}`
|
|
271
|
+
).then((importedModule) => {
|
|
272
|
+
if (!BUILD.hotModuleReplacement) cmpModules.set(bundleId, importedModule);
|
|
273
|
+
return importedModule[exportName];
|
|
274
|
+
}, (e) => {
|
|
275
|
+
consoleError(e, hostRef.$hostElement$);
|
|
276
|
+
});
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
//#endregion
|
|
280
|
+
//#region src/client/client-style.ts
|
|
281
|
+
const styles = /* @__PURE__ */ new Map();
|
|
282
|
+
const modeResolutionChain = [];
|
|
283
|
+
const needsScopedSSR = () => false;
|
|
284
|
+
|
|
285
|
+
//#endregion
|
|
286
|
+
//#region src/runtime/runtime-constants.ts
|
|
287
|
+
/**
|
|
288
|
+
* Bit flags for recording various properties of VDom nodes
|
|
289
|
+
*/
|
|
290
|
+
const VNODE_FLAGS = {
|
|
291
|
+
isSlotReference: 1,
|
|
292
|
+
isSlotFallback: 2,
|
|
293
|
+
isHost: 4
|
|
294
|
+
};
|
|
295
|
+
const PROXY_FLAGS = {
|
|
296
|
+
isElementConstructor: 1,
|
|
297
|
+
proxyState: 2
|
|
298
|
+
};
|
|
299
|
+
const PF_appLoaded = 2;
|
|
300
|
+
const PF_queueSync = 4;
|
|
301
|
+
const PLATFORM_FLAGS = {
|
|
302
|
+
isTmpDisconnected: 1,
|
|
303
|
+
appLoaded: PF_appLoaded,
|
|
304
|
+
queueSync: PF_queueSync,
|
|
305
|
+
queueMask: PF_appLoaded | PF_queueSync
|
|
306
|
+
};
|
|
307
|
+
/**
|
|
308
|
+
* A (subset) of node types which are relevant for the Stencil runtime. These
|
|
309
|
+
* values are based on the values which can possibly be returned by the
|
|
310
|
+
* `.nodeType` property of a DOM node. See here for details:
|
|
311
|
+
*
|
|
312
|
+
* {@link https://dom.spec.whatwg.org/#ref-for-dom-node-nodetype%E2%91%A0}
|
|
313
|
+
*/
|
|
314
|
+
const NODE_TYPE = {
|
|
315
|
+
ElementNode: 1,
|
|
316
|
+
TextNode: 3,
|
|
317
|
+
CommentNode: 8,
|
|
318
|
+
DocumentNode: 9,
|
|
319
|
+
DocumentTypeNode: 10,
|
|
320
|
+
DocumentFragment: 11
|
|
321
|
+
};
|
|
322
|
+
const CONTENT_REF_ID = "r";
|
|
323
|
+
const ORG_LOCATION_ID = "o";
|
|
324
|
+
const SLOT_NODE_ID = "s";
|
|
325
|
+
const TEXT_NODE_ID = "t";
|
|
326
|
+
const COMMENT_NODE_ID = "c";
|
|
327
|
+
const HYDRATE_ID = "s-id";
|
|
328
|
+
const HYDRATED_STYLE_ID = "sty-id";
|
|
329
|
+
const HYDRATE_CHILD_ID = "c-id";
|
|
330
|
+
const HYDRATED_CSS = "{visibility:hidden}.hydrated{visibility:inherit}";
|
|
331
|
+
const STENCIL_DOC_DATA = "_stencilDocData";
|
|
332
|
+
const DEFAULT_DOC_DATA = {
|
|
333
|
+
hostIds: 0,
|
|
334
|
+
rootLevelIds: 0,
|
|
335
|
+
staticComponents: /* @__PURE__ */ new Set()
|
|
336
|
+
};
|
|
337
|
+
/**
|
|
338
|
+
* Constant for styles to be globally applied to `slot-fb` elements for pseudo-slot behavior.
|
|
339
|
+
*
|
|
340
|
+
* Two cascading rules must be used instead of a `:not()` selector due to Stencil browser
|
|
341
|
+
* support as of Stencil v4.
|
|
342
|
+
*/
|
|
343
|
+
const SLOT_FB_CSS = "slot-fb{display:contents}slot-fb[hidden]{display:none}";
|
|
344
|
+
const XLINK_NS = "http://www.w3.org/1999/xlink";
|
|
345
|
+
const FORM_ASSOCIATED_CUSTOM_ELEMENT_CALLBACKS = [
|
|
346
|
+
"formAssociatedCallback",
|
|
347
|
+
"formResetCallback",
|
|
348
|
+
"formDisabledCallback",
|
|
349
|
+
"formStateRestoreCallback"
|
|
350
|
+
];
|
|
351
|
+
|
|
352
|
+
//#endregion
|
|
353
|
+
//#region src/client/client-window.ts
|
|
354
|
+
const win = typeof window !== "undefined" ? window : {};
|
|
355
|
+
const H = win.HTMLElement || class {};
|
|
356
|
+
const plt = {
|
|
357
|
+
$flags$: 0,
|
|
358
|
+
$resourcesUrl$: "",
|
|
359
|
+
jmp: (h) => h(),
|
|
360
|
+
raf: (h) => requestAnimationFrame(h),
|
|
361
|
+
ael: (el, eventName, listener, opts) => el.addEventListener(eventName, listener, opts),
|
|
362
|
+
rel: (el, eventName, listener, opts) => el.removeEventListener(eventName, listener, opts),
|
|
363
|
+
ce: (eventName, opts) => new CustomEvent(eventName, opts)
|
|
364
|
+
};
|
|
365
|
+
const setPlatformHelpers = (helpers) => {
|
|
366
|
+
Object.assign(plt, helpers);
|
|
367
|
+
};
|
|
368
|
+
const supportsShadow = BUILD.shadowDom;
|
|
369
|
+
const supportsListenerOptions = /* @__PURE__ */ (() => {
|
|
370
|
+
let supportsListenerOptions = false;
|
|
371
|
+
try {
|
|
372
|
+
win.document?.addEventListener("e", null, Object.defineProperty({}, "passive", { get() {
|
|
373
|
+
supportsListenerOptions = true;
|
|
374
|
+
} }));
|
|
375
|
+
} catch (e) {}
|
|
376
|
+
return supportsListenerOptions;
|
|
377
|
+
})();
|
|
378
|
+
const promiseResolve = (v) => Promise.resolve(v);
|
|
379
|
+
const supportsConstructableStylesheets = BUILD.constructableCSS ? /* @__PURE__ */ (() => {
|
|
380
|
+
try {
|
|
381
|
+
if (!win.document.adoptedStyleSheets) return false;
|
|
382
|
+
new CSSStyleSheet();
|
|
383
|
+
return typeof new CSSStyleSheet().replaceSync === "function";
|
|
384
|
+
} catch (e) {}
|
|
385
|
+
return false;
|
|
386
|
+
})() : false;
|
|
387
|
+
const supportsMutableAdoptedStyleSheets = supportsConstructableStylesheets ? !!win.document && Object.getOwnPropertyDescriptor(win.document.adoptedStyleSheets, "length").writable : false;
|
|
388
|
+
|
|
389
|
+
//#endregion
|
|
390
|
+
//#region src/client/client-task-queue.ts
|
|
391
|
+
let queueCongestion = 0;
|
|
392
|
+
let queuePending = false;
|
|
393
|
+
const queueDomReads = [];
|
|
394
|
+
const queueDomWrites = [];
|
|
395
|
+
const queueDomWritesLow = [];
|
|
396
|
+
const queueTask = (queue, write) => (cb) => {
|
|
397
|
+
queue.push(cb);
|
|
398
|
+
if (!queuePending) {
|
|
399
|
+
queuePending = true;
|
|
400
|
+
if (write && plt.$flags$ & PLATFORM_FLAGS.queueSync) nextTick(flush);
|
|
401
|
+
else plt.raf(flush);
|
|
402
|
+
}
|
|
403
|
+
};
|
|
404
|
+
const consume = (queue) => {
|
|
405
|
+
for (let i = 0; i < queue.length; i++) try {
|
|
406
|
+
queue[i](performance.now());
|
|
407
|
+
} catch (e) {
|
|
408
|
+
consoleError(e);
|
|
409
|
+
}
|
|
410
|
+
queue.length = 0;
|
|
411
|
+
};
|
|
412
|
+
const consumeTimeout = (queue, timeout) => {
|
|
413
|
+
let i = 0;
|
|
414
|
+
let ts = 0;
|
|
415
|
+
while (i < queue.length && (ts = performance.now()) < timeout) try {
|
|
416
|
+
queue[i++](ts);
|
|
417
|
+
} catch (e) {
|
|
418
|
+
consoleError(e);
|
|
419
|
+
}
|
|
420
|
+
if (i === queue.length) queue.length = 0;
|
|
421
|
+
else if (i !== 0) queue.splice(0, i);
|
|
422
|
+
};
|
|
423
|
+
const flush = () => {
|
|
424
|
+
if (BUILD.asyncQueue) queueCongestion++;
|
|
425
|
+
consume(queueDomReads);
|
|
426
|
+
if (BUILD.asyncQueue) {
|
|
427
|
+
const timeout = (plt.$flags$ & PLATFORM_FLAGS.queueMask) === PLATFORM_FLAGS.appLoaded ? performance.now() + 14 * Math.ceil(queueCongestion * (1 / 10)) : Infinity;
|
|
428
|
+
consumeTimeout(queueDomWrites, timeout);
|
|
429
|
+
consumeTimeout(queueDomWritesLow, timeout);
|
|
430
|
+
if (queueDomWrites.length > 0) {
|
|
431
|
+
queueDomWritesLow.push(...queueDomWrites);
|
|
432
|
+
queueDomWrites.length = 0;
|
|
433
|
+
}
|
|
434
|
+
if (queuePending = queueDomReads.length + queueDomWrites.length + queueDomWritesLow.length > 0) plt.raf(flush);
|
|
435
|
+
else queueCongestion = 0;
|
|
436
|
+
} else {
|
|
437
|
+
consume(queueDomWrites);
|
|
438
|
+
if (queuePending = queueDomReads.length > 0) plt.raf(flush);
|
|
439
|
+
}
|
|
440
|
+
};
|
|
441
|
+
const nextTick = (cb) => promiseResolve().then(cb);
|
|
442
|
+
const readTask = /* @__PURE__ */ queueTask(queueDomReads, false);
|
|
443
|
+
const writeTask = /* @__PURE__ */ queueTask(queueDomWrites, true);
|
|
444
|
+
|
|
445
|
+
//#endregion
|
|
446
|
+
//#region src/runtime/asset-path.ts
|
|
447
|
+
const getAssetPath = (path) => {
|
|
448
|
+
const base = plt.$resourcesUrl$ || new URL(".", import.meta.url).href;
|
|
449
|
+
const assetUrl = new URL(path, base);
|
|
450
|
+
return assetUrl.origin !== win.location.origin ? assetUrl.href : assetUrl.pathname;
|
|
451
|
+
};
|
|
452
|
+
const setAssetPath = (path) => plt.$resourcesUrl$ = path;
|
|
453
|
+
|
|
454
|
+
//#endregion
|
|
455
|
+
//#region src/app-globals/index.ts
|
|
456
|
+
const globalStyles = "";
|
|
457
|
+
|
|
458
|
+
//#endregion
|
|
459
|
+
//#region src/utils/style.ts
|
|
460
|
+
/**
|
|
461
|
+
* If (1) styles is not empty string, and (2) constructable stylesheets are supported,
|
|
462
|
+
* then make a stylesheet.
|
|
463
|
+
*
|
|
464
|
+
* @param styles - The styles to add to the stylesheet. If empty string, then no stylesheet is returned.
|
|
465
|
+
* @returns A stylesheet if it can be created, otherwise undefined.
|
|
466
|
+
*/
|
|
467
|
+
function createStyleSheetIfNeededAndSupported(styles) {
|
|
468
|
+
if (!styles || !supportsConstructableStylesheets) return void 0;
|
|
469
|
+
const sheet = new CSSStyleSheet();
|
|
470
|
+
sheet.replaceSync(styles);
|
|
471
|
+
return sheet;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
//#endregion
|
|
475
|
+
//#region src/utils/shadow-root.ts
|
|
476
|
+
let globalStyleSheet;
|
|
477
|
+
const GLOBAL_STYLE_ID = "sc-global";
|
|
478
|
+
function createShadowRoot(cmpMeta) {
|
|
479
|
+
const opts = { mode: "open" };
|
|
480
|
+
if (BUILD.shadowDelegatesFocus) opts.delegatesFocus = !!(cmpMeta.$flags$ & CMP_FLAGS.shadowDelegatesFocus);
|
|
481
|
+
if (BUILD.shadowSlotAssignmentManual) {
|
|
482
|
+
if (!!(cmpMeta.$flags$ & CMP_FLAGS.shadowSlotAssignmentManual)) opts.slotAssignment = "manual";
|
|
483
|
+
}
|
|
484
|
+
const shadowRoot = this.attachShadow(opts);
|
|
485
|
+
if (globalStyleSheet === void 0) globalStyleSheet = createStyleSheetIfNeededAndSupported(globalStyles) ?? null;
|
|
486
|
+
if (globalStyleSheet) if (supportsMutableAdoptedStyleSheets) shadowRoot.adoptedStyleSheets.push(globalStyleSheet);
|
|
487
|
+
else shadowRoot.adoptedStyleSheets = [...shadowRoot.adoptedStyleSheets, globalStyleSheet];
|
|
488
|
+
else if (globalStyles && !supportsConstructableStylesheets) {
|
|
489
|
+
const styleElm = document.createElement("style");
|
|
490
|
+
styleElm.innerHTML = globalStyles;
|
|
491
|
+
if (BUILD.hotModuleReplacement) styleElm.setAttribute(HYDRATED_STYLE_ID, GLOBAL_STYLE_ID);
|
|
492
|
+
shadowRoot.prepend(styleElm);
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
//#endregion
|
|
497
|
+
//#region src/runtime/slot-polyfill-utils.ts
|
|
498
|
+
/**
|
|
499
|
+
* Adjust the `.hidden` property as-needed on any nodes in a DOM subtree which
|
|
500
|
+
* are slot fallback nodes - `<slot-fb>...</slot-fb>`
|
|
501
|
+
*
|
|
502
|
+
* A slot fallback node should be visible by default. Then, it should be
|
|
503
|
+
* conditionally hidden if:
|
|
504
|
+
*
|
|
505
|
+
* - it has a sibling with a `slot` property set to its slot name or if
|
|
506
|
+
* - it is a default fallback slot node, in which case we hide if it has any
|
|
507
|
+
* content
|
|
508
|
+
*
|
|
509
|
+
* @param elm the element of interest
|
|
510
|
+
*/
|
|
511
|
+
const updateFallbackSlotVisibility = (elm) => {
|
|
512
|
+
const childNodes = internalCall(elm, "childNodes");
|
|
513
|
+
if (elm.tagName && elm.tagName.includes("-") && elm["s-cr"] && elm.tagName !== "SLOT-FB") getHostSlotNodes(childNodes, elm.tagName).forEach((slotNode) => {
|
|
514
|
+
if (slotNode.nodeType === NODE_TYPE.ElementNode && slotNode.tagName === "SLOT-FB") if (getSlotChildSiblings(slotNode, getSlotName(slotNode), false).length) slotNode.hidden = true;
|
|
515
|
+
else slotNode.hidden = false;
|
|
516
|
+
});
|
|
517
|
+
let i = 0;
|
|
518
|
+
for (i = 0; i < childNodes.length; i++) {
|
|
519
|
+
const childNode = childNodes[i];
|
|
520
|
+
if (childNode.nodeType === NODE_TYPE.ElementNode && internalCall(childNode, "childNodes").length) updateFallbackSlotVisibility(childNode);
|
|
521
|
+
}
|
|
522
|
+
};
|
|
523
|
+
/**
|
|
524
|
+
* Get's the child nodes of a component that are actually slotted.
|
|
525
|
+
* It does this by using root nodes of a component; for each slotted node there is a
|
|
526
|
+
* corresponding slot location node which points to the slotted node (via `['s-nr']`).
|
|
527
|
+
*
|
|
528
|
+
* This is only required until all patches are unified / switched on all the time (then we can rely on `childNodes`)
|
|
529
|
+
* either under 'experimentalSlotFixes' or on by default
|
|
530
|
+
* @param childNodes all 'internal' child nodes of the component
|
|
531
|
+
* @returns An array of slotted reference nodes.
|
|
532
|
+
*/
|
|
533
|
+
const getSlottedChildNodes = (childNodes) => {
|
|
534
|
+
const result = [];
|
|
535
|
+
for (let i = 0; i < childNodes.length; i++) {
|
|
536
|
+
const slottedNode = childNodes[i]["s-nr"] || void 0;
|
|
537
|
+
if (slottedNode && slottedNode.isConnected) result.push(slottedNode);
|
|
538
|
+
}
|
|
539
|
+
return result;
|
|
540
|
+
};
|
|
541
|
+
/**
|
|
542
|
+
* Recursively searches a series of child nodes for slot node/s, optionally with a provided slot name.
|
|
543
|
+
* @param childNodes the nodes to search for a slot with a specific name. Should be an element's root nodes.
|
|
544
|
+
* @param hostName the host name of the slot to match on.
|
|
545
|
+
* @param slotName the name of the slot to match on.
|
|
546
|
+
* @returns a reference to the slot node that matches the provided name, `null` otherwise
|
|
547
|
+
*/
|
|
548
|
+
function getHostSlotNodes(childNodes, hostName, slotName) {
|
|
549
|
+
let i = 0;
|
|
550
|
+
let slottedNodes = [];
|
|
551
|
+
let childNode;
|
|
552
|
+
for (; i < childNodes.length; i++) {
|
|
553
|
+
childNode = childNodes[i];
|
|
554
|
+
if (childNode["s-sr"] && (!hostName || childNode["s-hn"] === hostName) && (slotName === void 0 || getSlotName(childNode) === slotName)) {
|
|
555
|
+
slottedNodes.push(childNode);
|
|
556
|
+
if (typeof slotName !== "undefined") return slottedNodes;
|
|
557
|
+
}
|
|
558
|
+
slottedNodes = [...slottedNodes, ...getHostSlotNodes(childNode.childNodes, hostName, slotName)];
|
|
559
|
+
}
|
|
560
|
+
return slottedNodes;
|
|
561
|
+
}
|
|
562
|
+
/**
|
|
563
|
+
* Get all 'child' sibling nodes of a slot node
|
|
564
|
+
* @param slot - the slot node to get the child nodes from
|
|
565
|
+
* @param slotName - the name of the slot to match on
|
|
566
|
+
* @param includeSlot - whether to include the slot node in the result
|
|
567
|
+
* @returns child nodes of the slot node
|
|
568
|
+
*/
|
|
569
|
+
const getSlotChildSiblings = (slot, slotName, includeSlot = true) => {
|
|
570
|
+
const childNodes = [];
|
|
571
|
+
if (includeSlot && slot["s-sr"] || !slot["s-sr"]) childNodes.push(slot);
|
|
572
|
+
let node = slot;
|
|
573
|
+
while (node = node.nextSibling) if (getSlotName(node) === slotName && (includeSlot || !node["s-sr"])) childNodes.push(node);
|
|
574
|
+
return childNodes;
|
|
575
|
+
};
|
|
576
|
+
/**
|
|
577
|
+
* Check whether a node is located in a given named slot.
|
|
578
|
+
*
|
|
579
|
+
* @param nodeToRelocate the node of interest
|
|
580
|
+
* @param slotName the slot name to check
|
|
581
|
+
* @returns whether the node is located in the slot or not
|
|
582
|
+
*/
|
|
583
|
+
const isNodeLocatedInSlot = (nodeToRelocate, slotName) => {
|
|
584
|
+
if (nodeToRelocate.nodeType === NODE_TYPE.ElementNode) {
|
|
585
|
+
if (nodeToRelocate.getAttribute("slot") === null && slotName === "") return true;
|
|
586
|
+
if (nodeToRelocate.getAttribute("slot") === slotName) return true;
|
|
587
|
+
return false;
|
|
588
|
+
}
|
|
589
|
+
if (nodeToRelocate["s-sn"] === slotName) return true;
|
|
590
|
+
return slotName === "";
|
|
591
|
+
};
|
|
592
|
+
/**
|
|
593
|
+
* Creates an empty text node to act as a forwarding address to a slotted node:
|
|
594
|
+
* 1) When non-shadow components re-render, they need a place to temporarily put 'lightDOM' elements.
|
|
595
|
+
* 2) Patched dom methods and accessors use this node to calculate what 'lightDOM' nodes are in the host.
|
|
596
|
+
*
|
|
597
|
+
* @param newChild a node that's going to be added to the component
|
|
598
|
+
* @param slotNode the slot node that the node will be added to
|
|
599
|
+
* @param prepend move the slotted location node to the beginning of the host
|
|
600
|
+
* @param position an ordered position to add the ref node which mirrors the lightDom nodes' order. Used during SSR hydration
|
|
601
|
+
* (the order of the slot location nodes determines the order of the slotted nodes in our patched accessors)
|
|
602
|
+
*/
|
|
603
|
+
const addSlotRelocateNode = (newChild, slotNode, prepend, position) => {
|
|
604
|
+
if (newChild["s-ol"] && newChild["s-ol"].isConnected) return;
|
|
605
|
+
const slottedNodeLocation = document.createTextNode("");
|
|
606
|
+
slottedNodeLocation["s-nr"] = newChild;
|
|
607
|
+
if (!slotNode["s-cr"] || !slotNode["s-cr"].parentNode) return;
|
|
608
|
+
const parent = slotNode["s-cr"].parentNode;
|
|
609
|
+
const appendMethod = prepend ? internalCall(parent, "prepend") : internalCall(parent, "appendChild");
|
|
610
|
+
if (BUILD.hydrateClientSide && typeof position !== "undefined") {
|
|
611
|
+
slottedNodeLocation["s-oo"] = position;
|
|
612
|
+
const childNodes = internalCall(parent, "childNodes");
|
|
613
|
+
const slotRelocateNodes = [slottedNodeLocation];
|
|
614
|
+
childNodes.forEach((n) => {
|
|
615
|
+
if (n["s-nr"]) slotRelocateNodes.push(n);
|
|
616
|
+
});
|
|
617
|
+
slotRelocateNodes.sort((a, b) => {
|
|
618
|
+
if (!a["s-oo"] || a["s-oo"] < (b["s-oo"] || 0)) return -1;
|
|
619
|
+
else if (!b["s-oo"] || b["s-oo"] < a["s-oo"]) return 1;
|
|
620
|
+
return 0;
|
|
621
|
+
});
|
|
622
|
+
slotRelocateNodes.forEach((n) => appendMethod.call(parent, n));
|
|
623
|
+
} else appendMethod.call(parent, slottedNodeLocation);
|
|
624
|
+
newChild["s-ol"] = slottedNodeLocation;
|
|
625
|
+
newChild["s-sh"] = slotNode["s-hn"];
|
|
626
|
+
};
|
|
627
|
+
const getSlotName = (node) => typeof node["s-sn"] === "string" ? node["s-sn"] : node.nodeType === 1 && node.getAttribute("slot") || void 0;
|
|
628
|
+
/**
|
|
629
|
+
* Add `assignedElements` and `assignedNodes` methods on a fake slot node
|
|
630
|
+
*
|
|
631
|
+
* @param node - slot node to patch
|
|
632
|
+
*/
|
|
633
|
+
function patchSlotNode(node) {
|
|
634
|
+
if (node.assignedElements || node.assignedNodes || !node["s-sr"]) return;
|
|
635
|
+
const assignedFactory = (elementsOnly) => function(opts) {
|
|
636
|
+
const toReturn = [];
|
|
637
|
+
const slotName = this["s-sn"];
|
|
638
|
+
if (opts?.flatten) console.error(`
|
|
639
|
+
Flattening is not supported for Stencil non-shadow slots.
|
|
640
|
+
You can use \`.childNodes\` to nested slot fallback content.
|
|
641
|
+
If you have a particular use case, please open an issue on the Stencil repo.
|
|
642
|
+
`);
|
|
643
|
+
const parent = this["s-cr"].parentElement;
|
|
644
|
+
(parent.__childNodes ? parent.childNodes : getSlottedChildNodes(parent.childNodes)).forEach((n) => {
|
|
645
|
+
if (slotName === getSlotName(n)) toReturn.push(n);
|
|
646
|
+
});
|
|
647
|
+
if (elementsOnly) return toReturn.filter((n) => n.nodeType === NODE_TYPE.ElementNode);
|
|
648
|
+
return toReturn;
|
|
649
|
+
}.bind(node);
|
|
650
|
+
node.assignedElements = assignedFactory(true);
|
|
651
|
+
node.assignedNodes = assignedFactory(false);
|
|
652
|
+
}
|
|
653
|
+
/**
|
|
654
|
+
* Dispatches a `slotchange` event on a fake `<slot />` node.
|
|
655
|
+
*
|
|
656
|
+
* @param elm the slot node to dispatch the event from
|
|
657
|
+
*/
|
|
658
|
+
function dispatchSlotChangeEvent(elm) {
|
|
659
|
+
elm.dispatchEvent(new CustomEvent("slotchange", {
|
|
660
|
+
bubbles: false,
|
|
661
|
+
cancelable: false,
|
|
662
|
+
composed: false
|
|
663
|
+
}));
|
|
664
|
+
}
|
|
665
|
+
/**
|
|
666
|
+
* Find the slot node that a slotted node belongs to
|
|
667
|
+
*
|
|
668
|
+
* @param slottedNode - the slotted node to find the slot for
|
|
669
|
+
* @param parentHost - the parent host element of the slotted node
|
|
670
|
+
* @returns the slot node and slot name
|
|
671
|
+
*/
|
|
672
|
+
function findSlotFromSlottedNode(slottedNode, parentHost) {
|
|
673
|
+
parentHost = parentHost || slottedNode["s-ol"]?.parentElement;
|
|
674
|
+
if (!parentHost) return {
|
|
675
|
+
slotNode: null,
|
|
676
|
+
slotName: ""
|
|
677
|
+
};
|
|
678
|
+
const slotName = slottedNode["s-sn"] = getSlotName(slottedNode) || "";
|
|
679
|
+
return {
|
|
680
|
+
slotNode: getHostSlotNodes(internalCall(parentHost, "childNodes"), parentHost.tagName, slotName)[0],
|
|
681
|
+
slotName
|
|
682
|
+
};
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
//#endregion
|
|
686
|
+
//#region src/runtime/dom-extras.ts
|
|
687
|
+
const patchPseudoShadowDom = (hostElementPrototype) => {
|
|
688
|
+
patchCloneNode(hostElementPrototype);
|
|
689
|
+
patchSlotAppendChild(hostElementPrototype);
|
|
690
|
+
patchSlotAppend(hostElementPrototype);
|
|
691
|
+
patchSlotPrepend(hostElementPrototype);
|
|
692
|
+
patchSlotInsertAdjacentElement(hostElementPrototype);
|
|
693
|
+
patchSlotInsertAdjacentHTML(hostElementPrototype);
|
|
694
|
+
patchSlotInsertAdjacentText(hostElementPrototype);
|
|
695
|
+
patchInsertBefore(hostElementPrototype);
|
|
696
|
+
patchTextContent(hostElementPrototype);
|
|
697
|
+
patchChildSlotNodes(hostElementPrototype);
|
|
698
|
+
patchSlotRemoveChild(hostElementPrototype);
|
|
699
|
+
};
|
|
700
|
+
/**
|
|
701
|
+
* Patches the `cloneNode` method on a `scoped` Stencil component.
|
|
702
|
+
*
|
|
703
|
+
* @param HostElementPrototype The Stencil component to be patched
|
|
704
|
+
*/
|
|
705
|
+
const patchCloneNode = (HostElementPrototype) => {
|
|
706
|
+
if (HostElementPrototype.__cloneNode) return;
|
|
707
|
+
const orgCloneNode = HostElementPrototype.__cloneNode = HostElementPrototype.cloneNode;
|
|
708
|
+
HostElementPrototype.cloneNode = function(deep) {
|
|
709
|
+
const srcNode = this;
|
|
710
|
+
const isShadowDom = BUILD.shadowDom ? srcNode.shadowRoot && supportsShadow : false;
|
|
711
|
+
const clonedNode = orgCloneNode.call(srcNode, isShadowDom ? deep : false);
|
|
712
|
+
if (BUILD.slot && !isShadowDom && deep) {
|
|
713
|
+
let i = 0;
|
|
714
|
+
let slotted, nonStencilNode;
|
|
715
|
+
const stencilPrivates = [
|
|
716
|
+
"s-id",
|
|
717
|
+
"s-cr",
|
|
718
|
+
"s-lr",
|
|
719
|
+
"s-rc",
|
|
720
|
+
"s-sc",
|
|
721
|
+
"s-p",
|
|
722
|
+
"s-cn",
|
|
723
|
+
"s-sr",
|
|
724
|
+
"s-sn",
|
|
725
|
+
"s-hn",
|
|
726
|
+
"s-ol",
|
|
727
|
+
"s-nr",
|
|
728
|
+
"s-si",
|
|
729
|
+
"s-rf",
|
|
730
|
+
"s-scs"
|
|
731
|
+
];
|
|
732
|
+
const childNodes = this.__childNodes || this.childNodes;
|
|
733
|
+
for (; i < childNodes.length; i++) {
|
|
734
|
+
slotted = childNodes[i]["s-nr"];
|
|
735
|
+
nonStencilNode = stencilPrivates.every((privateField) => !childNodes[i][privateField]);
|
|
736
|
+
if (slotted) if (BUILD.appendChildSlotFix && clonedNode.__appendChild) clonedNode.__appendChild(slotted.cloneNode(true));
|
|
737
|
+
else clonedNode.appendChild(slotted.cloneNode(true));
|
|
738
|
+
if (nonStencilNode) clonedNode.appendChild(childNodes[i].cloneNode(true));
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
return clonedNode;
|
|
742
|
+
};
|
|
743
|
+
};
|
|
744
|
+
/**
|
|
745
|
+
* Patches the `appendChild` method on a `scoped` Stencil component.
|
|
746
|
+
* The patch will attempt to find a slot with the same name as the node being appended
|
|
747
|
+
* and insert it into the slot reference if found. Otherwise, it falls-back to the original
|
|
748
|
+
* `appendChild` method.
|
|
749
|
+
*
|
|
750
|
+
* @param HostElementPrototype The Stencil component to be patched
|
|
751
|
+
*/
|
|
752
|
+
const patchSlotAppendChild = (HostElementPrototype) => {
|
|
753
|
+
if (HostElementPrototype.__appendChild) return;
|
|
754
|
+
HostElementPrototype.__appendChild = HostElementPrototype.appendChild;
|
|
755
|
+
HostElementPrototype.appendChild = function(newChild) {
|
|
756
|
+
const { slotName, slotNode } = findSlotFromSlottedNode(newChild, this);
|
|
757
|
+
if (slotNode) {
|
|
758
|
+
addSlotRelocateNode(newChild, slotNode);
|
|
759
|
+
const slotChildNodes = getSlotChildSiblings(slotNode, slotName);
|
|
760
|
+
const appendAfter = slotChildNodes[slotChildNodes.length - 1];
|
|
761
|
+
const insertedNode = internalCall(internalCall(appendAfter, "parentNode"), "insertBefore")(newChild, appendAfter.nextSibling);
|
|
762
|
+
dispatchSlotChangeEvent(slotNode);
|
|
763
|
+
updateFallbackSlotVisibility(this);
|
|
764
|
+
return insertedNode;
|
|
765
|
+
}
|
|
766
|
+
return this.__appendChild(newChild);
|
|
767
|
+
};
|
|
768
|
+
};
|
|
769
|
+
/**
|
|
770
|
+
* Patches the `removeChild` method on a `scoped` Stencil component.
|
|
771
|
+
* This patch attempts to remove the specified node from a slot reference
|
|
772
|
+
* if the slot exists. Otherwise, it falls-back to the original `removeChild` method.
|
|
773
|
+
*
|
|
774
|
+
* @param ElementPrototype The Stencil component to be patched
|
|
775
|
+
*/
|
|
776
|
+
const patchSlotRemoveChild = (ElementPrototype) => {
|
|
777
|
+
if (ElementPrototype.__removeChild) return;
|
|
778
|
+
ElementPrototype.__removeChild = ElementPrototype.removeChild;
|
|
779
|
+
ElementPrototype.removeChild = function(toRemove) {
|
|
780
|
+
if (toRemove && typeof toRemove["s-sn"] !== "undefined") {
|
|
781
|
+
if (getHostSlotNodes(this.__childNodes || this.childNodes, this.tagName, toRemove["s-sn"]) && toRemove.isConnected) {
|
|
782
|
+
toRemove.remove();
|
|
783
|
+
updateFallbackSlotVisibility(this);
|
|
784
|
+
return;
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
return this.__removeChild(toRemove);
|
|
788
|
+
};
|
|
789
|
+
};
|
|
790
|
+
/**
|
|
791
|
+
* Patches the `prepend` method for a slotted node inside a scoped component.
|
|
792
|
+
*
|
|
793
|
+
* @param HostElementPrototype the `Element` to be patched
|
|
794
|
+
*/
|
|
795
|
+
const patchSlotPrepend = (HostElementPrototype) => {
|
|
796
|
+
if (HostElementPrototype.__prepend) return;
|
|
797
|
+
HostElementPrototype.__prepend = HostElementPrototype.prepend;
|
|
798
|
+
HostElementPrototype.prepend = function(...newChildren) {
|
|
799
|
+
newChildren.forEach((newChild) => {
|
|
800
|
+
if (typeof newChild === "string") newChild = this.ownerDocument.createTextNode(newChild);
|
|
801
|
+
const slotName = (newChild["s-sn"] = getSlotName(newChild)) || "";
|
|
802
|
+
const slotNode = getHostSlotNodes(internalCall(this, "childNodes"), this.tagName, slotName)[0];
|
|
803
|
+
if (slotNode) {
|
|
804
|
+
addSlotRelocateNode(newChild, slotNode, true);
|
|
805
|
+
const appendAfter = getSlotChildSiblings(slotNode, slotName)[0];
|
|
806
|
+
const toReturn = internalCall(internalCall(appendAfter, "parentNode"), "insertBefore")(newChild, internalCall(appendAfter, "nextSibling"));
|
|
807
|
+
dispatchSlotChangeEvent(slotNode);
|
|
808
|
+
return toReturn;
|
|
809
|
+
}
|
|
810
|
+
if (newChild.nodeType === 1 && !!newChild.getAttribute("slot")) newChild.hidden = true;
|
|
811
|
+
return HostElementPrototype.__prepend(newChild);
|
|
812
|
+
});
|
|
813
|
+
};
|
|
814
|
+
};
|
|
815
|
+
/**
|
|
816
|
+
* Patches the `append` method for a slotted node inside a scoped component. The patched method uses
|
|
817
|
+
* `appendChild` under-the-hood while creating text nodes for any new children that passed as bare strings.
|
|
818
|
+
*
|
|
819
|
+
* @param HostElementPrototype the `Element` to be patched
|
|
820
|
+
*/
|
|
821
|
+
const patchSlotAppend = (HostElementPrototype) => {
|
|
822
|
+
if (HostElementPrototype.__append) return;
|
|
823
|
+
HostElementPrototype.__append = HostElementPrototype.append;
|
|
824
|
+
HostElementPrototype.append = function(...newChildren) {
|
|
825
|
+
newChildren.forEach((newChild) => {
|
|
826
|
+
if (typeof newChild === "string") newChild = this.ownerDocument.createTextNode(newChild);
|
|
827
|
+
this.appendChild(newChild);
|
|
828
|
+
});
|
|
829
|
+
};
|
|
830
|
+
};
|
|
831
|
+
/**
|
|
832
|
+
* Patches the `insertAdjacentHTML` method for a slotted node inside a scoped component. Specifically,
|
|
833
|
+
* we only need to patch the behavior for the specific `beforeend` and `afterbegin` positions so the element
|
|
834
|
+
* gets inserted into the DOM in the correct location.
|
|
835
|
+
*
|
|
836
|
+
* @param HostElementPrototype the `Element` to be patched
|
|
837
|
+
*/
|
|
838
|
+
const patchSlotInsertAdjacentHTML = (HostElementPrototype) => {
|
|
839
|
+
if (HostElementPrototype.__insertAdjacentHTML) return;
|
|
840
|
+
const originalInsertAdjacentHtml = HostElementPrototype.insertAdjacentHTML;
|
|
841
|
+
HostElementPrototype.insertAdjacentHTML = function(position, text) {
|
|
842
|
+
if (position !== "afterbegin" && position !== "beforeend") return originalInsertAdjacentHtml.call(this, position, text);
|
|
843
|
+
const container = this.ownerDocument.createElement("_");
|
|
844
|
+
let node;
|
|
845
|
+
container.innerHTML = text;
|
|
846
|
+
if (position === "afterbegin") while (node = container.firstChild) this.prepend(node);
|
|
847
|
+
else if (position === "beforeend") while (node = container.firstChild) this.append(node);
|
|
848
|
+
};
|
|
849
|
+
};
|
|
850
|
+
/**
|
|
851
|
+
* Patches the `insertAdjacentText` method for a slotted node inside a scoped component. Specifically,
|
|
852
|
+
* we only need to patch the behavior for the specific `beforeend` and `afterbegin` positions so the text node
|
|
853
|
+
* gets inserted into the DOM in the correct location.
|
|
854
|
+
*
|
|
855
|
+
* @param HostElementPrototype the `Element` to be patched
|
|
856
|
+
*/
|
|
857
|
+
const patchSlotInsertAdjacentText = (HostElementPrototype) => {
|
|
858
|
+
HostElementPrototype.insertAdjacentText = function(position, text) {
|
|
859
|
+
this.insertAdjacentHTML(position, text);
|
|
860
|
+
};
|
|
861
|
+
};
|
|
862
|
+
/**
|
|
863
|
+
* Patches the `insertBefore` of a non-shadow component.
|
|
864
|
+
*
|
|
865
|
+
* The *current* node to insert before may not be in the root of our component
|
|
866
|
+
* (e.g. if it's 'slotted' it appears in the root, but isn't really)
|
|
867
|
+
*
|
|
868
|
+
* This tries to find where the *current* node lives within the component and insert the new node before it
|
|
869
|
+
* *If* the new node is in the same slot as the *current* node. Otherwise the new node is appended to it's 'slot'
|
|
870
|
+
*
|
|
871
|
+
* @param HostElementPrototype the custom element prototype to patch
|
|
872
|
+
*/
|
|
873
|
+
const patchInsertBefore = (HostElementPrototype) => {
|
|
874
|
+
if (HostElementPrototype.__insertBefore) return;
|
|
875
|
+
const eleProto = HostElementPrototype;
|
|
876
|
+
if (eleProto.__insertBefore) return;
|
|
877
|
+
eleProto.__insertBefore = HostElementPrototype.insertBefore;
|
|
878
|
+
HostElementPrototype.insertBefore = function(newChild, currentChild) {
|
|
879
|
+
const { slotName, slotNode } = findSlotFromSlottedNode(newChild, this);
|
|
880
|
+
const slottedNodes = this.__childNodes ? this.childNodes : getSlottedChildNodes(this.childNodes);
|
|
881
|
+
if (slotNode) {
|
|
882
|
+
let found = false;
|
|
883
|
+
slottedNodes.forEach((childNode) => {
|
|
884
|
+
if (childNode === currentChild || currentChild === null) {
|
|
885
|
+
found = true;
|
|
886
|
+
if (currentChild === null || slotName !== currentChild["s-sn"]) {
|
|
887
|
+
this.appendChild(newChild);
|
|
888
|
+
return;
|
|
889
|
+
}
|
|
890
|
+
if (slotName === currentChild["s-sn"]) {
|
|
891
|
+
addSlotRelocateNode(newChild, slotNode);
|
|
892
|
+
internalCall(internalCall(currentChild, "parentNode"), "insertBefore")(newChild, currentChild);
|
|
893
|
+
dispatchSlotChangeEvent(slotNode);
|
|
894
|
+
}
|
|
895
|
+
return;
|
|
896
|
+
}
|
|
897
|
+
});
|
|
898
|
+
if (found) return newChild;
|
|
899
|
+
}
|
|
900
|
+
/**
|
|
901
|
+
* Fixes an issue where slotted elements are dynamically relocated in React, such as after data fetch.
|
|
902
|
+
*
|
|
903
|
+
* When a slotted element is passed to another scoped component (e.g., <A><C slot="header"/></A>),
|
|
904
|
+
* the child’s __parentNode (original parent node property) does not match this.
|
|
905
|
+
*
|
|
906
|
+
* To prevent errors, this checks if the current child's parent node differs from this.
|
|
907
|
+
* If so, appendChild(newChild) is called to ensure the child is correctly inserted,
|
|
908
|
+
* allowing Stencil to properly manage the slot placement.
|
|
909
|
+
*/
|
|
910
|
+
const parentNode = currentChild?.__parentNode;
|
|
911
|
+
if (parentNode && !this.isSameNode(parentNode)) return this.appendChild(newChild);
|
|
912
|
+
return this.__insertBefore(newChild, currentChild);
|
|
913
|
+
};
|
|
914
|
+
};
|
|
915
|
+
/**
|
|
916
|
+
* Patches the `insertAdjacentElement` method for a slotted node inside a scoped component. Specifically,
|
|
917
|
+
* we only need to patch the behavior for the specific `beforeend` and `afterbegin` positions so the element
|
|
918
|
+
* gets inserted into the DOM in the correct location.
|
|
919
|
+
*
|
|
920
|
+
* @param HostElementPrototype the `Element` to be patched
|
|
921
|
+
*/
|
|
922
|
+
const patchSlotInsertAdjacentElement = (HostElementPrototype) => {
|
|
923
|
+
if (HostElementPrototype.__insertAdjacentElement) return;
|
|
924
|
+
const originalInsertAdjacentElement = HostElementPrototype.insertAdjacentElement;
|
|
925
|
+
HostElementPrototype.insertAdjacentElement = function(position, element) {
|
|
926
|
+
if (position !== "afterbegin" && position !== "beforeend") return originalInsertAdjacentElement.call(this, position, element);
|
|
927
|
+
if (position === "afterbegin") {
|
|
928
|
+
this.prepend(element);
|
|
929
|
+
return element;
|
|
930
|
+
} else if (position === "beforeend") {
|
|
931
|
+
this.append(element);
|
|
932
|
+
return element;
|
|
933
|
+
}
|
|
934
|
+
return element;
|
|
935
|
+
};
|
|
936
|
+
};
|
|
937
|
+
/**
|
|
938
|
+
* Patches the `textContent` of an unnamed slotted node inside a scoped component
|
|
939
|
+
*
|
|
940
|
+
* @param hostElementPrototype the `Element` to be patched
|
|
941
|
+
*/
|
|
942
|
+
const patchTextContent = (hostElementPrototype) => {
|
|
943
|
+
patchHostOriginalAccessor("textContent", hostElementPrototype);
|
|
944
|
+
Object.defineProperty(hostElementPrototype, "textContent", {
|
|
945
|
+
get: function() {
|
|
946
|
+
let text = "";
|
|
947
|
+
(this.__childNodes ? this.childNodes : getSlottedChildNodes(this.childNodes)).forEach((node) => text += node.textContent || "");
|
|
948
|
+
return text;
|
|
949
|
+
},
|
|
950
|
+
set: function(value) {
|
|
951
|
+
(this.__childNodes ? this.childNodes : getSlottedChildNodes(this.childNodes)).forEach((node) => {
|
|
952
|
+
if (node["s-ol"]) node["s-ol"].remove();
|
|
953
|
+
node.remove();
|
|
954
|
+
});
|
|
955
|
+
this.insertAdjacentHTML("beforeend", value);
|
|
956
|
+
}
|
|
957
|
+
});
|
|
958
|
+
};
|
|
959
|
+
const patchChildSlotNodes = (elm) => {
|
|
960
|
+
class FakeNodeList extends Array {
|
|
961
|
+
item(n) {
|
|
962
|
+
return this[n];
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
patchHostOriginalAccessor("children", elm);
|
|
966
|
+
Object.defineProperty(elm, "children", { get() {
|
|
967
|
+
return this.childNodes.filter((n) => n.nodeType === 1);
|
|
968
|
+
} });
|
|
969
|
+
Object.defineProperty(elm, "childElementCount", { get() {
|
|
970
|
+
return this.children.length;
|
|
971
|
+
} });
|
|
972
|
+
patchHostOriginalAccessor("firstChild", elm);
|
|
973
|
+
Object.defineProperty(elm, "firstChild", { get() {
|
|
974
|
+
return this.childNodes[0];
|
|
975
|
+
} });
|
|
976
|
+
patchHostOriginalAccessor("lastChild", elm);
|
|
977
|
+
Object.defineProperty(elm, "lastChild", { get() {
|
|
978
|
+
return this.childNodes[this.childNodes.length - 1];
|
|
979
|
+
} });
|
|
980
|
+
patchHostOriginalAccessor("childNodes", elm);
|
|
981
|
+
Object.defineProperty(elm, "childNodes", { get() {
|
|
982
|
+
const result = new FakeNodeList();
|
|
983
|
+
result.push(...getSlottedChildNodes(this.__childNodes));
|
|
984
|
+
return result;
|
|
985
|
+
} });
|
|
986
|
+
};
|
|
987
|
+
/**
|
|
988
|
+
* Patches sibling accessors of a 'slotted' node within a non-shadow component.
|
|
989
|
+
* Meaning whilst stepping through a non-shadow element's nodes, only the mock 'lightDOM' nodes are returned.
|
|
990
|
+
* Especially relevant when rendering components via SSR... Frameworks will often try to reconcile their
|
|
991
|
+
* VDOM with the real DOM by stepping through nodes with 'nextSibling' et al.
|
|
992
|
+
* - `nextSibling`
|
|
993
|
+
* - `nextElementSibling`
|
|
994
|
+
* - `previousSibling`
|
|
995
|
+
* - `previousElementSibling`
|
|
996
|
+
*
|
|
997
|
+
* @param node the slotted node to be patched
|
|
998
|
+
*/
|
|
999
|
+
const patchSlottedNode = (node) => {
|
|
1000
|
+
if (!node || node.__nextSibling !== void 0 || !globalThis.Node) return;
|
|
1001
|
+
patchNextSibling(node);
|
|
1002
|
+
patchPreviousSibling(node);
|
|
1003
|
+
patchParentNode(node);
|
|
1004
|
+
if (node.nodeType === Node.ELEMENT_NODE) {
|
|
1005
|
+
patchNextElementSibling(node);
|
|
1006
|
+
patchPreviousElementSibling(node);
|
|
1007
|
+
}
|
|
1008
|
+
};
|
|
1009
|
+
/**
|
|
1010
|
+
* Patches the `nextSibling` accessor of a non-shadow slotted node
|
|
1011
|
+
*
|
|
1012
|
+
* @param node the slotted node to be patched
|
|
1013
|
+
*/
|
|
1014
|
+
const patchNextSibling = (node) => {
|
|
1015
|
+
if (!node || node.__nextSibling) return;
|
|
1016
|
+
patchHostOriginalAccessor("nextSibling", node);
|
|
1017
|
+
Object.defineProperty(node, "nextSibling", { get: function() {
|
|
1018
|
+
const parentNodes = this["s-ol"]?.parentNode.childNodes;
|
|
1019
|
+
const index = parentNodes?.indexOf(this);
|
|
1020
|
+
if (parentNodes && index > -1) return parentNodes[index + 1];
|
|
1021
|
+
return this.__nextSibling;
|
|
1022
|
+
} });
|
|
1023
|
+
};
|
|
1024
|
+
/**
|
|
1025
|
+
* Patches the `nextElementSibling` accessor of a non-shadow slotted node
|
|
1026
|
+
*
|
|
1027
|
+
* @param element the slotted element node to be patched
|
|
1028
|
+
*/
|
|
1029
|
+
const patchNextElementSibling = (element) => {
|
|
1030
|
+
if (!element || element.__nextElementSibling) return;
|
|
1031
|
+
patchHostOriginalAccessor("nextElementSibling", element);
|
|
1032
|
+
Object.defineProperty(element, "nextElementSibling", { get: function() {
|
|
1033
|
+
const parentEles = this["s-ol"]?.parentNode.children;
|
|
1034
|
+
const index = parentEles?.indexOf(this);
|
|
1035
|
+
if (parentEles && index > -1) return parentEles[index + 1];
|
|
1036
|
+
return this.__nextElementSibling;
|
|
1037
|
+
} });
|
|
1038
|
+
};
|
|
1039
|
+
/**
|
|
1040
|
+
* Patches the `previousSibling` accessor of a non-shadow slotted node
|
|
1041
|
+
*
|
|
1042
|
+
* @param node the slotted node to be patched
|
|
1043
|
+
*/
|
|
1044
|
+
const patchPreviousSibling = (node) => {
|
|
1045
|
+
if (!node || node.__previousSibling) return;
|
|
1046
|
+
patchHostOriginalAccessor("previousSibling", node);
|
|
1047
|
+
Object.defineProperty(node, "previousSibling", { get: function() {
|
|
1048
|
+
const parentNodes = this["s-ol"]?.parentNode.childNodes;
|
|
1049
|
+
const index = parentNodes?.indexOf(this);
|
|
1050
|
+
if (parentNodes && index > -1) return parentNodes[index - 1];
|
|
1051
|
+
return this.__previousSibling;
|
|
1052
|
+
} });
|
|
1053
|
+
};
|
|
1054
|
+
/**
|
|
1055
|
+
* Patches the `previousElementSibling` accessor of a non-shadow slotted node
|
|
1056
|
+
*
|
|
1057
|
+
* @param element the slotted element node to be patched
|
|
1058
|
+
*/
|
|
1059
|
+
const patchPreviousElementSibling = (element) => {
|
|
1060
|
+
if (!element || element.__previousElementSibling) return;
|
|
1061
|
+
patchHostOriginalAccessor("previousElementSibling", element);
|
|
1062
|
+
Object.defineProperty(element, "previousElementSibling", { get: function() {
|
|
1063
|
+
const parentNodes = this["s-ol"]?.parentNode.children;
|
|
1064
|
+
const index = parentNodes?.indexOf(this);
|
|
1065
|
+
if (parentNodes && index > -1) return parentNodes[index - 1];
|
|
1066
|
+
return this.__previousElementSibling;
|
|
1067
|
+
} });
|
|
1068
|
+
};
|
|
1069
|
+
/**
|
|
1070
|
+
* Patches the `parentNode` accessor of a non-shadow slotted node
|
|
1071
|
+
*
|
|
1072
|
+
* @param node the slotted node to be patched
|
|
1073
|
+
*/
|
|
1074
|
+
const patchParentNode = (node) => {
|
|
1075
|
+
if (!node || node.__parentNode) return;
|
|
1076
|
+
patchHostOriginalAccessor("parentNode", node);
|
|
1077
|
+
Object.defineProperty(node, "parentNode", {
|
|
1078
|
+
get: function() {
|
|
1079
|
+
return this["s-ol"]?.parentNode || this.__parentNode;
|
|
1080
|
+
},
|
|
1081
|
+
set: function(value) {
|
|
1082
|
+
this.__parentNode = value;
|
|
1083
|
+
}
|
|
1084
|
+
});
|
|
1085
|
+
};
|
|
1086
|
+
const validElementPatches = [
|
|
1087
|
+
"children",
|
|
1088
|
+
"nextElementSibling",
|
|
1089
|
+
"previousElementSibling"
|
|
1090
|
+
];
|
|
1091
|
+
const validNodesPatches = [
|
|
1092
|
+
"childNodes",
|
|
1093
|
+
"firstChild",
|
|
1094
|
+
"lastChild",
|
|
1095
|
+
"nextSibling",
|
|
1096
|
+
"previousSibling",
|
|
1097
|
+
"textContent",
|
|
1098
|
+
"parentNode"
|
|
1099
|
+
];
|
|
1100
|
+
/**
|
|
1101
|
+
* Patches a node or element; making it's original accessor method available under a new name.
|
|
1102
|
+
* e.g. `nextSibling` -> `__nextSibling`
|
|
1103
|
+
*
|
|
1104
|
+
* @param accessorName - the name of the accessor to patch
|
|
1105
|
+
* @param node - the node to patch
|
|
1106
|
+
*/
|
|
1107
|
+
function patchHostOriginalAccessor(accessorName, node) {
|
|
1108
|
+
/**
|
|
1109
|
+
* skip this method if a component was imported from a non-browser environment
|
|
1110
|
+
*/
|
|
1111
|
+
if (!globalThis.Node || !globalThis.Element) return;
|
|
1112
|
+
let accessor;
|
|
1113
|
+
if (validElementPatches.includes(accessorName)) accessor = Object.getOwnPropertyDescriptor(Element.prototype, accessorName);
|
|
1114
|
+
else if (validNodesPatches.includes(accessorName)) accessor = Object.getOwnPropertyDescriptor(Node.prototype, accessorName);
|
|
1115
|
+
if (!accessor) accessor = Object.getOwnPropertyDescriptor(node, accessorName);
|
|
1116
|
+
if (accessor) Object.defineProperty(node, "__" + accessorName, accessor);
|
|
1117
|
+
}
|
|
1118
|
+
/**
|
|
1119
|
+
* Get the original / internal accessor or method of a node or element.
|
|
1120
|
+
*
|
|
1121
|
+
* @param node - the node to get the accessor from
|
|
1122
|
+
* @param method - the name of the accessor to get
|
|
1123
|
+
*
|
|
1124
|
+
* @returns the original accessor or method of the node
|
|
1125
|
+
*/
|
|
1126
|
+
function internalCall(node, method) {
|
|
1127
|
+
if ("__" + method in node) {
|
|
1128
|
+
const toReturn = node["__" + method];
|
|
1129
|
+
if (typeof toReturn !== "function") return toReturn;
|
|
1130
|
+
return toReturn.bind(node);
|
|
1131
|
+
} else {
|
|
1132
|
+
if (typeof node[method] !== "function") return node[method];
|
|
1133
|
+
return node[method].bind(node);
|
|
1134
|
+
}
|
|
1135
|
+
}
|
|
1136
|
+
|
|
1137
|
+
//#endregion
|
|
1138
|
+
//#region src/runtime/profile.ts
|
|
1139
|
+
let i = 0;
|
|
1140
|
+
const createTime = (fnName, tagName = "") => {
|
|
1141
|
+
if (BUILD.profile && performance.mark) {
|
|
1142
|
+
const key = `st:${fnName}:${tagName}:${i++}`;
|
|
1143
|
+
performance.mark(key);
|
|
1144
|
+
return () => performance.measure(`[Stencil] ${fnName}() <${tagName}>`, key);
|
|
1145
|
+
} else return () => {};
|
|
1146
|
+
};
|
|
1147
|
+
const uniqueTime = (key, measureText) => {
|
|
1148
|
+
if (BUILD.profile && performance.mark) {
|
|
1149
|
+
if (performance.getEntriesByName(key, "mark").length === 0) performance.mark(key);
|
|
1150
|
+
return () => {
|
|
1151
|
+
if (performance.getEntriesByName(measureText, "measure").length === 0) performance.measure(measureText, key);
|
|
1152
|
+
};
|
|
1153
|
+
} else return () => {};
|
|
1154
|
+
};
|
|
1155
|
+
const inspect = (ref) => {
|
|
1156
|
+
const hostRef = getHostRef(ref);
|
|
1157
|
+
if (!hostRef) return;
|
|
1158
|
+
const flags = hostRef.$flags$;
|
|
1159
|
+
const hostElement = hostRef.$hostElement$;
|
|
1160
|
+
return {
|
|
1161
|
+
renderCount: hostRef.$renderCount$,
|
|
1162
|
+
flags: {
|
|
1163
|
+
hasRendered: !!(flags & HOST_FLAGS.hasRendered),
|
|
1164
|
+
hasConnected: !!(flags & HOST_FLAGS.hasConnected),
|
|
1165
|
+
isWaitingForChildren: !!(flags & HOST_FLAGS.isWaitingForChildren),
|
|
1166
|
+
isConstructingInstance: !!(flags & HOST_FLAGS.isConstructingInstance),
|
|
1167
|
+
isQueuedForUpdate: !!(flags & HOST_FLAGS.isQueuedForUpdate),
|
|
1168
|
+
hasInitializedComponent: !!(flags & HOST_FLAGS.hasInitializedComponent),
|
|
1169
|
+
hasLoadedComponent: !!(flags & HOST_FLAGS.hasLoadedComponent),
|
|
1170
|
+
isWatchReady: !!(flags & HOST_FLAGS.isWatchReady),
|
|
1171
|
+
isListenReady: !!(flags & HOST_FLAGS.isListenReady),
|
|
1172
|
+
needsRerender: !!(flags & HOST_FLAGS.needsRerender)
|
|
1173
|
+
},
|
|
1174
|
+
instanceValues: hostRef.$instanceValues$,
|
|
1175
|
+
serializerValues: hostRef.$serializerValues$,
|
|
1176
|
+
ancestorComponent: hostRef.$ancestorComponent$,
|
|
1177
|
+
hostElement,
|
|
1178
|
+
lazyInstance: hostRef.$lazyInstance$,
|
|
1179
|
+
vnode: hostRef.$vnode$,
|
|
1180
|
+
modeName: hostRef.$modeName$,
|
|
1181
|
+
fetchedCbList: hostRef.$fetchedCbList$,
|
|
1182
|
+
onReadyPromise: hostRef.$onReadyPromise$,
|
|
1183
|
+
onReadyResolve: hostRef.$onReadyResolve$,
|
|
1184
|
+
onInstancePromise: hostRef.$onInstancePromise$,
|
|
1185
|
+
onInstanceResolve: hostRef.$onInstanceResolve$,
|
|
1186
|
+
onRenderResolve: hostRef.$onRenderResolve$,
|
|
1187
|
+
queuedListeners: hostRef.$queuedListeners$,
|
|
1188
|
+
rmListeners: hostRef.$rmListeners$,
|
|
1189
|
+
["s-id"]: hostElement["s-id"],
|
|
1190
|
+
["s-cr"]: hostElement["s-cr"],
|
|
1191
|
+
["s-lr"]: hostElement["s-lr"],
|
|
1192
|
+
["s-p"]: hostElement["s-p"],
|
|
1193
|
+
["s-rc"]: hostElement["s-rc"],
|
|
1194
|
+
["s-sc"]: hostElement["s-sc"]
|
|
1195
|
+
};
|
|
1196
|
+
};
|
|
1197
|
+
const installDevTools = () => {
|
|
1198
|
+
if (BUILD.devTools) {
|
|
1199
|
+
const stencil = win.stencil = win.stencil || {};
|
|
1200
|
+
const originalInspect = stencil.inspect;
|
|
1201
|
+
stencil.inspect = (ref) => {
|
|
1202
|
+
let result = inspect(ref);
|
|
1203
|
+
if (!result && typeof originalInspect === "function") result = originalInspect(ref);
|
|
1204
|
+
return result;
|
|
1205
|
+
};
|
|
1206
|
+
}
|
|
1207
|
+
};
|
|
1208
|
+
|
|
1209
|
+
//#endregion
|
|
1210
|
+
//#region src/runtime/styles.ts
|
|
1211
|
+
const rootAppliedStyles = /* @__PURE__ */ new WeakMap();
|
|
1212
|
+
/**
|
|
1213
|
+
* Register the styles for a component by creating a stylesheet and then
|
|
1214
|
+
* registering it under the component's scope ID in a `WeakMap` for later use.
|
|
1215
|
+
*
|
|
1216
|
+
* If constructable stylesheet are not supported or `allowCS` is set to
|
|
1217
|
+
* `false` then the styles will be registered as a string instead.
|
|
1218
|
+
*
|
|
1219
|
+
* @param scopeId the scope ID for the component of interest
|
|
1220
|
+
* @param cssText styles for the component of interest
|
|
1221
|
+
* @param allowCS whether or not to use a constructable stylesheet
|
|
1222
|
+
*/
|
|
1223
|
+
const registerStyle = (scopeId, cssText, allowCS) => {
|
|
1224
|
+
let style = styles.get(scopeId);
|
|
1225
|
+
if (supportsConstructableStylesheets && allowCS) {
|
|
1226
|
+
style = style || new CSSStyleSheet();
|
|
1227
|
+
if (typeof style === "string") style = cssText;
|
|
1228
|
+
else style.replaceSync(cssText);
|
|
1229
|
+
} else style = cssText;
|
|
1230
|
+
styles.set(scopeId, style);
|
|
1231
|
+
};
|
|
1232
|
+
/**
|
|
1233
|
+
* Attach the styles for a given component to the DOM
|
|
1234
|
+
*
|
|
1235
|
+
* If the element uses shadow or is already attached to the DOM then we can
|
|
1236
|
+
* create a stylesheet inside of its associated document fragment, otherwise
|
|
1237
|
+
* we'll stick the stylesheet into the document head.
|
|
1238
|
+
*
|
|
1239
|
+
* @param styleContainerNode the node within which a style element for the
|
|
1240
|
+
* component of interest should be added
|
|
1241
|
+
* @param cmpMeta runtime metadata for the component of interest
|
|
1242
|
+
* @param mode an optional current mode
|
|
1243
|
+
* @returns the scope ID for the component of interest
|
|
1244
|
+
*/
|
|
1245
|
+
const addStyle = (styleContainerNode, cmpMeta, mode) => {
|
|
1246
|
+
const scopeId = getScopeId(cmpMeta, mode);
|
|
1247
|
+
const style = styles.get(scopeId);
|
|
1248
|
+
if (!BUILD.attachStyles || !win.document) return scopeId;
|
|
1249
|
+
styleContainerNode = styleContainerNode.nodeType === NODE_TYPE.DocumentFragment ? styleContainerNode : win.document;
|
|
1250
|
+
if (style) {
|
|
1251
|
+
if (typeof style === "string") {
|
|
1252
|
+
styleContainerNode = styleContainerNode.head || styleContainerNode;
|
|
1253
|
+
let appliedStyles = rootAppliedStyles.get(styleContainerNode);
|
|
1254
|
+
let styleElm;
|
|
1255
|
+
if (!appliedStyles) rootAppliedStyles.set(styleContainerNode, appliedStyles = /* @__PURE__ */ new Set());
|
|
1256
|
+
const existingStyleElm = (BUILD.hydrateClientSide || BUILD.hotModuleReplacement) && styleContainerNode.querySelector(`[${HYDRATED_STYLE_ID}="${scopeId}"]`);
|
|
1257
|
+
if (existingStyleElm) existingStyleElm.textContent = style;
|
|
1258
|
+
else if (!appliedStyles.has(scopeId)) {
|
|
1259
|
+
styleElm = win.document.createElement("style");
|
|
1260
|
+
styleElm.textContent = style;
|
|
1261
|
+
const nonce = plt.$nonce$ ?? queryNonceMetaTagContent(win.document);
|
|
1262
|
+
if (nonce != null) styleElm.setAttribute("nonce", nonce);
|
|
1263
|
+
if ((BUILD.hydrateServerSide || BUILD.hotModuleReplacement) && (cmpMeta.$flags$ & CMP_FLAGS.scopedCssEncapsulation || cmpMeta.$flags$ & CMP_FLAGS.shadowNeedsScopedCss || cmpMeta.$flags$ & CMP_FLAGS.shadowDomEncapsulation)) styleElm.setAttribute(HYDRATED_STYLE_ID, scopeId);
|
|
1264
|
+
/**
|
|
1265
|
+
* attach styles at the end of the head tag if we render scoped components
|
|
1266
|
+
*/
|
|
1267
|
+
if (!(cmpMeta.$flags$ & CMP_FLAGS.shadowDomEncapsulation)) if (styleContainerNode.nodeName === "HEAD") {
|
|
1268
|
+
/**
|
|
1269
|
+
* if the page contains preconnect links, we want to insert the styles
|
|
1270
|
+
* after the last preconnect link to ensure the styles are preloaded
|
|
1271
|
+
*/
|
|
1272
|
+
const preconnectLinks = styleContainerNode.querySelectorAll("link[rel=preconnect]");
|
|
1273
|
+
const referenceNode = preconnectLinks.length > 0 ? preconnectLinks[preconnectLinks.length - 1].nextSibling : styleContainerNode.querySelector("style");
|
|
1274
|
+
styleContainerNode.insertBefore(styleElm, referenceNode?.parentNode === styleContainerNode ? referenceNode : null);
|
|
1275
|
+
} else if ("host" in styleContainerNode) if (supportsConstructableStylesheets) {
|
|
1276
|
+
const stylesheet = new (styleContainerNode.defaultView ?? styleContainerNode.ownerDocument.defaultView).CSSStyleSheet();
|
|
1277
|
+
stylesheet.replaceSync(style);
|
|
1278
|
+
/**
|
|
1279
|
+
* > If the array needs to be modified, use in-place mutations like push().
|
|
1280
|
+
* https://developer.mozilla.org/en-US/docs/Web/API/Document/adoptedStyleSheets
|
|
1281
|
+
*/
|
|
1282
|
+
if (supportsMutableAdoptedStyleSheets) styleContainerNode.adoptedStyleSheets.unshift(stylesheet);
|
|
1283
|
+
else styleContainerNode.adoptedStyleSheets = [stylesheet, ...styleContainerNode.adoptedStyleSheets];
|
|
1284
|
+
} else {
|
|
1285
|
+
/**
|
|
1286
|
+
* If a scoped component is used within a shadow root and constructable stylesheets are
|
|
1287
|
+
* not supported, we want to insert the styles at the beginning of the shadow root node.
|
|
1288
|
+
*
|
|
1289
|
+
* However, if there is already a style node in the shadow root, we just append
|
|
1290
|
+
* the styles to the existing node.
|
|
1291
|
+
*
|
|
1292
|
+
* Note: order of how styles are applied is important. The new style node
|
|
1293
|
+
* should be inserted before the existing style node.
|
|
1294
|
+
*
|
|
1295
|
+
* During HMR, create separate style elements for scoped components so they can be
|
|
1296
|
+
* updated independently without affecting other components' styles.
|
|
1297
|
+
*/
|
|
1298
|
+
const existingStyleContainer = styleContainerNode.querySelector("style");
|
|
1299
|
+
if (existingStyleContainer && !BUILD.hotModuleReplacement) existingStyleContainer.textContent = style + existingStyleContainer.textContent;
|
|
1300
|
+
else styleContainerNode.prepend(styleElm);
|
|
1301
|
+
}
|
|
1302
|
+
else styleContainerNode.append(styleElm);
|
|
1303
|
+
/**
|
|
1304
|
+
* attach styles at the beginning of a shadow root node if we render shadow components
|
|
1305
|
+
*/
|
|
1306
|
+
if (cmpMeta.$flags$ & CMP_FLAGS.shadowDomEncapsulation) styleContainerNode.insertBefore(styleElm, null);
|
|
1307
|
+
if (cmpMeta.$flags$ & CMP_FLAGS.hasSlotRelocation) styleElm.textContent += SLOT_FB_CSS;
|
|
1308
|
+
if (appliedStyles) appliedStyles.add(scopeId);
|
|
1309
|
+
}
|
|
1310
|
+
} else if (BUILD.constructableCSS) {
|
|
1311
|
+
let appliedStyles = rootAppliedStyles.get(styleContainerNode);
|
|
1312
|
+
if (!appliedStyles) rootAppliedStyles.set(styleContainerNode, appliedStyles = /* @__PURE__ */ new Set());
|
|
1313
|
+
if (!appliedStyles.has(scopeId)) {
|
|
1314
|
+
/**
|
|
1315
|
+
* Constructable stylesheets can't be shared between windows,
|
|
1316
|
+
* we need to create a new one for the current window if necessary
|
|
1317
|
+
*/
|
|
1318
|
+
const currentWindow = styleContainerNode.defaultView ?? styleContainerNode.ownerDocument.defaultView;
|
|
1319
|
+
let stylesheet;
|
|
1320
|
+
if (style.constructor === currentWindow.CSSStyleSheet) stylesheet = style;
|
|
1321
|
+
else {
|
|
1322
|
+
stylesheet = new currentWindow.CSSStyleSheet();
|
|
1323
|
+
for (let i = 0; i < style.cssRules.length; i++) stylesheet.insertRule(style.cssRules[i].cssText, i);
|
|
1324
|
+
}
|
|
1325
|
+
/**
|
|
1326
|
+
* > If the array needs to be modified, use in-place mutations like push().
|
|
1327
|
+
* https://developer.mozilla.org/en-US/docs/Web/API/Document/adoptedStyleSheets
|
|
1328
|
+
*/
|
|
1329
|
+
if (supportsMutableAdoptedStyleSheets) styleContainerNode.adoptedStyleSheets.push(stylesheet);
|
|
1330
|
+
else styleContainerNode.adoptedStyleSheets = [...styleContainerNode.adoptedStyleSheets, stylesheet];
|
|
1331
|
+
appliedStyles.add(scopeId);
|
|
1332
|
+
if (BUILD.hydrateClientSide && "host" in styleContainerNode) {
|
|
1333
|
+
const ssrStyleElm = styleContainerNode.querySelector(`[${HYDRATED_STYLE_ID}="${scopeId}"]`);
|
|
1334
|
+
if (ssrStyleElm) writeTask(() => ssrStyleElm.remove());
|
|
1335
|
+
}
|
|
1336
|
+
}
|
|
1337
|
+
}
|
|
1338
|
+
}
|
|
1339
|
+
return scopeId;
|
|
1340
|
+
};
|
|
1341
|
+
/**
|
|
1342
|
+
* Add styles for a given component to the DOM, optionally handling 'scoped'
|
|
1343
|
+
* encapsulation by adding an appropriate class name to the host element.
|
|
1344
|
+
*
|
|
1345
|
+
* @param hostRef the host reference for the component of interest
|
|
1346
|
+
*/
|
|
1347
|
+
const attachStyles = (hostRef) => {
|
|
1348
|
+
const cmpMeta = hostRef.$cmpMeta$;
|
|
1349
|
+
const elm = hostRef.$hostElement$;
|
|
1350
|
+
const flags = cmpMeta.$flags$;
|
|
1351
|
+
const endAttachStyles = createTime("attachStyles", cmpMeta.$tagName$);
|
|
1352
|
+
const scopeId = addStyle(BUILD.shadowDom && supportsShadow && elm.shadowRoot ? elm.shadowRoot : elm.getRootNode(), cmpMeta, hostRef.$modeName$);
|
|
1353
|
+
if ((BUILD.shadowDom || BUILD.scoped) && BUILD.cssAnnotations && flags & CMP_FLAGS.needsScopedEncapsulation) {
|
|
1354
|
+
elm["s-sc"] = scopeId;
|
|
1355
|
+
elm.classList.add(scopeId + "-h");
|
|
1356
|
+
}
|
|
1357
|
+
endAttachStyles();
|
|
1358
|
+
};
|
|
1359
|
+
/**
|
|
1360
|
+
* Get the scope ID for a given component
|
|
1361
|
+
*
|
|
1362
|
+
* @param cmp runtime metadata for the component of interest
|
|
1363
|
+
* @param mode the current mode (optional)
|
|
1364
|
+
* @returns a scope ID for the component of interest
|
|
1365
|
+
*/
|
|
1366
|
+
const getScopeId = (cmp, mode) => "sc-" + (BUILD.mode && mode && cmp.$flags$ & CMP_FLAGS.hasMode ? cmp.$tagName$ + "-" + mode : cmp.$tagName$);
|
|
1367
|
+
/**
|
|
1368
|
+
* Convert a 'scoped' CSS string to one appropriate for use in the shadow DOM.
|
|
1369
|
+
*
|
|
1370
|
+
* Given a 'scoped' CSS string that looks like this:
|
|
1371
|
+
*
|
|
1372
|
+
* ```
|
|
1373
|
+
* /*!@div*\/div.class-name { display: flex };
|
|
1374
|
+
* ```
|
|
1375
|
+
*
|
|
1376
|
+
* Convert it to a 'shadow' appropriate string, like so:
|
|
1377
|
+
*
|
|
1378
|
+
* ```
|
|
1379
|
+
* /*!@div*\/div.class-name { display: flex }
|
|
1380
|
+
* ─┬─ ────────┬────────
|
|
1381
|
+
* │ │
|
|
1382
|
+
* │ ┌─────────────────┘
|
|
1383
|
+
* ▼ ▼
|
|
1384
|
+
* div{ display: flex }
|
|
1385
|
+
* ```
|
|
1386
|
+
*
|
|
1387
|
+
* Note that forward-slashes in the above are escaped so they don't end the
|
|
1388
|
+
* comment.
|
|
1389
|
+
*
|
|
1390
|
+
* @param css a CSS string to convert
|
|
1391
|
+
* @returns the converted string
|
|
1392
|
+
*/
|
|
1393
|
+
const convertScopedToShadow = (css) => css.replace(/\/\*!@([^\/]+)\*\/[^\{]+\{/g, "$1{");
|
|
1394
|
+
/**
|
|
1395
|
+
* Hydrate styles after SSR for components *not* using DSD. Convert 'scoped' styles to 'shadow'
|
|
1396
|
+
* and add them to a constructable stylesheet.
|
|
1397
|
+
*/
|
|
1398
|
+
const hydrateScopedToShadow = () => {
|
|
1399
|
+
if (!win.document) return;
|
|
1400
|
+
const styles = win.document.querySelectorAll(`[${HYDRATED_STYLE_ID}]`);
|
|
1401
|
+
let i = 0;
|
|
1402
|
+
for (; i < styles.length; i++) registerStyle(styles[i].getAttribute(HYDRATED_STYLE_ID), convertScopedToShadow(styles[i].innerHTML), true);
|
|
1403
|
+
};
|
|
1404
|
+
|
|
1405
|
+
//#endregion
|
|
1406
|
+
//#region src/runtime/vdom/h.ts
|
|
1407
|
+
/**
|
|
1408
|
+
* Production h() function based on Preact by
|
|
1409
|
+
* Jason Miller (@developit)
|
|
1410
|
+
* Licensed under the MIT License
|
|
1411
|
+
* https://github.com/developit/preact/blob/master/LICENSE
|
|
1412
|
+
*
|
|
1413
|
+
* Modified for Stencil's compiler and vdom
|
|
1414
|
+
*/
|
|
1415
|
+
const h = (nodeName, vnodeData, ...children) => {
|
|
1416
|
+
if (typeof nodeName === "string") nodeName = transformTag(nodeName);
|
|
1417
|
+
let child = null;
|
|
1418
|
+
let key = null;
|
|
1419
|
+
let slotName = null;
|
|
1420
|
+
let simple = false;
|
|
1421
|
+
let lastSimple = false;
|
|
1422
|
+
const vNodeChildren = [];
|
|
1423
|
+
const walk = (c) => {
|
|
1424
|
+
for (let i = 0; i < c.length; i++) {
|
|
1425
|
+
child = c[i];
|
|
1426
|
+
if (Array.isArray(child)) walk(child);
|
|
1427
|
+
else if (child != null && typeof child !== "boolean") {
|
|
1428
|
+
if (simple = typeof nodeName !== "function" && !isComplexType(child)) child = String(child);
|
|
1429
|
+
else if (BUILD.isDev && typeof nodeName !== "function" && child.$flags$ === void 0) consoleDevError(`vNode passed as children has unexpected type.
|
|
1430
|
+
Make sure it's using the correct h() function.
|
|
1431
|
+
Empty objects can also be the cause, look for JSX comments that became objects.`);
|
|
1432
|
+
if (simple && lastSimple) vNodeChildren[vNodeChildren.length - 1].$text$ += child;
|
|
1433
|
+
else vNodeChildren.push(simple ? newVNode(null, child) : child);
|
|
1434
|
+
lastSimple = simple;
|
|
1435
|
+
}
|
|
1436
|
+
}
|
|
1437
|
+
};
|
|
1438
|
+
walk(children);
|
|
1439
|
+
if (vnodeData) {
|
|
1440
|
+
if (BUILD.isDev && nodeName === "input") validateInputProperties(vnodeData);
|
|
1441
|
+
if (BUILD.vdomKey && vnodeData.key) key = vnodeData.key;
|
|
1442
|
+
if (BUILD.slotRelocation && vnodeData.name) slotName = vnodeData.name;
|
|
1443
|
+
if (BUILD.vdomClass) {
|
|
1444
|
+
const classData = vnodeData.className || vnodeData.class;
|
|
1445
|
+
if (classData) vnodeData.class = typeof classData !== "object" ? classData : Object.keys(classData).filter((k) => classData[k]).join(" ");
|
|
1446
|
+
}
|
|
1447
|
+
}
|
|
1448
|
+
if (BUILD.isDev && vNodeChildren.some(isHost)) consoleDevError(`The <Host> must be the single root component. Make sure:
|
|
1449
|
+
- You are NOT using hostData() and <Host> in the same component.
|
|
1450
|
+
- <Host> is used once, and it's the single root component of the render() function.`);
|
|
1451
|
+
if (BUILD.vdomFunctional && typeof nodeName === "function") return nodeName(vnodeData === null ? {} : vnodeData, vNodeChildren, vdomFnUtils);
|
|
1452
|
+
const vnode = newVNode(nodeName, null);
|
|
1453
|
+
vnode.$attrs$ = vnodeData;
|
|
1454
|
+
if (vNodeChildren.length > 0) vnode.$children$ = vNodeChildren;
|
|
1455
|
+
if (BUILD.vdomKey) vnode.$key$ = key;
|
|
1456
|
+
if (BUILD.slotRelocation) vnode.$name$ = slotName;
|
|
1457
|
+
return vnode;
|
|
1458
|
+
};
|
|
1459
|
+
/**
|
|
1460
|
+
* A utility function for creating a virtual DOM node from a tag and some
|
|
1461
|
+
* possible text content.
|
|
1462
|
+
*
|
|
1463
|
+
* @param tag the tag for this element
|
|
1464
|
+
* @param text possible text content for the node
|
|
1465
|
+
* @returns a newly-minted virtual DOM node
|
|
1466
|
+
*/
|
|
1467
|
+
const newVNode = (tag, text) => {
|
|
1468
|
+
const vnode = {
|
|
1469
|
+
$flags$: 0,
|
|
1470
|
+
$tag$: tag,
|
|
1471
|
+
$text$: text ?? null,
|
|
1472
|
+
$elm$: null,
|
|
1473
|
+
$children$: null
|
|
1474
|
+
};
|
|
1475
|
+
if (BUILD.vdomAttribute) vnode.$attrs$ = null;
|
|
1476
|
+
if (BUILD.vdomKey) vnode.$key$ = null;
|
|
1477
|
+
if (BUILD.slotRelocation) vnode.$name$ = null;
|
|
1478
|
+
return vnode;
|
|
1479
|
+
};
|
|
1480
|
+
const Host = {};
|
|
1481
|
+
/**
|
|
1482
|
+
* Check whether a given node is a Host node or not
|
|
1483
|
+
*
|
|
1484
|
+
* @param node the virtual DOM node to check
|
|
1485
|
+
* @returns whether it's a Host node or not
|
|
1486
|
+
*/
|
|
1487
|
+
const isHost = (node) => node && node.$tag$ === Host;
|
|
1488
|
+
/**
|
|
1489
|
+
* Implementation of {@link d.FunctionalUtilities} for Stencil's VDom.
|
|
1490
|
+
*
|
|
1491
|
+
* Note that these functions convert from {@link d.VNode} to
|
|
1492
|
+
* {@link d.ChildNode} to give functional component developers a friendly
|
|
1493
|
+
* interface.
|
|
1494
|
+
*/
|
|
1495
|
+
const vdomFnUtils = {
|
|
1496
|
+
forEach: (children, cb) => children.map(convertToPublic).forEach(cb),
|
|
1497
|
+
map: (children, cb) => children.map(convertToPublic).map(cb).map(convertToPrivate)
|
|
1498
|
+
};
|
|
1499
|
+
/**
|
|
1500
|
+
* Convert a {@link d.VNode} to a {@link d.ChildNode} in order to present a
|
|
1501
|
+
* friendlier public interface (hence, 'convertToPublic').
|
|
1502
|
+
*
|
|
1503
|
+
* @param node the virtual DOM node to convert
|
|
1504
|
+
* @returns a converted child node
|
|
1505
|
+
*/
|
|
1506
|
+
const convertToPublic = (node) => ({
|
|
1507
|
+
vattrs: node.$attrs$,
|
|
1508
|
+
vchildren: node.$children$,
|
|
1509
|
+
vkey: node.$key$,
|
|
1510
|
+
vname: node.$name$,
|
|
1511
|
+
vtag: node.$tag$,
|
|
1512
|
+
vtext: node.$text$
|
|
1513
|
+
});
|
|
1514
|
+
/**
|
|
1515
|
+
* Convert a {@link d.ChildNode} back to an equivalent {@link d.VNode} in
|
|
1516
|
+
* order to use the resulting object in the virtual DOM. The initial object was
|
|
1517
|
+
* likely created as part of presenting a public API, so converting it back
|
|
1518
|
+
* involved making it 'private' again (hence, `convertToPrivate`).
|
|
1519
|
+
*
|
|
1520
|
+
* @param node the child node to convert
|
|
1521
|
+
* @returns a converted virtual DOM node
|
|
1522
|
+
*/
|
|
1523
|
+
const convertToPrivate = (node) => {
|
|
1524
|
+
if (typeof node.vtag === "function") {
|
|
1525
|
+
const vnodeData = { ...node.vattrs };
|
|
1526
|
+
if (node.vkey) vnodeData.key = node.vkey;
|
|
1527
|
+
if (node.vname) vnodeData.name = node.vname;
|
|
1528
|
+
return h(node.vtag, vnodeData, ...node.vchildren || []);
|
|
1529
|
+
}
|
|
1530
|
+
const vnode = newVNode(node.vtag, node.vtext);
|
|
1531
|
+
vnode.$attrs$ = node.vattrs;
|
|
1532
|
+
vnode.$children$ = node.vchildren;
|
|
1533
|
+
vnode.$key$ = node.vkey;
|
|
1534
|
+
vnode.$name$ = node.vname;
|
|
1535
|
+
return vnode;
|
|
1536
|
+
};
|
|
1537
|
+
/**
|
|
1538
|
+
* Validates the ordering of attributes on an input element
|
|
1539
|
+
*
|
|
1540
|
+
* @param inputElm the element to validate
|
|
1541
|
+
*/
|
|
1542
|
+
const validateInputProperties = (inputElm) => {
|
|
1543
|
+
const props = Object.keys(inputElm);
|
|
1544
|
+
const value = props.indexOf("value");
|
|
1545
|
+
if (value === -1) return;
|
|
1546
|
+
const typeIndex = props.indexOf("type");
|
|
1547
|
+
const minIndex = props.indexOf("min");
|
|
1548
|
+
const maxIndex = props.indexOf("max");
|
|
1549
|
+
const stepIndex = props.indexOf("step");
|
|
1550
|
+
if (value < typeIndex || value < minIndex || value < maxIndex || value < stepIndex) consoleDevWarn(`The "value" prop of <input> should be set after "min", "max", "type" and "step"`);
|
|
1551
|
+
};
|
|
1552
|
+
|
|
1553
|
+
//#endregion
|
|
1554
|
+
//#region src/runtime/client-hydrate.ts
|
|
1555
|
+
/**
|
|
1556
|
+
* Takes an SSR rendered document, as annotated by 'vdom-annotations.ts' and:
|
|
1557
|
+
*
|
|
1558
|
+
* 1) Recreate an accurate VDOM which is fed to 'vdom-render.ts'. A failure to do so can cause hydration errors; extra renders, duplicated nodes
|
|
1559
|
+
* 2) Add shadowDOM trees to their respective #document-fragment
|
|
1560
|
+
* 3) Move forwarded, slotted nodes out of shadowDOMs
|
|
1561
|
+
* 4) Add meta nodes to non-shadow DOMs and their 'slotted' nodes
|
|
1562
|
+
*
|
|
1563
|
+
* @param hostElm The element to hydrate.
|
|
1564
|
+
* @param tagName The element's tag name.
|
|
1565
|
+
* @param hostId The host ID assigned to the element by the server. e.g. `s-id="1"`
|
|
1566
|
+
* @param hostRef The host reference for the element.
|
|
1567
|
+
*/
|
|
1568
|
+
const initializeClientHydrate = (hostElm, tagName, hostId, hostRef) => {
|
|
1569
|
+
const endHydrate = createTime("hydrateClient", tagName);
|
|
1570
|
+
const shadowRoot = hostElm.shadowRoot;
|
|
1571
|
+
const childRenderNodes = [];
|
|
1572
|
+
const slotNodes = [];
|
|
1573
|
+
const slottedNodes = [];
|
|
1574
|
+
const shadowRootNodes = BUILD.shadowDom && shadowRoot ? [] : null;
|
|
1575
|
+
const vnode = newVNode(tagName, null);
|
|
1576
|
+
vnode.$elm$ = hostElm;
|
|
1577
|
+
let scopeId;
|
|
1578
|
+
if (BUILD.scoped) {
|
|
1579
|
+
const cmpMeta = hostRef.$cmpMeta$;
|
|
1580
|
+
if (cmpMeta && cmpMeta.$flags$ & CMP_FLAGS.needsScopedEncapsulation && hostElm["s-sc"]) {
|
|
1581
|
+
scopeId = hostElm["s-sc"];
|
|
1582
|
+
hostElm.classList.add(scopeId + "-h");
|
|
1583
|
+
} else if (hostElm["s-sc"]) delete hostElm["s-sc"];
|
|
1584
|
+
}
|
|
1585
|
+
if (win.document && (!plt.$orgLocNodes$ || !plt.$orgLocNodes$.size)) initializeDocumentHydrate(win.document.body, plt.$orgLocNodes$ = /* @__PURE__ */ new Map());
|
|
1586
|
+
hostElm[HYDRATE_ID] = hostId;
|
|
1587
|
+
hostElm.removeAttribute(HYDRATE_ID);
|
|
1588
|
+
hostRef.$vnode$ = clientHydrate(vnode, childRenderNodes, slotNodes, shadowRootNodes, hostElm, hostElm, hostId, slottedNodes);
|
|
1589
|
+
let crIndex = 0;
|
|
1590
|
+
const crLength = childRenderNodes.length;
|
|
1591
|
+
let childRenderNode;
|
|
1592
|
+
for (; crIndex < crLength; crIndex++) {
|
|
1593
|
+
childRenderNode = childRenderNodes[crIndex];
|
|
1594
|
+
const orgLocationId = childRenderNode.$hostId$ + "." + childRenderNode.$nodeId$;
|
|
1595
|
+
const orgLocationNode = plt.$orgLocNodes$.get(orgLocationId);
|
|
1596
|
+
const node = childRenderNode.$elm$;
|
|
1597
|
+
if (!shadowRoot) {
|
|
1598
|
+
node["s-hn"] = transformTag(tagName).toUpperCase();
|
|
1599
|
+
if (childRenderNode.$tag$ === "slot") node["s-cr"] = hostElm["s-cr"];
|
|
1600
|
+
} else if (childRenderNode.$tag$?.toString().includes("-") && childRenderNode.$tag$ !== "slot-fb" && !childRenderNode.$elm$.shadowRoot) {
|
|
1601
|
+
const cmpMeta = getHostRef(childRenderNode.$elm$);
|
|
1602
|
+
if (cmpMeta) {
|
|
1603
|
+
const scopeId = getScopeId(cmpMeta.$cmpMeta$, BUILD.mode ? childRenderNode.$elm$.getAttribute("s-mode") : void 0);
|
|
1604
|
+
const styleSheet = win.document.querySelector(`style[sty-id="${scopeId}"]`);
|
|
1605
|
+
if (styleSheet) shadowRootNodes.unshift(styleSheet.cloneNode(true));
|
|
1606
|
+
}
|
|
1607
|
+
}
|
|
1608
|
+
if (childRenderNode.$tag$ === "slot") {
|
|
1609
|
+
childRenderNode.$name$ = childRenderNode.$elm$["s-sn"] || childRenderNode.$elm$["name"] || null;
|
|
1610
|
+
if (childRenderNode.$children$) {
|
|
1611
|
+
childRenderNode.$flags$ |= VNODE_FLAGS.isSlotFallback;
|
|
1612
|
+
if (!childRenderNode.$elm$.childNodes.length) childRenderNode.$children$.forEach((c) => {
|
|
1613
|
+
childRenderNode.$elm$.appendChild(c.$elm$);
|
|
1614
|
+
});
|
|
1615
|
+
} else childRenderNode.$flags$ |= VNODE_FLAGS.isSlotReference;
|
|
1616
|
+
}
|
|
1617
|
+
if (orgLocationNode && orgLocationNode.isConnected) {
|
|
1618
|
+
if (orgLocationNode.parentElement.shadowRoot && orgLocationNode["s-en"] === "") orgLocationNode.parentNode.insertBefore(node, orgLocationNode.nextSibling);
|
|
1619
|
+
orgLocationNode.parentNode.removeChild(orgLocationNode);
|
|
1620
|
+
if (!shadowRoot) node["s-oo"] = parseInt(childRenderNode.$nodeId$);
|
|
1621
|
+
}
|
|
1622
|
+
if (orgLocationNode && !orgLocationNode["s-id"]) plt.$orgLocNodes$.delete(orgLocationId);
|
|
1623
|
+
}
|
|
1624
|
+
const hosts = [];
|
|
1625
|
+
const snLen = slottedNodes.length;
|
|
1626
|
+
let snIndex = 0;
|
|
1627
|
+
let slotGroup;
|
|
1628
|
+
let snGroupIdx;
|
|
1629
|
+
let snGroupLen;
|
|
1630
|
+
let slottedItem;
|
|
1631
|
+
let currentPos = 0;
|
|
1632
|
+
for (; snIndex < snLen; snIndex++) {
|
|
1633
|
+
slotGroup = slottedNodes[snIndex];
|
|
1634
|
+
if (!slotGroup || !slotGroup.length) continue;
|
|
1635
|
+
snGroupLen = slotGroup.length;
|
|
1636
|
+
snGroupIdx = 0;
|
|
1637
|
+
for (; snGroupIdx < snGroupLen; snGroupIdx++) {
|
|
1638
|
+
slottedItem = slotGroup[snGroupIdx];
|
|
1639
|
+
if (!hosts[slottedItem.hostId]) hosts[slottedItem.hostId] = plt.$orgLocNodes$.get(slottedItem.hostId);
|
|
1640
|
+
if (!hosts[slottedItem.hostId]) continue;
|
|
1641
|
+
const hostEle = hosts[slottedItem.hostId];
|
|
1642
|
+
if (hostEle.shadowRoot && slottedItem.node.parentElement !== hostEle) hostEle.insertBefore(slottedItem.node, slotGroup[snGroupIdx - 1]?.node?.nextSibling);
|
|
1643
|
+
if (!hostEle.shadowRoot || !shadowRoot) {
|
|
1644
|
+
if (!slottedItem.slot["s-cr"]) {
|
|
1645
|
+
slottedItem.slot["s-cr"] = hostEle["s-cr"];
|
|
1646
|
+
if (!slottedItem.slot["s-cr"] && hostEle.shadowRoot) slottedItem.slot["s-cr"] = hostEle;
|
|
1647
|
+
else slottedItem.slot["s-cr"] = (hostEle.__childNodes || hostEle.childNodes)[0];
|
|
1648
|
+
}
|
|
1649
|
+
addSlotRelocateNode(slottedItem.node, slottedItem.slot, false, slottedItem.node["s-oo"] || currentPos);
|
|
1650
|
+
if (slottedItem.node.parentElement?.shadowRoot && slottedItem.node["getAttribute"] && slottedItem.node.getAttribute("slot")) slottedItem.node.removeAttribute("slot");
|
|
1651
|
+
if (BUILD.experimentalSlotFixes) patchSlottedNode(slottedItem.node);
|
|
1652
|
+
}
|
|
1653
|
+
currentPos = (slottedItem.node["s-oo"] || currentPos) + 1;
|
|
1654
|
+
}
|
|
1655
|
+
}
|
|
1656
|
+
if (BUILD.scoped && scopeId && slotNodes.length) slotNodes.forEach((slot) => {
|
|
1657
|
+
slot.$elm$.parentElement.classList.add(scopeId + "-s");
|
|
1658
|
+
});
|
|
1659
|
+
if (BUILD.shadowDom && shadowRoot && !shadowRoot.childNodes.length) {
|
|
1660
|
+
let rnIdex = 0;
|
|
1661
|
+
const rnLen = shadowRootNodes.length;
|
|
1662
|
+
if (rnLen) {
|
|
1663
|
+
for (; rnIdex < rnLen; rnIdex++) {
|
|
1664
|
+
const node = shadowRootNodes[rnIdex];
|
|
1665
|
+
/**
|
|
1666
|
+
* in apps with a lot of components the `shadowRootNodes` array can be modified while iterating over it
|
|
1667
|
+
* so we need to check if the node is still in the array before appending it to avoid any errors like:
|
|
1668
|
+
*
|
|
1669
|
+
* TypeError: Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'
|
|
1670
|
+
*/
|
|
1671
|
+
if (node) shadowRoot.appendChild(node);
|
|
1672
|
+
}
|
|
1673
|
+
Array.from(hostElm.childNodes).forEach((node) => {
|
|
1674
|
+
if (typeof node["s-en"] !== "string" && typeof node["s-sn"] !== "string") {
|
|
1675
|
+
if (node.nodeType === NODE_TYPE.ElementNode && node.slot && node.hidden) node.removeAttribute("hidden");
|
|
1676
|
+
else if (node.nodeType === NODE_TYPE.CommentNode && !node.nodeValue) node.parentNode.removeChild(node);
|
|
1677
|
+
}
|
|
1678
|
+
});
|
|
1679
|
+
}
|
|
1680
|
+
}
|
|
1681
|
+
hostRef.$hostElement$ = hostElm;
|
|
1682
|
+
endHydrate();
|
|
1683
|
+
};
|
|
1684
|
+
/**
|
|
1685
|
+
* Recursively constructs the virtual node tree for a host element and its children.
|
|
1686
|
+
* The tree is constructed by parsing the annotations set on the nodes by the server (`vdom-annotations.ts`).
|
|
1687
|
+
*
|
|
1688
|
+
* In addition to constructing the VNode tree, we also track information about the node's descendants:
|
|
1689
|
+
* - which are slots
|
|
1690
|
+
* - which should exist in the shadow root
|
|
1691
|
+
* - which are nodes that should be rendered as children of the parent node
|
|
1692
|
+
*
|
|
1693
|
+
* @param parentVNode The vNode representing the parent node.
|
|
1694
|
+
* @param childRenderNodes An array of all child nodes in the parent's node tree.
|
|
1695
|
+
* @param slotNodes An array of all slot nodes in the parent's node tree.
|
|
1696
|
+
* @param shadowRootNodes An array of nodes that should be rendered in the shadowDOM of the parent.
|
|
1697
|
+
* @param hostElm The parent element.
|
|
1698
|
+
* @param node The node to construct the vNode tree for.
|
|
1699
|
+
* @param hostId The host ID assigned to the element by the server.
|
|
1700
|
+
* @param slottedNodes - nodes that have been slotted
|
|
1701
|
+
* @returns - the constructed VNode
|
|
1702
|
+
*/
|
|
1703
|
+
const clientHydrate = (parentVNode, childRenderNodes, slotNodes, shadowRootNodes, hostElm, node, hostId, slottedNodes = []) => {
|
|
1704
|
+
let childNodeType;
|
|
1705
|
+
let childIdSplt;
|
|
1706
|
+
let childVNode;
|
|
1707
|
+
let i;
|
|
1708
|
+
const scopeId = hostElm["s-sc"];
|
|
1709
|
+
if (node.nodeType === NODE_TYPE.ElementNode) {
|
|
1710
|
+
childNodeType = node.getAttribute(HYDRATE_CHILD_ID);
|
|
1711
|
+
if (childNodeType) {
|
|
1712
|
+
childIdSplt = childNodeType.split(".");
|
|
1713
|
+
if (childIdSplt[0] === hostId || childIdSplt[0] === "0") {
|
|
1714
|
+
childVNode = createSimpleVNode({
|
|
1715
|
+
$flags$: 0,
|
|
1716
|
+
$hostId$: childIdSplt[0],
|
|
1717
|
+
$nodeId$: childIdSplt[1],
|
|
1718
|
+
$depth$: childIdSplt[2],
|
|
1719
|
+
$index$: childIdSplt[3],
|
|
1720
|
+
$tag$: node.tagName.toLowerCase(),
|
|
1721
|
+
$elm$: node,
|
|
1722
|
+
$attrs$: { class: node.className || "" }
|
|
1723
|
+
});
|
|
1724
|
+
childRenderNodes.push(childVNode);
|
|
1725
|
+
node.removeAttribute(HYDRATE_CHILD_ID);
|
|
1726
|
+
if (!parentVNode.$children$) parentVNode.$children$ = [];
|
|
1727
|
+
if (BUILD.scoped && scopeId && childIdSplt[0] === hostId) {
|
|
1728
|
+
node["s-si"] = scopeId;
|
|
1729
|
+
childVNode.$attrs$.class += " " + scopeId;
|
|
1730
|
+
}
|
|
1731
|
+
const slotName = childVNode.$elm$.getAttribute("s-sn");
|
|
1732
|
+
if (typeof slotName === "string") {
|
|
1733
|
+
if (childVNode.$tag$ === "slot-fb") {
|
|
1734
|
+
addSlot(slotName, childIdSplt[2], childVNode, node, parentVNode, childRenderNodes, slotNodes, shadowRootNodes, slottedNodes);
|
|
1735
|
+
if (BUILD.scoped && scopeId) node.classList.add(scopeId);
|
|
1736
|
+
}
|
|
1737
|
+
childVNode.$elm$["s-sn"] = slotName;
|
|
1738
|
+
childVNode.$elm$.removeAttribute("s-sn");
|
|
1739
|
+
}
|
|
1740
|
+
if (childVNode.$index$ !== void 0) parentVNode.$children$[childVNode.$index$] = childVNode;
|
|
1741
|
+
parentVNode = childVNode;
|
|
1742
|
+
if (shadowRootNodes && childVNode.$depth$ === "0") shadowRootNodes[childVNode.$index$] = childVNode.$elm$;
|
|
1743
|
+
}
|
|
1744
|
+
}
|
|
1745
|
+
if (node.shadowRoot) for (i = node.shadowRoot.childNodes.length - 1; i >= 0; i--) clientHydrate(parentVNode, childRenderNodes, slotNodes, shadowRootNodes, hostElm, node.shadowRoot.childNodes[i], hostId, slottedNodes);
|
|
1746
|
+
const nonShadowNodes = node.__childNodes || node.childNodes;
|
|
1747
|
+
for (i = nonShadowNodes.length - 1; i >= 0; i--) clientHydrate(parentVNode, childRenderNodes, slotNodes, shadowRootNodes, hostElm, nonShadowNodes[i], hostId, slottedNodes);
|
|
1748
|
+
} else if (node.nodeType === NODE_TYPE.CommentNode) {
|
|
1749
|
+
childIdSplt = node.nodeValue.split(".");
|
|
1750
|
+
if (childIdSplt[1] === hostId || childIdSplt[1] === "0") {
|
|
1751
|
+
childNodeType = childIdSplt[0];
|
|
1752
|
+
childVNode = createSimpleVNode({
|
|
1753
|
+
$hostId$: childIdSplt[1],
|
|
1754
|
+
$nodeId$: childIdSplt[2],
|
|
1755
|
+
$depth$: childIdSplt[3],
|
|
1756
|
+
$index$: childIdSplt[4] || "0",
|
|
1757
|
+
$elm$: node,
|
|
1758
|
+
$attrs$: null,
|
|
1759
|
+
$children$: null,
|
|
1760
|
+
$key$: null,
|
|
1761
|
+
$name$: null,
|
|
1762
|
+
$tag$: null,
|
|
1763
|
+
$text$: null
|
|
1764
|
+
});
|
|
1765
|
+
if (childNodeType === TEXT_NODE_ID) {
|
|
1766
|
+
childVNode.$elm$ = findCorrespondingNode(node, NODE_TYPE.TextNode);
|
|
1767
|
+
if (childVNode.$elm$ && childVNode.$elm$.nodeType === NODE_TYPE.TextNode) {
|
|
1768
|
+
childVNode.$text$ = childVNode.$elm$.textContent;
|
|
1769
|
+
childRenderNodes.push(childVNode);
|
|
1770
|
+
node.remove();
|
|
1771
|
+
if (hostId === childVNode.$hostId$) {
|
|
1772
|
+
if (!parentVNode.$children$) parentVNode.$children$ = [];
|
|
1773
|
+
parentVNode.$children$[childVNode.$index$] = childVNode;
|
|
1774
|
+
}
|
|
1775
|
+
if (shadowRootNodes && childVNode.$depth$ === "0") shadowRootNodes[childVNode.$index$] = childVNode.$elm$;
|
|
1776
|
+
}
|
|
1777
|
+
} else if (childNodeType === COMMENT_NODE_ID) {
|
|
1778
|
+
childVNode.$elm$ = findCorrespondingNode(node, NODE_TYPE.CommentNode);
|
|
1779
|
+
if (childVNode.$elm$ && childVNode.$elm$.nodeType === NODE_TYPE.CommentNode) {
|
|
1780
|
+
childRenderNodes.push(childVNode);
|
|
1781
|
+
node.remove();
|
|
1782
|
+
}
|
|
1783
|
+
} else if (childVNode.$hostId$ === hostId) {
|
|
1784
|
+
if (childNodeType === SLOT_NODE_ID) addSlot(node["s-sn"] = childIdSplt[5] || "", childIdSplt[2], childVNode, node, parentVNode, childRenderNodes, slotNodes, shadowRootNodes, slottedNodes);
|
|
1785
|
+
else if (childNodeType === CONTENT_REF_ID) {
|
|
1786
|
+
if (BUILD.shadowDom && shadowRootNodes) node.remove();
|
|
1787
|
+
else if (BUILD.slotRelocation) {
|
|
1788
|
+
hostElm["s-cr"] = node;
|
|
1789
|
+
node["s-cn"] = true;
|
|
1790
|
+
}
|
|
1791
|
+
}
|
|
1792
|
+
}
|
|
1793
|
+
}
|
|
1794
|
+
} else if (parentVNode && parentVNode.$tag$ === "style") {
|
|
1795
|
+
const vnode = newVNode(null, node.textContent);
|
|
1796
|
+
vnode.$elm$ = node;
|
|
1797
|
+
vnode.$index$ = "0";
|
|
1798
|
+
parentVNode.$children$ = [vnode];
|
|
1799
|
+
}
|
|
1800
|
+
return parentVNode;
|
|
1801
|
+
};
|
|
1802
|
+
/**
|
|
1803
|
+
* Recursively locate any comments representing an 'original location' for a node; in a node's children or shadowRoot children.
|
|
1804
|
+
* Creates a map of component IDs and 'original location' ID's which are derived from comment nodes placed by 'vdom-annotations.ts'.
|
|
1805
|
+
* Each 'original location' relates to a lightDOM node that was moved deeper into the SSR markup. e.g. `<!--o.1-->` maps to `<div c-id="0.1">`
|
|
1806
|
+
*
|
|
1807
|
+
* @param node The node to search.
|
|
1808
|
+
* @param orgLocNodes A map of the original location annotations and the current node being searched.
|
|
1809
|
+
*/
|
|
1810
|
+
const initializeDocumentHydrate = (node, orgLocNodes) => {
|
|
1811
|
+
if (node.nodeType === NODE_TYPE.ElementNode) {
|
|
1812
|
+
const componentId = node[HYDRATE_ID] || node.getAttribute(HYDRATE_ID);
|
|
1813
|
+
if (componentId) orgLocNodes.set(componentId, node);
|
|
1814
|
+
let i = 0;
|
|
1815
|
+
if (node.shadowRoot) for (; i < node.shadowRoot.childNodes.length; i++) initializeDocumentHydrate(node.shadowRoot.childNodes[i], orgLocNodes);
|
|
1816
|
+
const nonShadowNodes = node.__childNodes || node.childNodes;
|
|
1817
|
+
for (i = 0; i < nonShadowNodes.length; i++) initializeDocumentHydrate(nonShadowNodes[i], orgLocNodes);
|
|
1818
|
+
} else if (node.nodeType === NODE_TYPE.CommentNode) {
|
|
1819
|
+
const childIdSplt = node.nodeValue.split(".");
|
|
1820
|
+
if (childIdSplt[0] === ORG_LOCATION_ID) {
|
|
1821
|
+
orgLocNodes.set(childIdSplt[1] + "." + childIdSplt[2], node);
|
|
1822
|
+
node.nodeValue = "";
|
|
1823
|
+
node["s-en"] = childIdSplt[3];
|
|
1824
|
+
}
|
|
1825
|
+
}
|
|
1826
|
+
};
|
|
1827
|
+
/**
|
|
1828
|
+
* Creates a VNode to add to a hydrated component VDOM
|
|
1829
|
+
*
|
|
1830
|
+
* @param vnode - a vnode partial which will be augmented
|
|
1831
|
+
* @returns an complete vnode
|
|
1832
|
+
*/
|
|
1833
|
+
const createSimpleVNode = (vnode) => {
|
|
1834
|
+
return {
|
|
1835
|
+
$flags$: 0,
|
|
1836
|
+
$hostId$: null,
|
|
1837
|
+
$nodeId$: null,
|
|
1838
|
+
$depth$: null,
|
|
1839
|
+
$index$: "0",
|
|
1840
|
+
$elm$: null,
|
|
1841
|
+
$attrs$: null,
|
|
1842
|
+
$children$: null,
|
|
1843
|
+
$key$: null,
|
|
1844
|
+
$name$: null,
|
|
1845
|
+
$tag$: null,
|
|
1846
|
+
$text$: null,
|
|
1847
|
+
...vnode
|
|
1848
|
+
};
|
|
1849
|
+
};
|
|
1850
|
+
function addSlot(slotName, slotId, childVNode, node, parentVNode, childRenderNodes, slotNodes, shadowRootNodes, slottedNodes) {
|
|
1851
|
+
node["s-sr"] = true;
|
|
1852
|
+
childVNode.$name$ = slotName || null;
|
|
1853
|
+
childVNode.$tag$ = "slot";
|
|
1854
|
+
const parentNodeId = parentVNode?.$elm$ ? parentVNode.$elm$["s-id"] || parentVNode.$elm$.getAttribute("s-id") : "";
|
|
1855
|
+
if (BUILD.shadowDom && shadowRootNodes && win.document) {
|
|
1856
|
+
const slot = childVNode.$elm$ = win.document.createElement(childVNode.$tag$);
|
|
1857
|
+
if (childVNode.$name$) childVNode.$elm$.setAttribute("name", slotName);
|
|
1858
|
+
if (parentVNode.$elm$.shadowRoot && parentNodeId && parentNodeId !== childVNode.$hostId$) internalCall(parentVNode.$elm$, "insertBefore")(slot, internalCall(parentVNode.$elm$, "children")[0]);
|
|
1859
|
+
else internalCall(internalCall(node, "parentNode"), "insertBefore")(slot, node);
|
|
1860
|
+
addSlottedNodes(slottedNodes, slotId, slotName, node, childVNode.$hostId$);
|
|
1861
|
+
node.remove();
|
|
1862
|
+
if (childVNode.$depth$ === "0") shadowRootNodes[childVNode.$index$] = childVNode.$elm$;
|
|
1863
|
+
} else {
|
|
1864
|
+
const slot = childVNode.$elm$;
|
|
1865
|
+
const shouldMove = parentNodeId && parentNodeId !== childVNode.$hostId$ && parentVNode.$elm$.shadowRoot;
|
|
1866
|
+
addSlottedNodes(slottedNodes, slotId, slotName, node, shouldMove ? parentNodeId : childVNode.$hostId$);
|
|
1867
|
+
patchSlotNode(node);
|
|
1868
|
+
if (shouldMove) parentVNode.$elm$.insertBefore(slot, parentVNode.$elm$.children[0]);
|
|
1869
|
+
}
|
|
1870
|
+
childRenderNodes.push(childVNode);
|
|
1871
|
+
slotNodes.push(childVNode);
|
|
1872
|
+
if (!parentVNode.$children$) parentVNode.$children$ = [];
|
|
1873
|
+
parentVNode.$children$[childVNode.$index$] = childVNode;
|
|
1874
|
+
}
|
|
1875
|
+
/**
|
|
1876
|
+
* Adds groups of slotted nodes (grouped by slot ID) to this host element's 'master' array.
|
|
1877
|
+
* We'll use this after the host element's VDOM is completely constructed to finally position and add meta required by non-shadow slotted nodes
|
|
1878
|
+
*
|
|
1879
|
+
* @param slottedNodes - the main host element 'master' array to add to
|
|
1880
|
+
* @param slotNodeId - the slot node unique ID
|
|
1881
|
+
* @param slotName - the slot node name (can be '')
|
|
1882
|
+
* @param slotNode - the slot node
|
|
1883
|
+
* @param hostId - the host element id where this node should be slotted
|
|
1884
|
+
*/
|
|
1885
|
+
const addSlottedNodes = (slottedNodes, slotNodeId, slotName, slotNode, hostId) => {
|
|
1886
|
+
let slottedNode = slotNode.nextSibling;
|
|
1887
|
+
slottedNodes[slotNodeId] = slottedNodes[slotNodeId] || [];
|
|
1888
|
+
if (!slottedNode || slottedNode.nodeValue?.startsWith(SLOT_NODE_ID + ".")) return;
|
|
1889
|
+
do {
|
|
1890
|
+
if (slottedNode && ((slottedNode["getAttribute"] && slottedNode.getAttribute("slot") || slottedNode["s-sn"]) === slotName || slotName === "" && !slottedNode["s-sn"] && (!slottedNode["getAttribute"] || !slottedNode.getAttribute("slot")) && (slottedNode.nodeType === NODE_TYPE.CommentNode || slottedNode.nodeType === NODE_TYPE.TextNode))) {
|
|
1891
|
+
slottedNode["s-sn"] = slotName;
|
|
1892
|
+
slottedNodes[slotNodeId].push({
|
|
1893
|
+
slot: slotNode,
|
|
1894
|
+
node: slottedNode,
|
|
1895
|
+
hostId
|
|
1896
|
+
});
|
|
1897
|
+
}
|
|
1898
|
+
slottedNode = slottedNode?.nextSibling;
|
|
1899
|
+
} while (slottedNode && !slottedNode.nodeValue?.startsWith(SLOT_NODE_ID + "."));
|
|
1900
|
+
};
|
|
1901
|
+
/**
|
|
1902
|
+
* Steps through the node's siblings to find the next node of a specific type, with a value.
|
|
1903
|
+
* e.g. when we find a position comment `<!--t.1-->`, we need to find the next text node with a value.
|
|
1904
|
+
* (it's a guard against whitespace which is never accounted for in the SSR output)
|
|
1905
|
+
* @param node - the starting node
|
|
1906
|
+
* @param type - the type of node to find
|
|
1907
|
+
* @returns the first corresponding node of the type
|
|
1908
|
+
*/
|
|
1909
|
+
const findCorrespondingNode = (node, type) => {
|
|
1910
|
+
let sibling = node;
|
|
1911
|
+
do
|
|
1912
|
+
sibling = sibling.nextSibling;
|
|
1913
|
+
while (sibling && (sibling.nodeType !== type || !sibling.nodeValue));
|
|
1914
|
+
return sibling;
|
|
1915
|
+
};
|
|
1916
|
+
|
|
1917
|
+
//#endregion
|
|
1918
|
+
//#region src/utils/shadow-css.ts
|
|
1919
|
+
/**
|
|
1920
|
+
* @license
|
|
1921
|
+
* Copyright Google Inc. All Rights Reserved.
|
|
1922
|
+
*
|
|
1923
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
1924
|
+
* found in the LICENSE file at https://angular.io/license
|
|
1925
|
+
*
|
|
1926
|
+
* This file is a port of shadowCSS from `webcomponents.js` to TypeScript.
|
|
1927
|
+
* https://github.com/webcomponents/webcomponentsjs/blob/4efecd7e0e/src/ShadowCSS/ShadowCSS.js
|
|
1928
|
+
* https://github.com/angular/angular/blob/master/packages/compiler/src/shadow_css.ts
|
|
1929
|
+
*/
|
|
1930
|
+
const safeSelector = (selector) => {
|
|
1931
|
+
const placeholders = [];
|
|
1932
|
+
let index = 0;
|
|
1933
|
+
selector = selector.replace(/(\[\s*part~=\s*("[^"]*"|'[^']*')\s*\])/g, (_, keep) => {
|
|
1934
|
+
const replaceBy = `__part-${index}__`;
|
|
1935
|
+
placeholders.push(keep);
|
|
1936
|
+
index++;
|
|
1937
|
+
return replaceBy;
|
|
1938
|
+
});
|
|
1939
|
+
selector = selector.replace(/(\[[^\]]*\])/g, (_, keep) => {
|
|
1940
|
+
const replaceBy = `__ph-${index}__`;
|
|
1941
|
+
placeholders.push(keep);
|
|
1942
|
+
index++;
|
|
1943
|
+
return replaceBy;
|
|
1944
|
+
});
|
|
1945
|
+
return {
|
|
1946
|
+
content: selector.replace(/(:nth-[-\w]+)(\([^)]+\))/g, (_, pseudo, exp) => {
|
|
1947
|
+
const replaceBy = `__ph-${index}__`;
|
|
1948
|
+
placeholders.push(exp);
|
|
1949
|
+
index++;
|
|
1950
|
+
return pseudo + replaceBy;
|
|
1951
|
+
}),
|
|
1952
|
+
placeholders
|
|
1953
|
+
};
|
|
1954
|
+
};
|
|
1955
|
+
const restoreSafeSelector = (placeholders, content) => {
|
|
1956
|
+
content = content.replace(/__part-(\d+)__/g, (_, index) => placeholders[+index]);
|
|
1957
|
+
return content.replace(/__ph-(\d+)__/g, (_, index) => placeholders[+index]);
|
|
1958
|
+
};
|
|
1959
|
+
const _polyfillHost = "-shadowcsshost";
|
|
1960
|
+
const _polyfillSlotted = "-shadowcssslotted";
|
|
1961
|
+
const _polyfillHostContext = "-shadowcsscontext";
|
|
1962
|
+
const _parenSuffix = ")(?:\\(((?:\\([^)(]*\\)|[^)(]*)+?)\\))?([^,{]*)";
|
|
1963
|
+
const _cssColonHostRe = new RegExp("(" + _polyfillHost + _parenSuffix, "gim");
|
|
1964
|
+
const _cssColonHostContextRe = new RegExp("(" + _polyfillHostContext + _parenSuffix, "gim");
|
|
1965
|
+
const _cssColonSlottedRe = new RegExp("(" + _polyfillSlotted + _parenSuffix, "gim");
|
|
1966
|
+
const _polyfillHostNoCombinator = _polyfillHost + "-no-combinator";
|
|
1967
|
+
const _polyfillHostNoCombinatorRe = /-shadowcsshost-no-combinator([^\s]*)/;
|
|
1968
|
+
const _shadowDOMSelectorsRe = [/::shadow/g, /::content/g];
|
|
1969
|
+
const _safePartRe = /__part-(\d+)__/g;
|
|
1970
|
+
const _polyfillHostRe = /-shadowcsshost/gim;
|
|
1971
|
+
/**
|
|
1972
|
+
* Little helper for generating a regex that will match a specified
|
|
1973
|
+
* CSS selector when that selector is _not_ a part of a `@supports` rule.
|
|
1974
|
+
*
|
|
1975
|
+
* The pattern will match the provided `selector` (i.e. ':host', ':host-context', etc.)
|
|
1976
|
+
* when that selector is not a part of a `@supports` selector rule _or_ if the selector
|
|
1977
|
+
* is a part of the rule's declaration.
|
|
1978
|
+
*
|
|
1979
|
+
* For instance, if we create the regex with the selector ':host-context':
|
|
1980
|
+
* - '@supports selector(:host-context())' will return no matches (starts with '@supports')
|
|
1981
|
+
* - '@supports selector(:host-context()) { :host-context() { ... }}' will match the second ':host-context' (part of declaration)
|
|
1982
|
+
* - ':host-context() { ... }' will match ':host-context' (selector is not a '@supports' rule)
|
|
1983
|
+
* - ':host() { ... }' will return no matches (selector doesn't match selector used to create regex)
|
|
1984
|
+
*
|
|
1985
|
+
* @param selector The CSS selector we want to match for replacement
|
|
1986
|
+
* @returns A look-behind regex containing the selector
|
|
1987
|
+
*/
|
|
1988
|
+
const createSupportsRuleRe = (selector) => {
|
|
1989
|
+
const safeSelector = escapeRegExpSpecialCharacters(selector);
|
|
1990
|
+
return new RegExp(`(^|[^@]|@(?!supports\\s+selector\\s*\\([^{]*?${safeSelector}))(${safeSelector}\\b)`, "g");
|
|
1991
|
+
};
|
|
1992
|
+
const _commentRe = /\/\*\s*[\s\S]*?\*\//g;
|
|
1993
|
+
const stripComments = (input) => {
|
|
1994
|
+
return input.replace(_commentRe, "");
|
|
1995
|
+
};
|
|
1996
|
+
const _commentWithHashRe = /\/\*\s*#\s*source(Mapping)?URL=[\s\S]+?\*\//g;
|
|
1997
|
+
const extractCommentsWithHash = (input) => {
|
|
1998
|
+
return input.match(_commentWithHashRe) || [];
|
|
1999
|
+
};
|
|
2000
|
+
const _ruleRe = /(\s*)([^;\{\}]+?)(\s*)((?:{%BLOCK%}?\s*;?)|(?:\s*;))/g;
|
|
2001
|
+
const _curlyRe = /([{}])/g;
|
|
2002
|
+
const _selectorPartsRe = /(^.*?[^\\])??((:+)(.*)|$)/;
|
|
2003
|
+
const OPEN_CURLY = "{";
|
|
2004
|
+
const CLOSE_CURLY = "}";
|
|
2005
|
+
const BLOCK_PLACEHOLDER = "%BLOCK%";
|
|
2006
|
+
const processRules = (input, ruleCallback) => {
|
|
2007
|
+
const inputWithEscapedBlocks = escapeBlocks(input);
|
|
2008
|
+
let nextBlockIndex = 0;
|
|
2009
|
+
return inputWithEscapedBlocks.escapedString.replace(_ruleRe, (...m) => {
|
|
2010
|
+
const selector = m[2];
|
|
2011
|
+
let content = "";
|
|
2012
|
+
let suffix = m[4];
|
|
2013
|
+
let contentPrefix = "";
|
|
2014
|
+
if (suffix && suffix.startsWith("{" + BLOCK_PLACEHOLDER)) {
|
|
2015
|
+
content = inputWithEscapedBlocks.blocks[nextBlockIndex++];
|
|
2016
|
+
suffix = suffix.substring(8);
|
|
2017
|
+
contentPrefix = "{";
|
|
2018
|
+
}
|
|
2019
|
+
const rule = ruleCallback({
|
|
2020
|
+
selector,
|
|
2021
|
+
content
|
|
2022
|
+
});
|
|
2023
|
+
return `${m[1]}${rule.selector}${m[3]}${contentPrefix}${rule.content}${suffix}`;
|
|
2024
|
+
});
|
|
2025
|
+
};
|
|
2026
|
+
const escapeBlocks = (input) => {
|
|
2027
|
+
const inputParts = input.split(_curlyRe);
|
|
2028
|
+
const resultParts = [];
|
|
2029
|
+
const escapedBlocks = [];
|
|
2030
|
+
let bracketCount = 0;
|
|
2031
|
+
let currentBlockParts = [];
|
|
2032
|
+
for (let partIndex = 0; partIndex < inputParts.length; partIndex++) {
|
|
2033
|
+
const part = inputParts[partIndex];
|
|
2034
|
+
if (part === CLOSE_CURLY) bracketCount--;
|
|
2035
|
+
if (bracketCount > 0) currentBlockParts.push(part);
|
|
2036
|
+
else {
|
|
2037
|
+
if (currentBlockParts.length > 0) {
|
|
2038
|
+
escapedBlocks.push(currentBlockParts.join(""));
|
|
2039
|
+
resultParts.push(BLOCK_PLACEHOLDER);
|
|
2040
|
+
currentBlockParts = [];
|
|
2041
|
+
}
|
|
2042
|
+
resultParts.push(part);
|
|
2043
|
+
}
|
|
2044
|
+
if (part === OPEN_CURLY) bracketCount++;
|
|
2045
|
+
}
|
|
2046
|
+
if (currentBlockParts.length > 0) {
|
|
2047
|
+
escapedBlocks.push(currentBlockParts.join(""));
|
|
2048
|
+
resultParts.push(BLOCK_PLACEHOLDER);
|
|
2049
|
+
}
|
|
2050
|
+
return {
|
|
2051
|
+
escapedString: resultParts.join(""),
|
|
2052
|
+
blocks: escapedBlocks
|
|
2053
|
+
};
|
|
2054
|
+
};
|
|
2055
|
+
/**
|
|
2056
|
+
* Replaces certain strings within the CSS with placeholders
|
|
2057
|
+
* that will later be replaced with class selectors appropriate
|
|
2058
|
+
* for the level of encapsulation (shadow or scoped).
|
|
2059
|
+
*
|
|
2060
|
+
* When performing these replacements, we want to ignore selectors that are a
|
|
2061
|
+
* part of an `@supports` rule. Replacing these selectors will result in invalid
|
|
2062
|
+
* CSS that gets passed to autoprefixer/postcss once the placeholders are replaced.
|
|
2063
|
+
* For example, a rule like:
|
|
2064
|
+
*
|
|
2065
|
+
* ```css
|
|
2066
|
+
* @supports selector(:host()) {
|
|
2067
|
+
* :host {
|
|
2068
|
+
* color: red;
|
|
2069
|
+
* }
|
|
2070
|
+
* }
|
|
2071
|
+
* ```
|
|
2072
|
+
*
|
|
2073
|
+
* Should be converted to:
|
|
2074
|
+
*
|
|
2075
|
+
* ```css
|
|
2076
|
+
* @supports selector(:host()) {
|
|
2077
|
+
* -shadowcsshost {
|
|
2078
|
+
* color: red;
|
|
2079
|
+
* }
|
|
2080
|
+
* }
|
|
2081
|
+
* ```
|
|
2082
|
+
*
|
|
2083
|
+
* The order the regex replacements happen in matters since we match
|
|
2084
|
+
* against a whole selector word so we need to match all of `:host-context`
|
|
2085
|
+
* before we try to replace `:host`. Otherwise the pattern for `:host` would match
|
|
2086
|
+
* `:host-context` resulting in something like `:-shadowcsshost-context`.
|
|
2087
|
+
*
|
|
2088
|
+
* @param cssText A CSS string for a component
|
|
2089
|
+
* @returns The modified CSS string
|
|
2090
|
+
*/
|
|
2091
|
+
const insertPolyfillHostInCssText = (cssText) => {
|
|
2092
|
+
const supportsBlocks = [];
|
|
2093
|
+
cssText = cssText.replace(/@supports\s+selector\s*\(\s*([^)]*)\s*\)/g, (_, selectorContent) => {
|
|
2094
|
+
const placeholder = `__supports_${supportsBlocks.length}__`;
|
|
2095
|
+
supportsBlocks.push(selectorContent);
|
|
2096
|
+
return `@supports selector(${placeholder})`;
|
|
2097
|
+
});
|
|
2098
|
+
const _colonSlottedRe = createSupportsRuleRe("::slotted");
|
|
2099
|
+
const _colonHostRe = createSupportsRuleRe(":host");
|
|
2100
|
+
const _colonHostContextRe = createSupportsRuleRe(":host-context");
|
|
2101
|
+
cssText = cssText.replace(_colonHostContextRe, `$1${_polyfillHostContext}`).replace(_colonHostRe, `$1${_polyfillHost}`).replace(_colonSlottedRe, `$1${_polyfillSlotted}`);
|
|
2102
|
+
supportsBlocks.forEach((originalSelector, index) => {
|
|
2103
|
+
cssText = cssText.replace(`__supports_${index}__`, originalSelector);
|
|
2104
|
+
});
|
|
2105
|
+
return cssText;
|
|
2106
|
+
};
|
|
2107
|
+
const convertColonRule = (cssText, regExp, partReplacer) => {
|
|
2108
|
+
return cssText.replace(regExp, (...m) => {
|
|
2109
|
+
if (m[2]) {
|
|
2110
|
+
const parts = m[2].split(",");
|
|
2111
|
+
const r = [];
|
|
2112
|
+
for (let i = 0; i < parts.length; i++) {
|
|
2113
|
+
const p = parts[i].trim();
|
|
2114
|
+
if (!p) break;
|
|
2115
|
+
r.push(partReplacer(_polyfillHostNoCombinator, p, m[3]));
|
|
2116
|
+
}
|
|
2117
|
+
return r.join(",");
|
|
2118
|
+
} else return _polyfillHostNoCombinator + m[3];
|
|
2119
|
+
});
|
|
2120
|
+
};
|
|
2121
|
+
const colonHostPartReplacer = (host, part, suffix) => {
|
|
2122
|
+
return host + part.replace(_polyfillHost, "") + suffix;
|
|
2123
|
+
};
|
|
2124
|
+
const convertColonHost = (cssText) => {
|
|
2125
|
+
return convertColonRule(cssText, _cssColonHostRe, colonHostPartReplacer);
|
|
2126
|
+
};
|
|
2127
|
+
const colonHostContextPartReplacer = (host, part, suffix) => {
|
|
2128
|
+
if (part.indexOf(_polyfillHost) > -1) return colonHostPartReplacer(host, part, suffix);
|
|
2129
|
+
else return host + part + suffix + ", " + part + " " + host + suffix;
|
|
2130
|
+
};
|
|
2131
|
+
const convertColonSlotted = (cssText, slotScopeId) => {
|
|
2132
|
+
const slotClass = "." + slotScopeId + " > ";
|
|
2133
|
+
const selectors = [];
|
|
2134
|
+
cssText = cssText.replace(_cssColonSlottedRe, (...m) => {
|
|
2135
|
+
if (m[2]) {
|
|
2136
|
+
const compound = m[2].trim();
|
|
2137
|
+
const suffix = m[3];
|
|
2138
|
+
const slottedSelector = slotClass + compound + suffix;
|
|
2139
|
+
let prefixSelector = "";
|
|
2140
|
+
for (let i = m[4] - 1; i >= 0; i--) {
|
|
2141
|
+
const char = m[5][i];
|
|
2142
|
+
if (char === "}" || char === ",") break;
|
|
2143
|
+
prefixSelector = char + prefixSelector;
|
|
2144
|
+
}
|
|
2145
|
+
const orgSelector = (prefixSelector + slottedSelector).trim();
|
|
2146
|
+
const addedSelector = `${prefixSelector.trimEnd()}${slottedSelector.trim()}`.trim();
|
|
2147
|
+
if (orgSelector !== addedSelector) {
|
|
2148
|
+
const updatedSelector = `${addedSelector}, ${orgSelector}`;
|
|
2149
|
+
selectors.push({
|
|
2150
|
+
orgSelector,
|
|
2151
|
+
updatedSelector
|
|
2152
|
+
});
|
|
2153
|
+
}
|
|
2154
|
+
return slottedSelector;
|
|
2155
|
+
} else return _polyfillHostNoCombinator + m[3];
|
|
2156
|
+
});
|
|
2157
|
+
return {
|
|
2158
|
+
selectors,
|
|
2159
|
+
cssText
|
|
2160
|
+
};
|
|
2161
|
+
};
|
|
2162
|
+
const convertColonHostContext = (cssText) => {
|
|
2163
|
+
return convertColonRule(cssText, _cssColonHostContextRe, colonHostContextPartReplacer);
|
|
2164
|
+
};
|
|
2165
|
+
const convertShadowDOMSelectors = (cssText) => {
|
|
2166
|
+
return _shadowDOMSelectorsRe.reduce((result, pattern) => result.replace(pattern, " "), cssText);
|
|
2167
|
+
};
|
|
2168
|
+
const makeScopeMatcher = (scopeSelector) => {
|
|
2169
|
+
scopeSelector = scopeSelector.replace(/\[/g, "\\[").replace(/\]/g, "\\]");
|
|
2170
|
+
return new RegExp("^(" + scopeSelector + ")([>\\s~+[.,{:][\\s\\S]*)?$", "m");
|
|
2171
|
+
};
|
|
2172
|
+
const selectorNeedsScoping = (selector, scopeSelector) => {
|
|
2173
|
+
return !makeScopeMatcher(scopeSelector).test(selector);
|
|
2174
|
+
};
|
|
2175
|
+
const injectScopingSelector = (selector, scopingSelector) => {
|
|
2176
|
+
return selector.replace(_selectorPartsRe, (_, before = "", _colonGroup, colon = "", after = "") => {
|
|
2177
|
+
return before + scopingSelector + colon + after;
|
|
2178
|
+
});
|
|
2179
|
+
};
|
|
2180
|
+
const applySimpleSelectorScope = (selector, scopeSelector, hostSelector) => {
|
|
2181
|
+
_polyfillHostRe.lastIndex = 0;
|
|
2182
|
+
if (_polyfillHostRe.test(selector)) {
|
|
2183
|
+
const replaceBy = `.${hostSelector}`;
|
|
2184
|
+
return selector.replace(_polyfillHostNoCombinatorRe, (_, selector) => injectScopingSelector(selector, replaceBy)).replace(_polyfillHostRe, replaceBy + " ");
|
|
2185
|
+
}
|
|
2186
|
+
return scopeSelector + " " + selector;
|
|
2187
|
+
};
|
|
2188
|
+
const applyStrictSelectorScope = (selector, scopeSelector, hostSelector) => {
|
|
2189
|
+
scopeSelector = scopeSelector.replace(/\[is=([^\]]*)\]/g, (_, ...parts) => parts[0]);
|
|
2190
|
+
const className = "." + scopeSelector;
|
|
2191
|
+
const _scopeSelectorPart = (p) => {
|
|
2192
|
+
let scopedP = p.trim();
|
|
2193
|
+
if (!scopedP) return "";
|
|
2194
|
+
if (p.indexOf(_polyfillHostNoCombinator) > -1) scopedP = applySimpleSelectorScope(p, scopeSelector, hostSelector);
|
|
2195
|
+
else {
|
|
2196
|
+
const t = p.replace(_polyfillHostRe, "");
|
|
2197
|
+
if (t.length > 0) scopedP = injectScopingSelector(t, className);
|
|
2198
|
+
}
|
|
2199
|
+
return scopedP;
|
|
2200
|
+
};
|
|
2201
|
+
const safeContent = safeSelector(selector);
|
|
2202
|
+
selector = safeContent.content;
|
|
2203
|
+
let scopedSelector = "";
|
|
2204
|
+
let startIndex = 0;
|
|
2205
|
+
let res;
|
|
2206
|
+
const sep = /( |>|\+|~(?!=))(?=(?:[^()]*\([^()]*\))*[^()]*$)\s*/g;
|
|
2207
|
+
let shouldScope = !(selector.indexOf(_polyfillHostNoCombinator) > -1);
|
|
2208
|
+
while ((res = sep.exec(selector)) !== null) {
|
|
2209
|
+
const separator = res[1];
|
|
2210
|
+
const part = selector.slice(startIndex, res.index).trim();
|
|
2211
|
+
shouldScope = shouldScope || part.indexOf(_polyfillHostNoCombinator) > -1;
|
|
2212
|
+
const scopedPart = shouldScope ? _scopeSelectorPart(part) : part;
|
|
2213
|
+
scopedSelector += `${scopedPart} ${separator} `;
|
|
2214
|
+
startIndex = sep.lastIndex;
|
|
2215
|
+
}
|
|
2216
|
+
const part = selector.substring(startIndex);
|
|
2217
|
+
shouldScope = !part.match(_safePartRe) && (shouldScope || part.indexOf(_polyfillHostNoCombinator) > -1);
|
|
2218
|
+
scopedSelector += shouldScope ? _scopeSelectorPart(part) : part;
|
|
2219
|
+
return restoreSafeSelector(safeContent.placeholders, scopedSelector);
|
|
2220
|
+
};
|
|
2221
|
+
const scopeSelector = (selector, scopeSelectorText, hostSelector, slotSelector) => {
|
|
2222
|
+
return selector.split(",").map((shallowPart) => {
|
|
2223
|
+
if (slotSelector && shallowPart.indexOf("." + slotSelector) > -1) return shallowPart.trim();
|
|
2224
|
+
if (selectorNeedsScoping(shallowPart, scopeSelectorText)) return applyStrictSelectorScope(shallowPart, scopeSelectorText, hostSelector).trim();
|
|
2225
|
+
else return shallowPart.trim();
|
|
2226
|
+
}).join(", ");
|
|
2227
|
+
};
|
|
2228
|
+
const scopeSelectors = (cssText, scopeSelectorText, hostSelector, slotSelector, commentOriginalSelector) => {
|
|
2229
|
+
return processRules(cssText, (rule) => {
|
|
2230
|
+
let selector = rule.selector;
|
|
2231
|
+
let content = rule.content;
|
|
2232
|
+
if (rule.selector[0] !== "@") selector = scopeSelector(rule.selector, scopeSelectorText, hostSelector, slotSelector);
|
|
2233
|
+
else if (rule.selector.startsWith("@media") || rule.selector.startsWith("@supports") || rule.selector.startsWith("@page") || rule.selector.startsWith("@document")) content = scopeSelectors(rule.content, scopeSelectorText, hostSelector, slotSelector, commentOriginalSelector);
|
|
2234
|
+
return {
|
|
2235
|
+
selector: selector.replace(/\s{2,}/g, " ").trim(),
|
|
2236
|
+
content
|
|
2237
|
+
};
|
|
2238
|
+
});
|
|
2239
|
+
};
|
|
2240
|
+
const scopeCssText = (cssText, scopeId, hostScopeId, slotScopeId, commentOriginalSelector) => {
|
|
2241
|
+
cssText = insertPolyfillHostInCssText(cssText);
|
|
2242
|
+
cssText = convertColonHost(cssText);
|
|
2243
|
+
cssText = convertColonHostContext(cssText);
|
|
2244
|
+
const slotted = convertColonSlotted(cssText, slotScopeId);
|
|
2245
|
+
cssText = slotted.cssText;
|
|
2246
|
+
cssText = convertShadowDOMSelectors(cssText);
|
|
2247
|
+
if (scopeId) cssText = scopeSelectors(cssText, scopeId, hostScopeId, slotScopeId, commentOriginalSelector);
|
|
2248
|
+
cssText = replaceShadowCssHost(cssText, hostScopeId);
|
|
2249
|
+
cssText = cssText.replace(/>\s*\*\s+([^{, ]+)/gm, " $1 ");
|
|
2250
|
+
return {
|
|
2251
|
+
cssText: cssText.trim(),
|
|
2252
|
+
slottedSelectors: slotted.selectors.map((ref) => ({
|
|
2253
|
+
orgSelector: replaceShadowCssHost(ref.orgSelector, hostScopeId),
|
|
2254
|
+
updatedSelector: replaceShadowCssHost(ref.updatedSelector, hostScopeId)
|
|
2255
|
+
}))
|
|
2256
|
+
};
|
|
2257
|
+
};
|
|
2258
|
+
/**
|
|
2259
|
+
* Helper function that replaces the interim string representing a `:host` selector with
|
|
2260
|
+
* the host scope selector class for the element.
|
|
2261
|
+
*
|
|
2262
|
+
* @param cssText The CSS string to make the replacement in
|
|
2263
|
+
* @param hostScopeId The scope ID that will be used as the class representing the host element
|
|
2264
|
+
* @returns CSS with the selector replaced
|
|
2265
|
+
*/
|
|
2266
|
+
const replaceShadowCssHost = (cssText, hostScopeId) => {
|
|
2267
|
+
return cssText.replace(/-shadowcsshost-no-combinator/g, `.${hostScopeId}`);
|
|
2268
|
+
};
|
|
2269
|
+
/**
|
|
2270
|
+
* Expands selectors with ::part(...) to also include [part~="..."] selectors.
|
|
2271
|
+
* For example:
|
|
2272
|
+
* ```css
|
|
2273
|
+
* selectors-like-this::part(demo) { ... }
|
|
2274
|
+
* .something .selectors::part(demo demo2):hover { ... }
|
|
2275
|
+
* ```
|
|
2276
|
+
* Becomes:
|
|
2277
|
+
* ```
|
|
2278
|
+
* selectors-like-this::part(demo), selectors-like-this [part~="demo"] { ... }
|
|
2279
|
+
* .something .selectors::part(demo demo2):hover, .something .selectors [part~="demo"][part~="demo2"]:hover { ... }
|
|
2280
|
+
* ```
|
|
2281
|
+
*
|
|
2282
|
+
* @param cssText The CSS text to process
|
|
2283
|
+
* @returns The CSS text with expanded ::part(...) selectors
|
|
2284
|
+
*/
|
|
2285
|
+
const expandPartSelectors = (cssText) => {
|
|
2286
|
+
const partSelectorRe = /([^\s,{][^,{]*?)::part\(\s*([^)]+?)\s*\)((?:[:.][^,{]*)*)/g;
|
|
2287
|
+
return processRules(cssText, (rule) => {
|
|
2288
|
+
if (rule.selector[0] === "@") return rule;
|
|
2289
|
+
rule.selector = rule.selector.split(",").map((sel) => {
|
|
2290
|
+
const out = [sel.trim()];
|
|
2291
|
+
let m;
|
|
2292
|
+
while ((m = partSelectorRe.exec(sel)) !== null) {
|
|
2293
|
+
const before = m[1].trimEnd();
|
|
2294
|
+
const partNames = m[2].trim().split(/\s+/);
|
|
2295
|
+
const after = m[3] || "";
|
|
2296
|
+
const partAttr = partNames.flatMap((p) => {
|
|
2297
|
+
if (!rule.selector.includes(`[part~="${p}"]`)) return [`[part~="${p}"]`];
|
|
2298
|
+
return [];
|
|
2299
|
+
}).join("");
|
|
2300
|
+
const expanded = `${before} ${partAttr}${after}`;
|
|
2301
|
+
if (!!partAttr && expanded !== sel.trim()) out.push(expanded);
|
|
2302
|
+
}
|
|
2303
|
+
return out.join(", ");
|
|
2304
|
+
}).join(", ");
|
|
2305
|
+
return rule;
|
|
2306
|
+
});
|
|
2307
|
+
};
|
|
2308
|
+
const scopeCss = (cssText, scopeId, commentOriginalSelector) => {
|
|
2309
|
+
const hostScopeId = scopeId + "-h";
|
|
2310
|
+
const slotScopeId = scopeId + "-s";
|
|
2311
|
+
const commentsWithHash = extractCommentsWithHash(cssText);
|
|
2312
|
+
cssText = stripComments(cssText);
|
|
2313
|
+
const orgSelectors = [];
|
|
2314
|
+
if (commentOriginalSelector) {
|
|
2315
|
+
const processCommentedSelector = (rule) => {
|
|
2316
|
+
const placeholder = `/*!@___${orgSelectors.length}___*/`;
|
|
2317
|
+
const comment = `/*!@${rule.selector}*/`;
|
|
2318
|
+
orgSelectors.push({
|
|
2319
|
+
placeholder,
|
|
2320
|
+
comment
|
|
2321
|
+
});
|
|
2322
|
+
rule.selector = placeholder + rule.selector;
|
|
2323
|
+
return rule;
|
|
2324
|
+
};
|
|
2325
|
+
cssText = processRules(cssText, (rule) => {
|
|
2326
|
+
if (rule.selector[0] !== "@") return processCommentedSelector(rule);
|
|
2327
|
+
else if (rule.selector.startsWith("@media") || rule.selector.startsWith("@supports") || rule.selector.startsWith("@page") || rule.selector.startsWith("@document")) {
|
|
2328
|
+
rule.content = processRules(rule.content, processCommentedSelector);
|
|
2329
|
+
return rule;
|
|
2330
|
+
}
|
|
2331
|
+
return rule;
|
|
2332
|
+
});
|
|
2333
|
+
}
|
|
2334
|
+
const scoped = scopeCssText(cssText, scopeId, hostScopeId, slotScopeId, commentOriginalSelector);
|
|
2335
|
+
cssText = [scoped.cssText, ...commentsWithHash].join("\n");
|
|
2336
|
+
if (commentOriginalSelector) orgSelectors.forEach(({ placeholder, comment }) => {
|
|
2337
|
+
cssText = cssText.replace(placeholder, comment);
|
|
2338
|
+
});
|
|
2339
|
+
scoped.slottedSelectors.forEach((slottedSelector) => {
|
|
2340
|
+
const regex = new RegExp(escapeRegExpSpecialCharacters(slottedSelector.orgSelector) + "(?=\\s*[,{]|$)", "g");
|
|
2341
|
+
cssText = cssText.replace(regex, slottedSelector.updatedSelector);
|
|
2342
|
+
});
|
|
2343
|
+
cssText = expandPartSelectors(cssText);
|
|
2344
|
+
return cssText;
|
|
2345
|
+
};
|
|
2346
|
+
|
|
2347
|
+
//#endregion
|
|
2348
|
+
//#region src/runtime/mode.ts
|
|
2349
|
+
const computeMode = (elm) => modeResolutionChain.map((h) => h(elm)).find((m) => !!m);
|
|
2350
|
+
const setMode = (handler) => modeResolutionChain.push(handler);
|
|
2351
|
+
const getMode = (ref) => getHostRef(ref)?.$modeName$;
|
|
2352
|
+
|
|
2353
|
+
//#endregion
|
|
2354
|
+
//#region src/runtime/parse-property-value.ts
|
|
2355
|
+
/**
|
|
2356
|
+
* Parse a new property value for a given property type.
|
|
2357
|
+
*
|
|
2358
|
+
* While the prop value can reasonably be expected to be of `any` type as far as TypeScript's type checker is concerned,
|
|
2359
|
+
* it is not safe to assume that the string returned by evaluating `typeof propValue` matches:
|
|
2360
|
+
* 1. `any`, the type given to `propValue` in the function signature
|
|
2361
|
+
* 2. the type stored from `propType`.
|
|
2362
|
+
*
|
|
2363
|
+
* This function provides the capability to parse/coerce a property's value to potentially any other JavaScript type.
|
|
2364
|
+
*
|
|
2365
|
+
* Property values represented in TSX preserve their type information. In the example below, the number 0 is passed to
|
|
2366
|
+
* a component. This `propValue` will preserve its type information (`typeof propValue === 'number'`). Note that is
|
|
2367
|
+
* based on the type of the value being passed in, not the type declared of the class member decorated with `@Prop`.
|
|
2368
|
+
* ```tsx
|
|
2369
|
+
* <my-cmp prop-val={0}></my-cmp>
|
|
2370
|
+
* ```
|
|
2371
|
+
*
|
|
2372
|
+
* HTML prop values on the other hand, will always a string
|
|
2373
|
+
*
|
|
2374
|
+
* @param propValue the new value to coerce to some type
|
|
2375
|
+
* @param propType the type of the prop, expressed as a binary number
|
|
2376
|
+
* @param isFormAssociated whether the component is form-associated (optional)
|
|
2377
|
+
* @returns the parsed/coerced value
|
|
2378
|
+
*/
|
|
2379
|
+
const parsePropertyValue = (propValue, propType, isFormAssociated) => {
|
|
2380
|
+
/**
|
|
2381
|
+
* Allow hydrate parameters that contain a complex non-serialized values.
|
|
2382
|
+
* This is SSR-specific and should only run during hydration.
|
|
2383
|
+
*/
|
|
2384
|
+
if ((BUILD.hydrateClientSide || BUILD.hydrateServerSide) && typeof propValue === "string" && propValue.startsWith(SERIALIZED_PREFIX)) {
|
|
2385
|
+
propValue = deserializeProperty(propValue);
|
|
2386
|
+
return propValue;
|
|
2387
|
+
}
|
|
2388
|
+
if (propValue != null && !isComplexType(propValue)) {
|
|
2389
|
+
/**
|
|
2390
|
+
* ensure this value is of the correct prop type
|
|
2391
|
+
*/
|
|
2392
|
+
if (BUILD.propBoolean && propType & MEMBER_FLAGS.Boolean)
|
|
2393
|
+
/**
|
|
2394
|
+
* For form-associated components, according to HTML spec, the presence of any boolean attribute
|
|
2395
|
+
* (regardless of its value, even "false") should make the property true.
|
|
2396
|
+
* For non-form-associated components, we maintain the legacy behavior where "false" becomes false.
|
|
2397
|
+
*/
|
|
2398
|
+
if (BUILD.formAssociated && isFormAssociated && typeof propValue === "string") return propValue === "" || !!propValue;
|
|
2399
|
+
else return propValue === "false" ? false : propValue === "" || !!propValue;
|
|
2400
|
+
/**
|
|
2401
|
+
* force it to be a number
|
|
2402
|
+
*/
|
|
2403
|
+
if (BUILD.propNumber && propType & MEMBER_FLAGS.Number) return typeof propValue === "string" ? parseFloat(propValue) : typeof propValue === "number" ? propValue : NaN;
|
|
2404
|
+
/**
|
|
2405
|
+
* could have been passed as a number or boolean but we still want it as a string
|
|
2406
|
+
*/
|
|
2407
|
+
if (BUILD.propString && propType & MEMBER_FLAGS.String) return String(propValue);
|
|
2408
|
+
return propValue;
|
|
2409
|
+
}
|
|
2410
|
+
/**
|
|
2411
|
+
* not sure exactly what type we want so no need to change to a different type
|
|
2412
|
+
*/
|
|
2413
|
+
return propValue;
|
|
2414
|
+
};
|
|
2415
|
+
|
|
2416
|
+
//#endregion
|
|
2417
|
+
//#region src/runtime/element.ts
|
|
2418
|
+
const getElement = (ref) => BUILD.lazyLoad ? getHostRef(ref)?.$hostElement$ : ref;
|
|
2419
|
+
|
|
2420
|
+
//#endregion
|
|
2421
|
+
//#region src/runtime/event-emitter.ts
|
|
2422
|
+
const createEvent = (ref, name, flags) => {
|
|
2423
|
+
const elm = getElement(ref);
|
|
2424
|
+
return { emit: (detail) => {
|
|
2425
|
+
if (BUILD.isDev && !elm.isConnected) consoleDevWarn(`The "${name}" event was emitted, but the dispatcher node is no longer connected to the dom.`);
|
|
2426
|
+
return emitEvent(elm, name, {
|
|
2427
|
+
bubbles: !!(flags & EVENT_FLAGS.Bubbles),
|
|
2428
|
+
composed: !!(flags & EVENT_FLAGS.Composed),
|
|
2429
|
+
cancelable: !!(flags & EVENT_FLAGS.Cancellable),
|
|
2430
|
+
detail
|
|
2431
|
+
});
|
|
2432
|
+
} };
|
|
2433
|
+
};
|
|
2434
|
+
/**
|
|
2435
|
+
* Helper function to create & dispatch a custom Event on a provided target
|
|
2436
|
+
* @param elm the target of the Event
|
|
2437
|
+
* @param name the name to give the custom Event
|
|
2438
|
+
* @param opts options for configuring a custom Event
|
|
2439
|
+
* @returns the custom Event
|
|
2440
|
+
*/
|
|
2441
|
+
const emitEvent = (elm, name, opts) => {
|
|
2442
|
+
const ev = plt.ce(name, opts);
|
|
2443
|
+
elm.dispatchEvent(ev);
|
|
2444
|
+
return ev;
|
|
2445
|
+
};
|
|
2446
|
+
|
|
2447
|
+
//#endregion
|
|
2448
|
+
//#region src/runtime/vdom/set-accessor.ts
|
|
2449
|
+
/**
|
|
2450
|
+
* Production setAccessor() function based on Preact by
|
|
2451
|
+
* Jason Miller (@developit)
|
|
2452
|
+
* Licensed under the MIT License
|
|
2453
|
+
* https://github.com/developit/preact/blob/master/LICENSE
|
|
2454
|
+
*
|
|
2455
|
+
* Modified for Stencil's compiler and vdom
|
|
2456
|
+
*/
|
|
2457
|
+
/**
|
|
2458
|
+
* When running a VDom render set properties present on a VDom node onto the
|
|
2459
|
+
* corresponding HTML element.
|
|
2460
|
+
*
|
|
2461
|
+
* Note that this function has special functionality for the `class`,
|
|
2462
|
+
* `style`, `key`, and `ref` attributes, as well as event handlers (like
|
|
2463
|
+
* `onClick`, etc). All others are just passed through as-is.
|
|
2464
|
+
*
|
|
2465
|
+
* @param elm the HTMLElement onto which attributes should be set
|
|
2466
|
+
* @param memberName the name of the attribute to set
|
|
2467
|
+
* @param oldValue the old value for the attribute
|
|
2468
|
+
* @param newValue the new value for the attribute
|
|
2469
|
+
* @param isSvg whether we're in an svg context or not
|
|
2470
|
+
* @param flags bitflags for Vdom variables
|
|
2471
|
+
* @param initialRender whether this is the first render of the VDom
|
|
2472
|
+
*/
|
|
2473
|
+
const setAccessor = (elm, memberName, oldValue, newValue, isSvg, flags, initialRender) => {
|
|
2474
|
+
if (oldValue === newValue) return;
|
|
2475
|
+
let isProp = isMemberInElement(elm, memberName);
|
|
2476
|
+
let ln = memberName.toLowerCase();
|
|
2477
|
+
if (BUILD.vdomClass && memberName === "class") {
|
|
2478
|
+
const classList = elm.classList;
|
|
2479
|
+
const oldClasses = parseClassList(oldValue);
|
|
2480
|
+
let newClasses = parseClassList(newValue);
|
|
2481
|
+
if (BUILD.hydrateClientSide && (elm["s-si"] || elm["s-sc"]) && initialRender) {
|
|
2482
|
+
const scopeId = elm["s-sc"] || elm["s-si"];
|
|
2483
|
+
newClasses.push(scopeId);
|
|
2484
|
+
oldClasses.forEach((c) => {
|
|
2485
|
+
if (c.startsWith(scopeId)) newClasses.push(c);
|
|
2486
|
+
});
|
|
2487
|
+
newClasses = [...new Set(newClasses)].filter((c) => c);
|
|
2488
|
+
classList.add(...newClasses);
|
|
2489
|
+
} else {
|
|
2490
|
+
classList.remove(...oldClasses.filter((c) => c && !newClasses.includes(c)));
|
|
2491
|
+
classList.add(...newClasses.filter((c) => c && !oldClasses.includes(c)));
|
|
2492
|
+
}
|
|
2493
|
+
} else if (BUILD.vdomStyle && memberName === "style") {
|
|
2494
|
+
if (BUILD.updatable) {
|
|
2495
|
+
for (const prop in oldValue) if (!newValue || newValue[prop] == null) if (!BUILD.hydrateServerSide && prop.includes("-")) elm.style.removeProperty(prop);
|
|
2496
|
+
else elm.style[prop] = "";
|
|
2497
|
+
}
|
|
2498
|
+
for (const prop in newValue) if (!oldValue || newValue[prop] !== oldValue[prop]) if (!BUILD.hydrateServerSide && prop.includes("-")) elm.style.setProperty(prop, newValue[prop]);
|
|
2499
|
+
else elm.style[prop] = newValue[prop];
|
|
2500
|
+
} else if (BUILD.vdomKey && memberName === "key") {} else if (BUILD.vdomRef && memberName === "ref") {
|
|
2501
|
+
if (newValue) queueRefAttachment(newValue, elm);
|
|
2502
|
+
} else if (BUILD.vdomListener && (BUILD.lazyLoad ? !isProp : !elm.__lookupSetter__(memberName)) && memberName[0] === "o" && memberName[1] === "n") {
|
|
2503
|
+
if (memberName[2] === "-") memberName = memberName.slice(3);
|
|
2504
|
+
else if (isMemberInElement(win, ln)) memberName = ln.slice(2);
|
|
2505
|
+
else memberName = ln[2] + memberName.slice(3);
|
|
2506
|
+
if (oldValue || newValue) {
|
|
2507
|
+
const capture = memberName.endsWith(CAPTURE_EVENT_SUFFIX);
|
|
2508
|
+
memberName = memberName.replace(CAPTURE_EVENT_REGEX, "");
|
|
2509
|
+
if (oldValue) plt.rel(elm, memberName, oldValue, capture);
|
|
2510
|
+
if (newValue) plt.ael(elm, memberName, newValue, capture);
|
|
2511
|
+
}
|
|
2512
|
+
} else if (BUILD.vdomPropOrAttr && memberName[0] === "a" && memberName.startsWith("attr:")) {
|
|
2513
|
+
const propName = memberName.slice(5);
|
|
2514
|
+
let attrName;
|
|
2515
|
+
if (BUILD.member) {
|
|
2516
|
+
const hostRef = getHostRef(elm);
|
|
2517
|
+
if (hostRef && hostRef.$cmpMeta$ && hostRef.$cmpMeta$.$members$) {
|
|
2518
|
+
const memberMeta = hostRef.$cmpMeta$.$members$[propName];
|
|
2519
|
+
if (memberMeta && memberMeta[1]) attrName = memberMeta[1];
|
|
2520
|
+
}
|
|
2521
|
+
}
|
|
2522
|
+
if (!attrName) attrName = propName.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
|
|
2523
|
+
if (newValue == null || newValue === false) {
|
|
2524
|
+
if (newValue !== false || elm.getAttribute(attrName) === "") elm.removeAttribute(attrName);
|
|
2525
|
+
} else elm.setAttribute(attrName, newValue === true ? "" : newValue);
|
|
2526
|
+
return;
|
|
2527
|
+
} else if (BUILD.vdomPropOrAttr && memberName[0] === "p" && memberName.startsWith("prop:")) {
|
|
2528
|
+
const propName = memberName.slice(5);
|
|
2529
|
+
try {
|
|
2530
|
+
elm[propName] = newValue;
|
|
2531
|
+
} catch (e) {}
|
|
2532
|
+
return;
|
|
2533
|
+
} else if (BUILD.vdomPropOrAttr) {
|
|
2534
|
+
const isComplex = isComplexType(newValue);
|
|
2535
|
+
if ((isProp || isComplex && newValue !== null) && !isSvg) try {
|
|
2536
|
+
if (!elm.tagName.includes("-")) {
|
|
2537
|
+
const n = newValue == null ? "" : newValue;
|
|
2538
|
+
if (memberName === "list") isProp = false;
|
|
2539
|
+
else if (oldValue == null || elm[memberName] !== n) if (typeof elm.__lookupSetter__(memberName) === "function") elm[memberName] = n;
|
|
2540
|
+
else elm.setAttribute(memberName, n);
|
|
2541
|
+
} else if (elm[memberName] !== newValue) elm[memberName] = newValue;
|
|
2542
|
+
} catch (e) {}
|
|
2543
|
+
/**
|
|
2544
|
+
* Need to manually update attribute if:
|
|
2545
|
+
* - memberName is not an attribute
|
|
2546
|
+
* - if we are rendering the host element in order to reflect attribute
|
|
2547
|
+
* - if it's a SVG, since properties might not work in <svg>
|
|
2548
|
+
* - if the newValue is null/undefined or 'false'.
|
|
2549
|
+
*/
|
|
2550
|
+
let xlink = false;
|
|
2551
|
+
if (BUILD.vdomXlink) {
|
|
2552
|
+
if (ln !== (ln = ln.replace(/^xlink\:?/, ""))) {
|
|
2553
|
+
memberName = ln;
|
|
2554
|
+
xlink = true;
|
|
2555
|
+
}
|
|
2556
|
+
}
|
|
2557
|
+
if (newValue == null || newValue === false) {
|
|
2558
|
+
if (newValue !== false || elm.getAttribute(memberName) === "") if (BUILD.vdomXlink && xlink) elm.removeAttributeNS(XLINK_NS, memberName);
|
|
2559
|
+
else elm.removeAttribute(memberName);
|
|
2560
|
+
} else if ((!isProp || flags & VNODE_FLAGS.isHost || isSvg) && !isComplex && elm.nodeType === NODE_TYPE.ElementNode) {
|
|
2561
|
+
newValue = newValue === true ? "" : newValue;
|
|
2562
|
+
if (BUILD.vdomXlink && xlink) elm.setAttributeNS(XLINK_NS, memberName, newValue);
|
|
2563
|
+
else elm.setAttribute(memberName, newValue);
|
|
2564
|
+
}
|
|
2565
|
+
}
|
|
2566
|
+
};
|
|
2567
|
+
const parseClassListRegex = /\s/;
|
|
2568
|
+
/**
|
|
2569
|
+
* Parsed a string of classnames into an array
|
|
2570
|
+
* @param value className string, e.g. "foo bar baz"
|
|
2571
|
+
* @returns list of classes, e.g. ["foo", "bar", "baz"]
|
|
2572
|
+
*/
|
|
2573
|
+
const parseClassList = (value) => {
|
|
2574
|
+
if (typeof value === "object" && value && "baseVal" in value) value = value.baseVal;
|
|
2575
|
+
if (!value || typeof value !== "string") return [];
|
|
2576
|
+
return value.split(parseClassListRegex);
|
|
2577
|
+
};
|
|
2578
|
+
const CAPTURE_EVENT_SUFFIX = "Capture";
|
|
2579
|
+
const CAPTURE_EVENT_REGEX = new RegExp(CAPTURE_EVENT_SUFFIX + "$");
|
|
2580
|
+
|
|
2581
|
+
//#endregion
|
|
2582
|
+
//#region src/runtime/vdom/update-element.ts
|
|
2583
|
+
/**
|
|
2584
|
+
* Handle updating attributes on the component element based on the current
|
|
2585
|
+
* values present in the virtual DOM.
|
|
2586
|
+
*
|
|
2587
|
+
* If the component of interest uses shadow DOM these are added to the shadow
|
|
2588
|
+
* root's host element.
|
|
2589
|
+
*
|
|
2590
|
+
* @param oldVnode an old virtual DOM node or null
|
|
2591
|
+
* @param newVnode a new virtual DOM node
|
|
2592
|
+
* @param isSvgMode whether or not we're in an SVG context
|
|
2593
|
+
* @param isInitialRender whether this is the first render of the VDOM
|
|
2594
|
+
*/
|
|
2595
|
+
const updateElement = (oldVnode, newVnode, isSvgMode, isInitialRender) => {
|
|
2596
|
+
const elm = newVnode.$elm$.nodeType === NODE_TYPE.DocumentFragment && newVnode.$elm$.host ? newVnode.$elm$.host : newVnode.$elm$;
|
|
2597
|
+
const oldVnodeAttrs = oldVnode && oldVnode.$attrs$ || {};
|
|
2598
|
+
const newVnodeAttrs = newVnode.$attrs$ || {};
|
|
2599
|
+
if (BUILD.updatable) {
|
|
2600
|
+
for (const memberName of sortedAttrNames(Object.keys(oldVnodeAttrs))) if (!(memberName in newVnodeAttrs)) setAccessor(elm, memberName, oldVnodeAttrs[memberName], void 0, isSvgMode, newVnode.$flags$, isInitialRender);
|
|
2601
|
+
}
|
|
2602
|
+
for (const memberName of sortedAttrNames(Object.keys(newVnodeAttrs))) setAccessor(elm, memberName, oldVnodeAttrs[memberName], newVnodeAttrs[memberName], isSvgMode, newVnode.$flags$, isInitialRender);
|
|
2603
|
+
};
|
|
2604
|
+
/**
|
|
2605
|
+
* Sort a list of attribute names to ensure that all the attribute names which
|
|
2606
|
+
* are _not_ `"ref"` come before `"ref"`. Preserve the order of the non-ref
|
|
2607
|
+
* attributes.
|
|
2608
|
+
*
|
|
2609
|
+
* **Note**: if the supplied attributes do not include `'ref'` then the same
|
|
2610
|
+
* (by reference) array will be returned without modification.
|
|
2611
|
+
*
|
|
2612
|
+
* @param attrNames attribute names to sort
|
|
2613
|
+
* @returns a list of attribute names, sorted if they include `"ref"`
|
|
2614
|
+
*/
|
|
2615
|
+
function sortedAttrNames(attrNames) {
|
|
2616
|
+
return attrNames.includes("ref") ? [...attrNames.filter((attr) => attr !== "ref"), "ref"] : attrNames;
|
|
2617
|
+
}
|
|
2618
|
+
|
|
2619
|
+
//#endregion
|
|
2620
|
+
//#region src/runtime/vdom/vdom-render.ts
|
|
2621
|
+
/**
|
|
2622
|
+
* Virtual DOM patching algorithm based on Snabbdom by
|
|
2623
|
+
* Simon Friis Vindum (@paldepind)
|
|
2624
|
+
* Licensed under the MIT License
|
|
2625
|
+
* https://github.com/snabbdom/snabbdom/blob/master/LICENSE
|
|
2626
|
+
*
|
|
2627
|
+
* Modified for Stencil's renderer and slot projection
|
|
2628
|
+
*/
|
|
2629
|
+
let scopeId;
|
|
2630
|
+
let contentRef;
|
|
2631
|
+
let hostTagName;
|
|
2632
|
+
let useNativeShadowDom = false;
|
|
2633
|
+
let checkSlotFallbackVisibility = false;
|
|
2634
|
+
let checkSlotRelocate = false;
|
|
2635
|
+
let isSvgMode = false;
|
|
2636
|
+
/**
|
|
2637
|
+
* Queues for ref callbacks that need to be called during rendering.
|
|
2638
|
+
* These ensure that ref callbacks are called in the correct order:
|
|
2639
|
+
* first all removal callbacks (with null), then all attachment callbacks (with elements).
|
|
2640
|
+
*/
|
|
2641
|
+
let refCallbacksToRemove = [];
|
|
2642
|
+
let refCallbacksToAttach = [];
|
|
2643
|
+
/**
|
|
2644
|
+
* Create a DOM Node corresponding to one of the children of a given VNode.
|
|
2645
|
+
*
|
|
2646
|
+
* @param oldParentVNode the parent VNode from the previous render
|
|
2647
|
+
* @param newParentVNode the parent VNode from the current render
|
|
2648
|
+
* @param childIndex the index of the VNode, in the _new_ parent node's
|
|
2649
|
+
* children, for which we will create a new DOM node
|
|
2650
|
+
* @returns the newly created node
|
|
2651
|
+
*/
|
|
2652
|
+
const createElm = (oldParentVNode, newParentVNode, childIndex) => {
|
|
2653
|
+
const newVNode = newParentVNode.$children$[childIndex];
|
|
2654
|
+
let i = 0;
|
|
2655
|
+
let elm;
|
|
2656
|
+
let childNode;
|
|
2657
|
+
let oldVNode;
|
|
2658
|
+
if (BUILD.slotRelocation && !useNativeShadowDom) {
|
|
2659
|
+
checkSlotRelocate = true;
|
|
2660
|
+
if (newVNode.$tag$ === "slot") newVNode.$flags$ |= newVNode.$children$ ? VNODE_FLAGS.isSlotFallback : VNODE_FLAGS.isSlotReference;
|
|
2661
|
+
}
|
|
2662
|
+
if (BUILD.isDev && newVNode.$elm$) consoleDevError(`The JSX ${newVNode.$text$ !== null ? `"${newVNode.$text$}" text` : `"${newVNode.$tag$}" element`} node should not be shared within the same renderer. The renderer caches element lookups in order to improve performance. However, a side effect from this is that the exact same JSX node should not be reused. For more information please see https://stenciljs.com/docs/templating-jsx#avoid-shared-jsx-nodes`);
|
|
2663
|
+
if (BUILD.vdomText && newVNode.$text$ != null) elm = newVNode.$elm$ = win.document.createTextNode(newVNode.$text$);
|
|
2664
|
+
else if (BUILD.slotRelocation && newVNode.$flags$ & VNODE_FLAGS.isSlotReference) {
|
|
2665
|
+
elm = newVNode.$elm$ = BUILD.isDebug || BUILD.hydrateServerSide ? slotReferenceDebugNode(newVNode) : win.document.createTextNode("");
|
|
2666
|
+
if (BUILD.vdomAttribute) updateElement(null, newVNode, isSvgMode);
|
|
2667
|
+
} else {
|
|
2668
|
+
if (BUILD.svg && !isSvgMode) isSvgMode = newVNode.$tag$ === "svg";
|
|
2669
|
+
if (!win.document) throw new Error("You are trying to render a Stencil component in an environment that doesn't support the DOM.");
|
|
2670
|
+
elm = newVNode.$elm$ = BUILD.svg ? win.document.createElementNS(isSvgMode ? SVG_NS : HTML_NS, !useNativeShadowDom && BUILD.slotRelocation && newVNode.$flags$ & VNODE_FLAGS.isSlotFallback ? "slot-fb" : newVNode.$tag$) : win.document.createElement(!useNativeShadowDom && BUILD.slotRelocation && newVNode.$flags$ & VNODE_FLAGS.isSlotFallback ? "slot-fb" : newVNode.$tag$);
|
|
2671
|
+
if (BUILD.svg && isSvgMode && newVNode.$tag$ === "foreignObject") isSvgMode = false;
|
|
2672
|
+
if (BUILD.vdomAttribute) updateElement(null, newVNode, isSvgMode);
|
|
2673
|
+
if ((BUILD.scoped || BUILD.hydrateServerSide && CMP_FLAGS.shadowNeedsScopedCss) && isDef(scopeId) && elm["s-si"] !== scopeId) elm.classList.add(elm["s-si"] = scopeId);
|
|
2674
|
+
if (newVNode.$children$) {
|
|
2675
|
+
const appendTarget = newVNode.$tag$ === "template" ? elm.content : elm;
|
|
2676
|
+
for (i = 0; i < newVNode.$children$.length; ++i) {
|
|
2677
|
+
childNode = createElm(oldParentVNode, newVNode, i);
|
|
2678
|
+
if (childNode) appendTarget.appendChild(childNode);
|
|
2679
|
+
}
|
|
2680
|
+
}
|
|
2681
|
+
if (BUILD.svg) {
|
|
2682
|
+
if (newVNode.$tag$ === "svg") isSvgMode = false;
|
|
2683
|
+
else if (elm.tagName === "foreignObject") isSvgMode = true;
|
|
2684
|
+
}
|
|
2685
|
+
}
|
|
2686
|
+
elm["s-hn"] = hostTagName;
|
|
2687
|
+
if (BUILD.slotRelocation) {
|
|
2688
|
+
if (newVNode.$flags$ & (VNODE_FLAGS.isSlotFallback | VNODE_FLAGS.isSlotReference)) {
|
|
2689
|
+
elm["s-sr"] = true;
|
|
2690
|
+
elm["s-cr"] = contentRef;
|
|
2691
|
+
elm["s-sn"] = newVNode.$name$ || "";
|
|
2692
|
+
elm["s-rf"] = newVNode.$attrs$?.ref;
|
|
2693
|
+
patchSlotNode(elm);
|
|
2694
|
+
oldVNode = oldParentVNode && oldParentVNode.$children$ && oldParentVNode.$children$[childIndex];
|
|
2695
|
+
if (oldVNode && oldVNode.$tag$ === newVNode.$tag$ && oldParentVNode.$elm$) relocateToHostRoot(oldParentVNode.$elm$);
|
|
2696
|
+
if (BUILD.scoped || BUILD.hydrateServerSide && CMP_FLAGS.shadowNeedsScopedCss) addRemoveSlotScopedClass(contentRef, elm, newParentVNode.$elm$, oldParentVNode?.$elm$);
|
|
2697
|
+
}
|
|
2698
|
+
}
|
|
2699
|
+
return elm;
|
|
2700
|
+
};
|
|
2701
|
+
/**
|
|
2702
|
+
* Relocates all child nodes of an element that were a part of a previous slot relocation
|
|
2703
|
+
* to the root of the Stencil component currently being rendered. This happens when a parent
|
|
2704
|
+
* element of a slot reference node dynamically changes and triggers a re-render. We cannot use
|
|
2705
|
+
* `putBackInOriginalLocation()` because that may relocate nodes to elements that will not be re-rendered
|
|
2706
|
+
* and so they will not be relocated again.
|
|
2707
|
+
*
|
|
2708
|
+
* @param parentElm The element potentially containing relocated nodes.
|
|
2709
|
+
*/
|
|
2710
|
+
const relocateToHostRoot = (parentElm) => {
|
|
2711
|
+
plt.$flags$ |= PLATFORM_FLAGS.isTmpDisconnected;
|
|
2712
|
+
const host = parentElm.closest(hostTagName.toLowerCase());
|
|
2713
|
+
if (host != null) {
|
|
2714
|
+
const contentRefNode = Array.from(host.__childNodes || host.childNodes).find((ref) => ref["s-cr"]);
|
|
2715
|
+
const childNodeArray = Array.from(parentElm.__childNodes || parentElm.childNodes);
|
|
2716
|
+
for (const childNode of contentRefNode ? childNodeArray.reverse() : childNodeArray) if (childNode["s-sh"] != null) {
|
|
2717
|
+
insertBefore(host, childNode, contentRefNode ?? null);
|
|
2718
|
+
childNode["s-sh"] = void 0;
|
|
2719
|
+
checkSlotRelocate = true;
|
|
2720
|
+
}
|
|
2721
|
+
}
|
|
2722
|
+
plt.$flags$ &= ~PLATFORM_FLAGS.isTmpDisconnected;
|
|
2723
|
+
};
|
|
2724
|
+
/**
|
|
2725
|
+
* Puts `<slot>` nodes and any slotted nodes back to their original location (wherever they were before being slotted).
|
|
2726
|
+
*
|
|
2727
|
+
* @param parentElm - The parent element of the nodes to relocate.
|
|
2728
|
+
* @param recursive - Whether or not to relocate nodes in child nodes as well.
|
|
2729
|
+
*/
|
|
2730
|
+
const putBackInOriginalLocation = (parentElm, recursive) => {
|
|
2731
|
+
plt.$flags$ |= PLATFORM_FLAGS.isTmpDisconnected;
|
|
2732
|
+
const oldSlotChildNodes = Array.from(parentElm.__childNodes || parentElm.childNodes);
|
|
2733
|
+
if (parentElm["s-sr"]) {
|
|
2734
|
+
let node = parentElm;
|
|
2735
|
+
while (node = node.nextSibling) if (node && node["s-sn"] === parentElm["s-sn"] && node["s-sh"] === hostTagName) oldSlotChildNodes.push(node);
|
|
2736
|
+
}
|
|
2737
|
+
for (let i = oldSlotChildNodes.length - 1; i >= 0; i--) {
|
|
2738
|
+
const childNode = oldSlotChildNodes[i];
|
|
2739
|
+
if (childNode["s-hn"] !== hostTagName && childNode["s-ol"]) {
|
|
2740
|
+
insertBefore(referenceNode(childNode).parentNode, childNode, referenceNode(childNode));
|
|
2741
|
+
childNode["s-ol"].remove();
|
|
2742
|
+
childNode["s-ol"] = void 0;
|
|
2743
|
+
childNode["s-sh"] = void 0;
|
|
2744
|
+
checkSlotRelocate = true;
|
|
2745
|
+
}
|
|
2746
|
+
if (recursive) putBackInOriginalLocation(childNode, recursive);
|
|
2747
|
+
}
|
|
2748
|
+
plt.$flags$ &= ~PLATFORM_FLAGS.isTmpDisconnected;
|
|
2749
|
+
};
|
|
2750
|
+
/**
|
|
2751
|
+
* Create DOM nodes corresponding to a list of {@link d.Vnode} objects and
|
|
2752
|
+
* add them to the DOM in the appropriate place.
|
|
2753
|
+
*
|
|
2754
|
+
* @param parentElm the DOM node which should be used as a parent for the new
|
|
2755
|
+
* DOM nodes
|
|
2756
|
+
* @param before a child of the `parentElm` which the new children should be
|
|
2757
|
+
* inserted before (optional)
|
|
2758
|
+
* @param parentVNode the parent virtual DOM node
|
|
2759
|
+
* @param vnodes the new child virtual DOM nodes to produce DOM nodes for
|
|
2760
|
+
* @param startIdx the index in the child virtual DOM nodes at which to start
|
|
2761
|
+
* creating DOM nodes (inclusive)
|
|
2762
|
+
* @param endIdx the index in the child virtual DOM nodes at which to stop
|
|
2763
|
+
* creating DOM nodes (inclusive)
|
|
2764
|
+
*/
|
|
2765
|
+
const addVnodes = (parentElm, before, parentVNode, vnodes, startIdx, endIdx) => {
|
|
2766
|
+
let containerElm = BUILD.slotRelocation && parentElm["s-cr"] && parentElm["s-cr"].parentNode || parentElm;
|
|
2767
|
+
let childNode;
|
|
2768
|
+
if (BUILD.shadowDom && containerElm.shadowRoot && containerElm.tagName === hostTagName) containerElm = containerElm.shadowRoot;
|
|
2769
|
+
if (parentVNode.$tag$ === "template") containerElm = containerElm.content;
|
|
2770
|
+
for (; startIdx <= endIdx; ++startIdx) if (vnodes[startIdx]) {
|
|
2771
|
+
childNode = createElm(null, parentVNode, startIdx);
|
|
2772
|
+
if (childNode) {
|
|
2773
|
+
vnodes[startIdx].$elm$ = childNode;
|
|
2774
|
+
insertBefore(containerElm, childNode, BUILD.slotRelocation ? referenceNode(before) : before);
|
|
2775
|
+
}
|
|
2776
|
+
}
|
|
2777
|
+
};
|
|
2778
|
+
/**
|
|
2779
|
+
* Remove the DOM elements corresponding to a list of {@link d.VNode} objects.
|
|
2780
|
+
* This can be used to, for instance, clean up after a list of children which
|
|
2781
|
+
* should no longer be shown.
|
|
2782
|
+
*
|
|
2783
|
+
* This function also handles some of Stencil's slot relocation logic.
|
|
2784
|
+
*
|
|
2785
|
+
* @param vnodes a list of virtual DOM nodes to remove
|
|
2786
|
+
* @param startIdx the index at which to start removing nodes (inclusive)
|
|
2787
|
+
* @param endIdx the index at which to stop removing nodes (inclusive)
|
|
2788
|
+
*/
|
|
2789
|
+
const removeVnodes = (vnodes, startIdx, endIdx) => {
|
|
2790
|
+
for (let index = startIdx; index <= endIdx; ++index) {
|
|
2791
|
+
const vnode = vnodes[index];
|
|
2792
|
+
if (vnode) {
|
|
2793
|
+
const elm = vnode.$elm$;
|
|
2794
|
+
nullifyVNodeRefs(vnode);
|
|
2795
|
+
if (elm) {
|
|
2796
|
+
if (BUILD.slotRelocation) {
|
|
2797
|
+
checkSlotFallbackVisibility = true;
|
|
2798
|
+
if (elm["s-ol"]) elm["s-ol"].remove();
|
|
2799
|
+
else putBackInOriginalLocation(elm, true);
|
|
2800
|
+
}
|
|
2801
|
+
elm.remove();
|
|
2802
|
+
}
|
|
2803
|
+
}
|
|
2804
|
+
}
|
|
2805
|
+
};
|
|
2806
|
+
/**
|
|
2807
|
+
* Reconcile the children of a new VNode with the children of an old VNode by
|
|
2808
|
+
* traversing the two collections of children, identifying nodes that are
|
|
2809
|
+
* conserved or changed, calling out to `patch` to make any necessary
|
|
2810
|
+
* updates to the DOM, and rearranging DOM nodes as needed.
|
|
2811
|
+
*
|
|
2812
|
+
* The algorithm for reconciling children works by analyzing two 'windows' onto
|
|
2813
|
+
* the two arrays of children (`oldCh` and `newCh`). We keep track of the
|
|
2814
|
+
* 'windows' by storing start and end indices and references to the
|
|
2815
|
+
* corresponding array entries. Initially the two 'windows' are basically equal
|
|
2816
|
+
* to the entire array, but we progressively narrow the windows until there are
|
|
2817
|
+
* no children left to update by doing the following:
|
|
2818
|
+
*
|
|
2819
|
+
* 1. Skip any `null` entries at the beginning or end of the two arrays, so
|
|
2820
|
+
* that if we have an initial array like the following we'll end up dealing
|
|
2821
|
+
* only with a window bounded by the highlighted elements:
|
|
2822
|
+
*
|
|
2823
|
+
* [null, null, VNode1 , ... , VNode2, null, null]
|
|
2824
|
+
* ^^^^^^ ^^^^^^
|
|
2825
|
+
*
|
|
2826
|
+
* 2. Check to see if the elements at the head and tail positions are equal
|
|
2827
|
+
* across the windows. This will basically detect elements which haven't
|
|
2828
|
+
* been added, removed, or changed position, i.e. if you had the following
|
|
2829
|
+
* VNode elements (represented as HTML):
|
|
2830
|
+
*
|
|
2831
|
+
* oldVNode: `<div><p><span>HEY</span></p></div>`
|
|
2832
|
+
* newVNode: `<div><p><span>THERE</span></p></div>`
|
|
2833
|
+
*
|
|
2834
|
+
* Then when comparing the children of the `<div>` tag we check the equality
|
|
2835
|
+
* of the VNodes corresponding to the `<p>` tags and, since they are the
|
|
2836
|
+
* same tag in the same position, we'd be able to avoid completely
|
|
2837
|
+
* re-rendering the subtree under them with a new DOM element and would just
|
|
2838
|
+
* call out to `patch` to handle reconciling their children and so on.
|
|
2839
|
+
*
|
|
2840
|
+
* 3. Check, for both windows, to see if the element at the beginning of the
|
|
2841
|
+
* window corresponds to the element at the end of the other window. This is
|
|
2842
|
+
* a heuristic which will let us identify _some_ situations in which
|
|
2843
|
+
* elements have changed position, for instance it _should_ detect that the
|
|
2844
|
+
* children nodes themselves have not changed but merely moved in the
|
|
2845
|
+
* following example:
|
|
2846
|
+
*
|
|
2847
|
+
* oldVNode: `<div><element-one /><element-two /></div>`
|
|
2848
|
+
* newVNode: `<div><element-two /><element-one /></div>`
|
|
2849
|
+
*
|
|
2850
|
+
* If we find cases like this then we also need to move the concrete DOM
|
|
2851
|
+
* elements corresponding to the moved children to write the re-order to the
|
|
2852
|
+
* DOM.
|
|
2853
|
+
*
|
|
2854
|
+
* 4. Finally, if VNodes have the `key` attribute set on them we check for any
|
|
2855
|
+
* nodes in the old children which have the same key as the first element in
|
|
2856
|
+
* our window on the new children. If we find such a node we handle calling
|
|
2857
|
+
* out to `patch`, moving relevant DOM nodes, and so on, in accordance with
|
|
2858
|
+
* what we find.
|
|
2859
|
+
*
|
|
2860
|
+
* Finally, once we've narrowed our 'windows' to the point that either of them
|
|
2861
|
+
* collapse (i.e. they have length 0) we then handle any remaining VNode
|
|
2862
|
+
* insertion or deletion that needs to happen to get a DOM state that correctly
|
|
2863
|
+
* reflects the new child VNodes. If, for instance, after our window on the old
|
|
2864
|
+
* children has collapsed we still have more nodes on the new children that
|
|
2865
|
+
* we haven't dealt with yet then we need to add them, or if the new children
|
|
2866
|
+
* collapse but we still have unhandled _old_ children then we need to make
|
|
2867
|
+
* sure the corresponding DOM nodes are removed.
|
|
2868
|
+
*
|
|
2869
|
+
* @param parentElm the node into which the parent VNode is rendered
|
|
2870
|
+
* @param oldCh the old children of the parent node
|
|
2871
|
+
* @param newVNode the new VNode which will replace the parent
|
|
2872
|
+
* @param newCh the new children of the parent node
|
|
2873
|
+
* @param isInitialRender whether or not this is the first render of the vdom
|
|
2874
|
+
*/
|
|
2875
|
+
const updateChildren = (parentElm, oldCh, newVNode, newCh, isInitialRender = false) => {
|
|
2876
|
+
let oldStartIdx = 0;
|
|
2877
|
+
let newStartIdx = 0;
|
|
2878
|
+
let idxInOld = 0;
|
|
2879
|
+
let i = 0;
|
|
2880
|
+
let oldEndIdx = oldCh.length - 1;
|
|
2881
|
+
let oldStartVnode = oldCh[0];
|
|
2882
|
+
let oldEndVnode = oldCh[oldEndIdx];
|
|
2883
|
+
let newEndIdx = newCh.length - 1;
|
|
2884
|
+
let newStartVnode = newCh[0];
|
|
2885
|
+
let newEndVnode = newCh[newEndIdx];
|
|
2886
|
+
let node;
|
|
2887
|
+
let elmToMove;
|
|
2888
|
+
const containerElm = newVNode.$tag$ === "template" ? parentElm.content : parentElm;
|
|
2889
|
+
while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) if (oldStartVnode == null) oldStartVnode = oldCh[++oldStartIdx];
|
|
2890
|
+
else if (oldEndVnode == null) oldEndVnode = oldCh[--oldEndIdx];
|
|
2891
|
+
else if (newStartVnode == null) newStartVnode = newCh[++newStartIdx];
|
|
2892
|
+
else if (newEndVnode == null) newEndVnode = newCh[--newEndIdx];
|
|
2893
|
+
else if (isSameVnode(oldStartVnode, newStartVnode, isInitialRender)) {
|
|
2894
|
+
patch(oldStartVnode, newStartVnode, isInitialRender);
|
|
2895
|
+
oldStartVnode = oldCh[++oldStartIdx];
|
|
2896
|
+
newStartVnode = newCh[++newStartIdx];
|
|
2897
|
+
} else if (isSameVnode(oldEndVnode, newEndVnode, isInitialRender)) {
|
|
2898
|
+
patch(oldEndVnode, newEndVnode, isInitialRender);
|
|
2899
|
+
oldEndVnode = oldCh[--oldEndIdx];
|
|
2900
|
+
newEndVnode = newCh[--newEndIdx];
|
|
2901
|
+
} else if (isSameVnode(oldStartVnode, newEndVnode, isInitialRender)) {
|
|
2902
|
+
if (BUILD.slotRelocation && (oldStartVnode.$tag$ === "slot" || newEndVnode.$tag$ === "slot")) putBackInOriginalLocation(oldStartVnode.$elm$.parentNode, false);
|
|
2903
|
+
patch(oldStartVnode, newEndVnode, isInitialRender);
|
|
2904
|
+
insertBefore(containerElm, oldStartVnode.$elm$, oldEndVnode.$elm$.nextSibling);
|
|
2905
|
+
oldStartVnode = oldCh[++oldStartIdx];
|
|
2906
|
+
newEndVnode = newCh[--newEndIdx];
|
|
2907
|
+
} else if (isSameVnode(oldEndVnode, newStartVnode, isInitialRender)) {
|
|
2908
|
+
if (BUILD.slotRelocation && (oldStartVnode.$tag$ === "slot" || newEndVnode.$tag$ === "slot")) putBackInOriginalLocation(oldEndVnode.$elm$.parentNode, false);
|
|
2909
|
+
patch(oldEndVnode, newStartVnode, isInitialRender);
|
|
2910
|
+
insertBefore(containerElm, oldEndVnode.$elm$, oldStartVnode.$elm$);
|
|
2911
|
+
oldEndVnode = oldCh[--oldEndIdx];
|
|
2912
|
+
newStartVnode = newCh[++newStartIdx];
|
|
2913
|
+
} else {
|
|
2914
|
+
idxInOld = -1;
|
|
2915
|
+
if (BUILD.vdomKey) {
|
|
2916
|
+
for (i = oldStartIdx; i <= oldEndIdx; ++i) if (oldCh[i] && oldCh[i].$key$ !== null && oldCh[i].$key$ === newStartVnode.$key$) {
|
|
2917
|
+
idxInOld = i;
|
|
2918
|
+
break;
|
|
2919
|
+
}
|
|
2920
|
+
}
|
|
2921
|
+
if (BUILD.vdomKey && idxInOld >= 0) {
|
|
2922
|
+
elmToMove = oldCh[idxInOld];
|
|
2923
|
+
if (elmToMove.$tag$ !== newStartVnode.$tag$) node = createElm(oldCh && oldCh[newStartIdx], newVNode, idxInOld);
|
|
2924
|
+
else {
|
|
2925
|
+
patch(elmToMove, newStartVnode, isInitialRender);
|
|
2926
|
+
oldCh[idxInOld] = void 0;
|
|
2927
|
+
node = elmToMove.$elm$;
|
|
2928
|
+
}
|
|
2929
|
+
newStartVnode = newCh[++newStartIdx];
|
|
2930
|
+
} else {
|
|
2931
|
+
node = createElm(oldCh && oldCh[newStartIdx], newVNode, newStartIdx);
|
|
2932
|
+
newStartVnode = newCh[++newStartIdx];
|
|
2933
|
+
}
|
|
2934
|
+
if (node) if (BUILD.slotRelocation) insertBefore(referenceNode(oldStartVnode.$elm$).parentNode, node, referenceNode(oldStartVnode.$elm$));
|
|
2935
|
+
else insertBefore(oldStartVnode.$elm$.parentNode, node, oldStartVnode.$elm$);
|
|
2936
|
+
}
|
|
2937
|
+
if (oldStartIdx > oldEndIdx) addVnodes(parentElm, newCh[newEndIdx + 1] == null ? null : newCh[newEndIdx + 1].$elm$, newVNode, newCh, newStartIdx, newEndIdx);
|
|
2938
|
+
else if (BUILD.updatable && newStartIdx > newEndIdx) removeVnodes(oldCh, oldStartIdx, oldEndIdx);
|
|
2939
|
+
};
|
|
2940
|
+
/**
|
|
2941
|
+
* Compare two VNodes to determine if they are the same
|
|
2942
|
+
*
|
|
2943
|
+
* **NB**: This function is an equality _heuristic_ based on the available
|
|
2944
|
+
* information set on the two VNodes and can be misleading under certain
|
|
2945
|
+
* circumstances. In particular, if the two nodes do not have `key` attrs
|
|
2946
|
+
* (available under `$key$` on VNodes) then the function falls back on merely
|
|
2947
|
+
* checking that they have the same tag.
|
|
2948
|
+
*
|
|
2949
|
+
* So, in other words, if `key` attrs are not set on VNodes which may be
|
|
2950
|
+
* changing order within a `children` array or something along those lines then
|
|
2951
|
+
* we could obtain a false negative and then have to do needless re-rendering
|
|
2952
|
+
* (i.e. we'd say two VNodes aren't equal when in fact they should be).
|
|
2953
|
+
*
|
|
2954
|
+
* @param leftVNode the first VNode to check
|
|
2955
|
+
* @param rightVNode the second VNode to check
|
|
2956
|
+
* @param isInitialRender whether or not this is the first render of the vdom
|
|
2957
|
+
* @returns whether they're equal or not
|
|
2958
|
+
*/
|
|
2959
|
+
const isSameVnode = (leftVNode, rightVNode, isInitialRender = false) => {
|
|
2960
|
+
if (leftVNode.$tag$ === rightVNode.$tag$) {
|
|
2961
|
+
if (BUILD.slotRelocation && leftVNode.$tag$ === "slot") return leftVNode.$name$ === rightVNode.$name$;
|
|
2962
|
+
if (BUILD.vdomKey && !isInitialRender) return leftVNode.$key$ === rightVNode.$key$;
|
|
2963
|
+
if (isInitialRender && !leftVNode.$key$ && rightVNode.$key$) leftVNode.$key$ = rightVNode.$key$;
|
|
2964
|
+
return true;
|
|
2965
|
+
}
|
|
2966
|
+
return false;
|
|
2967
|
+
};
|
|
2968
|
+
/**
|
|
2969
|
+
* Returns the reference node (a comment which represents the
|
|
2970
|
+
* original location of a node in the vdom - before it was moved to its slot)
|
|
2971
|
+
* of a given node.
|
|
2972
|
+
*
|
|
2973
|
+
* (slot nodes can be relocated to a new location in the dom because of
|
|
2974
|
+
* some other component's slot)
|
|
2975
|
+
* @param node the node to find the original location reference node for
|
|
2976
|
+
* @returns reference node
|
|
2977
|
+
*/
|
|
2978
|
+
const referenceNode = (node) => node && node["s-ol"] || node;
|
|
2979
|
+
/**
|
|
2980
|
+
* Handle reconciling an outdated VNode with a new one which corresponds to
|
|
2981
|
+
* it. This function handles flushing updates to the DOM and reconciling the
|
|
2982
|
+
* children of the two nodes (if any).
|
|
2983
|
+
*
|
|
2984
|
+
* @param oldVNode an old VNode whose DOM element and children we want to update
|
|
2985
|
+
* @param newVNode a new VNode representing an updated version of the old one
|
|
2986
|
+
* @param isInitialRender whether or not this is the first render of the vdom
|
|
2987
|
+
*/
|
|
2988
|
+
const patch = (oldVNode, newVNode, isInitialRender = false) => {
|
|
2989
|
+
const elm = newVNode.$elm$ = oldVNode.$elm$;
|
|
2990
|
+
const oldChildren = oldVNode.$children$;
|
|
2991
|
+
const newChildren = newVNode.$children$;
|
|
2992
|
+
const tag = newVNode.$tag$;
|
|
2993
|
+
const text = newVNode.$text$;
|
|
2994
|
+
let defaultHolder;
|
|
2995
|
+
if (!BUILD.vdomText || text == null) {
|
|
2996
|
+
if (BUILD.svg) isSvgMode = tag === "svg" ? true : tag === "foreignObject" ? false : isSvgMode;
|
|
2997
|
+
if (BUILD.vdomAttribute || BUILD.reflect) {
|
|
2998
|
+
if (BUILD.slot && tag === "slot" && !useNativeShadowDom) {
|
|
2999
|
+
if (oldVNode.$name$ !== newVNode.$name$) {
|
|
3000
|
+
newVNode.$elm$["s-sn"] = newVNode.$name$ || "";
|
|
3001
|
+
relocateToHostRoot(newVNode.$elm$.parentElement);
|
|
3002
|
+
}
|
|
3003
|
+
}
|
|
3004
|
+
updateElement(oldVNode, newVNode, isSvgMode, isInitialRender);
|
|
3005
|
+
}
|
|
3006
|
+
if (BUILD.updatable && oldChildren !== null && newChildren !== null) updateChildren(elm, oldChildren, newVNode, newChildren, isInitialRender);
|
|
3007
|
+
else if (newChildren !== null) {
|
|
3008
|
+
if (BUILD.updatable && BUILD.vdomText && oldVNode.$text$ !== null) elm.textContent = "";
|
|
3009
|
+
addVnodes(elm, null, newVNode, newChildren, 0, newChildren.length - 1);
|
|
3010
|
+
} else if (!isInitialRender && BUILD.updatable && oldChildren !== null) removeVnodes(oldChildren, 0, oldChildren.length - 1);
|
|
3011
|
+
else if (BUILD.hydrateClientSide && isInitialRender && BUILD.updatable && oldChildren !== null && newChildren === null) newVNode.$children$ = oldChildren;
|
|
3012
|
+
if (BUILD.svg && isSvgMode && tag === "svg") isSvgMode = false;
|
|
3013
|
+
} else if (BUILD.vdomText && BUILD.slotRelocation && (defaultHolder = elm["s-cr"])) defaultHolder.parentNode.textContent = text;
|
|
3014
|
+
else if (BUILD.vdomText && oldVNode.$text$ !== text) elm.data = text;
|
|
3015
|
+
};
|
|
3016
|
+
/**
|
|
3017
|
+
* Component-global information about nodes which are either currently being
|
|
3018
|
+
* relocated or will be shortly.
|
|
3019
|
+
*/
|
|
3020
|
+
const relocateNodes = [];
|
|
3021
|
+
/**
|
|
3022
|
+
* Mark the contents of a slot for relocation via adding references to them to
|
|
3023
|
+
* the {@link relocateNodes} data structure. The actual work of relocating them
|
|
3024
|
+
* will then be handled in {@link renderVdom}.
|
|
3025
|
+
*
|
|
3026
|
+
* @param elm a render node whose child nodes need to be relocated
|
|
3027
|
+
*/
|
|
3028
|
+
const markSlotContentForRelocation = (elm) => {
|
|
3029
|
+
let node;
|
|
3030
|
+
let hostContentNodes;
|
|
3031
|
+
let j;
|
|
3032
|
+
const children = elm.__childNodes || elm.childNodes;
|
|
3033
|
+
for (const childNode of children) {
|
|
3034
|
+
if (childNode["s-sr"] && (node = childNode["s-cr"]) && node.parentNode) {
|
|
3035
|
+
hostContentNodes = node.parentNode.__childNodes || node.parentNode.childNodes;
|
|
3036
|
+
const slotName = childNode["s-sn"];
|
|
3037
|
+
for (j = hostContentNodes.length - 1; j >= 0; j--) {
|
|
3038
|
+
node = hostContentNodes[j];
|
|
3039
|
+
if (!node["s-cn"] && !node["s-nr"] && node["s-hn"] !== childNode["s-hn"] && (!node["s-sh"] || node["s-sh"] !== childNode["s-hn"])) {
|
|
3040
|
+
if (isNodeLocatedInSlot(node, slotName)) {
|
|
3041
|
+
let relocateNodeData = relocateNodes.find((r) => r.$nodeToRelocate$ === node);
|
|
3042
|
+
checkSlotFallbackVisibility = true;
|
|
3043
|
+
node["s-sn"] = node["s-sn"] || slotName;
|
|
3044
|
+
if (relocateNodeData) {
|
|
3045
|
+
relocateNodeData.$nodeToRelocate$["s-sh"] = childNode["s-hn"];
|
|
3046
|
+
relocateNodeData.$slotRefNode$ = childNode;
|
|
3047
|
+
} else {
|
|
3048
|
+
node["s-sh"] = childNode["s-hn"];
|
|
3049
|
+
relocateNodes.push({
|
|
3050
|
+
$slotRefNode$: childNode,
|
|
3051
|
+
$nodeToRelocate$: node
|
|
3052
|
+
});
|
|
3053
|
+
}
|
|
3054
|
+
if (node["s-sr"]) relocateNodes.map((relocateNode) => {
|
|
3055
|
+
if (isNodeLocatedInSlot(relocateNode.$nodeToRelocate$, node["s-sn"])) {
|
|
3056
|
+
relocateNodeData = relocateNodes.find((r) => r.$nodeToRelocate$ === node);
|
|
3057
|
+
if (relocateNodeData && !relocateNode.$slotRefNode$) relocateNode.$slotRefNode$ = relocateNodeData.$slotRefNode$;
|
|
3058
|
+
}
|
|
3059
|
+
});
|
|
3060
|
+
} else if (!relocateNodes.some((r) => r.$nodeToRelocate$ === node)) relocateNodes.push({ $nodeToRelocate$: node });
|
|
3061
|
+
}
|
|
3062
|
+
}
|
|
3063
|
+
}
|
|
3064
|
+
if (childNode.nodeType === NODE_TYPE.ElementNode) markSlotContentForRelocation(childNode);
|
|
3065
|
+
}
|
|
3066
|
+
};
|
|
3067
|
+
/**
|
|
3068
|
+
* 'Nullify' any VDom `ref` callbacks on a VDom node or its children by calling
|
|
3069
|
+
* them with `null`. This signals that the DOM element corresponding to the VDom
|
|
3070
|
+
* node has been removed from the DOM.
|
|
3071
|
+
*
|
|
3072
|
+
* @param vNode a virtual DOM node
|
|
3073
|
+
*/
|
|
3074
|
+
const nullifyVNodeRefs = (vNode) => {
|
|
3075
|
+
if (BUILD.vdomRef) {
|
|
3076
|
+
if (vNode.$attrs$ && vNode.$attrs$.ref) refCallbacksToRemove.push(() => vNode.$attrs$.ref(null));
|
|
3077
|
+
vNode.$children$ && vNode.$children$.map(nullifyVNodeRefs);
|
|
3078
|
+
}
|
|
3079
|
+
};
|
|
3080
|
+
/**
|
|
3081
|
+
* Queue a ref callback to be called with an element during rendering.
|
|
3082
|
+
* This ensures ref callbacks are called in the correct order.
|
|
3083
|
+
*
|
|
3084
|
+
* @param refCallback the ref callback function to queue
|
|
3085
|
+
* @param elm the element to pass to the callback
|
|
3086
|
+
*/
|
|
3087
|
+
const queueRefAttachment = (refCallback, elm) => {
|
|
3088
|
+
if (BUILD.vdomRef) refCallbacksToAttach.push(() => refCallback(elm));
|
|
3089
|
+
};
|
|
3090
|
+
/**
|
|
3091
|
+
* Flush all queued ref callbacks in the correct order:
|
|
3092
|
+
* first all removal callbacks (with null), then all attachment callbacks (with elements).
|
|
3093
|
+
* This ensures that when elements are replaced/reordered, the ref is always left
|
|
3094
|
+
* pointing to the current element, not null.
|
|
3095
|
+
*/
|
|
3096
|
+
const flushQueuedRefCallbacks = () => {
|
|
3097
|
+
if (BUILD.vdomRef) {
|
|
3098
|
+
refCallbacksToRemove.forEach((cb) => cb());
|
|
3099
|
+
refCallbacksToRemove.length = 0;
|
|
3100
|
+
refCallbacksToAttach.forEach((cb) => cb());
|
|
3101
|
+
refCallbacksToAttach.length = 0;
|
|
3102
|
+
}
|
|
3103
|
+
};
|
|
3104
|
+
/**
|
|
3105
|
+
* Inserts a node before a reference node as a child of a specified parent node.
|
|
3106
|
+
* Additionally, adds parent elements' scope ids as class names to the new node.
|
|
3107
|
+
*
|
|
3108
|
+
* @param parent parent node
|
|
3109
|
+
* @param newNode element to be inserted
|
|
3110
|
+
* @param reference anchor element
|
|
3111
|
+
* @param isInitialLoad whether or not this is the first render
|
|
3112
|
+
* @returns inserted node
|
|
3113
|
+
*/
|
|
3114
|
+
const insertBefore = (parent, newNode, reference, isInitialLoad) => {
|
|
3115
|
+
if (BUILD.slotRelocation) {
|
|
3116
|
+
if (BUILD.scoped && typeof newNode["s-sn"] === "string" && !!newNode["s-sr"] && !!newNode["s-cr"]) addRemoveSlotScopedClass(newNode["s-cr"], newNode, parent, newNode.parentElement);
|
|
3117
|
+
else if (typeof newNode["s-sn"] === "string") {
|
|
3118
|
+
if (BUILD.experimentalSlotFixes && parent.getRootNode().nodeType !== NODE_TYPES.DOCUMENT_FRAGMENT_NODE) patchParentNode(newNode);
|
|
3119
|
+
parent.insertBefore(newNode, reference);
|
|
3120
|
+
const { slotNode } = findSlotFromSlottedNode(newNode);
|
|
3121
|
+
if (slotNode && !isInitialLoad) dispatchSlotChangeEvent(slotNode);
|
|
3122
|
+
return newNode;
|
|
3123
|
+
}
|
|
3124
|
+
}
|
|
3125
|
+
if (parent.__insertBefore) return parent.__insertBefore(newNode, reference);
|
|
3126
|
+
else return parent?.insertBefore(newNode, reference);
|
|
3127
|
+
};
|
|
3128
|
+
/**
|
|
3129
|
+
* Adds or removes a scoped class to the parent element of a slotted node.
|
|
3130
|
+
* This is used for styling slotted content (e.g. with `::scoped(...) {...}` selectors )
|
|
3131
|
+
* in `scoped: true` components.
|
|
3132
|
+
*
|
|
3133
|
+
* @param reference - Content Reference Node. Used to get the scope id of the parent component.
|
|
3134
|
+
* @param slotNode - the `<slot>` node to apply the class for
|
|
3135
|
+
* @param newParent - the slots' new parent element that requires the scoped class
|
|
3136
|
+
* @param oldParent - optionally, an old parent element that may no longer require the scoped class
|
|
3137
|
+
*/
|
|
3138
|
+
function addRemoveSlotScopedClass(reference, slotNode, newParent, oldParent) {
|
|
3139
|
+
let scopeId;
|
|
3140
|
+
if (reference && typeof slotNode["s-sn"] === "string" && !!slotNode["s-sr"] && reference.parentNode && reference.parentNode["s-sc"] && (scopeId = slotNode["s-si"] || reference.parentNode["s-sc"])) {
|
|
3141
|
+
const scopeName = slotNode["s-sn"];
|
|
3142
|
+
const hostName = slotNode["s-hn"];
|
|
3143
|
+
newParent.classList?.add(scopeId + "-s");
|
|
3144
|
+
if (oldParent && oldParent.classList?.contains(scopeId + "-s")) {
|
|
3145
|
+
let child = (oldParent.__childNodes || oldParent.childNodes)[0];
|
|
3146
|
+
let found = false;
|
|
3147
|
+
while (child) {
|
|
3148
|
+
if (child["s-sn"] !== scopeName && child["s-hn"] === hostName && !!child["s-sr"]) {
|
|
3149
|
+
found = true;
|
|
3150
|
+
break;
|
|
3151
|
+
}
|
|
3152
|
+
child = child.nextSibling;
|
|
3153
|
+
}
|
|
3154
|
+
if (!found) oldParent.classList.remove(scopeId + "-s");
|
|
3155
|
+
}
|
|
3156
|
+
}
|
|
3157
|
+
}
|
|
3158
|
+
/**
|
|
3159
|
+
* The main entry point for Stencil's virtual DOM-based rendering engine
|
|
3160
|
+
*
|
|
3161
|
+
* Given a {@link d.HostRef} container and some virtual DOM nodes, this
|
|
3162
|
+
* function will handle creating a virtual DOM tree with a single root, patching
|
|
3163
|
+
* the current virtual DOM tree onto an old one (if any), dealing with slot
|
|
3164
|
+
* relocation, and reflecting attributes.
|
|
3165
|
+
*
|
|
3166
|
+
* @param hostRef data needed to root and render the virtual DOM tree, such as
|
|
3167
|
+
* the DOM node into which it should be rendered.
|
|
3168
|
+
* @param renderFnResults the virtual DOM nodes to be rendered
|
|
3169
|
+
* @param isInitialLoad whether or not this is the first call after page load
|
|
3170
|
+
*/
|
|
3171
|
+
const renderVdom = (hostRef, renderFnResults, isInitialLoad = false) => {
|
|
3172
|
+
const hostElm = hostRef.$hostElement$;
|
|
3173
|
+
const cmpMeta = hostRef.$cmpMeta$;
|
|
3174
|
+
const oldVNode = hostRef.$vnode$ || newVNode(null, null);
|
|
3175
|
+
const rootVnode = isHost(renderFnResults) ? renderFnResults : h(null, null, renderFnResults);
|
|
3176
|
+
hostTagName = hostElm.tagName;
|
|
3177
|
+
if (BUILD.isDev && Array.isArray(renderFnResults) && renderFnResults.some(isHost)) throw new Error(`The <Host> must be the single root component.
|
|
3178
|
+
Looks like the render() function of "${hostTagName.toLowerCase()}" is returning an array that contains the <Host>.
|
|
3179
|
+
|
|
3180
|
+
The render() function should look like this instead:
|
|
3181
|
+
|
|
3182
|
+
render() {
|
|
3183
|
+
// Do not return an array
|
|
3184
|
+
return (
|
|
3185
|
+
<Host>{content}</Host>
|
|
3186
|
+
);
|
|
3187
|
+
}
|
|
3188
|
+
`);
|
|
3189
|
+
if (BUILD.reflect && cmpMeta.$attrsToReflect$) {
|
|
3190
|
+
rootVnode.$attrs$ = rootVnode.$attrs$ || {};
|
|
3191
|
+
cmpMeta.$attrsToReflect$.forEach(([propName, attribute]) => {
|
|
3192
|
+
if (BUILD.serializer && hostRef.$serializerValues$.has(propName)) rootVnode.$attrs$[attribute] = hostRef.$serializerValues$.get(propName);
|
|
3193
|
+
else rootVnode.$attrs$[attribute] = hostElm[propName];
|
|
3194
|
+
});
|
|
3195
|
+
}
|
|
3196
|
+
if (isInitialLoad && rootVnode.$attrs$) {
|
|
3197
|
+
for (const key of Object.keys(rootVnode.$attrs$)) if (hostElm.hasAttribute(key) && ![
|
|
3198
|
+
"key",
|
|
3199
|
+
"ref",
|
|
3200
|
+
"style",
|
|
3201
|
+
"class"
|
|
3202
|
+
].includes(key)) rootVnode.$attrs$[key] = hostElm[key];
|
|
3203
|
+
}
|
|
3204
|
+
rootVnode.$tag$ = null;
|
|
3205
|
+
rootVnode.$flags$ |= VNODE_FLAGS.isHost;
|
|
3206
|
+
hostRef.$vnode$ = rootVnode;
|
|
3207
|
+
rootVnode.$elm$ = oldVNode.$elm$ = BUILD.shadowDom ? hostElm.shadowRoot || hostElm : hostElm;
|
|
3208
|
+
if (BUILD.scoped || BUILD.shadowDom) scopeId = hostElm["s-sc"];
|
|
3209
|
+
useNativeShadowDom = supportsShadow && !!(cmpMeta.$flags$ & CMP_FLAGS.shadowDomEncapsulation) && !(cmpMeta.$flags$ & CMP_FLAGS.shadowNeedsScopedCss);
|
|
3210
|
+
if (BUILD.slotRelocation) {
|
|
3211
|
+
contentRef = hostElm["s-cr"];
|
|
3212
|
+
checkSlotFallbackVisibility = false;
|
|
3213
|
+
}
|
|
3214
|
+
patch(oldVNode, rootVnode, isInitialLoad);
|
|
3215
|
+
if (BUILD.slotRelocation) {
|
|
3216
|
+
plt.$flags$ |= PLATFORM_FLAGS.isTmpDisconnected;
|
|
3217
|
+
if (checkSlotRelocate) {
|
|
3218
|
+
markSlotContentForRelocation(rootVnode.$elm$);
|
|
3219
|
+
for (const relocateData of relocateNodes) {
|
|
3220
|
+
const nodeToRelocate = relocateData.$nodeToRelocate$;
|
|
3221
|
+
if (!nodeToRelocate["s-ol"] && win.document) {
|
|
3222
|
+
const orgLocationNode = BUILD.isDebug || BUILD.hydrateServerSide ? originalLocationDebugNode(nodeToRelocate) : win.document.createTextNode("");
|
|
3223
|
+
orgLocationNode["s-nr"] = nodeToRelocate;
|
|
3224
|
+
insertBefore(nodeToRelocate.parentNode, nodeToRelocate["s-ol"] = orgLocationNode, nodeToRelocate, isInitialLoad);
|
|
3225
|
+
}
|
|
3226
|
+
}
|
|
3227
|
+
for (const relocateData of relocateNodes) {
|
|
3228
|
+
const nodeToRelocate = relocateData.$nodeToRelocate$;
|
|
3229
|
+
const slotRefNode = relocateData.$slotRefNode$;
|
|
3230
|
+
if (nodeToRelocate.nodeType === NODE_TYPE.ElementNode && isInitialLoad) nodeToRelocate["s-ih"] = nodeToRelocate.hidden ?? false;
|
|
3231
|
+
if (slotRefNode) {
|
|
3232
|
+
const parentNodeRef = slotRefNode.parentNode;
|
|
3233
|
+
let insertBeforeNode = slotRefNode.nextSibling;
|
|
3234
|
+
if (!BUILD.hydrateServerSide && insertBeforeNode && insertBeforeNode.nodeType === NODE_TYPE.ElementNode) {
|
|
3235
|
+
let orgLocationNode = nodeToRelocate["s-ol"]?.previousSibling;
|
|
3236
|
+
while (orgLocationNode) {
|
|
3237
|
+
let refNode = orgLocationNode["s-nr"] ?? null;
|
|
3238
|
+
if (refNode && refNode["s-sn"] === nodeToRelocate["s-sn"] && parentNodeRef === (refNode.__parentNode || refNode.parentNode)) {
|
|
3239
|
+
refNode = refNode.nextSibling;
|
|
3240
|
+
while (refNode === nodeToRelocate || refNode?.["s-sr"]) refNode = refNode?.nextSibling;
|
|
3241
|
+
if (!refNode || !refNode["s-nr"]) {
|
|
3242
|
+
insertBeforeNode = refNode;
|
|
3243
|
+
break;
|
|
3244
|
+
}
|
|
3245
|
+
}
|
|
3246
|
+
orgLocationNode = orgLocationNode.previousSibling;
|
|
3247
|
+
}
|
|
3248
|
+
}
|
|
3249
|
+
const parent = nodeToRelocate.__parentNode || nodeToRelocate.parentNode;
|
|
3250
|
+
const nextSibling = nodeToRelocate.__nextSibling || nodeToRelocate.nextSibling;
|
|
3251
|
+
if (!insertBeforeNode && parentNodeRef !== parent || nextSibling !== insertBeforeNode) {
|
|
3252
|
+
if (nodeToRelocate !== insertBeforeNode) {
|
|
3253
|
+
insertBefore(parentNodeRef, nodeToRelocate, insertBeforeNode, isInitialLoad);
|
|
3254
|
+
if (nodeToRelocate.nodeType === NODE_TYPE.CommentNode && nodeToRelocate.nodeValue.startsWith("s-nt-")) {
|
|
3255
|
+
const textNode = win.document.createTextNode(nodeToRelocate.nodeValue.replace(/^s-nt-/, ""));
|
|
3256
|
+
textNode["s-hn"] = nodeToRelocate["s-hn"];
|
|
3257
|
+
textNode["s-sn"] = nodeToRelocate["s-sn"];
|
|
3258
|
+
textNode["s-sh"] = nodeToRelocate["s-sh"];
|
|
3259
|
+
textNode["s-sr"] = nodeToRelocate["s-sr"];
|
|
3260
|
+
textNode["s-ol"] = nodeToRelocate["s-ol"];
|
|
3261
|
+
textNode["s-ol"]["s-nr"] = textNode;
|
|
3262
|
+
insertBefore(nodeToRelocate.parentNode, textNode, nodeToRelocate, isInitialLoad);
|
|
3263
|
+
nodeToRelocate.parentNode.removeChild(nodeToRelocate);
|
|
3264
|
+
}
|
|
3265
|
+
if (nodeToRelocate.nodeType === NODE_TYPE.ElementNode && nodeToRelocate.tagName !== "SLOT-FB") nodeToRelocate.hidden = nodeToRelocate["s-ih"] ?? false;
|
|
3266
|
+
}
|
|
3267
|
+
}
|
|
3268
|
+
nodeToRelocate && typeof slotRefNode["s-rf"] === "function" && slotRefNode["s-rf"](slotRefNode);
|
|
3269
|
+
} else if (nodeToRelocate.nodeType === NODE_TYPE.ElementNode) nodeToRelocate.hidden = true;
|
|
3270
|
+
}
|
|
3271
|
+
}
|
|
3272
|
+
if (checkSlotFallbackVisibility) updateFallbackSlotVisibility(rootVnode.$elm$);
|
|
3273
|
+
plt.$flags$ &= ~PLATFORM_FLAGS.isTmpDisconnected;
|
|
3274
|
+
relocateNodes.length = 0;
|
|
3275
|
+
}
|
|
3276
|
+
if (BUILD.slotRelocation && !useNativeShadowDom && !(cmpMeta.$flags$ & CMP_FLAGS.shadowDomEncapsulation) && hostElm["s-cr"]) {
|
|
3277
|
+
const children = rootVnode.$elm$.__childNodes || rootVnode.$elm$.childNodes;
|
|
3278
|
+
for (const childNode of children) if (childNode["s-hn"] !== hostTagName && !childNode["s-sh"]) {
|
|
3279
|
+
if (isInitialLoad && childNode["s-ih"] == null) childNode["s-ih"] = childNode.hidden ?? false;
|
|
3280
|
+
if (childNode.nodeType === NODE_TYPE.ElementNode) childNode.hidden = true;
|
|
3281
|
+
else if (childNode.nodeType === NODE_TYPE.TextNode && !!childNode.nodeValue.trim()) {
|
|
3282
|
+
const textCommentNode = win.document.createComment("s-nt-" + childNode.nodeValue);
|
|
3283
|
+
textCommentNode["s-sn"] = childNode["s-sn"];
|
|
3284
|
+
insertBefore(childNode.parentNode, textCommentNode, childNode, isInitialLoad);
|
|
3285
|
+
childNode.parentNode.removeChild(childNode);
|
|
3286
|
+
}
|
|
3287
|
+
}
|
|
3288
|
+
}
|
|
3289
|
+
contentRef = void 0;
|
|
3290
|
+
flushQueuedRefCallbacks();
|
|
3291
|
+
};
|
|
3292
|
+
const slotReferenceDebugNode = (slotVNode) => win.document?.createComment(`<slot${slotVNode.$name$ ? " name=\"" + slotVNode.$name$ + "\"" : ""}> (host=${hostTagName.toLowerCase()})`);
|
|
3293
|
+
const originalLocationDebugNode = (nodeToRelocate) => win.document?.createComment(`org-location for ` + (nodeToRelocate.localName ? `<${nodeToRelocate.localName}> (host=${nodeToRelocate["s-hn"]})` : `[${nodeToRelocate.textContent}]`));
|
|
3294
|
+
|
|
3295
|
+
//#endregion
|
|
3296
|
+
//#region src/runtime/update-component.ts
|
|
3297
|
+
const attachToAncestor = (hostRef, ancestorComponent) => {
|
|
3298
|
+
if (BUILD.asyncLoading && ancestorComponent && !hostRef.$onRenderResolve$ && ancestorComponent["s-p"]) {
|
|
3299
|
+
const index = ancestorComponent["s-p"].push(new Promise((r) => hostRef.$onRenderResolve$ = () => {
|
|
3300
|
+
ancestorComponent["s-p"].splice(index - 1, 1);
|
|
3301
|
+
r();
|
|
3302
|
+
}));
|
|
3303
|
+
}
|
|
3304
|
+
};
|
|
3305
|
+
const scheduleUpdate = (hostRef, isInitialLoad) => {
|
|
3306
|
+
if (BUILD.taskQueue && BUILD.updatable) hostRef.$flags$ |= HOST_FLAGS.isQueuedForUpdate;
|
|
3307
|
+
if (BUILD.asyncLoading && hostRef.$flags$ & HOST_FLAGS.isWaitingForChildren) {
|
|
3308
|
+
hostRef.$flags$ |= HOST_FLAGS.needsRerender;
|
|
3309
|
+
return;
|
|
3310
|
+
}
|
|
3311
|
+
attachToAncestor(hostRef, hostRef.$ancestorComponent$);
|
|
3312
|
+
const dispatch = () => dispatchHooks(hostRef, isInitialLoad);
|
|
3313
|
+
if (isInitialLoad) {
|
|
3314
|
+
queueMicrotask(() => {
|
|
3315
|
+
dispatch();
|
|
3316
|
+
});
|
|
3317
|
+
return;
|
|
3318
|
+
}
|
|
3319
|
+
return BUILD.taskQueue ? writeTask(dispatch) : dispatch();
|
|
3320
|
+
};
|
|
3321
|
+
/**
|
|
3322
|
+
* Dispatch initial-render and update lifecycle hooks, enqueuing calls to
|
|
3323
|
+
* component lifecycle methods like `componentWillLoad` as well as
|
|
3324
|
+
* {@link updateComponent}, which will kick off the virtual DOM re-render.
|
|
3325
|
+
*
|
|
3326
|
+
* @param hostRef a reference to a host DOM node
|
|
3327
|
+
* @param isInitialLoad whether we're on the initial load or not
|
|
3328
|
+
* @returns an empty Promise which is used to enqueue a series of operations for
|
|
3329
|
+
* the component
|
|
3330
|
+
*/
|
|
3331
|
+
const dispatchHooks = (hostRef, isInitialLoad) => {
|
|
3332
|
+
const elm = hostRef.$hostElement$;
|
|
3333
|
+
const endSchedule = createTime("scheduleUpdate", hostRef.$cmpMeta$.$tagName$);
|
|
3334
|
+
const instance = BUILD.lazyLoad ? hostRef.$lazyInstance$ : elm;
|
|
3335
|
+
/**
|
|
3336
|
+
* Given a user imports a component compiled with a `dist-custom-element`
|
|
3337
|
+
* output target into a Stencil project compiled with a `dist` output target,
|
|
3338
|
+
* then `instance` will be `undefined` as `hostRef` won't have a `lazyInstance`
|
|
3339
|
+
* property. In this case, the component will fail to render in one of the
|
|
3340
|
+
* subsequent functions.
|
|
3341
|
+
*
|
|
3342
|
+
* For this scenario to work the user needs to set the `externalRuntime` flag
|
|
3343
|
+
* for the `dist-custom-element` component that is being imported into the `dist`
|
|
3344
|
+
* Stencil project.
|
|
3345
|
+
*/
|
|
3346
|
+
if (!instance) throw new Error(`Can't render component <${elm.tagName.toLowerCase()} /> with invalid Stencil runtime! Make sure this imported component is compiled with a \`externalRuntime: true\` flag. For more information, please refer to https://stenciljs.com/docs/custom-elements#externalruntime`);
|
|
3347
|
+
let maybePromise;
|
|
3348
|
+
if (isInitialLoad) {
|
|
3349
|
+
if (BUILD.lazyLoad) {
|
|
3350
|
+
if (BUILD.slotRelocation && hostRef.$deferredConnectedCallback$) {
|
|
3351
|
+
hostRef.$deferredConnectedCallback$ = false;
|
|
3352
|
+
safeCall(instance, "connectedCallback", void 0, elm);
|
|
3353
|
+
}
|
|
3354
|
+
if (BUILD.hostListener) {
|
|
3355
|
+
hostRef.$flags$ |= HOST_FLAGS.isListenReady;
|
|
3356
|
+
if (hostRef.$queuedListeners$) {
|
|
3357
|
+
hostRef.$queuedListeners$.map(([methodName, event]) => safeCall(instance, methodName, event, elm));
|
|
3358
|
+
hostRef.$queuedListeners$ = void 0;
|
|
3359
|
+
}
|
|
3360
|
+
}
|
|
3361
|
+
if (hostRef.$fetchedCbList$.length) hostRef.$fetchedCbList$.forEach((cb) => cb(elm));
|
|
3362
|
+
}
|
|
3363
|
+
emitLifecycleEvent(elm, "componentWillLoad");
|
|
3364
|
+
maybePromise = safeCall(instance, "componentWillLoad", void 0, elm);
|
|
3365
|
+
} else {
|
|
3366
|
+
emitLifecycleEvent(elm, "componentWillUpdate");
|
|
3367
|
+
maybePromise = safeCall(instance, "componentWillUpdate", void 0, elm);
|
|
3368
|
+
}
|
|
3369
|
+
emitLifecycleEvent(elm, "componentWillRender");
|
|
3370
|
+
maybePromise = enqueue(maybePromise, () => safeCall(instance, "componentWillRender", void 0, elm));
|
|
3371
|
+
endSchedule();
|
|
3372
|
+
return enqueue(maybePromise, () => updateComponent(hostRef, instance, isInitialLoad));
|
|
3373
|
+
};
|
|
3374
|
+
/**
|
|
3375
|
+
* This function uses a Promise to implement a simple first-in, first-out queue
|
|
3376
|
+
* of functions to be called.
|
|
3377
|
+
*
|
|
3378
|
+
* The queue is ordered on the basis of the first argument. If it's
|
|
3379
|
+
* `undefined`, then nothing is on the queue yet, so the provided function can
|
|
3380
|
+
* be called synchronously (although note that this function may return a
|
|
3381
|
+
* `Promise`). The idea is that then the return value of that enqueueing
|
|
3382
|
+
* operation is kept around, so that if it was a `Promise` then subsequent
|
|
3383
|
+
* functions can be enqueued by calling this function again with that `Promise`
|
|
3384
|
+
* as the first argument.
|
|
3385
|
+
*
|
|
3386
|
+
* @param maybePromise either a `Promise` which should resolve before the next function is called or an 'empty' sentinel
|
|
3387
|
+
* @param fn a function to enqueue
|
|
3388
|
+
* @returns either a `Promise` or the return value of the provided function
|
|
3389
|
+
*/
|
|
3390
|
+
const enqueue = (maybePromise, fn) => isPromisey(maybePromise) ? maybePromise.then(fn).catch((err) => {
|
|
3391
|
+
console.error(err);
|
|
3392
|
+
fn();
|
|
3393
|
+
}) : fn();
|
|
3394
|
+
/**
|
|
3395
|
+
* Check that a value is a `Promise`. To check, we first see if the value is an
|
|
3396
|
+
* instance of the `Promise` global. In a few circumstances, in particular if
|
|
3397
|
+
* the global has been overwritten, this is could be misleading, so we also do
|
|
3398
|
+
* a little 'duck typing' check to see if the `.then` property of the value is
|
|
3399
|
+
* defined and a function.
|
|
3400
|
+
*
|
|
3401
|
+
* @param maybePromise it might be a promise!
|
|
3402
|
+
* @returns whether it is or not
|
|
3403
|
+
*/
|
|
3404
|
+
const isPromisey = (maybePromise) => maybePromise instanceof Promise || maybePromise && maybePromise.then && typeof maybePromise.then === "function";
|
|
3405
|
+
/**
|
|
3406
|
+
* Update a component given reference to its host elements and so on.
|
|
3407
|
+
*
|
|
3408
|
+
* @param hostRef an object containing references to the element's host node,
|
|
3409
|
+
* VDom nodes, and other metadata
|
|
3410
|
+
* @param instance a reference to the underlying host element where it will be
|
|
3411
|
+
* rendered
|
|
3412
|
+
* @param isInitialLoad whether or not this function is being called as part of
|
|
3413
|
+
* the first render cycle
|
|
3414
|
+
*/
|
|
3415
|
+
const updateComponent = async (hostRef, instance, isInitialLoad) => {
|
|
3416
|
+
const elm = hostRef.$hostElement$;
|
|
3417
|
+
const endUpdate = createTime("update", hostRef.$cmpMeta$.$tagName$);
|
|
3418
|
+
const rc = elm["s-rc"];
|
|
3419
|
+
if (BUILD.style && isInitialLoad) attachStyles(hostRef);
|
|
3420
|
+
const endRender = createTime("render", hostRef.$cmpMeta$.$tagName$);
|
|
3421
|
+
if (BUILD.isDev) hostRef.$flags$ |= HOST_FLAGS.devOnRender;
|
|
3422
|
+
if (BUILD.hydrateServerSide) await callRender(hostRef, instance, elm, isInitialLoad);
|
|
3423
|
+
else callRender(hostRef, instance, elm, isInitialLoad);
|
|
3424
|
+
if (BUILD.isDev) {
|
|
3425
|
+
hostRef.$renderCount$ = hostRef.$renderCount$ === void 0 ? 1 : hostRef.$renderCount$ + 1;
|
|
3426
|
+
hostRef.$flags$ &= ~HOST_FLAGS.devOnRender;
|
|
3427
|
+
}
|
|
3428
|
+
if (BUILD.hydrateServerSide) try {
|
|
3429
|
+
serverSideConnected(elm);
|
|
3430
|
+
if (isInitialLoad) {
|
|
3431
|
+
if (hostRef.$cmpMeta$.$flags$ & CMP_FLAGS.shadowDomEncapsulation) elm["s-en"] = "";
|
|
3432
|
+
else if (hostRef.$cmpMeta$.$flags$ & CMP_FLAGS.scopedCssEncapsulation) elm["s-en"] = "c";
|
|
3433
|
+
}
|
|
3434
|
+
} catch (e) {
|
|
3435
|
+
consoleError(e, elm);
|
|
3436
|
+
}
|
|
3437
|
+
if (BUILD.asyncLoading && rc) {
|
|
3438
|
+
rc.map((cb) => cb());
|
|
3439
|
+
elm["s-rc"] = void 0;
|
|
3440
|
+
}
|
|
3441
|
+
endRender();
|
|
3442
|
+
endUpdate();
|
|
3443
|
+
if (BUILD.asyncLoading) {
|
|
3444
|
+
const childrenPromises = elm["s-p"] ?? [];
|
|
3445
|
+
const postUpdate = () => postUpdateComponent(hostRef);
|
|
3446
|
+
if (childrenPromises.length === 0) postUpdate();
|
|
3447
|
+
else {
|
|
3448
|
+
Promise.all(childrenPromises).then(postUpdate).catch(postUpdate);
|
|
3449
|
+
hostRef.$flags$ |= HOST_FLAGS.isWaitingForChildren;
|
|
3450
|
+
childrenPromises.length = 0;
|
|
3451
|
+
}
|
|
3452
|
+
} else postUpdateComponent(hostRef);
|
|
3453
|
+
};
|
|
3454
|
+
let renderingRef = null;
|
|
3455
|
+
/**
|
|
3456
|
+
* Handle making the call to the VDom renderer with the proper context given
|
|
3457
|
+
* various build variables
|
|
3458
|
+
*
|
|
3459
|
+
* @param hostRef an object containing references to the element's host node,
|
|
3460
|
+
* VDom nodes, and other metadata
|
|
3461
|
+
* @param instance a reference to the underlying host element where it will be
|
|
3462
|
+
* rendered
|
|
3463
|
+
* @param elm the Host element for the component
|
|
3464
|
+
* @param isInitialLoad whether or not this function is being called as part of
|
|
3465
|
+
* @returns an empty promise
|
|
3466
|
+
*/
|
|
3467
|
+
const callRender = (hostRef, instance, elm, isInitialLoad) => {
|
|
3468
|
+
const allRenderFn = BUILD.allRenderFn ? true : false;
|
|
3469
|
+
const lazyLoad = BUILD.lazyLoad ? true : false;
|
|
3470
|
+
const taskQueue = BUILD.taskQueue ? true : false;
|
|
3471
|
+
const updatable = BUILD.updatable ? true : false;
|
|
3472
|
+
try {
|
|
3473
|
+
renderingRef = instance;
|
|
3474
|
+
/**
|
|
3475
|
+
* minification optimization: `allRenderFn` is `true` if all components have a `render`
|
|
3476
|
+
* method, so we can call the method immediately. If not, check before calling it.
|
|
3477
|
+
*/
|
|
3478
|
+
instance = allRenderFn ? instance.render() : instance.render && instance.render();
|
|
3479
|
+
if (updatable && taskQueue) hostRef.$flags$ &= ~HOST_FLAGS.isQueuedForUpdate;
|
|
3480
|
+
if (updatable || lazyLoad) hostRef.$flags$ |= HOST_FLAGS.hasRendered;
|
|
3481
|
+
if (BUILD.hasRenderFn || BUILD.reflect) if (BUILD.vdomRender || BUILD.reflect) if (BUILD.hydrateServerSide) return Promise.resolve(instance).then((value) => renderVdom(hostRef, value, isInitialLoad));
|
|
3482
|
+
else renderVdom(hostRef, instance, isInitialLoad);
|
|
3483
|
+
else {
|
|
3484
|
+
const shadowRoot = elm.shadowRoot;
|
|
3485
|
+
if (hostRef.$cmpMeta$.$flags$ & CMP_FLAGS.shadowDomEncapsulation) shadowRoot.textContent = instance;
|
|
3486
|
+
else elm.textContent = instance;
|
|
3487
|
+
}
|
|
3488
|
+
} catch (e) {
|
|
3489
|
+
consoleError(e, hostRef.$hostElement$);
|
|
3490
|
+
}
|
|
3491
|
+
renderingRef = null;
|
|
3492
|
+
return null;
|
|
3493
|
+
};
|
|
3494
|
+
const getRenderingRef = () => renderingRef;
|
|
3495
|
+
const postUpdateComponent = (hostRef) => {
|
|
3496
|
+
const tagName = hostRef.$cmpMeta$.$tagName$;
|
|
3497
|
+
const elm = hostRef.$hostElement$;
|
|
3498
|
+
const endPostUpdate = createTime("postUpdate", tagName);
|
|
3499
|
+
const instance = BUILD.lazyLoad ? hostRef.$lazyInstance$ : elm;
|
|
3500
|
+
const ancestorComponent = hostRef.$ancestorComponent$;
|
|
3501
|
+
if (BUILD.isDev) hostRef.$flags$ |= HOST_FLAGS.devOnRender;
|
|
3502
|
+
safeCall(instance, "componentDidRender", void 0, elm);
|
|
3503
|
+
if (BUILD.isDev) hostRef.$flags$ &= ~HOST_FLAGS.devOnRender;
|
|
3504
|
+
emitLifecycleEvent(elm, "componentDidRender");
|
|
3505
|
+
if (!(hostRef.$flags$ & HOST_FLAGS.hasLoadedComponent)) {
|
|
3506
|
+
hostRef.$flags$ |= HOST_FLAGS.hasLoadedComponent;
|
|
3507
|
+
if (BUILD.asyncLoading && BUILD.cssAnnotations) addHydratedFlag(elm);
|
|
3508
|
+
if (BUILD.isDev) hostRef.$flags$ |= HOST_FLAGS.devOnDidLoad;
|
|
3509
|
+
safeCall(instance, "componentDidLoad", void 0, elm);
|
|
3510
|
+
if (BUILD.isDev) hostRef.$flags$ &= ~HOST_FLAGS.devOnDidLoad;
|
|
3511
|
+
emitLifecycleEvent(elm, "componentDidLoad");
|
|
3512
|
+
endPostUpdate();
|
|
3513
|
+
if (BUILD.asyncLoading) {
|
|
3514
|
+
hostRef.$onReadyResolve$(elm);
|
|
3515
|
+
if (!ancestorComponent) appDidLoad(tagName);
|
|
3516
|
+
}
|
|
3517
|
+
} else {
|
|
3518
|
+
if (BUILD.isDev) hostRef.$flags$ |= HOST_FLAGS.devOnRender;
|
|
3519
|
+
safeCall(instance, "componentDidUpdate", void 0, elm);
|
|
3520
|
+
if (BUILD.isDev) hostRef.$flags$ &= ~HOST_FLAGS.devOnRender;
|
|
3521
|
+
emitLifecycleEvent(elm, "componentDidUpdate");
|
|
3522
|
+
endPostUpdate();
|
|
3523
|
+
}
|
|
3524
|
+
if (BUILD.method && BUILD.lazyLoad) hostRef.$onInstanceResolve$(elm);
|
|
3525
|
+
if (BUILD.asyncLoading) {
|
|
3526
|
+
if (hostRef.$onRenderResolve$) {
|
|
3527
|
+
hostRef.$onRenderResolve$();
|
|
3528
|
+
hostRef.$onRenderResolve$ = void 0;
|
|
3529
|
+
}
|
|
3530
|
+
if (hostRef.$flags$ & HOST_FLAGS.needsRerender) nextTick(() => scheduleUpdate(hostRef, false));
|
|
3531
|
+
hostRef.$flags$ &= ~(HOST_FLAGS.isWaitingForChildren | HOST_FLAGS.needsRerender);
|
|
3532
|
+
}
|
|
3533
|
+
};
|
|
3534
|
+
const forceUpdate = (ref) => {
|
|
3535
|
+
if (BUILD.updatable && (Build.isBrowser || Build.isTesting)) {
|
|
3536
|
+
const hostRef = getHostRef(ref);
|
|
3537
|
+
const isConnected = hostRef?.$hostElement$?.isConnected;
|
|
3538
|
+
if (isConnected && (hostRef.$flags$ & (HOST_FLAGS.hasRendered | HOST_FLAGS.isQueuedForUpdate)) === HOST_FLAGS.hasRendered) scheduleUpdate(hostRef, false);
|
|
3539
|
+
return isConnected;
|
|
3540
|
+
}
|
|
3541
|
+
return false;
|
|
3542
|
+
};
|
|
3543
|
+
const appDidLoad = (who) => {
|
|
3544
|
+
if (BUILD.asyncQueue) plt.$flags$ |= PLATFORM_FLAGS.appLoaded;
|
|
3545
|
+
nextTick(() => emitEvent(win, "appload", { detail: { namespace: NAMESPACE } }));
|
|
3546
|
+
if (BUILD.hydrateClientSide) {
|
|
3547
|
+
if (plt.$orgLocNodes$?.size) plt.$orgLocNodes$.clear();
|
|
3548
|
+
}
|
|
3549
|
+
if (BUILD.profile && performance.measure) performance.measure(`[Stencil] ${NAMESPACE} initial load (by ${who})`, "st:app:start");
|
|
3550
|
+
};
|
|
3551
|
+
/**
|
|
3552
|
+
* Allows to safely call a method, e.g. `componentDidLoad`, on an instance,
|
|
3553
|
+
* e.g. custom element node. If a build figures out that e.g. no component
|
|
3554
|
+
* has a `componentDidLoad` method, the instance method gets removed from the
|
|
3555
|
+
* output bundle and this function returns `undefined`.
|
|
3556
|
+
* @param instance any object that may or may not contain methods
|
|
3557
|
+
* @param method method name
|
|
3558
|
+
* @param arg single arbitrary argument
|
|
3559
|
+
* @param elm the element which made the call
|
|
3560
|
+
* @returns result of method call if it exists, otherwise `undefined`
|
|
3561
|
+
*/
|
|
3562
|
+
const safeCall = (instance, method, arg, elm) => {
|
|
3563
|
+
if (instance && instance[method]) try {
|
|
3564
|
+
return instance[method](arg);
|
|
3565
|
+
} catch (e) {
|
|
3566
|
+
consoleError(e, elm);
|
|
3567
|
+
}
|
|
3568
|
+
};
|
|
3569
|
+
/**
|
|
3570
|
+
* For debugging purposes as `BUILD.lifecycleDOMEvents` is `false` by default and will
|
|
3571
|
+
* get removed by the compiler. Used for timing events to see how long they take.
|
|
3572
|
+
* @param elm the target of the Event
|
|
3573
|
+
* @param lifecycleName name of the event
|
|
3574
|
+
*/
|
|
3575
|
+
const emitLifecycleEvent = (elm, lifecycleName) => {
|
|
3576
|
+
if (BUILD.lifecycleDOMEvents) emitEvent(elm, "stencil_" + lifecycleName, {
|
|
3577
|
+
bubbles: true,
|
|
3578
|
+
composed: true,
|
|
3579
|
+
detail: { namespace: NAMESPACE }
|
|
3580
|
+
});
|
|
3581
|
+
};
|
|
3582
|
+
/**
|
|
3583
|
+
* Set the hydrated flag on a DOM element
|
|
3584
|
+
*
|
|
3585
|
+
* @param elm a reference to a DOM element
|
|
3586
|
+
* @returns undefined
|
|
3587
|
+
*/
|
|
3588
|
+
const addHydratedFlag = (elm) => BUILD.hydratedClass ? elm.classList.add(BUILD.hydratedSelectorName ?? "hydrated") : BUILD.hydratedAttribute ? elm.setAttribute(BUILD.hydratedSelectorName ?? "hydrated", "") : void 0;
|
|
3589
|
+
const serverSideConnected = (elm) => {
|
|
3590
|
+
const children = elm.children;
|
|
3591
|
+
if (children != null) for (let i = 0, ii = children.length; i < ii; i++) {
|
|
3592
|
+
const childElm = children[i];
|
|
3593
|
+
if (typeof childElm.connectedCallback === "function") childElm.connectedCallback();
|
|
3594
|
+
serverSideConnected(childElm);
|
|
3595
|
+
}
|
|
3596
|
+
};
|
|
3597
|
+
|
|
3598
|
+
//#endregion
|
|
3599
|
+
//#region src/runtime/set-value.ts
|
|
3600
|
+
const getValue = (ref, propName) => getHostRef(ref).$instanceValues$.get(propName);
|
|
3601
|
+
const setValue = (ref, propName, newVal, cmpMeta) => {
|
|
3602
|
+
const hostRef = getHostRef(ref);
|
|
3603
|
+
if (!hostRef) return;
|
|
3604
|
+
/**
|
|
3605
|
+
* If the host element is not found, let's fail with a better error message and provide
|
|
3606
|
+
* details on why this may happen. In certain cases, e.g. see https://github.com/stenciljs/core/issues/5457,
|
|
3607
|
+
* users might import a component through e.g. a loader script, which causes confusions in runtime
|
|
3608
|
+
* as there are multiple runtimes being loaded and/or different components used with different
|
|
3609
|
+
* loading strategies, e.g. lazy vs implicitly loaded.
|
|
3610
|
+
*
|
|
3611
|
+
* Todo(STENCIL-1308): remove, once a solution for this was identified and implemented
|
|
3612
|
+
*/
|
|
3613
|
+
if (BUILD.lazyLoad && !hostRef) throw new Error(`Couldn't find host element for "${cmpMeta.$tagName$}" as it is unknown to this Stencil runtime. This usually happens when integrating a 3rd party Stencil component with another Stencil component or application. Please reach out to the maintainers of the 3rd party Stencil component or report this on the Stencil Discord server (https://chat.stenciljs.com) or comment on this similar [GitHub issue](https://github.com/stenciljs/core/issues/5457).`);
|
|
3614
|
+
if (BUILD.serializer && hostRef.$serializerValues$.has(propName) && hostRef.$serializerValues$.get(propName) === newVal) return;
|
|
3615
|
+
const elm = BUILD.lazyLoad ? hostRef.$hostElement$ : ref;
|
|
3616
|
+
const oldVal = hostRef.$instanceValues$.get(propName);
|
|
3617
|
+
const flags = hostRef.$flags$;
|
|
3618
|
+
const instance = BUILD.lazyLoad ? hostRef.$lazyInstance$ : elm;
|
|
3619
|
+
newVal = parsePropertyValue(newVal, cmpMeta.$members$[propName][0], BUILD.formAssociated && !!(cmpMeta.$flags$ & CMP_FLAGS.formAssociated));
|
|
3620
|
+
const didValueChange = newVal !== oldVal && !(Number.isNaN(oldVal) && Number.isNaN(newVal));
|
|
3621
|
+
if ((!BUILD.lazyLoad || !(flags & HOST_FLAGS.isConstructingInstance) || oldVal === void 0) && didValueChange) {
|
|
3622
|
+
hostRef.$instanceValues$.set(propName, newVal);
|
|
3623
|
+
if (BUILD.serializer && BUILD.reflect && cmpMeta.$attrsToReflect$) {
|
|
3624
|
+
if (cmpMeta.$serializers$ && cmpMeta.$serializers$[propName]) {
|
|
3625
|
+
const runSerializer = (inst) => {
|
|
3626
|
+
let attrVal = newVal;
|
|
3627
|
+
for (const serializer of cmpMeta.$serializers$[propName]) {
|
|
3628
|
+
const [[methodName]] = Object.entries(serializer);
|
|
3629
|
+
attrVal = inst[methodName](attrVal, propName);
|
|
3630
|
+
}
|
|
3631
|
+
hostRef.$serializerValues$.set(propName, attrVal);
|
|
3632
|
+
};
|
|
3633
|
+
if (instance) runSerializer(instance);
|
|
3634
|
+
else hostRef.$fetchedCbList$.push(() => {
|
|
3635
|
+
runSerializer(hostRef.$lazyInstance$);
|
|
3636
|
+
});
|
|
3637
|
+
}
|
|
3638
|
+
}
|
|
3639
|
+
if (BUILD.isDev) {
|
|
3640
|
+
if (hostRef.$flags$ & HOST_FLAGS.devOnRender) consoleDevWarn(`The state/prop "${propName}" changed during rendering. This can potentially lead to infinite-loops and other bugs.`, "\nElement", elm, "\nNew value", newVal, "\nOld value", oldVal);
|
|
3641
|
+
else if (hostRef.$flags$ & HOST_FLAGS.devOnDidLoad) consoleDevWarn(`The state/prop "${propName}" changed during "componentDidLoad()", this triggers extra re-renders, try to setup on "componentWillLoad()"`, "\nElement", elm, "\nNew value", newVal, "\nOld value", oldVal);
|
|
3642
|
+
}
|
|
3643
|
+
if (BUILD.propChangeCallback && cmpMeta.$watchers$) {
|
|
3644
|
+
const watchMethods = cmpMeta.$watchers$[propName];
|
|
3645
|
+
if (watchMethods) watchMethods.map((watcher) => {
|
|
3646
|
+
try {
|
|
3647
|
+
const [[watchMethodName, watcherFlags]] = Object.entries(watcher);
|
|
3648
|
+
if (flags & HOST_FLAGS.isWatchReady || watcherFlags & WATCH_FLAGS.Immediate) if (!instance) hostRef.$fetchedCbList$.push(() => {
|
|
3649
|
+
hostRef.$lazyInstance$[watchMethodName](newVal, oldVal, propName);
|
|
3650
|
+
});
|
|
3651
|
+
else instance[watchMethodName](newVal, oldVal, propName);
|
|
3652
|
+
} catch (e) {
|
|
3653
|
+
consoleError(e, elm);
|
|
3654
|
+
}
|
|
3655
|
+
});
|
|
3656
|
+
}
|
|
3657
|
+
if (BUILD.updatable && flags & HOST_FLAGS.hasRendered) {
|
|
3658
|
+
if (instance.componentShouldUpdate) {
|
|
3659
|
+
if (instance.componentShouldUpdate(newVal, oldVal, propName) === false && !(flags & HOST_FLAGS.isQueuedForUpdate)) return;
|
|
3660
|
+
}
|
|
3661
|
+
if (!(flags & HOST_FLAGS.isQueuedForUpdate)) scheduleUpdate(hostRef, false);
|
|
3662
|
+
}
|
|
3663
|
+
}
|
|
3664
|
+
};
|
|
3665
|
+
|
|
3666
|
+
//#endregion
|
|
3667
|
+
//#region src/runtime/proxy-component.ts
|
|
3668
|
+
/**
|
|
3669
|
+
* Attach a series of runtime constructs to a compiled Stencil component
|
|
3670
|
+
* constructor, including getters and setters for the `@Prop` and `@State`
|
|
3671
|
+
* decorators, callbacks for when attributes change, and so on.
|
|
3672
|
+
*
|
|
3673
|
+
* On a lazy loaded component, this is wired up to both the class instance
|
|
3674
|
+
* and the element separately. A `hostRef` keeps the 2 in sync.
|
|
3675
|
+
*
|
|
3676
|
+
* On a traditional component, this is wired up to the element only.
|
|
3677
|
+
*
|
|
3678
|
+
* @param Cstr the constructor for a component that we need to process
|
|
3679
|
+
* @param cmpMeta metadata collected previously about the component
|
|
3680
|
+
* @param flags a number used to store a series of bit flags
|
|
3681
|
+
* @returns a reference to the same constructor passed in (but now mutated)
|
|
3682
|
+
*/
|
|
3683
|
+
const proxyComponent = (Cstr, cmpMeta, flags) => {
|
|
3684
|
+
const prototype = Cstr.prototype;
|
|
3685
|
+
if (BUILD.isTesting) {
|
|
3686
|
+
if (prototype.__stencilAugmented) return;
|
|
3687
|
+
prototype.__stencilAugmented = true;
|
|
3688
|
+
}
|
|
3689
|
+
/**
|
|
3690
|
+
* proxy form associated custom element lifecycle callbacks
|
|
3691
|
+
* @ref https://web.dev/articles/more-capable-form-controls#lifecycle_callbacks
|
|
3692
|
+
*/
|
|
3693
|
+
if (BUILD.formAssociated && cmpMeta.$flags$ & CMP_FLAGS.formAssociated && flags & PROXY_FLAGS.isElementConstructor) FORM_ASSOCIATED_CUSTOM_ELEMENT_CALLBACKS.forEach((cbName) => {
|
|
3694
|
+
const originalFormAssociatedCallback = prototype[cbName];
|
|
3695
|
+
Object.defineProperty(prototype, cbName, { value(...args) {
|
|
3696
|
+
const hostRef = getHostRef(this);
|
|
3697
|
+
const instance = BUILD.lazyLoad ? hostRef?.$lazyInstance$ : this;
|
|
3698
|
+
if (!instance) hostRef?.$onReadyPromise$?.then((asyncInstance) => {
|
|
3699
|
+
const cb = asyncInstance[cbName];
|
|
3700
|
+
typeof cb === "function" && cb.call(asyncInstance, ...args);
|
|
3701
|
+
});
|
|
3702
|
+
else {
|
|
3703
|
+
const cb = BUILD.lazyLoad ? instance[cbName] : originalFormAssociatedCallback;
|
|
3704
|
+
typeof cb === "function" && cb.call(instance, ...args);
|
|
3705
|
+
}
|
|
3706
|
+
} });
|
|
3707
|
+
});
|
|
3708
|
+
if (BUILD.member && cmpMeta.$members$ || BUILD.propChangeCallback) {
|
|
3709
|
+
if (BUILD.propChangeCallback) {
|
|
3710
|
+
if (Cstr.watchers && !cmpMeta.$watchers$) cmpMeta.$watchers$ = Cstr.watchers;
|
|
3711
|
+
if (Cstr.deserializers && !cmpMeta.$deserializers$) cmpMeta.$deserializers$ = Cstr.deserializers;
|
|
3712
|
+
if (Cstr.serializers && !cmpMeta.$serializers$) cmpMeta.$serializers$ = Cstr.serializers;
|
|
3713
|
+
}
|
|
3714
|
+
const members = Object.entries(cmpMeta.$members$ ?? {});
|
|
3715
|
+
members.map(([memberName, [memberFlags]]) => {
|
|
3716
|
+
if ((BUILD.prop || BUILD.state) && (memberFlags & MEMBER_FLAGS.Prop || (!BUILD.lazyLoad || flags & PROXY_FLAGS.proxyState) && memberFlags & MEMBER_FLAGS.State)) {
|
|
3717
|
+
const { get: origGetter, set: origSetter } = getPropertyDescriptor(prototype, memberName) || {};
|
|
3718
|
+
if (origGetter) cmpMeta.$members$[memberName][0] |= MEMBER_FLAGS.Getter;
|
|
3719
|
+
if (origSetter) cmpMeta.$members$[memberName][0] |= MEMBER_FLAGS.Setter;
|
|
3720
|
+
if (flags & PROXY_FLAGS.isElementConstructor || !origGetter) Object.defineProperty(prototype, memberName, {
|
|
3721
|
+
get() {
|
|
3722
|
+
if (BUILD.lazyLoad) {
|
|
3723
|
+
if ((cmpMeta.$members$[memberName][0] & MEMBER_FLAGS.Getter) === 0) return getValue(this, memberName);
|
|
3724
|
+
const ref = getHostRef(this);
|
|
3725
|
+
const instance = ref ? ref.$lazyInstance$ : prototype;
|
|
3726
|
+
if (!instance) return;
|
|
3727
|
+
return instance[memberName];
|
|
3728
|
+
}
|
|
3729
|
+
if (!BUILD.lazyLoad) return origGetter ? origGetter.apply(this) : getValue(this, memberName);
|
|
3730
|
+
},
|
|
3731
|
+
configurable: true,
|
|
3732
|
+
enumerable: true
|
|
3733
|
+
});
|
|
3734
|
+
Object.defineProperty(prototype, memberName, { set(newValue) {
|
|
3735
|
+
const ref = getHostRef(this);
|
|
3736
|
+
if (!ref) return;
|
|
3737
|
+
if (BUILD.isDev) {
|
|
3738
|
+
if ((flags & PROXY_FLAGS.isElementConstructor) === 0 && (cmpMeta.$members$[memberName][0] & MEMBER_FLAGS.Setter) === 0 && (ref && ref.$flags$ & HOST_FLAGS.isConstructingInstance) === 0 && (memberFlags & MEMBER_FLAGS.Prop) !== 0 && (memberFlags & MEMBER_FLAGS.Mutable) === 0) consoleDevWarn(`@Prop() "${memberName}" on <${cmpMeta.$tagName$}> is immutable but was modified from within the component.\nMore information: https://stenciljs.com/docs/properties#prop-mutability`);
|
|
3739
|
+
}
|
|
3740
|
+
if (origSetter) {
|
|
3741
|
+
if (typeof (memberFlags & MEMBER_FLAGS.State ? this[memberName] : ref.$hostElement$[memberName]) === "undefined" && ref.$instanceValues$.get(memberName)) newValue = ref.$instanceValues$.get(memberName);
|
|
3742
|
+
origSetter.apply(this, [parsePropertyValue(newValue, memberFlags, BUILD.formAssociated && !!(cmpMeta.$flags$ & CMP_FLAGS.formAssociated))]);
|
|
3743
|
+
newValue = memberFlags & MEMBER_FLAGS.State ? this[memberName] : ref.$hostElement$[memberName];
|
|
3744
|
+
setValue(this, memberName, newValue, cmpMeta);
|
|
3745
|
+
return;
|
|
3746
|
+
}
|
|
3747
|
+
if (!BUILD.lazyLoad) {
|
|
3748
|
+
setValue(this, memberName, newValue, cmpMeta);
|
|
3749
|
+
return;
|
|
3750
|
+
}
|
|
3751
|
+
if (BUILD.lazyLoad) {
|
|
3752
|
+
if ((flags & PROXY_FLAGS.isElementConstructor) === 0 || (cmpMeta.$members$[memberName][0] & MEMBER_FLAGS.Setter) === 0) {
|
|
3753
|
+
setValue(this, memberName, newValue, cmpMeta);
|
|
3754
|
+
if (flags & PROXY_FLAGS.isElementConstructor && !ref.$lazyInstance$) ref.$fetchedCbList$.push(() => {
|
|
3755
|
+
if (cmpMeta.$members$[memberName][0] & MEMBER_FLAGS.Setter && ref.$lazyInstance$[memberName] !== ref.$instanceValues$.get(memberName)) ref.$lazyInstance$[memberName] = newValue;
|
|
3756
|
+
});
|
|
3757
|
+
return;
|
|
3758
|
+
}
|
|
3759
|
+
const setterSetVal = () => {
|
|
3760
|
+
const currentValue = ref.$lazyInstance$[memberName];
|
|
3761
|
+
if (!ref.$instanceValues$.get(memberName) && currentValue) ref.$instanceValues$.set(memberName, currentValue);
|
|
3762
|
+
ref.$lazyInstance$[memberName] = parsePropertyValue(newValue, memberFlags, BUILD.formAssociated && !!(cmpMeta.$flags$ & CMP_FLAGS.formAssociated));
|
|
3763
|
+
setValue(this, memberName, ref.$lazyInstance$[memberName], cmpMeta);
|
|
3764
|
+
};
|
|
3765
|
+
if (ref.$lazyInstance$) setterSetVal();
|
|
3766
|
+
else ref.$fetchedCbList$.push(() => {
|
|
3767
|
+
setterSetVal();
|
|
3768
|
+
});
|
|
3769
|
+
}
|
|
3770
|
+
} });
|
|
3771
|
+
} else if (BUILD.lazyLoad && BUILD.method && flags & PROXY_FLAGS.isElementConstructor && memberFlags & MEMBER_FLAGS.Method) Object.defineProperty(prototype, memberName, { value(...args) {
|
|
3772
|
+
const ref = getHostRef(this);
|
|
3773
|
+
return ref?.$onInstancePromise$?.then(() => ref.$lazyInstance$?.[memberName](...args));
|
|
3774
|
+
} });
|
|
3775
|
+
});
|
|
3776
|
+
if (BUILD.observeAttribute && (!BUILD.lazyLoad || flags & PROXY_FLAGS.isElementConstructor)) {
|
|
3777
|
+
const attrNameToPropName = /* @__PURE__ */ new Map();
|
|
3778
|
+
prototype.attributeChangedCallback = function(attrName, oldValue, newValue) {
|
|
3779
|
+
plt.jmp(() => {
|
|
3780
|
+
const propName = attrNameToPropName.get(attrName);
|
|
3781
|
+
const hostRef = getHostRef(this);
|
|
3782
|
+
if (BUILD.serializer && hostRef.$serializerValues$.has(propName) && hostRef.$serializerValues$.get(propName) === newValue) return;
|
|
3783
|
+
if (this.hasOwnProperty(propName) && BUILD.lazyLoad) {
|
|
3784
|
+
newValue = this[propName];
|
|
3785
|
+
delete this[propName];
|
|
3786
|
+
}
|
|
3787
|
+
if (BUILD.deserializer && cmpMeta.$deserializers$ && cmpMeta.$deserializers$[propName]) {
|
|
3788
|
+
const setVal = (methodName, instance) => {
|
|
3789
|
+
const deserializeVal = instance?.[methodName](newValue, propName);
|
|
3790
|
+
if (deserializeVal !== this[propName]) this[propName] = deserializeVal;
|
|
3791
|
+
};
|
|
3792
|
+
for (const deserializer of cmpMeta.$deserializers$[propName]) {
|
|
3793
|
+
const [[methodName]] = Object.entries(deserializer);
|
|
3794
|
+
if (BUILD.lazyLoad) if (hostRef.$lazyInstance$) setVal(methodName, hostRef.$lazyInstance$);
|
|
3795
|
+
else hostRef.$fetchedCbList$.push(() => {
|
|
3796
|
+
setVal(methodName, hostRef.$lazyInstance$);
|
|
3797
|
+
});
|
|
3798
|
+
else setVal(methodName, this);
|
|
3799
|
+
}
|
|
3800
|
+
return;
|
|
3801
|
+
} else if (prototype.hasOwnProperty(propName) && typeof this[propName] === "number" && this[propName] == newValue) return;
|
|
3802
|
+
else if (propName == null) {
|
|
3803
|
+
const flags = hostRef?.$flags$;
|
|
3804
|
+
if (hostRef && flags && !(flags & HOST_FLAGS.isConstructingInstance) && newValue !== oldValue) {
|
|
3805
|
+
const elm = BUILD.lazyLoad ? hostRef.$hostElement$ : this;
|
|
3806
|
+
const instance = BUILD.lazyLoad ? hostRef.$lazyInstance$ : elm;
|
|
3807
|
+
(cmpMeta.$watchers$?.[attrName])?.forEach((watcher) => {
|
|
3808
|
+
const [[watchMethodName, watcherFlags]] = Object.entries(watcher);
|
|
3809
|
+
if (instance[watchMethodName] != null && (flags & HOST_FLAGS.isWatchReady || watcherFlags & WATCH_FLAGS.Immediate)) instance[watchMethodName].call(instance, newValue, oldValue, attrName);
|
|
3810
|
+
});
|
|
3811
|
+
}
|
|
3812
|
+
return;
|
|
3813
|
+
}
|
|
3814
|
+
const propFlags = members.find(([m]) => m === propName);
|
|
3815
|
+
if (propFlags && propFlags[1][0] & MEMBER_FLAGS.Boolean) newValue = newValue === null || newValue === "false" ? false : true;
|
|
3816
|
+
const propDesc = Object.getOwnPropertyDescriptor(prototype, propName);
|
|
3817
|
+
if (newValue != this[propName] && (!propDesc.get || !!propDesc.set)) this[propName] = newValue;
|
|
3818
|
+
});
|
|
3819
|
+
};
|
|
3820
|
+
Cstr.observedAttributes = Array.from(new Set([...Object.keys(cmpMeta.$watchers$ ?? {}), ...members.filter(([_, m]) => m[0] & MEMBER_FLAGS.HasAttribute).map(([propName, m]) => {
|
|
3821
|
+
const attrName = m[1] || propName;
|
|
3822
|
+
attrNameToPropName.set(attrName, propName);
|
|
3823
|
+
if (BUILD.reflect && m[0] & MEMBER_FLAGS.ReflectAttr) cmpMeta.$attrsToReflect$?.push([propName, attrName]);
|
|
3824
|
+
return attrName;
|
|
3825
|
+
})]));
|
|
3826
|
+
}
|
|
3827
|
+
}
|
|
3828
|
+
return Cstr;
|
|
3829
|
+
};
|
|
3830
|
+
|
|
3831
|
+
//#endregion
|
|
3832
|
+
//#region src/runtime/initialize-component.ts
|
|
3833
|
+
/**
|
|
3834
|
+
* Initialize a Stencil component given a reference to its host element, its
|
|
3835
|
+
* runtime bookkeeping data structure, runtime metadata about the component,
|
|
3836
|
+
* and (optionally) an HMR version ID.
|
|
3837
|
+
*
|
|
3838
|
+
* @param elm a host element
|
|
3839
|
+
* @param hostRef the element's runtime bookkeeping object
|
|
3840
|
+
* @param cmpMeta runtime metadata for the Stencil component
|
|
3841
|
+
* @param hmrVersionId an (optional) HMR version ID
|
|
3842
|
+
*/
|
|
3843
|
+
const initializeComponent = async (elm, hostRef, cmpMeta, hmrVersionId) => {
|
|
3844
|
+
let Cstr;
|
|
3845
|
+
try {
|
|
3846
|
+
if ((hostRef.$flags$ & HOST_FLAGS.hasInitializedComponent) === 0) {
|
|
3847
|
+
hostRef.$flags$ |= HOST_FLAGS.hasInitializedComponent;
|
|
3848
|
+
const bundleId = cmpMeta.$lazyBundleId$;
|
|
3849
|
+
if (BUILD.lazyLoad && bundleId) {
|
|
3850
|
+
const CstrImport = loadModule(cmpMeta, hostRef, hmrVersionId);
|
|
3851
|
+
if (CstrImport && "then" in CstrImport) {
|
|
3852
|
+
const endLoad = uniqueTime(`st:load:${cmpMeta.$tagName$}:${hostRef.$modeName$}`, `[Stencil] Load module for <${cmpMeta.$tagName$}>`);
|
|
3853
|
+
Cstr = await CstrImport;
|
|
3854
|
+
endLoad();
|
|
3855
|
+
} else Cstr = CstrImport;
|
|
3856
|
+
if (!Cstr) throw new Error(`Constructor for "${cmpMeta.$tagName$}#${hostRef.$modeName$}" was not found`);
|
|
3857
|
+
if (BUILD.member && !Cstr.isProxied) {
|
|
3858
|
+
if (BUILD.propChangeCallback) {
|
|
3859
|
+
cmpMeta.$watchers$ = Cstr.watchers;
|
|
3860
|
+
cmpMeta.$serializers$ = Cstr.serializers;
|
|
3861
|
+
cmpMeta.$deserializers$ = Cstr.deserializers;
|
|
3862
|
+
}
|
|
3863
|
+
proxyComponent(Cstr, cmpMeta, PROXY_FLAGS.proxyState);
|
|
3864
|
+
Cstr.isProxied = true;
|
|
3865
|
+
}
|
|
3866
|
+
const endNewInstance = createTime("createInstance", cmpMeta.$tagName$);
|
|
3867
|
+
if (BUILD.member) hostRef.$flags$ |= HOST_FLAGS.isConstructingInstance;
|
|
3868
|
+
try {
|
|
3869
|
+
new Cstr(hostRef);
|
|
3870
|
+
} catch (e) {
|
|
3871
|
+
consoleError(e, elm);
|
|
3872
|
+
}
|
|
3873
|
+
if (BUILD.member) hostRef.$flags$ &= ~HOST_FLAGS.isConstructingInstance;
|
|
3874
|
+
if (BUILD.propChangeCallback) hostRef.$flags$ |= HOST_FLAGS.isWatchReady;
|
|
3875
|
+
endNewInstance();
|
|
3876
|
+
if (!(BUILD.slotRelocation && cmpMeta.$flags$ & CMP_FLAGS.hasSlotRelocation)) fireConnectedCallback(hostRef.$lazyInstance$, elm);
|
|
3877
|
+
else hostRef.$deferredConnectedCallback$ = true;
|
|
3878
|
+
} else {
|
|
3879
|
+
Cstr = elm.constructor;
|
|
3880
|
+
/**
|
|
3881
|
+
* Instead of using e.g. `cmpMeta.$tagName$` we use `elm.localName` to get the tag name of the component.
|
|
3882
|
+
* This is because we can't guarantee that the component class is actually registered with the tag name
|
|
3883
|
+
* defined in the component class as users can very well also do this:
|
|
3884
|
+
*
|
|
3885
|
+
* ```html
|
|
3886
|
+
* <script type="module">
|
|
3887
|
+
* import { MyComponent } from 'my-stencil-component-library';
|
|
3888
|
+
* customElements.define('my-other-component', MyComponent);
|
|
3889
|
+
* <\/script>
|
|
3890
|
+
* ```
|
|
3891
|
+
*/
|
|
3892
|
+
const cmpTag = elm.localName;
|
|
3893
|
+
customElements.whenDefined(cmpTag).then(() => hostRef.$flags$ |= HOST_FLAGS.isWatchReady);
|
|
3894
|
+
}
|
|
3895
|
+
if (BUILD.style && Cstr && Cstr.style) {
|
|
3896
|
+
/**
|
|
3897
|
+
* this component has styles but we haven't registered them yet
|
|
3898
|
+
*/
|
|
3899
|
+
let style;
|
|
3900
|
+
if (typeof Cstr.style === "string")
|
|
3901
|
+
/**
|
|
3902
|
+
* in case the component has a `styleUrl` defined, e.g.
|
|
3903
|
+
* ```ts
|
|
3904
|
+
* @Component({
|
|
3905
|
+
* tag: 'my-component',
|
|
3906
|
+
* styleUrl: 'my-component.css'
|
|
3907
|
+
* })
|
|
3908
|
+
* ```
|
|
3909
|
+
*/
|
|
3910
|
+
style = Cstr.style;
|
|
3911
|
+
else if (BUILD.mode && typeof Cstr.style !== "string") {
|
|
3912
|
+
/**
|
|
3913
|
+
* in case the component has a `styleUrl` object defined, e.g.
|
|
3914
|
+
* ```ts
|
|
3915
|
+
* @Component({
|
|
3916
|
+
* tag: 'my-component',
|
|
3917
|
+
* styleUrl: {
|
|
3918
|
+
* ios: 'my-component.ios.css',
|
|
3919
|
+
* md: 'my-component.md.css'
|
|
3920
|
+
* }
|
|
3921
|
+
* })
|
|
3922
|
+
* ```
|
|
3923
|
+
*/
|
|
3924
|
+
hostRef.$modeName$ = computeMode(elm);
|
|
3925
|
+
if (hostRef.$modeName$) style = Cstr.style[hostRef.$modeName$];
|
|
3926
|
+
if (BUILD.hydrateServerSide && hostRef.$modeName$) elm.setAttribute("s-mode", hostRef.$modeName$);
|
|
3927
|
+
}
|
|
3928
|
+
const scopeId = getScopeId(cmpMeta, hostRef.$modeName$);
|
|
3929
|
+
if (!styles.has(scopeId) || BUILD.hotModuleReplacement && hmrVersionId) {
|
|
3930
|
+
const endRegisterStyles = createTime("registerStyles", cmpMeta.$tagName$);
|
|
3931
|
+
if (BUILD.hydrateServerSide && BUILD.shadowDom) {
|
|
3932
|
+
if (cmpMeta.$flags$ & CMP_FLAGS.shadowNeedsScopedCss) style = scopeCss(style, scopeId, true);
|
|
3933
|
+
else if (needsScopedSSR()) style = expandPartSelectors(style);
|
|
3934
|
+
}
|
|
3935
|
+
registerStyle(scopeId, style, !!(cmpMeta.$flags$ & CMP_FLAGS.shadowDomEncapsulation));
|
|
3936
|
+
endRegisterStyles();
|
|
3937
|
+
}
|
|
3938
|
+
}
|
|
3939
|
+
}
|
|
3940
|
+
const ancestorComponent = hostRef.$ancestorComponent$;
|
|
3941
|
+
const schedule = () => scheduleUpdate(hostRef, true);
|
|
3942
|
+
if (BUILD.asyncLoading && ancestorComponent && ancestorComponent["s-rc"]) ancestorComponent["s-rc"].push(schedule);
|
|
3943
|
+
else schedule();
|
|
3944
|
+
} catch (e) {
|
|
3945
|
+
consoleError(e, elm);
|
|
3946
|
+
if (BUILD.asyncLoading && hostRef.$onRenderResolve$) {
|
|
3947
|
+
hostRef.$onRenderResolve$();
|
|
3948
|
+
hostRef.$onRenderResolve$ = void 0;
|
|
3949
|
+
}
|
|
3950
|
+
if (BUILD.asyncLoading && hostRef.$onReadyResolve$) hostRef.$onReadyResolve$(elm);
|
|
3951
|
+
}
|
|
3952
|
+
};
|
|
3953
|
+
const fireConnectedCallback = (instance, elm) => {
|
|
3954
|
+
if (BUILD.lazyLoad) safeCall(instance, "connectedCallback", void 0, elm);
|
|
3955
|
+
};
|
|
3956
|
+
|
|
3957
|
+
//#endregion
|
|
3958
|
+
//#region src/runtime/connected-callback.ts
|
|
3959
|
+
const connectedCallback = (elm) => {
|
|
3960
|
+
if ((plt.$flags$ & PLATFORM_FLAGS.isTmpDisconnected) === 0) {
|
|
3961
|
+
const hostRef = getHostRef(elm);
|
|
3962
|
+
if (!hostRef) return;
|
|
3963
|
+
const cmpMeta = hostRef.$cmpMeta$;
|
|
3964
|
+
const endConnected = createTime("connectedCallback", cmpMeta.$tagName$);
|
|
3965
|
+
if (BUILD.hostListenerTargetParent) addHostEventListeners(elm, hostRef, cmpMeta.$listeners$, true);
|
|
3966
|
+
if (!(hostRef.$flags$ & HOST_FLAGS.hasConnected)) {
|
|
3967
|
+
hostRef.$flags$ |= HOST_FLAGS.hasConnected;
|
|
3968
|
+
let hostId;
|
|
3969
|
+
if (BUILD.hydrateClientSide) {
|
|
3970
|
+
hostId = elm.getAttribute(HYDRATE_ID);
|
|
3971
|
+
if (hostId) {
|
|
3972
|
+
if (BUILD.shadowDom && supportsShadow && cmpMeta.$flags$ & CMP_FLAGS.shadowDomEncapsulation) {
|
|
3973
|
+
const scopeId = BUILD.mode ? addStyle(elm.shadowRoot, cmpMeta, elm.getAttribute("s-mode")) : addStyle(elm.shadowRoot, cmpMeta);
|
|
3974
|
+
elm.classList.remove(scopeId + "-h", scopeId + "-s");
|
|
3975
|
+
} else if (BUILD.scoped && cmpMeta.$flags$ & CMP_FLAGS.scopedCssEncapsulation) elm["s-sc"] = getScopeId(cmpMeta, BUILD.mode ? elm.getAttribute("s-mode") : void 0);
|
|
3976
|
+
initializeClientHydrate(elm, cmpMeta.$tagName$, hostId, hostRef);
|
|
3977
|
+
}
|
|
3978
|
+
}
|
|
3979
|
+
if (BUILD.slotRelocation && !hostId) {
|
|
3980
|
+
if (BUILD.hydrateServerSide || (BUILD.slot || BUILD.shadowDom) && cmpMeta.$flags$ & (CMP_FLAGS.hasSlotRelocation | CMP_FLAGS.needsShadowDomShim)) setContentReference(elm);
|
|
3981
|
+
}
|
|
3982
|
+
if (BUILD.asyncLoading) {
|
|
3983
|
+
let ancestorComponent = elm;
|
|
3984
|
+
while (ancestorComponent = ancestorComponent.parentNode || ancestorComponent.host) if (BUILD.hydrateClientSide && ancestorComponent.nodeType === NODE_TYPE.ElementNode && ancestorComponent.hasAttribute("s-id") && ancestorComponent["s-p"] || ancestorComponent["s-p"]) {
|
|
3985
|
+
attachToAncestor(hostRef, hostRef.$ancestorComponent$ = ancestorComponent);
|
|
3986
|
+
break;
|
|
3987
|
+
}
|
|
3988
|
+
}
|
|
3989
|
+
if (BUILD.prop && !BUILD.hydrateServerSide && cmpMeta.$members$) Object.entries(cmpMeta.$members$).map(([memberName, [memberFlags]]) => {
|
|
3990
|
+
if (memberFlags & MEMBER_FLAGS.Prop && Object.prototype.hasOwnProperty.call(elm, memberName)) {
|
|
3991
|
+
const value = elm[memberName];
|
|
3992
|
+
delete elm[memberName];
|
|
3993
|
+
elm[memberName] = value;
|
|
3994
|
+
}
|
|
3995
|
+
});
|
|
3996
|
+
if (BUILD.initializeNextTick) nextTick(() => initializeComponent(elm, hostRef, cmpMeta));
|
|
3997
|
+
else initializeComponent(elm, hostRef, cmpMeta);
|
|
3998
|
+
} else {
|
|
3999
|
+
addHostEventListeners(elm, hostRef, cmpMeta.$listeners$, false);
|
|
4000
|
+
if (hostRef?.$lazyInstance$) fireConnectedCallback(hostRef.$lazyInstance$, elm);
|
|
4001
|
+
else if (hostRef?.$onReadyPromise$) hostRef.$onReadyPromise$.then(() => fireConnectedCallback(hostRef.$lazyInstance$, elm));
|
|
4002
|
+
}
|
|
4003
|
+
endConnected();
|
|
4004
|
+
}
|
|
4005
|
+
};
|
|
4006
|
+
const setContentReference = (elm) => {
|
|
4007
|
+
if (!win.document) return;
|
|
4008
|
+
const contentRefElm = elm["s-cr"] = win.document.createComment(BUILD.isDebug ? `content-ref (host=${elm.localName})` : "");
|
|
4009
|
+
contentRefElm["s-cn"] = true;
|
|
4010
|
+
insertBefore(elm, contentRefElm, elm.firstChild);
|
|
4011
|
+
};
|
|
4012
|
+
|
|
4013
|
+
//#endregion
|
|
4014
|
+
//#region src/runtime/disconnected-callback.ts
|
|
4015
|
+
const disconnectInstance = (instance, elm) => {
|
|
4016
|
+
if (BUILD.lazyLoad) safeCall(instance, "disconnectedCallback", void 0, elm || instance);
|
|
4017
|
+
};
|
|
4018
|
+
const disconnectedCallback = async (elm) => {
|
|
4019
|
+
if ((plt.$flags$ & PLATFORM_FLAGS.isTmpDisconnected) === 0) {
|
|
4020
|
+
const hostRef = getHostRef(elm);
|
|
4021
|
+
if (BUILD.hostListener) {
|
|
4022
|
+
if (hostRef?.$rmListeners$) {
|
|
4023
|
+
hostRef.$rmListeners$.map((rmListener) => rmListener());
|
|
4024
|
+
hostRef.$rmListeners$ = void 0;
|
|
4025
|
+
}
|
|
4026
|
+
}
|
|
4027
|
+
if (!BUILD.lazyLoad) disconnectInstance(elm);
|
|
4028
|
+
else if (hostRef?.$lazyInstance$) disconnectInstance(hostRef.$lazyInstance$, elm);
|
|
4029
|
+
else if (hostRef?.$onReadyPromise$) hostRef.$onReadyPromise$.then(() => disconnectInstance(hostRef.$lazyInstance$, elm));
|
|
4030
|
+
}
|
|
4031
|
+
/**
|
|
4032
|
+
* Remove the element from the `rootAppliedStyles` WeakMap
|
|
4033
|
+
*/
|
|
4034
|
+
if (rootAppliedStyles.has(elm)) rootAppliedStyles.delete(elm);
|
|
4035
|
+
/**
|
|
4036
|
+
* Remove the shadow root from the `rootAppliedStyles` WeakMap
|
|
4037
|
+
*/
|
|
4038
|
+
if (elm.shadowRoot && rootAppliedStyles.has(elm.shadowRoot)) rootAppliedStyles.delete(elm.shadowRoot);
|
|
4039
|
+
};
|
|
4040
|
+
|
|
4041
|
+
//#endregion
|
|
4042
|
+
//#region src/runtime/hmr-component.ts
|
|
4043
|
+
/**
|
|
4044
|
+
* Kick off hot-module-replacement for a component. In order to replace the
|
|
4045
|
+
* component in-place we:
|
|
4046
|
+
*
|
|
4047
|
+
* 1. get a reference to the {@link d.HostRef} for the element
|
|
4048
|
+
* 2. reset the element's runtime flags
|
|
4049
|
+
* 3. re-run the initialization logic for the element (via
|
|
4050
|
+
* {@link initializeComponent})
|
|
4051
|
+
*
|
|
4052
|
+
* @param hostElement the host element for the component which we want to start
|
|
4053
|
+
* doing HMR
|
|
4054
|
+
* @param cmpMeta runtime metadata for the component
|
|
4055
|
+
* @param hmrVersionId the current HMR version ID
|
|
4056
|
+
*/
|
|
4057
|
+
const hmrStart = (hostElement, cmpMeta, hmrVersionId) => {
|
|
4058
|
+
const hostRef = getHostRef(hostElement);
|
|
4059
|
+
if (!hostRef) return;
|
|
4060
|
+
hostRef.$flags$ = HOST_FLAGS.hasConnected;
|
|
4061
|
+
initializeComponent(hostElement, hostRef, cmpMeta, hmrVersionId);
|
|
4062
|
+
};
|
|
4063
|
+
|
|
4064
|
+
//#endregion
|
|
4065
|
+
//#region src/runtime/bootstrap-lazy.ts
|
|
4066
|
+
const bootstrapLazy = (lazyBundles, options = {}) => {
|
|
4067
|
+
if (BUILD.profile && performance.mark) performance.mark("st:app:start");
|
|
4068
|
+
installDevTools();
|
|
4069
|
+
if (!win.document) {
|
|
4070
|
+
console.warn("Stencil: No document found. Skipping bootstrapping lazy components.");
|
|
4071
|
+
return;
|
|
4072
|
+
}
|
|
4073
|
+
const endBootstrap = createTime("bootstrapLazy");
|
|
4074
|
+
const cmpTags = [];
|
|
4075
|
+
const exclude = options.exclude || [];
|
|
4076
|
+
const customElements = win.customElements;
|
|
4077
|
+
const head = win.document.head;
|
|
4078
|
+
const metaCharset = /* @__PURE__ */ head.querySelector("meta[charset]");
|
|
4079
|
+
const dataStyles = /* @__PURE__ */ win.document.createElement("style");
|
|
4080
|
+
const deferredConnectedCallbacks = [];
|
|
4081
|
+
let appLoadFallback;
|
|
4082
|
+
let isBootstrapping = true;
|
|
4083
|
+
Object.assign(plt, options);
|
|
4084
|
+
if (BUILD.asyncQueue && options.syncQueue) plt.$flags$ |= PLATFORM_FLAGS.queueSync;
|
|
4085
|
+
if (BUILD.hydrateClientSide) plt.$flags$ |= PLATFORM_FLAGS.appLoaded;
|
|
4086
|
+
if (BUILD.hydrateClientSide && BUILD.shadowDom) hydrateScopedToShadow();
|
|
4087
|
+
let hasSlotRelocation = false;
|
|
4088
|
+
lazyBundles.map((lazyBundle) => {
|
|
4089
|
+
lazyBundle[1].map((compactMeta) => {
|
|
4090
|
+
const cmpMeta = {
|
|
4091
|
+
$flags$: compactMeta[0],
|
|
4092
|
+
$tagName$: compactMeta[1],
|
|
4093
|
+
$members$: compactMeta[2],
|
|
4094
|
+
$listeners$: compactMeta[3]
|
|
4095
|
+
};
|
|
4096
|
+
if (cmpMeta.$flags$ & CMP_FLAGS.hasSlotRelocation) hasSlotRelocation = true;
|
|
4097
|
+
if (BUILD.member) cmpMeta.$members$ = compactMeta[2];
|
|
4098
|
+
if (BUILD.hostListener) cmpMeta.$listeners$ = compactMeta[3];
|
|
4099
|
+
if (BUILD.reflect) cmpMeta.$attrsToReflect$ = [];
|
|
4100
|
+
if (BUILD.propChangeCallback) {
|
|
4101
|
+
cmpMeta.$watchers$ = compactMeta[4] ?? {};
|
|
4102
|
+
cmpMeta.$serializers$ = compactMeta[5] ?? {};
|
|
4103
|
+
cmpMeta.$deserializers$ = compactMeta[6] ?? {};
|
|
4104
|
+
}
|
|
4105
|
+
if (BUILD.shadowDom && !supportsShadow && cmpMeta.$flags$ & CMP_FLAGS.shadowDomEncapsulation) cmpMeta.$flags$ |= CMP_FLAGS.needsShadowDomShim;
|
|
4106
|
+
const tagName = BUILD.transformTagName && options.transformTagName ? options.transformTagName(cmpMeta.$tagName$) : transformTag(cmpMeta.$tagName$);
|
|
4107
|
+
const HostElement = class extends HTMLElement {
|
|
4108
|
+
["s-p"];
|
|
4109
|
+
["s-rc"];
|
|
4110
|
+
hasRegisteredEventListeners = false;
|
|
4111
|
+
constructor(self) {
|
|
4112
|
+
super(self);
|
|
4113
|
+
self = this;
|
|
4114
|
+
registerHost(self, cmpMeta);
|
|
4115
|
+
if (BUILD.shadowDom && cmpMeta.$flags$ & CMP_FLAGS.shadowDomEncapsulation) {
|
|
4116
|
+
if (supportsShadow) {
|
|
4117
|
+
if (!self.shadowRoot) createShadowRoot.call(self, cmpMeta);
|
|
4118
|
+
else if (self.shadowRoot.mode !== "open") throw new Error(`Unable to re-use existing shadow root for ${cmpMeta.$tagName$}! Mode is set to ${self.shadowRoot.mode} but Stencil only supports open shadow roots.`);
|
|
4119
|
+
} else if (!BUILD.hydrateServerSide && !("shadowRoot" in self)) self.shadowRoot = self;
|
|
4120
|
+
}
|
|
4121
|
+
}
|
|
4122
|
+
connectedCallback() {
|
|
4123
|
+
const hostRef = getHostRef(this);
|
|
4124
|
+
if (!hostRef) return;
|
|
4125
|
+
/**
|
|
4126
|
+
* The `connectedCallback` lifecycle event can potentially be fired multiple times
|
|
4127
|
+
* if the element is removed from the DOM and re-inserted. This is not a common use case,
|
|
4128
|
+
* but it can happen in some scenarios. To prevent registering the same event listeners
|
|
4129
|
+
* multiple times, we will only register them once.
|
|
4130
|
+
*/
|
|
4131
|
+
if (!this.hasRegisteredEventListeners) {
|
|
4132
|
+
this.hasRegisteredEventListeners = true;
|
|
4133
|
+
addHostEventListeners(this, hostRef, cmpMeta.$listeners$, false);
|
|
4134
|
+
}
|
|
4135
|
+
if (appLoadFallback) {
|
|
4136
|
+
clearTimeout(appLoadFallback);
|
|
4137
|
+
appLoadFallback = null;
|
|
4138
|
+
}
|
|
4139
|
+
if (isBootstrapping) deferredConnectedCallbacks.push(this);
|
|
4140
|
+
else plt.jmp(() => connectedCallback(this));
|
|
4141
|
+
}
|
|
4142
|
+
disconnectedCallback() {
|
|
4143
|
+
plt.jmp(() => disconnectedCallback(this));
|
|
4144
|
+
/**
|
|
4145
|
+
* Clear up references within the `$vnode$` object to the DOM
|
|
4146
|
+
* node that was removed. This is necessary to ensure that these
|
|
4147
|
+
* references used as keys in the `hostRef` object can be properly
|
|
4148
|
+
* garbage collected.
|
|
4149
|
+
*
|
|
4150
|
+
* Also remove the reference from `deferredConnectedCallbacks` array
|
|
4151
|
+
* otherwise removed instances won't get garbage collected.
|
|
4152
|
+
*/
|
|
4153
|
+
plt.raf(() => {
|
|
4154
|
+
const hostRef = getHostRef(this);
|
|
4155
|
+
if (!hostRef) return;
|
|
4156
|
+
const i = deferredConnectedCallbacks.findIndex((host) => host === this);
|
|
4157
|
+
if (i > -1) deferredConnectedCallbacks.splice(i, 1);
|
|
4158
|
+
if (hostRef?.$vnode$?.$elm$ instanceof Node && !hostRef.$vnode$.$elm$.isConnected) delete hostRef.$vnode$.$elm$;
|
|
4159
|
+
});
|
|
4160
|
+
}
|
|
4161
|
+
componentOnReady() {
|
|
4162
|
+
return getHostRef(this)?.$onReadyPromise$;
|
|
4163
|
+
}
|
|
4164
|
+
};
|
|
4165
|
+
if (!(cmpMeta.$flags$ & CMP_FLAGS.shadowDomEncapsulation) && cmpMeta.$flags$ & CMP_FLAGS.hasSlot) if (BUILD.experimentalSlotFixes) patchPseudoShadowDom(HostElement.prototype);
|
|
4166
|
+
else {
|
|
4167
|
+
if (BUILD.slotChildNodesFix) patchChildSlotNodes(HostElement.prototype);
|
|
4168
|
+
if (BUILD.cloneNodeFix) patchCloneNode(HostElement.prototype);
|
|
4169
|
+
if (BUILD.appendChildSlotFix) patchSlotAppendChild(HostElement.prototype);
|
|
4170
|
+
if (BUILD.scopedSlotTextContentFix && cmpMeta.$flags$ & CMP_FLAGS.scopedCssEncapsulation) patchTextContent(HostElement.prototype);
|
|
4171
|
+
}
|
|
4172
|
+
else if (BUILD.cloneNodeFix) patchCloneNode(HostElement.prototype);
|
|
4173
|
+
if (BUILD.formAssociated && cmpMeta.$flags$ & CMP_FLAGS.formAssociated) HostElement.formAssociated = true;
|
|
4174
|
+
if (BUILD.hotModuleReplacement) HostElement.prototype["s-hmr"] = function(hmrVersionId) {
|
|
4175
|
+
hmrStart(this, cmpMeta, hmrVersionId);
|
|
4176
|
+
};
|
|
4177
|
+
cmpMeta.$lazyBundleId$ = lazyBundle[0];
|
|
4178
|
+
if (!exclude.includes(tagName) && !customElements.get(tagName)) {
|
|
4179
|
+
cmpTags.push(tagName);
|
|
4180
|
+
customElements.define(tagName, proxyComponent(HostElement, cmpMeta, PROXY_FLAGS.isElementConstructor));
|
|
4181
|
+
}
|
|
4182
|
+
});
|
|
4183
|
+
});
|
|
4184
|
+
if (cmpTags.length > 0) {
|
|
4185
|
+
if (BUILD.slotRelocation && hasSlotRelocation) dataStyles.textContent += SLOT_FB_CSS;
|
|
4186
|
+
if (BUILD.invisiblePrehydration && (BUILD.hydratedClass || BUILD.hydratedAttribute)) dataStyles.textContent += cmpTags.sort() + HYDRATED_CSS;
|
|
4187
|
+
if (dataStyles.innerHTML.length) {
|
|
4188
|
+
dataStyles.setAttribute("data-styles", "");
|
|
4189
|
+
const nonce = plt.$nonce$ ?? queryNonceMetaTagContent(win.document);
|
|
4190
|
+
if (nonce != null) dataStyles.setAttribute("nonce", nonce);
|
|
4191
|
+
head.insertBefore(dataStyles, metaCharset ? metaCharset.nextSibling : head.firstChild);
|
|
4192
|
+
}
|
|
4193
|
+
}
|
|
4194
|
+
isBootstrapping = false;
|
|
4195
|
+
if (deferredConnectedCallbacks.length) deferredConnectedCallbacks.map((host) => host.connectedCallback());
|
|
4196
|
+
else if (BUILD.profile) plt.jmp(() => appLoadFallback = setTimeout(appDidLoad, 30, "timeout"));
|
|
4197
|
+
else plt.jmp(() => appLoadFallback = setTimeout(appDidLoad, 30));
|
|
4198
|
+
endBootstrap();
|
|
4199
|
+
};
|
|
4200
|
+
|
|
4201
|
+
//#endregion
|
|
4202
|
+
//#region src/runtime/fragment.ts
|
|
4203
|
+
const Fragment = (_, children) => children;
|
|
4204
|
+
|
|
4205
|
+
//#endregion
|
|
4206
|
+
//#region src/runtime/host-listener.ts
|
|
4207
|
+
const addHostEventListeners = (elm, hostRef, listeners, attachParentListeners) => {
|
|
4208
|
+
if (BUILD.hostListener && listeners && win.document) {
|
|
4209
|
+
if (BUILD.hostListenerTargetParent) if (attachParentListeners) listeners = listeners.filter(([flags]) => flags & LISTENER_FLAGS.TargetParent);
|
|
4210
|
+
else listeners = listeners.filter(([flags]) => !(flags & LISTENER_FLAGS.TargetParent));
|
|
4211
|
+
listeners.map(([flags, name, method]) => {
|
|
4212
|
+
const target = BUILD.hostListenerTarget ? getHostListenerTarget(win.document, elm, flags) : elm;
|
|
4213
|
+
const handler = hostListenerProxy(hostRef, method);
|
|
4214
|
+
const opts = hostListenerOpts(flags);
|
|
4215
|
+
plt.ael(target, name, handler, opts);
|
|
4216
|
+
(hostRef.$rmListeners$ = hostRef.$rmListeners$ || []).push(() => plt.rel(target, name, handler, opts));
|
|
4217
|
+
});
|
|
4218
|
+
}
|
|
4219
|
+
};
|
|
4220
|
+
const hostListenerProxy = (hostRef, methodName) => (ev) => {
|
|
4221
|
+
try {
|
|
4222
|
+
if (BUILD.lazyLoad) if (hostRef.$flags$ & HOST_FLAGS.isListenReady) hostRef.$lazyInstance$?.[methodName](ev);
|
|
4223
|
+
else (hostRef.$queuedListeners$ = hostRef.$queuedListeners$ || []).push([methodName, ev]);
|
|
4224
|
+
else hostRef.$hostElement$[methodName](ev);
|
|
4225
|
+
} catch (e) {
|
|
4226
|
+
consoleError(e, hostRef.$hostElement$);
|
|
4227
|
+
}
|
|
4228
|
+
};
|
|
4229
|
+
const getHostListenerTarget = (doc, elm, flags) => {
|
|
4230
|
+
if (BUILD.hostListenerTargetDocument && flags & LISTENER_FLAGS.TargetDocument) return doc;
|
|
4231
|
+
if (BUILD.hostListenerTargetWindow && flags & LISTENER_FLAGS.TargetWindow) return win;
|
|
4232
|
+
if (BUILD.hostListenerTargetBody && flags & LISTENER_FLAGS.TargetBody) return doc.body;
|
|
4233
|
+
if (BUILD.hostListenerTargetParent && flags & LISTENER_FLAGS.TargetParent && elm.parentElement) return elm.parentElement;
|
|
4234
|
+
return elm;
|
|
4235
|
+
};
|
|
4236
|
+
const hostListenerOpts = (flags) => supportsListenerOptions ? {
|
|
4237
|
+
passive: (flags & LISTENER_FLAGS.Passive) !== 0,
|
|
4238
|
+
capture: (flags & LISTENER_FLAGS.Capture) !== 0
|
|
4239
|
+
} : (flags & LISTENER_FLAGS.Capture) !== 0;
|
|
4240
|
+
|
|
4241
|
+
//#endregion
|
|
4242
|
+
//#region src/runtime/mixin.ts
|
|
4243
|
+
const baseClass = BUILD.lazyLoad ? class {} : globalThis.HTMLElement || class {};
|
|
4244
|
+
function Mixin(...mixins) {
|
|
4245
|
+
return mixins.reduceRight((acc, mixin) => mixin(acc), baseClass);
|
|
4246
|
+
}
|
|
4247
|
+
|
|
4248
|
+
//#endregion
|
|
4249
|
+
//#region src/runtime/render.ts
|
|
4250
|
+
/**
|
|
4251
|
+
* Method to render a virtual DOM tree to a container element.
|
|
4252
|
+
*
|
|
4253
|
+
* @example
|
|
4254
|
+
* ```tsx
|
|
4255
|
+
* import { render } from '@stencil/core';
|
|
4256
|
+
*
|
|
4257
|
+
* const vnode = (
|
|
4258
|
+
* <div>
|
|
4259
|
+
* <h1>Hello, world!</h1>
|
|
4260
|
+
* </div>
|
|
4261
|
+
* );
|
|
4262
|
+
* render(vnode, document.body);
|
|
4263
|
+
* ```
|
|
4264
|
+
*
|
|
4265
|
+
* @param vnode - The virtual DOM tree to render
|
|
4266
|
+
* @param container - The container element to render the virtual DOM tree to
|
|
4267
|
+
*/
|
|
4268
|
+
function render(vnode, container) {
|
|
4269
|
+
renderVdom({
|
|
4270
|
+
$flags$: 0,
|
|
4271
|
+
$cmpMeta$: {
|
|
4272
|
+
$flags$: 0,
|
|
4273
|
+
$tagName$: container.tagName
|
|
4274
|
+
},
|
|
4275
|
+
$hostElement$: container
|
|
4276
|
+
}, vnode);
|
|
4277
|
+
}
|
|
4278
|
+
|
|
4279
|
+
//#endregion
|
|
4280
|
+
//#region src/runtime/tag-transform.ts
|
|
4281
|
+
let tagTransformer = void 0;
|
|
4282
|
+
/**
|
|
4283
|
+
* Transforms a tag name using the current tag transformer
|
|
4284
|
+
* @param tag - the tag to transform e.g. `my-tag`
|
|
4285
|
+
* @returns the transformed tag e.g. `new-my-tag`
|
|
4286
|
+
*/
|
|
4287
|
+
function transformTag(tag) {
|
|
4288
|
+
if (!tagTransformer) return tag;
|
|
4289
|
+
return tagTransformer(tag);
|
|
4290
|
+
}
|
|
4291
|
+
|
|
4292
|
+
//#endregion
|
|
4293
|
+
//#region src/runtime/vdom/vdom-annotations.ts
|
|
4294
|
+
/**
|
|
4295
|
+
* Updates the DOM generated on the server with annotations such as node attributes and
|
|
4296
|
+
* comment nodes to facilitate future client-side hydration. These annotations are used for things
|
|
4297
|
+
* like moving elements back to their original hosts if using Shadow DOM on the client, and for quickly
|
|
4298
|
+
* reconstructing the vNode representations of the DOM.
|
|
4299
|
+
*
|
|
4300
|
+
* @param doc The DOM generated by the server.
|
|
4301
|
+
* @param staticComponents Any components that should be considered static and do not need client-side hydration.
|
|
4302
|
+
*/
|
|
4303
|
+
const insertVdomAnnotations = (doc, staticComponents) => {
|
|
4304
|
+
if (doc != null) {
|
|
4305
|
+
/**
|
|
4306
|
+
* Initiated `docData` object from the document if it exists to ensure we
|
|
4307
|
+
* maintain the same `docData` object across multiple hydration hydration runs.
|
|
4308
|
+
*/
|
|
4309
|
+
const docData = STENCIL_DOC_DATA in doc ? doc[STENCIL_DOC_DATA] : { ...DEFAULT_DOC_DATA };
|
|
4310
|
+
docData.staticComponents = new Set(staticComponents);
|
|
4311
|
+
const orgLocationNodes = [];
|
|
4312
|
+
parseVNodeAnnotations(doc, doc.body, docData, orgLocationNodes);
|
|
4313
|
+
orgLocationNodes.forEach((orgLocationNode) => {
|
|
4314
|
+
if (orgLocationNode != null && orgLocationNode["s-nr"]) {
|
|
4315
|
+
const nodeRef = orgLocationNode["s-nr"];
|
|
4316
|
+
let hostId = nodeRef["s-host-id"];
|
|
4317
|
+
let nodeId = nodeRef["s-node-id"];
|
|
4318
|
+
let childId = `${hostId}.${nodeId}`;
|
|
4319
|
+
if (hostId == null) {
|
|
4320
|
+
hostId = 0;
|
|
4321
|
+
docData.rootLevelIds++;
|
|
4322
|
+
nodeId = docData.rootLevelIds;
|
|
4323
|
+
childId = `${hostId}.${nodeId}`;
|
|
4324
|
+
if (nodeRef.nodeType === NODE_TYPE.ElementNode) {
|
|
4325
|
+
nodeRef.setAttribute(HYDRATE_CHILD_ID, childId);
|
|
4326
|
+
if (typeof nodeRef["s-sn"] === "string" && !nodeRef.getAttribute("slot")) nodeRef.setAttribute("s-sn", nodeRef["s-sn"]);
|
|
4327
|
+
} else if (nodeRef.nodeType === NODE_TYPE.TextNode) {
|
|
4328
|
+
if (hostId === 0) {
|
|
4329
|
+
if (nodeRef.nodeValue?.trim() === "") {
|
|
4330
|
+
orgLocationNode.remove();
|
|
4331
|
+
return;
|
|
4332
|
+
}
|
|
4333
|
+
}
|
|
4334
|
+
const commentBeforeTextNode = doc.createComment(childId);
|
|
4335
|
+
commentBeforeTextNode.nodeValue = `${TEXT_NODE_ID}.${childId}`;
|
|
4336
|
+
insertBefore(nodeRef.parentNode, commentBeforeTextNode, nodeRef);
|
|
4337
|
+
} else if (nodeRef.nodeType === NODE_TYPE.CommentNode) {
|
|
4338
|
+
const commentBeforeTextNode = doc.createComment(childId);
|
|
4339
|
+
commentBeforeTextNode.nodeValue = `${COMMENT_NODE_ID}.${childId}`;
|
|
4340
|
+
nodeRef.parentNode.insertBefore(commentBeforeTextNode, nodeRef);
|
|
4341
|
+
}
|
|
4342
|
+
}
|
|
4343
|
+
let orgLocationNodeId = `${ORG_LOCATION_ID}.${childId}`;
|
|
4344
|
+
const orgLocationParentNode = orgLocationNode.parentElement;
|
|
4345
|
+
if (orgLocationParentNode) {
|
|
4346
|
+
if (orgLocationParentNode["s-en"] === "") orgLocationNodeId += `.`;
|
|
4347
|
+
else if (orgLocationParentNode["s-en"] === "c") orgLocationNodeId += `.c`;
|
|
4348
|
+
}
|
|
4349
|
+
orgLocationNode.nodeValue = orgLocationNodeId;
|
|
4350
|
+
}
|
|
4351
|
+
});
|
|
4352
|
+
}
|
|
4353
|
+
};
|
|
4354
|
+
/**
|
|
4355
|
+
* Recursively parses a node generated by the server and its children to set host and child id
|
|
4356
|
+
* attributes read during client-side hydration. This function also tracks whether each node is
|
|
4357
|
+
* an original location reference node meaning that a node has been moved via slot relocation.
|
|
4358
|
+
*
|
|
4359
|
+
* @param doc The DOM generated by the server.
|
|
4360
|
+
* @param node The node to parse.
|
|
4361
|
+
* @param docData An object containing metadata about the document.
|
|
4362
|
+
* @param orgLocationNodes An array of nodes that have been moved via slot relocation.
|
|
4363
|
+
*/
|
|
4364
|
+
const parseVNodeAnnotations = (doc, node, docData, orgLocationNodes) => {
|
|
4365
|
+
if (node == null) return;
|
|
4366
|
+
if (node["s-nr"] != null) orgLocationNodes.push(node);
|
|
4367
|
+
if (node.nodeType === NODE_TYPE.ElementNode) [...Array.from(node.childNodes), ...Array.from(node.shadowRoot?.childNodes || [])].forEach((childNode) => {
|
|
4368
|
+
const hostRef = getHostRef(childNode);
|
|
4369
|
+
if (hostRef != null && !docData.staticComponents.has(childNode.nodeName.toLowerCase())) insertVNodeAnnotations(doc, childNode, hostRef.$vnode$, docData, { nodeIds: 0 });
|
|
4370
|
+
parseVNodeAnnotations(doc, childNode, docData, orgLocationNodes);
|
|
4371
|
+
});
|
|
4372
|
+
};
|
|
4373
|
+
/**
|
|
4374
|
+
* Insert attribute annotations on an element for its host ID and, potentially, its child ID.
|
|
4375
|
+
* Also makes calls to insert annotations on the element's children, keeping track of the depth of
|
|
4376
|
+
* the component tree.
|
|
4377
|
+
*
|
|
4378
|
+
* @param doc The DOM generated by the server.
|
|
4379
|
+
* @param hostElm The element to insert annotations for.
|
|
4380
|
+
* @param vnode The vNode representation of the element.
|
|
4381
|
+
* @param docData An object containing metadata about the document.
|
|
4382
|
+
* @param cmpData An object containing metadata about the component.
|
|
4383
|
+
*/
|
|
4384
|
+
const insertVNodeAnnotations = (doc, hostElm, vnode, docData, cmpData) => {
|
|
4385
|
+
if (vnode != null) {
|
|
4386
|
+
const hostId = ++docData.hostIds;
|
|
4387
|
+
hostElm.setAttribute(HYDRATE_ID, hostId);
|
|
4388
|
+
if (hostElm["s-cr"] != null) hostElm["s-cr"].nodeValue = `${CONTENT_REF_ID}.${hostId}`;
|
|
4389
|
+
if (vnode.$children$ != null) {
|
|
4390
|
+
const depth = 0;
|
|
4391
|
+
vnode.$children$.forEach((vnodeChild, index) => {
|
|
4392
|
+
insertChildVNodeAnnotations(doc, vnodeChild, cmpData, hostId, depth, index);
|
|
4393
|
+
});
|
|
4394
|
+
}
|
|
4395
|
+
if (hostElm && vnode && vnode.$elm$ && !hostElm.hasAttribute(HYDRATE_CHILD_ID)) {
|
|
4396
|
+
const parent = hostElm.parentElement;
|
|
4397
|
+
if (parent && parent.childNodes) {
|
|
4398
|
+
const parentChildNodes = Array.from(parent.childNodes);
|
|
4399
|
+
const comment = parentChildNodes.find((node) => node.nodeType === NODE_TYPE.CommentNode && node["s-sr"]);
|
|
4400
|
+
if (comment) {
|
|
4401
|
+
const index = parentChildNodes.indexOf(hostElm) - 1;
|
|
4402
|
+
vnode.$elm$.setAttribute(HYDRATE_CHILD_ID, `${comment["s-host-id"]}.${comment["s-node-id"]}.0.${index}`);
|
|
4403
|
+
}
|
|
4404
|
+
}
|
|
4405
|
+
}
|
|
4406
|
+
}
|
|
4407
|
+
};
|
|
4408
|
+
/**
|
|
4409
|
+
* Recursively analyzes the type of a child vNode and inserts annotations on the vNodes's element based on its type.
|
|
4410
|
+
* Element nodes receive a child ID attribute, text nodes have a comment with the child ID inserted before them,
|
|
4411
|
+
* and comment nodes representing a slot have their node value set to a slot node ID containing the child ID.
|
|
4412
|
+
*
|
|
4413
|
+
* @param doc The DOM generated by the server.
|
|
4414
|
+
* @param vnodeChild The vNode to insert annotations for.
|
|
4415
|
+
* @param cmpData An object containing metadata about the component.
|
|
4416
|
+
* @param hostId The host ID of this element's parent.
|
|
4417
|
+
* @param depth How deep this element sits in the component tree relative to its parent.
|
|
4418
|
+
* @param index The index of this element in its parent's children array.
|
|
4419
|
+
*/
|
|
4420
|
+
const insertChildVNodeAnnotations = (doc, vnodeChild, cmpData, hostId, depth, index) => {
|
|
4421
|
+
const childElm = vnodeChild.$elm$;
|
|
4422
|
+
if (childElm == null) return;
|
|
4423
|
+
const nodeId = cmpData.nodeIds++;
|
|
4424
|
+
const childId = `${hostId}.${nodeId}.${depth}.${index}`;
|
|
4425
|
+
childElm["s-host-id"] = hostId;
|
|
4426
|
+
childElm["s-node-id"] = nodeId;
|
|
4427
|
+
if (childElm.nodeType === NODE_TYPE.ElementNode) {
|
|
4428
|
+
childElm.setAttribute(HYDRATE_CHILD_ID, childId);
|
|
4429
|
+
if (typeof childElm["s-sn"] === "string" && !childElm.getAttribute("slot")) childElm.setAttribute("s-sn", childElm["s-sn"]);
|
|
4430
|
+
} else if (childElm.nodeType === NODE_TYPE.TextNode) {
|
|
4431
|
+
const parentNode = childElm.parentNode;
|
|
4432
|
+
const nodeName = parentNode?.nodeName;
|
|
4433
|
+
if (nodeName !== "STYLE" && nodeName !== "SCRIPT") {
|
|
4434
|
+
const textNodeId = `${TEXT_NODE_ID}.${childId}`;
|
|
4435
|
+
insertBefore(parentNode, doc.createComment(textNodeId), childElm);
|
|
4436
|
+
}
|
|
4437
|
+
} else if (childElm.nodeType === NODE_TYPE.CommentNode) {
|
|
4438
|
+
if (childElm["s-sr"]) childElm.nodeValue = `${SLOT_NODE_ID}.${childId}.${childElm["s-sn"] || ""}`;
|
|
4439
|
+
}
|
|
4440
|
+
if (vnodeChild.$children$ != null) {
|
|
4441
|
+
const childDepth = depth + 1;
|
|
4442
|
+
vnodeChild.$children$.forEach((vnode, index) => {
|
|
4443
|
+
insertChildVNodeAnnotations(doc, vnode, cmpData, hostId, childDepth, index);
|
|
4444
|
+
});
|
|
4445
|
+
}
|
|
4446
|
+
};
|
|
4447
|
+
|
|
4448
|
+
//#endregion
|
|
4449
|
+
export { reWireGetterSetter as C, Env as E, setErrorHandler as S, BUILD as T, setAssetPath as _, bootstrapLazy as a, setPlatformHelpers as b, renderVdom as c, getMode as d, setMode as f, getAssetPath as g, h, Fragment as i, createEvent as l, Host as m, render as n, forceUpdate as o, scopeCss as p, Mixin as r, getRenderingRef as s, insertVdomAnnotations as t, getElement as u, readTask as v, Build as w, HYDRATED_CSS as x, writeTask as y };
|