Skip to content

Commit 85d3e5a

Browse files
committed
opengl support for memory64
1 parent 6840514 commit 85d3e5a

File tree

8 files changed

+421
-317
lines changed

8 files changed

+421
-317
lines changed

emcc.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2736,10 +2736,10 @@ def get_full_import_name(name):
27362736

27372737
# check if we can address the 2GB mark and higher: either if we start at
27382738
# 2GB, or if we allow growth to either any amount or to 2GB or more.
2739-
if settings.INITIAL_MEMORY > 2 * 1024 * 1024 * 1024 or \
2739+
if settings.MEMORY64 == 0 and (settings.INITIAL_MEMORY > 2 * 1024 * 1024 * 1024 or \
27402740
(settings.ALLOW_MEMORY_GROWTH and
27412741
(settings.MAXIMUM_MEMORY < 0 or
2742-
settings.MAXIMUM_MEMORY > 2 * 1024 * 1024 * 1024)):
2742+
settings.MAXIMUM_MEMORY > 2 * 1024 * 1024 * 1024))):
27432743
settings.CAN_ADDRESS_2GB = 1
27442744

27452745
settings.EMSCRIPTEN_VERSION = shared.EMSCRIPTEN_VERSION

src/embind/embind.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// Emscripten is available under two separate licenses, the MIT license and the
33
// University of Illinois/NCSA Open Source License. Both these licenses can be
44
// found in the LICENSE file.
5+
// SPDX-FileCopyrightText: Portions Copyright 2023 Siemens
6+
// Modified on February 2023 by Siemens and/or its affiliates to improve memory64 support
57

68
/*global LibraryManager, mergeInto*/
79

@@ -469,7 +471,11 @@ var LibraryEmbind = {
469471
} else {
470472
throw new TypeError("Unknown boolean type size: " + name);
471473
}
474+
#if MEMORY64
475+
return this['fromWireType'](heap[pointer / (1 << shift)]);
476+
#else
472477
return this['fromWireType'](heap[pointer >> shift]);
478+
#endif
473479
},
474480
destructorFunction: null, // This type does not need a destructor
475481
});

src/library_egl.js

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
* @license
33
* Copyright 2012 The Emscripten Authors
44
* SPDX-License-Identifier: MIT
5+
* SPDX-FileCopyrightText: Portions Copyright 2023 Siemens
6+
* Modified on February 2023 by Siemens and/or its affiliates to improve memory64 support
57
*/
68

