nodenetcdf 4.9.32 → 4.9.34

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/src/Variable.cpp CHANGED
@@ -22,9 +22,7 @@ Variable::Variable(int id_, int parent_id_) noexcept
22
22
  Wrap(obj);
23
23
  const int retval = nc_inq_var(parent_id, id, nullptr, &type, &ndims, nullptr, nullptr);
24
24
  if (retval != NC_NOERR)
25
- {
26
25
  throw_netcdf_error(isolate, retval);
27
- }
28
26
  }
29
27
 
30
28
  void Variable::Init(v8::Local<v8::Object> exports)
@@ -104,8 +102,14 @@ void Variable::Write(const v8::FunctionCallbackInfo<v8::Value> &args)
104
102
 
105
103
  if (args.Length() != obj->ndims + 1)
106
104
  {
105
+ char name[NC_MAX_NAME + 1];
106
+ obj->get_name(name);
107
+ char error_msg[512];
108
+ snprintf(error_msg, sizeof(error_msg),
109
+ "Variable.write() for '%s': Wrong number of arguments. Expected %d (position arguments) + 1 (value) = %d, but got %d",
110
+ name, obj->ndims, obj->ndims + 1, args.Length());
107
111
  isolate->ThrowException(v8::Exception::TypeError(
108
- v8::String::NewFromUtf8(isolate, "Wrong number of arguments", v8::NewStringType::kNormal)
112
+ v8::String::NewFromUtf8(isolate, error_msg, v8::NewStringType::kNormal)
109
113
  .ToLocalChecked()));
110
114
  return;
111
115
  }
@@ -162,33 +166,48 @@ void Variable::Write(const v8::FunctionCallbackInfo<v8::Value> &args)
162
166
  }
163
167
  break;
164
168
  default:
169
+ char name[NC_MAX_NAME + 1];
170
+ obj->get_name(name);
171
+ char error_msg[256];
172
+ snprintf(error_msg, sizeof(error_msg),
173
+ "Variable.write() for '%s': Variable type %d not supported for write operations",
174
+ name, obj->type);
165
175
  isolate->ThrowException(v8::Exception::TypeError(
166
- v8::String::NewFromUtf8(isolate, "Variable type not supported yet", v8::NewStringType::kNormal)
176
+ v8::String::NewFromUtf8(isolate, error_msg, v8::NewStringType::kNormal)
167
177
  .ToLocalChecked()));
168
178
  return;
169
179
  }
170
180
 
171
181
  if (retval != NC_NOERR)
172
- {
173
182
  throw_netcdf_error(isolate, retval);
174
- }
175
183
  }
176
184
 
177
185
  void Variable::WriteSlice(const v8::FunctionCallbackInfo<v8::Value> &args)
178
186
  {
179
187
  v8::Isolate *isolate = args.GetIsolate();
180
188
  Variable *obj = node::ObjectWrap::Unwrap<Variable>(args.Holder());
189
+ char name[NC_MAX_NAME + 1];
190
+ obj->get_name(name);
191
+
181
192
  if (args.Length() != 2 * obj->ndims + 1)
182
193
  {
194
+ char error_msg[512];
195
+ snprintf(error_msg, sizeof(error_msg),
196
+ "Variable.writeSlice() for '%s': Wrong number of arguments. Expected %d pairs (pos,size) + 1 (array) = %d, but got %d",
197
+ name, obj->ndims, 2 * obj->ndims + 1, args.Length());
183
198
  isolate->ThrowException(v8::Exception::TypeError(
184
- v8::String::NewFromUtf8(isolate, "Wrong number of arguments", v8::NewStringType::kNormal)
199
+ v8::String::NewFromUtf8(isolate, error_msg, v8::NewStringType::kNormal)
185
200
  .ToLocalChecked()));
186
201
  return;
187
202
  }
188
203
  if (!args[2 * obj->ndims]->IsTypedArray())
189
204
  {
205
+ char error_msg[256];
206
+ snprintf(error_msg, sizeof(error_msg),
207
+ "Variable.writeSlice() for '%s': Last argument must be a typed array (Int8Array, Float32Array, etc.), but got %s",
208
+ name, *v8::String::Utf8Value(isolate, args[2 * obj->ndims]->TypeOf(isolate)));
190
209
  isolate->ThrowException(v8::Exception::TypeError(
191
- v8::String::NewFromUtf8(isolate, "Expecting a typed array", v8::NewStringType::kNormal).ToLocalChecked()));
210
+ v8::String::NewFromUtf8(isolate, error_msg, v8::NewStringType::kNormal).ToLocalChecked()));
192
211
  return;
193
212
  }
