1818 */
1919
2020import {
21- _isValidExplicitDest ,
2221 AbortException ,
2322 AnnotationMode ,
2423 assert ,
@@ -29,7 +28,6 @@ import {
2928 RenderingIntentFlag ,
3029 setVerbosityLevel ,
3130 shadow ,
32- stringToBytes ,
3331 unreachable ,
3432 warn ,
3533} from "../shared/util.js" ;
@@ -47,6 +45,13 @@ import {
4745 StatTimer ,
4846} from "./display_utils.js" ;
4947import { FontFaceObject , FontLoader } from "./font_loader.js" ;
48+ import {
49+ getDataProp ,
50+ getFactoryUrlProp ,
51+ getUrlProp ,
52+ isRefProxy ,
53+ LoopbackPort ,
54+ } from "./api_utils.js" ;
5055import { MessageHandler , wrapReason } from "../shared/message_handler.js" ;
5156import {
5257 NodeCanvasFactory ,
@@ -68,10 +73,10 @@ import { PDFDataTransportStream } from "./transport_stream.js";
6873import { PDFFetchStream } from "display-fetch_stream" ;
6974import { PDFNetworkStream } from "display-network" ;
7075import { PDFNodeStream } from "display-node_stream" ;
76+ import { PDFObjects } from "./pdf_objects.js" ;
7177import { TextLayer } from "./text_layer.js" ;
7278import { XfaText } from "./xfa_text.js" ;
7379
74- const DEFAULT_RANGE_CHUNK_SIZE = 65536 ; // 2^16 = 65536
7580const RENDERING_CANCELLED_TIMEOUT = 100 ; // ms
7681
7782/**
@@ -111,7 +116,7 @@ const RENDERING_CANCELLED_TIMEOUT = 100; // ms
111116 * @property {PDFDataRangeTransport } [range] - Allows for using a custom range
112117 * transport implementation.
113118 * @property {number } [rangeChunkSize] - Specify maximum number of bytes fetched
114- * per range request. The default value is { @link DEFAULT_RANGE_CHUNK_SIZE} .
119+ * per range request. The default value is 65536 (= 2^16) .
115120 * @property {PDFWorker } [worker] - The worker that will be used for loading and
116121 * parsing the PDF data.
117122 * @property {number } [verbosity] - Controls the logging level; the constants
@@ -255,7 +260,7 @@ function getDocument(src = {}) {
255260 const rangeChunkSize =
256261 Number . isInteger ( src . rangeChunkSize ) && src . rangeChunkSize > 0
257262 ? src . rangeChunkSize
258- : DEFAULT_RANGE_CHUNK_SIZE ;
263+ : 2 ** 16 ;
259264 let worker = src . worker instanceof PDFWorker ? src . worker : null ;
260265 const verbosity = src . verbosity ;
261266 // Ignore "data:"-URLs, since they can't be used to recover valid absolute
@@ -507,94 +512,6 @@ function getDocument(src = {}) {
507512 return task ;
508513}
509514
510- function getUrlProp ( val ) {
511- if ( typeof PDFJSDev !== "undefined" && PDFJSDev . test ( "MOZCENTRAL" ) ) {
512- return null ; // The 'url' is unused with `PDFDataRangeTransport`.
513- }
514- if ( val instanceof URL ) {
515- return val . href ;
516- }
517- if ( typeof val === "string" ) {
518- if (
519- typeof PDFJSDev !== "undefined" &&
520- PDFJSDev . test ( "GENERIC" ) &&
521- isNodeJS
522- ) {
523- return val ; // Use the url as-is in Node.js environments.
524- }
525-
526- // The full path is required in the 'url' field.
527- const url = URL . parse ( val , window . location ) ;
528- if ( url ) {
529- return url . href ;
530- }
531- }
532- throw new Error (
533- "Invalid PDF url data: " +
534- "either string or URL-object is expected in the url property."
535- ) ;
536- }
537-
538- function getDataProp ( val ) {
539- // Converting string or array-like data to Uint8Array.
540- if (
541- typeof PDFJSDev !== "undefined" &&
542- PDFJSDev . test ( "GENERIC" ) &&
543- isNodeJS &&
544- typeof Buffer !== "undefined" && // eslint-disable-line no-undef
545- val instanceof Buffer // eslint-disable-line no-undef
546- ) {
547- throw new Error (
548- "Please provide binary data as `Uint8Array`, rather than `Buffer`."
549- ) ;
550- }
551- if ( val instanceof Uint8Array && val . byteLength === val . buffer . byteLength ) {
552- // Use the data as-is when it's already a Uint8Array that completely
553- // "utilizes" its underlying ArrayBuffer, to prevent any possible
554- // issues when transferring it to the worker-thread.
555- return val ;
556- }
557- if ( typeof val === "string" ) {
558- return stringToBytes ( val ) ;
559- }
560- if (
561- val instanceof ArrayBuffer ||
562- ArrayBuffer . isView ( val ) ||
563- ( typeof val === "object" && ! isNaN ( val ?. length ) )
564- ) {
565- return new Uint8Array ( val ) ;
566- }
567- throw new Error (
568- "Invalid PDF binary data: either TypedArray, " +
569- "string, or array-like object is expected in the data property."
570- ) ;
571- }
572-
573- function getFactoryUrlProp ( val ) {
574- if ( typeof val !== "string" ) {
575- return null ;
576- }
577- if ( val . endsWith ( "/" ) ) {
578- return val ;
579- }
580- throw new Error ( `Invalid factory url: "${ val } " must include trailing slash.` ) ;
581- }
582-
583- const isRefProxy = v =>
584- typeof v === "object" &&
585- Number . isInteger ( v ?. num ) &&
586- v . num >= 0 &&
587- Number . isInteger ( v ?. gen ) &&
588- v . gen >= 0 ;
589-
590- const isNameProxy = v => typeof v === "object" && typeof v ?. name === "string" ;
591-
592- const isValidExplicitDest = _isValidExplicitDest . bind (
593- null ,
594- /* validRef = */ isRefProxy ,
595- /* validName = */ isNameProxy
596- ) ;
597-
598515/**
599516 * @typedef {Object } OnProgressParameters
600517 * @property {number } loaded - Currently loaded number of bytes.
@@ -2012,54 +1929,6 @@ class PDFPageProxy {
20121929 }
20131930}
20141931
2015- class LoopbackPort {
2016- #listeners = new Map ( ) ;
2017-
2018- #deferred = Promise . resolve ( ) ;
2019-
2020- postMessage ( obj , transfer ) {
2021- const event = {
2022- data : structuredClone ( obj , transfer ? { transfer } : null ) ,
2023- } ;
2024-
2025- this . #deferred. then ( ( ) => {
2026- for ( const [ listener ] of this . #listeners) {
2027- listener . call ( this , event ) ;
2028- }
2029- } ) ;
2030- }
2031-
2032- addEventListener ( name , listener , options = null ) {
2033- let rmAbort = null ;
2034- if ( options ?. signal instanceof AbortSignal ) {
2035- const { signal } = options ;
2036- if ( signal . aborted ) {
2037- warn ( "LoopbackPort - cannot use an `aborted` signal." ) ;
2038- return ;
2039- }
2040- const onAbort = ( ) => this . removeEventListener ( name , listener ) ;
2041- rmAbort = ( ) => signal . removeEventListener ( "abort" , onAbort ) ;
2042-
2043- signal . addEventListener ( "abort" , onAbort ) ;
2044- }
2045- this . #listeners. set ( listener , rmAbort ) ;
2046- }
2047-
2048- removeEventListener ( name , listener ) {
2049- const rmAbort = this . #listeners. get ( listener ) ;
2050- rmAbort ?. ( ) ;
2051-
2052- this . #listeners. delete ( listener ) ;
2053- }
2054-
2055- terminate ( ) {
2056- for ( const [ , rmAbort ] of this . #listeners) {
2057- rmAbort ?. ( ) ;
2058- }
2059- this . #listeners. clear ( ) ;
2060- }
2061- }
2062-
20631932/**
20641933 * @typedef {Object } PDFWorkerParameters
20651934 * @property {string } [name] - The name of the worker.
@@ -3142,115 +3011,6 @@ class WorkerTransport {
31423011 }
31433012}
31443013
3145- const INITIAL_DATA = Symbol ( "INITIAL_DATA" ) ;
3146-
3147- /**
3148- * A PDF document and page is built of many objects. E.g. there are objects for
3149- * fonts, images, rendering code, etc. These objects may get processed inside of
3150- * a worker. This class implements some basic methods to manage these objects.
3151- */
3152- class PDFObjects {
3153- #objs = Object . create ( null ) ;
3154-
3155- /**
3156- * Ensures there is an object defined for `objId`.
3157- *
3158- * @param {string } objId
3159- * @returns {Object }
3160- */
3161- #ensureObj( objId ) {
3162- return ( this . #objs[ objId ] ||= {
3163- ...Promise . withResolvers ( ) ,
3164- data : INITIAL_DATA ,
3165- } ) ;
3166- }
3167-
3168- /**
3169- * If called *without* callback, this returns the data of `objId` but the
3170- * object needs to be resolved. If it isn't, this method throws.
3171- *
3172- * If called *with* a callback, the callback is called with the data of the
3173- * object once the object is resolved. That means, if you call this method
3174- * and the object is already resolved, the callback gets called right away.
3175- *
3176- * @param {string } objId
3177- * @param {function } [callback]
3178- * @returns {any }
3179- */
3180- get ( objId , callback = null ) {
3181- // If there is a callback, then the get can be async and the object is
3182- // not required to be resolved right now.
3183- if ( callback ) {
3184- const obj = this . #ensureObj( objId ) ;
3185- obj . promise . then ( ( ) => callback ( obj . data ) ) ;
3186- return null ;
3187- }
3188- // If there isn't a callback, the user expects to get the resolved data
3189- // directly.
3190- const obj = this . #objs[ objId ] ;
3191- // If there isn't an object yet or the object isn't resolved, then the
3192- // data isn't ready yet!
3193- if ( ! obj || obj . data === INITIAL_DATA ) {
3194- throw new Error ( `Requesting object that isn't resolved yet ${ objId } .` ) ;
3195- }
3196- return obj . data ;
3197- }
3198-
3199- /**
3200- * @param {string } objId
3201- * @returns {boolean }
3202- */
3203- has ( objId ) {
3204- const obj = this . #objs[ objId ] ;
3205- return ! ! obj && obj . data !== INITIAL_DATA ;
3206- }
3207-
3208- /**
3209- * @param {string } objId
3210- * @returns {boolean }
3211- */
3212- delete ( objId ) {
3213- const obj = this . #objs[ objId ] ;
3214- if ( ! obj || obj . data === INITIAL_DATA ) {
3215- // Only allow removing the object *after* it's been resolved.
3216- return false ;
3217- }
3218- delete this . #objs[ objId ] ;
3219- return true ;
3220- }
3221-
3222- /**
3223- * Resolves the object `objId` with optional `data`.
3224- *
3225- * @param {string } objId
3226- * @param {any } [data]
3227- */
3228- resolve ( objId , data = null ) {
3229- const obj = this . #ensureObj( objId ) ;
3230- obj . data = data ;
3231- obj . resolve ( ) ;
3232- }
3233-
3234- clear ( ) {
3235- for ( const objId in this . #objs) {
3236- const { data } = this . #objs[ objId ] ;
3237- data ?. bitmap ?. close ( ) ; // Release any `ImageBitmap` data.
3238- }
3239- this . #objs = Object . create ( null ) ;
3240- }
3241-
3242- * [ Symbol . iterator ] ( ) {
3243- for ( const objId in this . #objs) {
3244- const { data } = this . #objs[ objId ] ;
3245-
3246- if ( data === INITIAL_DATA ) {
3247- continue ;
3248- }
3249- yield [ objId , data ] ;
3250- }
3251- }
3252- }
3253-
32543014/**
32553015 * Allows controlling of the rendering tasks.
32563016 */
@@ -3511,8 +3271,6 @@ const build =
35113271export {
35123272 build ,
35133273 getDocument ,
3514- isValidExplicitDest ,
3515- LoopbackPort ,
35163274 PDFDataRangeTransport ,
35173275 PDFDocumentLoadingTask ,
35183276 PDFDocumentProxy ,
0 commit comments