Injects a PSP SDK <script> once per page (idempotent via DOM lookup) and
resolves on load. A load failure, including a file that fails its
options.integrity check, rejects with a retryable psp_unavailable
attributed to pspName and removes the tag this call injected, so a later
call fetches the file again. Adapters keep their own poll-for-global logic —
this only gets the script tag onto the page; an adapter that caches the
load promise must clear it when it rejects for that later call to happen.
A <script> already on the page for url is reused and nothing is
injected. If an earlier call injected that tag and it is still loading, the
call waits for it: it resolves when the tag loads and, when the tag fails,
rejects with its own retryable psp_unavailable attributed to pspName. There
is no timeout: a tag that fires neither event keeps every call waiting on it
pending. Any other tag resolves the call at once: one that has loaded, or one
the page added itself, which the call never listens to or removes, whether it
is still loading or its load failed, so callers keep confirming the SDK
global. With options.integrity the call also detects a conflicting tag:
every <script> for url must carry exactly the same integrity string and
a crossorigin attribute, whatever its value, since without one a
cross-origin file is fetched without CORS and cannot pass the check. A
conflicting tag makes the call reject with a non-retryable invalid_request
attributed to pspName, as does an integrity holding no sha256, sha384 or
sha512 hash; either way nothing is injected, and the call rejects at once,
even while a tag for url is still loading.
options.nonce and options.attributes are never compared with a tag
already on the page. The browser read that tag's nonce when it prepared it,
so nothing a later call sets changes whether it runs, and under a
header-delivered policy it hides the nonce of a connected tag, whose
getAttribute("nonce") then returns an empty string. A tag the page added
itself keeps the attributes the page gave it, so an SDK reading its
configuration from its own tag reads the page's. An invalid nonce or
attribute name rejects with a non-retryable invalid_request attributed to
pspName whatever the page holds, and nothing is injected.
A page that enforces Trusted Types (require-trusted-types-for 'script')
must accept url in its default policy: when the page has none, or its
policy rejects the URL or throws, the call rejects with a non-retryable
invalid_request attributed to pspName, carrying on raw the exception
the assignment threw, and injects nothing.
This is not a trust boundary: every shipped client adapter's loadSdk()
returns before calling injectScript once the SDK global exists, so a copy
the host page already loaded is used without any check.
Injects a PSP SDK
<script>once per page (idempotent via DOM lookup) and resolves on load. A load failure, including a file that fails itsoptions.integritycheck, rejects with a retryable psp_unavailable attributed topspNameand removes the tag this call injected, so a later call fetches the file again. Adapters keep their own poll-for-global logic — this only gets the script tag onto the page; an adapter that caches the load promise must clear it when it rejects for that later call to happen.A
<script>already on the page forurlis reused and nothing is injected. If an earlier call injected that tag and it is still loading, the call waits for it: it resolves when the tag loads and, when the tag fails, rejects with its own retryable psp_unavailable attributed topspName. There is no timeout: a tag that fires neither event keeps every call waiting on it pending. Any other tag resolves the call at once: one that has loaded, or one the page added itself, which the call never listens to or removes, whether it is still loading or its load failed, so callers keep confirming the SDK global. Withoptions.integritythe call also detects a conflicting tag: every<script>forurlmust carry exactly the sameintegritystring and acrossoriginattribute, whatever its value, since without one a cross-origin file is fetched without CORS and cannot pass the check. A conflicting tag makes the call reject with a non-retryable invalid_request attributed topspName, as does anintegrityholding no sha256, sha384 or sha512 hash; either way nothing is injected, and the call rejects at once, even while a tag forurlis still loading.options.nonceandoptions.attributesare never compared with a tag already on the page. The browser read that tag's nonce when it prepared it, so nothing a later call sets changes whether it runs, and under a header-delivered policy it hides the nonce of a connected tag, whosegetAttribute("nonce")then returns an empty string. A tag the page added itself keeps the attributes the page gave it, so an SDK reading its configuration from its own tag reads the page's. An invalid nonce or attribute name rejects with a non-retryable invalid_request attributed topspNamewhatever the page holds, and nothing is injected.A page that enforces Trusted Types (
require-trusted-types-for 'script') must accepturlin its default policy: when the page has none, or its policy rejects the URL or throws, the call rejects with a non-retryable invalid_request attributed topspName, carrying onrawthe exception the assignment threw, and injects nothing.This is not a trust boundary: every shipped client adapter's
loadSdk()returns before callinginjectScriptonce the SDK global exists, so a copy the host page already loaded is used without any check.