194
213
  size_t *pos = new size_t[obj->ndims];
@@ -204,44 +223,61 @@ void Variable::WriteSlice(const v8::FunctionCallbackInfo<v8::Value> &args)
204
223
  v8::Local<v8::TypedArray> val = v8::Local<v8::TypedArray>::Cast(args[2 * obj->ndims]);
205
224
  if (val->Length() != total_size)
206
225
  {
226
+ char error_msg[512];
227
+ snprintf(error_msg, sizeof(error_msg),
228
+ "Variable.writeSlice() for '%s': Array size mismatch. Expected %zu elements (product of sizes), but got %zu",
229
+ name, total_size, val->Length());
207
230
  isolate->ThrowException(v8::Exception::TypeError(
208
- v8::String::NewFromUtf8(isolate, "Wrong size of array", v8::NewStringType::kNormal).ToLocalChecked()));
231
+ v8::String::NewFromUtf8(isolate, error_msg, v8::NewStringType::kNormal).ToLocalChecked()));
209
232
  delete[] pos;
210
233
  delete[] size;
211
234
  return;
212
235
  }
213
236
 
214
237
  bool correct_type;
238
+ const char *expected_type_name = nullptr;
215
239
  switch (obj->type)
216
240
  {
217
241
  case NC_BYTE:
218
242
  case NC_CHAR:
219
243
  correct_type = val->IsInt8Array();
244
+ expected_type_name = "Int8Array";
220
245
  break;
221
246
  case NC_SHORT:
222
247
  correct_type = val->IsInt16Array();
248
+ expected_type_name = "Int16Array";
223
249
  break;
224
250
  case NC_INT:
225
251
  correct_type = val->IsInt32Array();
252
+ expected_type_name = "Int32Array";
226
253
  break;
227
254
  case NC_FLOAT:
228
255
  correct_type = val->IsFloat32Array();
256
+ expected_type_name = "Float32Array";
229
257
  break;
230
258
  case NC_DOUBLE:
231
259
  correct_type = val->IsFloat64Array();
260
+ expected_type_name = "Float64Array";
232
261
  break;
233
262
  case NC_UBYTE:
234
263
  correct_type = val->IsUint8Array();
264
+ expected_type_name = "Uint8Array";
235
265
  break;
236
266
  case NC_USHORT:
237
267
  correct_type = val->IsUint16Array();
268
+ expected_type_name = "Uint16Array";
238
269
  break;
239
270
  case NC_UINT:
240
271
  correct_type = val->IsUint32Array();
272
+ expected_type_name = "Uint32Array";
241
273
  break;
242
274
  default:
275
+ char error_msg[256];
276
+ snprintf(error_msg, sizeof(error_msg),
277
+ "Variable.writeSlice() for '%s': Variable type %d (%s) not supported for write operations",
278
+ name, obj->type, type_names[obj->type]);
243
279
  isolate->ThrowException(v8::Exception::TypeError(
244
- v8::String::NewFromUtf8(isolate, "Variable type not supported yet", v8::NewStringType::kNormal)
280
+ v8::String::NewFromUtf8(isolate, error_msg, v8::NewStringType::kNormal)
245
281
  .ToLocalChecked()));
246
282
  delete[] pos;
247
283
  delete[] size;
@@ -249,8 +285,13 @@ void Variable::WriteSlice(const v8::FunctionCallbackInfo<v8::Value> &args)
249
285
  }
250
286
  if (!correct_type)
251
287
  {
288
+ v8::String::Utf8Value actual_type(isolate, val->GetConstructorName());
289
+ char error_msg[512];
290
+ snprintf(error_msg, sizeof(error_msg),
291
+ "Variable.writeSlice() for '%s': Array type mismatch. Variable type is %s, expected %s array, but got %s",
292
+ name, type_names[obj->type], expected_type_name, *actual_type);
252
293
  isolate->ThrowException(v8::Exception::TypeError(
253
- v8::String::NewFromUtf8(isolate, "Wrong array type", v8::NewStringType::kNormal).ToLocalChecked()));
294
+ v8::String::NewFromUtf8(isolate, error_msg, v8::NewStringType::kNormal).ToLocalChecked()));
254
295
  delete[] pos;
255
296
  delete[] size;
256
297
  return;
