FreeWRL / FreeX3D 4.3.0
JScript_sm.cpp
1/*
2
3
4Javascript C language binding.
5
6*/
7
8/****************************************************************************
9 This file is part of the FreeWRL/FreeX3D Distribution.
10
11 Copyright 2009 CRC Canada. (http://www.crc.gc.ca)
12
13 FreeWRL/FreeX3D is free software: you can redistribute it and/or modify
14 it under the terms of the GNU Lesser Public License as published by
15 the Free Software Foundation, either version 3 of the License, or
16 (at your option) any later version.
17
18 FreeWRL/FreeX3D is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with FreeWRL/FreeX3D. If not, see <http://www.gnu.org/licenses/>.
25****************************************************************************/
26
27
28#include <config.h>
29#ifdef JAVASCRIPT_SM
30#if defined(JS_SMCPP)
31#undef DEBUG
32//#define DEBUG 1 //challenge it with lots of ASSERTS, just for cleaning up code correctness, not production
33//#include <system.h>
34//# include <stdint.h>
35//#include <ctype.h>
36//#undef HAVE_BOOL
37//#include <stdlib.h>
38//#include <math.h>
39//# include <stdio.h>
40//# include <string.h>
41
42# include <jsapi.h> /* JS compiler */
43//# include <jsdbgapi.h> /* JS debugger */
44
45//#if !(defined(JAVASCRIPT_STUB) || defined(JAVASCRIPT_DUK))
46#include <jsversion.h>
47//#undef JS_VERSION
48#ifndef JS_VERSION
49#define JS_VERSION 187
50#endif
51static int js_run_version = JS_VERSION; //may be over-ridden below when more info avail
52//#define JS_THREADSAFE 1 //by default in 186+
53
54#define STRING_SIZE 256
55#define uintN unsigned
56#define intN int
57#define jsint int32_t
58#define jsuint uint32_t
59#define int32 int32_t
60#define jsdouble double
61
62#define JS_FinalizeStub NULL
63#define JS_GET_CLASS JS_GetClassFw
64JSBool JS_NewNumberValue(JSContext *cx, jsdouble d, jsval *rval);
65//#define JSVAL_IS_OBJECT(retval) JSVAL_IS_OBJECT_OR_NULL_IMPL(retval)
66
67
68//typedef _Bool bool;
69
70
71#define JS_GET_PROPERTY_STUB JS_PropertyStub
72/* #define JS_GET_PROPERTY_STUB js_GetPropertyDebug */
73
74#define JS_SET_PROPERTY_STUB1 js_SetPropertyDebug1
75
76/* #define JS_SET_PROPERTY_STUB2 js_SetPropertyDebug2 */
77# define JS_SET_PROPERTY_STUB2 JS_StrictPropertyStub
78#define JS_SET_PROPERTY_STUB3 js_SetPropertyDebug3
79
80
81extern "C" {
82#ifndef IBOOL
83 typedef int IBOOL;
84#endif
85 typedef IBOOL _Bool;
86#include <system.h>
87#include "scenegraph/Vector.h"
88 //#include <display.h>
89#include <internal.h>
90#include <jsapi.h>
91#include "JScript.h"
92
93//class MyClass {
94// enum { PRIVATE_DATA, SLOT_COUNT };
95// JS::Heap<JSString*> str;
96//public:
97// void trace(JSTracer* trc, const char* name) {
98// //JSTraceEdge(trc, &str, "my string");
99// }
100//};
101
102//
103//#include <libFreeWRL.h>
104//
105#include "../vrml_parser/Structs.h"
106#include <iglobal.h>
107//#include "../main/headers.h"
108//#include "../vrml_parser/CParseGeneral.h"
109//#include "../vrml_parser/CRoutes.h"
110//#include "../main/Snapshot.h"
111//#include "../scenegraph/Collision.h"
112//#include "../scenegraph/quaternion.h"
113//#include "../scenegraph/Viewer.h"
114//#include "../input/EAIHelpers.h"
115//#include "../input/SensInterps.h"
116//#include "../x3d_parser/Bindable.h"
117#include "../vrml_parser/CRoutes.h"
118#include "jsNative.h"
119
120void Parser_scanStringValueToMem_B(union anyVrml* any, indexT ctype, const char *value, int isXML);
121int getJsEngineVariant();
122
123} //extern "C"
124
125
126#include "jsVRMLBrowser_sm.h"
127//#include "CScripts.h"
128#include "jsUtils_sm.h"
129#include "jsVRMLClasses_sm.h"
130
131
132#ifndef JSCLASS_GLOBAL_FLAGS
133//spidermonkey < 1.7 doesn't have so define here
134#define JSCLASS_GLOBAL_FLAGS 0
135#endif
136
137#ifdef JAVASCRIPTVERBOSE
138int ActualrunScript(int num, char *script, jsval *rval, char *fn, int line);
139#else
140int ActualrunScript(int num, char *script, jsval *rval);
141#endif
142
143
144static JSClass staticGlobalClass = {
145 "global", // char *name
146 JSCLASS_GLOBAL_FLAGS, // uint32 flags
147 JS_PropertyStub, // JSPropertyOp addProperty
148#if JS_VERSION >= 187
149 JS_DeletePropertyStub, // JSDeletePropertyOp delProperty
150#else
151 JS_PropertyStub,
152#endif
153 JS_PropertyStub, // JSPropertyOp getProperty
154 JS_StrictPropertyStub, // JSStrictPropertyOp setProperty
155 JS_EnumerateStub, // JSEnumerateOp enumerate
156 globalResolve, // JSResolveOp resolve
157 JS_ConvertStub, // JSConvertOp convert
158 // following are optional and can be NULL
159 JS_FinalizeStub, // JSFinalizeOp finalize
160 NULL, // JSClassInternal reserved
161 NULL, // JSCheckAccessOp checkAccess
162 NULL, // JSNative call
163 NULL, // JSNative construct
164 NULL, // JSXDRObjectOp xdrObject
165 NULL, // JSJasInstanceOp hasInstance
166 NULL // JSTraceOp trace
167};
168
169
170
171extern "C" {
172
173
174typedef struct pJScript{
175 JSRuntime *runtime;// = NULL;
176 JSClass globalClass;
177 jsval JSglobal_return_value;
178 struct Shader_Script *current_script; //when in some js callback, you get cx, obj. But what script? Set in the call stack
179 int ijunk;
180}* ppJScript;
181
182void *JScript_constructor(){
183 void *v = MALLOCV(sizeof(struct pJScript));
184 memset(v,0,sizeof(struct pJScript));
185 return v;
186}
187
188
189void JScript_init(struct iiglobal::tJScript *t){
190 //public
191 t->JSglobal_return_val = NULL;
192 //private
193 t->prv = JScript_constructor();
194 {
195 ppJScript p = (ppJScript)t->prv;
196
197 p->runtime = NULL;
198 memcpy(&p->globalClass,&staticGlobalClass,sizeof(staticGlobalClass));
199 t->JSglobal_return_val = &p->JSglobal_return_value;
200 p->current_script = NULL;
201
202 }
203}
204// ppJScript p = (ppJScript)gglobal()->JScript.prv;
205
206// April 20, 2023
207// I found a good test for correct JSAPI calls is to do a GC(runtime) after each call
208// I found we aren't rooting properly especially compiled JSScripts in eventIns
209// -- I don't know the exact proper method, but old way was bombing
210// -- and new way in SM 103 is to use native objects with a Trace function
211// xx but SM 24 doesn't have the trace function to delegate to
212// so I resorted to recompiling eventIn functions -and eventsProcessed- on each frame,
213// and that seems to fix it for now
214// I see memory leakage when running some scenes,
215// but I think its native mallocs not freed (our fault)
216static int DEBUG_SM = 0;
217void FW_MaybeGC(char* note,JSContext * cx) {
218 if (!DEBUG_SM) {
219 JS_MaybeGC(cx);
220 } else {
221 ttglobal tg = gglobal();
222 ppJScript p = (ppJScript)tg->JScript.prv;
223 printf("<%s ", note);
224 JS_GC(p->runtime);
225 printf(">");
226 }
227}
228void My_JSGCCallback(JSRuntime* rt, JSGCStatus status) { //}, void* data) {
229 if(DEBUG_SM) printf("GC %d ", (int)status);
230}
231
232void sm_js_cleanup_script_context(int counter){
233 ttglobal tg = gglobal();
234 ppJScript p = (ppJScript)tg->JScript.prv;
235 JSContext *cx;
236 JSObject *global;
237
238 cx = (JSContext *)getScriptControlIndex(counter)->cx;
239 global = (JSObject *)getScriptControlIndex(counter)->glob;
240 { // Scope A for our various stack objects (JSAutoRequest, RootedObject), so they all go
241 // out of scope before we JS_DestroyContext.
242 JSAutoRequest ar(cx); // In practice, you would want to exit this any
243 // time you're spinning the event loop
244 { // Scope B for JSAutoCompartment
245 JSAutoCompartment ac(cx, global);
246 FW_MaybeGC("C", cx);
247 //printf("<C");
249 //JS_GC(p->runtime);
250 //printf(">");
251 } //Scope B
252 //JS_GC(p->runtime);
253 } //Scope A
254
255}
256
257/********************************************************************
258
259process_eventsProcessed()
260
261According to the spec, all scripts can have an eventsProcessed
262function - see section C.4.3 of the spec.
263
264********************************************************************/
265/* run the script from within C */
266void sm_process_eventsProcessed() {
267
268 int counter;
269 jsval retval;
270 struct CRscriptStruct *scriptcontrol;
271 ttglobal tg = gglobal();
272 ppJScript p = (ppJScript)tg->JScript.prv;
273 for (counter = 0; counter <= tg->CRoutes.max_script_found_and_initialized; counter++) {
274 scriptcontrol = getScriptControlIndex(counter);
275 if(scriptcontrol->thisScriptType != NOSCRIPT ){
276 JSContext *cx = (JSContext *)scriptcontrol->cx;
277 JSObject *obj = (JSObject *)scriptcontrol->glob;
278 { // Scope A for our various stack objects (JSAutoRequest, RootedObject), so they all go
279 // out of scope before we JS_DestroyContext.
280 JSAutoRequest ar(cx); // In practice, you would want to exit this any
281 // time you're spinning the event loop
282 { // Scope B for JSAutoCompartment
283 JSAutoCompartment ac(cx, obj);
284 //printf("<E0");
286 //JS_GC(p->runtime);
287 //printf(">");
288 FW_MaybeGC("E0", cx);
289
290 if (scriptcontrol->eventsProcessed == NULL || TRUE) {
291 scriptcontrol->eventsProcessed = (void *)JS_CompileScript(cx,obj,"eventsProcessed(__eventInTickTime)", strlen ("eventsProcessed(__eventInTickTime)"),
292 "compile eventsProcessed()", 1);
293 if(0) if (!JS_AddObjectRoot(cx,(JSObject**)(&scriptcontrol->eventsProcessed))) {
294 printf ("can not add object root for compiled eventsProcessed() for script %d\n",counter);
295 }
296 }
297 FW_MaybeGC("E1", cx);
298 //printf("<E1");
300 //JS_GC(p->runtime);
301 //printf(">");
302
303 SET_JS_TICKTIME
304 if (!JS_ExecuteScript(cx,obj,(JSScript *)scriptcontrol->eventsProcessed, &retval)) {
305 printf ("can not run eventsProcessed() for script %d\n",counter);
306 }
307 FW_MaybeGC("E2", cx);
308 //printf("<E2");
310 //JS_GC(p->runtime);
311 //printf(">");
312 } //Scope B
313 //JS_GC(p->runtime);
314 } //Scope A
315 } //if !noscript
316 } //for counter
317}
318
319
320
321
322void sm_jsClearScriptControlEntries(int num) //struct CRscriptStruct *ScriptControl)
323{
324 struct CRscriptStruct *ScriptControl;
325 ScriptControl = getScriptControlIndex(num);
326 if (ScriptControl->eventsProcessed != NULL) {
327
328 if (ScriptControl->cx != NULL) {
329 JS_RemoveObjectRoot((JSContext *)ScriptControl->cx,(JSObject**)(&ScriptControl->eventsProcessed));
330 }
331
332 ScriptControl->eventsProcessed = NULL;
333 }
334}
335
336
337
338/* MAX_RUNTIME_BYTES controls when garbage collection takes place. */
339//#define MAX_RUNTIME_BYTES 0xB0000L
340//#define MAX_RUNTIME_BYTES 0xC00000L
341//#define MAX_RUNTIME_BYTES 0x1000000L
342#define MAX_RUNTIME_BYTES 0x4000000L
343//#define MAX_RUNTIME_BYTES 0xF000000L
344
345
346
347#define STACK_CHUNK_SIZE 8192
348
349static int JSaddGlobalECMANativeProperty(int num, const char *name);
350static int JSaddGlobalAssignProperty(int num, const char *name, const char *str);
351
352/*
353 * Global JS variables (from Brendan Eichs short embedding tutorial):
354 *
355 * JSRuntime - 1 runtime per process
356 * JSContext - 1 CONTEXT per thread
357 * global JSObject - 1 global object per CONTEXT
358 *
359 * struct JSClass {
360 * char *name;
361 * uint32 flags;
362 * Mandatory non-null function pointer members:
363 * JSPropertyOp addProperty;
364 * JSPropertyOp delProperty;
365 * JSPropertyOp getProperty;
366 * JSPropertyOp setProperty;
367 * JSEnumerateOp enumerate;
368 * JSResolveOp resolve;
369 * JSConvertOp convert;
370 * JSFinalizeOp finalize;
371 * Optionally non-null members start here:
372 * JSGetObjectOps getObjectOps;
373 * JSCheckAccessOp checkAccess;
374 * JSNative call;
375 * JSNative construct;
376 * JSXDRObjectOp xdrObject;
377 * JSHasInstanceOp hasInstance;
378 * prword spare[2];
379 * };
380 *
381 * global JSClass - populated by stubs
382 *
383 */
384
385static char *DefaultScriptMethods = "function initialize() {}; " \
386 " function shutdown() {}; " \
387 " function eventsProcessed() {}; " \
388 " TRUE=true; FALSE=false; " \
389 " function print(x) {Browser.print(x)}; " \
390 " function println(x) {Browser.println(x)}; " \
391 " function getName() {return Browser.getName()}; "\
392 " function getVersion() {return Browser.getVersion()}; "\
393 " function getCurrentSpeed() {return Browser.getCurrentSpeed()}; "\
394 " function getCurrentFrameRate() {return Browser.getCurrentFrameRate()}; "\
395 " function getWorldURL() {return Browser.getWorldURL()}; "\
396 " function replaceWorld(x) {Browser.replaceWorld(x)}; "\
397 " function loadURL(x,y) {Browser.loadURL(x,y)}; "\
398 " function setDescription(x) {Browser.setDescription(x)}; "\
399 " function createVrmlFromString(x) {Browser.createVrmlFromString(x)}; "\
400 " function createVrmlFromURL(x,y,z) {Browser.createVrmlFromURL(x,y,z)}; "\
401 " function createX3DFromString(x) {Browser.createX3DFromString(x)}; "\
402 " function createX3DFromURL(x,y,z) {Browser.createX3DFromURL(x,y,z)}; "\
403 " function addRoute(a,b,c,d) {Browser.addRoute(a,b,c,d)}; "\
404 " function deleteRoute(a,b,c,d) {Browser.deleteRoute(a,b,c,d)}; "\
405 " function _rename_function(obj,oldf,newf) {if(typeof obj[oldf] === 'function') {obj[newf]=obj[oldf]; delete obj[oldf];}}; "\
406 "";
407
408 //" function _rename_function(obj,oldf,newf) {obj[newf]=obj[oldf]; delete obj[oldf]}; "
409
410/* housekeeping routines */
411int sm_jsIsRunning(){
412 ppJScript p = (ppJScript)gglobal()->JScript.prv;
413 return p->runtime ? 1 : 0;
414}
415void sm_JSDeleteScriptContext(int num){
416 struct CRscriptStruct *ScriptControl;
417 //ppJScript p = (ppJScript)gglobal()->JScript.prv;
418 /* printf ("kill_javascript, context is %p\n",ScriptControl[i].cx); */
419 ScriptControl = getScriptControlIndex(num);
420
421 if (ScriptControl->eventsProcessed != NULL) {
422 JS_RemoveObjectRoot((JSContext *)ScriptControl->cx,(JSObject **)(&ScriptControl->eventsProcessed));
423 }
424
425 //JS_DestroyContext(ScriptControl->cx);
426
427}
428void sm_jsShutdown(){
429 ttglobal tg = gglobal();
430 ppJScript p = (ppJScript)tg->JScript.prv;
431 if(p->runtime)
432 JS_DestroyRuntime(p->runtime);
433 p->runtime = NULL;
434}
435//========================
436
437
438static struct keyname {
439 int key;
440 const char *name;
441} gcparamname [] = {
442{JSGC_MAX_BYTES,"JSGC_MAX_BYTES"},
443{JSGC_MAX_MALLOC_BYTES, "JSGC_MAX_MALLOC_BYTES"},
444{JSGC_BYTES,"JSGC_BYTES"},
445{JSGC_NUMBER,"JSGC_NUMBER"},
446{JSGC_MAX_CODE_CACHE_BYTES,"JSGC_MAX_CODE_CACHE_BYTES"},
447{JSGC_MODE,"JSGC_MODE"},
448{JSGC_UNUSED_CHUNKS,"JSGC_UNUSED_CHUNKS"},
449{JSGC_TOTAL_CHUNKS,"JSGC_TOTAL_CHUNKS"},
450{JSGC_SLICE_TIME_BUDGET,"JSGC_SLICE_TIME_BUDGET"},
451{JSGC_MARK_STACK_LIMIT,"JSGC_MARK_STACK_LIMIT"},
452{JSGC_HIGH_FREQUENCY_TIME_LIMIT,"JSGC_HIGH_FREQUENCY_TIME_LIMIT"},
453{JSGC_HIGH_FREQUENCY_LOW_LIMIT,"JSGC_HIGH_FREQUENCY_LOW_LIMIT"},
454{JSGC_HIGH_FREQUENCY_HIGH_LIMIT,"JSGC_HIGH_FREQUENCY_HIGH_LIMIT"},
455{JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MAX,"JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MAX"},
456{JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MIN,"JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MIN"},
457{JSGC_LOW_FREQUENCY_HEAP_GROWTH,"JSGC_LOW_FREQUENCY_HEAP_GROWTH"},
458{JSGC_DYNAMIC_HEAP_GROWTH,"JSGC_DYNAMIC_HEAP_GROWTH"},
459{JSGC_DYNAMIC_MARK_SLICE,"JSGC_DYNAMIC_MARK_SLICE"},
460{JSGC_ANALYSIS_PURGE_TRIGGER,"JSGC_ANALYSIS_PURGE_TRIGGER"},
461{-1,NULL},
462};
463
464const char *getgcparamname(int key){
465 int i = 0;
466 while(gcparamname[i].name != NULL){
467 if(gcparamname[i].key == key){
468 return gcparamname[i].name;
469 }
470 i++;
471 }
472 return "NULL";
473}
474//void reportError(JSContext *cx, const char *message, JSErrorReport *report) {
475// printf("%s:%u:%s\n",
476// report->filename ? report->filename : "[no filename]",
477// (unsigned int) report->lineno,
478// message);
479//}
480
481
482
483/* create the script context for this script. This is called from the thread
484 that handles script calling in the fwl_RenderSceneUpdateScene
485 July 3, 2018
486 x just changing to cpp for moz24 (from moz185/17) doesn't work. the moz dll bombs/throws.
487 * but following the formula here works - it runs a little script:
488 https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/How_to_embed_the_JavaScript_engine
489 so a lot of our code needs grooming for these weird stack techniques.
490
491 */
492void sm_JSCreateScriptContext(int num) {
493 jsval rval;
494 JSContext *_context; /* these are set here */
495 JSObject *_globalObj; /* these are set here */
496 BrowserNative *br; /* these are set here */
497 ppJScript p = (ppJScript)gglobal()->JScript.prv;
498 struct CRscriptStruct *ScriptControl;
499
500 ScriptControl = getScriptControlIndex(num);
501 /* is this the first time through? */
502 if (p->runtime == NULL) {
503 //p->runtime = JS_NewRuntime(MAX_RUNTIME_BYTES, JSUseHelperThreads::JS_USE_HELPER_THREADS);
504#if JS_VERSION >= 187
505 p->runtime = JS_NewRuntime(MAX_RUNTIME_BYTES, JS_NO_HELPER_THREADS); //JSUseHelperThreads::JS_NO_HELPER_THREADS);
506#else
507 p->runtime = JS_NewRuntime(MAX_RUNTIME_BYTES);
508#endif
509 if (!p->runtime) freewrlDie("JS_NewRuntime failed");
510 //printf("<0");
512 //JS_GC(p->runtime);
513 //printf(">");
514
515 JS_SetGCCallback(p->runtime, My_JSGCCallback); // , NULL);
516 //printf("<1");
518 //JS_GC(p->runtime);
519 //printf(">");
520
521 //js_run_version = (long)JS_GetVersion(cx);
522 const char* strversion = JS_GetImplementationVersion();
523 const char* substr = strstr(strversion, "-C");
524 substr = &substr[2]; //skip -C
525 int i1, i2, i3;
526 sscanf_s(substr, "%d.%d.%d", &i1, &i2, &i3);
527 printf("javascript engine spidermonkey %s %s\n", substr, SM_method() == 2 ? "SM2" : "SM1");
528 js_run_version = i1;
529 }
530
531
532 _context = JS_NewContext(p->runtime, STACK_CHUNK_SIZE);
533 if (!_context) freewrlDie("JS_NewContext failed");
534
535 //JS_SetErrorReporter(_context, reportError);
536
537 JSContext *cx = _context;
538 JS_SetContextPrivate(cx, ScriptControl->script->ShaderScriptNode->_executionContext); //Q. will it be helpful in any X3DScene (aka vrml context) functions?
539 //FW_MaybeGC("2", cx);
540 //printf("<2");
542 //JS_GC(p->runtime);
543 //printf(">");
544
545 { //scope A
546 JSAutoRequest ar(cx); // In practice, you would want to exit this any
547 // time you're spinning the event loop
548
549 JS::RootedObject global(cx, JS_NewGlobalObject(cx, &p->globalClass, nullptr));
550 if (!global)
551 return ;
552
553 JS::RootedValue rval(cx);
554
555 { // Scope B for JSAutoCompartment
556 JSAutoCompartment ac(cx, global);
557 JS_InitStandardClasses(cx, global);
558 FW_MaybeGC("3", cx);
559 //printf("<3");
561 //JS_GC(p->runtime);
562 //printf(">");
563
564 //br = (BrowserNative*)JS_malloc(_context, sizeof(BrowserNative));
565 br = (BrowserNative *) malloc(sizeof(BrowserNative));
566 /* for this script, here are the necessary data areas */
567 _globalObj = global;
568 ScriptControl->cx = _context;
569 ScriptControl->glob = _globalObj;
570 //printf("context %p global %p script %p\n", _context, _globalObj, ScriptControl->script);
571 if(SM_method()==2){
572 //JS_SetPrivateFw(_context,_globalObj,ScriptControl->script); //in get/setECMAtype we need our C script struct
573 //JS_SetPrivate((JSObject*)ScriptControl->glob, ScriptControl->script);
574 //JS_SetPrivate(global, ScriptControl->script);
575 JS_SetSecondContextPrivate(_context, ScriptControl->script);
576 FW_MaybeGC("4", cx);
577 //printf("<4");
579 //JS_GC(p->runtime);
580 //printf(">");
581
582 }
583
584 if (!loadVrmlClasses(_context, _globalObj)){
585 freewrlDie("loadVrmlClasses failed");
586 }
587 FW_MaybeGC("5", cx);
588 //printf("<5");
590 //JS_GC(p->runtime);
591 //printf(">");
592 if (!loadAuxiliaryClasses(_context, _globalObj)) {
593 freewrlDie("loadAuxiliaryClasses failed");
594 }
595 FW_MaybeGC("5b", cx);
596
597 if (!VrmlBrowserInit(_context, _globalObj, br)){
598 freewrlDie("VrmlBrowserInit failed");
599 }
600 FW_MaybeGC("6", cx);
601 //printf("<6");
603 //JS_GC(p->runtime);
604 //printf(">");
605
606 if (!ActualrunScript(num,DefaultScriptMethods,rval.address()))
607 cleanupDie(num,"runScript failed in VRML::newJS DefaultScriptMethods");
608 FW_MaybeGC("7", cx);
609 //printf("<7");
611 //JS_GC(p->runtime);
612 //printf(">");
613
614 if(0) {
615 //baby step test
616 const char *script = "'hello'+'world, it is '+new Date()";
617 const char *filename = "noname";
618 int lineno = 1;
619 bool ok = JS_EvaluateScript(cx, global, script, strlen(script), filename, lineno, rval.address());
620 if (!ok)
621 return ;
622 JSString *str = rval.toString();
623 printf("%s\n", JS_EncodeString(cx, str));
624 }
625 } //scope B
626
627 } //scope A
628
629 /* send this data over to the routing table functions. */
630 CRoutes_js_new (num, JAVASCRIPT);
631
632}
633} //extern "C"
634
635int SM_method(){
636 return getJsEngineVariant() == 2? 2 : 0;
637 //return 2; //new way dec 31, 2017
638 //return 0; //old way before dec 31, 2017
639}
640
641/* run the script from within C */
642int ActualrunScript(int num, char *script, jsval *rval) {
643
644 int len;
645 JSContext *cx;
646 JSObject *global;
647 struct CRscriptStruct *ScriptControl;
648 ttglobal tg = gglobal();
649 ppJScript p = (ppJScript)tg->JScript.prv;
650
651 ScriptControl = getScriptControlIndex(num);
652 /* get context and global object for this script */
653 cx = (JSContext*)ScriptControl->cx;
654 global = (JSObject*)ScriptControl->glob;
655
656 len = (int) strlen(script);
657
658 { // Scope A for our various stack objects (JSAutoRequest, RootedObject), so they all go
659 // out of scope before we JS_DestroyContext.
660 JSAutoRequest ar(cx); // In practice, you would want to exit this any
661 // time you're spinning the event loop
662 { // Scope B for JSAutoCompartment
663 JSAutoCompartment ac(cx, global);
664 bool ok = JS_EvaluateScript(cx, global, script, len, FNAME_STUB, LINENO_STUB, rval);
665 if (!ok) {
666 printf ("ActualrunScript - JS_EvaluateScript failed for %s", script);
667 printf ("\n");
668 ConsoleMessage ("ActualrunScript - JS_EvaluateScript failed for %s", script);
669 return JS_FALSE;
670 }
671 FW_MaybeGC("A", cx);
672
673 //printf("<A");
675 //JS_GC(p->runtime);
676 //printf(">");
677
678 } //Scope B
679 //JS_GC(p->runtime);
680 } //Scope A
681
682 return JS_TRUE;
683}
684
685/* run the script from within Javascript */
686int jsrrunScript(JSContext *cx, JSObject *global, char *script, jsval *rval) {
687 int len;
688 ttglobal tg = gglobal();
689 ppJScript p = (ppJScript)tg->JScript.prv;
690
691 #ifdef JAVASCRIPTVERBOSE
692 printf("jsrrunScript script cx %p \"%s\", \n",
693 _context, script);
694 #endif
695 len = (int) strlen(script);
696 { // Scope A for our various stack objects (JSAutoRequest, RootedObject), so they all go
697 // out of scope before we JS_DestroyContext.
698 JSAutoRequest ar(cx); // In practice, you would want to exit this any
699 // time you're spinning the event loop
700 { // Scope B for JSAutoCompartment
701 JSAutoCompartment ac(cx, global);
702 if (!JS_EvaluateScript(cx, global, script, len,
703 FNAME_STUB, LINENO_STUB, rval)) {
704 ConsoleMessage ("jsrunScript - JS_EvaluateScript failed for %s", script);
705 return JS_FALSE;
706 }
707 } //Scope B
708 JS_GC(p->runtime);
709 } //Scope A
710 return JS_TRUE;
711}
712
713
714extern "C" {
715
716int sm_jsActualrunScript(int num, char *script) {
717 jsval rval; //discard
718 return ACTUALRUNSCRIPT(num,script,&rval);
719}
720
721
722
723
724//put source = NULL if you want it to malloc
725//if its a script field, send in the pointer to the script field valuechanged, or NULL if new thing()
726int sizeofSForMF(int itype);
727void *AnyNativeNew(int type, union anyVrml* source, int *valueChanged){
728 AnyNative *ptr;
729 ptr = MALLOC(AnyNative *,sizeof(AnyNative));
730 memset(ptr,0,sizeof(AnyNative));
731 ptr->type = type;
732 ptr->valueChanged = valueChanged;
733 ptr->v = source;
734 ptr->gc = 0;
735 if(ptr->v == NULL){
736 ptr->v = (union anyVrml *)MALLOC(void *,sizeofSForMF(type));
737 memset(ptr->v,0,sizeofSForMF(type));
738 ptr->gc = 1;
739 }
740 return ptr;
741}
742void shallow_copy_field(int typeIndex, union anyVrml* source, union anyVrml* dest);
743void AnyNativeAssign(void *top, void *fromp)
744{
745 if(top != fromp){
746 AnyNative *to = (AnyNative *)top;
747 AnyNative *from = (AnyNative *)fromp;
748 if(to->valueChanged)
749 (*to->valueChanged) ++;
750 //shallow assumes the top has already been malloced (just base part of MF needed)
751 //use this if you need to malloc anyvrml: int sizeofSForMF(int itype)
752 if (to->type == from->type) {
753 shallow_copy_field(from->type,from->v,to->v);
754 }
755 else {
756 shallow_copy_field_precision(from->type, to->type, from->v, to->v);
757 }
758 }
759}
760/* FROM VRMLC.pm */
761void *SFNodeNativeNew()
762{
763 SFNodeNative *ptr;
764 ptr = MALLOC(SFNodeNative *, sizeof(*ptr));
765
766 /* printf ("SFNodeNativeNew; string len %d handle_len %d\n",vrmlstring_len,handle_len);*/
767
768 ptr->handle = 0;
769 ptr->valueChanged = 0;
770 if(SM_method() == 0){
771 ptr->X3DString = NULL;
772 ptr->fieldsExpanded = FALSE;
773 }
774 return ptr;
775}
776
777/* assign this internally to the Javascript engine environment */
778int SFNodeNativeAssign(void *top, void *fromp)
779{
780 SFNodeNative *to = (SFNodeNative *)top;
781 SFNodeNative *from = (SFNodeNative *)fromp;
782
783 /* indicate that this was touched; and copy contents over */
784 to->valueChanged++;
785
786 if (from != NULL) {
787 to->handle = from->handle;
788 if(SM_method() == 0)
789 to->X3DString = STRDUP(from->X3DString);
790
791 #ifdef JAVASCRIPTVERBOSE
792 printf ("SFNodeNativeAssign, copied %p to %p, handle %p, string %s\n", from, to, to->handle, to->X3DString);
793 #endif
794 } else {
795 to->handle = 0;
796 if(SM_method() == 0)
797 to->X3DString = STRDUP("from a NULL assignment");
798 }
799
800 return JS_TRUE;
801}
802/* assign this internally to the Javascript engine environment */
803int SFNodeNativeEquals(void *top, void *fromp)
804{
805 int equal;
806 SFNodeNative *to = (SFNodeNative *)top;
807 SFNodeNative *from = (SFNodeNative *)fromp;
808
809 equal = 0;
810
811 if (from != NULL) {
812 if(to->handle == from->handle)
813 equal=1;
814 }
815
816 return equal;// ? JS_TRUE : JS_FALSE;
817}
818
819void *SFColorRGBANativeNew()
820{
821 SFColorRGBANative *ptr;
822 ptr = MALLOC(SFColorRGBANative *, sizeof(*ptr));
823 ptr->valueChanged = 0;
824 return ptr;
825}
826
827void SFColorRGBANativeAssign(void *top, void *fromp)
828{
829 SFColorRGBANative *to = (SFColorRGBANative *)top;
830 SFColorRGBANative *from = (SFColorRGBANative *)fromp;
831 to->valueChanged ++;
832 (to->v) = (from->v);
833}
834
835void *SFColorNativeNew()
836{
837 SFColorNative *ptr;
838 ptr = MALLOC(SFColorNative *, sizeof(*ptr));
839 ptr->valueChanged = 0;
840 return ptr;
841}
842
843void SFColorNativeAssign(void *top, void *fromp)
844{
845 SFColorNative *to = (SFColorNative *)top;
846 SFColorNative *from = (SFColorNative *)fromp;
847 to->valueChanged++;
848 (to->v) = (from->v);
849}
850
851void *SFImageNativeNew()
852{
853 SFImageNative *ptr;
854 ptr =MALLOC(SFImageNative *, sizeof(*ptr));
855 ptr->valueChanged = 0;
856 return ptr;
857}
858
859void SFImageNativeAssign(void *top, void *fromp)
860{
861 SFImageNative *to = (SFImageNative *)top;
862 /* SFImageNative *from = fromp; */
863 UNUSED(fromp);
864
865 to->valueChanged++;
866/* (to->v) = (from->v); */
867}
868
869void *SFRotationNativeNew()
870{
871 SFRotationNative *ptr;
872 ptr = MALLOC(SFRotationNative *, sizeof(*ptr));
873 ptr->valueChanged = 0;
874 return ptr;
875}
876
877void SFRotationNativeAssign(void *top, void *fromp)
878{
879 SFRotationNative *to = (SFRotationNative *)top;
880 SFRotationNative *from = (SFRotationNative *)fromp;
881 to->valueChanged++;
882 (to->v) = (from->v);
883}
884
885void *SFVec2fNativeNew()
886{
887 SFVec2fNative *ptr;
888 ptr = MALLOC(SFVec2fNative *, sizeof(*ptr));
889 ptr->valueChanged = 0;
890 return ptr;
891}
892
893void SFVec2fNativeAssign(void *top, void *fromp)
894{
895 SFVec2fNative *to = (SFVec2fNative *)top;
896 SFVec2fNative *from = (SFVec2fNative *)fromp;
897 to->valueChanged++;
898 (to->v) = (from->v);
899}
900
901
902void *SFVec3fNativeNew() {
903 SFVec3fNative *ptr;
904 ptr = MALLOC(SFVec3fNative *, sizeof(*ptr));
905 ptr->valueChanged = 0;
906 return ptr;
907}
908
909void SFVec3fNativeAssign(void *top, void *fromp) {
910 SFVec3fNative *to = (SFVec3fNative *)top;
911 SFVec3fNative *from = (SFVec3fNative *)fromp;
912 to->valueChanged++;
913 (to->v) = (from->v);
914}
915
916void* SFVec2dNativeNew()
917{
918 SFVec2dNative* ptr;
919 ptr = MALLOC(SFVec2dNative*, sizeof(*ptr));
920 ptr->valueChanged = 0;
921 return ptr;
922}
923
924void SFVec2dNativeAssign(void* top, void* fromp)
925{
926 SFVec2dNative* to = (SFVec2dNative*)top;
927 SFVec2dNative* from = (SFVec2dNative*)fromp;
928 to->valueChanged++;
929 (to->v) = (from->v);
930}
931
932
933void *SFVec3dNativeNew() {
934 SFVec3dNative *ptr;
935 ptr = MALLOC(SFVec3dNative *, sizeof(*ptr));
936 ptr->valueChanged = 0;
937 return ptr;
938}
939
940void SFVec3dNativeAssign(void *top, void *fromp) {
941 SFVec3dNative *to = (SFVec3dNative *)top;
942 SFVec3dNative *from = (SFVec3dNative *)fromp;
943 to->valueChanged++;
944 (to->v) = (from->v);
945}
946
947void *SFVec4fNativeNew() {
948 SFVec4fNative *ptr;
949 ptr = MALLOC(SFVec4fNative *, sizeof(*ptr));
950 ptr->valueChanged = 0;
951 return ptr;
952}
953
954void SFVec4fNativeAssign(void *top, void *fromp) {
955 SFVec4fNative *to = (SFVec4fNative *)top;
956 SFVec4fNative *from = (SFVec4fNative *)fromp;
957 to->valueChanged++;
958 (to->v) = (from->v);
959}
960
961void *SFVec4dNativeNew() {
962 SFVec4dNative *ptr;
963 ptr = MALLOC(SFVec4dNative *, sizeof(*ptr));
964 ptr->valueChanged = 0;
965 return ptr;
966}
967
968void SFVec4dNativeAssign(void *top, void *fromp) {
969 SFVec4dNative *to = (SFVec4dNative *)top;
970 SFVec4dNative *from = (SFVec4dNative *)fromp;
971 to->valueChanged++;
972 (to->v) = (from->v);
973}
974
975} //extern "C"
976
977
978static char* re_strcat(char *_Dest, const char *_Source, int *destLen, int *destDim)
979{
980 /* strcats, but first checks strlen on source and destination
981 and reallocs if necessary - good when you are doing a lot of strcatting of un-pre-known elements
982 (Q. is there something for this already?)
983 _Dest, _Source - as with strcat(_Dest,_Source)
984 destLen - current cumulative strlen(_Dest)
985 destDim - current malloc/realloc dimension
986 Usage example:
987 dstdim = (rows+1)*(elements*15) + 100; //a guess
988 dstlen = 0;
989 smallfield = MALLOC (char *, dstdim+1); //rows+1)*(elements*15) + 100);
990 smallfield[0] = '\0';
991 ...
992 for(;;)
993 {
994 ...
995 smallfield = re_strcat(smallfield, "new ",&dstlen,&dstdim);
996 ...
997 FREE_IF_NZ(smallfield)
998 */
999 int srclen = (int) strlen(_Source);
1000 *destLen = *destLen + srclen;
1001 if(*destLen > *destDim -1)
1002 {
1003 *destDim = *destDim + srclen + 1 + 100;
1004 _Dest = (char *)REALLOC(_Dest,*destDim);
1005 }
1006 _Dest = strcat(_Dest,_Source);
1007 return _Dest;
1008}
1009/* the fwl_RenderSceneUpdateScene is initializing this field now */
1010/* A new version of InitScriptField which takes "nicer" arguments; currently a
1011 * simple and restricted wrapper, but it could replace it soon? */
1012/* Parameters:
1013 num: Script number. Starts at 0.
1014 kind: One of PKW_initializeOnly PKW_outputOnly PKW_inputOutput PKW_inputOnly
1015 type: One of the FIELDTYPE_ defines, eg, FIELDTYPE_MFFloat
1016 field: the field name as found in the VRML/X3D file. eg "set_myField"
1017
1018*/
1019void InitScriptField(int num, indexT kind, indexT type, const char* field, union anyVrml value) {
1020 jsval rval;
1021 char *smallfield = NULL;
1022 char mynewname[400];
1023 char *thisValue;
1024 int rows, elements;
1025 char *sftype = NULL;
1026
1027 int haveMulti;
1028 int MFhasECMAtype;
1029 int rowCount, eleCount;
1030
1031 int tlen;
1032 float *FloatPtr;
1033 struct X3D_Node **VoidPtr;
1034 int *IntPtr;
1035 double *DoublePtr;
1036 struct Uni_String **SVPtr;
1037
1038 float defaultFloat[] = {0.0f,0.0f,0.0f,0.0f};
1039 int defaultInt[] = {0,0,0,0};
1040 double defaultDouble[] = {0.0, 0.0, 0.0, 0.0};
1041 struct Uni_String *sptr[1];
1042 struct X3D_Node *defaultVoid[] = {NULL,NULL};
1043 struct CRscriptStruct *ScriptControl; //= getScriptControl();
1044
1045 #ifdef JAVASCRIPTVERBOSE
1046 printf ("calling InitScriptField from thread %u\n",pthread_self());
1047 printf ("\nInitScriptField, num %d, kind %s type %s field %s value %d\n", num,PROTOKEYWORDS[kind],FIELDTYPES[type],field,value);
1048 #endif
1049
1050 if ((kind != PKW_inputOnly) && (kind != PKW_outputOnly) && (kind != PKW_initializeOnly) && (kind != PKW_inputOutput)) {
1051 ConsoleMessage ("InitScriptField: invalid kind for script: %d\n",kind);
1052 return;
1053 }
1054
1055 if (type >= FIELDTYPES_COUNT) {
1056 ConsoleMessage ("InitScriptField: invalid type for script: %d\n",type);
1057 return;
1058 }
1059 ScriptControl = getScriptControlIndex(num);
1060
1061 /* first, make a new name up */
1062 //if (kind == PKW_inputOnly ) {
1063 // sprintf (mynewname,"__eventIn_Value_%s",field);
1064 // //strcpy(mynewname,field);
1065 //}else
1066 if (kind == PKW_inputOutput) {
1067 //check if user added an eventIn function with the same basename,
1068 // which is allowed with inputOutput fields
1069 JSContext *cx;
1070 JSObject *obj;
1071 jsval retval;
1072 cx = (JSContext*)ScriptControl->cx;
1073 obj = (JSObject*)ScriptControl->glob;
1074
1075 if (JS_GetProperty(cx,obj,field,&retval)){
1076 //if (JSVAL_IS_OBJECT(retval)){
1077 if(retval.isObject()){
1078 //I think functions are objects, doesn't seem to be a JSVAL_IS_FUNC
1079 char runstring[STRING_SIZE];
1080 // rename fieldname to set_fieldname
1081 sprintf(runstring,"_rename_function(this,'%s','set_%s');",field,field);
1082 //printf("%s\n",runstring);
1083 { // Scope A for our various stack objects (JSAutoRequest, RootedObject), so they all go
1084 // out of scope before we JS_DestroyContext.
1085 JSAutoRequest ar(cx); // In practice, you would want to exit this any
1086 // time you're spinning the event loop
1087 { // Scope B for JSAutoCompartment
1088 JSAutoCompartment ac(cx, obj);
1089 if(!JS_EvaluateScript(cx,obj, runstring, (int) strlen(runstring), FNAME_STUB, LINENO_STUB, &retval)){
1090 printf("sorry couldn't rename function: %s",runstring);
1091 }
1092 } //Scope B
1093 } //Scope A
1094 }
1095 }
1096 strcpy(mynewname,field); //now this is OK, won't overwrite function
1097 // and if so rename it to set_
1098 }else strcpy(mynewname,field);
1099
1100 /* ok, lets handle the types here */
1101 switch (type) {
1102 /* ECMA types */
1103 case FIELDTYPE_SFBool:
1104 case FIELDTYPE_SFFloat:
1105 case FIELDTYPE_SFTime:
1106 case FIELDTYPE_SFDouble:
1107 case FIELDTYPE_SFInt32:
1108 case FIELDTYPE_SFString: {
1109 /* do not care about eventIns */
1110 if (kind != PKW_inputOnly) {
1111 JSaddGlobalECMANativeProperty(num, field);
1112 if (kind == PKW_initializeOnly || kind == PKW_inputOutput) {
1113 if (type == FIELDTYPE_SFString) {
1114 tlen = (int) strlen(value.sfstring->strptr) + strlen(field) + 20;
1115 } else {
1116 tlen = (int) strlen(field) + 400; /* long, in the case of doubles */
1117 }
1118 smallfield = MALLOC (char *, tlen);
1119 smallfield[0] = '\0';
1120
1121 switch (type) {
1122 case FIELDTYPE_SFFloat: sprintf (smallfield,"%s=%f\n",field,value.sffloat);break;
1123 case FIELDTYPE_SFTime: sprintf (smallfield,"%s=%f\n",field,value.sftime);break;
1124 case FIELDTYPE_SFDouble: sprintf (smallfield,"%s=%f\n",field,value.sftime);break;
1125 case FIELDTYPE_SFInt32: sprintf (smallfield,"%s=%d\n",field,value.sfint32); break;
1126 case FIELDTYPE_SFBool:
1127 if (value.sfbool == 1) sprintf (smallfield,"%s=true",field);
1128 else sprintf (smallfield,"%s=false",field);
1129 break;
1130 case FIELDTYPE_SFString:
1131 sprintf (smallfield,"%s=\"%s\"\n",field,value.sfstring->strptr); break;
1132 }
1133
1134 if (!ACTUALRUNSCRIPT(num,smallfield,&rval))
1135 printf ("huh??? Field initialization script failed %s\n",smallfield);
1136 }
1137 }
1138 break;
1139 }
1140 /* non ECMA types */
1141 default: {
1142 /* get an appropriate pointer - we either point to the initialization value
1143 in the script header, or we point to some data here that are default values */
1144
1145 /* does this MF type have an ECMA type as a single element? */
1146 switch (type) {
1147 case FIELDTYPE_MFString:
1148 case FIELDTYPE_MFTime:
1149 case FIELDTYPE_MFBool:
1150 case FIELDTYPE_MFInt32:
1151 case FIELDTYPE_MFFloat:
1152 JSaddGlobalECMANativeProperty(num, field);
1153 MFhasECMAtype = TRUE;
1154 break;
1155 default: {
1156 MFhasECMAtype = FALSE;
1157 }
1158 }
1159
1160 elements=0;
1161 IntPtr = NULL;
1162 FloatPtr = NULL;
1163 DoublePtr = NULL;
1164 SVPtr = NULL;
1165 VoidPtr = NULL;
1166 if (kind == PKW_initializeOnly || kind == PKW_inputOutput) {
1167 switch (type) {
1168 //case FIELDTYPE_SFImage:
1169 // VoidPtr = (struct X3D_Node **) (&(value.sfimage)); elements = 1;
1170 // break;
1171 case FIELDTYPE_SFNode:
1172 VoidPtr = (struct X3D_Node **) (&(value.sfnode)); elements = 1;
1173 break;
1174 case FIELDTYPE_MFColor:
1175 FloatPtr = (float *) value.mfcolor.p; elements = value.mfcolor.n;
1176 break;
1177 case FIELDTYPE_MFColorRGBA:
1178 FloatPtr = (float *) value.mfcolorrgba.p; elements = value.mfcolorrgba.n;
1179 break;
1180 case FIELDTYPE_MFVec2f:
1181 FloatPtr = (float *) value.mfvec2f.p; elements = value.mfvec2f.n;
1182 break;
1183 case FIELDTYPE_MFVec3f:
1184 FloatPtr = (float *) value.mfvec3f.p; elements = value.mfvec3f.n;
1185 break;
1186 case FIELDTYPE_MFRotation:
1187 FloatPtr = (float *) value.mfrotation.p; elements = value.mfrotation.n;
1188 break;
1189 case FIELDTYPE_SFVec2f:
1190 FloatPtr = (float *) value.sfvec2f.c; elements = 1;
1191 break;
1192 case FIELDTYPE_SFColor:
1193 FloatPtr = value.sfcolor.c; elements = 1;
1194 break;
1195 case FIELDTYPE_SFColorRGBA:
1196 FloatPtr = value.sfcolorrgba.c; elements = 1;
1197 break;
1198 case FIELDTYPE_SFRotation:
1199 FloatPtr = value.sfrotation.c; elements = 1;
1200 break;
1201 case FIELDTYPE_SFVec3f:
1202 FloatPtr = value.sfvec3f.c; elements =1;
1203 break;
1204 case FIELDTYPE_SFVec3d:
1205 DoublePtr = value.sfvec3d.c; elements =1;
1206 break;
1207 case FIELDTYPE_MFString:
1208 SVPtr = value.mfstring.p; elements = value.mfstring.n;
1209 break;
1210 case FIELDTYPE_MFTime:
1211 DoublePtr = value.mftime.p; elements = value.mftime.n;
1212 break;
1213 case FIELDTYPE_MFBool:
1214 IntPtr = value.mfbool.p; elements = value.mfbool.n;
1215 break;
1216 case FIELDTYPE_SFImage: //Q. should SFImage change here and if so to what, since July 2023 struct change { int whc[3], Multi_Int32 arr;}
1217 case FIELDTYPE_MFInt32:
1218 IntPtr = value.mfint32.p; elements = value.mfint32.n;
1219 break;
1220 case FIELDTYPE_MFNode:
1221 VoidPtr = (struct X3D_Node **)(value.mfnode.p); elements = value.mfnode.n;
1222 break;
1223 case FIELDTYPE_MFFloat:
1224 FloatPtr = value.mffloat.p; elements = value.mffloat.n;
1225 break;
1226 case FIELDTYPE_SFVec4f:
1227 FloatPtr = value.sfvec4f.c; elements = 1;
1228 break;
1229 case FIELDTYPE_SFVec4d:
1230 DoublePtr = value.sfvec4d.c; elements = 1;
1231 break;
1232
1233 default: {
1234 printf ("unhandled type, in InitScriptField %d\n",type);
1235 return;
1236 }
1237 }
1238
1239 } else {
1240 /* make up a default pointer */
1241 elements = 1;
1242 switch (type) {
1243 /* Void types */
1244 case FIELDTYPE_SFNode:
1245 case FIELDTYPE_MFNode:
1246 VoidPtr = (struct X3D_Node **) &defaultVoid;
1247 break;
1248
1249 /* Float types */
1250 case FIELDTYPE_MFColor:
1251 case FIELDTYPE_MFColorRGBA:
1252 case FIELDTYPE_MFVec2f:
1253 case FIELDTYPE_MFVec3f:
1254 case FIELDTYPE_MFRotation:
1255 case FIELDTYPE_SFVec2f:
1256 case FIELDTYPE_SFColor:
1257 case FIELDTYPE_SFColorRGBA:
1258 case FIELDTYPE_SFRotation:
1259 case FIELDTYPE_SFVec3f:
1260 case FIELDTYPE_SFVec4f:
1261 case FIELDTYPE_MFFloat:
1262 FloatPtr = defaultFloat;
1263 break;
1264
1265 /* Int types */
1266 case FIELDTYPE_MFBool:
1267 case FIELDTYPE_MFInt32:
1268 IntPtr = defaultInt;
1269 break;
1270
1271 /* String types */
1272 case FIELDTYPE_SFString:
1273 case FIELDTYPE_MFString:
1274 sptr[0] = newASCIIString("");
1275 SVPtr = sptr;
1276 break;
1277
1278 /* SFImage */
1279 case FIELDTYPE_SFImage:
1280 IntPtr = defaultInt;
1281 break;
1282
1283 /* Double types */
1284 case FIELDTYPE_SFVec2d:
1285 case FIELDTYPE_SFVec3d:
1286 case FIELDTYPE_SFVec4d:
1287 case FIELDTYPE_MFTime:
1288 case FIELDTYPE_SFTime:
1289 case FIELDTYPE_SFDouble:
1290 DoublePtr = defaultDouble;
1291 break;
1292
1293 default: {
1294 printf ("unhandled type, in InitScriptField part 2 %d\n",type);
1295 return;
1296 }
1297 }
1298
1299 }
1300
1301 rows = returnElementRowSize (type);
1302
1303 #ifdef JAVASCRIPTVERBOSE
1304 printf ("in fieldSet, we have ElementRowSize %d and individual elements %d\n",rows,elements);
1305 #endif
1306
1307 /* make this at least as large as required, then add some more on to the end... */
1308 /*
1309 Old Approach
1310 step1: compute using guestimate formulas
1311 step2: malloc
1312 step3: loop through strcat() and hope no overrun
1313 Problem: heap corruption from array overrun - the guestimate has been bad
1314 a few times in 2010 with MFVec2fs and MFStrings with 42 and 47 elements, strings of varying length
1315 example for MFVec2f
1316 'new MFVec2f(new SFVec2f(1234.678910,1234.678910),...)'
1317 each SF 2 numbers each 10 digits plus new type(,), 15 chars =35.
1318 3 x 15 = 45 (or (rows+1)x(elements*15)+100)
1319 old formula falls short:
1320 old formula: smallfield = MALLOC (rows*((elements*15) + 100));
1321 example 47 SFVec2fs
1322 actual bytes: 47 x 35 bytes = 1645 + 13 for the MF = 1658
1323 old formula 2 x ((47*15)+100) = 1610 //thats 48 bytes short and I bomb out
1324 better formula 3 x (47*15) + 100 = 2215
1325 New Approach (July 28, 2010)
1326 step1: compute using guestimate formulas
1327 step2: malloc
1328 step3: loop through and realloc before strcat() if short
1329 */
1330 {
1331 int dstlen, dstdim, tdim;
1332 tdim = 200;
1333 thisValue = MALLOC(char *, tdim+1);
1334 dstdim = (rows+1)*(elements*15) + 100; /* a guess */
1335 dstlen = 0;
1336 smallfield = MALLOC (char *, dstdim+1); //rows+1)*(elements*15) + 100);
1337 /* what is the equivalent SF for this MF?? */
1338 if (type != convertToSFType(type)) haveMulti = TRUE;
1339 else haveMulti = FALSE;
1340
1341 /* the sftype is the SF form of either the MF or SF */
1342 sftype = STRDUP((char *)FIELDTYPES[convertToSFType(type)]);
1343
1344 /* SFStrings are Strings */
1345 if (strncmp(sftype,"SFString",8)==0) strcpy (sftype,"String");
1346
1347
1348 /* start the string */
1349 smallfield[0] = '\0';
1350
1351 /* is this an MF variable, with SFs in it? */
1352 if (haveMulti) {
1353 smallfield = re_strcat(smallfield, "new ",&dstlen,&dstdim);
1354 smallfield = re_strcat(smallfield, (char *)FIELDTYPES[type],&dstlen,&dstdim);
1355 smallfield = re_strcat(smallfield, "(",&dstlen,&dstdim);
1356 }
1357
1358 /* loop through, and put values in */
1359 for (eleCount=0; eleCount<elements; eleCount++) {
1360 /* ECMA native types can just be passed in... */
1361 if (!MFhasECMAtype) {
1362 smallfield = re_strcat(smallfield, "new ",&dstlen,&dstdim);
1363 smallfield = re_strcat(smallfield, sftype,&dstlen,&dstdim);
1364 smallfield = re_strcat(smallfield, "(",&dstlen,&dstdim);
1365 }
1366
1367 /* go through the SF type; SFints will have 1; SFVec3f's will have 3, etc */
1368 for (rowCount=0; rowCount<rows; rowCount++ ) {
1369 if (IntPtr != NULL) {
1370 sprintf (thisValue,"%d",*IntPtr); IntPtr++;
1371 } else if (FloatPtr != NULL) {
1372 sprintf (thisValue,"%f",*FloatPtr); FloatPtr++;
1373 } else if (DoublePtr != NULL) {
1374 sprintf (thisValue,"%f",*DoublePtr); DoublePtr++;
1375 } else if (SVPtr != NULL) {
1376 sptr[0] = *SVPtr; SVPtr++;
1377 if((int)strlen(sptr[0]->strptr)+2 > tdim-1)
1378 {
1379 tdim = (int) strlen(sptr[0]->strptr) + 1 + 100;
1380 thisValue = (char *)REALLOC(thisValue,tdim);
1381 }
1382 sprintf (thisValue,"\"%s\"",sptr[0]->strptr);
1383 } else { /* must be a Void */
1384 /* printf ("sending in a VoidPtr, it is %p\n",VoidPtr[0]);
1385 if (VoidPtr[0] != NULL) {printf ("it is a %s type\n",stringNodeType(X3D_NODE(VoidPtr[0])->_nodeType));} */
1386 sprintf (thisValue,"\"%p\"", VoidPtr[0]); VoidPtr++;
1387 }
1388 smallfield = re_strcat(smallfield, thisValue,&dstlen,&dstdim);
1389 if (rowCount < (rows-1)) smallfield = re_strcat(smallfield,",",&dstlen,&dstdim);
1390 }
1391
1392 if (!MFhasECMAtype) smallfield = re_strcat(smallfield, ")",&dstlen,&dstdim);
1393 if (eleCount < (elements-1)) smallfield = re_strcat(smallfield,",",&dstlen,&dstdim);
1394
1395 }
1396
1397
1398 if (haveMulti) {
1399 smallfield = re_strcat(smallfield,")",&dstlen,&dstdim);
1400 }
1401 /* printf("dstlen=%d dstdim=%d\n",dstlen,dstdim); */
1402 FREE_IF_NZ (thisValue);
1403 }
1404 /* Warp factor 5, Dr Sulu... */
1405 #ifdef JAVASCRIPTVERBOSE
1406 printf ("JScript, for non-ECMA newname %s, sending :%s:\n",mynewname,smallfield);
1407 #endif
1408
1409 JSaddGlobalAssignProperty (num,mynewname,smallfield);
1410 }
1411 }
1412
1413 /* Fields can generate an event, so we allow the touched flag to remain set. eventOuts have just
1414 been initialized, and as such, should not send events, until after they really have been set.
1415 */
1416 if (kind == PKW_outputOnly) {
1417 int fptr;
1418 int touched;
1419
1420 UNUSED(touched); // compiler warning mitigation
1421
1422 /* get the number representing this type */
1423 fptr = JSparamIndex (field, FIELDTYPES[type],kind);
1424
1425 /* set up global variables so that we can reset the touched flag */
1426 touched = get_valueChanged_flag (fptr, num);
1427
1428 /* and, reset the touched flag, knowing that we have the variables set properly */
1429 resetScriptTouchedFlag(num, fptr);
1430 }
1431 ScriptControl = getScriptControlIndex(num);
1432 js_cleanup_script_context(num);
1433
1434 FREE_IF_NZ (smallfield);
1435 FREE_IF_NZ (sftype);
1436
1437}
1438
1439void InitScriptFieldB(int num, indexT kind, indexT type, const char* field, union anyVrml value) {
1440 //Dec 31 2017 this version of initscriptfield for SM treats fields more generically
1441
1442 struct CRscriptStruct *ScriptControl; //= getScriptControl();
1443 //char mynewname[256];
1444 #ifdef JAVASCRIPTVERBOSE
1445 printf ("calling InitScriptField from thread %u\n",pthread_self());
1446 printf ("\nInitScriptField, num %d, kind %s type %s field %s value %d\n", num,PROTOKEYWORDS[kind],FIELDTYPES[type],field,value);
1447 #endif
1448
1449 if ((kind != PKW_inputOnly) && (kind != PKW_outputOnly) && (kind != PKW_initializeOnly) && (kind != PKW_inputOutput)) {
1450 ConsoleMessage ("InitScriptField: invalid kind for script: %d\n",kind);
1451 return;
1452 }
1453
1454 ScriptControl = getScriptControlIndex(num);
1455
1456
1457 // fix eventIn vs field name conflicts. by renameing inputOutput and inputOnly eventIn functions to set_fieldname
1458 //if (kind == PKW_inputOnly ||
1459 //strcpy(mynewname,field);
1460 //if (kind == PKW_inputOnly ) {
1461 // sprintf (mynewname,"__eventIn_Value_%s",field);
1462 // //strcpy(mynewname,field);
1463 //} else
1464 if( kind == PKW_inputOutput) {
1465 JSContext *cx;
1466 JSObject *obj;
1467 jsval retval;
1468 cx = (JSContext*)ScriptControl->cx;
1469 obj = (JSObject*)ScriptControl->glob;
1470
1471 if (JS_GetProperty(cx,obj,field,&retval)){
1472 //if (JSVAL_IS_OBJECT(retval)){
1473 if(retval.isObject()){
1474 //I think functions are objects, doesn't seem to be a JSVAL_IS_FUNC
1475 char runstring[STRING_SIZE];
1476 // rename fieldname to set_fieldname
1477 sprintf(runstring,"_rename_function(this,'%s','set_%s');",field,field);
1478 //printf("%s\n",runstring);
1479 { // Scope A for our various stack objects (JSAutoRequest, RootedObject), so they all go
1480 // out of scope before we JS_DestroyContext.
1481 JSAutoRequest ar(cx); // In practice, you would want to exit this any
1482 // time you're spinning the event loop
1483 { // Scope B for JSAutoCompartment
1484 JSAutoCompartment ac(cx, obj);
1485 if(!JS_EvaluateScript(cx,obj, runstring, (int) strlen(runstring), FNAME_STUB, LINENO_STUB, &retval)){
1486 printf("sorry couldn't rename function: %s",runstring);
1487 }
1488 } //Scope B
1489 } //Scope A
1490 }
1491 }
1492 // and if so rename it to set_
1493 }
1494
1495 //unconditionally add the field no matter its type
1496 //contains getter and setter
1497 JSaddGlobalECMANativeProperty(num, field);
1498}
1499
1500
1501
1502static int JSaddGlobalECMANativeProperty(int num, const char *name) {
1503 JSContext *cx;
1504 JSObject *global;
1505 jsval rval = INT_TO_JSVAL(0);
1506 struct CRscriptStruct *ScriptControl; // = getScriptControl();
1507
1508 ScriptControl = getScriptControlIndex(num);
1509 /* get context and global object for this script */
1510 cx = (JSContext*)ScriptControl->cx;
1511 global = (JSObject*)ScriptControl->glob;
1512
1513
1514/* Note, for JS-185+, JSPROP_PERMANENT makes properties non-configurable, which can cause runtime
1515 * errors from the JS engine when said property gets redefined to a function by the script. The
1516 * example file tests/Javascript_tests/MFFloat.wrl had this issue. */
1517
1518 { // Scope A for our various stack objects (JSAutoRequest, RootedObject), so they all go
1519 // out of scope before we JS_DestroyContext.
1520
1521 JSAutoRequest ar(cx); // In practice, you would want to exit this any
1522 // time you're spinning the event loop
1523 { // Scope B for JSAutoCompartment
1524 JSAutoCompartment ac(cx, global);
1525 bool ok = JS_DefineProperty(cx,global, name, rval, getECMANative, setECMANative,0);
1526 if (!ok){
1527 printf("JS_DefineProperty failed for \"%s\" in addGlobalECMANativeProperty.\n", name);
1528 return JS_FALSE;
1529 }
1530 } // Scope B
1531 } //Scope A
1532 return JS_TRUE;
1533}
1534
1535static int JSaddGlobalAssignProperty(int num, const char *name, const char *str) {
1536 jsval _rval = INT_TO_JSVAL(0);
1537 JSContext *cx;
1538 JSObject *global;
1539 struct CRscriptStruct *ScriptControl;
1540
1541 ScriptControl = getScriptControlIndex(num);
1542
1543 /* get context and global object for this script */
1544 cx = (JSContext*)ScriptControl->cx;
1545 global = (JSObject*)ScriptControl->glob;
1546
1547 { // Scope A for our various stack objects (JSAutoRequest, RootedObject), so they all go
1548 // out of scope before we JS_DestroyContext.
1549 JSAutoRequest ar(cx); // In practice, you would want to exit this any
1550 // time you're spinning the event loop
1551 { // Scope B for JSAutoCompartment
1552 JSAutoCompartment ac(cx,global);
1553 if (!JS_EvaluateScript(cx,global, str, (int) strlen(str), FNAME_STUB, LINENO_STUB, &_rval)) {
1554 ConsoleMessage ("JSaddGlobalAssignProperty - JS_EvaluateScript failed for %s", str);
1555 return JS_FALSE;
1556 }
1557 if (!JS_DefineProperty(cx,global, name, _rval, getAssignProperty, setAssignProperty, 0 | JSPROP_PERMANENT)) {
1558 printf("JS_DefineProperty failed for \"%s\" in addGlobalAssignProperty.\n", name);
1559 return JS_FALSE;
1560 }
1561 } //Scope B
1562 } //Scope A
1563 return JS_TRUE;
1564}
1565
1566/* defines for getting touched flags and exact Javascript pointers */
1567
1568/****************************** ECMA types ******************************************/
1569/* where we have a Native structure to go along with it */
1570#define GETJSPTR_TYPE_A(thistype) \
1571 case FIELDTYPE_##thistype: { \
1572 thistype##Native *ptr; \
1573 /* printf ("getting private data in GETJSPTR for %p \n",JSglobal_return_val); */ \
1574 if ((ptr = (thistype##Native *)JS_GetPrivateFw(cx, JSVAL_TO_OBJECT(*(jsval *)(tg->JScript.JSglobal_return_val)))) == NULL) { \
1575 printf( "JS_GetPrivate failed in get_valueChanged_flag\n"); \
1576 return JS_FALSE; \
1577 } \
1578 /* if (ptr->valueChanged > 0) printf ("private is %d valueChanged %d\n",ptr,ptr->valueChanged); */ \
1579 tg->CRoutes.JSSFpointer = (void *)ptr; /* save this for quick extraction of values */ \
1580 touched = ptr->valueChanged; \
1581 break; \
1582 }
1583
1584#define RESET_TOUCHED_TYPE_A(thistype) \
1585 case FIELDTYPE_##thistype: { \
1586 ((thistype##Native *)tg->CRoutes.JSSFpointer)->valueChanged = 0; \
1587 break; \
1588 }
1589
1590#define GETJSPTR_TYPE_MF_A(thisMFtype,thisSFtype) \
1591 case FIELDTYPE_##thisMFtype: { \
1592 thisSFtype##Native *ptr; \
1593 jsval mainElement; \
1594 int len; \
1595 int i; \
1596 if (!JS_GetProperty(cx, JSVAL_TO_OBJECT(*(jsval *)(tg->JScript.JSglobal_return_val)), "length", &mainElement)) { \
1597 printf ("JS_GetProperty failed for \"length\" in get_valueChanged_flag\n"); \
1598 return FALSE; \
1599 } \
1600 len = JSVAL_TO_INT(mainElement); \
1601 /* go through each element of the main array. */ \
1602 for (i = 0; i < len; i++) { \
1603 if (!JS_GetElement(cx, JSVAL_TO_OBJECT(*(jsval*)(tg->JScript.JSglobal_return_val)), i, &mainElement)) { \
1604 printf ("JS_GetElement failed for %d in get_valueChanged_flag\n",i); \
1605 return FALSE; \
1606 } \
1607 if ((ptr = (thisSFtype##Native *)JS_GetPrivateFw(cx, JSVAL_TO_OBJECT(mainElement))) == NULL) { \
1608 printf( "JS_GetPrivate failed for obj in setField_javascriptEventOut.\n"); \
1609 return FALSE; \
1610 } \
1611 if (ptr->valueChanged > 0) touched = TRUE; /* did this element change? */ \
1612 /* printf ("touched flag for element %d is %d\n",i,ptr->touched); */ \
1613 } \
1614 break; \
1615 }
1616
1617#define RESET_TOUCHED_TYPE_MF_A(thisMFtype,thisSFtype) \
1618 case FIELDTYPE_##thisMFtype: { \
1619 thisSFtype##Native *ptr; \
1620 jsval mainElement; \
1621 int len; \
1622 int i; \
1623 JSContext *cx; \
1624 cx = (JSContext*)scriptcontrol->cx; \
1625 if (!JS_GetProperty(cx, JSVAL_TO_OBJECT(*(jsval*)(tg->JScript.JSglobal_return_val)), "length", &mainElement)) { \
1626 printf ("JS_GetProperty failed for \"length\" in get_valueChanged_flag\n"); \
1627 break; \
1628 } \
1629 len = JSVAL_TO_INT(mainElement); \
1630 /* go through each element of the main array. */ \
1631 for (i = 0; i < len; i++) { \
1632 if (!JS_GetElement(cx, JSVAL_TO_OBJECT(*(jsval*)(tg->JScript.JSglobal_return_val)), i, &mainElement)) { \
1633 printf ("JS_GetElement failed for %d in get_valueChanged_flag\n",i); \
1634 break; \
1635 } \
1636 if ((ptr = (thisSFtype##Native *)JS_GetPrivateFw(cx, JSVAL_TO_OBJECT(mainElement))) == NULL) { \
1637 printf( "JS_GetPrivate failed for obj in setField_javascriptEventOut.\n"); \
1638 break; \
1639 } \
1640 ptr->valueChanged = 0; \
1641 } \
1642 break; \
1643 }
1644
1645/****************************** ECMA types ******************************************/
1646
1647#define GET_ECMA_TOUCHED(thistype) \
1648 case FIELDTYPE_SF##thistype: {\
1649 touched = findNameInECMATable( (JSContext*)scriptcontrol->cx,fullname);\
1650 break;\
1651 }
1652
1653#define GET_ECMA_MF_TOUCHED(thistype) \
1654 case FIELDTYPE_MF##thistype: {\
1655 jsval mainElement; \
1656 /* printf ("GET_ECMA_MF_TOUCHED called on %d\n",JSglobal_return_val); */ \
1657 if (!JS_GetProperty(cx, JSVAL_TO_OBJECT(*(jsval*)(tg->JScript.JSglobal_return_val)), "MF_ECMA_has_changed", &mainElement)) { \
1658 printf ("JS_GetProperty failed for \"MF_ECMA_HAS_changed\" in get_valueChanged_flag\n"); \
1659 } /* else printf ("GET_ECMA_MF_TOUCHED MF_ECMA_has_changed is %d for %d %d\n",JSVAL_TO_INT(mainElement),cx,JSglobal_return_val); */ \
1660 touched = JSVAL_TO_INT(mainElement);\
1661 break; \
1662 }
1663
1664#define RESET_ECMA_MF_TOUCHED(thistype) \
1665 case FIELDTYPE_##thistype: {\
1666 jsval myv = INT_TO_JSVAL(0); \
1667 /* printf ("RESET_ECMA_MF_TOUCHED called on %d ",JSglobal_return_val); */ \
1668 if (!JS_SetProperty(cx, JSVAL_TO_OBJECT(*(jsval*)(tg->JScript.JSglobal_return_val)), "MF_ECMA_has_changed", &myv)) { \
1669 printf( "JS_SetProperty failed for \"MF_ECMA_has_changed\" in RESET_ECMA_MF_TOUCHED.\n"); \
1670 }\
1671 /* if (!JS_GetProperty( p->ScriptControl[actualscript].cx, JSVAL_TO_OBJECT(JSglobal_return_val), "MF_ECMA_has_changed", &mainElement)) { \
1672 printf ("JS_GetProperty failed for \"MF_ECMA_HAS_changed\" in get_valueChanged_flag\n"); \
1673 } \
1674 printf ("and MF_ECMA_has_changed is %d\n",JSVAL_TO_INT(mainElement)); */\
1675 break; \
1676 }
1677
1678#define RESET_TOUCHED_TYPE_ECMA(thistype) \
1679 case FIELDTYPE_##thistype: { \
1680 resetNameInECMATable( cx,JSparamnames[fptr].name); \
1681 break; \
1682 }
1683
1684#ifdef OLDCODE
1685OLDCODE /* in case Bool was defined above, restore the value */
1686OLDCODE #define Bool savedBool
1687#endif //OLDCODE
1688
1689
1690
1691
1692/********************************************************************************/
1693/* */
1694/* get_valueChanged_flag - see if this variable (can be a sub-field; see tests */
1695/* 8.wrl for the DEF PI PositionInterpolator). return true if variable is */
1696/* touched, and pointer to touched value is in global variable */
1697/* JSglobal_return_val, AND possibly: */
1698/* void *JSSFpointer for SF non-ECMA nodes. */
1699/* */
1700/* the way touched, and, the actual values work is as follows: */
1701/* */
1702/* keep track of the name in a table, and set valueChanged flag. */
1703/* look around the function setECMANative to see how this is done. */
1704/* FIELDTYPE_SFInt32 */
1705/* FIELDTYPE_SFBool */
1706/* FIELDTYPE_SFFloat */
1707/* FIELDTYPE_SFTime */
1708/* FIELDTYPE_SFDouble */
1709/* FIELDTYPE_SFString */
1710/* */
1711/* check the "touched" flag for non-zero in the private area: */
1712/* FIELDTYPE_SFRotation */
1713/* FIELDTYPE_SFNode */
1714/* FIELDTYPE_SFVec2f */
1715/* FIELDTYPE_SFVec3f */
1716/* FIELDTYPE_SFImage */
1717/* FIELDTYPE_SFColor */
1718/* FIELDTYPE_SFColorRGBA */
1719/* */
1720/* go through all elements, and find if at least one SF has been touched: */
1721/* FIELDTYPE_MFRotation */
1722/* FIELDTYPE_MFNode */
1723/* FIELDTYPE_MFVec2f */
1724/* FIELDTYPE_MFVec3f */
1725/* FIELDTYPE_MFColor */
1726/* FIELDTYPE_MFColorRGBA */
1727
1728
1729/* has a flag called "MF_ECMA_has_changed" that is used here */
1730/* FIELDTYPE_MFFloat */
1731/* FIELDTYPE_MFBool */
1732/* FIELDTYPE_MFInt32 */
1733/* FIELDTYPE_MFTime */
1734/* FIELDTYPE_MFString */
1735/* */
1736/****************************************************************************/
1737extern "C" {
1738int sm1_get_valueChanged_flag (int fptr, int actualscript) {
1739
1740
1741 struct CRscriptStruct *scriptcontrol;
1742 JSContext *cx;
1743 JSObject *interpobj;
1744 char *fullname;
1745 int touched;
1746 //ppJScript p;
1747 ttglobal tg = gglobal();
1748 struct CRjsnameStruct *JSparamnames = getJSparamnames();
1749 //p = (ppJScript)tg->JScript.prv;
1750
1751 touched = FALSE;
1752 scriptcontrol = getScriptControlIndex(actualscript);
1753 interpobj = (JSObject*)scriptcontrol->glob;
1754 cx = (JSContext*)scriptcontrol->cx;
1755 fullname = JSparamnames[fptr].name;
1756
1757 { // Scope A for our various stack objects (JSAutoRequest, RootedObject), so they all go
1758 // out of scope before we JS_DestroyContext.
1759 JSAutoRequest ar(cx); // In practice, you would want to exit this any
1760 // time you're spinning the event loop
1761 { // Scope B for JSAutoCompartment
1762 JSAutoCompartment ac(cx, interpobj);
1763
1764 if (!JS_GetProperty(cx, interpobj ,fullname,(jsval*)tg->JScript.JSglobal_return_val)) {
1765 printf ("cant get property for %s\n",fullname);
1766 return FALSE;
1767 } else {
1768
1769 switch (JSparamnames[fptr].type) {
1770 GETJSPTR_TYPE_A(SFRotation)
1771 GETJSPTR_TYPE_A(SFNode)
1772 GETJSPTR_TYPE_A(SFVec2f)
1773 /* GETJSPTR_TYPE_A(SFVec2d) */
1774 GETJSPTR_TYPE_A(SFVec3f)
1775 GETJSPTR_TYPE_A(SFVec3d)
1776 GETJSPTR_TYPE_A(SFVec4f)
1777 GETJSPTR_TYPE_A(SFVec4d)
1778 GETJSPTR_TYPE_A(SFImage)
1779 GETJSPTR_TYPE_A(SFColor)
1780 GETJSPTR_TYPE_A(SFColorRGBA)
1781
1782 GETJSPTR_TYPE_MF_A(MFRotation,SFRotation)
1783 GETJSPTR_TYPE_MF_A(MFNode,SFNode)
1784 GETJSPTR_TYPE_MF_A(MFVec2f,SFVec2f)
1785 GETJSPTR_TYPE_MF_A(MFVec3f,SFVec3f)
1786 GETJSPTR_TYPE_MF_A(MFVec4f,SFVec4f)
1787 GETJSPTR_TYPE_MF_A(MFVec4d,SFVec4d)
1788 /* GETJSPTR_TYPE_MF_A(MFImage,SFImage) */
1789 GETJSPTR_TYPE_MF_A(MFColor,SFColor)
1790 GETJSPTR_TYPE_MF_A(MFColorRGBA,SFColorRGBA)
1791
1792 GET_ECMA_MF_TOUCHED(Int32)
1793 GET_ECMA_MF_TOUCHED(Bool)
1794 GET_ECMA_MF_TOUCHED(Time)
1795 GET_ECMA_MF_TOUCHED(Double)
1796 GET_ECMA_MF_TOUCHED(Float)
1797 GET_ECMA_MF_TOUCHED(String)
1798
1799 GET_ECMA_TOUCHED(Int32)
1800 GET_ECMA_TOUCHED(Bool)
1801 GET_ECMA_TOUCHED(Float)
1802 GET_ECMA_TOUCHED(Time)
1803 GET_ECMA_TOUCHED(Double)
1804 GET_ECMA_TOUCHED(String)
1805
1806 default: {printf ("not handled yet in get_valueChanged_flag %s\n",FIELDTYPES[JSparamnames[fptr].type]);
1807 }
1808 }
1809 }
1810
1811 } //Scope B
1812 } //Scope A
1813 return touched;
1814
1815}
1816
1817
1818/* this script value has been looked at, set the touched flag in it to FALSE. */
1819void sm1_resetScriptTouchedFlag(int actualscript, int fptr) {
1820
1821 struct CRscriptStruct *scriptcontrol;
1822 ttglobal tg = gglobal();
1823 struct CRjsnameStruct *JSparamnames = getJSparamnames();
1824 JSContext *cx;
1825 JSObject *global;
1826 scriptcontrol = getScriptControlIndex(actualscript);
1827 cx = (JSContext*)scriptcontrol->cx;
1828 global = (JSObject*)scriptcontrol->glob;
1829 { // Scope A for our various stack objects (JSAutoRequest, RootedObject), so they all go
1830 // out of scope before we JS_DestroyContext.
1831 JSAutoRequest ar(cx); // In practice, you would want to exit this any
1832 // time you're spinning the event loop
1833 { // Scope B for JSAutoCompartment
1834 JSAutoCompartment ac(cx, global);
1835
1836 switch (JSparamnames[fptr].type) {
1837 RESET_TOUCHED_TYPE_A(SFRotation)
1838 RESET_TOUCHED_TYPE_A(SFNode)
1839 RESET_TOUCHED_TYPE_A(SFVec2f)
1840 RESET_TOUCHED_TYPE_A(SFVec3f)
1841 RESET_TOUCHED_TYPE_A(SFVec4f)
1842 /* RESET_TOUCHED_TYPE_A(SFVec2d) */
1843 RESET_TOUCHED_TYPE_A(SFVec3d)
1844 RESET_TOUCHED_TYPE_A(SFVec4d)
1845 RESET_TOUCHED_TYPE_A(SFImage)
1846 RESET_TOUCHED_TYPE_A(SFColor)
1847 RESET_TOUCHED_TYPE_A(SFColorRGBA)
1848 RESET_TOUCHED_TYPE_MF_A(MFRotation,SFRotation)
1849 RESET_TOUCHED_TYPE_MF_A(MFNode,SFNode)
1850 RESET_TOUCHED_TYPE_MF_A(MFVec2f,SFVec2f)
1851 RESET_TOUCHED_TYPE_MF_A(MFVec3f,SFVec3f)
1852 RESET_TOUCHED_TYPE_MF_A(MFVec4f,SFVec4f)
1853 RESET_TOUCHED_TYPE_MF_A(MFVec4d,SFVec4d)
1854 /* RESET_TOUCHED_TYPE_MF_A(MFImage,SFImage) */
1855 RESET_TOUCHED_TYPE_MF_A(MFColor,SFColor)
1856 RESET_TOUCHED_TYPE_MF_A(MFColorRGBA,SFColorRGBA)
1857
1858 RESET_TOUCHED_TYPE_ECMA (SFInt32)
1859 RESET_TOUCHED_TYPE_ECMA (SFBool)
1860 RESET_TOUCHED_TYPE_ECMA (SFFloat)
1861 RESET_TOUCHED_TYPE_ECMA (SFTime)
1862 RESET_TOUCHED_TYPE_ECMA (SFDouble)
1863 RESET_TOUCHED_TYPE_ECMA (SFString)
1864 RESET_ECMA_MF_TOUCHED(MFInt32)
1865 RESET_ECMA_MF_TOUCHED(MFBool)
1866 RESET_ECMA_MF_TOUCHED(MFFloat)
1867 RESET_ECMA_MF_TOUCHED(MFTime)
1868 RESET_ECMA_MF_TOUCHED(MFString)
1869 default: {printf ("can not reset touched_flag for %s\n",stringFieldtypeType(JSparamnames[fptr].type));}
1870 }
1871 } //Scope B
1872 } //Scope A
1873}
1874
1875int sm2_get_valueChanged_flag (int fptr, int actualscript){
1876 char *fullname;
1877 union anyVrml* value;
1878 int type, kind, ifield, found;
1879 struct X3D_Node *node;
1880 struct Shader_Script *script;
1881 struct ScriptFieldDecl *field;
1882 struct CRscriptStruct *scriptcontrol; //, *ScriptControlArr = getScriptControl();
1883 struct CRjsnameStruct *JSparamnames = getJSparamnames();
1884
1885 scriptcontrol = getScriptControlIndex(actualscript); //&ScriptControlArr[actualscript];
1886 script = scriptcontrol->script;
1887 node = script->ShaderScriptNode;
1888 fullname = JSparamnames[fptr].name;
1889 found = getFieldFromNodeAndName(node,fullname,&type,&kind,&ifield,&value);
1890 if(found){
1891 field = Shader_Script_getScriptField(script, ifield);
1892 gglobal()->JScript.JSglobal_return_val = (void *)&field->value;
1893 return field->valueChanged;
1894 }
1895 gglobal()->JScript.JSglobal_return_val = NULL;
1896 return 0;
1897}
1898void sm2_resetScriptTouchedFlag(int actualscript, int fptr){
1899 char *fullname;
1900 union anyVrml* value;
1901 int type, kind, ifield, found;
1902 struct X3D_Node *node;
1903 struct Shader_Script *script;
1904 struct ScriptFieldDecl *field;
1905 struct CRscriptStruct *scriptcontrol; // *ScriptControlArr = getScriptControl();
1906 struct CRjsnameStruct *JSparamnames = getJSparamnames();
1907
1908 scriptcontrol = getScriptControlIndex(actualscript); //&ScriptControlArr[actualscript];
1909 script = scriptcontrol->script;
1910 node = script->ShaderScriptNode;
1911 fullname = JSparamnames[fptr].name;
1912 found = getFieldFromNodeAndName(node,fullname,&type,&kind,&ifield,&value);
1913 if(found){
1914 field = Shader_Script_getScriptField(script, ifield);
1915 field->valueChanged = 0;
1916 }
1917 //printf("in get_valueChanged_flag\n");
1918 return;
1919}
1920int sm_get_valueChanged_flag (int fptr, int actualscript){
1921 if(SM_method() == 2)
1922 return sm2_get_valueChanged_flag(fptr,actualscript);
1923 else
1924 return sm1_get_valueChanged_flag(fptr,actualscript);
1925}
1926void sm_resetScriptTouchedFlag(int actualscript, int fptr){
1927 if(SM_method() == 2)
1928 sm2_resetScriptTouchedFlag(actualscript,fptr);
1929 else
1930 sm1_resetScriptTouchedFlag(actualscript,fptr);
1931}
1932
1933int jsActualrunScript(int num, char *script);
1934void sm_JSInitializeScriptAndFields (int num) {
1935 //jsval rval;
1936 //ppCRoutes p = (ppCRoutes)gglobal()->CRoutes.prv;
1937 struct CRscriptStruct *ScriptControl; // = getScriptControl();
1938
1939 /* printf ("JSInitializeScriptAndFields script %d, thread %u\n",num,pthread_self()); */
1940 /* run through paramList, and run the script */
1941 /* printf ("JSInitializeScriptAndFields, running through params and main script\n"); */
1942 //if (num >= p->JSMaxScript) {
1943 // ConsoleMessage ("JSInitializeScriptAndFields: warning, script %d initialization out of order",num);
1944 // return;
1945 //}
1946 /* run through fields in order of entry in the X3D file */
1947
1948 int i,nfields,kind,itype;
1949 const char *fieldname;
1950 char longfieldname[256];
1951 struct Shader_Script *script;
1952 struct ScriptFieldDecl *field;
1953
1954 ScriptControl = getScriptControlIndex(num);
1955
1956 //add user code -including eventIn functions- first
1957 if(1) if (!jsActualrunScript(num, ScriptControl->scriptText)) {
1958 ConsoleMessage ("JSInitializeScriptAndFields, script failure\n");
1959 ScriptControl->scriptOK = FALSE;
1960 ScriptControl->_initialized = TRUE;
1961 return;
1962 }
1963
1964 // old way: when adding inputOutput fieldnname, check first if there's a user
1965 // eventin function with the same name, and if so rename it to set_fieldname
1966 // new way dec 2017: rename inputOutput functions with a set_prefix
1967 // may 2018: keep inputOnly function at its normal name and
1968 // prefix inputOnly fieldname with __eventIn_Value_
1969 // (inputOutput function is still dec 2017 renamed to set_, and inputOutput field has normal nae)
1970 script = ScriptControl->script;
1971 //printf("adding fields from script %x\n",script);
1972 nfields = Shader_Script_getScriptFieldCount(script);
1973 for(i=0;i<nfields;i++){
1974 field = Shader_Script_getScriptField(script,i);
1975 fieldname = ScriptFieldDecl_getName(field);
1976 kind = ScriptFieldDecl_getMode(field);
1977 itype = ScriptFieldDecl_getType(field);
1978 longfieldname[0] = 0;
1979 if(kind == PKW_inputOnly)
1980 strcat(longfieldname,"__eventIn_Value_");
1981 strcat(longfieldname,fieldname);
1982 if(SM_method() == 2)
1983 InitScriptFieldB(num, kind, itype, longfieldname, field->value);
1984 else
1985 InitScriptField(num, kind, itype, longfieldname, field->value);
1986 }
1987
1988
1989 if(0) if (!jsActualrunScript(num, ScriptControl->scriptText)) {
1990 ConsoleMessage ("JSInitializeScriptAndFields, script failure\n");
1991 ScriptControl->scriptOK = FALSE;
1992 ScriptControl->_initialized = TRUE;
1993 return;
1994 }
1995
1996 //FREE_IF_NZ(ScriptControl->scriptText);
1997 ScriptControl->_initialized = TRUE;
1998 ScriptControl->scriptOK = TRUE;
1999
2000}
2001
2002
2003
2004/* save this field from the parser; initialize it when the fwl_RenderSceneUpdateScene wants to initialize it */
2005void sm_SaveScriptField (int num, indexT kind, indexT type, const char* field, union anyVrml value) {
2006
2007}
2008
2009} //extern "C"
2010
2011
2012/****************************************************************/
2013/* a Jscript is returning a Multi-number type; copy this from */
2014/* the Jscript return string to the data structure within the */
2015/* freewrl C side of things. */
2016/* */
2017/* note - this cheats in that the code assumes that it is */
2018/* a series of Multi_Vec3f's while in reality the structure */
2019/* of the multi structures is the same - so we "fudge" things */
2020/* to make this multi-purpose. */
2021/****************************************************************/
2022void getJSMultiNumType (JSContext *cx, struct Multi_Vec3f *tn, int eletype) {
2023 float *fl;
2024 long *il;
2025 double *dl;
2026 struct X3D_Node * *nl;
2027
2028 double dtmp;
2029 jsval mainElement;
2030 int len;
2031 int i;
2032 char *strp;
2033
2034 char *strpp; /* we need this to reliably free the results of JS_EncodeString() */
2035
2036 int elesize;
2037 SFVec2fNative *sfvec2f;
2038 SFVec3fNative *sfvec3f;
2039 SFRotationNative *sfrotation;
2040 struct Uni_String * *ms;
2041 jsval *myJSVal;
2042 ttglobal tg = gglobal();
2043
2044 /* get size of each element, used for MALLOCing memory - eg, this will
2045 be sizeof(float) * 3 for a SFColor */
2046 elesize = returnElementLength(eletype) * returnElementRowSize(eletype);
2047
2048 /* rough check of return value */
2049 /* where did this come from? Was it from a script execution, or from an assignment from within a script?? */
2050 #ifdef SETFIELDVERBOSE
2051 printf ("getJSMultiNumType, JSCreate_global_return_val %u, JSglobal_return_val %u\n",
2052 (unsigned int) JSVAL_TO_INT(*(jsval *)tg->jsVRMLBrowser.JSCreate_global_return_val),
2053 (unsigned int) JSVAL_TO_INT(*(jsval *)tg->JScript.JSglobal_return_val));
2054 #endif
2055
2056 if (JSVAL_TO_INT(*(jsval*)(tg->jsVRMLBrowser.JSCreate_global_return_val)) != 0) {
2057 myJSVal = (jsval *)tg->jsVRMLBrowser.JSCreate_global_return_val;
2058 *(jsval *)(tg->jsVRMLBrowser.JSCreate_global_return_val) = INT_TO_JSVAL(0);
2059
2060 #ifdef SETFIELDVERBOSE
2061 printf ("getJSMultiNumType: using JSCreate_global_return_val\n");
2062 #endif
2063 } else {
2064 #ifdef SETFIELDVERBOSE
2065 printf ("getJSMultiNumType: using JSglobal_return_val\n");
2066 #endif
2067
2068 myJSVal = (jsval *)tg->JScript.JSglobal_return_val;
2069 }
2070
2072 if(!(*myJSVal).isObject()){
2073 printf ("getJSMultiNumType - did not get an object\n");
2074 return;
2075 }
2076
2077 #ifdef SETFIELDVERBOSE
2078 printf ("getJSMultiNumType, tn %p dest has %s size %d\n",tn,stringFieldtypeType(eletype), elesize);
2079
2080 printf("getJSMulitNumType, node type of myJSVal is :");
2081 printJSNodeType (cx,myJSVal);
2082 #endif
2083
2084 if (!JS_GetProperty(cx, JSVAL_TO_OBJECT(*myJSVal), MF_LENGTH_FIELD, &mainElement)) {
2085 printf ("JS_GetProperty failed for \"%s\" in getJSMultiNumType\n", MF_LENGTH_FIELD);
2086 return;
2087 }
2088 len = JSVAL_TO_INT(mainElement);
2089 #ifdef SETFIELDVERBOSE
2090 printf ("getmuiltie length of grv is %d old len is %d\n",len,tn->n);
2091 #endif
2092
2093 /* do we have to realloc memory? */
2094 if (len != tn->n) {
2095
2096 tn->n = 0;
2097 /* yep... */
2098 /* printf ("old pointer %d\n",tn->p); */
2099 FREE_IF_NZ (tn->p);
2100 tn->p = MALLOC (struct SFVec3f *, (unsigned)(elesize*len));
2101
2102 #ifdef SETFIELDVERBOSE
2103 printf ("MALLOCing memory for elesize %d len %d new pointer now is %p\n",elesize,len,tn->p);
2104 #endif
2105
2106 /* if this is an MFString, we should set each element to a null string */
2107 if (eletype == FIELDTYPE_SFString) {
2108 #ifdef SETFIELDVERBOSE
2109 printf ("getJSMultiNumType, this is a MFString, so making tiny strings for now\n");
2110 #endif
2111
2112 ms = (struct Uni_String * *) tn->p;
2113 for (i=0; i<len; i++) {
2114 *ms = newASCIIString ("(getJSMultiNumType null)");
2115 ms ++;
2116 }
2117 }
2118 }
2119
2120 /* set these three up, but we only use one of them */
2121 fl = (float *) tn->p;
2122 il = (long *) tn->p;
2123 dl = (double *) tn->p;
2124 nl = (struct X3D_Node * *) tn->p;
2125 ms = (struct Uni_String * *) tn->p;
2126
2127 /* go through each element of the main array. */
2128 for (i = 0; i < len; i++) {
2129 if (!JS_GetElement(cx, JSVAL_TO_OBJECT(*myJSVal), i, &mainElement)) {
2130 printf ("WARNING: JS_GetElement failed for %d in getJSMultiNumType\n",i);
2131 switch (eletype) {
2132 case FIELDTYPE_SFNode:
2133 *nl = 0; nl++; break;
2134 case FIELDTYPE_SFInt32:
2135 *il=0; il++; break;
2136 case FIELDTYPE_SFDouble:
2137 case FIELDTYPE_SFTime:
2138 *dl=0.0; dl++; break;
2139 case FIELDTYPE_SFFloat:
2140 *fl = (float) 0.0; fl++; break;
2141 case FIELDTYPE_SFVec2f:
2142 *fl = (float) 0.0; fl++; *fl = (float) 0.0; fl++; break;
2143 case FIELDTYPE_SFVec3f:
2144 case FIELDTYPE_SFColor:
2145 *fl = (float) 0.0; fl++; *fl = (float) 0.0; fl++; *fl = (float) 0.0; fl++; break;
2146 case FIELDTYPE_SFRotation:
2147 *fl = (float) 0.0; fl++; *fl = (float) 0.0; fl++; *fl = (float) 0.0; fl++; *fl = (float) 0.0; fl++; break;
2148 case FIELDTYPE_SFString:
2149 verify_Uni_String (*ms,"(empty value)"); ms++; break;
2150
2151 default : {printf ("getJSMultiNumType unhandled eletype: %d\n",
2152 eletype);
2153 return;
2154 }
2155 }
2156 } else {
2157 #ifdef SETFIELDVERBOSE
2158 JSString *_tmpStr;
2159
2160 _tmpStr = JS_ValueToString(cx, mainElement);
2161#if JS_VERSION < 185
2162 strp = JS_GetStringBytes(_tmpStr);
2163#else
2164 strp = strpp = JS_EncodeString(cx,_tmpStr);
2165#endif
2166 printf ("sub element %d is \"%s\" \n",i,strp);
2167#if JS_VERSION >= 185
2168 JS_free(cx,strpp);
2169#endif
2170
2171 if (JSVAL_IS_OBJECT(mainElement)) printf ("sub element %d is an OBJECT\n",i);
2172 if (JSVAL_IS_PRIMITIVE(mainElement)) printf ("sub element %d is an PRIMITIVE\n",i);
2173 #endif
2174
2175 /* code is pretty much same as SF* values in setField_javascriptEventOut */
2176 switch (eletype) {
2177 case FIELDTYPE_SFNode: {
2178
2179 if (JS_InstanceOf (cx, JSVAL_TO_OBJECT(mainElement), &SFNodeClass, NULL)) {
2180 SFNodeNative *_vec;
2181
2182 /* printf ("yep, this is an SFNode class\n"); */
2183 if ((_vec = (SFNodeNative *)JS_GetPrivateFw(cx, JSVAL_TO_OBJECT(mainElement))) == NULL) {
2184 printf ("error getting native\n");
2185 *nl = NULL;
2186 } else {
2187 /* printf ("have native, handle %p\n",_vec->handle);
2188 printf ("and it is a :%s:\n",stringNodeType(_vec->handle->_nodeType)); */
2189 *nl = _vec->handle;
2190 }
2191 } else {
2192 printf ("hmm - not an SFNode class\n");
2193 *nl = NULL;
2194 }
2195
2196 nl++;
2197 break;
2198 }
2199 case FIELDTYPE_SFInt32: {
2200 //if (!JS::ToInt32(cx, mainElement ,il)) {
2201 // printf ("error\n");
2202 // *il=0;
2203 //}
2204 *il = 0;
2205 if(mainElement.isInt32()) *il = mainElement.toInt32();
2206 il++;
2207 break;
2208 }
2209 case FIELDTYPE_SFDouble:
2210 case FIELDTYPE_SFTime: {
2211 if (!JS_ValueToNumber(cx, mainElement ,dl)) *dl=0.0;
2212 dl++;
2213 break;
2214 }
2215 case FIELDTYPE_SFFloat: {
2216 if (!JS_ValueToNumber(cx, mainElement, &dtmp)) dtmp=0.0;
2217 /* convert double precision to single, for X3D */
2218 *fl = (float) dtmp;
2219 fl++;
2220 break;
2221 }
2222 case FIELDTYPE_SFVec2f: {
2223 //if (JSVAL_IS_OBJECT(mainElement)) {
2224 if(mainElement.isObject()){
2225 if ((sfvec2f = (SFVec2fNative *)JS_GetPrivateFw(cx, JSVAL_TO_OBJECT(mainElement))) == NULL) {
2226 printf( "JS_GetPrivate failed for obj in setField_javascriptEventOut.\n");
2227 return;
2228 }
2229 memcpy ((void *)fl, (void *)&(sfvec2f->v),2*sizeof(float));
2230 fl += 2;
2231 } else {
2232 /* we are working in a value that kind of exists, but is undefined */
2233 *fl = (float) 0.0; fl++; *fl = (float) 0.0; fl++;
2234 }
2235 break;
2236 }
2237 case FIELDTYPE_SFVec3f:
2238 case FIELDTYPE_SFColor: { /* SFColor */
2239 //if (JSVAL_IS_OBJECT(mainElement)) {
2240 if(mainElement.isObject()){
2241 if ((sfvec3f = (SFVec3fNative *)JS_GetPrivateFw(cx, JSVAL_TO_OBJECT(mainElement))) == NULL) {
2242 printf( "JS_GetPrivate failed for obj in setField_javascriptEventOut.\n");
2243 return;
2244 }
2245 memcpy ((void *)fl, (void *)&(sfvec3f->v),3*sizeof(float));
2246 fl += 3;
2247 } else {
2248 /* we are working in a value that kind of exists, but is undefined */
2249 *fl = (float) 0.0; fl++;
2250 *fl = (float) 0.0; fl++;
2251 *fl = (float) 0.0; fl++;
2252 }
2253 break;
2254 }
2255 case FIELDTYPE_SFRotation: {
2256 //if (JSVAL_IS_OBJECT(mainElement)) {
2257 if(mainElement.isObject()){
2258 if ((sfrotation = (SFRotationNative *)JS_GetPrivateFw(cx, JSVAL_TO_OBJECT(mainElement))) == NULL) {
2259 printf( "JS_GetPrivate failed for obj in setField_javascriptEventOut.\n");
2260 return;
2261 }
2262 memcpy ((void *)fl, (void *)&(sfrotation->v),4*sizeof(float));
2263 fl += 4;
2264 } else {
2265 /* we are working in a value that kind of exists, but is undefined */
2266 *fl = (float) 0.0; fl++; *fl = (float) 0.0; fl++;
2267 *fl = (float) 0.0; fl++; *fl = (float) 0.0; fl++;
2268 }
2269 break;
2270 }
2271
2272 case FIELDTYPE_SFString: {
2273 JSString *strval;
2274
2275 strval = JS_ValueToString(cx, mainElement);
2276 strp = strpp = JS_EncodeString(cx,strval);
2277
2278
2279
2280 #ifdef SETFIELDVERBOSE
2281 printf ("getJSMultiNumType, got string %s\n",strp);
2282 #endif
2283
2284 /* copy the string over, delete the old one, if need be */
2285 verify_Uni_String (*ms,strp);
2286 ms++;
2287
2288 JS_free(cx,strpp);
2289
2290 break;
2291 }
2292
2293 default : {printf ("getJSMultiNumType unhandled eletype: %d\n",
2294 eletype);
2295 return;
2296 }
2297 }
2298 }
2299
2300 }
2301 #ifdef SETFIELDVERBOSE
2302 printf ("getJSMultiNumType, setting old length %d to length %d\n",tn->n, len);
2303 #endif
2304
2305 tn->n = len;
2306}
2307
2308/****************************************************************/
2309/* a script is returning a MFString type; add this to the C */
2310/* children field */
2311/****************************************************************/
2312void getMFStringtype (JSContext *cx, jsval *from, struct Multi_String *to) {
2313 int oldlen, newlen;
2314 jsval _v;
2315 JSObject *obj;
2316 int i;
2317 char *valStr, *OldvalStr;
2318 struct Uni_String **svptr;
2319 struct Uni_String **newp, **oldp;
2320 int count;
2321
2322 JSString *strval; /* strings */
2323
2324 oldlen = to->n;
2325 svptr = to->p;
2326 newlen=0;
2327
2328 if (!JS_ValueToObject(cx, *from, &obj))
2329 printf ("JS_ValueToObject failed in getMFStringtype\n");
2330
2331 if (!JS_GetProperty(cx, obj, MF_LENGTH_FIELD, &_v)) {
2332 printf ("JS_GetProperty failed for \"%s\" in getMFStringtype.\n", MF_LENGTH_FIELD);
2333 }
2334
2335 newlen = JSVAL_TO_INT(_v);
2336
2337 /* printf ("getMFStringType, newlen %d oldlen %d\n",newlen,oldlen); */
2338
2339
2340 /* if we have to expand size of SV... */
2341 if (newlen > oldlen) {
2342 oldp = to->p; /* same as svptr, assigned above */
2343 to->n = newlen;
2344 to->p = MALLOC(struct Uni_String **, newlen * sizeof(to->p));
2345 newp = to->p;
2346
2347 /* copy old values over */
2348 for (count = 0; count <oldlen; count ++) {
2349 /*printf ("copying over element %d\n",count); */
2350 *newp = *oldp;
2351 newp++;
2352 oldp++;
2353 }
2354
2355 /* zero new entries */
2356 for (count = oldlen; count < newlen; count ++) {
2357 /* make the new SV */
2358 *newp = MALLOC (struct Uni_String *, sizeof (struct Uni_String));
2359
2360
2361 /* now, make it point to a blank string */
2362 *newp = newASCIIString("");
2363 newp ++;
2364 }
2365 FREE_IF_NZ (svptr);
2366 svptr = to->p;
2367 } else {
2368 /* possibly truncate this, but leave the memory alone. */
2369 to->n = newlen;
2370 }
2371
2372 /* printf ("verifying structure here\n");
2373 for (i=0; i<(to->n); i++) {
2374 printf ("indx %d flag %x string :%s: len1 %d len2 %d\n",i,
2375 (svptr[i])->sv_flags,
2376 }
2377 printf ("done\n");
2378 */
2379
2380
2381 for (i = 0; i < newlen; i++) {
2382 /* get the old string pointer */
2383 OldvalStr = svptr[i]->strptr;
2384 /* printf ("old string at %d is %s len %d\n",i,OldvalStr,strlen(OldvalStr)); */
2385
2386 /* get the new string pointer */
2387 if (!JS_GetElement(cx, obj, i, &_v)) {
2388 fprintf(stderr,
2389 "JS_GetElement failed for %d in getMFStringtype\n",i);
2390 return;
2391 }
2392 strval = JS_ValueToString(cx, _v);
2393
2394 valStr = JS_EncodeString(cx,strval);
2395
2396
2397 /* printf ("new string %d is %s\n",i,valStr); */
2398
2399 /* if the strings are different... */
2400 if (strcmp(valStr,OldvalStr) != 0) {
2401 /* MALLOC a new string, of correct len for terminator */
2402 svptr[i] = newASCIIString(valStr);
2403 }
2404
2405 JS_free(cx,valStr);
2406
2407 }
2408 /*
2409 printf ("\n new structure: %d %d\n",svptr,newlen);
2410 for (i=0; i<newlen; i++) {
2411 printf ("indx %d string :%s: len1 %d len2 %d\n",i,
2412 mypv->xpv_pv, mypv->xpv_cur,mypv->xpv_len);
2413 }
2414 */
2415
2416}
2417
2418
2419
2420
2421void setField_javascriptEventOut(struct X3D_Node *tn,unsigned int tptr, int fieldType, unsigned len, int extraData, JSContext *scriptContext) {
2422 long ival;
2423 double tval;
2424 float fl[4];
2425 char *memptr;
2426 JSString *strval; /* strings */
2427 char *strp;
2428 char *strpp; /* strp is modified, so we cannot use it to free JS_EncodeString results */
2429 ttglobal tg = gglobal();
2430
2431
2432 /* set up a pointer to where to put this stuff */
2433 memptr = offsetPointer_deref(char *, tn, tptr);
2434
2435#define GETJSVAL_TYPE_A(thistype,field) \
2436 case FIELDTYPE_##thistype: { \
2437 /* printf ("doing TYPEA memcpy to %u, from %u, len %d\n",(void *)memptr, (void *) &(((thistype##Native *)JSSFpointer)->field),len); */ \
2438 memcpy ((void *)memptr, (void *) &(((thistype##Native *)tg->CRoutes.JSSFpointer)->field),len); \
2439 break; \
2440 }
2441
2442#define GETJSVAL_TYPE_MF_A(MFtype,SFtype) \
2443 case FIELDTYPE_##MFtype: {getJSMultiNumType (scriptContext, (struct Multi_Vec3f *)memptr,FIELDTYPE_##SFtype); break;}
2444
2445 switch (fieldType) {
2446 GETJSVAL_TYPE_A(SFRotation,v)
2447 /* GETJSVAL_TYPE_A(SFNode,handle) */
2448 /* not implemented yet? GETJSVAL_TYPE_A(SFVec2d,v) */
2449 GETJSVAL_TYPE_A(SFVec3d,v)
2450 GETJSVAL_TYPE_A(SFVec4d,v)
2451 GETJSVAL_TYPE_A(SFVec2f,v)
2452 GETJSVAL_TYPE_A(SFVec3f,v)
2453 GETJSVAL_TYPE_A(SFVec4f,v)
2454 GETJSVAL_TYPE_A(SFColor,v)
2455 GETJSVAL_TYPE_A(SFColorRGBA,v)
2456
2457 GETJSVAL_TYPE_MF_A(MFRotation,SFRotation)
2458 GETJSVAL_TYPE_MF_A(MFVec2d,SFVec2d)
2459 GETJSVAL_TYPE_MF_A(MFVec3d,SFVec3d)
2460 GETJSVAL_TYPE_MF_A(MFVec4d,SFVec4d)
2461 GETJSVAL_TYPE_MF_A(MFVec2f,SFVec2f)
2462 GETJSVAL_TYPE_MF_A(MFVec3f,SFVec3f)
2463 GETJSVAL_TYPE_MF_A(MFVec4f,SFVec4f)
2464 GETJSVAL_TYPE_MF_A(MFColor,SFColor)
2465 GETJSVAL_TYPE_MF_A(MFColorRGBA,SFColorRGBA)
2466
2467
2468 case FIELDTYPE_SFInt32:
2469 case FIELDTYPE_SFBool: { /* SFBool */
2470 jsval val;
2471 val = *(jsval*)(tg->JScript.JSglobal_return_val);
2472 //if (!JS::ToInt32(scriptContext, *(jsval*)(tg->JScript.JSglobal_return_val),&ival)) {
2473 ival=0;
2474 if(! (val.isBoolean() || val.isInt32())){
2475 printf ("error\n");
2476 }
2477 if(val.isBoolean()) ival = val.isTrue() ? TRUE : FALSE;
2478 if(val.isInt32()) ival = val.toInt32() == 0 ? FALSE : TRUE;
2479 memcpy ((void *)memptr, (void *)&ival,len);
2480 break;
2481 }
2482
2483 case FIELDTYPE_SFDouble:
2484 case FIELDTYPE_SFTime: {
2485 if (!JS_ValueToNumber(scriptContext, *(jsval*)(tg->JScript.JSglobal_return_val),&tval)) tval=0.0;
2486 memcpy ((void *)memptr, (void *)&tval,len);
2487 break;
2488 }
2489
2490 case FIELDTYPE_SFFloat: {
2491 if (!JS_ValueToNumber(scriptContext, *(jsval*)(tg->JScript.JSglobal_return_val),&tval)) tval=0.0;
2492 /* convert double precision to single, for X3D */
2493 fl[0] = (float) tval;
2494 memcpy ((void *)memptr, (void *)fl,len);
2495 break;
2496 }
2497
2498 case FIELDTYPE_SFImage: {
2499 /* the string should be saved as an SFImage */
2500 strval = JS_ValueToString(scriptContext, *(jsval*)(tg->JScript.JSglobal_return_val));
2501 strp = strpp = JS_EncodeString(scriptContext,strval);
2502 Parser_scanStringValueToMem(tn, tptr, FIELDTYPE_SFImage, strp, FALSE);
2503 JS_free(scriptContext,strpp);
2504 break;
2505 }
2506
2507 case FIELDTYPE_SFString: {
2508 struct Uni_String *ms;
2509 intptr_t *newptr;
2510
2511 strval = JS_ValueToString(scriptContext, *(jsval*)(tg->JScript.JSglobal_return_val));
2512 strp = strpp = JS_EncodeString(scriptContext,strval);
2513 /* copy the string over, delete the old one, if need be */
2514 /* printf ("fieldSet SFString, tn %d tptr %d offset from struct %d\n",
2515 tn, tptr, offsetof (struct X3D_TextureCoordinateGenerator, mode)); */
2516 newptr = (intptr_t *)memptr;
2517 ms = (struct Uni_String*) *newptr;
2518 verify_Uni_String (ms,strp);
2519 JS_free(scriptContext,strpp);
2520 break;
2521 }
2522
2523 /* a series of Floats... */
2524 case FIELDTYPE_MFFloat: {getJSMultiNumType (scriptContext, (struct Multi_Vec3f *)memptr,FIELDTYPE_SFFloat); break;}
2525 case FIELDTYPE_MFInt32: {getJSMultiNumType (scriptContext, (struct Multi_Vec3f *)memptr,FIELDTYPE_SFInt32); break;}
2526 case FIELDTYPE_MFTime: {getJSMultiNumType (scriptContext, (struct Multi_Vec3f *)memptr,FIELDTYPE_SFTime); break;}
2527 case FIELDTYPE_MFDouble: {getJSMultiNumType (scriptContext, (struct Multi_Vec3f *)memptr,FIELDTYPE_SFDouble); break;}
2528 case FIELDTYPE_MFNode: {
2529 struct X3D_Node *mynode;
2530
2531 strval = JS_ValueToString(scriptContext, *(jsval*)(tg->JScript.JSglobal_return_val));
2532 strp = strpp = JS_EncodeString(scriptContext,strval);
2533
2534 /* we will have at least one node here, in an ascii string */
2535 while ((*strp > '\0') && (*strp <= ' ')) strp ++;
2536 /* are we at a bracket? */
2537 if (*strp == '[') strp ++;
2538 while ((*strp > '\0') && (*strp <= ' ')) strp ++;
2539
2540 /* printf ("convertingthe following string to a pointer :%s:\n",strp); */
2541#ifndef _x64
2542 mynode = X3D_NODE(atol(strp));
2543#else
2544 mynode = X3D_NODE(atoll(strp));
2545#endif
2546 JS_free(scriptContext,strpp);
2547
2548 /* printf ("mynode is %p %d, \n",mynode,mynode);
2549 printf ("mynode is %p %d, type %d\n",mynode,mynode,mynode->_nodeType);
2550 printf ("calling getMFNodeType now\n"); */
2551
2552
2553 getMFNodetype (mynode,(struct Multi_Node *)memptr,X3D_NODE(tn),extraData); break;
2554 }
2555 case FIELDTYPE_MFString: {
2556 getMFStringtype (
2557 scriptContext,
2558 (jsval *)tg->JScript.JSglobal_return_val,
2559 (struct Multi_String *)memptr);
2560 break;
2561 }
2562
2563 case FIELDTYPE_SFNode: {
2564 //unsigned int valuecopied;
2565 //unsigned int *ptr2value;
2566 /* printf ("doing TYPEA memcpy to %u, from %u, len %d\n",(void *)memptr, (void *) &(((SFNodeNative *)JSSFpointer)->handle),returnElementLength(FIELDTYPE_SFNode));*/
2567 memcpy ((void *)memptr, (void *) &(((SFNodeNative *)tg->CRoutes.JSSFpointer)->handle),returnElementLength(FIELDTYPE_SFNode));
2568 //ptr2value = (unsigned int*)memptr;
2569 //valuecopied = *ptr2value;
2570 //printf("value of memptr %u after memcpy in script route= %u\n",(void*)memptr,valuecopied);
2571 break;
2572 }
2573 default: { printf("WARNING: unhandled from type %s\n", stringFieldtypeType(fieldType));
2574 }
2575 }
2576}
2577
2578
2579
2580void setField_javascriptEventOut_B(union anyVrml* any,
2581 int fieldType, unsigned len, int extraData, JSContext *scriptContext)
2582{
2583 //dug9 Feb 2013 for new propagate_events - like setField_javascriptEventout except:
2584 // writes to *anyVrml instead of (toNode,toOffset) combo (which doesn't work for Proto fields)
2585 // and doesn't update parents for SFNode,MFNode - that's done later.
2586 long ival;
2587 double tval;
2588 float fl[4];
2589 char *memptr;
2590 JSString *strval; /* strings */
2591 char *strp;
2592 char *strpp; /* strp is modified, so we cannot use it to free JS_EncodeString results */
2593 ttglobal tg = gglobal();
2594 /* set up a pointer to where to put this stuff */
2595 memptr = (char *)any; //offsetPointer_deref(char *, tn, tptr);
2596
2597#define GETJSVAL_TYPE_A(thistype,field) \
2598 case FIELDTYPE_##thistype: { \
2599 /* printf ("doing TYPEA memcpy to %u, from %u, len %d\n",(void *)memptr, (void *) &(((thistype##Native *)JSSFpointer)->field),len); */ \
2600 memcpy ((void *)memptr, (void *) &(((thistype##Native *)tg->CRoutes.JSSFpointer)->field),len); \
2601 break; \
2602 }
2603
2604#define GETJSVAL_TYPE_MF_A(MFtype,SFtype) \
2605 case FIELDTYPE_##MFtype: {getJSMultiNumType (scriptContext, (struct Multi_Vec3f *)memptr,FIELDTYPE_##SFtype); break;}
2606
2607 switch (fieldType) {
2608 GETJSVAL_TYPE_A(SFRotation,v)
2609 /* GETJSVAL_TYPE_A(SFNode,handle) */
2610 /* not implemented yet? GETJSVAL_TYPE_A(SFVec2d,v) */
2611 GETJSVAL_TYPE_A(SFVec3d,v)
2612 GETJSVAL_TYPE_A(SFVec4d,v)
2613 GETJSVAL_TYPE_A(SFVec2f,v)
2614 GETJSVAL_TYPE_A(SFVec3f,v)
2615 GETJSVAL_TYPE_A(SFVec4f,v)
2616 GETJSVAL_TYPE_A(SFColor,v)
2617 GETJSVAL_TYPE_A(SFColorRGBA,v)
2618
2619 GETJSVAL_TYPE_MF_A(MFRotation,SFRotation)
2620 GETJSVAL_TYPE_MF_A(MFVec2d,SFVec2d)
2621 GETJSVAL_TYPE_MF_A(MFVec3d,SFVec3d)
2622 GETJSVAL_TYPE_MF_A(MFVec4d,SFVec4d)
2623 GETJSVAL_TYPE_MF_A(MFVec2f,SFVec2f)
2624 GETJSVAL_TYPE_MF_A(MFVec3f,SFVec3f)
2625 GETJSVAL_TYPE_MF_A(MFVec4f,SFVec4f)
2626 GETJSVAL_TYPE_MF_A(MFColor,SFColor)
2627 GETJSVAL_TYPE_MF_A(MFColorRGBA,SFColorRGBA)
2628
2629
2630 case FIELDTYPE_SFInt32:
2631 case FIELDTYPE_SFBool: { /* SFBool */
2632
2633 jsval val = *(jsval*)(tg->JScript.JSglobal_return_val);
2634 if(!val.isBoolean() || val.isInt32()){
2635 //if (!JS::ToInt32(scriptContext, ,&ival)) {
2636 printf ("error\n");
2637 ival=0;
2638 }
2639 if(val.isBoolean()) ival = val.isTrue() ? TRUE : FALSE;
2640 if(val.isInt32()) ival = val.toInt32() == 0 ? FALSE : TRUE;
2641 memcpy ((void *)memptr, (void *)&ival,len);
2642 break;
2643 }
2644
2645 case FIELDTYPE_SFDouble:
2646 case FIELDTYPE_SFTime: {
2647 if (!JS_ValueToNumber(scriptContext, *(jsval*)(tg->JScript.JSglobal_return_val),&tval)) tval=0.0;
2648 memcpy ((void *)memptr, (void *)&tval,len);
2649 break;
2650 }
2651
2652 case FIELDTYPE_SFFloat: {
2653 if (!JS_ValueToNumber(scriptContext, *(jsval*)(tg->JScript.JSglobal_return_val),&tval)) tval=0.0;
2654 /* convert double precision to single, for X3D */
2655 fl[0] = (float) tval;
2656 memcpy ((void *)memptr, (void *)fl,len);
2657 break;
2658 }
2659
2660 case FIELDTYPE_SFImage: {
2661 /* the string should be saved as an SFImage */
2662 strval = JS_ValueToString(scriptContext, *(jsval*)(tg->JScript.JSglobal_return_val));
2663 strp = strpp = JS_EncodeString(scriptContext,strval);
2664 Parser_scanStringValueToMem_B(any, FIELDTYPE_SFImage, strp, FALSE);
2665 JS_free(scriptContext,strpp);
2666 break;
2667 }
2668
2669 case FIELDTYPE_SFString: {
2670 struct Uni_String *ms;
2671 intptr_t *newptr;
2672
2673 strval = JS_ValueToString(scriptContext, *(jsval*)(tg->JScript.JSglobal_return_val));
2674 strp = strpp = JS_EncodeString(scriptContext,strval);
2675
2676 /* copy the string over, delete the old one, if need be */
2677 /* printf ("fieldSet SFString, tn %d tptr %d offset from struct %d\n",
2678 tn, tptr, offsetof (struct X3D_TextureCoordinateGenerator, mode)); */
2679 newptr = (intptr_t *)memptr;
2680 ms = (struct Uni_String*) *newptr;
2681 if(!ms) {
2682 ms = (struct Uni_String*)malloc(sizeof(struct Uni_String));
2683 *newptr = (intptr_t) ms;
2684 ms->len = 0;
2685 ms->strptr = NULL;
2686 ms->touched = FALSE;
2687 }
2688 verify_Uni_String (ms,strp);
2689 JS_free(scriptContext,strpp);
2690 break;
2691 }
2692
2693
2694 /* a series of Floats... */
2695 case FIELDTYPE_MFFloat: {getJSMultiNumType (scriptContext, (struct Multi_Vec3f *)memptr,FIELDTYPE_SFFloat); break;}
2696 case FIELDTYPE_MFInt32: {getJSMultiNumType (scriptContext, (struct Multi_Vec3f *)memptr,FIELDTYPE_SFInt32); break;}
2697 case FIELDTYPE_MFTime: {getJSMultiNumType (scriptContext, (struct Multi_Vec3f *)memptr,FIELDTYPE_SFTime); break;}
2698 case FIELDTYPE_MFDouble: {getJSMultiNumType (scriptContext, (struct Multi_Vec3f *)memptr,FIELDTYPE_SFDouble); break;}
2699 case FIELDTYPE_MFNode: {
2700 struct X3D_Node *mynode;
2701
2702 strval = JS_ValueToString(scriptContext, *(jsval*)(tg->JScript.JSglobal_return_val));
2703 strp = strpp = JS_EncodeString(scriptContext,strval);
2704 /* we will have at least one node here, in an ascii string */
2705 while ((*strp > '\0') && (*strp <= ' ')) strp ++;
2706 /* are we at a bracket? */
2707 if (*strp == '[') strp ++;
2708 while ((*strp > '\0') && (*strp <= ' ')) strp ++;
2709
2710 /* printf ("convertingthe following string to a pointer :%s:\n",strp); */
2711
2712#ifndef _x64
2713 mynode = X3D_NODE(atol(strp));
2714#else
2715 mynode = X3D_NODE(atoll(strp));
2716#endif
2717 JS_free(scriptContext,strpp);
2718
2719 /* printf ("mynode is %p %d, \n",mynode,mynode);
2720 printf ("mynode is %p %d, type %d\n",mynode,mynode,mynode->_nodeType);
2721 printf ("calling getMFNodeType now\n"); */
2722
2723
2724 //getMFNodetype (mynode,(struct Multi_Node *)memptr,X3D_NODE(tn),extraData);
2725 any->mfnode.n = 1;
2726 any->mfnode.p = MALLOC(struct X3D_Node **, sizeof(struct X3D_Node *));
2727 any->mfnode.p[0] = mynode;
2728 //Q. can we do add/remove children outside?
2729 break;
2730 }
2731 case FIELDTYPE_MFString: {
2732 getMFStringtype (
2733 scriptContext,
2734 (jsval *)tg->JScript.JSglobal_return_val,
2735 (struct Multi_String *)memptr);
2736 break;
2737 }
2738
2739 case FIELDTYPE_SFNode: {
2740 //unsigned int valuecopied;
2741 //unsigned int *ptr2value;
2742 /* printf ("doing TYPEA memcpy to %u, from %u, len %d\n",(void *)memptr, (void *) &(((SFNodeNative *)JSSFpointer)->handle),returnElementLength(FIELDTYPE_SFNode));*/
2743 memcpy ((void *)memptr, (void *) &(((SFNodeNative *)tg->CRoutes.JSSFpointer)->handle),returnElementLength(FIELDTYPE_SFNode));
2744 //ptr2value = (unsigned int*)memptr;
2745 //valuecopied = *ptr2value;
2746 //printf("value of memptr %u after memcpy in script route= %u\n",(void*)memptr,valuecopied);
2747 break;
2748 }
2749 default: { printf("WARNING: unhandled from type %s\n", stringFieldtypeType(fieldType));
2750 }
2751 }
2752
2753}
2754
2755extern "C" {
2756void sm_js_setField_javascriptEventOut(struct X3D_Node *tn,unsigned int tptr, int fieldType, unsigned len, int extraData, int actualscript) {
2757 struct CRscriptStruct *scriptcontrol;
2758 JSContext *cx;
2759 JSObject *global;
2760 scriptcontrol = getScriptControlIndex(actualscript);
2761 cx = (JSContext*)scriptcontrol->cx;
2762 global = (JSObject*)scriptcontrol->glob;
2763 { // Scope A for our various stack objects (JSAutoRequest, RootedObject), so they all go
2764 // out of scope before we JS_DestroyContext.
2765 JSAutoRequest ar(cx); // In practice, you would want to exit this any
2766 // time you're spinning the event loop
2767 { // Scope B for JSAutoCompartment
2768 JSAutoCompartment ac(cx, global);
2769 setField_javascriptEventOut(tn,tptr,fieldType, len, extraData, (JSContext*)scriptcontrol->cx);
2770 } //Scope B
2771 } //Scope A
2772}
2773
2774void sm_js_setField_javascriptEventOut_B(union anyVrml* any, int fieldType, unsigned len, int extraData, int actualscript){
2775 struct CRscriptStruct *scriptcontrol;
2776 JSContext *cx;
2777 JSObject *global;
2778 scriptcontrol = getScriptControlIndex(actualscript);
2779 cx = (JSContext*)scriptcontrol->cx;
2780 global = (JSObject*)scriptcontrol->glob;
2781 { // Scope A for our various stack objects (JSAutoRequest, RootedObject), so they all go
2782 // out of scope before we JS_DestroyContext.
2783 JSAutoRequest ar(cx); // In practice, you would want to exit this any
2784 // time you're spinning the event loop
2785 { // Scope B for JSAutoCompartment
2786 JSAutoCompartment ac(cx, global);
2787 setField_javascriptEventOut_B(any,fieldType, len, extraData, (JSContext*)scriptcontrol->cx);
2788 } //Scope B
2789 } //Scope A
2790}
2791
2792
2793/******************************************************************************/
2794
2795void sm_set_one_ECMAtype (int tonode, int toname, int dataType, void *Data, int datalen) {
2796 char scriptline[256];
2797 jsval newval;
2798 JSContext *cx;
2799 JSObject *obj;
2800 int kind;
2801 ttglobal tg = gglobal();
2802 ppJScript p = (ppJScript)tg->JScript.prv;
2803
2804 struct CRscriptStruct *ScriptControl; // = getScriptControl();
2805 struct CRjsnameStruct *JSparamnames = getJSparamnames();
2806
2807 #ifdef SETFIELDVERBOSE
2808 printf ("set_one_ECMAtype, to %d namepointer %d, fieldname %s, datatype %d length %d\n",
2809 tonode,toname,JSparamnames[toname].name,dataType,datalen);
2810 #endif
2811 ScriptControl = getScriptControlIndex(tonode);
2812 /* get context and global object for this script */
2813 cx = (JSContext*)ScriptControl->cx;
2814 obj = (JSObject*)ScriptControl->glob;
2815
2816 { // Scope for our various stack objects (JSAutoRequest, RootedObject), so they all go
2817 // out of scope before we JS_DestroyContext.
2818
2819 JSAutoRequest ar(cx); // In practice, you would want to exit this any
2820 // time you're spinning the event loop
2821 { // Scope for JSAutoCompartment
2822 JSAutoCompartment ac(cx, obj);
2823
2824 /* set the time for this script */
2825 //SET_JS_TICKTIME
2826 {
2827 jsval zimbo;
2828 JS_NewNumberValue(cx, TickTime(), &zimbo);
2829 if (!JS_DefineProperty(cx,obj, "__eventInTickTime", zimbo, JS_GET_PROPERTY_STUB, JS_SET_PROPERTY_STUB2, JSPROP_PERMANENT)) {
2830 printf( "JS_DefineProperty failed for \"__eventInTickTime\" at %s:%d.\n",__FILE__,__LINE__);
2831 return;
2832 }
2833 FW_MaybeGC("SOET TT", cx);
2834
2835 //printf("<SOET TT ");
2836 //JS_GC(p->runtime);
2837 //printf(">");
2838 }
2839
2840 //step 1 set the field value
2841 kind = JSparamnames[toname].kind; //PKW_inputOnly;
2842 if(SM_method() == 2){
2843 int type, iifield, *valueChanged, ifound;
2844 union anyVrml *value;
2845 char *fieldname;
2846 struct Shader_Script *script = ScriptControl->script;
2847 fieldname = JSparamnames[toname].name;
2848 //step 1 update the fieldvalue
2849 ifound = getFieldFromScript(script,fieldname,&type,&kind,&iifield,&value,&valueChanged);
2850 if(ifound && type == dataType && isSFType(type)){
2851 //we have an MF field, and mf coming in, we'll call our field LHS and incoming RHS
2852 union anyVrml *any = (union anyVrml*)Data;
2853 //printf("any float=%f",any->sffloat);
2854 shallow_copy_field(type,any,value);
2855 //if we have an inputOutput field with no eventIn function, we may still be routing
2856 //from the out side
2857 (*valueChanged) = 1;
2858 }else{
2859 ConsoleMessage("sm_set_one_ECMAtype did not find field %s type %d\n",fieldname, dataType);
2860 return;
2861 }
2862
2863 }else{ //SM_method == 2
2864 X3D_ECMA_TO_JS(cx, Data, datalen, dataType, &newval);
2865
2866 /* get the variable name to hold the incoming value */
2867 scriptline[0] = 0;
2868 if(kind == PKW_inputOnly)
2869 strcat(scriptline,"__eventIn_Value_");
2870 //sprintf (scriptline,"__eventIn_Value_%s", JSparamnames[toname].name);
2871 strcat(scriptline,JSparamnames[toname].name);
2872 #ifdef SETFIELDVERBOSE
2873 printf ("set_one_ECMAtype, calling JS_DefineProperty on name %s obj %u, setting setECMANative, 0 \n",scriptline,obj);
2874 #endif
2875
2876 if (!JS_DefineProperty(cx,obj, scriptline, newval, JS_GET_PROPERTY_STUB, JS_SET_PROPERTY_STUB3, JSPROP_PERMANENT)) {
2877 printf( "JS_DefineProperty failed for \"ECMA in\" at %s:%d.\n",__FILE__,__LINE__);
2878 return;
2879 }
2880
2881 } //SM_method == 2
2882
2883 //step 2 run eventin if it exists
2884 /* is the function compiled yet? */
2885 //printf("[SOET ");
2886 JSScript* hscript = NULL;
2887 JS::RootedScript rscript(cx,hscript);
2888 //COMPILE_FUNCTION_IF_NEEDED_SET(toname, kind);
2889 {
2890 //#define COMPILE_FUNCTION_IF_NEEDED_SET(tnfield,kind)
2891 int tnfield = toname;
2892 hscript = (JSScript*)JSparamnames[tnfield].eventInFunction;
2893 if (JSparamnames[tnfield].eventInFunction == NULL || TRUE) {
2894 if(kind == PKW_inputOutput)
2895 sprintf (scriptline,"set_%s(%s,__eventInTickTime)", JSparamnames[tnfield].name,JSparamnames[tnfield].name);
2896 else /* PKW_inputOnly */
2897 sprintf (scriptline,"%s(%s%s,__eventInTickTime)", JSparamnames[tnfield].name,"__eventIn_Value_",JSparamnames[tnfield].name);
2898 /* printf ("compiling function %s for type %d\n",scriptline,JSparamnames[tnfield].type); */
2899 hscript = (JSScript*)JS_CompileScript(
2900 cx, obj, scriptline, strlen(scriptline), "compile eventIn",1);
2901 JSparamnames[tnfield].eventInFunction = (void*)hscript;
2902 if(0) if (!JS_AddObjectRoot(cx,(JSObject**)(&JSparamnames[tnfield].eventInFunction))) {
2903 printf( "JS_AddObjectRoot failed for compilation of script \"%s\" at %s:%d.\n",scriptline,__FILE__,__LINE__);
2904 return;
2905 }
2906 }
2907 }
2908 FW_MaybeGC("CF", cx);
2909
2910 //printf("<CF");
2911 //JS_GC(p->runtime);
2912 //printf(">");
2913
2914 /* and run the function */
2915 RUN_FUNCTION(toname);
2916 FW_MaybeGC("RF", cx);
2917 //printf("<RF");
2918 //JS_GC(p->runtime);
2919 //printf(">]");
2920
2921 } //Scope B
2922
2923 } //Scope A
2924
2925
2926}
2927
2928/* setScriptECMAtype called by getField_ToJavascript for
2929 case FIELDTYPE_SFBool:
2930 case FIELDTYPE_SFFloat:
2931 case FIELDTYPE_SFTime:
2932 case FIELDTYPE_SFDouble:
2933 case FIELDTYPE_SFInt32:
2934 case FIELDTYPE_SFString:
2935*/
2936
2937void sm_setScriptECMAtype (int num) {
2938 void *fn;
2939 int tptr;
2940 int len;
2941 int to_counter;
2942 CRnodeStruct *to_ptr = NULL;
2943 struct CRStruct *CRoutes = getCRoutes();
2944 struct CRjsnameStruct *JSparamnames = getJSparamnames();
2945
2946 fn = offsetPointer_deref(void *, CRoutes[num].routeFromNode, CRoutes[num].fnptr);
2947 len = CRoutes[num].len;
2948
2949 for (to_counter = 0; to_counter < CRoutes[num].tonode_count; to_counter++) {
2950 struct Shader_Script *myObj;
2951
2952 to_ptr = &(CRoutes[num].tonodes[to_counter]);
2953 myObj = (struct Shader_Script*)X3D_SCRIPT(to_ptr->routeToNode)->__scriptObj;
2954 /* printf ("setScriptECMAtype, myScriptNumber is %d\n",myObj->num); */
2955 tptr = to_ptr->foffset;
2956 set_one_ECMAtype (myObj->num, tptr, JSparamnames[tptr].type, fn,len);
2957 }
2958}
2959
2960
2961
2962/* use Javascript to send in one element of an MF. datalen is in number of elements in type. */
2963void sm_set_one_MFElementType(int tonode, int toname, int dataType, void *Data, int datalen) {
2964 JSContext *cx;
2965 JSObject *obj;
2966 int elementlen;
2967 int x;
2968 char scriptline[20000];
2969
2970 /* for PixelTextures we have: */
2971 //struct X3D_PixelTexture *mePix;
2972 //struct Multi_Int32 image;
2973
2974 /* for MFStrings we have: */
2975 char *chptr;
2976 struct Uni_String **uniptr;
2977 int kind;
2978 struct CRscriptStruct *ScriptControl; // = getScriptControl();
2979 struct CRjsnameStruct *JSparamnames = getJSparamnames();
2980 ttglobal tg = gglobal();
2981 ppJScript p = (ppJScript)tg->JScript.prv;
2982
2983 /* get context and global object for this script */
2984 ScriptControl = getScriptControlIndex(tonode);
2985 cx = (JSContext*)ScriptControl->cx;
2986 obj = (JSObject*)ScriptControl->glob;
2987
2988 { // Scope A for our various stack objects (JSAutoRequest, RootedObject), so they all go
2989 // out of scope before we JS_DestroyContext.
2990 JSAutoRequest ar(cx); // In practice, you would want to exit this any
2991 // time you're spinning the event loop
2992 { // Scope B for JSAutoCompartment
2993 JSAutoCompartment ac(cx, obj);
2994
2995 /* set the TickTime (possibly again) for this context */
2996 kind = JSparamnames[toname].kind; //PKW_inputOnly;
2997 if(SM_method() == 2){
2998 int type, iifield, *valueChanged, ifound;
2999 union anyVrml *value;
3000 char *fieldname;
3001 struct Shader_Script *script = ScriptControl->script;
3002 fieldname = JSparamnames[toname].name;
3003 //step 1 update the fieldvalue
3004 ifound = getFieldFromScript(script,fieldname,&type,&kind,&iifield,&value,&valueChanged);
3005 if(ifound && type == dataType && !isSFType(type)){
3006 //we have an MF field, and mf coming in, we'll call our field LHS and incoming RHS
3007 union anyVrml any;
3008 any.mfbool.n = datalen;
3009 any.mfbool.p = (int *)Data;
3010 //printf("address of any.p %x value.p %x",any.mfbool.p,value->mfbool.p);
3011 //printf("any.n=%d \n",any.mffloat.n);
3012 //printf("mfany= %f %f %f",any.mffloat.p[0],any.mffloat.p[1],any.mffloat.p[2]);
3013 //printf("target value.n= %d\n",value->mfbool.n);
3014 shallow_copy_field(type,&any,value);
3015 //printf("after shallow_copy_field:\n");
3016 //printf("target value.n= %d\n",value->mfbool.n);
3017 //printf("mfvalue= %f %f %f",value->mffloat.p[0],value->mffloat.p[1],value->mffloat.p[2]);
3018
3019 //if we have an inputOutput field with no eventIn function, we may still be routing
3020 //from the out side
3021 (*valueChanged) = 1;
3022 }else{
3023 ConsoleMessage("sm_set_one_MFElementType did not find field %s type %d\n",fieldname, dataType);
3024 return;
3025 }
3026 //step 2 run the eventIn if it exists
3027 //printf("<TT ");
3028 SET_JS_TICKTIME;
3029 FW_MaybeGC("TT",cx);
3030
3031 //JS_GC(p->runtime);
3032 //printf(">");
3033 //compile also pushes the field val onto call stack
3034 JSScript* hscript = NULL;
3035 JS::RootedScript rscript(cx, hscript);
3036 //COMPILE_FUNCTION_IF_NEEDED_SET(toname, kind);
3037 {
3038 int tnfield = toname;
3039 //#define COMPILE_FUNCTION_IF_NEEDED_SET(tnfield,kind)
3040 if (JSparamnames[tnfield].eventInFunction == NULL || TRUE) {
3041 if(kind == PKW_inputOutput)
3042 sprintf (scriptline,"set_%s(%s,__eventInTickTime)", JSparamnames[tnfield].name,JSparamnames[tnfield].name);
3043 else /* PKW_inputOnly */
3044 sprintf (scriptline,"%s(%s%s,__eventInTickTime)", JSparamnames[tnfield].name,"__eventIn_Value_",JSparamnames[tnfield].name);
3045 /* printf ("compiling function %s for type %d\n",scriptline,JSparamnames[tnfield].type); */
3046 //JS::Heap<JSScript*> hscript;
3047 hscript = JS_CompileScript( cx, obj, scriptline, strlen(scriptline), "compile eventIn",1);
3048 JSparamnames[tnfield].eventInFunction = (void*)hscript;
3049 //JSScript *script = JS_CompileScript(cx, obj, scriptline, strlen(scriptline), "compile eventIn", 1);
3050 //JS::RootedScript rscript(cx, script);
3051 //rscript.set(script);
3052 //JSparamnames[tnfield].eventInFunction = (void*)script;
3053 if(0) if (!JS_AddObjectRoot(cx,(JSObject**)(&JSparamnames[tnfield].eventInFunction))) {
3054 printf( "JS_AddObjectRoot failed for compilation of script \"%s\" at %s:%d.\n",scriptline,__FILE__,__LINE__);
3055 return;
3056 }
3057 }
3058
3059 }
3060 FW_MaybeGC("CF", cx);
3061
3062 //printf("<CF ");
3063 //JS_GC(p->runtime);
3064 //printf(">");
3065 //printf("<RF");
3066 RUN_FUNCTION(toname);
3067 //if(0){
3068 // int tnfield = toname;
3069 // //#define RUN_FUNCTION(tnfield)
3070 // {
3071 // jsval zimbo;
3072 // //if (!JS_ExecuteScript(cx, obj, (JSScript*)JSparamnames[tnfield].eventInFunction, &zimbo)) {
3073 // if (!JS_ExecuteScript(cx, obj, rscript, &zimbo)) {
3074 // printf ("eventIn %s failed to complete successfully, in FreeWRL code %s:%d\n",JSparamnames[tnfield].name,__FILE__,__LINE__);
3075 // /* printf ("myThread is %u\n",pthread_self());*/ \
3076 // }
3077 // }
3078
3079 //}
3080 FW_MaybeGC("RF", cx);
3081
3082 //JS_GC(p->runtime);
3083 //printf(">");
3084 return;
3085 }
3086 SET_JS_TICKTIME
3087
3088 /* make up the name */
3089 switch (dataType) {
3090 case FIELDTYPE_MFRotation: {
3091 JSObject *newMFObject;
3092 JSObject *newSFObject;
3093 SFRotationNative *SFRPptr;
3094 float *fp, *fp_in=(float *)Data;
3095
3096 /* create a new MFRotation object... */
3097 newMFObject = JS_ConstructObjectFw(cx, &MFRotationClass, NULL ,JS_GetParentFw(cx, obj));
3098 ADD_ROOT (cx, newMFObject)
3099
3100 /* define the "length" property for this object */
3101 DEFINE_LENGTH_NORV(cx,newMFObject,datalen)
3102
3103 /* fill in private pointer area */
3104 elementlen = (int) sizeof (float);
3105 for (x=0; x<datalen; x++) {
3106 /* create a new SFRotation object */
3107 newSFObject = JS_ConstructObjectFw(cx,&SFRotationClass,NULL, newMFObject);
3108 if ((SFRPptr = (SFRotationNative *)JS_GetPrivateFw(cx, newSFObject)) == NULL) {
3109 ConsoleMessage ("failure in getting SF class at %s:%d\n",__FILE__,__LINE__);
3110 return;
3111 }
3112
3113 /* fill the private pointer area */
3114 fp = (float *)fp_in; SFRPptr->v.c[0] = *fp; fp_in = offsetPointer_deref(float *,fp_in,elementlen);
3115 fp = (float *)fp_in; SFRPptr->v.c[1] = *fp; fp_in = offsetPointer_deref(float *,fp_in,elementlen);
3116 fp = (float *)fp_in; SFRPptr->v.c[2] = *fp; fp_in = offsetPointer_deref(float *,fp_in,elementlen);
3117 fp = (float *)fp_in; SFRPptr->v.c[3] = *fp; fp_in = offsetPointer_deref(float *,fp_in,elementlen);
3118
3119 /* put this object into the MF class */
3120 if (!JS_DefineElement(cx, newMFObject, (jsint) x, OBJECT_TO_JSVAL(newSFObject),
3121 JS_GET_PROPERTY_STUB, JS_SET_PROPERTY_STUB3, JSPROP_ENUMERATE)) {
3122 printf("failure in inserting SF class at %s:%d\n",__FILE__,__LINE__);
3123 }
3124 }
3125
3126 /* set the length of this MF */
3127 SET_LENGTH (cx,newMFObject,datalen)
3128
3129 /* set the obj variable with this new MF object */
3130 SET_EVENTIN_VALUE (cx,obj,toname,newMFObject)
3131
3132 /* run the function */
3133 COMPILE_FUNCTION_IF_NEEDED_SET(toname,kind)
3134 RUN_FUNCTION(toname)
3135 break;
3136 }
3137
3138 case FIELDTYPE_MFVec3f: {
3139 JSObject *newMFObject;
3140 JSObject *newSFObject;
3141 SFVec3fNative *SFRPptr;
3142 float *fp, *fp_in=(float *)Data;
3143
3144 /* create a new MFVec3f object... */
3145 newMFObject = JS_ConstructObjectFw(cx, &MFVec3fClass, NULL ,JS_GetParentFw(cx, obj));
3146 ADD_ROOT (cx, newMFObject)
3147
3148 /* define the "length" property for this object */
3149 DEFINE_LENGTH_NORV(cx,newMFObject,datalen)
3150
3151 /* fill in private pointer area */
3152 elementlen = (int) sizeof (float);
3153 for (x=0; x<datalen; x++) {
3154 /* create a new SFVec3f object */
3155 newSFObject = JS_ConstructObjectFw(cx,&SFVec3fClass,NULL, newMFObject);
3156 if ((SFRPptr = (SFVec3fNative *)JS_GetPrivateFw(cx, newSFObject)) == NULL) {
3157 ConsoleMessage ("failure in getting SF class at %s:%d\n",__FILE__,__LINE__);
3158 return;
3159 }
3160
3161 /* fill the private pointer area */
3162 fp = (float *)fp_in; SFRPptr->v.c[0] = *fp; fp_in = offsetPointer_deref(float *,fp_in,elementlen);
3163 fp = (float *)fp_in; SFRPptr->v.c[1] = *fp; fp_in = offsetPointer_deref(float *,fp_in,elementlen);
3164 fp = (float *)fp_in; SFRPptr->v.c[2] = *fp; fp_in = offsetPointer_deref(float *,fp_in,elementlen);
3165
3166 /* put this object into the MF class */
3167 if (!JS_DefineElement(cx, newMFObject, (jsint) x, OBJECT_TO_JSVAL(newSFObject),
3168 JS_GET_PROPERTY_STUB, JS_SET_PROPERTY_STUB3, JSPROP_ENUMERATE)) {
3169 printf("failure in inserting SF class at %s:%d\n",__FILE__,__LINE__);
3170 }
3171 }
3172
3173 /* set the length of this MF */
3174 SET_LENGTH (cx,newMFObject,datalen)
3175
3176 /* set the global variable with this new MF object */
3177 SET_EVENTIN_VALUE (cx,obj,toname,newMFObject)
3178
3179 /* run the function */
3180 COMPILE_FUNCTION_IF_NEEDED_SET(toname,kind)
3181 RUN_FUNCTION(toname)
3182 break;
3183 }
3184
3185 case FIELDTYPE_MFColor: {
3186 JSObject *newMFObject;
3187 JSObject *newSFObject;
3188 SFColorNative *SFRPptr;
3189 float *fp, *fp_in=(float *)Data;
3190
3191 /* create a new MFColor object... */
3192 newMFObject = JS_ConstructObjectFw(cx, &MFColorClass, NULL ,JS_GetParentFw(cx, obj));
3193 ADD_ROOT (cx, newMFObject)
3194
3195 /* define the "length" property for this object */
3196 DEFINE_LENGTH_NORV(cx,newMFObject,datalen)
3197
3198 /* fill in private pointer area */
3199 elementlen = (int) sizeof (float);
3200 for (x=0; x<datalen; x++) {
3201 /* create a new SFColor object */
3202 newSFObject = JS_ConstructObjectFw(cx,&SFColorClass,NULL, newMFObject);
3203 if ((SFRPptr = (SFColorNative *)JS_GetPrivateFw(cx, newSFObject)) == NULL) {
3204 ConsoleMessage ("failure in getting SF class at %s:%d\n",__FILE__,__LINE__);
3205 return;
3206 }
3207
3208 /* fill the private pointer area */
3209 fp = (float *)fp_in; SFRPptr->v.c[0] = *fp; fp_in = offsetPointer_deref(float *,fp_in,elementlen);
3210 fp = (float *)fp_in; SFRPptr->v.c[1] = *fp; fp_in = offsetPointer_deref(float *,fp_in,elementlen);
3211 fp = (float *)fp_in; SFRPptr->v.c[2] = *fp; fp_in = offsetPointer_deref(float *,fp_in,elementlen);
3212
3213 /* put this object into the MF class */
3214 if (!JS_DefineElement(cx, newMFObject, (jsint) x, OBJECT_TO_JSVAL(newSFObject),
3215 JS_GET_PROPERTY_STUB, JS_SET_PROPERTY_STUB3, JSPROP_ENUMERATE)) {
3216 printf("failure in inserting SF class at %s:%d\n",__FILE__,__LINE__);
3217 }
3218 }
3219
3220 /* set the length of this MF */
3221 SET_LENGTH (cx,newMFObject,datalen)
3222
3223 /* set the global variable with this new MF object */
3224 SET_EVENTIN_VALUE (cx,obj,toname,newMFObject)
3225
3226 /* run the function */
3227 COMPILE_FUNCTION_IF_NEEDED_SET(toname,kind)
3228 RUN_FUNCTION(toname)
3229 break;
3230 }
3231
3232 case FIELDTYPE_MFVec2f: {
3233 JSObject *newMFObject;
3234 JSObject *newSFObject;
3235 SFVec2fNative *SFRPptr;
3236 float *fp, *fp_in=(float *)Data;
3237
3238 /* create a new MFVec2f object... */
3239 newMFObject = JS_ConstructObjectFw(cx, &MFVec2fClass, NULL ,JS_GetParentFw(cx, obj));
3240 ADD_ROOT (cx, newMFObject)
3241
3242 /* define the "length" property for this object */
3243 DEFINE_LENGTH_NORV(cx,newMFObject,datalen)
3244
3245 /* fill in private pointer area */
3246 elementlen = (int) sizeof (float);
3247 for (x=0; x<datalen; x++) {
3248 /* create a new SFVec2f object */
3249 newSFObject = JS_ConstructObjectFw(cx,&SFVec2fClass,NULL, newMFObject);
3250 if ((SFRPptr = (SFVec2fNative *)JS_GetPrivateFw(cx, newSFObject)) == NULL) {
3251 ConsoleMessage ("failure in getting SF class at %s:%d\n",__FILE__,__LINE__);
3252 return;
3253 }
3254
3255 /* fill the private pointer area */
3256 fp = (float *)fp_in; SFRPptr->v.c[0] = *fp; fp_in = offsetPointer_deref(float *,fp_in,elementlen);
3257 fp = (float *)fp_in; SFRPptr->v.c[1] = *fp; fp_in = offsetPointer_deref(float *,fp_in,elementlen);
3258
3259 /* put this object into the MF class */
3260 if (!JS_DefineElement(cx, newMFObject, (jsint) x, OBJECT_TO_JSVAL(newSFObject),
3261 JS_GET_PROPERTY_STUB, JS_SET_PROPERTY_STUB3, JSPROP_ENUMERATE)) {
3262 ConsoleMessage("failure in inserting SF class at %s:%d\n",__FILE__,__LINE__);
3263 }
3264 }
3265
3266 /* set the length of this MF */
3267 SET_LENGTH (cx,newMFObject,datalen)
3268
3269 /* set the global variable with this new MF object */
3270 SET_EVENTIN_VALUE (cx,obj,toname,newMFObject)
3271
3272 /* run the function */
3273 COMPILE_FUNCTION_IF_NEEDED_SET(toname,kind)
3274 RUN_FUNCTION(toname)
3275 break;
3276 }
3277
3278
3279 case FIELDTYPE_MFFloat: {
3280 JSObject *newMFObject;
3281 jsval newjsval;
3282 float *fp, *fp_in=(float *)Data;
3283 /* create a new MFFloat object... */
3284 newMFObject = JS_ConstructObjectFw(cx, &MFFloatClass, NULL ,JS_GetParentFw(cx, obj));
3285 ADD_ROOT (cx, newMFObject)
3286
3287 /* define the "length" property for this object */
3288 DEFINE_LENGTH_NORV(cx,newMFObject,datalen)
3289
3290 /* fill in private pointer area */
3291 elementlen = (int) sizeof (float);
3292 for (x=0; x<datalen; x++) {
3293 /* create a new SFFloat object */
3294
3295 fp = (float *)fp_in;
3296 JS_NewNumberValue(cx,(double)*fp,&newjsval);
3297 fp_in = offsetPointer_deref(float *,fp_in,elementlen);
3298
3299 /* put this object into the MF class */
3300 if (!JS_DefineElement(cx, newMFObject, (jsint) x, newjsval,
3301 JS_GET_PROPERTY_STUB, JS_SET_PROPERTY_STUB3, JSPROP_ENUMERATE)) {
3302 printf("failure in inserting SF class at %s:%d\n",__FILE__,__LINE__);
3303 }
3304 }
3305
3306 /* set the length of this MF */
3307 SET_LENGTH (cx,newMFObject,datalen)
3308
3309 /* set the global variable with this new MF object */
3310 SET_EVENTIN_VALUE (cx,obj,toname,newMFObject)
3311
3312 /* run the function */
3313 COMPILE_FUNCTION_IF_NEEDED_SET(toname,kind)
3314 RUN_FUNCTION(toname)
3315 break;
3316 }
3317 case FIELDTYPE_MFTime: {
3318 JSObject *newMFObject;
3319 jsval newjsval;
3320 double *dp, *dp_in=(double *)Data;
3321
3322 /* create a new MFTime object... */
3323 newMFObject = JS_ConstructObjectFw(cx, &MFTimeClass, NULL ,JS_GetParentFw(cx, obj));
3324 ADD_ROOT (cx, newMFObject)
3325
3326 /* define the "length" property for this object */
3327 DEFINE_LENGTH_NORV(cx,newMFObject,datalen)
3328
3329 /* fill in private pointer area */
3330 elementlen = (int) sizeof (double);
3331 for (x=0; x<datalen; x++) {
3332 /* create a new SFTime object */
3333
3334 dp = (double *)dp_in;
3335 JS_NewNumberValue(cx,(double)*dp,&newjsval);
3336 dp_in = offsetPointer_deref(double *,dp_in,elementlen);
3337
3338 /* put this object into the MF class */
3339 if (!JS_DefineElement(cx, newMFObject, (jsint) x, newjsval,
3340 JS_GET_PROPERTY_STUB, JS_SET_PROPERTY_STUB3, JSPROP_ENUMERATE)) {
3341 printf("failure in inserting SF class at %s:%d\n",__FILE__,__LINE__);
3342 }
3343 }
3344
3345 /* set the length of this MF */
3346 SET_LENGTH (cx,newMFObject,datalen)
3347
3348 /* set the global variable with this new MF object */
3349 SET_EVENTIN_VALUE (cx,obj,toname,newMFObject)
3350
3351 /* run the function */
3352 COMPILE_FUNCTION_IF_NEEDED_SET(toname,kind)
3353 RUN_FUNCTION(toname)
3354 break;
3355 }
3356 case FIELDTYPE_MFInt32: {
3357 JSObject *newMFObject;
3358 jsval newjsval;
3359 int *ip, *ip_in=(int *)Data;
3360
3361 /* create a new MFInt32 object... */
3362 newMFObject = JS_ConstructObjectFw(cx, &MFInt32Class, NULL ,JS_GetParentFw(cx, obj));
3363 ADD_ROOT (cx, newMFObject)
3364
3365 /* define the "length" property for this object */
3366 DEFINE_LENGTH_NORV(cx,newMFObject,datalen)
3367
3368 /* fill in private pointer area */
3369 elementlen = (int) sizeof (float);
3370 for (x=0; x<datalen; x++) {
3371 /* create a new SFInt32 object */
3372
3373 ip = (int *)ip_in;
3374 newjsval = INT_TO_JSVAL((int)*ip);
3375 ip_in = offsetPointer_deref(int *,ip_in,elementlen);
3376
3377 /* put this object into the MF class */
3378 if (!JS_DefineElement(cx, newMFObject, (jsint) x, newjsval,
3379 JS_GET_PROPERTY_STUB, JS_SET_PROPERTY_STUB3, JSPROP_ENUMERATE)) {
3380 printf("failure in inserting SF class at %s:%d\n",__FILE__,__LINE__);
3381 }
3382 }
3383
3384 /* set the length of this MF */
3385 SET_LENGTH (cx,newMFObject,datalen)
3386
3387 /* set the global variable with this new MF object */
3388 SET_EVENTIN_VALUE (cx,obj,toname,newMFObject)
3389
3390 /* run the function */
3391 COMPILE_FUNCTION_IF_NEEDED_SET(toname,kind)
3392 RUN_FUNCTION(toname)
3393 break;
3394 }
3395 case FIELDTYPE_MFString: {
3396 JSObject *newMFObject;
3397 jsval newjsval;
3398 struct Uni_String * *ip_in=(struct Uni_String **)Data;
3399
3400 /* create a new MFString object... */
3401 newMFObject = JS_ConstructObjectFw(cx, &MFStringClass, NULL ,JS_GetParentFw(cx, obj));
3402 ADD_ROOT (cx, newMFObject)
3403
3404 /* Data points to a Uni_String */
3405 uniptr = (struct Uni_String **) ip_in;
3406
3407 /* define the "length" property for this object */
3408 DEFINE_LENGTH_NORV(cx,newMFObject,datalen)
3409
3410 /* fill in private pointer area */
3411 for (x=0; x<datalen; x++) {
3412 /* create a new SFString object */
3413
3414 chptr = uniptr[x]->strptr;
3415 newjsval = STRING_TO_JSVAL( JS_NewStringCopyZ(cx,chptr));
3416
3417 /* put this object into the MF class */
3418 if (!JS_DefineElement(cx, newMFObject, (jsint) x, newjsval,
3419 JS_GET_PROPERTY_STUB, JS_SET_PROPERTY_STUB3, JSPROP_ENUMERATE)) {
3420 printf("failure in inserting SF class at %s:%d\n",__FILE__,__LINE__);
3421 }
3422 }
3423
3424 /* set the length of this MF */
3425 SET_LENGTH (cx,newMFObject,datalen)
3426
3427 /* set the global variable with this new MF object */
3428 SET_EVENTIN_VALUE (cx,obj,toname,newMFObject)
3429
3430 /* run the function */
3431 COMPILE_FUNCTION_IF_NEEDED_SET(toname,kind)
3432 RUN_FUNCTION(toname)
3433 break;
3434 }
3435 case FIELDTYPE_MFNode: {
3436 JSObject *newMFObject;
3437 jsval newjsval;
3438 void **ip, **ip_in=(void **)Data;
3439 /* create a new MFNode object... */
3440 newMFObject = JS_ConstructObjectFw(cx, &MFNodeClass, NULL ,JS_GetParentFw(cx, obj));
3441 ADD_ROOT (cx, newMFObject)
3442
3443 /* define the "length" property for this object */
3444 DEFINE_LENGTH_NORV(cx,newMFObject,datalen)
3445
3446 /* fill in private pointer area */
3447 elementlen = (int) sizeof (void *);
3448 for (x=0; x<datalen; x++) {
3449 ip = ip_in;
3450 newjsval = PRIVATE_TO_JSVAL((void*)*ip); //July 4, 2018 SM1 routing MFNode doesn't work
3451 ip_in = offsetPointer_deref(void **,ip_in,elementlen);
3452
3453 /* put this object into the MF class */
3454 if (!JS_DefineElement(cx, newMFObject, (jsint) x, newjsval,
3455 JS_GET_PROPERTY_STUB, JS_SET_PROPERTY_STUB3, JSPROP_ENUMERATE)) {
3456 printf("failure in inserting SF class at %s:%d\n",__FILE__,__LINE__);
3457 }
3458 }
3459
3460 /* set the length of this MF */
3461 SET_LENGTH (cx,newMFObject,datalen)
3462
3463 /* set the global variable with this new MF object */
3464 SET_EVENTIN_VALUE (cx,obj,toname,newMFObject)
3465
3466 /* run the function */
3467 COMPILE_FUNCTION_IF_NEEDED_SET(toname,kind)
3468 RUN_FUNCTION(toname)
3469 break;
3470 }
3471
3472 case FIELDTYPE_SFImage: {
3473 JSObject *newMFObject;
3474 jsval newjsval;
3475 int *ip_in=(int *)Data;
3476
3477 /* create a new MFNode object... */
3478 newMFObject = JS_ConstructObjectFw(cx, &SFImageClass, NULL ,JS_GetParentFw(cx, obj));
3479 ADD_ROOT (cx, newMFObject)
3480
3481 /* define the "length" property for this object */
3482 DEFINE_LENGTH_NORV(cx,newMFObject,datalen)
3483
3484 /* fill in private pointer area */
3485 for (x=0; x<datalen; x++) {
3486 newjsval = INT_TO_JSVAL(ip_in[x]);
3487 /* put this object into the MF class */
3488 if (!JS_DefineElement(cx, newMFObject, (jsint) x, newjsval,
3489 JS_GET_PROPERTY_STUB, JS_SET_PROPERTY_STUB3, JSPROP_ENUMERATE)) {
3490 printf("failure in inserting SF class at %s:%d\n",__FILE__,__LINE__);
3491 }
3492 }
3493
3494 /* set the length of this MF */
3495 SET_LENGTH (cx,newMFObject,datalen)
3496
3497 /* set the global variable with this new MF object */
3498 SET_EVENTIN_VALUE (cx,obj,toname,newMFObject)
3499
3500 /* run the function */
3501 COMPILE_FUNCTION_IF_NEEDED_SET(toname,kind)
3502 RUN_FUNCTION(toname)
3503
3504 break;
3505 }
3506
3507 default: {
3508 printf ("setMFElement, SHOULD NOT DISPLAY THIS\n");
3509 strcat (scriptline,"(");
3510 }
3511 }
3512 } //Scope B
3513 } //Scope A
3514
3515}
3516
3517} //extern "C"
3518
3519/****************************************************************/
3520/* sets a SFVec3f and SFColor and SFVec3d */
3521/* and SFRotation and SFVec2fin a script */
3522/* */
3523/* all *Native types have the same structure of the struct - */
3524/* we are just looking for the pointer, thus we can handle */
3525/* multi types here */
3526/* sets a SFVec3f and SFColor in a script */
3527/****************************************************************/
3528
3529/* get a pointer to the internal data for this object, or return NULL on error */
3530void **getInternalDataPointerForJavascriptObject(JSContext *cx, JSObject *obj, int tnfield, int *iflag) {
3531 char scriptline[256];
3532 void *_privPtr;
3533 JSObject *sfObj;
3534 jsval retval;
3535 struct CRjsnameStruct *JSparamnames = getJSparamnames();
3536
3537 /* get the variable name to hold the incoming value */
3538 //sprintf (scriptline,"__eventIn_Value_%s", JSparamnames[tnfield].name);
3539 scriptline[0] = 0;
3540 if(JSparamnames[tnfield].kind == PKW_inputOnly)
3541 strcat(scriptline,"__eventIn_Value_");
3542 strcat(scriptline,JSparamnames[tnfield].name);
3543 #ifdef SETFIELDVERBOSE
3544 printf ("getInternalDataPointerForJavascriptObject: line %s\n",scriptline);
3545 #endif
3546
3547 if (!JS_GetProperty(cx,obj,scriptline,&retval)){
3548 //if you forgot to put both an inputOnly or inputOutput field AND
3549 // you forgot to define a function() with the same name
3550 // then you won't have any objects
3551 // if you didn't have a field then ROUTE would complain, unless directAccess
3552 printf ("JS_GetProperty failed in set_one_MultiElementType.\n");
3553 //return NULL;
3554 }
3555 *iflag = 1;
3556 //if (!JSVAL_IS_OBJECT(retval)){
3557 if(!retval.isObject()){
3558 // you don't have an inputOnly static object with this name (but might have a field static object,
3559 //return NULL;
3560 //could be inputOutput which has a norma field name
3561 *iflag = 0;
3562 if (!JS_GetProperty(cx,obj,JSparamnames[tnfield].name,&retval)){
3563 //you may have an inputOutput field, with the plane name
3564 printf ("no field for eventIn function: %s\n",JSparamnames[tnfield].name);
3565 return NULL;
3566 }
3567 //if (!JSVAL_IS_OBJECT(retval)){
3568 if(!retval.isObject()){
3569 printf ("no field for eventIn function: %s\n",JSparamnames[tnfield].name);
3570 return NULL;
3571 }
3572 *iflag = 2;
3573 }
3574
3575 sfObj = JSVAL_TO_OBJECT(retval);
3576
3577 if ((_privPtr = JS_GetPrivateFw(cx, sfObj)) == NULL)
3578 printf("JS_GetPrivate failed set_one_MultiElementType.\n");
3579
3580 if (_privPtr == NULL) return NULL;
3581
3582 /* what kind of class of object is this? */
3583
3584 /* we look at EVERY kind of native class found in "jsNative.h" even
3585 if it may not be ever used here */
3586
3587 if (JS_InstanceOf(cx, sfObj, &SFVec3fClass, NULL)) {
3588 SFVec3fNative *me = (SFVec3fNative *)_privPtr;
3589 return (void **) &me->v;
3590
3591 } else if (JS_InstanceOf(cx, sfObj, &SFVec3dClass, NULL)) {
3592 SFVec3dNative *me = (SFVec3dNative *)_privPtr;
3593 return (void **) &me->v;
3594
3595 } else if (JS_InstanceOf(cx, sfObj, &SFRotationClass, NULL)) {
3596 SFRotationNative *me = (SFRotationNative *)_privPtr;
3597 return (void **) &me->v;
3598
3599 } else if (JS_InstanceOf(cx, sfObj, &SFVec2fClass, NULL)) {
3600 SFVec2fNative *me = (SFVec2fNative *)_privPtr;
3601 return (void **) &me->v;
3602
3603 } else if (JS_InstanceOf(cx, sfObj, &SFColorClass, NULL)) {
3604 SFColorNative *me = (SFColorNative *)_privPtr;
3605 return (void **) &me->v;
3606
3607 } else if (JS_InstanceOf(cx, sfObj, &SFColorRGBAClass, NULL)) {
3608 SFColorRGBANative *me = (SFColorRGBANative *)_privPtr;
3609 return (void **) &me->v;
3610
3611 } else if (JS_InstanceOf(cx, sfObj, &SFVec4fClass, NULL)) {
3612 SFVec4fNative *me = (SFVec4fNative *)_privPtr;
3613 return (void **) &me->v;
3614
3615 } else if (JS_InstanceOf(cx, sfObj, &SFVec4dClass, NULL)) {
3616 SFVec4dNative *me = (SFVec4dNative *)_privPtr;
3617 return (void **) &me->v;
3618
3619 } else if (JS_InstanceOf(cx, sfObj, &SFNodeClass, NULL)) {
3620 SFNodeNative *me = (SFNodeNative *)_privPtr;
3621 return (void **) &me->handle;;
3622 //JAS return (void **) &me->v;
3623
3624 } else if (JS_InstanceOf(cx, sfObj, &SFImageClass, NULL)) {
3625 //SFImageNative *me = (SFImageNative *)_privPtr;
3626 //JAS return (void **) &me->v;
3627
3628 }
3629
3630 ConsoleMessage ("getInternalDataPointerForJavascriptObject malfunction");
3631
3632 return NULL;
3633}
3634
3635
3636
3637/* really do the individual set; used by script routing and EAI sending to a script
3638 Dec 2017 - You may have a inpoutOutput field you want to route values to
3639 and not have any inputOnly function() associated with the field
3640 for this scenario you want to check first if there's a function,
3641 and if so do some extra work. If not so be it.
3642 set_one_multielementtype is for SFVecxx, SFColorxxxx, SFNode, SFRotation
3643*/
3644extern "C" {
3645void sm_set_one_MultiElementType (int tonode, int tnfield, void *Data, int dataLen ) {
3646 char scriptline[256];
3647 JSContext *cx;
3648 JSObject *obj;
3649 void **pp;
3650 int iflag, kind, toname;
3651 ttglobal tg = gglobal();
3652 ppJScript p = (ppJScript)tg->JScript.prv;
3653
3654 struct CRscriptStruct *ScriptControl; // = getScriptControl();
3655 struct CRjsnameStruct *JSparamnames = getJSparamnames();
3656
3657 /* get context and global object for this script */
3658 ScriptControl = getScriptControlIndex(tonode);
3659 if (ScriptControl->thisScriptType == NOSCRIPT) return;
3660 cx = (JSContext*)ScriptControl->cx;
3661 obj = (JSObject*)ScriptControl->glob;
3662
3663 { // Scope A for our various stack objects (JSAutoRequest, RootedObject), so they all go
3664 // out of scope before we JS_DestroyContext.
3665 JSAutoRequest ar(cx); // In practice, you would want to exit this any
3666 // time you're spinning the event loop
3667 { // Scope B for JSAutoCompartment
3668 JSAutoCompartment ac(cx, obj);
3669 toname = tnfield;
3670 kind = JSparamnames[toname].kind; // PKW_inputOnly;
3671 if (SM_method() == 2) {
3672 int type, iifield, * valueChanged, ifound, datatype;
3673 union anyVrml* value;
3674 char* fieldname;
3675 struct Shader_Script* script = ScriptControl->script;
3676
3677 fieldname = JSparamnames[toname].name;
3678 datatype = JSparamnames[toname].type;
3679
3680 //step 1 update the fieldvalue
3681 ifound = getFieldFromScript(script, fieldname, &type, &kind, &iifield, &value, &valueChanged);
3682 if (ifound && type == datatype && isSFType(type)) {
3683 //we have an SF field, and sf coming in, we'll call our field LHS and incoming RHS
3684 shallow_copy_field(type, (union anyVrml*)Data, value);
3685 (*valueChanged) = 1;
3686 }
3687 else {
3688 ConsoleMessage("sm_set_one_MultiElementType did not find field %s type %d\n", fieldname, datatype);
3689 return;
3690 }
3691 //step 2 run the eventIn if it exists
3692 SET_JS_TICKTIME;
3693 FW_MaybeGC("TT", cx);
3694
3695 //printf("<SOMET TT");
3696 //JS_GC(p->runtime);
3697 //printf(">");
3698 //compile also pushes the field val onto call stack
3699 JSScript* hscript = NULL;
3700 JS::RootedScript rscript(cx, hscript);
3701
3702 //COMPILE_FUNCTION_IF_NEEDED_SET(toname, kind);
3703 {
3704 //#define COMPILE_FUNCTION_IF_NEEDED_SET(tnfield,kind)
3705 int tnfield = toname;
3706 if (JSparamnames[tnfield].eventInFunction == NULL || TRUE) {
3707 if (kind == PKW_inputOutput)
3708 sprintf(scriptline, "set_%s(%s,__eventInTickTime)", JSparamnames[tnfield].name, JSparamnames[tnfield].name);
3709 else /* PKW_inputOnly */
3710 sprintf(scriptline, "%s(%s%s,__eventInTickTime)", JSparamnames[tnfield].name, "__eventIn_Value_", JSparamnames[tnfield].name);
3711 //printf ("compiling function %s for type %d\n",scriptline,JSparamnames[tnfield].type);
3712 hscript = JS_CompileScript(
3713 cx, obj, scriptline, strlen(scriptline), "compile eventIn", 1);
3714 JSparamnames[tnfield].eventInFunction = (void*)hscript;
3715 //printf("sizeof(JS_HEAP)=%ld\n", (int)sizeof(sscript));
3716 //JS_AddNamedScriptRoot(cx, &hscript, JSparamnames[tnfield].name);
3717 if (0) if (!JS_AddObjectRoot(cx, (JSObject**)(&JSparamnames[tnfield].eventInFunction))) {
3718 printf("JS_AddObjectRoot failed for compilation of script \"%s\" at %s:%d.\n", scriptline, __FILE__, __LINE__);
3719 return;
3720 }
3721 }
3722
3723 }
3724 FW_MaybeGC("SOMET CF", cx);
3725
3726 //printf("<SOMET CF");
3727 //JS_GC(p->runtime);
3728 //printf(">");
3729 //RUN_FUNCTION(toname);
3730 {
3731 //#define RUN_FUNCTION(tnfield)
3732 int tnfield = toname;
3733 {
3734 jsval zimbo;
3735 if (!JS_ExecuteScript(cx, obj, (JSScript*)JSparamnames[tnfield].eventInFunction, &zimbo)) {
3736 printf("eventIn %s failed to complete successfully, in FreeWRL code %s:%d\n", JSparamnames[tnfield].name, __FILE__, __LINE__);
3737 /* printf ("myThread is %u\n",pthread_self());*/
3738 }
3739 }
3740
3741 }
3742 FW_MaybeGC("SOMET RF", cx);
3743
3744 //printf("<SOMET RF");
3745 //JS_GC(p->runtime);
3746 //printf(">");
3747 return;
3748
3749 }
3750 /* copy over the data from the VRML side into the script variable. */
3751 iflag = 0;
3752 pp = getInternalDataPointerForJavascriptObject(cx, obj, tnfield, &iflag);
3753 if (pp == NULL) {
3754 //no script function with this name - you might be routing to an inputOutput field
3755 printf("function not found\n");
3756 return;
3757 }
3758 memcpy(pp, Data, dataLen);
3759 /* printf ("set_one_MultiElementType, dataLen %d, sizeof(double) %d\n",dataLen, sizeof(double));
3760 printf ("and, sending the data to pointer %p\n",pp); */
3761
3762 //if we added a __eventIn_Value_<fieldname> for inputOnly field
3763 /* set the time for this script */
3764 SET_JS_TICKTIME
3765 /* is the function compiled yet? */
3766 COMPILE_FUNCTION_IF_NEEDED_SET(tnfield, kind)
3767
3768 RUN_FUNCTION(tnfield)
3769
3770 } // Scope B
3771 } // Scope A
3772
3773}
3774
3775int sm_runQueuedDirectOutputs(){
3776 //stub for SM and STUBS (DUK has it)
3777
3778 return FALSE;
3779}
3780} //extern "C"
3781
3782#endif //defined(JS_SMCPP)
3783#endif //JAVASCRIPT_SM
3784
3785
Definition Viewer.h:141