@hrforte/react-pivottable 2.2.1 → 3.0.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.
@@ -6,7 +6,12 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.DEFAULT_WORKER_URL = undefined;
7
7
  exports.setWorkerDebug = setWorkerDebug;
8
8
  exports.configureWorkerUrl = configureWorkerUrl;
9
+ exports.retainPivotWorker = retainPivotWorker;
10
+ exports.releasePivotWorker = releasePivotWorker;
9
11
  exports.computePivotInWorker = computePivotInWorker;
12
+ exports.computePivotViewportInWorker = computePivotViewportInWorker;
13
+ exports.releasePivotInWorker = releasePivotInWorker;
14
+ exports.releaseDatasetInWorker = releaseDatasetInWorker;
10
15
  exports.computePivotSynchronously = computePivotSynchronously;
11
16
  exports.computePivotWithFallback = computePivotWithFallback;
12
17
 
@@ -21,8 +26,7 @@ var DEFAULT_WORKER_URL = exports.DEFAULT_WORKER_URL = 'pivot-worker.js'; /* esli
21
26
  * Responsibilities:
22
27
  * - lazily create a single shared Worker (at `workerUrl`, overrideable),
23
28
  * - route result/error messages to the matching request,
24
- * - transparently fall back to a synchronous main-thread computation when
25
- * workers are unavailable or the worker bundle fails to load.
29
+ * - surface worker errors instead of silently recomputing on the main thread.
26
30
  *
27
31
  * Debug logging is off by default. Turn it on with the `workerDebug` prop of
28
32
  * PivotTableUI (or by setting `window.__PVT_WORKER_DEBUG__ = true` before
@@ -32,6 +36,8 @@ var DEFAULT_WORKER_URL = exports.DEFAULT_WORKER_URL = 'pivot-worker.js'; /* esli
32
36
 
33
37
 
34
38
  var REQUEST_TIMEOUT_MS = 300000;
39
+ var VIEWPORT_TIMEOUT_MS = 10000;
40
+ var DATA_CHUNK_SIZE = 500;
35
41
 
36
42
  var workerUrl = DEFAULT_WORKER_URL;
37
43
  var sharedWorker = null;
@@ -42,8 +48,11 @@ var sharedWorkerBroken = false;
42
48
  var hasResultEver = false;
43
49
  var nextRequestId = 1;
44
50
  var lastStagedDataKey = null;
51
+ var stagingPromises = new Map();
45
52
  var workerDebug = false;
46
53
  var pendingRequests = new Map();
54
+ var pendingViewportByPivot = new Map();
55
+ var workerOwners = new Set();
47
56
 
48
57
  function setWorkerDebug(enabled) {
49
58
  var next = Boolean(enabled);
@@ -97,6 +106,24 @@ var failAllPending = function failAllPending(error) {
97
106
  entry.reject(error);
98
107
  });
99
108
  pendingRequests.clear();
109
+ pendingViewportByPivot.clear();
110
+ };
111
+
112
+ var cancelPendingViewport = function cancelPendingViewport(viewportKey) {
113
+ var requestId = pendingViewportByPivot.get(viewportKey);
114
+ if (typeof requestId !== 'number') {
115
+ return;
116
+ }
117
+ pendingViewportByPivot.delete(viewportKey);
118
+ var entry = pendingRequests.get(requestId);
119
+ if (!entry) {
120
+ return;
121
+ }
122
+ clearTimeout(entry.timer);
123
+ pendingRequests.delete(requestId);
124
+ var error = new Error('Pivot viewport request was replaced');
125
+ error.code = 'PIVOT_VIEWPORT_CANCELLED';
126
+ entry.reject(error);
100
127
  };
101
128
 
102
129
  function configureWorkerUrl(url) {
@@ -111,10 +138,36 @@ function configureWorkerUrl(url) {
111
138
  sharedWorkerBroken = false;
112
139
  hasResultEver = false;
113
140
  lastStagedDataKey = null;
141
+ stagingPromises.clear();
114
142
  }
115
143
  }
116
144
  }
117
145
 
146
+ function retainPivotWorker(ownerKey) {
147
+ if (ownerKey) {
148
+ workerOwners.add(ownerKey);
149
+ }
150
+ }
151
+
152
+ function releasePivotWorker(ownerKey) {
153
+ if (!ownerKey) {
154
+ return;
155
+ }
156
+ workerOwners.delete(ownerKey);
157
+ if (sharedWorker) {
158
+ sharedWorker.postMessage({ type: 'pivot:releaseOwner', ownerKey: ownerKey });
159
+ }
160
+ if (sharedWorker && workerOwners.size === 0) {
161
+ failAllPending(new Error('Pivot worker was released'));
162
+ sharedWorker.terminate();
163
+ sharedWorker = null;
164
+ sharedWorkerBroken = false;
165
+ hasResultEver = false;
166
+ lastStagedDataKey = null;
167
+ stagingPromises.clear();
168
+ }
169
+ }
170
+
118
171
  var handleWorkerMessage = function handleWorkerMessage(event) {
119
172
  var message = event.data || {};
120
173
  if (message.type === 'pivot:log') {
@@ -133,7 +186,15 @@ var handleWorkerMessage = function handleWorkerMessage(event) {
133
186
  }
134
187
  clearTimeout(entry.timer);
135
188
  pendingRequests.delete(message.id);
136
- if (message.type === 'pivot:result') {
189
+ if (entry.viewportKey !== undefined && pendingViewportByPivot.get(entry.viewportKey) === message.id) {
190
+ pendingViewportByPivot.delete(entry.viewportKey);
191
+ }
192
+ if (message.type === 'pivot:result' || message.type === 'pivot:viewportResult') {
193
+ if (message.type === 'pivot:viewportResult') {
194
+ log('#' + message.id + ' viewport received in ' + (Date.now() - entry.startedAt) + 'ms');
195
+ entry.resolve(message.result);
196
+ return;
197
+ }
137
198
  hasResultEver = true;
138
199
  var result = message.result;
139
200
  log('#' + message.id + ' result received in ' + (Date.now() - entry.startedAt) + 'ms', {
@@ -149,6 +210,48 @@ var handleWorkerMessage = function handleWorkerMessage(event) {
149
210
  }
150
211
  };
151
212
 
213
+ // `Worker.postMessage()` structured-clones its payload on the calling thread.
214
+ // Sending a wide dataset in one message can therefore freeze the UI before
215
+ // the worker has even started. Large inputs are split across macrotasks so
216
+ // pointer and paint work can run between chunks.
217
+ var stageDataInWorker = function stageDataInWorker(worker, id, dataKey, data, ownerKey) {
218
+ var owner = ownerKey ? { ownerKey: ownerKey } : {};
219
+ if (!Array.isArray(data) || data.length <= DATA_CHUNK_SIZE) {
220
+ worker.postMessage(Object.assign({ type: 'pivot:setData', id: id, dataKey: dataKey, data: data }, owner));
221
+ return null;
222
+ }
223
+
224
+ return new Promise(function (resolve, reject) {
225
+ try {
226
+ worker.postMessage(Object.assign({ type: 'pivot:setDataStart', id: id, dataKey: dataKey }, owner));
227
+ var offset = 0;
228
+ var postNextChunk = function postNextChunk() {
229
+ try {
230
+ var end = Math.min(offset + DATA_CHUNK_SIZE, data.length);
231
+ worker.postMessage({
232
+ type: 'pivot:setDataChunk',
233
+ id: id,
234
+ dataKey: dataKey,
235
+ data: data.slice(offset, end)
236
+ });
237
+ offset = end;
238
+ if (offset < data.length) {
239
+ setTimeout(postNextChunk, 0);
240
+ return;
241
+ }
242
+ worker.postMessage({ type: 'pivot:setDataEnd', id: id, dataKey: dataKey });
243
+ resolve();
244
+ } catch (error) {
245
+ reject(error);
246
+ }
247
+ };
248
+ postNextChunk();
249
+ } catch (error) {
250
+ reject(error);
251
+ }
252
+ });
253
+ };
254
+
152
255
  var ensureWorker = function ensureWorker() {
153
256
  if (sharedWorkerBroken) {
154
257
  return null;
@@ -191,7 +294,7 @@ var ensureWorker = function ensureWorker() {
191
294
  * worker reuse the materialized dataset across consecutive computations and
192
295
  * lets the client skip re-staging identical data.
193
296
  */
