459 lines
18 KiB
C
459 lines
18 KiB
C
/*
|
|
* QuickJS C/JS Interaction Demo Program
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <time.h>
|
|
#include "quickjs.h"
|
|
#include "quickjs-libc.h"
|
|
|
|
void print_js_value(JSContext *ctx, JSValue val, const char *name) {
|
|
printf("%s: ", name);
|
|
if (JS_IsUndefined(val)) {
|
|
printf("undefined\n");
|
|
} else if (JS_IsNull(val)) {
|
|
printf("null\n");
|
|
} else if (JS_IsBool(val)) {
|
|
printf("%s\n", JS_ToBool(ctx, val) ? "true" : "false");
|
|
} else if (JS_IsNumber(val)) {
|
|
double num;
|
|
JS_ToFloat64(ctx, &num, val);
|
|
printf("%.2f\n", num);
|
|
} else if (JS_IsString(val)) {
|
|
const char *str = JS_ToCString(ctx, val);
|
|
printf("'%s'\n", str);
|
|
JS_FreeCString(ctx, str);
|
|
} else if (JS_IsObject(val)) {
|
|
printf("[Object]\n");
|
|
} else if (JS_IsFunction(ctx, val)) {
|
|
printf("[Function]\n");
|
|
} else {
|
|
printf("[Unknown]\n");
|
|
}
|
|
}
|
|
|
|
void check_exception(JSContext *ctx) {
|
|
JSValue exception = JS_GetException(ctx);
|
|
if (!JS_IsUndefined(exception) && !JS_IsNull(exception)) {
|
|
printf("Exception: ");
|
|
JSValue error_message = JS_ToString(ctx, exception);
|
|
const char *msg = JS_ToCString(ctx, error_message);
|
|
printf("%s\n", msg);
|
|
JS_FreeCString(ctx, msg);
|
|
JS_FreeValue(ctx, error_message);
|
|
|
|
JSValue stack = JS_GetPropertyStr(ctx, exception, "stack");
|
|
if (!JS_IsUndefined(stack) && !JS_IsNull(stack)) {
|
|
const char *stack_str = JS_ToCString(ctx, stack);
|
|
printf("Stack:\n%s\n", stack_str);
|
|
JS_FreeCString(ctx, stack_str);
|
|
}
|
|
JS_FreeValue(ctx, stack);
|
|
}
|
|
JS_FreeValue(ctx, exception);
|
|
}
|
|
|
|
void example1_basic_execution(JSContext *ctx) {
|
|
printf("\n========== Example 1: Basic JavaScript Execution ==========\n");
|
|
JSValue result;
|
|
|
|
result = JS_Eval(ctx, "1 + 2", 5, "<eval>", JS_EVAL_TYPE_GLOBAL);
|
|
print_js_value(ctx, result, "1 + 2");
|
|
JS_FreeValue(ctx, result);
|
|
|
|
const char *code = "let x = 10; let y = 20; x * y;";
|
|
result = JS_Eval(ctx, code, strlen(code), "<multiline>", JS_EVAL_TYPE_GLOBAL);
|
|
print_js_value(ctx, result, "x * y");
|
|
JS_FreeValue(ctx, result);
|
|
|
|
const char *func_code = "function add(a, b) { return a + b; } add(5, 3);";
|
|
result = JS_Eval(ctx, func_code, strlen(func_code), "<func>", JS_EVAL_TYPE_GLOBAL);
|
|
print_js_value(ctx, result, "add(5, 3)");
|
|
JS_FreeValue(ctx, result);
|
|
}
|
|
|
|
static JSValue js_add(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) {
|
|
double a, b;
|
|
if (JS_ToFloat64(ctx, &a, argv[0]) || JS_ToFloat64(ctx, &b, argv[1])) {
|
|
return JS_ThrowTypeError(ctx, "Parameters must be numbers");
|
|
}
|
|
return JS_NewFloat64(ctx, a + b);
|
|
}
|
|
|
|
static JSValue js_greet(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) {
|
|
if (argc < 1 || !JS_IsString(argv[0])) {
|
|
return JS_ThrowTypeError(ctx, "Need a string parameter");
|
|
}
|
|
const char *name = JS_ToCString(ctx, argv[0]);
|
|
char greeting[256];
|
|
snprintf(greeting, sizeof(greeting), "Hello from C, %s!", name);
|
|
JS_FreeCString(ctx, name);
|
|
return JS_NewString(ctx, greeting);
|
|
}
|
|
|
|
static JSValue js_get_current_time(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) {
|
|
JSValue obj = JS_NewObject(ctx);
|
|
time_t now = time(NULL);
|
|
struct tm *tm_info = localtime(&now);
|
|
|
|
char time_str[64];
|
|
strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", tm_info);
|
|
|
|
JS_SetPropertyStr(ctx, obj, "timestamp", JS_NewInt64(ctx, (int64_t)now));
|
|
JS_SetPropertyStr(ctx, obj, "formatted", JS_NewString(ctx, time_str));
|
|
JS_SetPropertyStr(ctx, obj, "year", JS_NewInt32(ctx, tm_info->tm_year + 1900));
|
|
JS_SetPropertyStr(ctx, obj, "month", JS_NewInt32(ctx, tm_info->tm_mon + 1));
|
|
JS_SetPropertyStr(ctx, obj, "day", JS_NewInt32(ctx, tm_info->tm_mday));
|
|
|
|
return obj;
|
|
}
|
|
|
|
static JSValue js_reverse_array(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) {
|
|
if (argc < 1 || !JS_IsArray(argv[0])) {
|
|
return JS_ThrowTypeError(ctx, "Need an array parameter");
|
|
}
|
|
JSValue input_arr = argv[0];
|
|
JSValue length_val = JS_GetPropertyStr(ctx, input_arr, "length");
|
|
uint32_t length;
|
|
JS_ToUint32(ctx, &length, length_val);
|
|
JS_FreeValue(ctx, length_val);
|
|
|
|
JSValue result_arr = JS_NewArray(ctx);
|
|
for (uint32_t i = 0; i < length; i++) {
|
|
JSValue element = JS_GetPropertyUint32(ctx, input_arr, i);
|
|
JS_SetPropertyUint32(ctx, result_arr, length - 1 - i, element);
|
|
}
|
|
return result_arr;
|
|
}
|
|
|
|
static JSValue js_sum_all(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) {
|
|
double sum = 0;
|
|
double value;
|
|
for (int i = 0; i < argc; i++) {
|
|
if (JS_ToFloat64(ctx, &value, argv[i])) {
|
|
return JS_ThrowTypeError(ctx, "All parameters must be numbers");
|
|
}
|
|
sum += value;
|
|
}
|
|
return JS_NewFloat64(ctx, sum);
|
|
}
|
|
|
|
void example3_call_c_from_js(JSContext *ctx) {
|
|
printf("\n========== Example 3: Call C Functions from JavaScript ==========\n");
|
|
JSValue global_obj = JS_GetGlobalObject(ctx);
|
|
|
|
JSValue func = JS_NewCFunction(ctx, js_add, "c_add", 2);
|
|
JS_SetPropertyStr(ctx, global_obj, "c_add", func);
|
|
|
|
func = JS_NewCFunction(ctx, js_greet, "c_greet", 1);
|
|
JS_SetPropertyStr(ctx, global_obj, "c_greet", func);
|
|
|
|
func = JS_NewCFunction(ctx, js_get_current_time, "c_getCurrentTime", 0);
|
|
JS_SetPropertyStr(ctx, global_obj, "c_getCurrentTime", func);
|
|
|
|
func = JS_NewCFunction(ctx, js_reverse_array, "c_reverseArray", 1);
|
|
JS_SetPropertyStr(ctx, global_obj, "c_reverseArray", func);
|
|
|
|
func = JS_NewCFunction(ctx, js_sum_all, "c_sumAll", 0);
|
|
JS_SetPropertyStr(ctx, global_obj, "c_sumAll", func);
|
|
|
|
JS_FreeValue(ctx, global_obj);
|
|
|
|
const char *test_code = "console.log('c_add(3, 4) =', c_add(3, 4));";
|
|
JS_Eval(ctx, test_code, strlen(test_code), "<test_c_func>", JS_EVAL_TYPE_GLOBAL);
|
|
|
|
test_code = "console.log('c_greet(\"Bob\") =', c_greet('Bob'));";
|
|
JS_Eval(ctx, test_code, strlen(test_code), "<test_c_func>", JS_EVAL_TYPE_GLOBAL);
|
|
|
|
test_code = "let time = c_getCurrentTime(); console.log('Current time:', time.formatted);";
|
|
JS_Eval(ctx, test_code, strlen(test_code), "<test_c_func>", JS_EVAL_TYPE_GLOBAL);
|
|
|
|
test_code = "let arr = [1, 2, 3, 4, 5]; let reversed = c_reverseArray(arr); console.log('Original:', arr); console.log('Reversed:', reversed);";
|
|
JS_Eval(ctx, test_code, strlen(test_code), "<test_c_func>", JS_EVAL_TYPE_GLOBAL);
|
|
|
|
test_code = "console.log('c_sumAll(1, 2, 3, 4, 5) =', c_sumAll(1, 2, 3, 4, 5));";
|
|
JS_Eval(ctx, test_code, strlen(test_code), "<test_c_func>", JS_EVAL_TYPE_GLOBAL);
|
|
|
|
check_exception(ctx);
|
|
}
|
|
|
|
void example4_type_conversion(JSContext *ctx) {
|
|
printf("\n========== Example 4: Type Conversion ==========\n");
|
|
JSValue js_undefined = JS_UNDEFINED;
|
|
JSValue js_null = JS_NULL;
|
|
JSValue js_bool_true = JS_NewBool(ctx, 1);
|
|
JSValue js_bool_false = JS_NewBool(ctx, 0);
|
|
JSValue js_int = JS_NewInt32(ctx, 42);
|
|
JSValue js_float = JS_NewFloat64(ctx, 3.14159);
|
|
JSValue js_string = JS_NewString(ctx, "Hello, QuickJS!");
|
|
JSValue js_object = JS_NewObject(ctx);
|
|
JSValue js_array = JS_NewArray(ctx);
|
|
|
|
JS_SetPropertyUint32(ctx, js_array, 0, JS_NewInt32(ctx, 1));
|
|
JS_SetPropertyUint32(ctx, js_array, 1, JS_NewInt32(ctx, 2));
|
|
JS_SetPropertyUint32(ctx, js_array, 2, JS_NewInt32(ctx, 3));
|
|
|
|
JS_SetPropertyStr(ctx, js_object, "name", JS_NewString(ctx, "TestObject"));
|
|
JS_SetPropertyStr(ctx, js_object, "value", JS_NewInt32(ctx, 123));
|
|
|
|
print_js_value(ctx, js_undefined, "undefined");
|
|
print_js_value(ctx, js_null, "null");
|
|
print_js_value(ctx, js_bool_true, "true");
|
|
print_js_value(ctx, js_bool_false, "false");
|
|
print_js_value(ctx, js_int, "42");
|
|
print_js_value(ctx, js_float, "3.14159");
|
|
print_js_value(ctx, js_string, "string");
|
|
print_js_value(ctx, js_object, "object");
|
|
print_js_value(ctx, js_array, "array");
|
|
|
|
double num_value;
|
|
if (!JS_ToFloat64(ctx, &num_value, js_int)) {
|
|
printf("Get integer from JS: %.0f\n", num_value);
|
|
}
|
|
|
|
const char *str_value = JS_ToCString(ctx, js_string);
|
|
printf("Get string from JS: %s\n", str_value);
|
|
JS_FreeCString(ctx, str_value);
|
|
|
|
JSValue js_bigint = JS_NewBigInt64(ctx, 9007199254740993LL);
|
|
print_js_value(ctx, js_bigint, "BigInt");
|
|
|
|
int64_t bigint_value;
|
|
if (!JS_ToBigInt64(ctx, &bigint_value, js_bigint)) {
|
|
printf("Get BigInt from JS: %lld\n", (long long)bigint_value);
|
|
}
|
|
|
|
JS_FreeValue(ctx, js_bool_true);
|
|
JS_FreeValue(ctx, js_bool_false);
|
|
JS_FreeValue(ctx, js_int);
|
|
JS_FreeValue(ctx, js_float);
|
|
JS_FreeValue(ctx, js_string);
|
|
JS_FreeValue(ctx, js_object);
|
|
JS_FreeValue(ctx, js_array);
|
|
JS_FreeValue(ctx, js_bigint);
|
|
}
|
|
|
|
void example5_object_manipulation(JSContext *ctx) {
|
|
printf("\n========== Example 5: Object Manipulation ==========\n");
|
|
JSValue obj = JS_NewObject(ctx);
|
|
JS_SetPropertyStr(ctx, obj, "name", JS_NewString(ctx, "MyObject"));
|
|
JS_SetPropertyStr(ctx, obj, "count", JS_NewInt32(ctx, 100));
|
|
JS_SetPropertyStr(ctx, obj, "active", JS_NewBool(ctx, 1));
|
|
|
|
JSValue nested = JS_NewObject(ctx);
|
|
JS_SetPropertyStr(ctx, nested, "x", JS_NewInt32(ctx, 10));
|
|
JS_SetPropertyStr(ctx, nested, "y", JS_NewInt32(ctx, 20));
|
|
JS_SetPropertyStr(ctx, obj, "position", nested);
|
|
|
|
const char *complex_obj_code = "const person = { firstName: 'John', lastName: 'Doe', age: 30, getFullName: function() { return this.firstName + ' ' + this.lastName; } };";
|
|
JSValue person = JS_Eval(ctx, complex_obj_code, strlen(complex_obj_code), "<complex_obj>", JS_EVAL_TYPE_GLOBAL);
|
|
|
|
JSValue name = JS_GetPropertyStr(ctx, person, "firstName");
|
|
JSValue age = JS_GetPropertyStr(ctx, person, "age");
|
|
print_js_value(ctx, name, "person.firstName");
|
|
print_js_value(ctx, age, "person.age");
|
|
|
|
JSValue get_full_name = JS_GetPropertyStr(ctx, person, "getFullName");
|
|
JSValue full_name = JS_Call(ctx, get_full_name, person, 0, NULL);
|
|
print_js_value(ctx, full_name, "person.getFullName()");
|
|
|
|
JS_FreeValue(ctx, obj);
|
|
JS_FreeValue(ctx, person);
|
|
JS_FreeValue(ctx, name);
|
|
JS_FreeValue(ctx, age);
|
|
JS_FreeValue(ctx, get_full_name);
|
|
JS_FreeValue(ctx, full_name);
|
|
}
|
|
|
|
void example6_array_manipulation(JSContext *ctx) {
|
|
printf("\n========== Example 6: Array Manipulation ==========\n");
|
|
JSValue arr = JS_NewArray(ctx);
|
|
|
|
for (int i = 0; i < 5; i++) {
|
|
JS_SetPropertyUint32(ctx, arr, i, JS_NewInt32(ctx, i * 10));
|
|
}
|
|
|
|
JSValue length_val = JS_GetPropertyStr(ctx, arr, "length");
|
|
uint32_t length;
|
|
JS_ToUint32(ctx, &length, length_val);
|
|
printf("Array length: %u\n", length);
|
|
JS_FreeValue(ctx, length_val);
|
|
|
|
printf("Array elements: ");
|
|
for (uint32_t i = 0; i < length; i++) {
|
|
JSValue element = JS_GetPropertyUint32(ctx, arr, i);
|
|
int32_t value;
|
|
JS_ToInt32(ctx, &value, element);
|
|
printf("%d ", value);
|
|
JS_FreeValue(ctx, element);
|
|
}
|
|
printf("\n");
|
|
|
|
const char *array_code = "const numbers = [1, 2, 3, 4, 5]; const doubled = numbers.map(x => x * 2); const sum = numbers.reduce((a, b) => a + b, 0);";
|
|
JS_Eval(ctx, array_code, strlen(array_code), "<arrays>", JS_EVAL_TYPE_GLOBAL);
|
|
|
|
JSValue global = JS_GetGlobalObject(ctx);
|
|
JSValue doubled = JS_GetPropertyStr(ctx, global, "doubled");
|
|
JSValue sum = JS_GetPropertyStr(ctx, global, "sum");
|
|
print_js_value(ctx, doubled, "numbers.map(x => x * 2)");
|
|
print_js_value(ctx, sum, "numbers.reduce((a, b) => a + b, 0)");
|
|
|
|
const char *typed_array_code = "const int8 = new Int8Array([1, 2, 3, 127]); const float64 = new Float64Array([1.1, 2.2, 3.3]);";
|
|
JS_Eval(ctx, typed_array_code, strlen(typed_array_code), "<typed_arrays>", JS_EVAL_TYPE_GLOBAL);
|
|
|
|
JSValue int8 = JS_GetPropertyStr(ctx, global, "int8");
|
|
JSValue float64_arr = JS_GetPropertyStr(ctx, global, "float64");
|
|
print_js_value(ctx, int8, "Int8Array");
|
|
print_js_value(ctx, float64_arr, "Float64Array");
|
|
|
|
JS_FreeValue(ctx, arr);
|
|
JS_FreeValue(ctx, global);
|
|
JS_FreeValue(ctx, doubled);
|
|
JS_FreeValue(ctx, sum);
|
|
JS_FreeValue(ctx, int8);
|
|
JS_FreeValue(ctx, float64_arr);
|
|
}
|
|
|
|
static JSValue js_c_throw_error(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) {
|
|
JSValue error_obj = JS_NewObject(ctx);
|
|
JS_SetPropertyStr(ctx, error_obj, "message", JS_NewString(ctx, "Error thrown from C!"));
|
|
return JS_Throw(ctx, error_obj);
|
|
}
|
|
|
|
void example7_exception_handling(JSContext *ctx) {
|
|
printf("\n========== Example 7: Exception Handling ==========\n");
|
|
printf("Test JavaScript exception:\n");
|
|
const char *error_code = "throw new Error('This is a test error');";
|
|
JSValue result = JS_Eval(ctx, error_code, strlen(error_code), "<error>", JS_EVAL_TYPE_GLOBAL);
|
|
check_exception(ctx);
|
|
JS_FreeValue(ctx, result);
|
|
|
|
printf("\nTest throw exception from C:\n");
|
|
const char *test_c_throw_code = "function testCThrow() { return c_throw_error(); } testCThrow();";
|
|
|
|
JSValue global = JS_GetGlobalObject(ctx);
|
|
JSValue c_throw_func = JS_NewCFunction(ctx, js_c_throw_error, "c_throw_error", 0);
|
|
JS_SetPropertyStr(ctx, global, "c_throw_error", c_throw_func);
|
|
JS_FreeValue(ctx, global);
|
|
|
|
result = JS_Eval(ctx, test_c_throw_code, strlen(test_c_throw_code), "<c_error>", JS_EVAL_TYPE_GLOBAL);
|
|
check_exception(ctx);
|
|
JS_FreeValue(ctx, result);
|
|
}
|
|
|
|
void example8_memory_management(JSContext *ctx) {
|
|
printf("\n========== Example 8: Memory Management ==========\n");
|
|
JSValue val = JS_NewString(ctx, "test");
|
|
printf("Created string: %s\n", JS_ToCString(ctx, val));
|
|
JS_FreeValue(ctx, val);
|
|
|
|
val = JS_NewString(ctx, "shared");
|
|
JSValue val2 = JS_DupValue(ctx, val);
|
|
printf("Shared string: %s\n", JS_ToCString(ctx, val2));
|
|
JS_FreeValue(ctx, val);
|
|
JS_FreeValue(ctx, val2);
|
|
|
|
printf("\nCreating large array...\n");
|
|
JSValue large_array = JS_NewArray(ctx);
|
|
for (int i = 0; i < 1000; i++) {
|
|
JS_SetPropertyUint32(ctx, large_array, i, JS_NewInt32(ctx, i));
|
|
}
|
|
printf("Large array created\n");
|
|
JS_FreeValue(ctx, large_array);
|
|
printf("Large array freed\n");
|
|
|
|
printf("\nTrigger garbage collection...\n");
|
|
JS_RunGC(JS_GetRuntime(ctx));
|
|
printf("Garbage collection completed\n");
|
|
}
|
|
|
|
void example9_stdlib_modules(JSContext *ctx) {
|
|
printf("\n========== Example 9: Standard Library Modules ==========\n");
|
|
js_init_module_std(ctx, "std");
|
|
js_init_module_os(ctx, "os");
|
|
js_init_module_bjson(ctx, "bjson");
|
|
|
|
const char *stdlib_code = "import * as std from 'std'; import * as os from 'os'; console.log('Current working directory:', os.getcwd());";
|
|
JSValue result = JS_Eval(ctx, stdlib_code, strlen(stdlib_code), "<stdlib>", JS_EVAL_TYPE_MODULE);
|
|
check_exception(ctx);
|
|
JS_FreeValue(ctx, result);
|
|
}
|
|
|
|
static JSValue js_multiply(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) {
|
|
double a, b;
|
|
if (JS_ToFloat64(ctx, &a, argv[0]) || JS_ToFloat64(ctx, &b, argv[1])) {
|
|
return JS_ThrowTypeError(ctx, "Parameters must be numbers");
|
|
}
|
|
return JS_NewFloat64(ctx, a * b);
|
|
}
|
|
|
|
static int my_math_module_init(JSContext *ctx, JSModuleDef *m) {
|
|
JSValue add_func = JS_NewCFunction(ctx, js_add, "add", 2);
|
|
JS_SetModuleExport(ctx, m, "add", add_func);
|
|
|
|
JSValue multiply_func = JS_NewCFunction(ctx, js_multiply, "multiply", 2);
|
|
JS_SetModuleExport(ctx, m, "multiply", multiply_func);
|
|
return 0;
|
|
}
|
|
|
|
void example10_custom_module(JSContext *ctx) {
|
|
printf("\n========== Example 10: Custom JavaScript Modules ==========\n");
|
|
|
|
JSModuleDef *m = JS_NewCModule(ctx, "my_math", my_math_module_init);
|
|
|
|
const char *module_code = "import { add, multiply } from 'my_math'; console.log('add(5, 3) =', add(5, 3)); console.log('multiply(4, 6) =', multiply(4, 6));";
|
|
JSValue result = JS_Eval(ctx, module_code, strlen(module_code), "<custom_module>", JS_EVAL_TYPE_MODULE);
|
|
check_exception(ctx);
|
|
JS_FreeValue(ctx, result);
|
|
|
|
const char *module_source = "export function factorial(n) { if (n <= 1) return 1; return n * factorial(n - 1); } export const PI = 3.14159;";
|
|
JSValue module_val = JS_Eval(ctx, module_source, strlen(module_source), "math_utils.js", JS_EVAL_TYPE_MODULE);
|
|
JS_FreeValue(ctx, module_val);
|
|
|
|
const char *use_math_utils = "import { factorial, PI } from 'math_utils.js'; console.log('5! =', factorial(5)); console.log('PI =', PI);";
|
|
result = JS_Eval(ctx, use_math_utils, strlen(use_math_utils), "<use_math_utils>", JS_EVAL_TYPE_MODULE);
|
|
check_exception(ctx);
|
|
JS_FreeValue(ctx, result);
|
|
}
|
|
|
|
int main(int argc, char **argv) {
|
|
JSRuntime *rt = JS_NewRuntime();
|
|
if (!rt) {
|
|
fprintf(stderr, "Failed to create QuickJS runtime\n");
|
|
return 1;
|
|
}
|
|
|
|
JSContext *ctx = JS_NewContext(rt);
|
|
if (!ctx) {
|
|
fprintf(stderr, "Failed to create QuickJS context\n");
|
|
JS_FreeRuntime(rt);
|
|
return 1;
|
|
}
|
|
|
|
printf("======================================================\n");
|
|
printf(" QuickJS C/JS Interaction Demo Program\n");
|
|
printf("======================================================\n");
|
|
|
|
js_std_add_helpers(ctx, argc, argv);
|
|
|
|
example1_basic_execution(ctx);
|
|
example3_call_c_from_js(ctx);
|
|
example4_type_conversion(ctx);
|
|
example5_object_manipulation(ctx);
|
|
example6_array_manipulation(ctx);
|
|
example7_exception_handling(ctx);
|
|
example8_memory_management(ctx);
|
|
example9_stdlib_modules(ctx);
|
|
example10_custom_module(ctx);
|
|
|
|
printf("\n======================================================\n");
|
|
printf(" All examples completed!\n");
|
|
printf("======================================================\n");
|
|
|
|
JS_FreeContext(ctx);
|
|
JS_FreeRuntime(rt);
|
|
|
|
return 0;
|
|
} |