@@ -268,17 +309,28 @@ void Variable::WriteStridedSlice(const v8::FunctionCallbackInfo<v8::Value> &args
268
309
  {
269
310
  v8::Isolate *isolate = args.GetIsolate();
270
311
  Variable *obj = node::ObjectWrap::Unwrap<Variable>(args.Holder());
312
+ char name[NC_MAX_NAME + 1];
313
+ obj->get_name(name);
314
+
271
315
  if (args.Length() != 3 * obj->ndims + 1)
272
316
  {
317
+ char error_msg[512];
318
+ snprintf(error_msg, sizeof(error_msg),
319
+ "Variable.writeStridedSlice() for '%s': Wrong number of arguments. Expected %d triplets (pos,size,stride) + 1 (array) = %d, but got %d",
320
+ name, obj->ndims, 3 * obj->ndims + 1, args.Length());
273
321
  isolate->ThrowException(v8::Exception::TypeError(
274
- v8::String::NewFromUtf8(isolate, "Wrong number of arguments", v8::NewStringType::kNormal)
322
+ v8::String::NewFromUtf8(isolate, error_msg, v8::NewStringType::kNormal)
275
323
  .ToLocalChecked()));
276
324
  return;
277
325
  }
278
326
  if (!args[3 * obj->ndims]->IsTypedArray())
279
327
  {
328
+ char error_msg[256];
329
+ snprintf(error_msg, sizeof(error_msg),
330
+ "Variable.writeStridedSlice() for '%s': Last argument must be a typed array, but got %s",
331
+ name, *v8::String::Utf8Value(isolate, args[3 * obj->ndims]->TypeOf(isolate)));
280
332
  isolate->ThrowException(v8::Exception::TypeError(
281
- v8::String::NewFromUtf8(isolate, "Expecting a typed array", v8::NewStringType::kNormal).ToLocalChecked()));
333
+ v8::String::NewFromUtf8(isolate, error_msg, v8::NewStringType::kNormal).ToLocalChecked()));
282
334
  return;
283
335
  }
284
336
  size_t *pos = new size_t[obj->ndims];
@@ -296,8 +348,12 @@ void Variable::WriteStridedSlice(const v8::FunctionCallbackInfo<v8::Value> &args
296
348
  v8::Local<v8::TypedArray> val = v8::Local<v8::TypedArray>::Cast(args[3 * obj->ndims]);
297
349
  if (val->Length() != total_size)
298
350
  {
351
+ char error_msg[512];
352
+ snprintf(error_msg, sizeof(error_msg),
353
+ "Variable.writeStridedSlice() for '%s': Array size mismatch. Expected %zu elements (product of sizes), but got %zu",
354
+ name, total_size, val->Length());
299
355
  isolate->ThrowException(v8::Exception::TypeError(
300
- v8::String::NewFromUtf8(isolate, "Wrong size of array", v8::NewStringType::kNormal).ToLocalChecked()));
356
+ v8::String::NewFromUtf8(isolate, error_msg, v8::NewStringType::kNormal).ToLocalChecked()));
301
357
  delete[] pos;
302
358
  delete[] size;
303
359
  delete[] stride;
@@ -305,36 +361,49 @@ void Variable::WriteStridedSlice(const v8::FunctionCallbackInfo<v8::Value> &args
305
361
  }
306
362
 
307
363
  bool correct_type;
364
+ const char *expected_type_name = nullptr;
308
365
  switch (obj->type)
309
366
  {
310
367
  case NC_BYTE:
311
368
  case NC_CHAR:
312
369
  correct_type = val->IsInt8Array();
370
+ expected_type_name = "Int8Array";
313
371
  break;
314
372
  case NC_SHORT:
315
373
  correct_type = val->IsInt16Array();
374
+ expected_type_name = "Int16Array";
316
375
  break;
317
376
  case NC_INT:
318
377
  correct_type = val->IsInt32Array();
378
+ expected_type_name = "Int32Array";
319
379
  break;
320
380
  case NC_FLOAT:
321
381
  correct_type = val->IsFloat32Array();
382
+ expected_type_name = "Float32Array";
322
383
  break;
323
384
  case NC_DOUBLE:
324
385
  correct_type = val->IsFloat64Array();
386
+ expected_type_name = "Float64Array";
325
387
  break;
326
388
  case NC_UBYTE:
327
389
  correct_type = val->IsUint8Array();
390
+ expected_type_name = "Uint8Array";
328
391
  break;
329
392
  case NC_USHORT:
330
393
  correct_type = val->IsUint16Array();
394
+ expected_type_name = "Uint16Array";
331
395
  break;
332
396
  case NC_UINT:
333
397
  correct_type = val->IsUint32Array();
398
+ expected_type_name = "Uint32Array";
334
399
  break;
335
400
  default:
401
+ char error_msg[256];
402
+ snprintf(error_msg, sizeof(error_msg),
403
+ "Variable.writeStridedSlice() for '%s': Variable type %d (%s) not supported for write operations",
404
+ name, obj->type, type_names[obj->type]);
336
405
  isolate->ThrowException(v8::Exception::TypeError(
337
- v8::String::NewFromUtf8(isolate, "Variable type not supported yet", v8::NewStringType::kNormal)
406
+ v8::String::NewFromUtf8(isolate, error_msg, v8::NewStringType::kNormal)
338
407
  .ToLocalChecked()));
339
408
  delete[] pos;
340
409
  delete[] size;
@@ -343,8 +412,13 @@ void Variable::WriteStridedSlice(const v8::FunctionCallbackInfo<v8::Value> &args
343
412
  }
344
413
  if (!correct_type)
345
414
  {
415
+ v8::String::Utf8Value actual_type(isolate, val->GetConstructorName());
416
+ char error_msg[512];
417
+ snprintf(error_msg, sizeof(error_msg),
418
+ "Variable.writeStridedSlice() for '%s': Array type mismatch. Variable type is %s, expected %s array, but got %s",
419
+ name, type_names[obj->type], expected_type_name, *actual_type);
346
420
  isolate->ThrowException(v8::Exception::TypeError(
347
- v8::String::NewFromUtf8(isolate, "Wrong array type", v8::NewStringType::kNormal).ToLocalChecked()));
421
+ v8::String::NewFromUtf8(isolate, error_msg, v8::NewStringType::kNormal).ToLocalChecked()));
348
422
  delete[] pos;