194
- function computePivotInWorker(data, dataKey, config) {
297
+ function computePivotInWorker(data, dataKey, config, ownerKey) {
195
298
  var worker = ensureWorker();
196
299
  if (!worker) {
197
300
  log('worker unavailable -> synchronous fallback');
@@ -212,14 +315,118 @@ function computePivotInWorker(data, dataKey, config) {
212
315
  });
213
316
  var mustStage = lastStagedDataKey !== dataKey;
214
317
  log('#' + id + ' dispatching to worker (dataKey=' + dataKey + (mustStage ? ', staging ' + (data || []).length + ' records' : ', cached dataset') + ', ' + describeConfig(config) + ')');
318
+ var dataReady = null;
215
319
  if (mustStage) {
216
- worker.postMessage({ type: 'pivot:setData', id: id, dataKey: dataKey, data: data });
217
320
  lastStagedDataKey = dataKey;
321
+ dataReady = stageDataInWorker(worker, id, dataKey, data, ownerKey);
322
+ if (dataReady) {
323
+ stagingPromises.set(dataKey, dataReady);
324
+ dataReady.then(function () {
325
+ if (stagingPromises.get(dataKey) === dataReady) {
326
+ stagingPromises.delete(dataKey);
327
+ }
328
+ }, function () {
329
+ return stagingPromises.delete(dataKey);
330
+ });
331
+ }
332
+ } else if (stagingPromises.has(dataKey)) {
333
+ dataReady = stagingPromises.get(dataKey);
334
+ }
335
+ var postCompute = function postCompute() {
336
+ if (pendingRequests.has(id)) {
337
+ worker.postMessage({
338
+ type: 'pivot:compute',
339
+ id: id,
340
+ dataKey: dataKey,
341
+ config: config,
342
+ ownerKey: ownerKey
343
+ });
344
+ }
345
+ };
346
+ if (dataReady) {
347
+ dataReady.then(postCompute).catch(function (error) {
348
+ clearTimeout(timer);
349
+ pendingRequests.delete(id);
350
+ reject(error);
351
+ });
352
+ } else {
353
+ postCompute();
354
+ }
355
+ });
356
+ }
357
+
358
+ // Request a small row window from a pivot result already cached in the worker.
359
+ // No dataset or full pivot state is cloned for a scroll request.
360
+ function computePivotViewportInWorker(viewportKey, start, end, columnMode) {
361
+ var columnStart = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 0;
362
+ var columnEnd = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : Number.MAX_SAFE_INTEGER;
363
+
364
+ var worker = ensureWorker();
365
+ if (!worker) {
366
+ return Promise.reject(new Error('Web worker unavailable'));
367
+ }
368
+ cancelPendingViewport(viewportKey);
369
+ var id = nextRequestId++;
370
+ return new Promise(function (resolve, reject) {
371
+ var timer = setTimeout(function () {
372
+ pendingRequests.delete(id);
373
+ if (pendingViewportByPivot.get(viewportKey) === id) {
374
+ pendingViewportByPivot.delete(viewportKey);
375
+ }
376
+ reject(new Error('Pivot viewport timed out'));
377
+ }, VIEWPORT_TIMEOUT_MS);
378
+ pendingRequests.set(id, {
379
+ resolve: resolve,
380
+ reject: reject,
381
+ timer: timer,
382
+ startedAt: Date.now(),
383
+ viewportKey: viewportKey
384
+ });
385
+ pendingViewportByPivot.set(viewportKey, id);
386
+ log('#' + id + ' viewport dispatch (rows=' + start + '-' + end + ', ' + ('columns=' + columnStart + '-' + columnEnd + ', pivot=' + viewportKey + ')'));
387
+ try {
388
+ worker.postMessage({
389
+ type: 'pivot:viewport',
390
+ id: id,
391
+ viewportKey: viewportKey,
392
+ start: start,
393
+ end: end,
394
+ columnMode: columnMode,
395
+ columnStart: columnStart,
396
+ columnEnd: columnEnd
397
+ });
398
+ } catch (error) {
399
+ clearTimeout(timer);
400
+ pendingRequests.delete(id);
401
+ if (pendingViewportByPivot.get(viewportKey) === id) {
402
+ pendingViewportByPivot.delete(viewportKey);
403
+ }
404
+ reject(error);
218
405
  }
219
- worker.postMessage({ type: 'pivot:compute', id: id, dataKey: dataKey, config: config });
220
406
  });
221
407
  }