79
/*
@@ -91,7 +93,7 @@ var LibraryEGL = {
9193

9294
// EGLAPI EGLDisplay EGLAPIENTRY eglGetDisplay(EGLNativeDisplayType display_id);
9395
eglGetDisplay__proxy: 'sync',
94-
eglGetDisplay__sig: 'ii',
96+
eglGetDisplay__sig: 'pp',
9597
eglGetDisplay: function(nativeDisplayType) {
9698
EGL.setErrorCode(0x3000 /* EGL_SUCCESS */);
9799
// Note: As a 'conformant' implementation of EGL, we would prefer to init here only if the user
@@ -110,7 +112,7 @@ var LibraryEGL = {
110112

111113
// EGLAPI EGLBoolean EGLAPIENTRY eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor);
112114
eglInitialize__proxy: 'sync',
113-
eglInitialize__sig: 'iiii',
115+
eglInitialize__sig: 'ippp',
114116
eglInitialize: function(display, majorVersion, minorVersion) {
115117
if (display != 62000 /* Magic ID for Emscripten 'default display' */) {
116118
EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */);
@@ -129,7 +131,7 @@ var LibraryEGL = {
129131

130132
// EGLAPI EGLBoolean EGLAPIENTRY eglTerminate(EGLDisplay dpy);
131133
eglTerminate__proxy: 'sync',
132-
eglTerminate__sig: 'ii',
134+
eglTerminate__sig: 'ip',
133135
eglTerminate: function(display) {
134136
if (display != 62000 /* Magic ID for Emscripten 'default display' */) {
135137
EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */);
@@ -145,21 +147,21 @@ var LibraryEGL = {
145147

146148
// EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config);
147149
eglGetConfigs__proxy: 'sync',
148-
eglGetConfigs__sig: 'iiiii',
150+
eglGetConfigs__sig: 'ippip',
149151
eglGetConfigs: function(display, configs, config_size, numConfigs) {
150152
return EGL.chooseConfig(display, 0, configs, config_size, numConfigs);
151153
},
152154

153155
// EGLAPI EGLBoolean EGLAPIENTRY eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config);
154156
eglChooseConfig__proxy: 'sync',
155-
eglChooseConfig__sig: 'iiiiii',
157+
eglChooseConfig__sig: 'ipppip',
156158
eglChooseConfig: function(display, attrib_list, configs, config_size, numConfigs) {
157159
return EGL.chooseConfig(display, attrib_list, configs, config_size, numConfigs);
158160
},
159161

160162
// EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value);
161163
eglGetConfigAttrib__proxy: 'sync',
162-
eglGetConfigAttrib__sig: 'iiiii',
164+
eglGetConfigAttrib__sig: 'ippip',
163165
eglGetConfigAttrib: function(display, config, attribute, value) {
164166
if (display != 62000 /* Magic ID for Emscripten 'default display' */) {
165167
EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */);
@@ -277,7 +279,7 @@ var LibraryEGL = {
277279

278280
// EGLAPI EGLSurface EGLAPIENTRY eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list);
279281
eglCreateWindowSurface__proxy: 'sync',
280-
eglCreateWindowSurface__sig: 'iiiii',
282+
eglCreateWindowSurface__sig: 'ppppp',
281283
eglCreateWindowSurface: function(display, config, win, attrib_list) {
282284
if (display != 62000 /* Magic ID for Emscripten 'default display' */) {
283285
EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */);
@@ -297,7 +299,7 @@ var LibraryEGL = {
297299

298300
// EGLAPI EGLBoolean EGLAPIENTRY eglDestroySurface(EGLDisplay display, EGLSurface surface);
299301
eglDestroySurface__proxy: 'sync',
300-
eglDestroySurface__sig: 'iii',
302+
eglDestroySurface__sig: 'ipp',
301303
eglDestroySurface: function(display, surface) {
302304
if (display != 62000 /* Magic ID for Emscripten 'default display' */) {
303305
EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */);
@@ -321,7 +323,7 @@ var LibraryEGL = {
321323

322324
// EGLAPI EGLContext EGLAPIENTRY eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list);
323325
eglCreateContext__proxy: 'sync',
324-
eglCreateContext__sig: 'iiiii',
326+
eglCreateContext__sig: 'ppppp',
325327
eglCreateContext: function(display, config, hmm, contextAttribs) {
326328
if (display != 62000 /* Magic ID for Emscripten 'default display' */) {
327329
EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */);
@@ -386,7 +388,7 @@ var LibraryEGL = {
386388

387389
// EGLAPI EGLBoolean EGLAPIENTRY eglDestroyContext(EGLDisplay dpy, EGLContext context);
388390
eglDestroyContext__proxy: 'sync',
389-
eglDestroyContext__sig: 'iii',
391+
eglDestroyContext__sig: 'ipp',
390392
eglDestroyContext: function(display, context) {
391393
if (display != 62000 /* Magic ID for Emscripten 'default display' */) {
392394
EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */);
@@ -407,7 +409,7 @@ var LibraryEGL = {
407409

408410
// EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value);
409411
eglQuerySurface__proxy: 'sync',
410-
eglQuerySurface__sig: 'iiiii',
412+
eglQuerySurface__sig: 'ippip',
411413
eglQuerySurface: function(display, surface, attribute, value) {
412414
if (display != 62000 /* Magic ID for Emscripten 'default display' */) {
413415
EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */);
@@ -474,7 +476,7 @@ var LibraryEGL = {
474476

475477
// EGLAPI EGLBoolean EGLAPIENTRY eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value);
476478
eglQueryContext__proxy: 'sync',
477-
eglQueryContext__sig: 'iiiii',
479+
eglQueryContext__sig: 'ippip',
478480
eglQueryContext: function(display, context, attribute, value) {
479481
if (display != 62000 /* Magic ID for Emscripten 'default display' */) {
480482
EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */);
@@ -522,7 +524,7 @@ var LibraryEGL = {
522524
// EGLAPI const char * EGLAPIENTRY eglQueryString(EGLDisplay dpy, EGLint name);
523525
eglQueryString__deps: ['$allocateUTF8'],
524526
eglQueryString__proxy: 'sync',
525-
eglQueryString__sig: 'iii',
527+
eglQueryString__sig: 'ppi',
526528
eglQueryString: function(display, name) {
527529
if (display != 62000 /* Magic ID for Emscripten 'default display' */) {
528530
EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */);
@@ -589,7 +591,7 @@ var LibraryEGL = {
589591
// EGLAPI EGLBoolean EGLAPIENTRY eglSwapInterval(EGLDisplay dpy, EGLint interval);
590592
eglSwapInterval__deps: ['emscripten_set_main_loop_timing'],
591593
eglSwapInterval__proxy: 'sync',
592-
eglSwapInterval__sig: 'iii',
594+
eglSwapInterval__sig: 'ipi',
593595
eglSwapInterval: function(display, interval) {
594596
if (display != 62000 /* Magic ID for Emscripten 'default display' */) {
595597
EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */);
@@ -605,7 +607,7 @@ var LibraryEGL = {
605607
// EGLAPI EGLBoolean EGLAPIENTRY eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx);
606608
eglMakeCurrent__deps: ['$GL'],
607609
eglMakeCurrent__proxy: 'sync',
608-
eglMakeCurrent__sig: 'iiiii',
610+
eglMakeCurrent__sig: 'ipppp',
609611
eglMakeCurrent: function(display, draw, read, context) {
610612
if (display != 62000 /* Magic ID for Emscripten 'default display' */) {
611613
EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */);
@@ -632,14 +634,14 @@ var LibraryEGL = {
632634

633635
// EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext(void);
634636
eglGetCurrentContext__proxy: 'sync',
635-
eglGetCurrentContext__sig: 'i',
637+
eglGetCurrentContext__sig: 'p',
636638
eglGetCurrentContext: function() {
637639
return EGL.currentContext;
638640
},
639641

640642
// EGLAPI EGLSurface EGLAPIENTRY eglGetCurrentSurface(EGLint readdraw);
641643
eglGetCurrentSurface__proxy: 'sync',
642-
eglGetCurrentSurface__sig: 'ii',
644+
eglGetCurrentSurface__sig: 'pi',
643645
eglGetCurrentSurface: function(readdraw) {
644646
if (readdraw == 0x305A /* EGL_READ */) {
645647
return EGL.currentReadSurface;
@@ -653,15 +655,15 @@ var LibraryEGL = {
653655

654656
// EGLAPI EGLDisplay EGLAPIENTRY eglGetCurrentDisplay(void);
655657
eglGetCurrentDisplay__proxy: 'sync',
656-
eglGetCurrentDisplay__sig: 'i',
658+
eglGetCurrentDisplay__sig: 'p',
657659
eglGetCurrentDisplay: function() {
658660
return EGL.currentContext ? 62000 /* Magic ID for Emscripten 'default display' */ : 0;
659661
},
660662

661663
// EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay dpy, EGLSurface surface);
662664
eglSwapBuffers__proxy: 'sync',
663-
eglSwapBuffers__sig: 'iii',
664-
eglSwapBuffers: function() {
665+
eglSwapBuffers__sig: 'ipp',
666+
eglSwapBuffers: function(dpy, surface) {
665667
#if PROXY_TO_WORKER
666668
if (Browser.doSwapBuffers) Browser.doSwapBuffers();
667669
#endif

src/library_html5.js

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
* @license
33
* Copyright 2014 The Emscripten Authors
44
* SPDX-License-Identifier: MIT
5+
* SPDX-FileCopyrightText: Portions Copyright 2023 Siemens
6+
* Modified on February 2023 by Siemens and/or its affiliates to improve memory64 support
57
*/
68

79
var LibraryHTML5 = {
@@ -314,7 +316,11 @@ var LibraryHTML5 = {
314316
// values we accept here, EMSCRIPTEN_EVENT_TARGET_* (which map to 0, 1, 2).
315317
// In other words, if cString > 2 then it's a pointer to a valid place in
316318
// memory, and points to a C string.
319+
#if MEMORY64
320+
return cString > 2 ? UTF8ToString(Number(cString)) : cString;
321+
#else
317322
return cString > 2 ? UTF8ToString(cString) : cString;
323+
#endif
318324
},
319325

320326
$findEventTarget__deps: ['$maybeCStringToJsString', '$specialHTMLTargets'],
@@ -524,10 +530,10 @@ var LibraryHTML5 = {
524530
if (targetThread) {
525531
var mouseEventData = _malloc( {{{ C_STRUCTS.EmscriptenMouseEvent.__size__ }}} ); // This allocated block is passed as satellite data to the proxied function call, so the call frees up the data block when done.
526532
fillMouseEventData(mouseEventData, e, target);
527-
JSEvents.queueEventHandlerOnThread_iiii(targetThread, callbackfunc, eventTypeId, mouseEventData, userData);
533+
JSEvents.queueEventHandlerOnThread_iipp(targetThread, callbackfunc, eventTypeId, mouseEventData, userData);
528534
} else
529535
#endif
530-
if ({{{ makeDynCall('iiii', 'callbackfunc') }}}(eventTypeId, JSEvents.mouseEvent, userData)) e.preventDefault();
536+
if ({{{ makeDynCall('iipp', 'callbackfunc') }}}(eventTypeId, JSEvents.mouseEvent, userData)) e.preventDefault();
531537
};
532538

533539
var eventHandler = {
@@ -548,71 +554,71 @@ var LibraryHTML5 = {
548554
},
549555

550556
emscripten_set_click_callback_on_thread__proxy: 'sync',
551-
emscripten_set_click_callback_on_thread__sig: 'iiiiii',
557+
emscripten_set_click_callback_on_thread__sig: 'ippipp',
552558
emscripten_set_click_callback_on_thread__deps: ['$registerMouseEventCallback'],
553559
emscripten_set_click_callback_on_thread: function(target, userData, useCapture, callbackfunc, targetThread) {
554560
registerMouseEventCallback(target, userData, useCapture, callbackfunc, {{{ cDefine('EMSCRIPTEN_EVENT_CLICK') }}}, "click", targetThread);
555561
return {{{ cDefine('EMSCRIPTEN_RESULT_SUCCESS') }}};
556562
},
557563

558564
emscripten_set_mousedown_callback_on_thread__proxy: 'sync',
559-
emscripten_set_mousedown_callback_on_thread__sig: 'iiiiii',
565+
emscripten_set_mousedown_callback_on_thread__sig: 'ippipp',
560566
emscripten_set_mousedown_callback_on_thread__deps: ['$registerMouseEventCallback'],
561567
emscripten_set_mousedown_callback_on_thread: function(target, userData, useCapture, callbackfunc, targetThread) {
562568
registerMouseEventCallback(target, userData, useCapture, callbackfunc, {{{ cDefine('EMSCRIPTEN_EVENT_MOUSEDOWN') }}}, "mousedown", targetThread);
563569
return {{{ cDefine('EMSCRIPTEN_RESULT_SUCCESS') }}};
564570
},
565571

566572
emscripten_set_mouseup_callback_on_thread__proxy: 'sync',
567-
emscripten_set_mouseup_callback_on_thread__sig: 'iiiiii',
573+
emscripten_set_mouseup_callback_on_thread__sig: 'ippipp',
568574
emscripten_set_mouseup_callback_on_thread__deps: ['$registerMouseEventCallback'],
569575
emscripten_set_mouseup_callback_on_thread: function(target, userData, useCapture, callbackfunc, targetThread) {
570576
registerMouseEventCallback(target, userData, useCapture, callbackfunc, {{{ cDefine('EMSCRIPTEN_EVENT_MOUSEUP') }}}, "mouseup", targetThread);
571577
return {{{ cDefine('EMSCRIPTEN_RESULT_SUCCESS') }}};
572578
},
573579

574580
emscripten_set_dblclick_callback_on_thread__proxy: 'sync',
575-
emscripten_set_dblclick_callback_on_thread__sig: 'iiiiii',
581+
emscripten_set_dblclick_callback_on_thread__sig: 'ippipp',
576582
emscripten_set_dblclick_callback_on_thread__deps: ['$registerMouseEventCallback'],
577583
emscripten_set_dblclick_callback_on_thread: function(target, userData, useCapture, callbackfunc, targetThread) {
578584
registerMouseEventCallback(target, userData, useCapture, callbackfunc, {{{ cDefine('EMSCRIPTEN_EVENT_DBLCLICK') }}}, "dblclick", targetThread);
579585
return {{{ cDefine('EMSCRIPTEN_RESULT_SUCCESS') }}};
580586
},
581587

582588
emscripten_set_mousemove_callback_on_thread__proxy: 'sync',
583-
emscripten_set_mousemove_callback_on_thread__sig: 'iiiiii',
589+
emscripten_set_mousemove_callback_on_thread__sig: 'ippipp',
584590
emscripten_set_mousemove_callback_on_thread__deps: ['$registerMouseEventCallback'],
585591
emscripten_set_mousemove_callback_on_thread: function(target, userData, useCapture, callbackfunc, targetThread) {
586592
registerMouseEventCallback(target, userData, useCapture, callbackfunc, {{{ cDefine('EMSCRIPTEN_EVENT_MOUSEMOVE') }}}, "mousemove", targetThread);
587593
return {{{ cDefine('EMSCRIPTEN_RESULT_SUCCESS') }}};
588594
},
589595

590596
emscripten_set_mouseenter_callback_on_thread__proxy: 'sync',
591-
emscripten_set_mouseenter_callback_on_thread__sig: 'iiiiii',
597+
emscripten_set_mouseenter_callback_on_thread__sig: 'ippipp',
592598
emscripten_set_mouseenter_callback_on_thread__deps: ['$registerMouseEventCallback'],
593599
emscripten_set_mouseenter_callback_on_thread: function(target, userData, useCapture, callbackfunc, targetThread) {
594600
registerMouseEventCallback(target, userData, useCapture, callbackfunc, {{{ cDefine('EMSCRIPTEN_EVENT_MOUSEENTER') }}}, "mouseenter", targetThread);
595601
return {{{ cDefine('EMSCRIPTEN_RESULT_SUCCESS') }}};
596602
},
597603

598604
emscripten_set_mouseleave_callback_on_thread__proxy: 'sync',
599-
emscripten_set_mouseleave_callback_on_thread__sig: 'iiiiii',
605+
emscripten_set_mouseleave_callback_on_thread__sig: 'ippipp',
600606
emscripten_set_mouseleave_callback_on_thread__deps: ['$registerMouseEventCallback'],
601607
emscripten_set_mouseleave_callback_on_thread: function(target, userData, useCapture, callbackfunc, targetThread) {
602608
registerMouseEventCallback(target, userData, useCapture, callbackfunc, {{{ cDefine('EMSCRIPTEN_EVENT_MOUSELEAVE') }}}, "mouseleave", targetThread);
603609
return {{{ cDefine('EMSCRIPTEN_RESULT_SUCCESS') }}};
604610
},
605611

606612
emscripten_set_mouseover_callback_on_thread__proxy: 'sync',
607-
emscripten_set_mouseover_callback_on_thread__sig: 'iiiiii',
613+
emscripten_set_mouseover_callback_on_thread__sig: 'ippipp',
608614
emscripten_set_mouseover_callback_on_thread__deps: ['$registerMouseEventCallback'],
609615
emscripten_set_mouseover_callback_on_thread: function(target, userData, useCapture, callbackfunc, targetThread) {
610616
registerMouseEventCallback(target, userData, useCapture, callbackfunc, {{{ cDefine('EMSCRIPTEN_EVENT_MOUSEOVER') }}}, "mouseover", targetThread);
611617
return {{{ cDefine('EMSCRIPTEN_RESULT_SUCCESS') }}};
612618
},
613619

614620
emscripten_set_mouseout_callback_on_thread__proxy: 'sync',
615-
emscripten_set_mouseout_callback_on_thread__sig: 'iiiiii',
621+
emscripten_set_mouseout_callback_on_thread__sig: 'ippipp',
616622
emscripten_set_mouseout_callback_on_thread__deps: ['$registerMouseEventCallback'],
617623
emscripten_set_mouseout_callback_on_thread: function(target, userData, useCapture, callbackfunc, targetThread) {
618624
registerMouseEventCallback(target, userData, useCapture, callbackfunc, {{{ cDefine('EMSCRIPTEN_EVENT_MOUSEOUT') }}}, "mouseout", targetThread);
@@ -655,7 +661,7 @@ var LibraryHTML5 = {
655661
if (targetThread) JSEvents.queueEventHandlerOnThread_iiii(targetThread, callbackfunc, eventTypeId, wheelEvent, userData);
656662
else
657663
#endif
658-
if ({{{ makeDynCall('iiii', 'callbackfunc') }}}(eventTypeId, wheelEvent, userData)) e.preventDefault();
664+
if ({{{ makeDynCall('iipp', 'callbackfunc') }}}(eventTypeId, wheelEvent, userData)) e.preventDefault();
659665
};
660666
#if MIN_IE_VERSION <= 8 || MIN_SAFARI_VERSION < 60100 // Browsers that do not support https://caniuse.com/#feat=mdn-api_wheelevent
661667
// The 'mousewheel' event as implemented in Safari 6.0.5
@@ -668,7 +674,7 @@ var LibraryHTML5 = {
668674
{{{ makeSetValue('JSEvents.wheelEvent', C_STRUCTS.EmscriptenWheelEvent.deltaY, 'wheelDeltaY', 'double') }}};
669675
{{{ makeSetValue('JSEvents.wheelEvent', C_STRUCTS.EmscriptenWheelEvent.deltaZ, '0 /* Not available */', 'double') }}};
670676
{{{ makeSetValue('JSEvents.wheelEvent', C_STRUCTS.EmscriptenWheelEvent.deltaMode, '0 /* DOM_DELTA_PIXEL */', 'i32') }}};
671-
var shouldCancel = {{{ makeDynCall('iiii', 'callbackfunc') }}}( eventTypeId, JSEvents.wheelEvent, userData);
677+
var shouldCancel = {{{ makeDynCall('iipp', 'callbackfunc') }}}( eventTypeId, JSEvents.wheelEvent, userData);
672678
if (shouldCancel) {
673679
e.preventDefault();
674680
}

0 commit comments

Comments
 (0)