349
423
  delete[] size;
350
424
  delete[] stride;
@@ -352,9 +426,7 @@ void Variable::WriteStridedSlice(const v8::FunctionCallbackInfo<v8::Value> &args
352
426
  }
353
427
  int retval = nc_put_vars(obj->parent_id, obj->id, pos, size, stride, val->Buffer()->GetBackingStore()->Data());
354
428
  if (retval != NC_NOERR)
355
- {
356
429
  throw_netcdf_error(isolate, retval);
357
- }
358
430
  delete[] pos;
359
431
  delete[] size;
360
432
  delete[] stride;
@@ -364,17 +436,28 @@ void Variable::Read(const v8::FunctionCallbackInfo<v8::Value> &args)
364
436
  {
365
437
  v8::Isolate *isolate = args.GetIsolate();
366
438
  Variable *obj = node::ObjectWrap::Unwrap<Variable>(args.Holder());
439
+ char name[NC_MAX_NAME + 1];
440
+ obj->get_name(name);
441
+
367
442
  if (args.Length() != obj->ndims)
368
443
  {
444
+ char error_msg[512];
445
+ snprintf(error_msg, sizeof(error_msg),
446
+ "Variable.read() for '%s': Wrong number of arguments. Expected %d position indices (one per dimension), but got %d",
447
+ name, obj->ndims, args.Length());
369
448
  isolate->ThrowException(v8::Exception::TypeError(
370
- v8::String::NewFromUtf8(isolate, "Wrong number of arguments", v8::NewStringType::kNormal)
449
+ v8::String::NewFromUtf8(isolate, error_msg, v8::NewStringType::kNormal)
371
450
  .ToLocalChecked()));
372
451
  return;
373
452
  }
374
453
  if (obj->type < NC_BYTE || obj->type > NC_UINT)
375
454
  {
455
+ char error_msg[256];
456
+ snprintf(error_msg, sizeof(error_msg),
457
+ "Variable.read() for '%s': Variable type %d not supported for read operations",
458
+ name, obj->type);
376
459
  isolate->ThrowException(v8::Exception::TypeError(
377
- v8::String::NewFromUtf8(isolate, "Variable type not supported yet", v8::NewStringType::kNormal)
460
+ v8::String::NewFromUtf8(isolate, error_msg, v8::NewStringType::kNormal)
378
461
  .ToLocalChecked()));
379
462
  return;
380
463
  }
@@ -446,13 +529,9 @@ void Variable::Read(const v8::FunctionCallbackInfo<v8::Value> &args)
446
529
  break;
447
530
  }
448
531
  if (retval != NC_NOERR)
449
- {
450
532
  throw_netcdf_error(isolate, retval);
451
- }
452
533
  else
453
- {
454
534
  args.GetReturnValue().Set(result);
455
- }
456
535
  delete[] pos;
457
536
  delete[] size;
458
537
  }