222
408
 
409
+ // Release a full virtual pivot as soon as its table no longer references it.
410
+ // This intentionally does not create a worker during component cleanup.
411
+ function releasePivotInWorker(viewportKey) {
412
+ if (!sharedWorker || typeof viewportKey !== 'number') {
413
+ return;
414
+ }
415
+ cancelPendingViewport(viewportKey);
416
+ sharedWorker.postMessage({ type: 'pivot:release', viewportKey: viewportKey });
417
+ }
418
+
419
+ function releaseDatasetInWorker(dataKey) {
420
+ if (!sharedWorker || !dataKey) {
421
+ return;
422
+ }
423
+ if (lastStagedDataKey === dataKey) {
424
+ lastStagedDataKey = null;
425
+ }
426
+ stagingPromises.delete(dataKey);
427
+ sharedWorker.postMessage({ type: 'pivot:releaseData', dataKey: dataKey });
428
+ }
429
+
223
430
  /*
224
431
  * Same contract as the worker path, executed on the main thread. Used as the
225
432
  * automatic fallback whenever the worker path is unavailable. Deferred by
@@ -248,14 +455,13 @@ function computePivotSynchronously(data, config) {
248
455
  }
249
456
 
250
457
  /*
251
- * Worker-first entry point with automatic synchronous fallback. The fallback
252
- * produces the exact same serialized shape, so callers render identically
253
- * either way.
458
+ * Keep the existing entry point while testing worker failures without a
459
+ * synchronous fallback. Rejections reach PivotTableUI's error state.
254
460
  */
