Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
emscripten-core
GitHub Repository: emscripten-core/emscripten
Path: blob/main/test/embind/test_val.cpp
6160 views
1
// Copyright 2018 The Emscripten Authors. All rights reserved.
2
// Emscripten is available under two separate licenses, the MIT license and the
3
// University of Illinois/NCSA Open Source License. Both these licenses can be
4
// found in the LICENSE file.
5
6
#include <cstdio>
7
#include <iostream>
8
#include <cmath>
9
#include <emscripten/bind.h>
10
#include <emscripten/emscripten.h>
11
#include <emscripten/val.h>
12
13
using namespace emscripten;
14
using namespace std;
15
16
void test(string message) {
17
cout << "test: " << message << "...\n";
18
}
19
20
#define ensure(X) assert(X)
21
#define ensure_not(X) assert(!(X))
22
23
#define ensure_js(js_code) ensure(emscripten_run_script_int(js_code))
24
#define ensure_js_not(js_code) ensure_js((string("!( ") + js_code + " )").c_str())
25
26
void throw_js_error(val js_error) {
27
js_error.throw_();
28
}
29
30
struct Dummy {};
31
32
Dummy * makeDummy() {
33
return new Dummy();
34
}
35
36
EMSCRIPTEN_BINDINGS(test_bindings) {
37
emscripten::class_<Dummy>("Dummy");
38
emscripten::function("throw_js_error", &throw_js_error);
39
emscripten::function("makeDummy", &makeDummy, emscripten::allow_raw_pointers());
40
}
41
42
int main() {
43
printf("start\n");
44
Dummy *dummy;
45
46
test("val array()");
47
val::global().set("a", val::array());
48
ensure_js("a instanceof Array");
49
ensure_js_not("a instanceof Boolean");
50
ensure_js_not("a instanceof Number");
51
52
test("template<typename T> val array(const std::vector<T> vec)");
53
vector<val> vec1;
54
vec1.push_back(val(11));
55
vec1.push_back(val("a"));
56
vec1.push_back(val::array());
57
val::global().set("a", val::array(vec1));
58
ensure_js("a instanceof Array");
59
ensure_js_not("a instanceof Boolean");
60
ensure_js_not("a instanceof Number");
61
ensure_js("a[0] == 11");
62
ensure_js_not("a[0] == 12");
63
ensure_js("a[1] == 'a'");
64
ensure_js("a[2] instanceof Array");
65
vector<int> vec2;
66
vec2.push_back(0);
67
vec2.push_back(1);
68
vec2.push_back(3);
69
val::global().set("a", val::array(vec2));
70
ensure_js("a instanceof Array");
71
ensure_js_not("a instanceof Number");
72
ensure_js("a[0] == 0");
73
ensure_js_not("a[0] == 1");
74
ensure_js("a[1] == 1");
75
ensure_js("a[2] == 3");
76
ensure_js_not("a[2] == 2");
77
vector<int> vec2_from_iter;
78
for (val&& v : val::global("a")) {
79
vec2_from_iter.push_back(v.as<int>());
80
}
81
ensure(vec2 == vec2_from_iter);
82
83
test("template<typename Iter> val array(Iter begin, Iter end)");
84
val::global().set("a", val::array(vec1.begin(), vec1.end()));
85
ensure_js("a instanceof Array");
86
ensure_js_not("a instanceof Boolean");
87
ensure_js_not("a instanceof Number");
88
ensure_js("a[0] == 11");
89
ensure_js_not("a[0] == 12");
90
ensure_js("a[1] == 'a'");
91
ensure_js("a[2] instanceof Array");
92
val::global().set("a", val::array(vec2.begin(), vec2.end()));
93
ensure_js("a instanceof Array");
94
ensure_js_not("a instanceof Number");
95
ensure_js("a[0] == 0");
96
ensure_js_not("a[0] == 1");
97
ensure_js("a[1] == 1");
98
ensure_js("a[2] == 3");
99
ensure_js_not("a[2] == 2");
100
int arr[] = {1, 2, 3};
101
val::global().set("a", val::array(arr, arr + 3));
102
ensure_js("a instanceof Array");
103
ensure_js_not("a instanceof Number");
104
ensure_js("a[0] == 1");
105
ensure_js("a[1] == 2");
106
ensure_js("a[2] == 3");
107
108
test("val object()");
109
val::global().set("a", val::object());
110
ensure_js("a instanceof Object");
111
112
// Test emval{From,To}Handle roundtrip.
113
{
114
val a = val::global("a");
115
val a_roundtrip = val::take_ownership(EM_VAL(EM_ASM_PTR({
116
return Emval.toHandle(Emval.toValue($0));
117
}, a.as_handle())));
118
ensure(a == a_roundtrip);
119
}
120
121
test("val undefined()");
122
val::global().set("a", val::undefined());
123
ensure_js("a == undefined");
124
ensure_js("a != false");
125
126
test("val null()");
127
val::global().set("a", val::null());
128
ensure_js("a == null");
129
ensure_js("a != false");
130
131
test("val global(const char* name = 0)");
132
// best we can probably do is ensure that calling it does not raise an exception
133
val::global();
134
val::global("addEventListener");
135
136
test("template<typename T> explicit val(T&& value)");
137
val::global().set("a", val(false));
138
ensure_js("a == false");
139
val::global().set("a", val(true));
140
ensure_js("a == true");
141
val::global().set("a", val(1));
142
ensure_js("a == 1");
143
val::global().set("a", val(string("1")));
144
ensure_js("a == '1'");
145
146
test("val(const char* v)");
147
val::global().set("a", val("1"));
148
ensure_js("a == '1'");
149
150
test("val()");
151
val a;
152
val::global().set("a", a);
153
ensure_js("a === undefined");
154
a = val(1);
155
val::global().set("a", a);
156
ensure_js("a == 1");
157
val ar[2];
158
ar[0] = val(1);
159
ar[1] = val(2);
160
val::global().set("a", val::array(ar, ar + 2));
161
ensure_js("a instanceof Array");
162
ensure_js_not("a instanceof Number");
163
ensure_js("a[0] == 1");
164
ensure_js("a[1] == 2");
165
166
test("bool isNull()");
167
EM_ASM(
168
globalThis.a = null;
169
globalThis.b = false;
170
globalThis.c = null;
171
globalThis.d = null;
172
globalThis.e = null;
173
globalThis.f = null;
174
globalThis.g = null;
175
globalThis.h = null;
176
globalThis.i = null;
177
);
178
ensure(val::global("a").isNull());
179
ensure_not(val::global("b").isNull());
180
181
test("bool isUndefined()");
182
EM_ASM(
183
a = undefined;
184
b = false;
185
);
186
ensure(val::global("a").isUndefined());
187
ensure_not(val::global("b").isUndefined());
188
189
test("bool isTrue()");
190
EM_ASM(
191
a = true;
192
b = false;
193
c = null;
194
);
195
ensure(val::global("a").isTrue());
196
ensure_not(val::global("b").isTrue());
197
ensure_not(val::global("c").isTrue());
198
199
test("bool isFalse()");
200
EM_ASM(
201
a = false;
202
b = true;
203
c = null;
204
);
205
ensure(val::global("a").isFalse());
206
ensure_not(val::global("b").isFalse());
207
ensure_not(val::global("c").isFalse());
208
209
test("bool isNumber()");
210
EM_ASM(
211
a = 1;
212
b = 1.1;
213
c = true;
214
);
215
ensure(val::global("a").isNumber());
216
ensure(val::global("b").isNumber());
217
ensure_not(val::global("c").isNumber());
218
219
test("bool isString()");
220
EM_ASM(
221
a = '1';
222
b = 1;
223
c = true;
224
);
225
ensure(val::global("a").isString());
226
ensure_not(val::global("b").isString());
227
ensure_not(val::global("c").isString());
228
229
test("bool isArray()");
230
EM_ASM(
231
a = [];
232
b = [1];
233
c = true;
234
d = {};
235
);
236
ensure(val::global("a").isArray());
237
ensure(val::global("b").isArray());
238
ensure_not(val::global("c").isArray());
239
ensure_not(val::global("d").isArray());
240
241
test("val& operator=(val&& v)");
242
val source(val::object());
243
val target(val::object());
244
source.set("val", 1);
245
target = std::move(source);
246
ensure(target["val"].as<int>() == 1);
247
// move and assign to itself
248
target.set("val", 2);
249
target = std::move(target);
250
ensure(target["val"].as<int>() == 2);
251
252
test("bool equals(const val& v)");
253
EM_ASM(
254
a = 1;
255
b = 1;
256
c = 2;
257
d = true;
258
e = '1';
259
);
260
ensure(val::global("a").equals(val::global("a")));
261
ensure(val::global("a").equals(val::global("b")));
262
ensure_not(val::global("a").equals(val::global("c")));
263
ensure(val::global("a").equals(val::global("d")));
264
ensure(val::global("a").equals(val::global("e")));
265
ensure_not(val::global("c").equals(val::global("d")));
266
267
268
test("bool operator==(const val& v)");
269
EM_ASM(
270
a = 1;
271
b = 1;
272
c = 2;
273
d = true;
274
e = '1';
275
);
276
ensure(val::global("a") == val::global("a"));
277
ensure(val::global("a") == val::global("b"));
278
ensure_not(val::global("a") == val::global("c"));
279
ensure(val::global("a") == val::global("d"));
280
ensure(val::global("a") == val::global("e"));
281
ensure_not(val::global("c") == val::global("d"));
282
283
test("bool operator!=(const val& v)");
284
EM_ASM(
285
a = 1;
286
b = 1;
287
c = 2;
288
d = true;
289
e = '1';
290
);
291
ensure_not(val::global("a") != val::global("a"));
292
ensure_not(val::global("a") != val::global("b"));
293
ensure(val::global("a") != val::global("c"));
294
ensure_not(val::global("a") != val::global("d"));
295
ensure_not(val::global("a") != val::global("e"));
296
ensure(val::global("c") != val::global("d"));
297
298
test("bool strictlyEquals(const val& v)");
299
EM_ASM(
300
a = 1;
301
b = 1;
302
c = 2;
303
d = true;
304
e = '1';
305
);
306
ensure(val::global("a").strictlyEquals(val::global("a")));
307
ensure(val::global("a").strictlyEquals(val::global("b")));
308
ensure_not(val::global("a").strictlyEquals(val::global("c")));
309
ensure_not(val::global("a").strictlyEquals(val::global("d")));
310
ensure_not(val::global("a").strictlyEquals(val::global("e")));
311
ensure_not(val::global("c").strictlyEquals(val::global("d")));
312
313
test("bool operator>(const val& v)");
314
EM_ASM(
315
a = 1;
316
b = 1;
317
c = 2;
318
d = '2';
319
);
320
ensure_not(val::global("a") > val::global("a"));
321
ensure_not(val::global("a") > val::global("b"));
322
ensure_not(val::global("a") > val::global("c"));
323
ensure_not(val::global("a") > val::global("d"));
324
ensure(val::global("c") > val::global("a"));
325
ensure(val::global("d") > val::global("a"));
326
327
test("bool operator>= (const val& v)");
328
EM_ASM(
329
a = 1;
330
b = 1;
331
c = 2;
332
d = '2';
333
);
334
ensure(val::global("a") >= val::global("a"));
335
ensure(val::global("a") >= val::global("b"));
336
ensure_not(val::global("a") >= val::global("c"));
337
ensure_not(val::global("a") >= val::global("d"));
338
ensure(val::global("c") >= val::global("a"));
339
ensure(val::global("d") >= val::global("a"));
340
341
test("bool operator<(const val& v)");
342
EM_ASM(
343
a = 1;
344
b = 1;
345
c = 2;
346
d = '2';
347
);
348
ensure_not(val::global("a") < val::global("a"));
349
ensure_not(val::global("a") < val::global("b"));
350
ensure(val::global("a") < val::global("c"));
351
ensure(val::global("a") < val::global("d"));
352
ensure_not(val::global("c") < val::global("a"));
353
ensure_not(val::global("d") < val::global("a"));
354
355
test("bool operator<= (const val& v)");
356
EM_ASM(
357
a = 1;
358
b = 1;
359
c = 2;
360
d = '2';
361
);
362
ensure(val::global("a") <= val::global("a"));
363
ensure(val::global("a") <= val::global("b"));
364
ensure(val::global("a") <= val::global("c"));
365
ensure(val::global("a") <= val::global("d"));
366
ensure_not(val::global("c") <= val::global("a"));
367
ensure_not(val::global("d") <= val::global("a"));
368
369
test("bool operator!()");
370
EM_ASM(
371
a = true;
372
b = false;
373
c = null;
374
d = undefined;
375
e = 0;
376
f = 1;
377
g = "";
378
h = '0';
379
i = 'false';
380
);
381
ensure(!val::global("a") == false);
382
ensure(!val::global("b") == true);
383
ensure(!val::global("c") == true);
384
ensure(!val::global("d") == true);
385
ensure(!val::global("e") == true);
386
ensure(!val::global("f") == false);
387
ensure(!val::global("g") == true);
388
ensure(!val::global("h") == false);
389
ensure(!val::global("i") == false);
390
ensure(!!val::global("a") == true);
391
ensure(!!val::global("b") == false);
392
393
test("template<typename... Args> val new_(Args&&... args)");
394
EM_ASM(
395
globalThis.A = function() {
396
this.value = 2;
397
}
398
);
399
val::global().set("a", val::global("A").new_());
400
ensure_js("a instanceof A");
401
ensure_js("a.value == 2");
402
EM_ASM(
403
globalThis.A = function(arg1, arg2) {
404
this.arg1 = arg1;
405
this.arg2 = arg2;
406
}
407
);
408
val::global().set("a", val::global("A").new_(val(2), val("b")));
409
ensure_js("a instanceof A");
410
ensure_js("a.arg1 == 2");
411
ensure_js("a.arg2 == 'b'");
412
#if __cplusplus >= 201703L
413
dummy = new Dummy();
414
val::global().set("a", val::global("A").new_(dummy, val("b"), allow_raw_pointers()));
415
ensure_js("a instanceof A");
416
ensure_js("a.arg1 instanceof Module.Dummy");
417
ensure_js("a.arg2 == 'b'");
418
delete dummy;
419
#endif
420
421
test("template<typename T> val operator[](const T& key)");
422
EM_ASM(
423
a = 2;
424
);
425
ensure(val::global()["a"].as<int>() == 2);
426
ensure_not(val::global()["a"].as<int>() == 3);
427
val k("a");
428
ensure(val::global()[k].as<int>() == 2);
429
ensure_not(val::global()[k].as<int>() == 3);
430
431
test("template<typename K, typename V> void set(const K& key, const V& value)");
432
val::global().set("a", val(2));
433
ensure_js("a == 2");
434
val::global().set("a", val(3));
435
ensure_js("a == 3");
436
val::global().set("a", 0);
437
ensure_js("a == 0");
438
val::global().set("a", false);
439
ensure_js("a == false");
440
val::global().set("a", 2);
441
ensure_js("a == 2");
442
val::global().set("a", "b");
443
ensure_js("a == 'b'");
444
val::global().set(k, 1);
445
ensure_js("a == 1");
446
val v(3);
447
val::global().set(k, v);
448
ensure("a == 3");
449
ensure(val::global()[k].as<int>() == 3);
450
451
test("template<typename... Args> val operator()(Args&&... args)");
452
EM_ASM(
453
f = function() {
454
return 2;
455
};
456
);
457
ensure(val::global("f")().as<int>() == 2);
458
ensure_not(val::global("f")().as<int>() == 3);
459
EM_ASM(
460
globalThis.f1 = function(arg1, arg2) {
461
return arg1;
462
};
463
globalThis.f2 = function(arg1, arg2) {
464
return arg2;
465
};
466
);
467
ensure(val::global("f1")(val(2),val("3")).as<int>() == 2);
468
ensure(val::global("f2")(val(2),val("3")).as<string>() == "3");
469
#if __cplusplus >= 201703L
470
dummy = new Dummy();
471
ensure(val::global("f1")(dummy, 42, allow_raw_pointers()).as<Dummy*>(allow_raw_pointers()) == dummy);
472
delete dummy;
473
#endif
474
475
test("template<typename ReturnValue, typename... Args> ReturnValue call(const char* name, Args&&... args)");
476
EM_ASM(
477
globalThis.C = function() {
478
this.method = function() { return this; };
479
};
480
c = new C;
481
);
482
ensure(val::global("c").call<val>("method") == val::global("c"));
483
EM_ASM(
484
globalThis.C = function() {
485
this.method = function(arg) { return arg; };
486
};
487
c = new C;
488
);
489
ensure(val::global("c").call<int>("method", val(2)) == 2);
490
#if __cplusplus >= 201703L
491
dummy = new Dummy();
492
EM_ASM(
493
globalThis.C = function() {
494
this.method = function(arg) { this.obj = arg; };
495
};
496
c = new C;
497
);
498
val::global("c").call<void>("method", dummy, allow_raw_pointers());
499
ensure_js("c.obj instanceof Module.Dummy");
500
delete dummy;
501
#endif
502
503
test("template<typename T, typename ...Policies> T as(Policies...)");
504
EM_ASM(
505
a = 1;
506
b = 'b';
507
);
508
ensure(val::global("a").as<int>() == (int)1);
509
ensure(val::global("a").as<double>() == (double)1.0);
510
ensure_not(val::global("a").as<double>() == (double)1.1);
511
ensure(val::global("b").as<string>() == "b");
512
513
// test:
514
// val typeof()
515
#if __STRICT_ANSI__
516
EM_ASM(
517
a = undefined;
518
b = null;
519
c = true;
520
d = 2;
521
e = '2';
522
f = Symbol();
523
g = function () {};
524
h = {};
525
);
526
if (
527
val::global("a").typeOf().as<string>() != "undefined" ||
528
val::global("a").typeOf().as<string>() == "" ||
529
val::global("b").typeOf().as<string>() != "object" ||
530
val::global("c").typeOf().as<string>() != "boolean" ||
531
val::global("d").typeOf().as<string>() != "number" ||
532
val::global("e").typeOf().as<string>() != "string" ||
533
val::global("f").typeOf().as<string>() != "symbol" ||
534
val::global("g").typeOf().as<string>() != "function" ||
535
val::global("h").typeOf().as<string>() != "object"
536
) {
537
printf("test:\nval typeof()\nfail\n");
538
assert(false);
539
}
540
#endif
541
542
test("val typeOf()");
543
EM_ASM(
544
a = undefined;
545
b = null;
546
c = true;
547
d = 2;
548
e = '2';
549
f = Symbol();
550
g = function () {};
551
h = {};
552
);
553
ensure(val::global("a").typeOf().as<string>() == "undefined");
554
ensure_not(val::global("a").typeOf().as<string>() == "");
555
ensure(val::global("b").typeOf().as<string>() == "object");
556
ensure(val::global("c").typeOf().as<string>() == "boolean");
557
ensure(val::global("d").typeOf().as<string>() == "number");
558
ensure(val::global("e").typeOf().as<string>() == "string");
559
ensure(val::global("f").typeOf().as<string>() == "symbol");
560
ensure(val::global("g").typeOf().as<string>() == "function");
561
ensure(val::global("h").typeOf().as<string>() == "object");
562
ensure(val::undefined().typeOf().as<string>() == "undefined");
563
ensure(val::null().typeOf().as<string>() == "object");
564
ensure(val(true).typeOf().as<string>() == "boolean");
565
ensure(val(2).typeOf().as<string>() == "number");
566
ensure(val("2").typeOf().as<string>() == "string");
567
ensure(val::global().call<val>("Symbol").typeOf().as<string>() == "symbol");
568
ensure(val::object().typeOf().as<string>() == "object");
569
570
test("bool instanceof(const val& v)");
571
EM_ASM(
572
globalThis.A = function() {};
573
globalThis.B = function() {};
574
a = new A;
575
);
576
ensure(val::global("a").instanceof(val::global("A")));
577
ensure_not(val::global("a").instanceof(val::global("B")));
578
579
test("bool in(const val& v)");
580
EM_ASM(
581
// can't declare like this because I get:
582
// error: use of undeclared identifier 'c'
583
// possibly a bug with EM_ASM
584
//a = {b: 'bb',c: 'cc'};
585
a = {};
586
a.b = 'bb';
587
a.c = 'cc';
588
);
589
ensure(val("c").in(val::global("a")));
590
ensure_not(val("d").in(val::global("a")));
591
592
test("template<typename T> bool delete_(const T& property)");
593
EM_ASM(
594
a = {};
595
a.b = undefined;
596
a[0] = null;
597
a[1] = 2;
598
a.c = 'c';
599
);
600
ensure_js("'b' in a");
601
ensure_js("0 in a");
602
ensure_js("1 in a");
603
ensure_js("'c' in a");
604
ensure(val::global("a").delete_("b") == true);
605
ensure_js_not("'b' in a");
606
ensure_js("0 in a");
607
ensure_js("1 in a");
608
ensure_js("'c' in a");
609
ensure(val::global("a").delete_(0) == true);
610
ensure(val::global("a").delete_(val(1)) == true);
611
ensure(val::global("a").delete_(val("c")) == true);
612
ensure_js_not("'b' in a");
613
ensure_js_not("0 in a");
614
ensure_js_not("1 in a");
615
ensure_js_not("'c' in a");
616
617
test("void throw_() const");
618
EM_ASM(
619
globalThis.test_val_throw_ = function(error) {
620
try {
621
Module.throw_js_error(error);
622
return false;
623
} catch(error_thrown) {
624
if (error_thrown != error)
625
throw error_thrown;
626
}
627
return true;
628
}
629
);
630
ensure_js("test_val_throw_(new Error)");
631
ensure_js("test_val_throw_(Error)");
632
ensure_js("test_val_throw_(2)");
633
ensure_js("test_val_throw_('message')");
634
ensure_js("test_val_throw_(new TypeError('message'))");
635
636
// these tests should probably go elsewhere as it is not a member of val
637
test("template<typename T> std::vector<T> vecFromJSArray(const val& v)");
638
EM_ASM(
639
// can't declare like this because I get:
640
// error: expected ')'
641
// possibly a bug with EM_ASM
642
//a = [1, '2'];
643
a = [];
644
a[0] = 1;
645
a[1] = '42';
646
a[2] = 'b';
647
a[3] = new Date(100000);
648
);
649
const std::vector<val>& aAsArray = vecFromJSArray<val>(val::global("a"));
650
ensure(aAsArray.at(0).as<int>() == 1);
651
ensure(aAsArray.at(1).as<string>() == "42");
652
ensure(aAsArray.at(2).as<string>() == "b");
653
ensure(aAsArray.size() == 4);
654
655
test("template<typename T> std::vector<T *> vecFromJSArray(const val& v)");
656
EM_ASM(
657
b = [];
658
b[0] = Module.makeDummy();
659
b[1] = Module.makeDummy();
660
);
661
const std::vector<Dummy *>& bAsArray = vecFromJSArray<Dummy *>(val::global("b"), allow_raw_pointers());
662
ensure(bAsArray.size() == 2);
663
for (auto *dummy : bAsArray) {
664
delete dummy;
665
}
666
667
test("template<typename T> std::vector<T> convertJSArrayToNumberVector(const val& v)");
668
669
const std::vector<float>& aAsNumberVectorFloat = convertJSArrayToNumberVector<float>(val::global("a"));
670
ensure(aAsNumberVectorFloat.size() == 4);
671
672
ensure(aAsNumberVectorFloat.at(0) == 1.f);
673
ensure(aAsNumberVectorFloat.at(1) == 42.f); // String containing numbers are converted correctly
674
ensure(std::isnan(aAsNumberVectorFloat.at(2))); // NaN returned if can not be converted for floats
675
ensure(aAsNumberVectorFloat.at(3) == 100000.f); // Date returns milliseconds since epoch
676
677
const std::vector<uint32_t>& aAsNumberVectorUint32_t = convertJSArrayToNumberVector<uint32_t>(val::global("a"));
678
ensure(aAsNumberVectorUint32_t.size() == 4);
679
680
ensure(aAsNumberVectorUint32_t.at(0) == 1);
681
ensure(aAsNumberVectorUint32_t.at(1) == 42); // String containing numbers are converted correctly
682
ensure(aAsNumberVectorUint32_t.at(2) == 0); // 0 is returned if can not be converted for integers
683
ensure(aAsNumberVectorUint32_t.at(3) == 100000); // Date returns milliseconds since epoch
684
685
test("val u8string(const char* s)");
686
val::global().set("a", val::u8string(u8"abc"));
687
ensure_js("a == 'abc'");
688
val::global().set("a", val::u8string(u8"你好"));
689
ensure_js_not("a == 'abc'");
690
ensure_js("a == '你好'");
691
auto u8_str = val::global()["a"].as<std::string>();
692
ensure(u8_str == u8"你好");
693
694
test("val u16string(const char16_t* s)");
695
val::global().set("a", val::u16string(u"hello"));
696
ensure_js("a == 'hello'");
697
val::global().set("a", val::u16string(u"世界"));
698
ensure_js_not("a == 'hello'");
699
ensure_js("a == '世界'");
700
// UTF-16 encoded SMILING FACE WITH OPEN MOUTH (U+1F603)
701
const char16_t* s = u"😃 = \U0001F603 is :-D";
702
val::global().set("a", val::u16string(s));
703
ensure_js("a == '😃 = \U0001F603 is :-D'");
704
705
test("val set() with policy");
706
dummy = new Dummy();
707
val::global().set("a", dummy, allow_raw_pointers());
708
ensure_js("a instanceof Module.Dummy");
709
val::global().set("a", val::null());
710
delete dummy;
711
712
test("val as<> with reference");
713
EM_ASM(
714
globalThis.staticDummy = Module.makeDummy();
715
globalThis.c = function(obj) {
716
return globalThis.staticDummy;
717
};
718
);
719
Dummy& staticDummy = val::global("c")().as<Dummy&>();
720
EM_ASM(
721
globalThis.staticDummy.delete();
722
);
723
724
printf("end\n");
725
return 0;
726
}
727
728