whatwg / loader

Loader Standard
https://whatwg.github.io/loader/
Creative Commons Zero v1.0 Universal
607 stars 45 forks source link

Make importing fail if URL has changed (for SPA, PJAX, and History API) #158

Closed falsandtru closed 7 years ago

falsandtru commented 7 years ago

After url and dom are changed by SPA or PJAX, requested scripts must NOT be evaluated. So importing must have failed if url has changed.

If it is not a module script, we can cancel the evaluation of that. But if it is a module script, we cannot cancel the evaluation of that.

Here is my code having this problem.

  const url = new URL(standardizeUrl(location.href));
  if (script.type.toLowerCase() === 'module') {
    return wait.then(() => import(script.src))
      .then(
        () => (
          void script.dispatchEvent(new Event('load')),
          Right(script)),
        reason => (
          void script.dispatchEvent(new Event('error')),
          Left(new FatalError(reason instanceof Error ? reason.message : reason + ''))));
  }
  else {
    return script.hasAttribute('defer')
      ? wait.then(evaluate)
      : evaluate();
  }

  function evaluate() {
    try {
      if (new URL(standardizeUrl(location.href)).path !== url.path) throw new FatalError('Expired.');
      if (skip.has(standardizeUrl(location.href))) throw new FatalError('Expired.');
      void (0, eval)(code);
      script.hasAttribute('src') && void script.dispatchEvent(new Event('load'));
      return Right(script);
    }
    catch (reason) {
      script.hasAttribute('src') && void script.dispatchEvent(new Event('error'));
      return Left(new FatalError(reason instanceof Error ? reason.message : reason + ''));
    }
  }

https://github.com/falsandtru/pjax-api/blob/ae05475a829974d634b46ac346939a599c90545b/src/layer/domain/router/module/update/script.ts#L123-L152

caridy commented 7 years ago

@falsandtru this issue belongs to tc39/proposal-dynamic-import or maybe whatwg directly (since this is a behavior specified by the host environment). I also noticed that you have open the issue there, and closed it in favor of this one, not sure why.