255
- function computePivotWithFallback(data, dataKey, config) {
256
- return computePivotInWorker(data, dataKey, config).catch(function (error) {
257
- log('worker request failed, falling back to the main thread:', error && error.message || error);
258
- return computePivotSynchronously(data, config);
461
+ function computePivotWithFallback(data, dataKey, config, ownerKey) {
462
+ return computePivotInWorker(data, dataKey, config, ownerKey).catch(function (error) {
463
+ log('worker request failed (synchronous fallback disabled):', error);
464
+ throw error;
259
465
  });
260
466
  }
261
467
  //# sourceMappingURL=PivotDataWorker.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/PivotDataWorker.js"],"names":["setWorkerDebug","configureWorkerUrl","computePivotInWorker","computePivotSynchronously","computePivotWithFallback","DEFAULT_WORKER_URL","REQUEST_TIMEOUT_MS","workerUrl","sharedWorker","sharedWorkerBroken","hasResultEver","nextRequestId","lastStagedDataKey","workerDebug","pendingRequests","Map","enabled","next","Boolean","wasEnabled","log","postMessage","type","isDebugEnabled","window","__PVT_WORKER_DEBUG__","args","describeConfig","config","rows","join","cols","aggregations","length","countOf","Array","isArray","value","undefined","failAllPending","forEach","clearTimeout","entry","timer","reject","error","clear","url","Error","terminate","handleWorkerMessage","message","event","data","detail","get","id","delete","result","Date","now","startedAt","totalRecords","rowKeys","colKeys","resolve","ensureWorker","Worker","onmessage","onerror","dataKey","worker","Promise","setTimeout","set","mustStage","materialized","catch"],"mappings":"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","file":"PivotDataWorker.js","sourcesContent":["/* eslint-disable valid-jsdoc */\n/* eslint-disable no-console */\n/* eslint-disable no-undefined */\n/*\n * Main-thread client for the pivot Web Worker (src/pivotWorker.js).\n *\n * Responsibilities:\n * - lazily create a single shared Worker (at `workerUrl`, overrideable),\n * - route result/error messages to the matching request,\n * - transparently fall back to a synchronous main-thread computation when\n * workers are unavailable or the worker bundle fails to load.\n *\n * Debug logging is off by default. Turn it on with the `workerDebug` prop of\n * PivotTableUI (or by setting `window.__PVT_WORKER_DEBUG__ = true` before\n * rendering) to trace worker creation, staging, computation, progress,\n * results, errors and fallbacks in the browser console.\n */\nimport {materializeData, computePivotState} from './pivotCompute';\n\nexport const DEFAULT_WORKER_URL = 'pivot-worker.js';\n\nconst REQUEST_TIMEOUT_MS = 300000;\n\nlet workerUrl = DEFAULT_WORKER_URL;\nlet sharedWorker = null;\n// The worker is marked broken only if it fails before ever producing a\n// result (e.g. a 404 worker script); runtime hiccups later on just reject\n// the affected request and fall back once.\nlet sharedWorkerBroken = false;\nlet hasResultEver = false;\nlet nextRequestId = 1;\nlet lastStagedDataKey = null;\nlet workerDebug = false;\nconst pendingRequests = new Map();\n\nexport function setWorkerDebug(enabled) {\n const next = Boolean(enabled);\n const wasEnabled = workerDebug;\n if (next === wasEnabled) {\n return;\n }\n if (next) {\n workerDebug = true;\n log('debug logging enabled');\n } else {\n // Log while logging is still active, so the \"disabled\" notice is shown.\n log('debug logging disabled');\n workerDebug = false;\n }\n if (sharedWorker) {\n sharedWorker.postMessage({type: 'pivot:debug', enabled: workerDebug});\n }\n}\n\nconst isDebugEnabled = () =>\n workerDebug ||\n (typeof window !== 'undefined' && window.__PVT_WORKER_DEBUG__ === true);\n\nfunction log(...args) {\n if (!isDebugEnabled()) {\n return;\n }\n console.log(\n '%c[pivottable worker]',\n 'color:#ff6600;font-weight:bold',\n ...args\n );\n}\n\nconst describeConfig = config =>\n `rows=[${(config.rows || []).join(', ')}] cols=[${(config.cols || []).join(\n ', '\n )}] aggregations=${(config.aggregations || []).length}`;\n\n// Length of an optional array field, used for defensive debug logging.\nconst countOf = value => (Array.isArray(value) ? value.length : undefined);\n\nconst failAllPending = error => {\n pendingRequests.forEach(entry => {\n clearTimeout(entry.timer);\n entry.reject(error);\n });\n pendingRequests.clear();\n};\n\nexport function configureWorkerUrl(url) {\n if (url && url !== workerUrl) {\n workerUrl = url;\n if (sharedWorker) {\n // Reject in-flight requests first so callers fall back to the\n // synchronous path instead of waiting for the request timeout.\n failAllPending(new Error('Pivot worker was reconfigured'));\n sharedWorker.terminate();\n sharedWorker = null;\n sharedWorkerBroken = false;\n hasResultEver = false;\n lastStagedDataKey = null;\n }\n }\n}\n\nconst handleWorkerMessage = event => {\n const message = event.data || {};\n if (message.type === 'pivot:log') {\n log('(in worker)', message.message, message.detail || '');\n return;\n }\n const entry = pendingRequests.get(message.id);\n if (!entry) {\n return;\n }\n if (message.type === 'pivot:progress') {\n // Progress reporting was removed: the UI only shows a loading overlay\n // until `pivot:result` arrives. Ignore messages from older worker\n // bundles that still emit progress so the request is not corrupted.\n return;\n }\n clearTimeout(entry.timer);\n pendingRequests.delete(message.id);\n if (message.type === 'pivot:result') {\n hasResultEver = true;\n const result = message.result;\n log(`#${message.id} result received in ${Date.now() - entry.startedAt}ms`, {\n totalRecords: result && result.totalRecords,\n rowKeys: countOf(result && result.rowKeys),\n colKeys: countOf(result && result.colKeys),\n aggregations: countOf(result && result.aggregations),\n });\n entry.resolve(message.result);\n } else if (message.type === 'pivot:error') {\n log(`#${message.id} worker reported an error:`, message.message);\n entry.reject(new Error(message.message || 'Pivot worker error'));\n }\n};\n\nconst ensureWorker = () => {\n if (sharedWorkerBroken) {\n return null;\n }\n\n if (typeof Worker === 'undefined') {\n log('no Worker support in this environment');\n return null;\n }\n\n if (!sharedWorker) {\n try {\n sharedWorker = new Worker(workerUrl);\n log('worker created:', workerUrl);\n } catch (error) {\n sharedWorkerBroken = true;\n log('worker creation failed:', error && error.message);\n return null;\n }\n sharedWorker.onmessage = handleWorkerMessage;\n sharedWorker.onerror = event => {\n log(\n 'worker error event (script failed to load / runtime error):',\n (event && event.message) || ''\n );\n failAllPending(new Error('Pivot worker failed to load'));\n if (!hasResultEver) {\n sharedWorkerBroken = true;\n log('worker marked unusable -> will use the synchronous fallback');\n }\n };\n if (isDebugEnabled()) {\n sharedWorker.postMessage({type: 'pivot:debug', enabled: true});\n }\n }\n return sharedWorker;\n};\n\n/*\n * Runs a full computation inside the shared worker.\n *\n * `dataKey` must change whenever the underlying dataset changes. It lets the\n * worker reuse the materialized dataset across consecutive computations and\n * lets the client skip re-staging identical data.\n */\nexport function computePivotInWorker(data, dataKey, config) {\n const worker = ensureWorker();\n if (!worker) {\n log('worker unavailable -> synchronous fallback');\n return Promise.reject(new Error('Web worker unavailable'));\n }\n const id = nextRequestId++;\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n pendingRequests.delete(id);\n log(`#${id} timed out after ${REQUEST_TIMEOUT_MS}ms`);\n reject(new Error('Pivot worker timed out'));\n }, REQUEST_TIMEOUT_MS);\n pendingRequests.set(id, {\n resolve,\n reject,\n timer,\n startedAt: Date.now(),\n });\n const mustStage = lastStagedDataKey !== dataKey;\n log(\n `#${id} dispatching to worker (dataKey=${dataKey}${\n mustStage\n ? ', staging ' + (data || []).length + ' records'\n : ', cached dataset'\n }, ${describeConfig(config)})`\n );\n if (mustStage) {\n worker.postMessage({type: 'pivot:setData', id, dataKey, data});\n lastStagedDataKey = dataKey;\n }\n worker.postMessage({type: 'pivot:compute', id, dataKey, config});\n });\n}\n\n/*\n * Same contract as the worker path, executed on the main thread. Used as the\n * automatic fallback whenever the worker path is unavailable. Deferred by\n * one tick so a loading indicator can paint before the blocking work starts.\n */\nexport function computePivotSynchronously(data, config) {\n return new Promise((resolve, reject) => {\n setTimeout(() => {\n const startedAt = Date.now();\n log('running synchronous computation on the main thread...');\n try {\n const materialized = materializeData(data, {});\n const result = computePivotState(materialized, config);\n log(`synchronous computation finished in ${Date.now() - startedAt}ms`, {\n totalRecords: result.totalRecords,\n rowKeys: result.rowKeys.length,\n colKeys: result.colKeys.length,\n });\n resolve(result);\n } catch (error) {\n log('synchronous computation failed:', error && error.message);\n reject(error);\n }\n }, 0);\n });\n}\n\n/*\n * Worker-first entry point with automatic synchronous fallback. The fallback\n * produces the exact same serialized shape, so callers render identically\n * either way.\n */\nexport function computePivotWithFallback(data, dataKey, config) {\n return computePivotInWorker(data, dataKey, config).catch(error => {\n log(\n 'worker request failed, falling back to the main thread:',\n (error && error.message) || error\n );\n return computePivotSynchronously(data, config);\n });\n}\n"]}
1
+ {"version":3,"sources":["../src/PivotDataWorker.js"],"names":["setWorkerDebug","configureWorkerUrl","retainPivotWorker","releasePivotWorker","computePivotInWorker","computePivotViewportInWorker","releasePivotInWorker","releaseDatasetInWorker","computePivotSynchronously","computePivotWithFallback","DEFAULT_WORKER_URL","REQUEST_TIMEOUT_MS","VIEWPORT_TIMEOUT_MS","DATA_CHUNK_SIZE","workerUrl","sharedWorker","sharedWorkerBroken","hasResultEver","nextRequestId","lastStagedDataKey","stagingPromises","Map","workerDebug","pendingRequests","pendingViewportByPivot","workerOwners","Set","enabled","next","Boolean","wasEnabled","log","postMessage","type","isDebugEnabled","window","__PVT_WORKER_DEBUG__","args","describeConfig","config","rows","join","cols","aggregations","length","countOf","Array","isArray","value","undefined","failAllPending","forEach","clearTimeout","entry","timer","reject","error","clear","cancelPendingViewport","requestId","get","viewportKey","delete","Error","code","url","terminate","ownerKey","add","size","handleWorkerMessage","message","event","data","detail","id","Date","now","startedAt","resolve","result","totalRecords","rowKeys","colKeys","stageDataInWorker","worker","dataKey","owner","Object","assign","Promise","offset","postNextChunk","end","Math","min","slice","setTimeout","ensureWorker","Worker","onmessage","onerror","set","mustStage","dataReady","then","has","postCompute","catch","start","columnMode","columnStart","columnEnd","Number","MAX_SAFE_INTEGER","materialized"],"mappings":"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","file":"PivotDataWorker.js","sourcesContent":["/* eslint-disable valid-jsdoc */\n/* eslint-disable no-console */\n/* eslint-disable no-undefined */\n/*\n * Main-thread client for the pivot Web Worker (src/pivotWorker.js).\n *\n * Responsibilities:\n * - lazily create a single shared Worker (at `workerUrl`, overrideable),\n * - route result/error messages to the matching request,\n * - surface worker errors instead of silently recomputing on the main thread.\n *\n * Debug logging is off by default. Turn it on with the `workerDebug` prop of\n * PivotTableUI (or by setting `window.__PVT_WORKER_DEBUG__ = true` before\n * rendering) to trace worker creation, staging, computation, progress,\n * results, errors and fallbacks in the browser console.\n */\nimport {materializeData, computePivotState} from './pivotCompute';\n\nexport const DEFAULT_WORKER_URL = 'pivot-worker.js';\n\nconst REQUEST_TIMEOUT_MS = 300000;\nconst VIEWPORT_TIMEOUT_MS = 10000;\nconst DATA_CHUNK_SIZE = 500;\n\nlet workerUrl = DEFAULT_WORKER_URL;\nlet sharedWorker = null;\n// The worker is marked broken only if it fails before ever producing a\n// result (e.g. a 404 worker script); runtime hiccups later on just reject\n// the affected request and fall back once.\nlet sharedWorkerBroken = false;\nlet hasResultEver = false;\nlet nextRequestId = 1;\nlet lastStagedDataKey = null;\nconst stagingPromises = new Map();\nlet workerDebug = false;\nconst pendingRequests = new Map();\nconst pendingViewportByPivot = new Map();\nconst workerOwners = new Set();\n\nexport function setWorkerDebug(enabled) {\n const next = Boolean(enabled);\n const wasEnabled = workerDebug;\n if (next === wasEnabled) {\n return;\n }\n if (next) {\n workerDebug = true;\n log('debug logging enabled');\n } else {\n // Log while logging is still active, so the \"disabled\" notice is shown.\n log('debug logging disabled');\n workerDebug = false;\n }\n if (sharedWorker) {\n sharedWorker.postMessage({type: 'pivot:debug', enabled: workerDebug});\n }\n}\n\nconst isDebugEnabled = () =>\n workerDebug ||\n (typeof window !== 'undefined' && window.__PVT_WORKER_DEBUG__ === true);\n\nfunction log(...args) {\n if (!isDebugEnabled()) {\n return;\n }\n console.log(\n '%c[pivottable worker]',\n 'color:#ff6600;font-weight:bold',\n ...args\n );\n}\n\nconst describeConfig = config =>\n `rows=[${(config.rows || []).join(', ')}] cols=[${(config.cols || []).join(\n ', '\n )}] aggregations=${(config.aggregations || []).length}`;\n\n// Length of an optional array field, used for defensive debug logging.\nconst countOf = value => (Array.isArray(value) ? value.length : undefined);\n\nconst failAllPending = error => {\n pendingRequests.forEach(entry => {\n clearTimeout(entry.timer);\n entry.reject(error);\n });\n pendingRequests.clear();\n pendingViewportByPivot.clear();\n};\n\nconst cancelPendingViewport = viewportKey => {\n const requestId = pendingViewportByPivot.get(viewportKey);\n if (typeof requestId !== 'number') {\n return;\n }\n pendingViewportByPivot.delete(viewportKey);\n const entry = pendingRequests.get(requestId);\n if (!entry) {\n return;\n }\n clearTimeout(entry.timer);\n pendingRequests.delete(requestId);\n const error = new Error('Pivot viewport request was replaced');\n error.code = 'PIVOT_VIEWPORT_CANCELLED';\n entry.reject(error);\n};\n\nexport function configureWorkerUrl(url) {\n if (url && url !== workerUrl) {\n workerUrl = url;\n if (sharedWorker) {\n // Reject in-flight requests first so callers fall back to the\n // synchronous path instead of waiting for the request timeout.\n failAllPending(new Error('Pivot worker was reconfigured'));\n sharedWorker.terminate();\n sharedWorker = null;\n sharedWorkerBroken = false;\n hasResultEver = false;\n lastStagedDataKey = null;\n stagingPromises.clear();\n }\n }\n}\n\nexport function retainPivotWorker(ownerKey) {\n if (ownerKey) {\n workerOwners.add(ownerKey);\n }\n}\n\nexport function releasePivotWorker(ownerKey) {\n if (!ownerKey) {\n return;\n }\n workerOwners.delete(ownerKey);\n if (sharedWorker) {\n sharedWorker.postMessage({type: 'pivot:releaseOwner', ownerKey});\n }\n if (sharedWorker && workerOwners.size === 0) {\n failAllPending(new Error('Pivot worker was released'));\n sharedWorker.terminate();\n sharedWorker = null;\n sharedWorkerBroken = false;\n hasResultEver = false;\n lastStagedDataKey = null;\n stagingPromises.clear();\n }\n}\n\nconst handleWorkerMessage = event => {\n const message = event.data || {};\n if (message.type === 'pivot:log') {\n log('(in worker)', message.message, message.detail || '');\n return;\n }\n const entry = pendingRequests.get(message.id);\n if (!entry) {\n return;\n }\n if (message.type === 'pivot:progress') {\n // Progress reporting was removed: the UI only shows a loading overlay\n // until `pivot:result` arrives. Ignore messages from older worker\n // bundles that still emit progress so the request is not corrupted.\n return;\n }\n clearTimeout(entry.timer);\n pendingRequests.delete(message.id);\n if (\n entry.viewportKey !== undefined &&\n pendingViewportByPivot.get(entry.viewportKey) === message.id\n ) {\n pendingViewportByPivot.delete(entry.viewportKey);\n }\n if (\n message.type === 'pivot:result' ||\n message.type === 'pivot:viewportResult'\n ) {\n if (message.type === 'pivot:viewportResult') {\n log(\n `#${message.id} viewport received in ${Date.now() - entry.startedAt}ms`\n );\n entry.resolve(message.result);\n return;\n }\n hasResultEver = true;\n const result = message.result;\n log(`#${message.id} result received in ${Date.now() - entry.startedAt}ms`, {\n totalRecords: result && result.totalRecords,\n rowKeys: countOf(result && result.rowKeys),\n colKeys: countOf(result && result.colKeys),\n aggregations: countOf(result && result.aggregations),\n });\n entry.resolve(message.result);\n } else if (message.type === 'pivot:error') {\n log(`#${message.id} worker reported an error:`, message.message);\n entry.reject(new Error(message.message || 'Pivot worker error'));\n }\n};\n\n// `Worker.postMessage()` structured-clones its payload on the calling thread.\n// Sending a wide dataset in one message can therefore freeze the UI before\n// the worker has even started. Large inputs are split across macrotasks so\n// pointer and paint work can run between chunks.\nconst stageDataInWorker = (worker, id, dataKey, data, ownerKey) => {\n const owner = ownerKey ? {ownerKey} : {};\n if (!Array.isArray(data) || data.length <= DATA_CHUNK_SIZE) {\n worker.postMessage(\n Object.assign({type: 'pivot:setData', id, dataKey, data}, owner)\n );\n return null;\n }\n\n return new Promise((resolve, reject) => {\n try {\n worker.postMessage(\n Object.assign({type: 'pivot:setDataStart', id, dataKey}, owner)\n );\n let offset = 0;\n const postNextChunk = () => {\n try {\n const end = Math.min(offset + DATA_CHUNK_SIZE, data.length);\n worker.postMessage({\n type: 'pivot:setDataChunk',\n id,\n dataKey,\n data: data.slice(offset, end),\n });\n offset = end;\n if (offset < data.length) {\n setTimeout(postNextChunk, 0);\n return;\n }\n worker.postMessage({type: 'pivot:setDataEnd', id, dataKey});\n resolve();\n } catch (error) {\n reject(error);\n }\n };\n postNextChunk();\n } catch (error) {\n reject(error);\n }\n });\n};\n\nconst ensureWorker = () => {\n if (sharedWorkerBroken) {\n return null;\n }\n\n if (typeof Worker === 'undefined') {\n log('no Worker support in this environment');\n return null;\n }\n\n if (!sharedWorker) {\n try {\n sharedWorker = new Worker(workerUrl);\n log('worker created:', workerUrl);\n } catch (error) {\n sharedWorkerBroken = true;\n log('worker creation failed:', error && error.message);\n return null;\n }\n sharedWorker.onmessage = handleWorkerMessage;\n sharedWorker.onerror = event => {\n log(\n 'worker error event (script failed to load / runtime error):',\n (event && event.message) || ''\n );\n failAllPending(new Error('Pivot worker failed to load'));\n if (!hasResultEver) {\n sharedWorkerBroken = true;\n log('worker marked unusable -> will use the synchronous fallback');\n }\n };\n if (isDebugEnabled()) {\n sharedWorker.postMessage({type: 'pivot:debug', enabled: true});\n }\n }\n return sharedWorker;\n};\n\n/*\n * Runs a full computation inside the shared worker.\n *\n * `dataKey` must change whenever the underlying dataset changes. It lets the\n * worker reuse the materialized dataset across consecutive computations and\n * lets the client skip re-staging identical data.\n */\nexport function computePivotInWorker(data, dataKey, config, ownerKey) {\n const worker = ensureWorker();\n if (!worker) {\n log('worker unavailable -> synchronous fallback');\n return Promise.reject(new Error('Web worker unavailable'));\n }\n const id = nextRequestId++;\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n pendingRequests.delete(id);\n log(`#${id} timed out after ${REQUEST_TIMEOUT_MS}ms`);\n reject(new Error('Pivot worker timed out'));\n }, REQUEST_TIMEOUT_MS);\n pendingRequests.set(id, {\n resolve,\n reject,\n timer,\n startedAt: Date.now(),\n });\n const mustStage = lastStagedDataKey !== dataKey;\n log(\n `#${id} dispatching to worker (dataKey=${dataKey}${\n mustStage\n ? ', staging ' + (data || []).length + ' records'\n : ', cached dataset'\n }, ${describeConfig(config)})`\n );\n let dataReady = null;\n if (mustStage) {\n lastStagedDataKey = dataKey;\n dataReady = stageDataInWorker(worker, id, dataKey, data, ownerKey);\n if (dataReady) {\n stagingPromises.set(dataKey, dataReady);\n dataReady.then(\n () => {\n if (stagingPromises.get(dataKey) === dataReady) {\n stagingPromises.delete(dataKey);\n }\n },\n () => stagingPromises.delete(dataKey)\n );\n }\n } else if (stagingPromises.has(dataKey)) {\n dataReady = stagingPromises.get(dataKey);\n }\n const postCompute = () => {\n if (pendingRequests.has(id)) {\n worker.postMessage({\n type: 'pivot:compute',\n id,\n dataKey,\n config,\n ownerKey,\n });\n }\n };\n if (dataReady) {\n dataReady.then(postCompute).catch(error => {\n clearTimeout(timer);\n pendingRequests.delete(id);\n reject(error);\n });\n } else {\n postCompute();\n }\n });\n}\n\n// Request a small row window from a pivot result already cached in the worker.\n// No dataset or full pivot state is cloned for a scroll request.\nexport function computePivotViewportInWorker(\n viewportKey,\n start,\n end,\n columnMode,\n columnStart = 0,\n columnEnd = Number.MAX_SAFE_INTEGER\n) {\n const worker = ensureWorker();\n if (!worker) {\n return Promise.reject(new Error('Web worker unavailable'));\n }\n cancelPendingViewport(viewportKey);\n const id = nextRequestId++;\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n pendingRequests.delete(id);\n if (pendingViewportByPivot.get(viewportKey) === id) {\n pendingViewportByPivot.delete(viewportKey);\n }\n reject(new Error('Pivot viewport timed out'));\n }, VIEWPORT_TIMEOUT_MS);\n pendingRequests.set(id, {\n resolve,\n reject,\n timer,\n startedAt: Date.now(),\n viewportKey,\n });\n pendingViewportByPivot.set(viewportKey, id);\n log(\n `#${id} viewport dispatch (rows=${start}-${end}, ` +\n `columns=${columnStart}-${columnEnd}, pivot=${viewportKey})`\n );\n try {\n worker.postMessage({\n type: 'pivot:viewport',\n id,\n viewportKey,\n start,\n end,\n columnMode,\n columnStart,\n columnEnd,\n });\n } catch (error) {\n clearTimeout(timer);\n pendingRequests.delete(id);\n if (pendingViewportByPivot.get(viewportKey) === id) {\n pendingViewportByPivot.delete(viewportKey);\n }\n reject(error);\n }\n });\n}\n\n// Release a full virtual pivot as soon as its table no longer references it.\n// This intentionally does not create a worker during component cleanup.\nexport function releasePivotInWorker(viewportKey) {\n if (!sharedWorker || typeof viewportKey !== 'number') {\n return;\n }\n cancelPendingViewport(viewportKey);\n sharedWorker.postMessage({type: 'pivot:release', viewportKey});\n}\n\nexport function releaseDatasetInWorker(dataKey) {\n if (!sharedWorker || !dataKey) {\n return;\n }\n if (lastStagedDataKey === dataKey) {\n lastStagedDataKey = null;\n }\n stagingPromises.delete(dataKey);\n sharedWorker.postMessage({type: 'pivot:releaseData', dataKey});\n}\n\n/*\n * Same contract as the worker path, executed on the main thread. Used as the\n * automatic fallback whenever the worker path is unavailable. Deferred by\n * one tick so a loading indicator can paint before the blocking work starts.\n */\nexport function computePivotSynchronously(data, config) {\n return new Promise((resolve, reject) => {\n setTimeout(() => {\n const startedAt = Date.now();\n log('running synchronous computation on the main thread...');\n try {\n const materialized = materializeData(data, {});\n const result = computePivotState(materialized, config);\n log(`synchronous computation finished in ${Date.now() - startedAt}ms`, {\n totalRecords: result.totalRecords,\n rowKeys: result.rowKeys.length,\n colKeys: result.colKeys.length,\n });\n resolve(result);\n } catch (error) {\n log('synchronous computation failed:', error && error.message);\n reject(error);\n }\n }, 0);\n });\n}\n\n/*\n * Keep the existing entry point while testing worker failures without a\n * synchronous fallback. Rejections reach PivotTableUI's error state.\n */\nexport function computePivotWithFallback(data, dataKey, config, ownerKey) {\n return computePivotInWorker(data, dataKey, config, ownerKey).catch(error => {\n log('worker request failed (synchronous fallback disabled):', error);\n throw error;\n });\n}\n"]}
@@ -58,7 +58,8 @@ PivotTable.propTypes = Object.assign({}, _Utilities.PivotData.propTypes, {
58
58
  rowSorts: _propTypes2.default.objectOf(_propTypes2.default.oneOf(['ASC', 'DESC'])),
59
59
  onColSort: _propTypes2.default.func,
60
60
  onRowSort: _propTypes2.default.func,
61
- tableOptions: _propTypes2.default.object
61
+ tableOptions: _propTypes2.default.object,
62
+ virtualizeRows: _propTypes2.default.bool
62
63
  });
63
64
 
64
65
  PivotTable.defaultProps = Object.assign({}, _Utilities.PivotData.defaultProps, {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/PivotTable.jsx"],"names":["PivotTable","Renderer","props","renderers","rendererName","Object","keys","React","PureComponent","propTypes","assign","PivotData","PropTypes","string","objectOf","func","colSorts","oneOf","rowSorts","onColSort","onRowSort","tableOptions","object","defaultProps","TableRenderers"],"mappings":";;;;;;;;AAAA;;;;AACA;;;;AACA;;AACA;;;;;;;;;;;;AAEA;AACA;;IAEMA,U;;;;;;;;;;;6BACK;AACP,UAAMC,WAAW,KAAKC,KAAL,CAAWC,SAAX,CACf,KAAKD,KAAL,CAAWE,YAAX,IAA2B,KAAKF,KAAL,CAAWC,SAAtC,GACI,KAAKD,KAAL,CAAWE,YADf,GAEIC,OAAOC,IAAP,CAAY,KAAKJ,KAAL,CAAWC,SAAvB,EAAkC,CAAlC,CAHW,CAAjB;AAKA,aAAO,8BAAC,QAAD,EAAc,KAAKD,KAAnB,CAAP;AACD;;;;EARsBK,gBAAMC,a;;AAW/BR,WAAWS,SAAX,GAAuBJ,OAAOK,MAAP,CAAc,EAAd,EAAkBC,qBAAUF,SAA5B,EAAuC;AAC5DL,gBAAcQ,oBAAUC,MADoC;AAE5DV,aAAWS,oBAAUE,QAAV,CAAmBF,oBAAUG,IAA7B,CAFiD;AAG5DC,YAAUJ,oBAAUE,QAAV,CAAmBF,oBAAUK,KAAV,CAAgB,CAAC,KAAD,EAAQ,MAAR,CAAhB,CAAnB,CAHkD;AAI5DC,YAAUN,oBAAUE,QAAV,CAAmBF,oBAAUK,KAAV,CAAgB,CAAC,KAAD,EAAQ,MAAR,CAAhB,CAAnB,CAJkD;AAK5DE,aAAWP,oBAAUG,IALuC;AAM5DK,aAAWR,oBAAUG,IANuC;AAO5DM,gBAAcT,oBAAUU;AAPoC,CAAvC,CAAvB;;AAUAtB,WAAWuB,YAAX,GAA0BlB,OAAOK,MAAP,CAAc,EAAd,EAAkBC,qBAAUY,YAA5B,EAA0C;AAClEnB,gBAAc,OADoD;AAElED,aAAWqB,wBAFuD;AAGlEH,gBAAc;AAHoD,CAA1C,CAA1B;;kBAMerB,U","file":"PivotTable.js","sourcesContent":["import React from 'react';\nimport PropTypes from 'prop-types';\nimport {PivotData} from './Utilities';\nimport TableRenderers from './TableRenderers';\n\n/* eslint-disable react/prop-types */\n// eslint can't see inherited propTypes!\n\nclass PivotTable extends React.PureComponent {\n render() {\n const Renderer = this.props.renderers[\n this.props.rendererName in this.props.renderers\n ? this.props.rendererName\n : Object.keys(this.props.renderers)[0]\n ];\n return <Renderer {...this.props} />;\n }\n}\n\nPivotTable.propTypes = Object.assign({}, PivotData.propTypes, {\n rendererName: PropTypes.string,\n renderers: PropTypes.objectOf(PropTypes.func),\n colSorts: PropTypes.objectOf(PropTypes.oneOf(['ASC', 'DESC'])),\n rowSorts: PropTypes.objectOf(PropTypes.oneOf(['ASC', 'DESC'])),\n onColSort: PropTypes.func,\n onRowSort: PropTypes.func,\n tableOptions: PropTypes.object,\n});\n\nPivotTable.defaultProps = Object.assign({}, PivotData.defaultProps, {\n rendererName: 'Table',\n renderers: TableRenderers,\n tableOptions: {},\n});\n\nexport default PivotTable;\n"]}
1
+ {"version":3,"sources":["../src/PivotTable.jsx"],"names":["PivotTable","Renderer","props","renderers","rendererName","Object","keys","React","PureComponent","propTypes","assign","PivotData","PropTypes","string","objectOf","func","colSorts","oneOf","rowSorts","onColSort","onRowSort","tableOptions","object","virtualizeRows","bool","defaultProps","TableRenderers"],"mappings":";;;;;;;;AAAA;;;;AACA;;;;AACA;;AACA;;;;;;;;;;;;AAEA;AACA;;IAEMA,U;;;;;;;;;;;6BACK;AACP,UAAMC,WAAW,KAAKC,KAAL,CAAWC,SAAX,CACf,KAAKD,KAAL,CAAWE,YAAX,IAA2B,KAAKF,KAAL,CAAWC,SAAtC,GACI,KAAKD,KAAL,CAAWE,YADf,GAEIC,OAAOC,IAAP,CAAY,KAAKJ,KAAL,CAAWC,SAAvB,EAAkC,CAAlC,CAHW,CAAjB;AAKA,aAAO,8BAAC,QAAD,EAAc,KAAKD,KAAnB,CAAP;AACD;;;;EARsBK,gBAAMC,a;;AAW/BR,WAAWS,SAAX,GAAuBJ,OAAOK,MAAP,CAAc,EAAd,EAAkBC,qBAAUF,SAA5B,EAAuC;AAC5DL,gBAAcQ,oBAAUC,MADoC;AAE5DV,aAAWS,oBAAUE,QAAV,CAAmBF,oBAAUG,IAA7B,CAFiD;AAG5DC,YAAUJ,oBAAUE,QAAV,CAAmBF,oBAAUK,KAAV,CAAgB,CAAC,KAAD,EAAQ,MAAR,CAAhB,CAAnB,CAHkD;AAI5DC,YAAUN,oBAAUE,QAAV,CAAmBF,oBAAUK,KAAV,CAAgB,CAAC,KAAD,EAAQ,MAAR,CAAhB,CAAnB,CAJkD;AAK5DE,aAAWP,oBAAUG,IALuC;AAM5DK,aAAWR,oBAAUG,IANuC;AAO5DM,gBAAcT,oBAAUU,MAPoC;AAQ5DC,kBAAgBX,oBAAUY;AARkC,CAAvC,CAAvB;;AAWAxB,WAAWyB,YAAX,GAA0BpB,OAAOK,MAAP,CAAc,EAAd,EAAkBC,qBAAUc,YAA5B,EAA0C;AAClErB,gBAAc,OADoD;AAElED,aAAWuB,wBAFuD;AAGlEL,gBAAc;AAHoD,CAA1C,CAA1B;;kBAMerB,U","file":"PivotTable.js","sourcesContent":["import React from 'react';\nimport PropTypes from 'prop-types';\nimport {PivotData} from './Utilities';\nimport TableRenderers from './TableRenderers';\n\n/* eslint-disable react/prop-types */\n// eslint can't see inherited propTypes!\n\nclass PivotTable extends React.PureComponent {\n render() {\n const Renderer = this.props.renderers[\n this.props.rendererName in this.props.renderers\n ? this.props.rendererName\n : Object.keys(this.props.renderers)[0]\n ];\n return <Renderer {...this.props} />;\n }\n}\n\nPivotTable.propTypes = Object.assign({}, PivotData.propTypes, {\n rendererName: PropTypes.string,\n renderers: PropTypes.objectOf(PropTypes.func),\n colSorts: PropTypes.objectOf(PropTypes.oneOf(['ASC', 'DESC'])),\n rowSorts: PropTypes.objectOf(PropTypes.oneOf(['ASC', 'DESC'])),\n onColSort: PropTypes.func,\n onRowSort: PropTypes.func,\n tableOptions: PropTypes.object,\n virtualizeRows: PropTypes.bool,\n});\n\nPivotTable.defaultProps = Object.assign({}, PivotData.defaultProps, {\n rendererName: 'Table',\n renderers: TableRenderers,\n tableOptions: {},\n});\n\nexport default PivotTable;\n"]}