ScriptBasic

Extension Modules => Extension Modules => Topic started by: Support on October 18, 2017, 10:25:25 PM

Title: Script BASIC JavaScript Extension Module (Linux)
Post by: Support on October 18, 2017, 10:25:25 PM
The Script BASIC JS extension module for Linux is based on the Cesanta's V7 JavaScript Engine (https://github.com/cesanta/v7). It claims to be the world's smallest footprint JavaScript 5.1 compatible embeddable engine. There are no other dependencies required.

JavaScript Programmers Guide (https://developer.mozilla.org/en-US/docs/Web/JavaScript)

V7 JavaScript Documentation (https://docs.cesanta.com/v7/master/)

Features:

Note: The \ character is used by Script BASIC as a string escape character and must be inserted in the JavaScript code to make the \ just text. Loading JavaScript code from a file doesn't have the escape character issue and can be run verbatim.

js.inc
Code: Script BASIC
  1. MODULE JS
  2.  
  3. ' CORE
  4. DECLARE SUB      js_create                  ALIAS "js_create"                 LIB "js"
  5. DECLARE SUB      js_destroy                 ALIAS "js_destroy"                LIB "js"
  6. DECLARE SUB      js_get_global              ALIAS "js_get_global"             LIB "js"
  7. DECLARE SUB      js_get_this                ALIAS "js_get_this"               LIB "js"
  8. DECLARE SUB      js_get_arguments           ALIAS "js_get_arguments"          LIB "js"
  9. DECLARE SUB      js_arg                     ALIAS "js_arg"                    LIB "js"
  10. DECLARE SUB      js_argc                    ALIAS "js_argc"                   LIB "js"
  11. DECLARE SUB      js_own                     ALIAS "js_own"                    LIB "js"
  12. DECLARE SUB      js_disown                  ALIAS "js_disown"                 LIB "js"
  13. DECLARE SUB      js_set_gc_enabled          ALIAS "js_set_gc_enabled"         LIB "js"
  14. DECLARE SUB      js_interrupt               ALIAS "js_interrupt"              LIB "js"
  15. DECLARE SUB      js_get_parser_error        ALIAS "js_get_parser_error"       LIB "js"
  16.  
  17. ' PRIMITIVES
  18. DECLARE SUB      js_mk_number               ALIAS "js_mk_number"              LIB "js"
  19. DECLARE SUB      js_get_double              ALIAS "js_get_double"             LIB "js"
  20. DECLARE SUB      js_get_int                 ALIAS "js_get_int"                LIB "js"
  21. DECLARE SUB      js_is_number               ALIAS "js_is_number"              LIB "js"
  22. DECLARE SUB      js_mk_boolean              ALIAS "js_mk_boolean"             LIB "js"
  23. DECLARE SUB      js_get_bool                ALIAS "js_get_bool"               LIB "js"
  24. DECLARE SUB      js_is_boolean              ALIAS "js_is_boolean"             LIB "js"
  25. DECLARE SUB      js_mk_null                 ALIAS "js_mk_null"                LIB "js"
  26. DECLARE SUB      js_is_null                 ALIAS "js_is_null"                LIB "js"
  27. DECLARE SUB      js_mk_undefined            ALIAS "js_mk_undefined"           LIB "js"
  28. DECLARE SUB      js_is_undefined            ALIAS "js_is_undefined"           LIB "js"
  29. DECLARE SUB      js_mk_foreign              ALIAS "js_mk_foreign"             LIB "js"
  30. DECLARE SUB      js_get_ptr                 ALIAS "js_get_ptr"                LIB "js"
  31. DECLARE SUB      js_is_foreign              ALIAS "js_is_foreign"             LIB "js"
  32.  
  33. ' STRINGS
  34. DECLARE SUB      js_mk_string               ALIAS "js_mk_string"              LIB "js"
  35. DECLARE SUB      js_is_string               ALIAS "js_is_string"              LIB "js"
  36. DECLARE SUB      js_get_string              ALIAS "js_get_string"             LIB "js"
  37. DECLARE SUB      js_get_cstring             ALIAS "js_get_cstring"            LIB "js"
  38.  
  39. ' OBJECTS
  40. DECLARE SUB      js_mk_object               ALIAS "js_mk_object"              LIB "js"
  41. DECLARE SUB      js_is_object               ALIAS "js_is_object"              LIB "js"
  42. DECLARE SUB      js_get_proto               ALIAS "js_get_proto"              LIB "js"
  43. DECLARE SUB      js_set_proto               ALIAS "js_set_proto"              LIB "js"
  44. DECLARE SUB      js_get                     ALIAS "js_get"                    LIB "js"
  45. DECLARE SUB      js_def                     ALIAS "js_def"                    LIB "js"
  46. DECLARE SUB      js_set                     ALIAS "js_set"                    LIB "js"
  47. DECLARE SUB      js_del                     ALIAS "js_del"                    LIB "js"
  48. DECLARE SUB      js_init_prop_iter_ctx      ALIAS "js_init_prop_iter_ctx"     LIB "js"
  49. DECLARE SUB      js_next_prop               ALIAS "js_next_prop"              LIB "js"
  50. DECLARE SUB      js_destruct_prop_iter_ctx  ALIAS "js_destruct_prop_iter_ctx" LIB "js"
  51. DECLARE SUB      js_is_instanceof           ALIAS "js_is_instanceof"          LIB "js"
  52. DECLARE SUB      js_is_instanceof_v         ALIAS "js_is_instanceof_v"        LIB "js"
  53.  
  54. ' ARRAYS
  55. DECLARE SUB      js_mk_array                ALIAS "js_mk_array"               LIB "js"
  56. DECLARE SUB      js_is_array                ALIAS "js_is_array"               LIB "js"
  57. DECLARE SUB      js_array_length            ALIAS "js_array_length"           LIB "js"
  58. DECLARE SUB      js_array_push              ALIAS "js_array_push"             LIB "js"
  59. DECLARE SUB      js_array_get               ALIAS "js_array_get"              LIB "js"
  60. DECLARE SUB      js_array_set               ALIAS "js_array_set"              LIB "js"
  61. DECLARE SUB      js_array_del               ALIAS "js_array_del"              LIB "js"
  62.  
  63. ' EXECUTION
  64. DECLARE SUB      js_exec                    ALIAS "js_exec"                   LIB "js"
  65. DECLARE SUB      js_exec_file               ALIAS "js_exec_file"              LIB "js"
  66. DECLARE SUB      js_apply                   ALIAS "js_apply"                  LIB "js"
  67. DECLARE SUB      js_parse_json              ALIAS "js_parse_json"             LIB "js"
  68. DECLARE SUB      js_parse_json_file         ALIAS "js_parse_json_file"        LIB "js"
  69.  
  70. 'REGEX
  71. DECLARE SUB      js_mk_regexp               ALIAS "js_mk_regexp"              LIB "js"
  72. DECLARE SUB      js_is_regexp               ALIAS "js_is_regexp"              LIB "js"
  73.  
  74. ' UTILITY
  75. DECLARE SUB      js_stringify               ALIAS "js_stringify"              LIB "js"
  76. DECLARE SUB      js_println                 ALIAS "js_println"                LIB "js"
  77.  
  78. DECLARE SUB      SB_shifts                  ALIAS "SB_shifts"                 LIB "js"
  79. DECLARE COMMAND  js_iif                     ALIAS "js_iif"                    LIB "js"
  80.  
  81.  
  82. ' JS Global Module Variables
  83. OBJ = 0
  84. SYS = 0
  85.  
  86. ' Stringify Modes
  87. DEFAULT = 0
  88. JSON    = 1
  89. DEBUG   = 2
  90.  
  91. ' Property Attribute Support
  92.  
  93. CONST V7_PROPERTY_NON_WRITABLE              = 1
  94. CONST V7_PROPERTY_NON_ENUMERABLE            = 2
  95. CONST V7_PROPERTY_NON_CONFIGURABLE          = 4
  96. CONST V7_PROPERTY_GETTER                    = 8
  97. CONST V7_PROPERTY_SETTER                    = 16
  98. CONST _V7_PROPERTY_HIDDEN                   = 32
  99. CONST _V7_PROPERTY_OFF_HEAP                 = 64
  100. CONST _V7_PROPERTY_USER_DATA_AND_DESTRUCTOR = 128
  101. CONST _V7_DESC_PRESERVE_VALUE               = 256
  102. CONST _V7_DESC_MASK                         = &HFFFF
  103.  
  104. CONST PROPERTY_DEFAULT = 0
  105.  
  106. ' TRUE or FALSE. Whether the property's value can be set.
  107. FUNCTION WRITABLE(v)
  108.   IF v THEN
  109.     WRITABLE = PROPERTY_DEFAULT
  110.   ELSE
  111.     WRITABLE = V7_PROPERTY_NON_WRITABLE
  112.   END IF
  113. END FUNCTION
  114.  
  115. ' TRUE or FALSE. Whether the property shows in some loop constructs.
  116. FUNCTION ENUMERABLE(v)
  117.   IF v THEN
  118.     ENUMERABLE = PROPERTY_DEFAULT
  119.   ELSE
  120.     ENUMERABLE = V7_PROPERTY_NON_ENUMERABLE
  121.   END IF
  122. END FUNCTION
  123.  
  124. ' TRUE or FALSE. Whether the property can be deleted and whether its attributes can be changed.
  125. FUNCTION CONFIGURABLE(v)
  126.   IF v THEN
  127.     CONFIGURABLE = PROPERTY_DEFAULT
  128.   ELSE
  129.     CONFIGURABLE = V7_PROPERTY_NON_CONFIGURABLE
  130.   END IF
  131. END FUNCTION
  132.  
  133. ' TRUE or FALSE. When a property is accessed the value is generated by calling a function implicitly.
  134. FUNCTION GETTER(v)
  135.   IF v THEN
  136.     GETTER = V7_PROPERTY_GETTER
  137.   ELSE
  138.     GETTER = FALSE
  139.   END IF
  140. END FUNCTION
  141.  
  142. ' TRUE or FALSE. When a property is set it will implicitly call a function and pass a
  143. ' value as argument, and the return value of the function is set to the property.
  144. FUNCTION SETTER(v)
  145.   IF v THEN
  146.     SETTER = V7_PROPERTY_SETTER
  147.   ELSE
  148.     SETTER = FALSE
  149.   END IF
  150. END FUNCTION
  151.  
  152. FUNCTION PRESERVE_VALUE
  153.     PRESERVE_VALUE = _V7_DESC_PRESERVE_VALUE
  154. END FUNCTION
  155.  
  156. FUNCTION HIDDEN(v)
  157.   IF v THEN
  158.     HIDDEN = V7_PROPERTY_HIDDEN
  159.   ELSE
  160.     HIDDEN = FALSE
  161.   END IF
  162. END FUNCTION
  163.  
  164. FUNCTION OFF_HEAP(v)
  165.   IF v THEN
  166.     OFF_HEAP = _V7_PROPERTY_OFF_HEAP
  167.   ELSE
  168.     OFF_HEAP = FALSE
  169.   END IF
  170. END FUNCTION
  171.  
  172.  
  173. ' JS API Function Wrappers
  174.  
  175. ' Create V7 instance
  176. FUNCTION CREATE
  177.   OBJ = js_create()
  178.   SYS = js_get_global(OBJ)
  179.   CREATE = OBJ
  180. END FUNCTION
  181.  
  182. ' Destroy V7 instance
  183. SUB DESTROY
  184.   js_destroy(OBJ)
  185.   UNDEF OBJ
  186. END SUB
  187.  
  188. ' Return root level (`global`) object of the given V7 instance
  189. FUNCTION GET_GLOBAL
  190.   GET_GLOBAL = js_get_global(OBJ)
  191. END FUNCTION
  192.  
  193. ' Return current `this` object
  194. FUNCTION GET_THIS
  195.   GET_THIS = js_get_this(OBJ)
  196. END FUNCTION
  197.  
  198. ' Return current `arguments` array
  199. FUNCTION GET_ARGUMENTS
  200.   GET_ARGUMENTS = js_get_arguments(OBJ)
  201. END FUNCTION
  202.  
  203. ' Return i-th argument
  204. FUNCTION ARG(i)
  205.   ARG = js_arg(OBJ, i)
  206. END FUNCTION
  207.  
  208. ' Return the length (`count`) of `arguments`
  209. FUNCTION ARGC
  210.   ARGC = js_argc(OBJ)
  211. END FUNCTION
  212.  
  213. ' Tells the GC about a JS value variable/field owned by `C` code.
  214. SUB OWN(v)
  215.   js_own(OBJ, v)
  216. END SUB
  217.  
  218. ' User code should also explicitly disown the variables with v7_disown
  219. ' once it goes out of scope or the structure containing the v7_val_t field is freed.
  220. ' Returns 1 if value is found, 0 otherwise
  221. FUNCTION DISOWN(v)
  222.   DISOWN = js_disown(OBJ, v)
  223. END FUNCTION
  224.  
  225. ' Enable or disable GC
  226. SUB SET_GC_ENABLED(enabled)
  227.   js_set_gc_enabled(OBJ, enabled)
  228. END SUB
  229.  
  230. ' It sets a flag that will cause the interpreter to throw an Interrupted Error
  231. SUB INTERRUPT
  232.   js_interrupt(OBJ)
  233. END SUB
  234.  
  235. ' Returns last parser error message
  236. FUNCTION GET_ERROR
  237.   GET_ERROR = js_get_parser_error(OBJ)
  238. END FUNCTION
  239.  
  240. ' Make numeric primitive value
  241. FUNCTION MK_NUMBER(num)
  242.   MK_NUMBER = js_mk_number(OBJ, num)
  243. END FUNCTION
  244.  
  245. ' Returns number value stored in `v7_val_t` as `double`
  246. FUNCTION GET_DOUBLE(v)
  247.   GET_DOUBLE = js_get_double(OBJ, v)
  248. END FUNCTION
  249.  
  250. ' Returns number value stored in `v7_val_t` as `int`. If the number
  251. ' value is not an integer, the fraction part will be discarded.
  252. FUNCTION GET_INT(v)
  253.   GET_INT = js_get_int(OBJ, v)
  254. END FUNCTION
  255.  
  256. ' Returns true if given value is a primitive number value
  257. FUNCTION IS_NUMBER(v)
  258.   IS_NUMBER = js_is_number(v)
  259. END FUNCTION
  260.  
  261. ' Make boolean primitive value (either `true` or `false`)
  262. FUNCTION MK_BOOLEAN(is_true)
  263.   MK_BOOLEAN = js_mk_boolean(OBJ, is_true)
  264. END FUNCTION
  265.  
  266. ' Returns boolean stored in `v7_val_t`: 0 for `false` or
  267. ' non-boolean, non-0 for `true`
  268. FUNCTION GET_BOOL(v)
  269.   GET_BOOL = js_get_bool(OBJ, v)
  270. END FUNCTION
  271.  
  272. ' Returns `true` if given value is a primitive boolean value
  273. FUNCTION IS_BOOLEAN(v)
  274.   IS_BOOLEAN = js_is_boolean(v)
  275. END FUNCTION
  276.  
  277. ' Make `null` primitive value
  278. FUNCTION MK_NULL
  279.   MK_NULL = js_mk_null()
  280. END FUNCTION
  281.  
  282. ' Returns true if given value is a primitive `null` value
  283. FUNCTION IS_NULL(v)
  284.   IS_NULL = js_is_null(v)
  285. END FUNCTION
  286.  
  287. ' Make `undefined` primitive value
  288. FUNCTION MK_UNDEFINED
  289.   MK_UNDEFINED = js_mk_undefined()
  290. END FUNCTION
  291.  
  292. ' Returns true if given value is a primitive `undefined` value
  293. FUNCTION IS_UNDEFINED(v)
  294.   IS_UNDEFINED = js_is_undefined(v)
  295. END FUNCTION
  296.  
  297. ' Make JavaScript value that holds C/C++ `void *` pointer
  298. FUNCTION MK_FOREIGN
  299.   MK_FOREIGN = js_mk_foreign(OBJ)
  300. END FUNCTION
  301.  
  302. ' Returns `void *` pointer stored in `v7_val_t`
  303. ' Returns NULL `undef` if the value is not a foreign pointer
  304. FUNCTION GET_PTR(v)
  305.   GET_PTR = js_get_ptr(OBJ, v)
  306. END FUNCTION
  307.  
  308. ' Returns true if given value holds `void *` pointer
  309. FUNCTION IS_FOREIGN(v)
  310.   IS_FOREIGN = js_is_foreign(v)
  311. END FUNCTION
  312.  
  313. ' Creates a string primitive value
  314. FUNCTION MK_STRING(strval)
  315.   MK_STRING = js_mk_string(OBJ, strval, LEN(strval), 1)
  316. END FUNCTION
  317.  
  318. ' Returns true if given value is a primitive string value
  319. FUNCTION IS_STRING(v)
  320.   IS_STRING = js_is_string(v)
  321. END FUNCTION
  322.  
  323. ' Returns a pointer to the string stored in `v7_val_t`
  324. FUNCTION GET_STRING(v)
  325.   GET_STRING = js_get_string(OBJ, v)
  326. END FUNCTION
  327.  
  328. ' Returns a pointer to the string stored in `v7_val_t`
  329. ' Returns NULL `undef` if the value is not a string or
  330. ' if the string is not compatible with a C string
  331. FUNCTION GET_CSTRING(v)
  332.   GET_CSTRING = js_get_cstring(OBJ, v)
  333. END FUNCTION
  334.  
  335. ' Make an empty object
  336. FUNCTION MK_OBJECT
  337.   MK_OBJECT = js_mk_object(OBJ)
  338. END FUNCTION
  339.  
  340. ' Returns true if the given value is an object or function
  341. FUNCTION IS_OBJECT(v)
  342.   IS_OBJECT = js_is_object(v)
  343. END FUNCTION
  344.  
  345. ' Get object's prototype.
  346. FUNCTION GET_PROTO(object)
  347.   GET_PROTO = js_get_proto(OBJ, object)
  348. END FUNCTION
  349.  
  350. ' Set object's prototype. Return old prototype or undefined on error
  351. FUNCTION SET_PROTO(object, proto)
  352.   SET_PROTO = js_set_proto(OBJ, object, proto)
  353. END FUNCTION
  354.  
  355. ' Lookup property `name` in object `obj`. If `obj` holds no such property,
  356. ' an `undefined` value is returned
  357. FUNCTION GETS(object, objname)
  358.   GETS = js_get(OBJ, object, objname, LEN(objname))
  359. END FUNCTION
  360.  
  361. ' Define object property, similar to JavaScript `Object.defineProperty()`
  362. FUNCTION DEF(object, objname, attr, value)
  363.   DEF = js_def(OBJ, object, objname, LEN(objname), attr, value)
  364. END FUNCTION
  365.  
  366. ' Set object property. Behaves just like JavaScript assignment
  367. FUNCTION SETS(object, objname, value)
  368.   SETS = js_set(OBJ, object, objname, LEN(objname), value)
  369. END FUNCTION
  370.  
  371. ' Delete own property `name` of the object `obj`
  372. ' Does not follow the prototype chain
  373. FUNCTION DEL(object, objname)
  374.   DEL = js_del(OBJ, object, objname, LEN(objname))
  375. END FUNCTION
  376.  
  377. ' Returns true if the object is an instance of a given constructor / class name
  378. FUNCTION IS_INSTANCEOF(object, classname)
  379.   IS_INSTANCEOF = js_is_instanceof(OBJ, object, classname)
  380. END FUNCTION
  381.  
  382. ' Returns true if the object is an instance of a given constructor object class
  383. FUNCTION IS_INSTANCEOF_V(object, objclass)
  384.   IS_INSTANCEOF_V = js_is_instanceof_v(OBJ, object, objclass)
  385. END FUNCTION
  386.  
  387. ' Custom multi-property `GET` function
  388. FUNCTION GET_PROPERTIES(object, proparray)
  389.   LOCAL objname, value, attr, propcnt
  390.   objname = ""
  391.   value = 0
  392.   attr = 0
  393.   propcnt = 1
  394.  ' UNDEF proparray
  395.  js_init_prop_iter_ctx(OBJ, object)
  396.   WHILE js_next_prop(OBJ, objname, value, attr) <> undef
  397.     proparray[propcnt, 0] = js_get_string(OBJ, objname)
  398.     proparray[propcnt, 1] = js_get_int(OBJ, value)
  399.     proparray[propcnt, 2] = attr
  400.     propcnt += 1
  401.   WEND
  402.   js_destruct_prop_iter_ctx(OBJ)
  403.   GET_PROPERTIES = propcnt - 1
  404. END FUNCTION
  405.  
  406. ' Make an empty array object
  407. FUNCTION MK_ARRAY
  408.   MK_ARRAY = js_mk_array(OBJ)
  409. END FUNCTION
  410.  
  411. ' Returns true if given value is an array object
  412. FUNCTION IS_ARRAY(object)
  413.   IS_ARRAY = js_is_array(OBJ, object)
  414. END FUNCTION
  415.  
  416. ' Returns length on an array. If `object` is not an array, 0 is returned
  417. FUNCTION ARRAY_LENGTH(object)
  418.   ARRAY_LENGTH = js_array_length(OBJ, object)
  419. END FUNCTION
  420.  
  421. ' Insert `value` in `object` at the end of the array
  422. FUNCTION ARRAY_PUSH(object, value)
  423.   ARRAY_PUSH = js_array_push(OBJ, object, value)
  424. END FUNCTION
  425.  
  426. '  Return array member at index `index`. If `index` is out of bounds, undefined is returned
  427. FUNCTION ARRAY_GET(object, index)
  428.   ARRAY_GET = js_array_get(OBJ, object, index)
  429. END FUNCTION
  430.  
  431. ' Insert value `v` into `arr` at 'index`
  432. FUNCTION ARRAY_SET(object, index, value)
  433.   ARRAY_SET = js_array_set(OBJ, object, index, value)
  434. END FUNCTION
  435.  
  436. ' Delete value in array `arr` at index `index`, if it exists
  437. SUB ARRAY_DEL(object, index)
  438.    js_array_del(OBJ, object, index)
  439. END SUB
  440.  
  441. ' Execute JavaScript `js_code`
  442. ' The result of evaluation is stored in the `return` variable
  443. ' The 'ok' argument will contain the function's execution success status flag
  444. FUNCTION EXEC(code, ok)
  445.   EXEC = js_exec(OBJ, code, ok)
  446. END FUNCTION
  447.  
  448. ' Same as `v7_exec()`, but loads source code from `path` file
  449. FUNCTION EXEC_FILE(codepath, ok)
  450.   EXEC_FILE = js_exec_file(OBJ, codepath, ok)
  451. END FUNCTION
  452.  
  453. ' Parse `json_code`
  454. ' The result of evaluation is stored in the `return` variable
  455. ' The 'ok' argument will contain the function's parse success status flag
  456. FUNCTION PARSE_JSON(json_code, ok)
  457.   PARSE_JSON = js_parse_json(OBJ, json_code, ok)
  458. END FUNCTION
  459.  
  460. ' Same as `v7_parse_json()`, but loads `json_code` from `path` file
  461. FUNCTION PARSE_JSON_FILE(json_code_file, ok)
  462.   PARSE_JSON_FILE = js_parse_json_file(OBJ, json_code_file, ok)
  463. END FUNCTION
  464.  
  465. ' Call function `func` with arguments `args`, using `object` as `this`
  466. ' `args` should be an array containing arguments or `undefined`
  467. FUNCTION APPLY(func, object, args)
  468.   APPLY = js_apply(OBJ, func, object, args)
  469. END FUNCTION
  470.  
  471. ' Make RegExp object. For example, `regex` is `(.+)`, `flags` is `gi`.
  472. FUNCTION MK_REGEXP(regex, flags, rcode)
  473.   MK_REGEXP = js_mk_regexp(OBJ, regex, LEN(regex), flags, LEN(flags), rcode)
  474. END FUNCTION
  475.  
  476. ' Returns true if given value is a JavaScript RegExp object
  477. FUNCTION IS_REGEXP(object)
  478.   IS_REGEXP = js_is_regexp(OBJ, object)
  479. END FUNCTION
  480.  
  481. ' Generate string representation of the JavaScript value
  482. FUNCTION STRINGIFY(object, convtype)
  483.   STRINGIFY = js_stringify(OBJ, object, convtype)
  484. END FUNCTION
  485.  
  486. ' Output a string representation of the value to stdout followed by a newline
  487. SUB PRINTIFY(object)
  488.   js_println(OBJ, object)
  489. END SUB
  490.  
  491.  
  492. END MODULE
  493.  


Hello JavaScript
Code: Script BASIC
  1. IMPORT js.inc
  2.  
  3. JS::CREATE
  4. PRINT JS::GET_INT(JS::EXEC("1 + 1")),"\n"
  5. JS::DESTROY
  6.  


jrs@jrs-laptop:~/sb/examples/js$ time scriba js_hello2.sb
2

real   0m0.026s
user   0m0.016s
sys   0m0.008s
jrs@jrs-laptop:~/sb/examples/js$


Fibonacci
Code: Script BASIC
  1. IMPORT js.inc
  2.  
  3. jscode = """
  4. function fibonacci(n) {
  5.  if (n <= 2) {
  6.    return 1;
  7.  } else {
  8.    return fibonacci(n - 1) + fibonacci(n - 2);
  9.  }
  10. }
  11.  
  12. print(fibonacci(24));
  13. """
  14.  
  15. JS::CREATE
  16. JS::EXEC(jscode)
  17. JS::DESTROY
  18.  


jrs@jrs-laptop:~/sb/examples/js$ scriba js_fibonacci.sb
46368
jrs@jrs-laptop:~/sb/examples/js$


Create object, property and attributes
Code: Script BASIC
  1. IMPORT js.inc
  2.  
  3. JS::CREATE
  4. myobj = JS::MK_OBJECT()
  5. JS::DEF(myobj, "test", 0, JS::MK_NUMBER(64))
  6. JS::SETS(myobj, "test", JS::MK_NUMBER(32))
  7. JS::DEF(myobj, "test", JS::WRITABLE(FALSE) OR JS::PRESERVE_VALUE(),JS::MK_NULL())
  8. JS::SETS(myobj, "test", JS::MK_NUMBER(16))
  9. PRINT "test = ",JS::GET_INT(JS::GETS(myobj, "test")),"\n"
  10. JS::DESTROY
  11.  


jrs@jrs-laptop:~/sb/examples/js$ scriba js_deftest.sb
test = 32
jrs@jrs-laptop:~/sb/examples/js$


Load .js file and get properties
Code: Script BASIC
  1. IMPORT js.inc
  2.  
  3. JS::CREATE
  4. JS::EXEC_FILE "properties.js"
  5. propcnt = JS::GET_PROPERTIES(JS::GETS(JS::SYS,"test"), proparray)
  6. PRINT "Property\tValue\tAttribute\n"
  7. FOR i = 1 to propcnt
  8.   PRINT proparray[i,0],"\t\t",proparray[i,1],"\t",proparray[i,2],"\n"
  9. NEXT
  10. JS::DESTROY
  11.  

properties.js
Code: Javascript
  1. var test = {};
  2.  
  3. Object.defineProperty(test, 'a', {
  4.   value: 1,
  5.   writable: true,
  6.   enumerable: true,
  7.   configurable: true
  8. });
  9.  
  10. Object.defineProperty(test, 'b', {
  11.   value: 2,
  12.   writable: false,
  13.   enumerable: false,
  14.   configurable: false
  15. });
  16.  


jrs@jrs-laptop:~/sb/examples/js$ scriba js_propfile.sb
Property   Value   Attribute
b      2   7
a      1   0
jrs@jrs-laptop:~/sb/examples/js$


Call JavaScript function
Code: Script BASIC
  1. IMPORT js.inc
  2.  
  3. jscode = """
  4. var sum = function(a, b, c) {
  5.  print (c);
  6.  return a + b; };
  7. """
  8.  
  9. JS::CREATE()
  10. JS::EXEC(jscode)
  11. func = JS::GETS(JS::SYS, "sum")
  12. args = JS::MK_ARRAY()
  13. JS::ARRAY_PUSH(args, JS::MK_NUMBER(123.0))
  14. JS::ARRAY_PUSH(args, JS::MK_NUMBER(0.456))
  15. JS::ARRAY_PUSH(args, JS::MK_STRING("Script BASIC"))
  16. result = JS::APPLY(func, 0, args, rcode)
  17. PRINT FORMAT("Result: %g\n", JS::GET_DOUBLE(result))
  18. JS::DESTROY
  19.  


jrs@jrs-laptop:~/sb/examples/js$ scriba js_callfunc.sb
Script BASIC
Result: 123.456
jrs@jrs-laptop:~/sb/examples/js$


Describe Properties with JavaScript
Code: Script BASIC
  1. IMPORT js.inc
  2.  
  3. ' Create JavaScript instance
  4. JS::CREATE
  5.  
  6. ' Create JavaScript object
  7. JS::EXEC("var myobj = {};")
  8. myobj = JS::GETS(JS::SYS, "myobj")
  9.  
  10. ' Create object property
  11. JS::DEF(myobj, "test", JS::WRITABLE(TRUE), JS::MK_NUMBER(64))
  12.  
  13. ' Describe object properties with JavaScript
  14. jscode = """
  15. var descriptors = {};
  16.  
  17. Object.keys(myobj).forEach(function(key) {
  18.    descriptors[key] = Object.getOwnPropertyDescriptor(myobj, key);
  19. });
  20.  
  21. var objdesc = JSON.stringify(descriptors);
  22. """
  23. JS::EXEC(jscode)
  24.  
  25. ' Return JSON formatted result string
  26. PRINT JS::GET_STRING(JS::GETS(JS::SYS, "objdesc")),"\n"
  27.  
  28. ' Release JavaScript instance
  29. JS::DESTROY
  30.  


jrs@jrs-laptop:~/sb/examples/js$ scriba js_defobj.sb
{"test":{"configurable":true,"enumerable":true,"writable":true,"value":64}}
jrs@jrs-laptop:~/sb/examples/js$


JSON / Stringify
Code: Script BASIC
  1. IMPORT js.inc
  2.  
  3. JS::CREATE
  4. myobj = JS::MK_OBJECT()
  5. JS::DEF(myobj, "myprop_1", 0, JS::MK_NUMBER(64))
  6. JS::DEF(myobj, "myprop_2", 0, JS::MK_NUMBER(1.23))
  7. JS::DEF(myobj, "myprop_3", 0, JS::MK_STRING("JavaScript"))
  8. PRINT JS::STRINGIFY(myobj, JS::JSON),"\n"
  9. JS::DESTROY
  10.  


jrs@jrs-laptop:~/sb/examples/js$ scriba js_stringify.sb
{"myprop_3":"JavaScript","myprop_2":1.23,"myprop_1":64}
jrs@jrs-laptop:~/sb/examples/js$


JavaScript Regular Expression
Code: Script BASIC
  1. IMPORT js.inc
  2.  
  3. jscode = """
  4. var output = ['---------- Original String\\n', names + '\\n'];
  5.  
  6. // Prepare two regular expression patterns and array storage.
  7. // Split the string into array elements.
  8.  
  9. // pattern: possible white space then semicolon then possible white space
  10. var pattern = /\\s*;\\s*/;
  11.  
  12. // Break the string into pieces separated by the pattern above and
  13. // store the pieces in an array called nameList
  14. var nameList = names.split(pattern);
  15.  
  16. // new pattern: one or more characters then spaces then characters.
  17. // Use parentheses to "memorize" portions of the pattern.
  18. // The memorized portions are referred to later.
  19. pattern = /(\\w+)\\s+(\\w+)/;
  20.  
  21. // New array for holding names being processed.
  22. var bySurnameList = [];
  23.  
  24. // Display the name array and populate the new array
  25. // with comma-separated names, last first.
  26. //
  27. // The replace method removes anything matching the pattern
  28. // and replaces it with the memorized string—second memorized portion
  29. // followed by comma space followed by first memorized portion.
  30. //
  31. // The variables $1 and $2 refer to the portions
  32. // memorized while matching the pattern.
  33.  
  34. output.push('---------- After Split by Regular Expression');
  35.  
  36. var i, len;
  37. for (i = 0, len = nameList.length; i < len; i++) {
  38.  output.push(nameList[i]);
  39.  bySurnameList[i] = nameList[i].replace(pattern, '$2, $1');
  40. }
  41.  
  42. // Display the new array.
  43. output.push('---------- Names Reversed');
  44. for (i = 0, len = bySurnameList.length; i < len; i++) {
  45.  output.push(bySurnameList[i]);
  46. }
  47.  
  48. // Sort by last name, then display the sorted array.
  49. bySurnameList.sort();
  50. output.push('---------- Sorted');
  51. for (i = 0, len = bySurnameList.length; i < len; i++) {
  52.  output.push(bySurnameList[i]);
  53. }
  54.  
  55. output.push('---------- End');
  56.  
  57. var retstr = output.join('\\n');
  58. """
  59.  
  60. ' The name string contains multiple spaces and tabs,
  61. ' and may have multiple spaces between first and last names.
  62.  
  63. JS::CREATE
  64. JS::EXEC("var names = 'Harry Trump ;Fred Barney; Helen Rigby ; Bill Abel ; Chris Hand ';")
  65. JS::EXEC(jscode)
  66. PRINT JS::GET_STRING(JS::GETS(JS::SYS, "retstr"))
  67. JS::DESTROY
  68.  


jrs@jrs-laptop:~/sb/examples/js$ time scriba js_regexp.sb
---------- Original String

Harry Trump ;Fred Barney; Helen Rigby ; Bill Abel ; Chris Hand

---------- After Split by Regular Expression
Harry Trump
Fred Barney
Helen Rigby
Bill Abel
Chris Hand
---------- Names Reversed
Trump, Harry
Barney, Fred
Rigby, Helen
Abel, Bill
Hand, Chris
---------- Sorted
Abel, Bill
Barney, Fred
Hand, Chris
Rigby, Helen
Trump, Harry
---------- End
real   0m0.030s
user   0m0.028s
sys   0m0.000s
jrs@jrs-laptop:~/sb/examples/js$