@@ -461,17 +540,28 @@ void Variable::ReadSlice(const v8::FunctionCallbackInfo<v8::Value> &args)
461
540
  {
462
541
  v8::Isolate *isolate = args.GetIsolate();
463
542
  Variable *obj = node::ObjectWrap::Unwrap<Variable>(args.Holder());
543
+ char name[NC_MAX_NAME + 1];
544
+ obj->get_name(name);
545
+
464
546
  if (args.Length() != 2 * obj->ndims)
465
547
  {
548
+ char error_msg[512];
549
+ snprintf(error_msg, sizeof(error_msg),
550
+ "Variable.readSlice() for '%s': Wrong number of arguments. Expected %d pairs (pos,size) = %d arguments, but got %d",
551
+ name, obj->ndims, 2 * obj->ndims, args.Length());
466
552
  isolate->ThrowException(v8::Exception::TypeError(
467
- v8::String::NewFromUtf8(isolate, "Wrong number of arguments", v8::NewStringType::kNormal)
553
+ v8::String::NewFromUtf8(isolate, error_msg, v8::NewStringType::kNormal)
468
554
  .ToLocalChecked()));
469
555
  return;
470
556
  }
471
557
  if (obj->type < NC_BYTE || obj->type > NC_UINT)
472
558
  {
559
+ char error_msg[256];
560
+ snprintf(error_msg, sizeof(error_msg),
561
+ "Variable.readSlice() for '%s': Variable type %d not supported for read operations",
562
+ name, obj->type);
473
563
  isolate->ThrowException(v8::Exception::TypeError(
474
- v8::String::NewFromUtf8(isolate, "Variable type not supported yet", v8::NewStringType::kNormal)
564
+ v8::String::NewFromUtf8(isolate, error_msg, v8::NewStringType::kNormal)
475
565
  .ToLocalChecked()));
476
566
  return;
477
567
  }
@@ -525,8 +615,12 @@ void Variable::ReadSlice(const v8::FunctionCallbackInfo<v8::Value> &args)
525
615
  result = v8::Uint32Array::New(buffer, 0, total_size);
526
616
  break;
527
617
  default:
618
+ char error_msg[256];
619
+ snprintf(error_msg, sizeof(error_msg),
620
+ "Variable.readSlice() for '%s': Variable type %d (%s) not supported for creating typed array result",
621
+ name, obj->type, type_names[obj->type]);
528
622
  isolate->ThrowException(v8::Exception::TypeError(
529
- v8::String::NewFromUtf8(isolate, "Variable type not supported yet", v8::NewStringType::kNormal)
623
+ v8::String::NewFromUtf8(isolate, error_msg, v8::NewStringType::kNormal)
530
624
  .ToLocalChecked()));
531
625
  delete[] pos;
532
626
  delete[] size;
@@ -541,17 +635,28 @@ void Variable::ReadStridedSlice(const v8::FunctionCallbackInfo<v8::Value> &args)
541
635
  {
542
636
  v8::Isolate *isolate = args.GetIsolate();
543
637
  Variable *obj = node::ObjectWrap::Unwrap<Variable>(args.Holder());
638
+ char name[NC_MAX_NAME + 1];
639
+ obj->get_name(name);
640
+
544
641
  if (args.Length() != 3 * obj->ndims)
545
642
  {
643
+ char error_msg[512];
644
+ snprintf(error_msg, sizeof(error_msg),
645
+ "Variable.readStridedSlice() for '%s': Wrong number of arguments. Expected %d triplets (pos,size,stride) = %d arguments, but got %d",
646
+ name, obj->ndims, 3 * obj->ndims, args.Length());
546
647
  isolate->ThrowException(v8::Exception::TypeError(
547
- v8::String::NewFromUtf8(isolate, "Wrong number of arguments", v8::NewStringType::kNormal)
648
+ v8::String::NewFromUtf8(isolate, error_msg, v8::NewStringType::kNormal)
548
649
  .ToLocalChecked()));
549
650
  return;
550
651
  }
551
652
  if (obj->type < NC_BYTE || obj->type > NC_UINT)
552
653
  {
654
+ char error_msg[256];
655
+ snprintf(error_msg, sizeof(error_msg),
656
+ "Variable.readStridedSlice() for '%s': Variable type %d not supported for read operations",
657
+ name, obj->type);
553
658
  isolate->ThrowException(v8::Exception::TypeError(
554
- v8::String::NewFromUtf8(isolate, "Variable type not supported yet", v8::NewStringType::kNormal)
659
+ v8::String::NewFromUtf8(isolate, error_msg, v8::NewStringType::kNormal)
555
660
  .ToLocalChecked()));
556
661
  return;
557
662
  }
@@ -618,10 +723,17 @@ void Variable::AddAttribute(const v8::FunctionCallbackInfo<v8::Value> &args)
618
723
  {
619
724
  v8::Isolate *isolate = args.GetIsolate();
620
725
  Variable *obj = node::ObjectWrap::Unwrap<Variable>(args.Holder());
726
+ char var_name[NC_MAX_NAME + 1];
727
+ obj->get_name(var_name);
728
+
621
729
  if (args.Length() < 3)
622
730
  {
731
+ char error_msg[512];
732
+ snprintf(error_msg, sizeof(error_msg),
733
+ "Variable.addAttribute() for '%s': Wrong number of arguments. Expected 3 (name, type, value), but got %d",
734
+ var_name, args.Length());
623
735
  isolate->ThrowException(v8::Exception::TypeError(
624
- v8::String::NewFromUtf8(isolate, "Wrong number of arguments", v8::NewStringType::kNormal)
736
+ v8::String::NewFromUtf8(isolate, error_msg, v8::NewStringType::kNormal)
625
737
  .ToLocalChecked()));
626
738
  return;
627
739
  }
@@ -633,8 +745,17 @@ void Variable::AddAttribute(const v8::FunctionCallbackInfo<v8::Value> &args)
633
745
  int type = get_type(type_str);
634
746
  if (type == NC2_ERR)
635
747
  {
748
+ std::string attr_name = *v8::String::Utf8Value(
749
+ #if NODE_MAJOR_VERSION >= 8
750
+ isolate,
751
+ #endif
752
+ args[0]);
753
+ char error_msg[512];
754
+ snprintf(error_msg, sizeof(error_msg),
755
+ "Variable.addAttribute() for '%s': Unknown attribute type '%s' for attribute '%s'. Valid types are: byte, char, short, int, float, double, ubyte, ushort, uint",
756
+ var_name, type_str.c_str(), attr_name.c_str());
636
757
  isolate->ThrowException(v8::Exception::TypeError(
637
- v8::String::NewFromUtf8(isolate, "Unknown variable type", v8::NewStringType::kNormal).ToLocalChecked()));
758
+ v8::String::NewFromUtf8(isolate, error_msg, v8::NewStringType::kNormal).ToLocalChecked()));
638
759
  return;
639
760
  }
640
761
  Attribute *res = new Attribute(*v8::String::Utf8Value(
@@ -727,9 +848,7 @@ void Variable::GetName(v8::Local<v8::String> property, const v8::PropertyCallbac
727
848
  Variable *obj = node::ObjectWrap::Unwrap<Variable>(info.Holder());
728
849
  char name[NC_MAX_NAME + 1];
729
850
  if (obj->get_name(name))
730
- {
731
851
  info.GetReturnValue().Set(v8::String::NewFromUtf8(isolate, name, v8::NewStringType::kNormal).ToLocalChecked());
732
- }
733
852
  }
734
853
 
735
854
  void Variable::SetName(v8::Local<v8::String> property, v8::Local<v8::Value> val,
@@ -792,17 +911,11 @@ void Variable::SetEndianness(v8::Local<v8::String> property, v8::Local<v8::Value
792
911
  val->ToString(isolate->GetCurrentContext()).ToLocalChecked());
793
912
  int v;
794
913
  if (arg == "little")
795
- {
796
914
  v = NC_ENDIAN_LITTLE;
797
- }
798
915
  else if (arg == "big")
799
- {
800
916
  v = NC_ENDIAN_BIG;
801
- }
802
917
  else if (arg == "native")
803
- {
804
918
  v = NC_ENDIAN_NATIVE;
805
- }
806
919
  else
807
920
  {
808
921
  isolate->ThrowException(v8::Exception::TypeError(
@@ -856,13 +969,9 @@ void Variable::SetChecksumMode(v8::Local<v8::String> property, v8::Local<v8::Val
856
969
  val->ToString(isolate->GetCurrentContext()).ToLocalChecked());
857
970
  int v;
858
971
  if (arg == "none")
859
- {
860
972
  v = NC_NOCHECKSUM;
861
- }
862
973
  else if (arg == "fletcher32")
863
- {
864
974
  v = NC_FLETCHER32;
865
- }
866
975
  else
867
976
  {
868
977
  isolate->ThrowException(v8::Exception::TypeError(
@@ -916,13 +1025,9 @@ void Variable::SetChunkMode(v8::Local<v8::String> property, v8::Local<v8::Value>
916
1025
  val->ToString(isolate->GetCurrentContext()).ToLocalChecked());
917
1026
  int v;
918
1027
  if (arg == "contiguous")
919
- {
920
1028
  v = NC_CONTIGUOUS;
921
- }
922
1029
  else if (arg == "chunked")
923
- {
924
1030
  v = NC_CHUNKED;
925
- }
926
1031
  else
927
1032
  {
928
1033
  isolate->ThrowException(v8::Exception::TypeError(
@@ -946,9 +1051,7 @@ void Variable::SetChunkMode(v8::Local<v8::String> property, v8::Local<v8::Value>
946
1051
  }
947
1052
  retval = nc_def_var_chunking(obj->parent_id, obj->id, v, sizes);
948
1053
  if (retval != NC_NOERR)
949
- {
950
1054
  throw_netcdf_error(isolate, retval);
951
- }
952
1055
  delete[] sizes;
953
1056
  }
954
1057
 
@@ -966,9 +1069,7 @@ void Variable::GetChunkSizes(v8::Local<v8::String> property, const v8::PropertyC
966
1069
  }
967
1070
  v8::Local<v8::Array> result = v8::Array::New(isolate);
968
1071
  for (int i = 0; i < obj->ndims; i++)
969
- {
970
1072
  result->Set(isolate->GetCurrentContext(), i, v8::Integer::New(isolate, i));
971
- }
972
1073
  info.GetReturnValue().Set(result);
973
1074
  delete[] sizes;
974
1075
  }
@@ -1005,17 +1106,13 @@ void Variable::SetChunkSizes(v8::Local<v8::String> property, v8::Local<v8::Value
1005
1106
  }
1006
1107
  size_t *sizes = new size_t[obj->ndims];
1007
1108
  for (int i = 0; i < obj->ndims; i++)
1008
- {
1009
1109
  sizes[i] = array->Get(isolate->GetCurrentContext(), i)
1010
1110
  .ToLocalChecked()
1011
1111
  ->Uint32Value(isolate->GetCurrentContext())
1012
1112
  .ToChecked();
1013
- }
1014
1113
  retval = nc_def_var_chunking(obj->parent_id, obj->id, v, sizes);
1015
1114
  if (retval != NC_NOERR)
1016
- {
1017
1115
  throw_netcdf_error(isolate, retval);
1018
- }
1019
1116
  delete[] sizes;
1020
1117
  }
1021
1118
 
@@ -1066,9 +1163,7 @@ void Variable::SetFillMode(v8::Local<v8::String> property, v8::Local<v8::Value>
1066
1163
  }
1067
1164
  retval = nc_def_var_fill(obj->parent_id, obj->id, v, value);
1068
1165
  if (retval != NC_NOERR)
1069
- {
1070
1166
  throw_netcdf_error(isolate, retval);
1071
- }
1072
1167
  delete[] value;
1073
1168
  }
1074
1169
 
@@ -1211,9 +1306,7 @@ void Variable::SetFillValue(v8::Local<v8::String> property, v8::Local<v8::Value>
1211
1306
  return;
1212
1307
  }
1213
1308
  if (retval != NC_NOERR)
1214
- {
1215
1309
  throw_netcdf_error(isolate, retval);
1216
- }
1217
1310
  }
1218
1311
 
1219
1312
  void Variable::GetCompressionShuffle(v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value> &info)
@@ -1299,9 +1392,7 @@ void Variable::SetCompressionDeflate(v8::Local<v8::String> property, v8::Local<v
1299
1392
  }
1300
1393
  retval = nc_def_var_deflate(obj->parent_id, obj->id, v1, v, v2);
1301
1394
  if (retval != NC_NOERR)
1302
- {
1303
1395
  throw_netcdf_error(isolate, retval);
1304
- }
1305
1396
  }
1306
1397
 
1307
1398
  void Variable::GetCompressionLevel(v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value> &info)
@@ -1358,7 +1449,6 @@ void Variable::ToJSON(const v8::FunctionCallbackInfo<v8::Value> &args)
1358
1449
  v8::Local<v8::Context> context = isolate->GetCurrentContext();
1359
1450
  const auto *obj = node::ObjectWrap::Unwrap<Variable>(args.Holder());
1360
1451
 
1361
- // Use internalized strings for better performance
1362
1452
  v8::Local<v8::String> id_str = v8::String::NewFromUtf8Literal(isolate, "id");
1363
1453
  v8::Local<v8::String> name_str = v8::String::NewFromUtf8Literal(isolate, "name");
1364
1454
  v8::Local<v8::String> type_str = v8::String::NewFromUtf8Literal(isolate, "type");
@@ -1367,41 +1457,70 @@ void Variable::ToJSON(const v8::FunctionCallbackInfo<v8::Value> &args)
1367
1457
 
1368
1458
  v8::Local<v8::Object> json = v8::Object::New(isolate);
1369
1459
 
1370
- // Add id
1371
1460
  (void)json->CreateDataProperty(context, id_str, v8::Integer::New(isolate, obj->id));
1372
1461
 
1373
- // Add name
1374
1462
  char name[NC_MAX_NAME + 1];
1375
1463
  if (obj->get_name(name))
1376
- {
1377
1464
  (void)json->CreateDataProperty(context, name_str,
1378
1465
  v8::String::NewFromUtf8(isolate, name, v8::NewStringType::kInternalized).ToLocalChecked());
1379
- }
1380
1466
 
1381
1467
  // Add type
1382
1468
  const char *type_name = (obj->type < NC_BYTE || obj->type > NC_UINT) ? "unknown" : type_names[obj->type];
1383
1469
  (void)json->CreateDataProperty(context, type_str,
1384
1470
  v8::String::NewFromUtf8(isolate, type_name, v8::NewStringType::kInternalized).ToLocalChecked());
1385
1471
 
1386
- // Dimensions are already an array, just add them
1387
1472
  v8::Local<v8::Value> dimensions = args.Holder()->Get(context, dimensions_str).ToLocalChecked();
1388
1473
  if (dimensions->IsArray())
1389
1474
  {
1390
- (void)json->CreateDataProperty(context, dimensions_str, dimensions);
1475
+ v8::Local<v8::Array> dimsArray = v8::Local<v8::Array>::Cast(dimensions);
1476
+ v8::Local<v8::Array> newDimsArray = v8::Array::New(isolate, dimsArray->Length());
1477
+ v8::Local<v8::String> toJSONStr = v8::String::NewFromUtf8Literal(isolate, "toJSON");
1478
+
1479
+ for (uint32_t i = 0; i < dimsArray->Length(); i++)
1480
+ {
1481
+ v8::Local<v8::Value> value = dimsArray->Get(context, i).ToLocalChecked();
1482
+
1483
+ // Call toJSON if available to ensure proper serialization
1484
+ if (value->IsObject())
1485
+ {
1486
+ v8::Local<v8::Object> valueObj = value->ToObject(context).ToLocalChecked();
1487
+ v8::Local<v8::Value> toJSON = valueObj->Get(context, toJSONStr).ToLocalChecked();
1488
+ if (toJSON->IsFunction())
1489
+ {
1490
+ v8::Local<v8::Function> toJSONFunc = v8::Local<v8::Function>::Cast(toJSON);
1491
+ value = toJSONFunc->Call(context, valueObj, 0, nullptr).ToLocalChecked();
1492
+ }
1493
+ }
1494
+ (void)newDimsArray->Set(context, i, value);
1495
+ }
1496
+ (void)json->CreateDataProperty(context, dimensions_str, newDimsArray);
1391
1497
  }
1392
1498
 
1393
- // Convert attributes object to array
1499
+ // Convert attributes object to array, calling toJSON on each item
1394
1500
  v8::Local<v8::Value> attributes = args.Holder()->Get(context, attributes_str).ToLocalChecked();
1395
1501
  if (attributes->IsObject() && !attributes->IsNull())
1396
1502
  {
1397
1503
  v8::Local<v8::Object> attrsObj = attributes->ToObject(context).ToLocalChecked();
1398
1504
  v8::Local<v8::Array> propNames = attrsObj->GetOwnPropertyNames(context).ToLocalChecked();
1399
1505
  v8::Local<v8::Array> attrsArray = v8::Array::New(isolate, propNames->Length());
1506
+ v8::Local<v8::String> toJSONStr = v8::String::NewFromUtf8Literal(isolate, "toJSON");
1400
1507
 
1401
1508
  for (uint32_t i = 0; i < propNames->Length(); i++)
1402
1509
  {
1403
1510
  v8::Local<v8::Value> key = propNames->Get(context, i).ToLocalChecked();
1404
1511
  v8::Local<v8::Value> value = attrsObj->Get(context, key).ToLocalChecked();
1512
+
1513
+ // Call toJSON if available to ensure proper serialization
1514
+ if (value->IsObject())
1515
+ {
1516
+ v8::Local<v8::Object> valueObj = value->ToObject(context).ToLocalChecked();
1517
+ v8::Local<v8::Value> toJSON = valueObj->Get(context, toJSONStr).ToLocalChecked();
1518
+ if (toJSON->IsFunction())
1519
+ {
1520
+ v8::Local<v8::Function> toJSONFunc = v8::Local<v8::Function>::Cast(toJSON);
1521
+ value = toJSONFunc->Call(context, valueObj, 0, nullptr).ToLocalChecked();
1522
+ }
1523
+ }
1405
1524
  (void)attrsArray->Set(context, i, value);
1406
1525
  }
1407
1526
  (void)json->CreateDataProperty(context, attributes_str, attrsArray);