bippy 0.7.2 → 0.7.3-dev.8ba0705

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.
@@ -39,6 +39,7 @@ export interface SourceFetch {
39
39
  }
40
40
 
41
41
  export interface SourceMapRequestOptions {
42
+ allowCrossOriginSourceMap?: boolean;
42
43
  allowUnsafeServerFetch?: boolean;
43
44
  maxBundleSizeBytes?: number;
44
45
  maxSourceMapSizeBytes?: number;
@@ -49,6 +50,7 @@ export interface SourceMapRequestOptions {
49
50
  export interface SourceMap {
50
51
  file?: string;
51
52
  ignoredSourceIndices?: Set<number>;
53
+ sourceMapUrl?: string;
52
54
  mappings: SourceMapSegment[][];
53
55
  names?: string[];
54
56
  sections?: DecodedSourceMapSection[];
@@ -298,10 +300,14 @@ const resolveUrl = (reference: string, baseUrl: string): string | null => {
298
300
  return new URL(reference, baseUrl).toString();
299
301
  } catch {
300
302
  try {
301
- const resolvedUrl = new URL(reference, new URL(baseUrl, "https://bippy.invalid/"));
302
- return `${resolvedUrl.pathname}${resolvedUrl.search}${resolvedUrl.hash}`;
303
+ return new URL(reference).toString();
303
304
  } catch {
304
- return null;
305
+ try {
306
+ const resolvedUrl = new URL(reference, new URL(baseUrl, "https://bippy.invalid/"));
307
+ return `${resolvedUrl.pathname}${resolvedUrl.search}${resolvedUrl.hash}`;
308
+ } catch {
309
+ return null;
310
+ }
305
311
  }
306
312
  }
307
313
  };
@@ -460,6 +466,11 @@ const resolveSourceMapSources = (rawSourceMap: StandardSourceMap, sourceMapUrl:
460
466
  resolveSourceRoot(rawSourceMap.sourceRoot, source, sourceMapUrl),
461
467
  );
462
468
 
469
+ // An inline URL carries the whole encoded map, so retaining it in the cache would
470
+ // double the memory held per source map for the lifetime of the process.
471
+ const getRetainableSourceMapUrl = (sourceMapUrl: string): string | undefined =>
472
+ INLINE_SOURCEMAP_REGEX.test(sourceMapUrl) ? undefined : sourceMapUrl;
473
+
463
474
  const decodeStandardSourceMap = (
464
475
  rawSourceMap: StandardSourceMap,
465
476
  sourceMapUrl: string,
@@ -470,6 +481,7 @@ const decodeStandardSourceMap = (
470
481
  ignoredSourceIndices: getIgnoredSourceIndices(rawSourceMap),
471
482
  mappings: decode(rawSourceMap.mappings),
472
483
  names: rawSourceMap.names,
484
+ sourceMapUrl: getRetainableSourceMapUrl(sourceMapUrl),
473
485
  sourceRoot: rawSourceMap.sourceRoot,
474
486
  sources: resolveSourceMapSources(rawSourceMap, sourceMapUrl),
475
487
  sourcesContent: rawSourceMap.sourcesContent,
@@ -532,6 +544,7 @@ const decodeIndexSourceMap = async (
532
544
  mappings: [],
533
545
  names: [],
534
546
  sections: decodedSections,
547
+ sourceMapUrl: getRetainableSourceMapUrl(sourceMapUrl),
535
548
  sourceRoot: undefined,
536
549
  sources: Array.from(allSources),
537
550
  sourcesContent: undefined,
@@ -782,22 +795,23 @@ const readSourceMapDocument = async (
782
795
 
783
796
  const getSourceMapUncachedInternal = async (
784
797
  bundleUrl: string,
785
- fetchFn?: SourceFetch,
798
+ sourceFetchOverride?: SourceFetch,
786
799
  options: SourceMapRequestOptions = {},
787
800
  ): Promise<null | SourceMap> => {
788
- const shouldAllowCustomProtocol = fetchFn !== undefined;
801
+ const shouldAllowCustomProtocol = sourceFetchOverride !== undefined;
789
802
  if (!isFetchableUrl(bundleUrl, shouldAllowCustomProtocol)) {
790
803
  return null;
791
804
  }
792
805
 
793
806
  const isServer = isServerRuntime();
794
- const shouldRejectRedirects = isServer || isExtensionUrl(bundleUrl);
795
- if (isServer && !fetchFn) {
807
+ const shouldRejectRedirects =
808
+ (isServer || isExtensionUrl(bundleUrl)) && !options.allowCrossOriginSourceMap;
809
+ if (isServer && !sourceFetchOverride) {
796
810
  if (!options.allowUnsafeServerFetch || !isAbsoluteHttpUrl(bundleUrl)) return null;
797
811
  }
798
812
 
799
813
  const sourceFetch =
800
- fetchFn ??
814
+ sourceFetchOverride ??
801
815
  (typeof globalThis.fetch === "function" ? globalThis.fetch.bind(globalThis) : undefined);
802
816
  if (!sourceFetch) return null;
803
817
  const maxBundleSizeBytes = options.maxBundleSizeBytes ?? defaultMaxBundleSizeBytes;
@@ -864,11 +878,11 @@ const getSourceMapUncachedInternal = async (
864
878
 
865
879
  export const getSourceMapUncached = async (
866
880
  bundleUrl: string,
867
- fetchFn?: SourceFetch,
881
+ sourceFetch?: SourceFetch,
868
882
  options: SourceMapRequestOptions = {},
869
883
  ): Promise<null | SourceMap> => {
870
884
  try {
871
- return await getSourceMapUncachedInternal(bundleUrl, fetchFn, options);
885
+ return await getSourceMapUncachedInternal(bundleUrl, sourceFetch, options);
872
886
  } catch (error) {
873
887
  if (error instanceof TransientSourceMapError) return null;
874
888
  throw error;
@@ -878,66 +892,67 @@ export const getSourceMapUncached = async (
878
892
  const getPerFetchMap = <Value>(
879
893
  mapsByFetch: WeakMap<SourceFetch, Map<string, Value>>,
880
894
  globalMap: Map<string, Value>,
881
- fetchFn: SourceFetch | undefined,
895
+ sourceFetch: SourceFetch | undefined,
882
896
  ): Map<string, Value> => {
883
- if (!fetchFn) return globalMap;
884
- let map = mapsByFetch.get(fetchFn);
897
+ if (!sourceFetch) return globalMap;
898
+ let map = mapsByFetch.get(sourceFetch);
885
899
  if (!map) {
886
900
  map = new Map();
887
- mapsByFetch.set(fetchFn, map);
901
+ mapsByFetch.set(sourceFetch, map);
888
902
  }
889
903
  return map;
890
904
  };
891
905
 
892
- const getSourceMapCache = (fetchFn: SourceFetch | undefined): Map<string, null | SourceMap> =>
893
- getPerFetchMap(sourceMapCachesByFetch, sourceMapCache, fetchFn);
906
+ const getSourceMapCache = (sourceFetch: SourceFetch | undefined): Map<string, null | SourceMap> =>
907
+ getPerFetchMap(sourceMapCachesByFetch, sourceMapCache, sourceFetch);
894
908
 
895
909
  const getPendingSourceMapRequests = (
896
- fetchFn: SourceFetch | undefined,
910
+ sourceFetch: SourceFetch | undefined,
897
911
  ): Map<string, Promise<SourceMapResult>> =>
898
- getPerFetchMap(pendingSourceMapRequestsByFetch, pendingSourceMapRequests, fetchFn);
912
+ getPerFetchMap(pendingSourceMapRequestsByFetch, pendingSourceMapRequests, sourceFetch);
899
913
 
900
914
  const getSourceMapCacheKey = (file: string, options: SourceMapRequestOptions): string =>
915
+ options.allowCrossOriginSourceMap === undefined &&
901
916
  options.allowUnsafeServerFetch === undefined &&
902
917
  options.maxBundleSizeBytes === undefined &&
903
918
  options.maxSourceMapSizeBytes === undefined &&
904
919
  options.timeoutMs === undefined
905
920
  ? file
906
- : `${file}\0${options.allowUnsafeServerFetch ?? ""}\0${options.maxBundleSizeBytes ?? ""}\0${options.maxSourceMapSizeBytes ?? ""}\0${options.timeoutMs ?? ""}`;
921
+ : `${file}\0${options.allowCrossOriginSourceMap ?? ""}\0${options.allowUnsafeServerFetch ?? ""}\0${options.maxBundleSizeBytes ?? ""}\0${options.maxSourceMapSizeBytes ?? ""}\0${options.timeoutMs ?? ""}`;
907
922
 
908
923
  export const getSourceMap = async (
909
924
  file: string,
910
- useCache = true,
911
- fetchFn?: SourceFetch,
925
+ shouldUseCache = true,
926
+ sourceFetch?: SourceFetch,
912
927
  options: SourceMapRequestOptions = {},
913
928
  ): Promise<null | SourceMap> => {
914
- const shouldUseCache = useCache && options.signal === undefined;
915
- const cache = getSourceMapCache(fetchFn);
916
- const pendingRequests = getPendingSourceMapRequests(fetchFn);
929
+ const canUseCache = shouldUseCache && options.signal === undefined;
930
+ const cache = getSourceMapCache(sourceFetch);
931
+ const pendingRequests = getPendingSourceMapRequests(sourceFetch);
917
932
  const cacheKey = getSourceMapCacheKey(file, options);
918
- if (shouldUseCache && cache.has(cacheKey)) {
933
+ if (canUseCache && cache.has(cacheKey)) {
919
934
  return cache.get(cacheKey) ?? null;
920
935
  }
921
936
 
922
- const pendingRequest = shouldUseCache ? pendingRequests.get(cacheKey) : undefined;
937
+ const pendingRequest = canUseCache ? pendingRequests.get(cacheKey) : undefined;
923
938
  if (pendingRequest) {
924
939
  return (await pendingRequest).sourceMap;
925
940
  }
926
941
 
927
942
  const fetchPromise: Promise<SourceMapResult> = getSourceMapUncachedInternal(
928
943
  file,
929
- fetchFn,
944
+ sourceFetch,
930
945
  options,
931
946
  ).then(
932
947
  (sourceMap) => ({ sourceMap, isTransientFailure: false }),
933
948
  () => ({ sourceMap: null, isTransientFailure: true }),
934
949
  );
935
- if (shouldUseCache) {
950
+ if (canUseCache) {
936
951
  pendingRequests.set(cacheKey, fetchPromise);
937
952
  }
938
953
 
939
954
  const { sourceMap, isTransientFailure } = await fetchPromise;
940
- if (shouldUseCache) {
955
+ if (canUseCache) {
941
956
  pendingRequests.delete(cacheKey);
942
957
  if (!isTransientFailure) {
943
958
  cache.set(cacheKey, sourceMap);
@@ -949,13 +964,19 @@ export const getSourceMap = async (
949
964
 
950
965
  export const symbolicateStack = async (
951
966
  stack: StackFrame[],
952
- cache = true,
953
- fetchFn?: SourceFetch,
967
+ shouldUseCache = true,
968
+ sourceFetch?: SourceFetch,
969
+ requestOptions: SourceMapRequestOptions = {},
954
970
  ): Promise<StackFrame[]> => {
955
971
  return Promise.all(
956
972
  stack.map(async (stackFrame) => {
957
973
  if (!stackFrame.fileName) return stackFrame;
958
- const sourceMap = await getSourceMap(stackFrame.fileName, cache, fetchFn);
974
+ const sourceMap = await getSourceMap(
975
+ stackFrame.fileName,
976
+ shouldUseCache,
977
+ sourceFetch,
978
+ requestOptions,
979
+ );
959
980
  if (
960
981
  !sourceMap ||
961
982
  typeof stackFrame.lineNumber !== "number" ||