@reekon-tools/react-native-pdf-canvas 0.1.0 → 0.2.0
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.
- package/LICENSE +202 -0
- package/NOTICE +57 -0
- package/PdfCanvas.podspec +68 -39
- package/README.md +213 -1316
- package/android/build.gradle +67 -54
- package/android/consumer-rules.pro +7 -0
- package/android/src/androidTest/java/tools/reekon/pdfcanvas/PdfCanvasNativeTest.java +254 -0
- package/android/src/androidTest/java/tools/reekon/pdfcanvas/TestPdfs.java +60 -468
- package/android/src/main/cpp/CMakeLists.txt +54 -0
- package/android/src/main/cpp/pdfcanvas-jni.cpp +262 -0
- package/android/src/main/java/tools/reekon/pdfcanvas/PdfCanvasNative.java +167 -0
- package/android/src/main/java/tools/reekon/pdfcanvas/PdfErrorCode.java +14 -4
- package/android/src/main/java/tools/reekon/pdfcanvas/PdfRasterException.java +10 -4
- package/android/src/reactnative/java/tools/reekon/pdfcanvas/rn/PdfCanvasModule.java +160 -376
- package/android/tools/compile-gate.sh +81 -101
- package/dist/controller.d.ts +14 -0
- package/dist/controller.js +4 -3
- package/dist/index.native.d.ts +5 -0
- package/dist/index.native.js +5 -0
- package/dist/index.web.d.ts +10 -0
- package/dist/index.web.js +10 -0
- package/dist/rasterizer/index.native.d.ts +8 -12
- package/dist/rasterizer/index.native.js +15 -21
- package/dist/rasterizer/native-bridge.d.ts +51 -75
- package/dist/rasterizer/native-bridge.js +49 -33
- package/dist/rasterizer/native.d.ts +45 -0
- package/dist/rasterizer/native.js +123 -0
- package/dist/react/usePdfDocument.d.ts +5 -5
- package/dist/react/usePdfLayer.d.ts +10 -1
- package/dist/react/usePdfLayer.js +10 -2
- package/dist/skia/index.native.d.ts +7 -3
- package/dist/skia/index.native.js +7 -3
- package/dist/skia/index.web.d.ts +4 -2
- package/dist/skia/index.web.js +4 -2
- package/dist/testing/scenes.d.ts +3 -3
- package/dist/testing/scenes.js +4 -4
- package/dist/types.d.ts +36 -42
- package/ios/Sources/PdfCanvasBridge/PdfCanvasModule.mm +234 -536
- package/native/.clangd +5 -0
- package/native/CMakeLists.txt +89 -0
- package/native/core/include/pdfcanvas/document.h +90 -0
- package/native/core/include/pdfcanvas/error.h +47 -0
- package/native/core/include/pdfcanvas/jsi.h +18 -0
- package/native/core/include/pdfcanvas/jsi_config.h +30 -0
- package/native/core/include/pdfcanvas/library.h +28 -0
- package/native/core/include/pdfcanvas/pixels.h +92 -0
- package/native/core/include/pdfcanvas/service.h +87 -0
- package/native/core/include/pdfcanvas/slots.h +113 -0
- package/native/core/include/pdfcanvas/types.h +110 -0
- package/native/core/pdfcanvas-core.cmake +22 -0
- package/native/core/src/document.cpp +516 -0
- package/native/core/src/error.cpp +29 -0
- package/native/core/src/jsi.cpp +66 -0
- package/native/core/src/library.cpp +52 -0
- package/native/core/src/pixels.cpp +45 -0
- package/native/core/src/service.cpp +156 -0
- package/native/core/src/slots.cpp +139 -0
- package/native/tests/fixtures.cpp +451 -0
- package/native/tests/fixtures.h +96 -0
- package/native/tests/harness.h +122 -0
- package/native/tests/main.cpp +64 -0
- package/native/tests/pixels_util.h +126 -0
- package/native/tests/test_document.cpp +485 -0
- package/native/tests/test_service.cpp +130 -0
- package/native/tests/test_slots.cpp +250 -0
- package/package.json +38 -8
- package/react-native.config.js +5 -2
- package/scripts/fetch-pdfium.mjs +487 -0
- package/scripts/pdfium-manifest.json +46 -0
- package/android/src/androidTest/java/tools/reekon/pdfcanvas/PdfCanvasCancellationTest.java +0 -226
- package/android/src/androidTest/java/tools/reekon/pdfcanvas/PdfCanvasConcurrencyTest.java +0 -239
- package/android/src/androidTest/java/tools/reekon/pdfcanvas/PdfCanvasDeviceTimingTest.java +0 -251
- package/android/src/androidTest/java/tools/reekon/pdfcanvas/PdfCanvasFailureTest.java +0 -221
- package/android/src/androidTest/java/tools/reekon/pdfcanvas/PdfCanvasJsiTransportTest.java +0 -783
- package/android/src/androidTest/java/tools/reekon/pdfcanvas/PdfCanvasPhaseTimingTest.java +0 -1388
- package/android/src/androidTest/java/tools/reekon/pdfcanvas/PdfCanvasPoisonGuardTest.java +0 -98
- package/android/src/androidTest/java/tools/reekon/pdfcanvas/PdfCanvasQuirksTest.java +0 -324
- package/android/src/androidTest/java/tools/reekon/pdfcanvas/PdfCanvasRasterizerTest.java +0 -775
- package/android/src/androidTest/java/tools/reekon/pdfcanvas/PoisonsTheProcess.java +0 -20
- package/android/src/jsi/cpp/CMakeLists.txt +0 -33
- package/android/src/jsi/cpp/pdfcanvas-jsi.cpp +0 -469
- package/android/src/jsi/java/tools/reekon/pdfcanvas/jsi/PdfCanvasPixelBridge.java +0 -140
- package/android/src/main/java/tools/reekon/pdfcanvas/PageGeometry.java +0 -45
- package/android/src/main/java/tools/reekon/pdfcanvas/PdfCanvasRasterizer.java +0 -564
- package/android/src/main/java/tools/reekon/pdfcanvas/PdfPlatformQuirks.java +0 -277
- package/android/src/main/java/tools/reekon/pdfcanvas/PdfPreflight.java +0 -214
- package/android/src/main/java/tools/reekon/pdfcanvas/PdfRendererPool.java +0 -234
- package/android/src/main/java/tools/reekon/pdfcanvas/RasterCancellation.java +0 -47
- package/android/src/main/java/tools/reekon/pdfcanvas/RasterPixels.java +0 -143
- package/android/src/main/java/tools/reekon/pdfcanvas/RasterRequest.java +0 -95
- package/dist/rasterizer/android.d.ts +0 -121
- package/dist/rasterizer/android.js +0 -126
- package/dist/rasterizer/ios.d.ts +0 -84
- package/dist/rasterizer/ios.js +0 -155
- package/ios/Package.swift +0 -58
- package/ios/Sources/PdfCanvasCore/PdfCanvasCancellation.m +0 -38
- package/ios/Sources/PdfCanvasCore/PdfCanvasDocumentPool.m +0 -389
- package/ios/Sources/PdfCanvasCore/PdfCanvasErrorCode.m +0 -57
- package/ios/Sources/PdfCanvasCore/PdfCanvasPageGeometry.m +0 -44
- package/ios/Sources/PdfCanvasCore/PdfCanvasPageTransform.m +0 -82
- package/ios/Sources/PdfCanvasCore/PdfCanvasPixelSink.m +0 -37
- package/ios/Sources/PdfCanvasCore/PdfCanvasPreflight.m +0 -158
- package/ios/Sources/PdfCanvasCore/PdfCanvasRasterPixels.m +0 -80
- package/ios/Sources/PdfCanvasCore/PdfCanvasRasterRequest.m +0 -65
- package/ios/Sources/PdfCanvasCore/PdfCanvasRasterizer.m +0 -548
- package/ios/Sources/PdfCanvasCore/include/PdfCanvasCancellation.h +0 -48
- package/ios/Sources/PdfCanvasCore/include/PdfCanvasCore.h +0 -26
- package/ios/Sources/PdfCanvasCore/include/PdfCanvasDocumentPool.h +0 -122
- package/ios/Sources/PdfCanvasCore/include/PdfCanvasErrorCode.h +0 -80
- package/ios/Sources/PdfCanvasCore/include/PdfCanvasPageGeometry.h +0 -79
- package/ios/Sources/PdfCanvasCore/include/PdfCanvasPageTransform.h +0 -129
- package/ios/Sources/PdfCanvasCore/include/PdfCanvasPixelSink.h +0 -100
- package/ios/Sources/PdfCanvasCore/include/PdfCanvasPreflight.h +0 -65
- package/ios/Sources/PdfCanvasCore/include/PdfCanvasRasterPixels.h +0 -111
- package/ios/Sources/PdfCanvasCore/include/PdfCanvasRasterRequest.h +0 -85
- package/ios/Sources/PdfCanvasCore/include/PdfCanvasRasterizer.h +0 -163
- package/ios/Sources/PdfCanvasSlots/PdfCanvasSlots.mm +0 -297
- package/ios/Sources/PdfCanvasSlots/include/PdfCanvasSlots.h +0 -140
- package/ios/Tests/PdfCanvasCoreTests/ConcurrencyTests.swift +0 -358
- package/ios/Tests/PdfCanvasCoreTests/FailureTests.swift +0 -262
- package/ios/Tests/PdfCanvasCoreTests/GeometryTests.swift +0 -173
- package/ios/Tests/PdfCanvasCoreTests/PreviewTests.swift +0 -114
- package/ios/Tests/PdfCanvasCoreTests/RasterAssertions.swift +0 -158
- package/ios/Tests/PdfCanvasCoreTests/RasterizerTests.swift +0 -544
- package/ios/Tests/PdfCanvasCoreTests/SinkTests.swift +0 -287
- package/ios/Tests/PdfCanvasCoreTests/SlotsTests.swift +0 -396
- package/ios/Tests/PdfCanvasCoreTests/TestPdfs.swift +0 -639
- package/ios/Tests/PdfCanvasCoreTests/TimingTests.swift +0 -179
- package/ios/Tests/PdfCanvasCoreTests/TransformTests.swift +0 -283
|
@@ -1,64 +1,43 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The
|
|
2
|
+
* The wire format between JS and the `PdfCanvas` native module, and everything
|
|
3
|
+
* built on it that is not a per-backend fact.
|
|
3
4
|
*
|
|
4
|
-
* TWO NATIVE
|
|
5
|
-
*
|
|
5
|
+
* TWO NATIVE MODULES, ONE WIRE FORMAT, ONE ADAPTER. `native.ts` is thin over
|
|
6
|
+
* this file: it states the `id`, the `RasterizerCapabilities`, the
|
|
6
7
|
* `AlphaEncoding` and how a `PdfSource` becomes a native source, and everything
|
|
7
8
|
* else — error mapping, page-geometry marshalling, the transport negotiation, the
|
|
8
|
-
* base64
|
|
9
|
-
* identical. That is not tidiness: the spec's whole claim for the iOS step is
|
|
10
|
-
* "the seam is a seam and not an Android-shaped hole", and the cheapest way to
|
|
11
|
-
* be held to it is for the second backend to be unable to drift.
|
|
12
|
-
*
|
|
13
|
-
* PURE ON PURPOSE, exactly as `android.ts` was before it was split. Nothing here
|
|
14
|
-
* imports `react-native`, which is what lets the whole adapter be tested in
|
|
15
|
-
* vitest against a fake native module. `./index.native.ts` is the only file that
|
|
16
|
-
* resolves a real one.
|
|
9
|
+
* base64 codec, the cancellation wiring, the phase timings — is here.
|
|
17
10
|
*
|
|
18
11
|
* WHY THE WIRE FORMAT IS SHARED RATHER THAN MERELY SIMILAR. The two native
|
|
19
|
-
* modules are written
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
12
|
+
* modules are written in different languages — `PdfCanvasModule.java` and
|
|
13
|
+
* `PdfCanvasModule.mm` — over the same C++ core, so the one thing that can still
|
|
14
|
+
* diverge is the shape of the maps they resolve with. One set of TypeScript
|
|
15
|
+
* types for both makes a divergence a failing marshalling test rather than a
|
|
16
|
+
* wrong image on one platform.
|
|
17
|
+
*
|
|
18
|
+
* PURE ON PURPOSE. Nothing here imports `react-native`, which is what lets the
|
|
19
|
+
* whole adapter be tested in vitest against a fake native module.
|
|
20
|
+
* `./index.native.ts` is the only file that resolves a real one. `globalThis` is
|
|
21
|
+
* the only ambient thing this file reads, and it is universal — the
|
|
22
|
+
* `__pdfCanvasTakePixels` lookup finds nothing under vitest and the adapter
|
|
27
23
|
* carries on.
|
|
28
24
|
*/
|
|
29
25
|
import { PdfError } from '../types.js';
|
|
30
26
|
import type { AlphaEncoding, PageGeometry, PageRasterizer, PdfSource, PixelFormat, RasterizerCapabilities, RasterizerHandle, RasterTransport } from '../types.js';
|
|
31
|
-
/**
|
|
32
|
-
* Whether this DEVICE draws a page carrying `/Rotate` upright.
|
|
33
|
-
*
|
|
34
|
-
* A THREE-STATE ANSWER BECAUSE ANDROID GENUINELY HAS THREE. API 24 reports the
|
|
35
|
-
* rotated DIMENSIONS but draws the content unrotated and clipped, while 31 and
|
|
36
|
-
* 33 are correct, and the verdict is measured on device rather than derived from
|
|
37
|
-
* `Build.VERSION` — see `PdfPlatformQuirks`. iOS answers `'supported'`
|
|
38
|
-
* unconditionally: CoreGraphics applies the transform this backend hands it, and
|
|
39
|
-
* `ios/Sources/PdfCanvasCore/PdfCanvasPageTransform.mm` is where `/Rotate`
|
|
40
|
-
* becomes part of that transform, so there is no device variable to probe.
|
|
41
|
-
*
|
|
42
|
-
* It stays on the shared wire format rather than being an Android extension
|
|
43
|
-
* precisely so a host does not have to know which platform it is on to ask.
|
|
44
|
-
*/
|
|
45
|
-
export type NativeRotationSupport = 'supported' | 'unsupported' | 'unknown';
|
|
46
27
|
export interface NativePdfPage {
|
|
47
28
|
index: number;
|
|
29
|
+
/** Post-rotation, in PDF points. A double: A4 is 595.276 wide. */
|
|
48
30
|
width: number;
|
|
49
31
|
height: number;
|
|
50
32
|
/**
|
|
51
|
-
*
|
|
33
|
+
* Always 0 from the native core, and informational everywhere.
|
|
52
34
|
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
* the web PDFium backend.
|
|
60
|
-
* - Android reports 0, because `PdfRenderer` exposes no way to read `/Rotate`
|
|
61
|
-
* below API 35. That is an inability, not a policy.
|
|
35
|
+
* PDFium pre-applies `/Rotate` to both the size above and the render, so
|
|
36
|
+
* there is no residual rotation for a caller to apply, and reading the raw
|
|
37
|
+
* `/Rotate` would need `FPDF_LoadPage` — which parses the content stream, the
|
|
38
|
+
* one thing `pageGeometry` is forbidden to do. The web backend reports the
|
|
39
|
+
* real value through an `@embedpdf` extension that has no stock-PDFium
|
|
40
|
+
* counterpart. No consumer rotates anything on the strength of this field.
|
|
62
41
|
*/
|
|
63
42
|
rotation: number;
|
|
64
43
|
}
|
|
@@ -66,7 +45,6 @@ export interface NativeOpenResult {
|
|
|
66
45
|
handle: number;
|
|
67
46
|
pageCount: number;
|
|
68
47
|
pages: NativePdfPage[];
|
|
69
|
-
rotationSupport: NativeRotationSupport;
|
|
70
48
|
}
|
|
71
49
|
export interface NativeRenderResult {
|
|
72
50
|
/**
|
|
@@ -110,9 +88,14 @@ export interface NativeSource {
|
|
|
110
88
|
password?: string;
|
|
111
89
|
}
|
|
112
90
|
export interface PdfCanvasNativeModule {
|
|
113
|
-
open(source: NativeSource
|
|
91
|
+
open(source: NativeSource): Promise<NativeOpenResult>;
|
|
114
92
|
render(handle: number, request: NativeRenderRequest, token: number): Promise<NativeRenderResult>;
|
|
115
|
-
/**
|
|
93
|
+
/**
|
|
94
|
+
* Sets the signal the render polls — including MID-RENDER, through PDFium's
|
|
95
|
+
* progressive API — so a superseded tile stops within one batch of page
|
|
96
|
+
* objects. A cancel for a token whose render already finished finds nothing
|
|
97
|
+
* and does nothing.
|
|
98
|
+
*/
|
|
116
99
|
cancel(handle: number, token: number): void;
|
|
117
100
|
close(handle: number): void;
|
|
118
101
|
/**
|
|
@@ -160,21 +143,26 @@ export declare function toPdfError(error: unknown, fallback: string): PdfError;
|
|
|
160
143
|
*/
|
|
161
144
|
export declare function decodeBase64(input: string): Uint8Array;
|
|
162
145
|
/**
|
|
163
|
-
*
|
|
164
|
-
*
|
|
146
|
+
* The encoder, for the one thing that travels JS -> native as bytes: a document
|
|
147
|
+
* opened from memory. Hand-rolled for the same reasons as the decoder — no
|
|
148
|
+
* `Buffer` on RN, and `btoa` wants a string. Standard alphabet, `=` padding, no
|
|
149
|
+
* line breaks, which is what both native modules' decoders accept.
|
|
150
|
+
*/
|
|
151
|
+
export declare function encodeBase64(bytes: Uint8Array): string;
|
|
152
|
+
/**
|
|
153
|
+
* Mirrors `slots::probeBytes()` in `native/core/src/slots.cpp` (the one store
|
|
154
|
+
* both platforms now share) and `PdfCanvasNative.PROBE_BYTES` in Java.
|
|
165
155
|
*
|
|
166
|
-
* The
|
|
167
|
-
*
|
|
156
|
+
* The lists are restated rather than derived, which is the point: they are the
|
|
157
|
+
* only places the transport's byte fidelity is asserted, and if one is edited
|
|
168
158
|
* without the others the probe fails and that platform degrades to base64 rather
|
|
169
159
|
* than shipping a shear.
|
|
170
160
|
*
|
|
171
161
|
* The contents are chosen, not arbitrary. 0x00 and 0xFF pin both ends of the
|
|
172
162
|
* range; 0xFD/0xFE/0xFF are above 0x7F, where Java's SIGNED byte and a
|
|
173
|
-
* JS `Uint8Array` disagree unless every step of the copy is right.
|
|
174
|
-
*
|
|
175
|
-
*
|
|
176
|
-
* external memory at all, which is a claim about a JS engine version and not
|
|
177
|
-
* about a language.)
|
|
163
|
+
* JS `Uint8Array` disagree unless every step of the copy is right. The probe's
|
|
164
|
+
* other job is platform-blind: it proves the runtime will build an ArrayBuffer
|
|
165
|
+
* over external memory at all, which is a claim about a JS engine version.
|
|
178
166
|
*/
|
|
179
167
|
export declare const TRANSPORT_PROBE_BYTES: readonly number[];
|
|
180
168
|
/**
|
|
@@ -226,36 +214,24 @@ export declare function bytesFromResult(result: NativeRenderResult, transport: N
|
|
|
226
214
|
payloadChars: number;
|
|
227
215
|
used: RasterTransport;
|
|
228
216
|
};
|
|
229
|
-
|
|
230
|
-
* Surfaced so a host can decide what to do about a device that does not draw
|
|
231
|
-
* rotated pages upright — warn, fall back, or accept it.
|
|
232
|
-
*/
|
|
233
|
-
export interface NativeRasterizerHandle extends RasterizerHandle {
|
|
234
|
-
readonly rotationSupport: NativeRotationSupport;
|
|
235
|
-
}
|
|
236
|
-
export declare function createNativeHandle(native: PdfCanvasNativeModule, opened: NativeOpenResult, transport: NativeTransport, alpha: AlphaEncoding, label: string): NativeRasterizerHandle;
|
|
217
|
+
export declare function createNativeHandle(native: PdfCanvasNativeModule, opened: NativeOpenResult, transport: NativeTransport, alpha: AlphaEncoding, label: string): RasterizerHandle;
|
|
237
218
|
export interface NativeRasterizerSpec {
|
|
238
219
|
/** Surfaced as `PageRasterizer.id`, so a bug report names a backend. */
|
|
239
220
|
id: string;
|
|
240
|
-
/**
|
|
241
|
-
* Everything except `maxConcurrentRenders` and `transport`, both of which are
|
|
242
|
-
* resolved here — the first from the pool size actually asked for, the second
|
|
243
|
-
* from the negotiation.
|
|
244
|
-
*/
|
|
221
|
+
/** Everything except `transport`, which is resolved here from the negotiation. */
|
|
245
222
|
capabilities: RasterizerCapabilities;
|
|
246
|
-
/** What
|
|
223
|
+
/** What the engine's bitmaps encode. Never defaulted — see `AlphaEncoding`. */
|
|
247
224
|
alpha: AlphaEncoding;
|
|
248
|
-
/** Clamped concurrent renders, already resolved by the caller. */
|
|
249
|
-
poolSize: number;
|
|
250
225
|
/** Named in the "handle is closed" message. */
|
|
251
226
|
label: string;
|
|
252
227
|
toNativeSource: (source: PdfSource) => NativeSource;
|
|
253
228
|
lookupTakePixels?: () => TakePixels | null;
|
|
254
229
|
}
|
|
255
230
|
/**
|
|
256
|
-
* Wraps a native module in a `PageRasterizer
|
|
231
|
+
* Wraps a native module in a `PageRasterizer`, given the facts only the backend
|
|
232
|
+
* knows. `native.ts` is the one caller.
|
|
257
233
|
*
|
|
258
234
|
* The native module is INJECTED rather than imported so this file stays pure.
|
|
259
235
|
* `getDefaultRasterizer()` in `./index.native.ts` supplies the real one.
|
|
260
236
|
*/
|
|
261
|
-
export declare function
|
|
237
|
+
export declare function createRasterizerOverBridge(native: PdfCanvasNativeModule, spec: NativeRasterizerSpec): PageRasterizer;
|
|
@@ -1,29 +1,25 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The
|
|
2
|
+
* The wire format between JS and the `PdfCanvas` native module, and everything
|
|
3
|
+
* built on it that is not a per-backend fact.
|
|
3
4
|
*
|
|
4
|
-
* TWO NATIVE
|
|
5
|
-
*
|
|
5
|
+
* TWO NATIVE MODULES, ONE WIRE FORMAT, ONE ADAPTER. `native.ts` is thin over
|
|
6
|
+
* this file: it states the `id`, the `RasterizerCapabilities`, the
|
|
6
7
|
* `AlphaEncoding` and how a `PdfSource` becomes a native source, and everything
|
|
7
8
|
* else — error mapping, page-geometry marshalling, the transport negotiation, the
|
|
8
|
-
* base64
|
|
9
|
-
* identical. That is not tidiness: the spec's whole claim for the iOS step is
|
|
10
|
-
* "the seam is a seam and not an Android-shaped hole", and the cheapest way to
|
|
11
|
-
* be held to it is for the second backend to be unable to drift.
|
|
12
|
-
*
|
|
13
|
-
* PURE ON PURPOSE, exactly as `android.ts` was before it was split. Nothing here
|
|
14
|
-
* imports `react-native`, which is what lets the whole adapter be tested in
|
|
15
|
-
* vitest against a fake native module. `./index.native.ts` is the only file that
|
|
16
|
-
* resolves a real one.
|
|
9
|
+
* base64 codec, the cancellation wiring, the phase timings — is here.
|
|
17
10
|
*
|
|
18
11
|
* WHY THE WIRE FORMAT IS SHARED RATHER THAN MERELY SIMILAR. The two native
|
|
19
|
-
* modules are written
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
12
|
+
* modules are written in different languages — `PdfCanvasModule.java` and
|
|
13
|
+
* `PdfCanvasModule.mm` — over the same C++ core, so the one thing that can still
|
|
14
|
+
* diverge is the shape of the maps they resolve with. One set of TypeScript
|
|
15
|
+
* types for both makes a divergence a failing marshalling test rather than a
|
|
16
|
+
* wrong image on one platform.
|
|
24
17
|
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
18
|
+
* PURE ON PURPOSE. Nothing here imports `react-native`, which is what lets the
|
|
19
|
+
* whole adapter be tested in vitest against a fake native module.
|
|
20
|
+
* `./index.native.ts` is the only file that resolves a real one. `globalThis` is
|
|
21
|
+
* the only ambient thing this file reads, and it is universal — the
|
|
22
|
+
* `__pdfCanvasTakePixels` lookup finds nothing under vitest and the adapter
|
|
27
23
|
* carries on.
|
|
28
24
|
*/
|
|
29
25
|
import { monotonicNow } from '../clock.js';
|
|
@@ -111,25 +107,43 @@ export function decodeBase64(input) {
|
|
|
111
107
|
}
|
|
112
108
|
return outIndex === out.length ? out : out.subarray(0, outIndex).slice();
|
|
113
109
|
}
|
|
110
|
+
/**
|
|
111
|
+
* The encoder, for the one thing that travels JS -> native as bytes: a document
|
|
112
|
+
* opened from memory. Hand-rolled for the same reasons as the decoder — no
|
|
113
|
+
* `Buffer` on RN, and `btoa` wants a string. Standard alphabet, `=` padding, no
|
|
114
|
+
* line breaks, which is what both native modules' decoders accept.
|
|
115
|
+
*/
|
|
116
|
+
export function encodeBase64(bytes) {
|
|
117
|
+
let out = '';
|
|
118
|
+
for (let i = 0; i < bytes.length; i += 3) {
|
|
119
|
+
const b0 = bytes[i] ?? 0;
|
|
120
|
+
const b1 = bytes[i + 1] ?? 0;
|
|
121
|
+
const b2 = bytes[i + 2] ?? 0;
|
|
122
|
+
const remaining = bytes.length - i;
|
|
123
|
+
out += BASE64_ALPHABET[b0 >> 2];
|
|
124
|
+
out += BASE64_ALPHABET[((b0 & 3) << 4) | (b1 >> 4)];
|
|
125
|
+
out += remaining > 1 ? BASE64_ALPHABET[((b1 & 15) << 2) | (b2 >> 6)] : '=';
|
|
126
|
+
out += remaining > 2 ? BASE64_ALPHABET[b2 & 63] : '=';
|
|
127
|
+
}
|
|
128
|
+
return out;
|
|
129
|
+
}
|
|
114
130
|
/* ------------------------------------------------------------------ *
|
|
115
131
|
* Transport negotiation
|
|
116
132
|
* ------------------------------------------------------------------ */
|
|
117
133
|
/**
|
|
118
|
-
* Mirrors `
|
|
119
|
-
* `
|
|
134
|
+
* Mirrors `slots::probeBytes()` in `native/core/src/slots.cpp` (the one store
|
|
135
|
+
* both platforms now share) and `PdfCanvasNative.PROBE_BYTES` in Java.
|
|
120
136
|
*
|
|
121
|
-
* The
|
|
122
|
-
*
|
|
137
|
+
* The lists are restated rather than derived, which is the point: they are the
|
|
138
|
+
* only places the transport's byte fidelity is asserted, and if one is edited
|
|
123
139
|
* without the others the probe fails and that platform degrades to base64 rather
|
|
124
140
|
* than shipping a shear.
|
|
125
141
|
*
|
|
126
142
|
* The contents are chosen, not arbitrary. 0x00 and 0xFF pin both ends of the
|
|
127
143
|
* range; 0xFD/0xFE/0xFF are above 0x7F, where Java's SIGNED byte and a
|
|
128
|
-
* JS `Uint8Array` disagree unless every step of the copy is right.
|
|
129
|
-
*
|
|
130
|
-
*
|
|
131
|
-
* external memory at all, which is a claim about a JS engine version and not
|
|
132
|
-
* about a language.)
|
|
144
|
+
* JS `Uint8Array` disagree unless every step of the copy is right. The probe's
|
|
145
|
+
* other job is platform-blind: it proves the runtime will build an ArrayBuffer
|
|
146
|
+
* over external memory at all, which is a claim about a JS engine version.
|
|
133
147
|
*/
|
|
134
148
|
export const TRANSPORT_PROBE_BYTES = [
|
|
135
149
|
0x00, 0x01, 0x02, 0xfd, 0xfe, 0xff, 0x2a, 0x07,
|
|
@@ -279,6 +293,9 @@ export function bytesFromResult(result, transport) {
|
|
|
279
293
|
}
|
|
280
294
|
throw new PdfError('backend-failure', 'The native module returned neither `base64` nor `pixelsSlot`.');
|
|
281
295
|
}
|
|
296
|
+
/* ------------------------------------------------------------------ *
|
|
297
|
+
* The handle
|
|
298
|
+
* ------------------------------------------------------------------ */
|
|
282
299
|
export function createNativeHandle(native, opened, transport, alpha, label) {
|
|
283
300
|
const pages = opened.pages.map(toPageGeometry);
|
|
284
301
|
let closed = false;
|
|
@@ -294,7 +311,6 @@ export function createNativeHandle(native, opened, transport, alpha, label) {
|
|
|
294
311
|
};
|
|
295
312
|
return {
|
|
296
313
|
pageCount: opened.pageCount,
|
|
297
|
-
rotationSupport: opened.rotationSupport,
|
|
298
314
|
pageGeometry: requirePage,
|
|
299
315
|
async render(request, signal) {
|
|
300
316
|
if (closed) {
|
|
@@ -379,12 +395,13 @@ export function createNativeHandle(native, opened, transport, alpha, label) {
|
|
|
379
395
|
};
|
|
380
396
|
}
|
|
381
397
|
/**
|
|
382
|
-
* Wraps a native module in a `PageRasterizer
|
|
398
|
+
* Wraps a native module in a `PageRasterizer`, given the facts only the backend
|
|
399
|
+
* knows. `native.ts` is the one caller.
|
|
383
400
|
*
|
|
384
401
|
* The native module is INJECTED rather than imported so this file stays pure.
|
|
385
402
|
* `getDefaultRasterizer()` in `./index.native.ts` supplies the real one.
|
|
386
403
|
*/
|
|
387
|
-
export function
|
|
404
|
+
export function createRasterizerOverBridge(native, spec) {
|
|
388
405
|
// ONCE, here, and not lazily on first render. The probe is two synchronous
|
|
389
406
|
// bridge calls and an eight-byte round trip, so it costs nothing worth
|
|
390
407
|
// deferring — and doing it now is what lets `capabilities.transport` be true
|
|
@@ -393,7 +410,6 @@ export function createNativeRasterizer(native, spec) {
|
|
|
393
410
|
const transport = negotiateTransport(native, spec.lookupTakePixels ?? lookupTakePixels);
|
|
394
411
|
const capabilities = {
|
|
395
412
|
...spec.capabilities,
|
|
396
|
-
maxConcurrentRenders: spec.poolSize,
|
|
397
413
|
transport: transport.kind,
|
|
398
414
|
};
|
|
399
415
|
return {
|
|
@@ -402,7 +418,7 @@ export function createNativeRasterizer(native, spec) {
|
|
|
402
418
|
async open(source) {
|
|
403
419
|
let opened;
|
|
404
420
|
try {
|
|
405
|
-
opened = await native.open(spec.toNativeSource(source)
|
|
421
|
+
opened = await native.open(spec.toNativeSource(source));
|
|
406
422
|
}
|
|
407
423
|
catch (error) {
|
|
408
424
|
throw toPdfError(error, 'Could not open the document');
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The TypeScript half of the native backend — ONE adapter for iOS and Android.
|
|
3
|
+
*
|
|
4
|
+
* There used to be two (`android.ts`, `ios.ts`), and the split was load-bearing:
|
|
5
|
+
* the platforms differed in engine (PdfRenderer vs CoreGraphics/PDFKit), in
|
|
6
|
+
* alpha encoding, in whether `annotations: false` was honoured, in whether a
|
|
7
|
+
* password was accepted, in what `PageGeometry.rotation` meant, and in how many
|
|
8
|
+
* render lanes made sense. Every one of those differences is gone. Both native
|
|
9
|
+
* modules now marshal to the same C++ core (`native/core`) linked against the
|
|
10
|
+
* same pinned PDFium release the web backend runs, so what this file states —
|
|
11
|
+
* capabilities, alpha, source handling — is one truth with no platform branch,
|
|
12
|
+
* and a tile rendered on an iPhone is byte-identical to the same tile on a
|
|
13
|
+
* Pixel and in a browser.
|
|
14
|
+
*
|
|
15
|
+
* PURE ON PURPOSE. Nothing here imports `react-native`, which is what lets the
|
|
16
|
+
* whole adapter be tested in vitest against a fake native module.
|
|
17
|
+
* `./index.native.ts` is the only file that resolves the real one.
|
|
18
|
+
*
|
|
19
|
+
* The native side is proven on a laptop by `native/tests` (the core, against
|
|
20
|
+
* real PDFium) and by `android/tools/compile-gate.sh` (the JNI seam); the iOS
|
|
21
|
+
* binding's only proof is a device session, as it always was.
|
|
22
|
+
*/
|
|
23
|
+
import type { TakePixels } from './native-bridge.js';
|
|
24
|
+
import type { PageRasterizer, RasterizerCapabilities } from '../types.js';
|
|
25
|
+
export { TRANSPORT_PROBE_BYTES, bytesFromResult, decodeBase64, encodeBase64, lookupTakePixels, negotiateTransport, toPageGeometry, } from './native-bridge.js';
|
|
26
|
+
export type { NativeOpenResult, NativePdfPage, NativeRenderRequest, NativeRenderResult, NativeSource, NativeTransport, PdfCanvasNativeModule, TakePixels, } from './native-bridge.js';
|
|
27
|
+
export type NativePlatform = 'ios' | 'android';
|
|
28
|
+
export declare const NATIVE_CAPABILITIES: RasterizerCapabilities;
|
|
29
|
+
export interface NativeRasterizerOptions {
|
|
30
|
+
/** Named in the `id` and in error messages. Diagnostics only. */
|
|
31
|
+
platform?: NativePlatform;
|
|
32
|
+
id?: string;
|
|
33
|
+
/**
|
|
34
|
+
* How to find the installed JSI host function. Injected only by tests; the
|
|
35
|
+
* default reads `globalThis`.
|
|
36
|
+
*/
|
|
37
|
+
lookupTakePixels?: () => TakePixels | null;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Wraps the `PdfCanvas` native module in a `PageRasterizer`.
|
|
41
|
+
*
|
|
42
|
+
* The native module is INJECTED rather than imported so this file stays pure.
|
|
43
|
+
* `getDefaultRasterizer()` in `./index.native.ts` supplies the real one.
|
|
44
|
+
*/
|
|
45
|
+
export declare function createNativeRasterizer(native: import('./native-bridge.js').PdfCanvasNativeModule, options?: NativeRasterizerOptions): PageRasterizer;
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The TypeScript half of the native backend — ONE adapter for iOS and Android.
|
|
3
|
+
*
|
|
4
|
+
* There used to be two (`android.ts`, `ios.ts`), and the split was load-bearing:
|
|
5
|
+
* the platforms differed in engine (PdfRenderer vs CoreGraphics/PDFKit), in
|
|
6
|
+
* alpha encoding, in whether `annotations: false` was honoured, in whether a
|
|
7
|
+
* password was accepted, in what `PageGeometry.rotation` meant, and in how many
|
|
8
|
+
* render lanes made sense. Every one of those differences is gone. Both native
|
|
9
|
+
* modules now marshal to the same C++ core (`native/core`) linked against the
|
|
10
|
+
* same pinned PDFium release the web backend runs, so what this file states —
|
|
11
|
+
* capabilities, alpha, source handling — is one truth with no platform branch,
|
|
12
|
+
* and a tile rendered on an iPhone is byte-identical to the same tile on a
|
|
13
|
+
* Pixel and in a browser.
|
|
14
|
+
*
|
|
15
|
+
* PURE ON PURPOSE. Nothing here imports `react-native`, which is what lets the
|
|
16
|
+
* whole adapter be tested in vitest against a fake native module.
|
|
17
|
+
* `./index.native.ts` is the only file that resolves the real one.
|
|
18
|
+
*
|
|
19
|
+
* The native side is proven on a laptop by `native/tests` (the core, against
|
|
20
|
+
* real PDFium) and by `android/tools/compile-gate.sh` (the JNI seam); the iOS
|
|
21
|
+
* binding's only proof is a device session, as it always was.
|
|
22
|
+
*/
|
|
23
|
+
import { createRasterizerOverBridge, encodeBase64 } from './native-bridge.js';
|
|
24
|
+
import { PdfError } from '../types.js';
|
|
25
|
+
export { TRANSPORT_PROBE_BYTES, bytesFromResult, decodeBase64, encodeBase64, lookupTakePixels, negotiateTransport, toPageGeometry, } from './native-bridge.js';
|
|
26
|
+
/**
|
|
27
|
+
* STRAIGHT (un-premultiplied), and — unlike the two constants this replaces —
|
|
28
|
+
* a measurement of the engine rather than of a platform bitmap type.
|
|
29
|
+
*
|
|
30
|
+
* MEASURED in `native/tests` (`alphaIsStraight`): every partially covered pixel
|
|
31
|
+
* of an antialiased opaque-white edge over a transparent page reads
|
|
32
|
+
* `[255, 255, 255, a]`, where premultiplied would be `[a, a, a, a]`. It matches
|
|
33
|
+
* the web backend for the only good reason two backends can match: they are the
|
|
34
|
+
* same engine. The retired cores were both `'premultiplied'` — Android because
|
|
35
|
+
* `Bitmap` is, iOS because `CGBitmapContext` offers nothing else — which is why
|
|
36
|
+
* `RasterPixels.alpha` is a required field and `ingest.ts` has no default.
|
|
37
|
+
*
|
|
38
|
+
* Invisible under `background: 'white'`, where every pixel is opaque; wrong
|
|
39
|
+
* under `'transparent'`, which is in the contract.
|
|
40
|
+
*/
|
|
41
|
+
const NATIVE_ALPHA = 'straight';
|
|
42
|
+
export const NATIVE_CAPABILITIES = Object.freeze({
|
|
43
|
+
/**
|
|
44
|
+
* True in BOTH directions, on both platforms. `annotations: true` passes
|
|
45
|
+
* `FPDF_ANNOT` and draws form fields through `FPDF_FFLDraw`; `false` draws
|
|
46
|
+
* the content stream alone. Android could not do the second and iOS did it
|
|
47
|
+
* through a different engine than its tiles; neither caveat survives.
|
|
48
|
+
*/
|
|
49
|
+
annotations: true,
|
|
50
|
+
/**
|
|
51
|
+
* TRUE, for the first time on a native backend. The core renders through
|
|
52
|
+
* PDFium's progressive API and polls the cancellation signal between batches
|
|
53
|
+
* of page objects, so an abort stops a superseded tile mid-draw rather than
|
|
54
|
+
* merely preventing the next one from starting. `RasterPolicy.
|
|
55
|
+
* minEpochIntervalMs` was written for engines that could not do this.
|
|
56
|
+
*/
|
|
57
|
+
interruptibleRender: true,
|
|
58
|
+
/**
|
|
59
|
+
* FALSE, AND A DECLARATION ABOUT THE PACKAGE, NOT THE ENGINE. PDFium has
|
|
60
|
+
* text extraction, search and link enumeration, so all three could be true
|
|
61
|
+
* the day a surface for them exists. It does not — see the non-goals — and a
|
|
62
|
+
* capability that says "yes" about an API no consumer can reach is worse
|
|
63
|
+
* than one that says "no".
|
|
64
|
+
*/
|
|
65
|
+
text: false,
|
|
66
|
+
search: false,
|
|
67
|
+
links: false,
|
|
68
|
+
/**
|
|
69
|
+
* ONE. PDFium is not thread-safe — not across documents, not across threads
|
|
70
|
+
* — so the core serialises every call behind a process-wide lock, and a
|
|
71
|
+
* second lane would only queue behind the first while holding a promise
|
|
72
|
+
* open. Neither retired core did better in practice: Android measured every
|
|
73
|
+
* lane count above one as SLOWER (AOSP's lock convoyed), and iOS defaulted
|
|
74
|
+
* to one because a second was never measured to help. What replaces
|
|
75
|
+
* parallelism is cancellation: a stale render gives the lock up within one
|
|
76
|
+
* progressive batch.
|
|
77
|
+
*/
|
|
78
|
+
maxConcurrentRenders: 1,
|
|
79
|
+
});
|
|
80
|
+
/**
|
|
81
|
+
* A `uri` passes straight through. Bytes are ACCEPTED — both native modules
|
|
82
|
+
* open a memory document — but cross the bridge as base64, which for a
|
|
83
|
+
* document is a one-off cost proportional to its size (a 20 MB drawing is a
|
|
84
|
+
* ~27 MB string, marshalled once). Prefer a `uri` where one exists: the
|
|
85
|
+
* previous adapters refused bytes outright for this reason, and refusing was
|
|
86
|
+
* the wrong trade once the engine could take them, but the cost is real.
|
|
87
|
+
*/
|
|
88
|
+
function toNativeSource(source) {
|
|
89
|
+
const password = source.password;
|
|
90
|
+
const withPassword = (bare) => password === undefined ? bare : { ...bare, password };
|
|
91
|
+
if ('uri' in source) {
|
|
92
|
+
return withPassword({ uri: source.uri });
|
|
93
|
+
}
|
|
94
|
+
if (source.data.byteLength === 0) {
|
|
95
|
+
throw new PdfError('corrupt', 'The document is empty (0 bytes).');
|
|
96
|
+
}
|
|
97
|
+
return withPassword({ base64: encodeBase64(source.data) });
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Wraps the `PdfCanvas` native module in a `PageRasterizer`.
|
|
101
|
+
*
|
|
102
|
+
* The native module is INJECTED rather than imported so this file stays pure.
|
|
103
|
+
* `getDefaultRasterizer()` in `./index.native.ts` supplies the real one.
|
|
104
|
+
*/
|
|
105
|
+
export function createNativeRasterizer(native, options = {}) {
|
|
106
|
+
const platform = options.platform;
|
|
107
|
+
return createRasterizerOverBridge(native, {
|
|
108
|
+
// `ios-pdfium` / `android-pdfium`: the engine is what a bug report needs
|
|
109
|
+
// to name, and it is the same word on both platforms now.
|
|
110
|
+
id: options.id ?? `${platform ?? 'native'}-pdfium`,
|
|
111
|
+
capabilities: NATIVE_CAPABILITIES,
|
|
112
|
+
alpha: NATIVE_ALPHA,
|
|
113
|
+
label: platform === 'ios'
|
|
114
|
+
? 'iOS'
|
|
115
|
+
: platform === 'android'
|
|
116
|
+
? 'Android'
|
|
117
|
+
: 'Native',
|
|
118
|
+
toNativeSource,
|
|
119
|
+
...(options.lookupTakePixels === undefined
|
|
120
|
+
? {}
|
|
121
|
+
: { lookupTakePixels: options.lookupTakePixels }),
|
|
122
|
+
});
|
|
123
|
+
}
|
|
@@ -45,12 +45,12 @@ export interface PdfRenderOptions {
|
|
|
45
45
|
/** Target width in device pixels; derives `scale` from `docRect.width`. */
|
|
46
46
|
widthPx?: number;
|
|
47
47
|
/**
|
|
48
|
-
* Draw PDF-embedded annotations into the raster.
|
|
48
|
+
* Draw PDF-embedded annotations (and form fields) into the raster.
|
|
49
49
|
*
|
|
50
|
-
* Defaults to TRUE
|
|
51
|
-
* look like the document does in any other viewer
|
|
52
|
-
*
|
|
53
|
-
*
|
|
50
|
+
* Defaults to TRUE — a file raster (thumbnail, print, hero) is expected to
|
|
51
|
+
* look like the document does in any other viewer, and so are the layer's
|
|
52
|
+
* tiles (`UsePdfLayerOptions.annotations`, same default). Silently downgraded
|
|
53
|
+
* to false if the backend cannot do it; every shipped backend can.
|
|
54
54
|
*/
|
|
55
55
|
annotations?: boolean;
|
|
56
56
|
/**
|
|
@@ -79,6 +79,15 @@ export interface UsePdfLayerOptions {
|
|
|
79
79
|
layout?: PdfPageLayout;
|
|
80
80
|
/** Overrides merged over the default `RasterPolicy`. */
|
|
81
81
|
policy?: Partial<RasterPolicy>;
|
|
82
|
+
/**
|
|
83
|
+
* Draw the PDF's own annotations and form fields into the tiles.
|
|
84
|
+
*
|
|
85
|
+
* @default true — the page looks as it does in any other viewer. Pass false
|
|
86
|
+
* only if the host imports the PDF's annotations into its own Skia layer and
|
|
87
|
+
* would otherwise show each one twice. Changing it REBUILDS the controller
|
|
88
|
+
* and its raster cache: every cached tile was rendered one way or the other.
|
|
89
|
+
*/
|
|
90
|
+
annotations?: boolean;
|
|
82
91
|
onDiagnostic?: (diagnostic: PdfDiagnostic) => void;
|
|
83
92
|
}
|
|
84
93
|
export interface PdfLayer {
|
|
@@ -91,4 +100,4 @@ export interface PdfLayer {
|
|
|
91
100
|
*/
|
|
92
101
|
controller: PdfController;
|
|
93
102
|
}
|
|
94
|
-
export declare function usePdfLayer({ document, pages: pageSelection, layout, policy, onDiagnostic, }: UsePdfLayerOptions): PdfLayer;
|
|
103
|
+
export declare function usePdfLayer({ document, pages: pageSelection, layout, policy, annotations, onDiagnostic, }: UsePdfLayerOptions): PdfLayer;
|
|
@@ -181,7 +181,7 @@ export function usePdfLayer({ document,
|
|
|
181
181
|
// The PUBLIC name stays `pages`; locally it is the SELECTION, and the
|
|
182
182
|
// controller's own `pages` is the per-page geometry. Two very different things
|
|
183
183
|
// one rename apart.
|
|
184
|
-
pages: pageSelection = DEFAULT_PAGE_SELECTION, layout, policy, onDiagnostic, }) {
|
|
184
|
+
pages: pageSelection = DEFAULT_PAGE_SELECTION, layout, policy, annotations = true, onDiagnostic, }) {
|
|
185
185
|
// The diagnostic callback is almost always an inline arrow. Route it through a
|
|
186
186
|
// ref so a fresh identity on every render never counts as a reason to rebuild
|
|
187
187
|
// the controller.
|
|
@@ -254,6 +254,7 @@ pages: pageSelection = DEFAULT_PAGE_SELECTION, layout, policy, onDiagnostic, })
|
|
|
254
254
|
// before the field existed) means 1, which is the sequential behaviour
|
|
255
255
|
// every backend was proven against.
|
|
256
256
|
maxConcurrentRenders: document.capabilities.maxConcurrentRenders,
|
|
257
|
+
annotations,
|
|
257
258
|
onDiagnostic: emitDiagnostic,
|
|
258
259
|
backendId: document.rasterizerId,
|
|
259
260
|
});
|
|
@@ -277,7 +278,14 @@ pages: pageSelection = DEFAULT_PAGE_SELECTION, layout, policy, onDiagnostic, })
|
|
|
277
278
|
// cost of the teardown is one page's rasters, which is the page you are turning
|
|
278
279
|
// to and would have paid for anyway. See `__tests__/single-page.test.ts`.
|
|
279
280
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
280
|
-
[
|
|
281
|
+
[
|
|
282
|
+
document,
|
|
283
|
+
pageRects,
|
|
284
|
+
pagesKey,
|
|
285
|
+
policySignature,
|
|
286
|
+
annotations,
|
|
287
|
+
emitDiagnostic,
|
|
288
|
+
]);
|
|
281
289
|
const instance = layer?.controller ?? null;
|
|
282
290
|
useEffect(() => {
|
|
283
291
|
if (layer === null) {
|
|
@@ -7,8 +7,12 @@
|
|
|
7
7
|
*
|
|
8
8
|
* The one thing it adds over the shared barrel is installing the native
|
|
9
9
|
* resolver, so a consumer who imports ONLY this subpath still gets a working
|
|
10
|
-
* `skiaApi()`. The call
|
|
11
|
-
* `
|
|
12
|
-
*
|
|
10
|
+
* `skiaApi()`. The call only survives a bundler because this file is NAMED in
|
|
11
|
+
* `package.json#sideEffects`: a module that declares no used binding of its
|
|
12
|
+
* own (this one only re-exports) is otherwise never marked executed by
|
|
13
|
+
* Rollup, and its top-level statements go with it — a call on an imported
|
|
14
|
+
* binding is no safer than a bare `import './x.js'`. That is exactly how the
|
|
15
|
+
* web twin's install was dropped from the production web build once; see
|
|
16
|
+
* `__tests__/tree-shaking.test.ts`.
|
|
13
17
|
*/
|
|
14
18
|
export * from './index.js';
|
|
@@ -7,9 +7,13 @@
|
|
|
7
7
|
*
|
|
8
8
|
* The one thing it adds over the shared barrel is installing the native
|
|
9
9
|
* resolver, so a consumer who imports ONLY this subpath still gets a working
|
|
10
|
-
* `skiaApi()`. The call
|
|
11
|
-
* `
|
|
12
|
-
*
|
|
10
|
+
* `skiaApi()`. The call only survives a bundler because this file is NAMED in
|
|
11
|
+
* `package.json#sideEffects`: a module that declares no used binding of its
|
|
12
|
+
* own (this one only re-exports) is otherwise never marked executed by
|
|
13
|
+
* Rollup, and its top-level statements go with it — a call on an imported
|
|
14
|
+
* binding is no safer than a bare `import './x.js'`. That is exactly how the
|
|
15
|
+
* web twin's install was dropped from the production web build once; see
|
|
16
|
+
* `__tests__/tree-shaking.test.ts`.
|
|
13
17
|
*/
|
|
14
18
|
import { installNativeSkiaResolver } from './resolve.native.js';
|
|
15
19
|
export * from './index.js';
|
package/dist/skia/index.web.d.ts
CHANGED
|
@@ -6,7 +6,9 @@
|
|
|
6
6
|
* install itself decides nothing: it stores a closure, and
|
|
7
7
|
* `globalThis.CanvasKit` is not read until the first raster.
|
|
8
8
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
9
|
+
* This file is named in `package.json#sideEffects`, and must stay there: it
|
|
10
|
+
* declares no binding of its own, so without the listing Rollup never marks it
|
|
11
|
+
* executed and the install below is dropped. See `index.native.ts` and
|
|
12
|
+
* `__tests__/tree-shaking.test.ts`.
|
|
11
13
|
*/
|
|
12
14
|
export * from './index.js';
|