18
18
*/
19
19
20
20
import {
21
- _isValidExplicitDest ,
22
21
AbortException ,
23
22
AnnotationMode ,
24
23
assert ,
@@ -29,7 +28,6 @@ import {
29
28
RenderingIntentFlag ,
30
29
setVerbosityLevel ,
31
30
shadow ,
32
- stringToBytes ,
33
31
unreachable ,
34
32
warn ,
35
33
} from "../shared/util.js" ;
@@ -47,6 +45,13 @@ import {
47
45
StatTimer ,
48
46
} from "./display_utils.js" ;
49
47
import { FontFaceObject , FontLoader } from "./font_loader.js" ;
48
+ import {
49
+ getDataProp ,
50
+ getFactoryUrlProp ,
51
+ getUrlProp ,
52
+ isRefProxy ,
53
+ LoopbackPort ,
54
+ } from "./api_utils.js" ;
50
55
import { MessageHandler , wrapReason } from "../shared/message_handler.js" ;
51
56
import {
52
57
NodeCanvasFactory ,
@@ -68,10 +73,10 @@ import { PDFDataTransportStream } from "./transport_stream.js";
68
73
import { PDFFetchStream } from "display-fetch_stream" ;
69
74
import { PDFNetworkStream } from "display-network" ;
70
75
import { PDFNodeStream } from "display-node_stream" ;
76
+ import { PDFObjects } from "./pdf_objects.js" ;
71
77
import { TextLayer } from "./text_layer.js" ;
72
78
import { XfaText } from "./xfa_text.js" ;
73
79
74
- const DEFAULT_RANGE_CHUNK_SIZE = 65536 ; // 2^16 = 65536
75
80
const RENDERING_CANCELLED_TIMEOUT = 100 ; // ms
76
81
77
82
/**
@@ -111,7 +116,7 @@ const RENDERING_CANCELLED_TIMEOUT = 100; // ms
111
116
* @property {PDFDataRangeTransport } [range] - Allows for using a custom range
112
117
* transport implementation.
113
118
* @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) .
115
120
* @property {PDFWorker } [worker] - The worker that will be used for loading and
116
121
* parsing the PDF data.
117
122
* @property {number } [verbosity] - Controls the logging level; the constants
@@ -255,7 +260,7 @@ function getDocument(src = {}) {
255
260
const rangeChunkSize =
256
261
Number . isInteger ( src . rangeChunkSize ) && src . rangeChunkSize > 0
257
262
? src . rangeChunkSize
258
- : DEFAULT_RANGE_CHUNK_SIZE ;
263
+ : 2 ** 16 ;
259
264
let worker = src . worker instanceof PDFWorker ? src . worker : null ;
260
265
const verbosity = src . verbosity ;
261
266
// Ignore "data:"-URLs, since they can't be used to recover valid absolute
@@ -507,94 +512,6 @@ function getDocument(src = {}) {
507
512
return task ;
508
513
}
509
514
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
-
598
515
/**
599
516
* @typedef {Object } OnProgressParameters
600
517
* @property {number } loaded - Currently loaded number of bytes.
@@ -2012,54 +1929,6 @@ class PDFPageProxy {
2012
1929
}
2013
1930
}
2014
1931
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
-
2063
1932
/**
2064
1933
* @typedef {Object } PDFWorkerParameters
2065
1934
* @property {string } [name] - The name of the worker.
@@ -3142,115 +3011,6 @@ class WorkerTransport {
3142
3011
}
3143
3012
}
3144
3013
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
-
3254
3014
/**
3255
3015
* Allows controlling of the rendering tasks.
3256
3016
*/
@@ -3511,8 +3271,6 @@ const build =
3511
3271
export {
3512
3272
build ,
3513
3273
getDocument ,
3514
- isValidExplicitDest ,
3515
- LoopbackPort ,
3516
3274
PDFDataRangeTransport ,
3517
3275
PDFDocumentLoadingTask ,
3518
3276
PDFDocumentProxy ,
0 commit comments