Compare commits
34 Commits
js-rm-weak
...
js-libffi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cbd27e0783 | ||
|
|
6eb33b8e48 | ||
|
|
3d5f345236 | ||
|
|
4689ea1167 | ||
|
|
15d85096a2 | ||
|
|
f2c2ecf692 | ||
|
|
458215f838 | ||
|
|
7f002e306d | ||
|
|
91a3fef065 | ||
|
|
843b4bd8a8 | ||
|
|
41fdf49df5 | ||
|
|
c9adbed3ff | ||
|
|
3459d85a82 | ||
|
|
9ecdaae7a7 | ||
|
|
43b55b29f3 | ||
|
|
a88cee7fae | ||
|
|
8b3f5476a9 | ||
|
|
233f59e04a | ||
|
|
7b16259c00 | ||
|
|
43baa23dfe | ||
|
|
a9ebea9f26 | ||
|
|
19b729afbf | ||
|
|
47729c225f | ||
|
|
ea6cf5db49 | ||
|
|
794baf8598 | ||
|
|
a551368681 | ||
|
|
c20ca8c937 | ||
|
|
0217cf0da6 | ||
|
|
6bd7251933 | ||
|
|
6dc8d97001 | ||
|
|
9c0565d34f | ||
|
|
0702e3495d | ||
|
|
108c39d22d | ||
|
|
946ebe5cd7 |
@@ -27,7 +27,7 @@ function TreeNode(left, right) {
|
||||
}
|
||||
|
||||
function itemCheck(node) {
|
||||
if (node.left === null)
|
||||
if (node.left == null)
|
||||
return 1;
|
||||
return 1 + itemCheck(node.left) + itemCheck(node.right);
|
||||
}
|
||||
|
||||
@@ -296,7 +296,7 @@ function benchClosures() {
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
log.console("JavaScript Performance Benchmark");
|
||||
log.console("================================\n");
|
||||
log.console("======================\n");
|
||||
|
||||
// Property Access
|
||||
log.console("BENCHMARK: Property Access");
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
var N = 10000000;
|
||||
var N = 1000000;
|
||||
var num = 0;
|
||||
for (var i = 0; i < N; i ++) {
|
||||
var x = 2 * $_.random();
|
||||
|
||||
@@ -42,34 +42,34 @@ for (let i = 0; i < 100; i++) {
|
||||
|
||||
// Calculate statistics
|
||||
function getStats(arr) {
|
||||
const avg = arr.reduce((a, b) => a + b) / arr.length;
|
||||
const min = Math.min(...arr);
|
||||
const max = Math.max(...arr);
|
||||
def avg = arr.reduce((a, b) => a + b) / arr.length;
|
||||
def min = Math.min(...arr);
|
||||
def max = Math.max(...arr);
|
||||
return { avg, min, max };
|
||||
}
|
||||
|
||||
// Pretty print results
|
||||
log.console("\n=== Performance Test Results (100 iterations) ===");
|
||||
log.console("\n== Performance Test Results (100 iterations) ==");
|
||||
log.console("\nJSON Decoding (ms):");
|
||||
const jsonDecStats = getStats(jsonDecodeTimes);
|
||||
def jsonDecStats = getStats(jsonDecodeTimes);
|
||||
log.console(`Average: ${jsonDecStats.avg.toFixed(2)} ms`);
|
||||
log.console(`Min: ${jsonDecStats.min.toFixed(2)} ms`);
|
||||
log.console(`Max: ${jsonDecStats.max.toFixed(2)} ms`);
|
||||
|
||||
log.console("\nJSON Encoding (ms):");
|
||||
const jsonEncStats = getStats(jsonEncodeTimes);
|
||||
def jsonEncStats = getStats(jsonEncodeTimes);
|
||||
log.console(`Average: ${jsonEncStats.avg.toFixed(2)} ms`);
|
||||
log.console(`Min: ${jsonEncStats.min.toFixed(2)} ms`);
|
||||
log.console(`Max: ${jsonEncStats.max.toFixed(2)} ms`);
|
||||
|
||||
log.console("\nNOTA Encoding (ms):");
|
||||
const notaEncStats = getStats(notaEncodeTimes);
|
||||
def notaEncStats = getStats(notaEncodeTimes);
|
||||
log.console(`Average: ${notaEncStats.avg.toFixed(2)} ms`);
|
||||
log.console(`Min: ${notaEncStats.min.toFixed(2)} ms`);
|
||||
log.console(`Max: ${notaEncStats.max.toFixed(2)} ms`);
|
||||
|
||||
log.console("\nNOTA Decoding (ms):");
|
||||
const notaDecStats = getStats(notaDecodeTimes);
|
||||
def notaDecStats = getStats(notaDecodeTimes);
|
||||
log.console(`Average: ${notaDecStats.avg.toFixed(2)} ms`);
|
||||
log.console(`Min: ${notaDecStats.min.toFixed(2)} ms`);
|
||||
log.console(`Max: ${notaDecStats.max.toFixed(2)} ms`);
|
||||
|
||||
@@ -36,7 +36,7 @@ function roundTripWota(value) {
|
||||
// iterations: how many times to loop
|
||||
//
|
||||
// You can tweak these as you like for heavier or lighter tests.
|
||||
const benchmarks = [
|
||||
def benchmarks = [
|
||||
{
|
||||
name: "Small Integers",
|
||||
data: [0, 42, -1, 2023],
|
||||
@@ -76,7 +76,7 @@ const benchmarks = [
|
||||
|
||||
// Print a header
|
||||
log.console("Wota Encode/Decode Benchmark");
|
||||
log.console("============================\n");
|
||||
log.console("===================\n");
|
||||
|
||||
// We'll run each benchmark scenario in turn.
|
||||
for (let bench of benchmarks) {
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
//
|
||||
|
||||
// Parse command line arguments
|
||||
if (arg.length !== 2) {
|
||||
if (arg.length != 2) {
|
||||
log.console('Usage: cell benchmark_wota_nota_json.ce <LibraryName> <ScenarioName>');
|
||||
$_.stop()
|
||||
}
|
||||
@@ -25,7 +25,7 @@ var scenario_name = arg[1];
|
||||
// 1. Setup "libraries" array to easily switch among wota, nota, and json
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const libraries = [
|
||||
def libraries = [
|
||||
{
|
||||
name: "wota",
|
||||
encode: wota.encode,
|
||||
@@ -62,7 +62,7 @@ const libraries = [
|
||||
// Each scenario has { name, data, iterations }
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const benchmarks = [
|
||||
def benchmarks = [
|
||||
{
|
||||
name: "empty",
|
||||
data: [{}, {}, {}, {}],
|
||||
@@ -139,7 +139,7 @@ function runBenchmarkForLibrary(lib, bench) {
|
||||
let e = lib.encode(bench.data[j]);
|
||||
// store only in the very first iteration, so we can decode them later
|
||||
// but do not store them every iteration or we blow up memory.
|
||||
if (i === 0) {
|
||||
if (i == 0) {
|
||||
encodedList.push(e);
|
||||
totalSize += lib.getSize(e);
|
||||
}
|
||||
@@ -166,8 +166,8 @@ function runBenchmarkForLibrary(lib, bench) {
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Find the requested library and scenario
|
||||
var lib = libraries.find(l => l.name === lib_name);
|
||||
var bench = benchmarks.find(b => b.name === scenario_name);
|
||||
var lib = libraries.find(l => l.name == lib_name);
|
||||
var bench = benchmarks.find(b => b.name == scenario_name);
|
||||
|
||||
if (!lib) {
|
||||
log.console('Unknown library:', lib_name);
|
||||
|
||||
2
cell.md
2
cell.md
@@ -1,5 +1,7 @@
|
||||
JAVASCRIPT VISION
|
||||
|
||||
I see objects as being a sort of combination of a lisp cell and a record: symbols, which are used internally, and are private and non iterable, and record string values, which are iterable, readable, and writable; of course everything becomes locked in when stone.
|
||||
|
||||
CELLSCRIPT
|
||||
|
||||
Javascript to its core. Objects. What does the language need? It can be quite small, I think. The key is, ANYTHING that we want to be fast and JIT'd, must be present. So, record lookups. These are actually quicker in a jit'd language that have them as a feature. Most things should be libraries. Blobs need to be in the runtime.
|
||||
|
||||
@@ -18,7 +18,7 @@ var state = {
|
||||
|
||||
// Helper to calculate progress percentage
|
||||
function get_progress() {
|
||||
if (state.total_bytes === 0) {
|
||||
if (state.total_bytes == 0) {
|
||||
return 0;
|
||||
}
|
||||
return Math.round((state.downloaded_bytes / state.total_bytes) * 100);
|
||||
@@ -150,7 +150,7 @@ function read_next_chunk() {
|
||||
try {
|
||||
var chunk = http.fetch_read_chunk(state.connection);
|
||||
|
||||
if (chunk === null) {
|
||||
if (chunk == null) {
|
||||
// Download complete
|
||||
finish_download();
|
||||
return;
|
||||
|
||||
@@ -18,7 +18,7 @@ $_.portal(e => {
|
||||
send(waiting_client, e.actor)
|
||||
send(e, waiting_client.actor)
|
||||
|
||||
waiting_client = undefined
|
||||
waiting_client = null
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
21
meson.build
21
meson.build
@@ -161,15 +161,6 @@ else
|
||||
endif
|
||||
endif
|
||||
|
||||
# Try to find system-installed qjs-layout first
|
||||
qjs_layout_dep = dependency('qjs-layout', static: true, required: false)
|
||||
if not qjs_layout_dep.found()
|
||||
message('⚙ System qjs-layout not found, building subproject...')
|
||||
deps += dependency('qjs-layout', static:true)
|
||||
else
|
||||
deps += qjs_layout_dep
|
||||
endif
|
||||
|
||||
miniz_dep = dependency('miniz', static: true, required: false)
|
||||
if not miniz_dep.found()
|
||||
message('⚙ System miniz not found, building subproject...')
|
||||
@@ -178,14 +169,6 @@ else
|
||||
deps += miniz_dep
|
||||
endif
|
||||
|
||||
libuv_dep = dependency('libuv', static: true, required: false)
|
||||
if not libuv_dep.found()
|
||||
message('⚙ System libuv not found, building subproject...')
|
||||
deps += dependency('libuv', static:true, fallback: ['libuv', 'libuv_dep'])
|
||||
else
|
||||
deps += libuv_dep
|
||||
endif
|
||||
|
||||
# Try to find system-installed physfs first
|
||||
physfs_dep = dependency('physfs', static: true, required: false)
|
||||
if not physfs_dep.found()
|
||||
@@ -207,6 +190,8 @@ else
|
||||
deps += chipmunk_dep
|
||||
endif
|
||||
|
||||
deps += dependency('libffi', static:true)
|
||||
|
||||
if host_machine.system() != 'emscripten'
|
||||
# Try to find system-installed enet first
|
||||
enet_dep = dependency('enet', static: true, required: false)
|
||||
@@ -288,7 +273,7 @@ src += [
|
||||
'anim.c', 'config.c', 'datastream.c','font.c','HandmadeMath.c','jsffi.c','model.c',
|
||||
'render.c','simplex.c','spline.c', 'transform.c','cell.c', 'wildmatch.c',
|
||||
'sprite.c', 'rtree.c', 'qjs_nota.c', 'qjs_soloud.c', 'qjs_sdl.c', 'qjs_sdl_input.c', 'qjs_sdl_video.c', 'qjs_sdl_surface.c', 'qjs_math.c', 'qjs_geometry.c', 'qjs_transform.c', 'qjs_sprite.c', 'qjs_io.c', 'qjs_fd.c', 'qjs_os.c', 'qjs_actor.c',
|
||||
'qjs_qr.c', 'qjs_wota.c', 'monocypher.c', 'qjs_blob.c', 'qjs_crypto.c', 'qjs_time.c', 'qjs_http.c', 'qjs_rtree.c', 'qjs_spline.c', 'qjs_js.c', 'qjs_debug.c', 'picohttpparser.c', 'qjs_miniz.c', 'qjs_num.c', 'timer.c', 'qjs_socket.c', 'qjs_kim.c', 'qjs_utf8.c', 'qjs_fit.c', 'qjs_text.c'
|
||||
'qjs_qr.c', 'qjs_wota.c', 'monocypher.c', 'qjs_blob.c', 'qjs_crypto.c', 'qjs_time.c', 'qjs_http.c', 'qjs_rtree.c', 'qjs_spline.c', 'qjs_js.c', 'qjs_debug.c', 'picohttpparser.c', 'qjs_miniz.c', 'qjs_num.c', 'timer.c', 'qjs_socket.c', 'qjs_kim.c', 'qjs_utf8.c', 'qjs_fit.c', 'qjs_text.c', 'point.c', 'qjs_ffi.c'
|
||||
]
|
||||
# quirc src
|
||||
src += [
|
||||
|
||||
@@ -2,7 +2,7 @@ var graphics = use('graphics')
|
||||
var color = use('color')
|
||||
|
||||
var sprite = {
|
||||
image: undefined,
|
||||
image: null,
|
||||
set color(x) { this._sprite.color = x; },
|
||||
get color() { return this._sprite.color; },
|
||||
anim_speed: 1,
|
||||
@@ -12,7 +12,7 @@ var sprite = {
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof str === 'string') {
|
||||
if (typeof str == 'string') {
|
||||
if (!this.animset[str]) {
|
||||
fn?.();
|
||||
return;
|
||||
@@ -26,8 +26,8 @@ var sprite = {
|
||||
|
||||
this.del_anim?.();
|
||||
this.del_anim = () => {
|
||||
this.del_anim = undefined;
|
||||
advance = undefined;
|
||||
this.del_anim = null;
|
||||
advance = null;
|
||||
stop?.();
|
||||
};
|
||||
|
||||
@@ -38,10 +38,10 @@ var sprite = {
|
||||
var done = false;
|
||||
if (reverse) {
|
||||
f = (((f - 1) % playing.frames.length) + playing.frames.length) % playing.frames.length;
|
||||
if (f === playing.frames.length - 1) done = true;
|
||||
if (f == playing.frames.length - 1) done = true;
|
||||
} else {
|
||||
f = (f + 1) % playing.frames.length;
|
||||
if (f === 0) done = true;
|
||||
if (f == 0) done = true;
|
||||
}
|
||||
|
||||
this.image = playing.frames[f];
|
||||
@@ -102,11 +102,11 @@ var sprite = {
|
||||
},
|
||||
garbage: function() {
|
||||
this.del_anim?.();
|
||||
this.anim = undefined;
|
||||
this.anim = null;
|
||||
tree.delete(this._sprite)
|
||||
this.transform.parent = undefined
|
||||
this.transform.parent = null
|
||||
for (var t of this.transform.children())
|
||||
t.parent = undefined
|
||||
t.parent = null
|
||||
delete this.transform.sprite
|
||||
delete this._sprite
|
||||
// log.console("CLEARED SPRITE")
|
||||
@@ -216,7 +216,7 @@ sprite.to_queue = function(ysort = false)
|
||||
};
|
||||
var culled = sprite.tree.query(camrect)
|
||||
if (culled.length == 0) return [];
|
||||
var cmd = graphics.make_sprite_queue(culled, prosperon.camera, undefined, 1);
|
||||
var cmd = graphics.make_sprite_queue(culled, prosperon.camera, null, 1);
|
||||
return cmd;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,18 +11,18 @@ var input = use('input')
|
||||
var lay_ctx = layout.make_context();
|
||||
|
||||
var clay_base = {
|
||||
font: undefined,
|
||||
background_image: undefined,
|
||||
font: null,
|
||||
background_image: null,
|
||||
slice: 0,
|
||||
font: 'smalle.16',
|
||||
font_size: undefined,
|
||||
font_size: null,
|
||||
color: [1,1,1,1],
|
||||
spacing:0,
|
||||
padding:0,
|
||||
margin:0,
|
||||
offset:[0,0],
|
||||
size:undefined,
|
||||
background_color: undefined
|
||||
size:null,
|
||||
background_color: null
|
||||
};
|
||||
|
||||
var root_item;
|
||||
@@ -125,8 +125,8 @@ function add_item(config)
|
||||
// Adjust for child_gap
|
||||
if (root_config._childIndex > 0) {
|
||||
var parentContain = root_config.contain || 0;
|
||||
var isVStack = (parentContain & layout.contain.column) !== 0;
|
||||
var isHStack = (parentContain & layout.contain.row) !== 0;
|
||||
var isVStack = (parentContain & layout.contain.column) != 0;
|
||||
var isHStack = (parentContain & layout.contain.row) != 0;
|
||||
|
||||
if (isVStack) {
|
||||
margin.t += childGap;
|
||||
@@ -162,7 +162,7 @@ function add_item(config)
|
||||
|
||||
function rectify_configs(config_array)
|
||||
{
|
||||
if (config_array.length === 0)
|
||||
if (config_array.length == 0)
|
||||
config_array = [{}];
|
||||
|
||||
for (var i = config_array.length-1; i > 0; i--)
|
||||
@@ -216,8 +216,8 @@ clay.button = function button(str, action, config = {})
|
||||
config.action = action;
|
||||
}
|
||||
|
||||
var hovered = undefined;
|
||||
clay.newframe = function() { hovered = undefined; }
|
||||
var hovered = null;
|
||||
clay.newframe = function() { hovered = null; }
|
||||
|
||||
// mousepos given in hud coordinates
|
||||
clay.draw_commands = function draw_commands(cmds, pos = [0,0], mousepos = prosperon.camera.screen2hud(input.mouse.screenpos()))
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
function tohex(n) {
|
||||
var s = Math.floor(n).toString(16);
|
||||
if (s.length === 1) s = "0" + s;
|
||||
if (s.length == 1) s = "0" + s;
|
||||
return s.toUpperCase();
|
||||
};
|
||||
|
||||
@@ -98,14 +98,14 @@ Color.normalize = function (c) {
|
||||
};
|
||||
|
||||
for (var p of Object.keys(c)) {
|
||||
if (typeof c[p] !== "object") continue;
|
||||
if (typeof c[p] != "object") continue;
|
||||
if (!Array.isArray(c[p])) {
|
||||
Color.normalize(c[p]);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Add alpha channel if not present
|
||||
if (c[p].length === 3) {
|
||||
if (c[p].length == 3) {
|
||||
c[p][3] = 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -107,9 +107,9 @@ input.mouse.normal.doc = "Set the mouse to show again after hiding.";
|
||||
|
||||
input.keyboard = {};
|
||||
input.keyboard.down = function (code) {
|
||||
if (typeof code === "number") return downkeys[code];
|
||||
if (typeof code === "string") return downkeys[code.toUpperCase().charCodeAt()] || downkeys[code.toLowerCase().charCodeAt()];
|
||||
return undefined;
|
||||
if (typeof code == "number") return downkeys[code];
|
||||
if (typeof code == "string") return downkeys[code.toUpperCase().charCodeAt()] || downkeys[code.toLowerCase().charCodeAt()];
|
||||
return null;
|
||||
};
|
||||
|
||||
input.print_pawn_kbm = function (pawn) {
|
||||
@@ -157,7 +157,7 @@ input.print_md_kbm = function print_md_kbm(pawn) {
|
||||
};
|
||||
|
||||
input.has_bind = function (pawn, bind) {
|
||||
return typeof pawn.inputs?.[bind] === "function";
|
||||
return typeof pawn.inputs?.[bind] == "function";
|
||||
};
|
||||
|
||||
input.action = {
|
||||
@@ -176,17 +176,17 @@ input.tabcomplete = function tabcomplete(val, list) {
|
||||
if (!val) return val;
|
||||
list = filter(x => x.startsWith(val))
|
||||
|
||||
if (list.length === 1) {
|
||||
if (list.length == 1) {
|
||||
return list[0];
|
||||
}
|
||||
|
||||
var ret = undefined;
|
||||
var ret = null;
|
||||
var i = val.length;
|
||||
while (!ret && list.length !== 0) {
|
||||
while (!ret && list.length != 0) {
|
||||
var char = list[0][i];
|
||||
if (
|
||||
!list.every(function (x) {
|
||||
return x[i] === char;
|
||||
return x[i] == char;
|
||||
})
|
||||
)
|
||||
ret = list[0].slice(0, i);
|
||||
@@ -213,7 +213,7 @@ var Player = {
|
||||
|
||||
mouse_input(type, ...args) {
|
||||
for (var pawn of [...this.pawns].reverse()) {
|
||||
if (typeof pawn.inputs?.mouse?.[type] === "function") {
|
||||
if (typeof pawn.inputs?.mouse?.[type] == "function") {
|
||||
pawn.inputs.mouse[type].call(pawn, ...args);
|
||||
pawn.inputs.post?.call(pawn);
|
||||
if (!pawn.inputs.fallthru) return;
|
||||
@@ -223,7 +223,7 @@ var Player = {
|
||||
|
||||
char_input(c) {
|
||||
for (var pawn of [...this.pawns].reverse()) {
|
||||
if (typeof pawn.inputs?.char === "function") {
|
||||
if (typeof pawn.inputs?.char == "function") {
|
||||
pawn.inputs.char.call(pawn, c);
|
||||
pawn.inputs.post?.call(pawn);
|
||||
if (!pawn.inputs.fallthru) return;
|
||||
@@ -270,16 +270,16 @@ var Player = {
|
||||
fn = inputs[cmd].released;
|
||||
break;
|
||||
case "down":
|
||||
if (typeof inputs[cmd].down === "function") fn = inputs[cmd].down;
|
||||
if (typeof inputs[cmd].down == "function") fn = inputs[cmd].down;
|
||||
else if (inputs[cmd].down) fn = inputs[cmd];
|
||||
}
|
||||
|
||||
var consumed = false;
|
||||
if (typeof fn === "function") {
|
||||
if (typeof fn == "function") {
|
||||
fn.call(pawn, ...args);
|
||||
consumed = true;
|
||||
}
|
||||
if (state === "released") inputs.release_post?.call(pawn);
|
||||
if (state == "released") inputs.release_post?.call(pawn);
|
||||
if (inputs.block) return;
|
||||
if (consumed) return;
|
||||
}
|
||||
|
||||
@@ -76,8 +76,8 @@ draw.point = function(pos, size, opt = {}, material) {
|
||||
})
|
||||
}
|
||||
|
||||
draw.ellipse = function(pos, radii, def, material) {
|
||||
var opt = def ? {...ellipse_def, ...def} : ellipse_def
|
||||
draw.ellipse = function(pos, radii, defl, material) {
|
||||
var opt = defl ? {...ellipse_def, ...defl} : ellipse_def
|
||||
if (opt.thickness <= 0) opt.thickness = Math.max(radii[0], radii[1])
|
||||
|
||||
add_command("draw_ellipse", {
|
||||
@@ -88,9 +88,9 @@ draw.ellipse = function(pos, radii, def, material) {
|
||||
})
|
||||
}
|
||||
|
||||
draw.line = function(points, def, material)
|
||||
draw.line = function(points, defl, material)
|
||||
{
|
||||
var opt = def ? {...line_def, ...def} : line_def
|
||||
var opt = defl ? {...line_def, ...defl} : line_def
|
||||
|
||||
add_command("draw_line", {
|
||||
points: points,
|
||||
@@ -99,24 +99,24 @@ draw.line = function(points, def, material)
|
||||
})
|
||||
}
|
||||
|
||||
draw.cross = function render_cross(pos, size, def, material) {
|
||||
draw.cross = function render_cross(pos, size, defl, material) {
|
||||
var a = [pos.add([0, size]), pos.add([0, -size])]
|
||||
var b = [pos.add([size, 0]), pos.add([-size, 0])]
|
||||
draw.line(a, def, material)
|
||||
draw.line(b, def, material)
|
||||
draw.line(a, defl, material)
|
||||
draw.line(b, defl, material)
|
||||
}
|
||||
|
||||
draw.arrow = function render_arrow(start, end, wingspan = 4, wingangle = 10, def, material) {
|
||||
draw.arrow = function render_arrow(start, end, wingspan = 4, wingangle = 10, defl, material) {
|
||||
var dir = math.norm(end.sub(start))
|
||||
var wing1 = [math.rotate(dir, wingangle).scale(wingspan).add(end), end]
|
||||
var wing2 = [math.rotate(dir, -wingangle).scale(wingspan).add(end), end]
|
||||
draw.line([start, end], def, material)
|
||||
draw.line(wing1, def, material)
|
||||
draw.line(wing2, def, material)
|
||||
draw.line([start, end], defl, material)
|
||||
draw.line(wing1, defl, material)
|
||||
draw.line(wing2, defl, material)
|
||||
}
|
||||
|
||||
draw.rectangle = function render_rectangle(rect, def, material) {
|
||||
var opt = def ? {...rect_def, ...def} : rect_def
|
||||
draw.rectangle = function render_rectangle(rect, defl, material) {
|
||||
var opt = defl ? {...rect_def, ...defl} : rect_def
|
||||
|
||||
add_command("draw_rect", {
|
||||
rect: rect,
|
||||
@@ -154,8 +154,8 @@ draw.image = function image(image, rect, rotation, anchor, shear, info, material
|
||||
})
|
||||
}
|
||||
|
||||
draw.circle = function render_circle(pos, radius, def, material) {
|
||||
draw.ellipse(pos, [radius,radius], def, material)
|
||||
draw.circle = function render_circle(pos, radius, defl, material) {
|
||||
draw.ellipse(pos, [radius,radius], defl, material)
|
||||
}
|
||||
|
||||
draw.text = function text(text, pos, font = 'fonts/c64.ttf', size = 8, color = color.white, wrap = 0) {
|
||||
|
||||
@@ -111,7 +111,7 @@ ex.draw = function()
|
||||
if (!diff) throw new Error("emitter does not have a proper diffuse texture")
|
||||
|
||||
var mesh = graphics.make_sprite_mesh(this.particles)
|
||||
if (mesh.num_indices === 0) return
|
||||
if (mesh.num_indices == 0) return
|
||||
render.queue({
|
||||
type:'geometry',
|
||||
mesh,
|
||||
|
||||
@@ -66,5 +66,5 @@ this.hud = function() {
|
||||
draw.images(bunnyTex, bunnies)
|
||||
|
||||
var msg = 'FPS: ' + fpsAvg.toFixed(2) + ' Bunnies: ' + bunnies.length
|
||||
draw.text(msg, {x:0, y:0, width:config.width, height:40}, undefined, 0, color.white, 0)
|
||||
draw.text(msg, {x:0, y:0, width:config.width, height:40}, null, 0, color.white, 0)
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ function updateTitle() {
|
||||
break;
|
||||
case 'connected':
|
||||
if (myColor) {
|
||||
title += (mover.turn === myColor ? "Your turn (" + myColor + ")" : "Opponent's turn (" + mover.turn + ")");
|
||||
title += (mover.turn == myColor ? "Your turn (" + myColor + ")" : "Opponent's turn (" + mover.turn + ")");
|
||||
} else {
|
||||
title += mover.turn + " turn";
|
||||
}
|
||||
@@ -64,10 +64,10 @@ var opponentHoldingPiece = false;
|
||||
var opponentSelectPos = null;
|
||||
|
||||
function handleMouseButtonDown(e) {
|
||||
if (e.which !== 0) return;
|
||||
if (e.which != 0) return;
|
||||
|
||||
// Don't allow piece selection unless we have an opponent
|
||||
if (gameState !== 'connected' || !opponent) return;
|
||||
if (gameState != 'connected' || !opponent) return;
|
||||
|
||||
var mx = e.mouse.x;
|
||||
var my = e.mouse.y;
|
||||
@@ -76,7 +76,7 @@ function handleMouseButtonDown(e) {
|
||||
if (!grid.inBounds(c)) return;
|
||||
|
||||
var cell = grid.at(c);
|
||||
if (cell.length && cell[0].colour === mover.turn) {
|
||||
if (cell.length && cell[0].colour == mover.turn) {
|
||||
selectPos = c;
|
||||
holdingPiece = true;
|
||||
// Send pickup notification to opponent
|
||||
@@ -92,10 +92,10 @@ function handleMouseButtonDown(e) {
|
||||
}
|
||||
|
||||
function handleMouseButtonUp(e) {
|
||||
if (e.which !== 0 || !holdingPiece || !selectPos) return;
|
||||
if (e.which != 0 || !holdingPiece || !selectPos) return;
|
||||
|
||||
// Don't allow moves unless we have an opponent and it's our turn
|
||||
if (gameState !== 'connected' || !opponent || !isMyTurn) {
|
||||
if (gameState != 'connected' || !opponent || !isMyTurn) {
|
||||
holdingPiece = false;
|
||||
return;
|
||||
}
|
||||
@@ -147,7 +147,7 @@ function handleMouseMotion(e) {
|
||||
hoverPos = c;
|
||||
|
||||
// Send mouse position to opponent in real-time
|
||||
if (opponent && gameState === 'connected') {
|
||||
if (opponent && gameState == 'connected') {
|
||||
send(opponent, {
|
||||
type: 'mouse_move',
|
||||
pos: c,
|
||||
@@ -159,11 +159,11 @@ function handleMouseMotion(e) {
|
||||
|
||||
function handleKeyDown(e) {
|
||||
// S key - start server
|
||||
if (e.scancode === 22 && gameState === 'waiting') { // S key
|
||||
if (e.scancode == 22 && gameState == 'waiting') { // S key
|
||||
startServer();
|
||||
}
|
||||
// J key - join server
|
||||
else if (e.scancode === 13 && gameState === 'waiting') { // J key
|
||||
else if (e.scancode == 13 && gameState == 'waiting') { // J key
|
||||
joinServer();
|
||||
}
|
||||
}
|
||||
@@ -181,8 +181,8 @@ var opponentMouseColor = [1.0, 0.0, 0.0, 1.0]; // Red for opponent mouse
|
||||
function drawBoard() {
|
||||
for (var y = 0; y < 8; ++y)
|
||||
for (var x = 0; x < 8; ++x) {
|
||||
var isMyHover = hoverPos && hoverPos[0] === x && hoverPos[1] === y;
|
||||
var isOpponentHover = opponentMousePos && opponentMousePos[0] === x && opponentMousePos[1] === y;
|
||||
var isMyHover = hoverPos && hoverPos[0] == x && hoverPos[1] == y;
|
||||
var isOpponentHover = opponentMousePos && opponentMousePos[0] == x && opponentMousePos[1] == y;
|
||||
var isValidMove = selectPos && holdingPiece && isValidMoveForTurn(selectPos, [x, y]);
|
||||
|
||||
var color = ((x+y)&1) ? dark : light;
|
||||
@@ -211,7 +211,7 @@ function isValidMoveForTurn(from, to) {
|
||||
|
||||
// Check if the destination has a piece of the same color
|
||||
var destCell = grid.at(to);
|
||||
if (destCell.length && destCell[0].colour === piece.colour) {
|
||||
if (destCell.length && destCell[0].colour == piece.colour) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -225,15 +225,15 @@ function drawPieces() {
|
||||
|
||||
// Skip drawing the piece being held (by me or opponent)
|
||||
if (holdingPiece && selectPos &&
|
||||
piece.coord[0] === selectPos[0] &&
|
||||
piece.coord[1] === selectPos[1]) {
|
||||
piece.coord[0] == selectPos[0] &&
|
||||
piece.coord[1] == selectPos[1]) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Skip drawing the piece being held by opponent
|
||||
if (opponentHoldingPiece && opponentSelectPos &&
|
||||
piece.coord[0] === opponentSelectPos[0] &&
|
||||
piece.coord[1] === opponentSelectPos[1]) {
|
||||
piece.coord[0] == opponentSelectPos[0] &&
|
||||
piece.coord[1] == opponentSelectPos[1]) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -329,10 +329,10 @@ $_.receiver(e => {
|
||||
send(e, update(e.dt))
|
||||
else if (e.kind == 'draw')
|
||||
send(e, draw())
|
||||
else if (e.type === 'game_start' || e.type === 'move' || e.type === 'greet')
|
||||
else if (e.type == 'game_start' || e.type == 'move' || e.type == 'greet')
|
||||
log.console("Receiver got message:", e.type, e);
|
||||
|
||||
if (e.type === 'greet') {
|
||||
if (e.type == 'greet') {
|
||||
log.console("Server received greet from client");
|
||||
// Store the client's actor object for ongoing communication
|
||||
opponent = e.client_actor;
|
||||
@@ -348,13 +348,13 @@ $_.receiver(e => {
|
||||
});
|
||||
log.console("game_start message sent to client");
|
||||
}
|
||||
else if (e.type === 'game_start') {
|
||||
else if (e.type == 'game_start') {
|
||||
log.console("Game starting, I am:", e.your_color);
|
||||
myColor = e.your_color;
|
||||
isMyTurn = (myColor === 'white');
|
||||
isMyTurn = (myColor == 'white');
|
||||
gameState = 'connected';
|
||||
updateTitle();
|
||||
} else if (e.type === 'move') {
|
||||
} else if (e.type == 'move') {
|
||||
log.console("Received move from opponent:", e.from, "to", e.to);
|
||||
// Apply opponent's move
|
||||
var fromCell = grid.at(e.from);
|
||||
@@ -370,26 +370,26 @@ $_.receiver(e => {
|
||||
} else {
|
||||
log.console("No piece found at from position");
|
||||
}
|
||||
} else if (e.type === 'mouse_move') {
|
||||
} else if (e.type == 'mouse_move') {
|
||||
// Update opponent's mouse position
|
||||
opponentMousePos = e.pos;
|
||||
opponentHoldingPiece = e.holding;
|
||||
opponentSelectPos = e.selectPos;
|
||||
} else if (e.type === 'piece_pickup') {
|
||||
} else if (e.type == 'piece_pickup') {
|
||||
// Opponent picked up a piece
|
||||
opponentSelectPos = e.pos;
|
||||
opponentHoldingPiece = true;
|
||||
} else if (e.type === 'piece_drop') {
|
||||
} else if (e.type == 'piece_drop') {
|
||||
// Opponent dropped their piece
|
||||
opponentHoldingPiece = false;
|
||||
opponentSelectPos = null;
|
||||
} else if (e.type === 'mouse_button_down') {
|
||||
} else if (e.type == 'mouse_button_down') {
|
||||
handleMouseButtonDown(e)
|
||||
} else if (e.type === 'mouse_button_up') {
|
||||
} else if (e.type == 'mouse_button_up') {
|
||||
handleMouseButtonUp(e)
|
||||
} else if (e.type === 'mouse_motion') {
|
||||
} else if (e.type == 'mouse_motion') {
|
||||
handleMouseMotion(e)
|
||||
} else if (e.type === 'key_down') {
|
||||
} else if (e.type == 'key_down') {
|
||||
handleKeyDown(e)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -1,57 +1,69 @@
|
||||
var CELLS = Symbol()
|
||||
|
||||
var key = function key(x,y) { return `${x},${y}` }
|
||||
|
||||
function grid(w, h)
|
||||
{
|
||||
this[CELLS] = new Map()
|
||||
this.width = w;
|
||||
function grid(w, h) {
|
||||
this.width = w;
|
||||
this.height = h;
|
||||
// create a height×width array of empty lists
|
||||
this.cells = new Array(h);
|
||||
for (let y = 0; y < h; y++) {
|
||||
this.cells[y] = new Array(w);
|
||||
for (let x = 0; x < w; x++) {
|
||||
this.cells[y][x] = []; // each cell holds its own list
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
grid.prototype = {
|
||||
cell(x,y) {
|
||||
var k = key(x,y)
|
||||
if (!this[CELLS].has(k)) this[CELLS].set(k,[])
|
||||
return this[CELLS].get(k)
|
||||
// return the array at (x,y)
|
||||
cell(x, y) {
|
||||
return this.cells[y][x];
|
||||
},
|
||||
|
||||
|
||||
// alias for cell
|
||||
at(pos) {
|
||||
return this.cell(pos.x, pos.y);
|
||||
},
|
||||
|
||||
// add an entity into a cell
|
||||
add(entity, pos) {
|
||||
this.cell(pos.x, pos.y).push(entity);
|
||||
entity.coord = pos.slice();
|
||||
},
|
||||
|
||||
remove(entity, pos) {
|
||||
var c = this.cell(pos.x, pos.y);
|
||||
c.splice(c.indexOf(entity), 1);
|
||||
},
|
||||
|
||||
at(pos) {
|
||||
return this.cell(pos.x, pos.y);
|
||||
},
|
||||
|
||||
inBounds(pos) {
|
||||
return pos.x >= 0 && pos.x < this.width && pos.y >= 0 && pos.y < this.height;
|
||||
},
|
||||
|
||||
each(fn) {
|
||||
for (var [k, list] of this[CELLS])
|
||||
for (var p of list) fn(p, p.coord);
|
||||
},
|
||||
|
||||
toString() {
|
||||
var out = `grid [${this.width}x${this.height}]
|
||||
`
|
||||
for (var y = 0; y < this.height; y++) {
|
||||
for (var x = 0; x < this.width; x++) {
|
||||
var cell = this.at([x,y]);
|
||||
out += cell.length
|
||||
}
|
||||
if (y !== this.height - 1) out += "\n"
|
||||
}
|
||||
|
||||
return out
|
||||
},
|
||||
}
|
||||
|
||||
return grid
|
||||
// remove an entity from a cell
|
||||
remove(entity, pos) {
|
||||
const c = this.cell(pos.x, pos.y);
|
||||
const i = c.indexOf(entity);
|
||||
if (i !== -1) c.splice(i, 1);
|
||||
},
|
||||
|
||||
// bounds check
|
||||
inBounds(pos) {
|
||||
return (
|
||||
pos.x >= 0 && pos.x < this.width &&
|
||||
pos.y >= 0 && pos.y < this.height
|
||||
);
|
||||
},
|
||||
|
||||
// call fn(entity, coord) for every entity in every cell
|
||||
each(fn) {
|
||||
for (let y = 0; y < this.height; y++) {
|
||||
for (let x = 0; x < this.width; x++) {
|
||||
const list = this.cells[y][x];
|
||||
for (let entity of list) {
|
||||
fn(entity, entity.coord);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// printable representation
|
||||
toString() {
|
||||
let out = `grid [${this.width}×${this.height}]\n`;
|
||||
for (let y = 0; y < this.height; y++) {
|
||||
for (let x = 0; x < this.width; x++) {
|
||||
out += this.cells[y][x].length;
|
||||
}
|
||||
if (y !== this.height - 1) out += "\n";
|
||||
}
|
||||
return out;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -5,17 +5,17 @@ var MovementSystem = function(grid, rules) {
|
||||
}
|
||||
|
||||
MovementSystem.prototype.tryMove = function (piece, to) {
|
||||
if (piece.colour !== this.turn) return false;
|
||||
if (piece.colour != this.turn) return false;
|
||||
|
||||
// normalise ‘to’ into our hybrid coord
|
||||
var dest = [to.x !== undefined ? to.x : to[0],
|
||||
to.y !== undefined ? to.y : to[1]];
|
||||
var dest = [to.x ?? t[0],
|
||||
to.y ?? to[1]];
|
||||
|
||||
if (!this.grid.inBounds(dest)) return false;
|
||||
if (!this.rules.canMove(piece, piece.coord, dest, this.grid)) return false;
|
||||
|
||||
var victims = this.grid.at(dest);
|
||||
if (victims.length && victims[0].colour === piece.colour) return false;
|
||||
if (victims.length && victims[0].colour == piece.colour) return false;
|
||||
if (victims.length) victims[0].captured = true;
|
||||
|
||||
this.grid.remove(piece, piece.coord);
|
||||
@@ -25,7 +25,7 @@ MovementSystem.prototype.tryMove = function (piece, to) {
|
||||
piece.coord.x = dest.x;
|
||||
piece.coord.y = dest.y;
|
||||
|
||||
this.turn = (this.turn === 'white') ? 'black' : 'white';
|
||||
this.turn = (this.turn == 'white') ? 'black' : 'white';
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,32 +1,32 @@
|
||||
/* helper – robust coord access */
|
||||
function cx(c) { return (c.x !== undefined) ? c.x : c[0]; }
|
||||
function cy(c) { return (c.y !== undefined) ? c.y : c[1]; }
|
||||
function cx(c) { return c.x ?? c[0] }
|
||||
function cy(c) { return c.y ?? c[1] }
|
||||
|
||||
/* simple move-shape checks */
|
||||
var deltas = {
|
||||
pawn: function (pc, dx, dy, grid, to) {
|
||||
var dir = (pc.colour === 'white') ? -1 : 1;
|
||||
var base = (pc.colour === 'white') ? 6 : 1;
|
||||
var one = (dy === dir && dx === 0 && grid.at(to).length === 0);
|
||||
var two = (dy === 2 * dir && dx === 0 && cy(pc.coord) === base &&
|
||||
grid.at({ x: cx(pc.coord), y: cy(pc.coord)+dir }).length === 0 &&
|
||||
grid.at(to).length === 0);
|
||||
var cap = (dy === dir && Math.abs(dx) === 1 && grid.at(to).length);
|
||||
var dir = (pc.colour == 'white') ? -1 : 1;
|
||||
var base = (pc.colour == 'white') ? 6 : 1;
|
||||
var one = (dy == dir && dx == 0 && grid.at(to).length == 0);
|
||||
var two = (dy == 2 * dir && dx == 0 && cy(pc.coord) == base &&
|
||||
grid.at({ x: cx(pc.coord), y: cy(pc.coord)+dir }).length == 0 &&
|
||||
grid.at(to).length == 0);
|
||||
var cap = (dy == dir && Math.abs(dx) == 1 && grid.at(to).length);
|
||||
return one || two || cap;
|
||||
},
|
||||
rook : function (pc, dx, dy) { return (dx === 0 || dy === 0); },
|
||||
bishop: function (pc, dx, dy) { return Math.abs(dx) === Math.abs(dy); },
|
||||
queen : function (pc, dx, dy) { return (dx === 0 || dy === 0 || Math.abs(dx) === Math.abs(dy)); },
|
||||
knight: function (pc, dx, dy) { return (Math.abs(dx) === 1 && Math.abs(dy) === 2) ||
|
||||
(Math.abs(dx) === 2 && Math.abs(dy) === 1); },
|
||||
king : function (pc, dx, dy) { return Math.max(Math.abs(dx), Math.abs(dy)) === 1; }
|
||||
rook : function (pc, dx, dy) { return (dx == 0 || dy == 0); },
|
||||
bishop: function (pc, dx, dy) { return Math.abs(dx) == Math.abs(dy); },
|
||||
queen : function (pc, dx, dy) { return (dx == 0 || dy == 0 || Math.abs(dx) == Math.abs(dy)); },
|
||||
knight: function (pc, dx, dy) { return (Math.abs(dx) == 1 && Math.abs(dy) == 2) ||
|
||||
(Math.abs(dx) == 2 && Math.abs(dy) == 1); },
|
||||
king : function (pc, dx, dy) { return Math.max(Math.abs(dx), Math.abs(dy)) == 1; }
|
||||
};
|
||||
|
||||
function clearLine(from, to, grid) {
|
||||
var dx = Math.sign(cx(to) - cx(from));
|
||||
var dy = Math.sign(cy(to) - cy(from));
|
||||
var x = cx(from) + dx, y = cy(from) + dy;
|
||||
while (x !== cx(to) || y !== cy(to)) {
|
||||
while (x != cx(to) || y != cy(to)) {
|
||||
if (grid.at({ x: x, y: y }).length) return false;
|
||||
x += dx; y += dy;
|
||||
}
|
||||
@@ -38,7 +38,7 @@ function canMove(piece, from, to, grid) {
|
||||
var dy = cy(to) - cy(from);
|
||||
var f = deltas[piece.kind];
|
||||
if (!f || !f(piece, dx, dy, grid, to)) return false;
|
||||
if (piece.kind === 'knight') return true;
|
||||
if (piece.kind == 'knight') return true;
|
||||
return clearLine(from, to, grid);
|
||||
}
|
||||
|
||||
|
||||
@@ -82,5 +82,5 @@ this.hud = function() {
|
||||
|
||||
// Simple score display
|
||||
var msg = score1 + " " + score2
|
||||
draw.text(msg, {x:0, y:10, width:config.width, height:40}, undefined, 0, color.white, 0)
|
||||
draw.text(msg, {x:0, y:10, width:config.width, height:40}, null, 0, color.white, 0)
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ function spawnApple() {
|
||||
apple = {x:Math.floor(Math.random()*gridW), y:Math.floor(Math.random()*gridH)}
|
||||
// Re-spawn if apple lands on snake
|
||||
for (var i=0; i<snake.length; i++)
|
||||
if (snake[i].x === apple.x && snake[i].y === apple.y) { spawnApple(); return }
|
||||
if (snake[i].x == apple.x && snake[i].y == apple.y) { spawnApple(); return }
|
||||
}
|
||||
|
||||
function wrap(pos) {
|
||||
@@ -49,7 +49,7 @@ function wrap(pos) {
|
||||
resetGame()
|
||||
|
||||
this.update = function(dt) {
|
||||
if (gameState !== "playing") return
|
||||
if (gameState != "playing") return
|
||||
moveTimer += dt
|
||||
if (moveTimer < moveInterval) return
|
||||
moveTimer -= moveInterval
|
||||
@@ -63,7 +63,7 @@ this.update = function(dt) {
|
||||
|
||||
// Check collision with body
|
||||
for (var i=0; i<snake.length; i++) {
|
||||
if (snake[i].x === head.x && snake[i].y === head.y) {
|
||||
if (snake[i].x == head.x && snake[i].y == head.y) {
|
||||
gameState = "gameover"
|
||||
return
|
||||
}
|
||||
@@ -73,7 +73,7 @@ this.update = function(dt) {
|
||||
snake.unshift(head)
|
||||
|
||||
// Eat apple?
|
||||
if (head.x === apple.x && head.y === apple.y) spawnApple()
|
||||
if (head.x == apple.x && head.y == apple.y) spawnApple()
|
||||
else snake.pop()
|
||||
}
|
||||
|
||||
@@ -90,9 +90,9 @@ this.hud = function() {
|
||||
// Draw apple
|
||||
draw.rectangle({x:apple.x*cellSize, y:apple.y*cellSize, width:cellSize, height:cellSize}, color.red)
|
||||
|
||||
if (gameState === "gameover") {
|
||||
if (gameState == "gameover") {
|
||||
var msg = "GAME OVER! Press SPACE to restart."
|
||||
draw.text(msg, {x:0, y:config.height*0.5-10, width:config.width, height:20}, undefined, 0, color.white)
|
||||
draw.text(msg, {x:0, y:config.height*0.5-10, width:config.width, height:20}, null, 0, color.white)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,19 +100,19 @@ this.hud = function() {
|
||||
// "Up" means y=1, so going physically up on screen
|
||||
this.inputs = {
|
||||
up: function() {
|
||||
if (direction.y !== -1) nextDirection = {x:0,y:1}
|
||||
if (direction.y != -1) nextDirection = {x:0,y:1}
|
||||
},
|
||||
down: function() {
|
||||
if (direction.y !== 1) nextDirection = {x:0,y:-1}
|
||||
if (direction.y != 1) nextDirection = {x:0,y:-1}
|
||||
},
|
||||
left: function() {
|
||||
if (direction.x !== 1) nextDirection = {x:-1,y:0}
|
||||
if (direction.x != 1) nextDirection = {x:-1,y:0}
|
||||
},
|
||||
right: function() {
|
||||
if (direction.x !== -1) nextDirection = {x:1,y:0}
|
||||
if (direction.x != -1) nextDirection = {x:1,y:0}
|
||||
},
|
||||
space: function() {
|
||||
if (gameState==="gameover") resetGame()
|
||||
if (gameState=="gameover") resetGame()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -128,7 +128,7 @@ function end_game(score) {
|
||||
update_stat(STATS.TOTAL_SCORE, total_score, false);
|
||||
|
||||
// Check for achievements
|
||||
if (games_played === 1) {
|
||||
if (games_played == 1) {
|
||||
unlock_achievement(ACHIEVEMENTS.FIRST_WIN);
|
||||
}
|
||||
|
||||
|
||||
@@ -128,10 +128,10 @@ function clearLines() {
|
||||
}
|
||||
}
|
||||
// Score
|
||||
if (lines===1) score += 100
|
||||
else if (lines===2) score += 300
|
||||
else if (lines===3) score += 500
|
||||
else if (lines===4) score += 800
|
||||
if (lines==1) score += 100
|
||||
else if (lines==2) score += 300
|
||||
else if (lines==3) score += 500
|
||||
else if (lines==4) score += 800
|
||||
linesCleared += lines
|
||||
level = Math.floor(linesCleared/10)
|
||||
}
|
||||
@@ -153,7 +153,7 @@ spawnPiece()
|
||||
this.update = function(dt) {
|
||||
if (gameOver) return
|
||||
|
||||
// ========== Horizontal Movement Gate ==========
|
||||
// ======= Horizontal Movement Gate =======
|
||||
var leftPressed = input.keyboard.down('a')
|
||||
var rightPressed = input.keyboard.down('d')
|
||||
var horizontalMove = 0
|
||||
@@ -191,7 +191,7 @@ this.update = function(dt) {
|
||||
hMoveTimer -= dt
|
||||
prevLeft = leftPressed
|
||||
prevRight = rightPressed
|
||||
// ========== End Horizontal Movement Gate ==========
|
||||
// ======= End Horizontal Movement Gate =======
|
||||
|
||||
// Rotate with W (once per press, no spinning)
|
||||
if (input.keyboard.down('w')) {
|
||||
@@ -249,7 +249,7 @@ this.hud = function() {
|
||||
}
|
||||
|
||||
// Next piece window
|
||||
draw.text("Next", {x:70, y:5, width:50, height:10}, undefined, 0, color.white)
|
||||
draw.text("Next", {x:70, y:5, width:50, height:10}, null, 0, color.white)
|
||||
if (nextPiece) {
|
||||
for (var i=0; i<nextPiece.blocks.length; i++) {
|
||||
var nx = nextPiece.blocks[i][0]
|
||||
@@ -262,10 +262,10 @@ this.hud = function() {
|
||||
|
||||
// Score & Level
|
||||
var info = "Score: " + score + "\nLines: " + linesCleared + "\nLevel: " + level
|
||||
draw.text(info, {x:70, y:30, width:90, height:50}, undefined, 0, color.white)
|
||||
draw.text(info, {x:70, y:30, width:90, height:50}, null, 0, color.white)
|
||||
|
||||
if (gameOver) {
|
||||
draw.text("GAME OVER", {x:10, y:config.height*0.5-5, width:config.width-20, height:20}, undefined, 0, color.red)
|
||||
draw.text("GAME OVER", {x:10, y:config.height*0.5-5, width:config.width-20, height:20}, null, 0, color.red)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -46,9 +46,9 @@ geometry.sphere.volume[cell.DOC] = `
|
||||
`
|
||||
|
||||
geometry.sphere.random = function (r, theta = [0, 1], phi = [-0.5, 0.5]) {
|
||||
if (typeof r === "number") r = [r, r]
|
||||
if (typeof theta === "number") theta = [theta, theta]
|
||||
if (typeof phi === "number") phi = [phi, phi]
|
||||
if (typeof r == "number") r = [r, r]
|
||||
if (typeof theta == "number") theta = [theta, theta]
|
||||
if (typeof phi == "number") phi = [phi, phi]
|
||||
|
||||
var ra = Math.random_range(r[0], r[1])
|
||||
var ta = Math.turn2rad(Math.random_range(theta[0], theta[1]))
|
||||
|
||||
@@ -18,13 +18,13 @@ var CPU = Symbol()
|
||||
var LASTUSE = Symbol()
|
||||
var LOADING = Symbol()
|
||||
|
||||
var cache = new Map()
|
||||
var cache = {}
|
||||
|
||||
// Image constructor function
|
||||
graphics.Image = function(surfaceData) {
|
||||
// Initialize private properties
|
||||
this[CPU] = surfaceData || undefined;
|
||||
this[GPU] = undefined;
|
||||
this[CPU] = surfaceData || null;
|
||||
this[GPU] = null;
|
||||
this[LOADING] = false;
|
||||
this[LASTUSE] = time.number();
|
||||
this.rect = {x:0, y:0, width:surfaceData.width, height:surfaceData.height};
|
||||
@@ -89,11 +89,11 @@ Object.defineProperties(graphics.Image.prototype, {
|
||||
|
||||
// Add methods to prototype
|
||||
graphics.Image.prototype.unload_gpu = function() {
|
||||
this[GPU] = undefined
|
||||
this[GPU] = null
|
||||
}
|
||||
|
||||
graphics.Image.prototype.unload_cpu = function() {
|
||||
this[CPU] = undefined
|
||||
this[CPU] = null
|
||||
}
|
||||
|
||||
function calc_image_size(img) {
|
||||
@@ -123,7 +123,7 @@ function make_handle(obj)
|
||||
}
|
||||
|
||||
function wrapSurface(surf, maybeRect){
|
||||
const h = make_handle(surf);
|
||||
def h = make_handle(surf);
|
||||
if(maybeRect) h.rect = maybeRect; /* honour frame sub-rect */
|
||||
return h;
|
||||
}
|
||||
@@ -150,7 +150,7 @@ function decode_image(bytes, ext)
|
||||
|
||||
function create_image(path){
|
||||
try{
|
||||
const bytes = io.slurpbytes(path);
|
||||
def bytes = io.slurpbytes(path);
|
||||
|
||||
let raw = decode_image(bytes, path.ext());
|
||||
|
||||
@@ -169,8 +169,8 @@ function create_image(path){
|
||||
return makeAnim( wrapFrames(raw.frames), !!raw.loop );
|
||||
|
||||
/* ── Case D: ASE helpers returned { animName:{frames,loop}, … } ── */
|
||||
const anims = {};
|
||||
for(const [name, anim] of Object.entries(raw)){
|
||||
def anims = {};
|
||||
for(def [name, anim] of Object.entries(raw)){
|
||||
if(anim && Array.isArray(anim.frames))
|
||||
anims[name] = makeAnim( wrapFrames(anim.frames), !!anim.loop );
|
||||
else if(anim && anim.surface) /* ase with flat surface */
|
||||
@@ -219,7 +219,7 @@ graphics.is_image[cell.DOC] = `
|
||||
|
||||
graphics.texture_from_data = function(data)
|
||||
{
|
||||
if (!(data instanceof ArrayBuffer)) return undefined
|
||||
if (!(data instanceof ArrayBuffer)) return null
|
||||
|
||||
var image = graphics.make_texture(data);
|
||||
var img = make_handle(image)
|
||||
@@ -236,7 +236,7 @@ graphics.from_surface = function(id, surf)
|
||||
|
||||
graphics.from = function(id, data)
|
||||
{
|
||||
if (typeof id !== 'string')
|
||||
if (typeof id != 'string')
|
||||
throw new Error('Expected a string ID')
|
||||
|
||||
if (data instanceof ArrayBuffer)
|
||||
@@ -246,18 +246,18 @@ graphics.from = function(id, data)
|
||||
graphics.texture = function texture(path) {
|
||||
if (path instanceof graphics.Image) return path
|
||||
|
||||
if (typeof path !== 'string')
|
||||
if (typeof path != 'string')
|
||||
throw new Error('need a string for graphics.texture')
|
||||
|
||||
var id = path //.split(':')[0]
|
||||
if (cache.has(id)) return cache.get(id)
|
||||
if (cache[id]) return cache[id]
|
||||
|
||||
var ipath = res.find_image(id)
|
||||
if (!ipath)
|
||||
throw new Error(`unknown image ${id}`)
|
||||
|
||||
var image = create_image(ipath)
|
||||
cache.set(id, image)
|
||||
cache[id] = image
|
||||
return image
|
||||
}
|
||||
graphics.texture[cell.DOC] = `
|
||||
@@ -365,8 +365,8 @@ Load a font from file if not cached, or retrieve from cache if already loaded.
|
||||
`
|
||||
|
||||
graphics.queue_sprite_mesh = function(queue) {
|
||||
var sprites = queue.filter(x => x.type === 'sprite')
|
||||
if (sprites.length === 0) return []
|
||||
var sprites = queue.filter(x => x.type == 'sprite')
|
||||
if (sprites.length == 0) return []
|
||||
var mesh = graphics.make_sprite_mesh(sprites)
|
||||
for (var i = 0; i < sprites.length; i++) {
|
||||
sprites[i].mesh = mesh
|
||||
|
||||
@@ -17,7 +17,7 @@ function imtoggle(name, obj, field) {
|
||||
var changed = false;
|
||||
var old = obj[field];
|
||||
obj[field] = imgui.checkbox(name, obj[field]);
|
||||
if (old !== obj[field]) return true;
|
||||
if (old != obj[field]) return true;
|
||||
return false;
|
||||
};
|
||||
|
||||
@@ -32,7 +32,7 @@ if (render_menu) {
|
||||
if (debug.console)
|
||||
debug.console = imgui.window("console", _ => {
|
||||
imgui.text(log.transcript);
|
||||
replstr = imgui.textinput(undefined, replstr);
|
||||
replstr = imgui.textinput(null, replstr);
|
||||
imgui.button("submit", _ => {
|
||||
eval(replstr);
|
||||
replstr = "";
|
||||
@@ -242,14 +242,14 @@ imgui.imagebutton[cell.DOC] = `Create an ImageButton widget which displays a tex
|
||||
imgui.textinput[cell.DOC] = `Show a single-line text input widget.
|
||||
|
||||
:param label: The label text next to the input box.
|
||||
:param text: The current text. If undefined, the box starts empty.
|
||||
:param text: The current text. If null, the box starts empty.
|
||||
:return: The updated text string after user editing.
|
||||
`;
|
||||
|
||||
imgui.textbox[cell.DOC] = `Show a multi-line text input widget.
|
||||
|
||||
:param label: The label text next to the input box.
|
||||
:param text: The current multi-line text. If undefined, starts empty.
|
||||
:param text: The current multi-line text. If null, starts empty.
|
||||
:return: The updated text after user editing.
|
||||
`;
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ var video
|
||||
var cnf = use('accio/config')
|
||||
|
||||
$_.start(e => {
|
||||
if (e.type !== 'greet') return
|
||||
if (e.type != 'greet') return
|
||||
video = e.actor
|
||||
graphics = use('graphics', video)
|
||||
send(video, {kind:"window", op:"makeRenderer"}, e => {
|
||||
@@ -36,16 +36,16 @@ var geometry = use('geometry')
|
||||
|
||||
function updateCameraMatrix(camera, winW, winH) {
|
||||
// world→NDC
|
||||
const sx = 1 / camera.size[0];
|
||||
const sy = 1 / camera.size[1];
|
||||
const ox = camera.pos[0] - camera.size[0] * camera.anchor[0];
|
||||
const oy = camera.pos[1] - camera.size[1] * camera.anchor[1];
|
||||
def sx = 1 / camera.size[0];
|
||||
def sy = 1 / camera.size[1];
|
||||
def ox = camera.pos[0] - camera.size[0] * camera.anchor[0];
|
||||
def oy = camera.pos[1] - camera.size[1] * camera.anchor[1];
|
||||
|
||||
// NDC→pixels
|
||||
const vx = camera.viewport.x * winW;
|
||||
const vy = camera.viewport.y * winH;
|
||||
const vw = camera.viewport.width * winW;
|
||||
const vh = camera.viewport.height * winH;
|
||||
def vx = camera.viewport.x * winW;
|
||||
def vy = camera.viewport.y * winH;
|
||||
def vw = camera.viewport.width * winW;
|
||||
def vh = camera.viewport.height * winH;
|
||||
|
||||
// final “mat” coefficients
|
||||
// [ a 0 c ]
|
||||
@@ -82,14 +82,14 @@ function screenToWorldPoint(pos, camera) {
|
||||
//---- rectangle (two corner) ----
|
||||
function worldToScreenRect(rect, camera) {
|
||||
// map bottom-left and top-right
|
||||
const x1 = camera.a * rect.x + camera.c;
|
||||
const y1 = camera.e * rect.y + camera.f;
|
||||
const x2 = camera.a * (rect.x + rect.width) + camera.c;
|
||||
const y2 = camera.e * (rect.y + rect.height) + camera.f;
|
||||
def x1 = camera.a * rect.x + camera.c;
|
||||
def y1 = camera.e * rect.y + camera.f;
|
||||
def x2 = camera.a * (rect.x + rect.width) + camera.c;
|
||||
def y2 = camera.e * (rect.y + rect.height) + camera.f;
|
||||
|
||||
// pick mins and abs deltas
|
||||
const x0 = x1 < x2 ? x1 : x2;
|
||||
const y0 = y1 < y2 ? y1 : y2;
|
||||
def x0 = x1 < x2 ? x1 : x2;
|
||||
def y0 = y1 < y2 ? y1 : y2;
|
||||
return {
|
||||
x: x0,
|
||||
y: y0,
|
||||
@@ -108,7 +108,7 @@ var camera = {
|
||||
ortho:true,
|
||||
anchor:[0.5,0.5],//{x:0.5,y:0.5},
|
||||
rotation:[0,0,0,1],
|
||||
surface: undefined
|
||||
surface: null
|
||||
}
|
||||
|
||||
var util = use('util')
|
||||
@@ -145,15 +145,15 @@ function translate_draw_commands(commands) {
|
||||
// Handle rectangles with optional rounding and thickness
|
||||
if (cmd.opt && cmd.opt.radius && cmd.opt.radius > 0) {
|
||||
// Rounded rectangle
|
||||
var thickness = (cmd.opt.thickness === 0) ? 0 : (cmd.opt.thickness || 1)
|
||||
var thickness = (cmd.opt.thickness == 0) ? 0 : (cmd.opt.thickness || 1)
|
||||
var raster_result = rasterize.round_rect(cmd.rect, cmd.opt.radius, thickness)
|
||||
|
||||
if (raster_result.type === 'rect') {
|
||||
if (raster_result.type == 'rect') {
|
||||
renderer_commands.push({
|
||||
op: "fillRect",
|
||||
data: {rect: raster_result.data}
|
||||
})
|
||||
} else if (raster_result.type === 'rects') {
|
||||
} else if (raster_result.type == 'rects') {
|
||||
raster_result.data.forEach(function(rect) {
|
||||
renderer_commands.push({
|
||||
op: "fillRect",
|
||||
@@ -165,12 +165,12 @@ function translate_draw_commands(commands) {
|
||||
// Outlined rectangle
|
||||
var raster_result = rasterize.outline_rect(cmd.rect, cmd.opt.thickness)
|
||||
|
||||
if (raster_result.type === 'rect') {
|
||||
if (raster_result.type == 'rect') {
|
||||
renderer_commands.push({
|
||||
op: "fillRect",
|
||||
data: {rect: raster_result.data}
|
||||
})
|
||||
} else if (raster_result.type === 'rects') {
|
||||
} else if (raster_result.type == 'rects') {
|
||||
renderer_commands.push({
|
||||
op: "rects",
|
||||
data: {rects: raster_result.data}
|
||||
@@ -191,12 +191,12 @@ function translate_draw_commands(commands) {
|
||||
var radii = cmd.radii || [cmd.radius, cmd.radius]
|
||||
var raster_result = rasterize.ellipse(cmd.pos, radii, cmd.opt || {})
|
||||
|
||||
if (raster_result.type === 'points') {
|
||||
if (raster_result.type == 'points') {
|
||||
renderer_commands.push({
|
||||
op: "point",
|
||||
data: {points: raster_result.data}
|
||||
})
|
||||
} else if (raster_result.type === 'rects') {
|
||||
} else if (raster_result.type == 'rects') {
|
||||
// Use 'rects' operation for multiple rectangles
|
||||
renderer_commands.push({
|
||||
op: "rects",
|
||||
@@ -260,6 +260,7 @@ function translate_draw_commands(commands) {
|
||||
return graphics.texture(tile)
|
||||
})
|
||||
var geom = geometry.tilemap_to_data(cmd.tilemap)
|
||||
if (!texid) break
|
||||
if (texid.gpu)
|
||||
geom.texture_id = texid.gpu.id
|
||||
|
||||
@@ -277,13 +278,13 @@ function translate_draw_commands(commands) {
|
||||
var parseq = use('parseq', $_.delay)
|
||||
|
||||
// Wrap `send(actor,msg,cb)` into a parseq “requestor”
|
||||
// • on success: cb(data) → value=data, reason=undefined
|
||||
// • on failure: cb(undefined,err)
|
||||
// • on success: cb(data) → value=data, reason=null
|
||||
// • on failure: cb(null,err)
|
||||
function rpc_req(actor, msg) {
|
||||
return (cb, _) => {
|
||||
send(actor, msg, data => {
|
||||
if (data.error)
|
||||
cb(undefined, data)
|
||||
cb(null, data)
|
||||
else
|
||||
cb(data)
|
||||
})
|
||||
@@ -311,7 +312,7 @@ var input_state = {
|
||||
function poll_input() {
|
||||
send(video, {kind:'input', op:'get'}, evs => {
|
||||
for (var ev of evs) {
|
||||
if (ev.type === 'quit')
|
||||
if (ev.type == 'quit')
|
||||
$_.stop()
|
||||
|
||||
if (ev.type.includes('mouse')) {
|
||||
@@ -335,7 +336,7 @@ function poll_input() {
|
||||
|
||||
// 2) helper to build & send a batch, then call done()
|
||||
function create_batch(draw_cmds, done) {
|
||||
const batch = [
|
||||
def batch = [
|
||||
{op:'set', prop:'drawColor', value:[0.1,0.1,0.15,1]},
|
||||
{op:'clear'}
|
||||
]
|
||||
@@ -349,8 +350,8 @@ function create_batch(draw_cmds, done) {
|
||||
)
|
||||
|
||||
send(video, {kind:'renderer', op:'batch', data:batch}, () => {
|
||||
const now = time.number()
|
||||
const dt = now - last_time
|
||||
def now = time.number()
|
||||
def dt = now - last_time
|
||||
last_time = now
|
||||
|
||||
frames.push(dt)
|
||||
@@ -376,7 +377,7 @@ function start_pipeline() {
|
||||
|
||||
function render_step() {
|
||||
// a) fire off the next update→draw immediately
|
||||
const dt = time.number() - last_time
|
||||
def dt = time.number() - last_time
|
||||
send(gameactor, {kind:'update', dt:1/60}, () =>
|
||||
send(gameactor, {kind:'draw'}, cmds => pending_next = cmds)
|
||||
)
|
||||
@@ -390,8 +391,8 @@ function render_step() {
|
||||
}
|
||||
|
||||
// d) schedule the next render step
|
||||
const render_dur = time.number() - last_time
|
||||
const wait = Math.max(0, 1/60 - ttr)
|
||||
def render_dur = time.number() - last_time
|
||||
def wait = Math.max(0, 1/60 - ttr)
|
||||
$_.delay(render_step, 0)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ rasterize.ellipse = function ellipse(pos, radii, opt) {
|
||||
ry_i = ry - thickness
|
||||
var hole = (rx_i > 0 && ry_i > 0)
|
||||
|
||||
if (!hole && thickness === 1) {
|
||||
if (!hole && thickness == 1) {
|
||||
var points = []
|
||||
var rx_sq = rx * rx, ry_sq = ry * ry
|
||||
var two_rx_sq = rx_sq << 1, two_ry_sq = ry_sq << 1
|
||||
@@ -82,9 +82,9 @@ rasterize.ellipse = function ellipse(pos, radii, opt) {
|
||||
if (hole && Math.abs(dx) <= x_in) { run_start = null; continue }
|
||||
if (!within_wedge(dx, dy, start, end, full_circle)) { run_start = null; continue }
|
||||
|
||||
if (run_start === null) run_start = cx + dx
|
||||
if (run_start == null) run_start = cx + dx
|
||||
|
||||
var last = (dx === x_out)
|
||||
var last = (dx == x_out)
|
||||
var next_in_ring =
|
||||
!last &&
|
||||
!(hole && Math.abs(dx+1) <= x_in) &&
|
||||
|
||||
@@ -2,12 +2,12 @@ var io = use('io')
|
||||
|
||||
Object.defineProperty(Function.prototype, "hashify", {
|
||||
value: function () {
|
||||
var hash = new Map()
|
||||
var hash = {}
|
||||
var fn = this
|
||||
function hashified(...args) {
|
||||
var key = args[0]
|
||||
if (!hash.has(key)) hash.set(key, fn(...args))
|
||||
return hash.get(key)
|
||||
if (hash[key] == null) hash[key] = fn(...args)
|
||||
return hash[key]
|
||||
}
|
||||
return hashified
|
||||
},
|
||||
@@ -41,12 +41,12 @@ function isRecognizedExtension(ext) {
|
||||
}
|
||||
|
||||
function find_in_path(filename, exts = []) {
|
||||
if (typeof filename !== 'string') return undefined
|
||||
if (typeof filename != 'string') return null
|
||||
|
||||
if (filename.includes('.')) {
|
||||
var candidate = filename // possibly need "/" ?
|
||||
if (io.exists(candidate) && !io.is_directory(candidate)) return candidate
|
||||
return undefined
|
||||
return null
|
||||
}
|
||||
|
||||
// Only check extensions if exts is provided and not empty
|
||||
@@ -60,7 +60,7 @@ function find_in_path(filename, exts = []) {
|
||||
var candidate = filename
|
||||
if (io.exists(candidate) && !io.is_directory(candidate)) return candidate
|
||||
}
|
||||
return undefined
|
||||
return null
|
||||
}
|
||||
|
||||
// Return a canonical path (the real directory plus the path)
|
||||
|
||||
@@ -16,8 +16,8 @@ function add_timer(obj, fn, seconds) {
|
||||
var stop = function () {
|
||||
if (!timer) return
|
||||
timers.delete(stop)
|
||||
timer.fn = undefined
|
||||
timer = undefined
|
||||
timer.fn = null
|
||||
timer = null
|
||||
}
|
||||
|
||||
function execute() {
|
||||
@@ -45,7 +45,7 @@ globalThis.Register = {
|
||||
var fns = []
|
||||
|
||||
n.register = function (fn, oname) {
|
||||
if (typeof fn !== 'function') return
|
||||
if (typeof fn != 'function') return
|
||||
|
||||
var dofn = function (...args) {
|
||||
fn(...args)
|
||||
@@ -59,7 +59,7 @@ globalThis.Register = {
|
||||
|
||||
while (left <= right) {
|
||||
var mid = Math.floor((left + right) / 2)
|
||||
if (fns[mid] === dofn.layer) {
|
||||
if (fns[mid] == dofn.layer) {
|
||||
left = mid
|
||||
break
|
||||
} else if (fns[mid].layer < dofn.layer) left = mid + 1
|
||||
@@ -93,7 +93,7 @@ globalThis.Register = {
|
||||
Register.pull_registers = function pull_registers(obj) {
|
||||
var reggies = []
|
||||
for (var reg in Register.registries) {
|
||||
if (typeof obj[reg] === "function")
|
||||
if (typeof obj[reg] == "function")
|
||||
reggies.push(reg)
|
||||
}
|
||||
return reggies
|
||||
@@ -115,7 +115,7 @@ Register.check_registers = function check_registers(obj) {
|
||||
return
|
||||
}
|
||||
for (var reg in Register.registries) {
|
||||
if (typeof obj[reg] === "function")
|
||||
if (typeof obj[reg] == "function")
|
||||
Register.register_obj(obj,reg)
|
||||
}
|
||||
}
|
||||
@@ -203,9 +203,9 @@ actor.spawn = function spawn(script, config, actor_context) {
|
||||
prog.prog_fn.call(underling, actor_dollar)
|
||||
} catch(e) { throw e; }
|
||||
|
||||
if (underling[DEAD]) return undefined;
|
||||
if (underling[DEAD]) return null;
|
||||
|
||||
if (typeof config === 'object') Object.assign(underling, config)
|
||||
if (typeof config == 'object') Object.assign(underling, config)
|
||||
|
||||
if (!underling[REGGIES])
|
||||
underling.__proto__[REGGIES] = Register.pull_registers(underling)
|
||||
@@ -238,8 +238,8 @@ actor.kill = function kill() {
|
||||
this[OVERLING][UNDERLINGS].delete(this)
|
||||
delete this[UNDERLINGS]
|
||||
|
||||
if (typeof this.garbage === "function") this.garbage()
|
||||
if (typeof this.then === "function") this.then()
|
||||
if (typeof this.garbage == "function") this.garbage()
|
||||
if (typeof this.then == "function") this.then()
|
||||
|
||||
act.tag_clear_guid(this)
|
||||
}
|
||||
@@ -264,7 +264,7 @@ function eachobj(obj, fn) {
|
||||
var val = fn(obj)
|
||||
if (val) return val
|
||||
for (var o in obj.objects) {
|
||||
if (obj.objects[o] === obj) log.error(`Object ${obj.toString()} is referenced by itself.`)
|
||||
if (obj.objects[o] == obj) log.error(`Object ${obj.toString()} is referenced by itself.`)
|
||||
val = eachobj(obj.objects[o], fn)
|
||||
if (val) return val
|
||||
}
|
||||
@@ -276,7 +276,7 @@ ex.all_objects = function (fn, startobj = world) {
|
||||
ex.all_objects[cell.DOC] = `
|
||||
:param fn: A callback function that receives each object. If it returns a truthy value, iteration stops and that value is returned.
|
||||
:param startobj: The root object at which iteration begins, default is the global "world".
|
||||
:return: The first truthy value returned by fn, or undefined if none.
|
||||
:return: The first truthy value returned by fn, or null if none.
|
||||
Iterate over each object (and its sub-objects) in the hierarchy, calling fn for each one.
|
||||
`
|
||||
|
||||
@@ -379,10 +379,10 @@ var script_fn = function script_fn(path, args) {
|
||||
// Create a context object with args
|
||||
var context = Object.create(parsed.module_ret)
|
||||
context.__args__ = args || []
|
||||
var mod_script = `(function setup_${module_name}_module(){ var self = this; var $ = this; var exports = {}; var module = {exports: exports}; var define = undefined; var arg = this.__args__; ${parsed.module}})`
|
||||
var mod_script = `(function setup_${module_name}_module(){ var self = this; var $ = this; var exports = {}; var module = {exports: exports}; var define = null; var arg = this.__args__; ${parsed.module}})`
|
||||
var module_fn = js.eval(file, mod_script)
|
||||
parsed.module_ret = module_fn.call(context)
|
||||
if (parsed.module_ret === undefined || parsed.module_ret === null)
|
||||
if (parsed.module_ret == null || parsed.module_ret == null)
|
||||
throw new Error(`Module ${module_name} must return a value`)
|
||||
parsed.module_fn = module_fn
|
||||
}
|
||||
|
||||
@@ -138,14 +138,14 @@ function get_pipeline_ubo_slot(pipeline, name) {
|
||||
if (ubo.name.endsWith(name))
|
||||
return i;
|
||||
}
|
||||
return undefined;
|
||||
return null;
|
||||
}
|
||||
|
||||
get_pipeline_ubo_slot[cell.DOC] = `Return the index of a uniform buffer block within the pipeline's vertex reflection data by name suffix.
|
||||
|
||||
:param pipeline: The pipeline whose vertex reflection is inspected.
|
||||
:param name: A string suffix to match against the uniform buffer block name.
|
||||
:return: The integer index of the matching UBO, or undefined if not found.
|
||||
:return: The integer index of the matching UBO, or null if not found.
|
||||
`
|
||||
|
||||
function transpose4x4(val) {
|
||||
@@ -181,7 +181,7 @@ function ubo_obj_to_array(pipeline, name, obj) {
|
||||
var val = obj[mem.name];
|
||||
if (!val) throw new Error (`Could not find ${mem.name} on supplied object`);
|
||||
|
||||
if (mem.name === 'model')
|
||||
if (mem.name == 'model')
|
||||
val = transpose4x4(val.array());
|
||||
|
||||
for (var i = 0; i < val.length; i++)
|
||||
@@ -226,9 +226,9 @@ var shader_times = {};
|
||||
function make_pipeline(pipeline) {
|
||||
if (pipeline.hasOwnProperty("gpu")) return; // this pipeline has already been made
|
||||
|
||||
if (typeof pipeline.vertex === 'string')
|
||||
if (typeof pipeline.vertex == 'string')
|
||||
pipeline.vertex = make_shader(pipeline.vertex);
|
||||
if (typeof pipeline.fragment === 'string')
|
||||
if (typeof pipeline.fragment == 'string')
|
||||
pipeline.fragment = make_shader(pipeline.fragment)
|
||||
|
||||
// 1) Reflection data for vertex shader
|
||||
@@ -309,7 +309,7 @@ function make_shader(sh_file) {
|
||||
num_textures: 0,
|
||||
num_storage_buffers: refl.separate_storage_buffers ? refl.separate_storage_buffers.length : 0,
|
||||
num_uniform_buffers: refl.ubos ? refl.ubos.length : 0,
|
||||
entrypoint: shader_type === "msl" ? "main0" : "main"
|
||||
entrypoint: shader_type == "msl" ? "main0" : "main"
|
||||
}
|
||||
|
||||
shader.gpu = context.make_shader(shader)
|
||||
@@ -349,7 +349,7 @@ var std_sampler = {
|
||||
function upload_model(model) {
|
||||
var bufs = [];
|
||||
for (var i in model) {
|
||||
if (typeof model[i] !== 'object') continue;
|
||||
if (typeof model[i] != 'object') continue;
|
||||
bufs.push(model[i]);
|
||||
}
|
||||
context.upload(this, bufs);
|
||||
@@ -405,7 +405,7 @@ bind_mat[cell.DOC] = `Bind the material images and samplers needed by the pipeli
|
||||
`
|
||||
|
||||
function group_sprites_by_texture(sprites, mesh) {
|
||||
if (sprites.length === 0) return;
|
||||
if (sprites.length == 0) return;
|
||||
for (var i = 0; i < sprites.length; i++) {
|
||||
sprites[i].mesh = mesh;
|
||||
sprites[i].first_index = i*6;
|
||||
@@ -418,7 +418,7 @@ function group_sprites_by_texture(sprites, mesh) {
|
||||
var group = {image:sprites[0].image, first_index:0};
|
||||
var count = 1;
|
||||
for (var i = 1; i < sprites.length; i++) {
|
||||
if (sprites[i].image === group.image) {
|
||||
if (sprites[i].image == group.image) {
|
||||
count++;
|
||||
continue;
|
||||
}
|
||||
@@ -495,7 +495,7 @@ function render_camera(cmds, camera) {
|
||||
|
||||
buffers = buffers.concat(graphics.queue_sprite_mesh(hud_queue));
|
||||
for (var q of hud_queue)
|
||||
if (q.type === 'geometry') buffers = buffers.concat([q.mesh.pos, q.mesh.color, q.mesh.uv, q.mesh.indices]);
|
||||
if (q.type == 'geometry') buffers = buffers.concat([q.mesh.pos, q.mesh.color, q.mesh.uv, q.mesh.indices]);
|
||||
|
||||
full_upload(buffers)
|
||||
|
||||
@@ -505,11 +505,11 @@ function render_camera(cmds, camera) {
|
||||
bind_pipeline(pass,pipeline);
|
||||
|
||||
var camslot = get_pipeline_ubo_slot(pipeline, 'TransformBuffer');
|
||||
if (typeof camslot !== 'undefined')
|
||||
if (camslot != null)
|
||||
cmds.camera(camera, camslot);
|
||||
|
||||
modelslot = get_pipeline_ubo_slot(pipeline, "model");
|
||||
if (typeof modelslot !== 'undefined') {
|
||||
if (modelslot != null) {
|
||||
var ubo = ubo_obj_to_array(pipeline, 'model', sprite_model_ubo);
|
||||
cmds.push_vertex_uniform_data(modelslot, ubo);
|
||||
}
|
||||
@@ -537,7 +537,7 @@ function render_camera(cmds, camera) {
|
||||
|
||||
cmds.push_debug_group("hud")
|
||||
var camslot = get_pipeline_ubo_slot(pipeline, 'TransformBuffer');
|
||||
if (typeof camslot !== 'undefined')
|
||||
if (camslot != null)
|
||||
cmds.hud(camera.size, camslot);
|
||||
|
||||
for (var group of hud_queue) {
|
||||
@@ -651,7 +651,7 @@ var stencil_invert = {
|
||||
};
|
||||
|
||||
function mask(image, pos, scale, rotation = 0, ref = 1) {
|
||||
if (typeof image === 'string')
|
||||
if (typeof image == 'string')
|
||||
image = graphics.texture(image);
|
||||
|
||||
var tex = image.texture;
|
||||
@@ -661,7 +661,7 @@ function mask(image, pos, scale, rotation = 0, ref = 1) {
|
||||
var pipe = stencil_writer(ref);
|
||||
render.use_shader('sprite.cg', pipe);
|
||||
var t = new transform;
|
||||
t.trs(pos, undefined, scale);
|
||||
t.trs(pos, null, scale);
|
||||
set_model(t);
|
||||
render.use_mat({
|
||||
diffuse:image.texture,
|
||||
|
||||
@@ -17,8 +17,8 @@ var default_window = {
|
||||
height: 480,
|
||||
|
||||
// Position - can be numbers or "centered"
|
||||
x: undefined, // SDL_WINDOWPOS_UNDEFINED by default
|
||||
y: undefined, // SDL_WINDOWPOS_UNDEFINED by default
|
||||
x: null, // SDL_WINDOWPOS_null by default
|
||||
y: null, // SDL_WINDOWPOS_null by default
|
||||
|
||||
// Window behavior flags
|
||||
resizable: true,
|
||||
@@ -52,7 +52,7 @@ var default_window = {
|
||||
metal: false, // Force Metal context (macOS)
|
||||
|
||||
// Advanced properties
|
||||
parent: undefined, // Parent window for tooltips/popups/modal
|
||||
parent: null, // Parent window for tooltips/popups/modal
|
||||
modal: false, // Modal to parent window (requires parent)
|
||||
externalGraphicsContext: false, // Use external graphics context
|
||||
|
||||
@@ -129,7 +129,7 @@ function handle_window(msg) {
|
||||
switch (msg.op) {
|
||||
case 'destroy':
|
||||
win.destroy();
|
||||
win = undefined
|
||||
win = null
|
||||
return {success: true};
|
||||
|
||||
case 'show':
|
||||
@@ -145,7 +145,7 @@ function handle_window(msg) {
|
||||
if (!prop) return {error: "Missing property name"};
|
||||
|
||||
// Handle special cases
|
||||
if (prop === 'surface') {
|
||||
if (prop == 'surface') {
|
||||
var surf = win.surface;
|
||||
if (!surf) return {data: null};
|
||||
var surf_id = allocate_id();
|
||||
@@ -157,12 +157,12 @@ function handle_window(msg) {
|
||||
|
||||
case 'set':
|
||||
var prop = msg.data ? msg.data.property : null;
|
||||
var value = msg.data ? msg.data.value : undefined;
|
||||
var value = msg.data ? msg.data.value : null;
|
||||
if (!prop) return {error: "Missing property name"};
|
||||
|
||||
// Validate property is settable
|
||||
var readonly = ['id', 'pixelDensity', 'displayScale', 'sizeInPixels', 'flags', 'surface'];
|
||||
if (readonly.indexOf(prop) !== -1) {
|
||||
if (readonly.indexOf(prop) != -1) {
|
||||
return {error: "Property '" + prop + "' is read-only"};
|
||||
}
|
||||
|
||||
@@ -220,7 +220,7 @@ function handle_window(msg) {
|
||||
// Renderer operation functions
|
||||
var renderfuncs = {
|
||||
destroy: function(msg) {
|
||||
ren = undefined
|
||||
ren = null
|
||||
return {success: true};
|
||||
},
|
||||
|
||||
@@ -244,9 +244,9 @@ var renderfuncs = {
|
||||
if (!prop) return {error: "Missing property name"};
|
||||
|
||||
// Handle special getters that might return objects
|
||||
if (prop === 'drawColor') {
|
||||
if (prop == 'drawColor') {
|
||||
var color = ren[prop];
|
||||
if (color && typeof color === 'object') {
|
||||
if (color && typeof color == 'object') {
|
||||
// Convert color object to array format [r,g,b,a]
|
||||
return {data: [color.r || 0, color.g || 0, color.b || 0, color.a || 255]};
|
||||
}
|
||||
@@ -264,12 +264,12 @@ var renderfuncs = {
|
||||
|
||||
// Validate property is settable
|
||||
var readonly = ['window', 'name', 'outputSize', 'currentOutputSize', 'logicalPresentationRect', 'safeArea'];
|
||||
if (readonly.indexOf(prop) !== -1) {
|
||||
if (readonly.indexOf(prop) != -1) {
|
||||
return {error: "Property '" + prop + "' is read-only"};
|
||||
}
|
||||
|
||||
// Special handling for render target
|
||||
if (prop === 'target' && value !== null && value !== undefined) {
|
||||
if (prop == 'target' && value != null && value != null) {
|
||||
var tex = resources.texture[value];
|
||||
if (!tex) return {error: "Invalid texture id"};
|
||||
value = tex;
|
||||
@@ -468,7 +468,7 @@ function handle_renderer(msg) {
|
||||
// Texture operations
|
||||
function handle_texture(msg) {
|
||||
// Special case: create needs a renderer
|
||||
if (msg.op === 'create') {
|
||||
if (msg.op == 'create') {
|
||||
if (!msg.data) return {error: "Missing texture data"};
|
||||
var ren_id = msg.data.renderer_id;
|
||||
if (!ren_id || !resources.renderer[ren_id]) return {error: "Invalid renderer id"};
|
||||
@@ -522,12 +522,12 @@ function handle_texture(msg) {
|
||||
|
||||
case 'set':
|
||||
var prop = msg.data ? msg.data.property : null;
|
||||
var value = msg.data ? msg.data.value : undefined;
|
||||
var value = msg.data ? msg.data.value : null;
|
||||
if (!prop) return {error: "Missing property name"};
|
||||
|
||||
// Validate property is settable
|
||||
var readonly = ['size', 'width', 'height'];
|
||||
if (readonly.indexOf(prop) !== -1) {
|
||||
if (readonly.indexOf(prop) != -1) {
|
||||
return {error: "Property '" + prop + "' is read-only"};
|
||||
}
|
||||
|
||||
@@ -616,12 +616,12 @@ function handle_mouse(msg) {
|
||||
|
||||
switch (msg.op) {
|
||||
case 'show':
|
||||
if (msg.data === undefined) return {error: "Missing show parameter"};
|
||||
if (msg.data == null) return {error: "Missing show parameter"};
|
||||
mouse.show(msg.data);
|
||||
return {success: true};
|
||||
|
||||
case 'capture':
|
||||
if (msg.data === undefined) return {error: "Missing capture parameter"};
|
||||
if (msg.data == null) return {error: "Missing capture parameter"};
|
||||
mouse.capture(msg.data);
|
||||
return {success: true};
|
||||
|
||||
@@ -655,7 +655,7 @@ function handle_mouse(msg) {
|
||||
if (!cursor) return {data: null};
|
||||
// Find or create cursor ID
|
||||
for (var id in resources.cursor) {
|
||||
if (resources.cursor[id] === cursor) {
|
||||
if (resources.cursor[id] == cursor) {
|
||||
return {data: id};
|
||||
}
|
||||
}
|
||||
@@ -669,7 +669,7 @@ function handle_mouse(msg) {
|
||||
if (!cursor) return {data: null};
|
||||
// Find or create cursor ID
|
||||
for (var id in resources.cursor) {
|
||||
if (resources.cursor[id] === cursor) {
|
||||
if (resources.cursor[id] == cursor) {
|
||||
return {data: id};
|
||||
}
|
||||
}
|
||||
@@ -679,7 +679,7 @@ function handle_mouse(msg) {
|
||||
return {data: cursor_id};
|
||||
|
||||
case 'create_system_cursor':
|
||||
if (msg.data === undefined) return {error: "Missing cursor type"};
|
||||
if (msg.data == null) return {error: "Missing cursor type"};
|
||||
var cursor = mouse.create_system_cursor(msg.data);
|
||||
var cursor_id = allocate_id();
|
||||
resources.cursor[cursor_id] = cursor;
|
||||
@@ -690,7 +690,7 @@ function handle_mouse(msg) {
|
||||
if (!window) return {data: null};
|
||||
// Find window ID
|
||||
for (var id in resources.window) {
|
||||
if (resources.window[id] === window) {
|
||||
if (resources.window[id] == window) {
|
||||
return {data: id};
|
||||
}
|
||||
}
|
||||
@@ -717,7 +717,7 @@ function handle_keyboard(msg) {
|
||||
if (!window) return {data: null};
|
||||
// Find window ID
|
||||
for (var id in resources.window) {
|
||||
if (resources.window[id] === window) {
|
||||
if (resources.window[id] == window) {
|
||||
return {data: id};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ audio.cry = function cry(file) {
|
||||
if (!voice) return;
|
||||
return function() {
|
||||
voice.stop();
|
||||
voice = undefined;
|
||||
voice = null;
|
||||
}
|
||||
};
|
||||
audio.cry[doc.sym] =
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* anim.js – drop this at top of your script or in a module */
|
||||
var Anim = (() => {
|
||||
const DEFAULT_MIN = 1 / 60; /* 16 ms – one frame */
|
||||
def DEFAULT_MIN = 1 / 60; /* 16 ms – one frame */
|
||||
|
||||
function play(source, loop=true){
|
||||
return {
|
||||
@@ -13,9 +13,9 @@ var Anim = (() => {
|
||||
|
||||
function update(a, dt){
|
||||
a.timer += dt;
|
||||
const frames = a.src.frames;
|
||||
def frames = a.src.frames;
|
||||
while(true){
|
||||
const time = Math.max(frames[a.idx].time || 0, Anim.minDelay);
|
||||
def time = Math.max(frames[a.idx].time || 0, Anim.minDelay);
|
||||
if(a.timer < time) break; /* still on current frame */
|
||||
|
||||
a.timer -= time;
|
||||
@@ -29,7 +29,7 @@ var Anim = (() => {
|
||||
}
|
||||
|
||||
function current(a){ return a.src.frames[a.idx].image; }
|
||||
function updateAll(arr, dt){ for(const a of arr) update(a, dt); }
|
||||
function updateAll(arr, dt){ for(def a of arr) update(a, dt); }
|
||||
function draw(a, pos, opt, pipe){
|
||||
draw2d.image(current(a), pos, 0, [0,0], [0,0], opt, pipe);
|
||||
}
|
||||
@@ -53,17 +53,17 @@ var camera = {
|
||||
fov:50,
|
||||
near_z: 0,
|
||||
far_z: 1000,
|
||||
surface: undefined,
|
||||
surface: null,
|
||||
viewport: {x:0,y:0,width:1,height:1},
|
||||
ortho:true,
|
||||
anchor:[0,0],
|
||||
}
|
||||
|
||||
/* ── load animations ───────────────────── */
|
||||
const crab = gfx.texture('tests/crab'); // gif → Animation
|
||||
const warrior = gfx.texture('tests/warrior'); // ase → {Original:Animation}
|
||||
def crab = gfx.texture('tests/crab'); // gif → Animation
|
||||
def warrior = gfx.texture('tests/warrior'); // ase → {Original:Animation}
|
||||
|
||||
const anims = [
|
||||
def anims = [
|
||||
Anim.play(crab), // crab.frames
|
||||
Anim.play(warrior.Run) // warrior.Original.frames
|
||||
];
|
||||
@@ -76,8 +76,8 @@ Anim.minDelay = 1 / 100; // 10 ms, feel free to tune later
|
||||
let last = os.now();
|
||||
|
||||
function loop(){
|
||||
const now = os.now();
|
||||
const dt = now - last; // real frame time
|
||||
def now = os.now();
|
||||
def dt = now - last; // real frame time
|
||||
last = now;
|
||||
|
||||
Anim.updateAll(anims, dt);
|
||||
|
||||
@@ -18,7 +18,7 @@ var camera = {
|
||||
fov:50,
|
||||
near_z: 0,
|
||||
far_z: 1000,
|
||||
surface: undefined,
|
||||
surface: null,
|
||||
viewport: {x:0,y:0,width:1,height:1},
|
||||
ortho:true,
|
||||
anchor:[0,0],
|
||||
|
||||
@@ -19,7 +19,7 @@ var camera = {
|
||||
fov:50,
|
||||
near_z: 0,
|
||||
far_z: 1000,
|
||||
surface: undefined,
|
||||
surface: null,
|
||||
viewport: {x:0,y:0,width:1,height:1},
|
||||
ortho:true,
|
||||
anchor:[0.5,0.5],
|
||||
@@ -31,7 +31,7 @@ var hudcam = {
|
||||
fov:50,
|
||||
near_z: 0,
|
||||
far_z: 1000,
|
||||
surface: undefined,
|
||||
surface: null,
|
||||
viewport: {x:0,y:0,width:1,height:1},
|
||||
ortho:true,
|
||||
anchor:[0,0],
|
||||
|
||||
@@ -4,7 +4,7 @@ var json = use('json');
|
||||
|
||||
// Get list of cameras
|
||||
var cameras = camera.list();
|
||||
if (cameras.length === 0) {
|
||||
if (cameras.length == 0) {
|
||||
log.console("No cameras found!");
|
||||
$_. stop();
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ var json = use('json');
|
||||
|
||||
// Get first camera
|
||||
var cameras = camera.list();
|
||||
if (cameras.length === 0) {
|
||||
if (cameras.length == 0) {
|
||||
log.console("No cameras found!");
|
||||
$_.stop();
|
||||
}
|
||||
@@ -30,10 +30,10 @@ log.console(" Colorspace:", format.colorspace);
|
||||
// Handle camera approval
|
||||
var approved = false;
|
||||
$_.receiver(e => {
|
||||
if (e.type === 'camera_device_approved') {
|
||||
if (e.type == 'camera_device_approved') {
|
||||
log.console("\nCamera approved!");
|
||||
approved = true;
|
||||
} else if (e.type === 'camera_device_denied') {
|
||||
} else if (e.type == 'camera_device_denied') {
|
||||
log.error("Camera access denied!");
|
||||
$_.stop();
|
||||
}
|
||||
@@ -63,7 +63,7 @@ function capture_test() {
|
||||
log.console("\nTesting colorspace conversions:");
|
||||
|
||||
// Convert to sRGB if not already
|
||||
if (format.colorspace !== "srgb") {
|
||||
if (format.colorspace != "srgb") {
|
||||
try {
|
||||
var srgb_surf = surf.convert(surf.format, "srgb");
|
||||
log.console(" Converted to sRGB colorspace");
|
||||
@@ -89,7 +89,7 @@ function capture_test() {
|
||||
}
|
||||
|
||||
// If YUV format, try BT.709 (HD video standard)
|
||||
if (surf.format.indexOf("yuv") !== -1 || surf.format.indexOf("yuy") !== -1) {
|
||||
if (surf.format.indexOf("yuv") != -1 || surf.format.indexOf("yuy") != -1) {
|
||||
try {
|
||||
var hd_surf = surf.convert(surf.format, "bt709_limited");
|
||||
log.console(" Converted to BT.709 limited (HD video standard)");
|
||||
|
||||
@@ -41,7 +41,7 @@ if (cameras.length > 0) {
|
||||
// Try to find a 640x480 format
|
||||
var preferred_format = null;
|
||||
for (var i = 0; i < formats.length; i++) {
|
||||
if (formats[i].width === 640 && formats[i].height === 480) {
|
||||
if (formats[i].width == 640 && formats[i].height == 480) {
|
||||
preferred_format = formats[i];
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -20,10 +20,10 @@ var webcam_texture = null;
|
||||
|
||||
// Handle camera events
|
||||
$_.receiver(e => {
|
||||
if (e.type === 'camera_device_approved' && e.which === cam_id) {
|
||||
if (e.type == 'camera_device_approved' && e.which == cam_id) {
|
||||
log.console("Camera approved!");
|
||||
cam_approved = true;
|
||||
} else if (e.type === 'camera_device_denied' && e.which === cam_id) {
|
||||
} else if (e.type == 'camera_device_denied' && e.which == cam_id) {
|
||||
log.error("Camera access denied!");
|
||||
$_.stop();
|
||||
}
|
||||
@@ -67,7 +67,7 @@ send(video_actor, {
|
||||
|
||||
// List available cameras
|
||||
var cameras = camera.list();
|
||||
if (cameras.length === 0) {
|
||||
if (cameras.length == 0) {
|
||||
log.error("No cameras found!");
|
||||
log.console(json.encode(cameras))
|
||||
$_.stop();
|
||||
@@ -89,10 +89,10 @@ send(video_actor, {
|
||||
// Look for a 640x480 format with preferred colorspace
|
||||
var preferred_format = null;
|
||||
for (var i = 0; i < formats.length; i++) {
|
||||
if (formats[i].width === 640 && formats[i].height === 480) {
|
||||
if (formats[i].width == 640 && formats[i].height == 480) {
|
||||
preferred_format = formats[i];
|
||||
// Prefer JPEG or sRGB colorspace if available
|
||||
if (formats[i].colorspace === "jpeg" || formats[i].colorspace === "srgb") {
|
||||
if (formats[i].colorspace == "jpeg" || formats[i].colorspace == "srgb") {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ send(ioguy, {
|
||||
})
|
||||
|
||||
$_.receiver(e => {
|
||||
if (e.type === 'quit')
|
||||
if (e.type == 'quit')
|
||||
os.exit()
|
||||
else
|
||||
log.console(json.encode(e))
|
||||
|
||||
@@ -14,12 +14,12 @@ tilemap.for = function (map, fn) {
|
||||
for (var x = 0; x < map.tiles.length; x++) {
|
||||
if (!map.tiles[x]) continue;
|
||||
for (var y = 0; y < map.tiles[x].length; y++) {
|
||||
if (map.tiles[x][y] !== undefined) {
|
||||
if (map.tiles[x][y] != null) {
|
||||
var result = fn(map.tiles[x][y], {
|
||||
x: x + map.offset_x,
|
||||
y: y + map.offset_y
|
||||
});
|
||||
if (result !== undefined) {
|
||||
if (result != null) {
|
||||
map.tiles[x][y] = result;
|
||||
}
|
||||
}
|
||||
@@ -32,7 +32,7 @@ tilemap.prototype =
|
||||
at(pos) {
|
||||
var x = pos.x - this.offset_x;
|
||||
var y = pos.y - this.offset_y;
|
||||
if (!this.tiles[x]) return undefined;
|
||||
if (!this.tiles[x]) return null;
|
||||
return this.tiles[x][y];
|
||||
},
|
||||
|
||||
@@ -51,7 +51,7 @@ tilemap.prototype =
|
||||
for (var i = 0; i < this.tiles.length; i++) {
|
||||
if (!this.tiles[i]) this.tiles[i] = [];
|
||||
var new_col = [];
|
||||
for (var j = 0; j < shift; j++) new_col[j] = undefined;
|
||||
for (var j = 0; j < shift; j++) new_col[j] = null;
|
||||
this.tiles[i] = new_col.concat(this.tiles[i]);
|
||||
}
|
||||
this.offset_y = pos.y;
|
||||
|
||||
@@ -43,15 +43,15 @@ Ease.quint = make_easing_fns(5)
|
||||
|
||||
Ease.expo = {
|
||||
in(t) {
|
||||
return t === 0 ? 0 : Math.pow(2, 10 * t - 10)
|
||||
return t == 0 ? 0 : Math.pow(2, 10 * t - 10)
|
||||
},
|
||||
out(t) {
|
||||
return t === 1 ? 1 : 1 - Math.pow(2, -10 * t)
|
||||
return t == 1 ? 1 : 1 - Math.pow(2, -10 * t)
|
||||
},
|
||||
inout(t) {
|
||||
return t === 0
|
||||
return t == 0
|
||||
? 0
|
||||
: t === 1
|
||||
: t == 1
|
||||
? 1
|
||||
: t < 0.5
|
||||
? Math.pow(2, 20 * t - 10) / 2
|
||||
@@ -93,26 +93,26 @@ Ease.sine = {
|
||||
|
||||
Ease.elastic = {
|
||||
in(t) {
|
||||
return t === 0
|
||||
return t == 0
|
||||
? 0
|
||||
: t === 1
|
||||
: t == 1
|
||||
? 1
|
||||
: -Math.pow(2, 10 * t - 10) *
|
||||
Math.sin((t * 10 - 10.75) * this.c4)
|
||||
},
|
||||
out(t) {
|
||||
return t === 0
|
||||
return t == 0
|
||||
? 0
|
||||
: t === 1
|
||||
: t == 1
|
||||
? 1
|
||||
: Math.pow(2, -10 * t) *
|
||||
Math.sin((t * 10 - 0.75) * this.c4) +
|
||||
1
|
||||
},
|
||||
inout(t) {
|
||||
t === 0
|
||||
t == 0
|
||||
? 0
|
||||
: t === 1
|
||||
: t == 1
|
||||
? 1
|
||||
: t < 0.5
|
||||
? -(Math.pow(2, 20 * t - 10) * Math.sin((20 * t - 11.125) * this.c5)) / 2
|
||||
@@ -128,10 +128,10 @@ var tween = function (from, to, time, fn, cb) {
|
||||
|
||||
function cleanup() {
|
||||
stop()
|
||||
fn = undefined
|
||||
stop = undefined
|
||||
cb = undefined
|
||||
update = undefined
|
||||
fn = null
|
||||
stop = null
|
||||
cb = null
|
||||
update = null
|
||||
}
|
||||
|
||||
var update = function tween_update(dt) {
|
||||
@@ -159,8 +159,8 @@ var Tween = {
|
||||
var defn = Object.create(this.default)
|
||||
Object.assign(defn, options)
|
||||
|
||||
if (defn.loop === "circle") tvals.push(tvals[0])
|
||||
else if (defn.loop === "yoyo") {
|
||||
if (defn.loop == "circle") tvals.push(tvals[0])
|
||||
else if (defn.loop == "yoyo") {
|
||||
for (var i = tvals.length - 2; i >= 0; i--) tvals.push(tvals[i])
|
||||
}
|
||||
|
||||
@@ -170,15 +170,15 @@ var Tween = {
|
||||
|
||||
defn.fn = function (dt) {
|
||||
defn.accum += dt
|
||||
if (defn.accum >= defn.time && defn.loop === "hold") {
|
||||
if (typeof target === "string") obj[target] = tvals[tvals.length - 1]
|
||||
if (defn.accum >= defn.time && defn.loop == "hold") {
|
||||
if (typeof target == "string") obj[target] = tvals[tvals.length - 1]
|
||||
else target(tvals[tvals.length - 1])
|
||||
defn.pause()
|
||||
defn.cb.call(obj)
|
||||
return
|
||||
}
|
||||
defn.pct = (defn.accum % defn.time) / defn.time
|
||||
if (defn.loop === "none" && defn.accum >= defn.time) defn.stop()
|
||||
if (defn.loop == "none" && defn.accum >= defn.time) defn.stop()
|
||||
|
||||
var t = defn.whole ? defn.ease(defn.pct) : defn.pct
|
||||
var nval = t / slicelen
|
||||
@@ -186,7 +186,7 @@ var Tween = {
|
||||
nval -= i
|
||||
if (!defn.whole) nval = defn.ease(nval)
|
||||
|
||||
if (typeof target === "string") obj[target] = tvals[i].lerp(tvals[i + 1], nval)
|
||||
if (typeof target == "string") obj[target] = tvals[i].lerp(tvals[i + 1], nval)
|
||||
else target(tvals[i].lerp(tvals[i + 1], nval))
|
||||
}
|
||||
|
||||
@@ -199,7 +199,7 @@ var Tween = {
|
||||
}
|
||||
defn.restart = function () {
|
||||
defn.accum = 0
|
||||
if (typeof target === "string") obj[target] = tvals[0]
|
||||
if (typeof target == "string") obj[target] = tvals[0]
|
||||
else target(tvals[0])
|
||||
}
|
||||
defn.stop = function () {
|
||||
|
||||
180
scripts/base.cm
180
scripts/base.cm
@@ -1,30 +1,16 @@
|
||||
Object.mixin = function (target, source) {
|
||||
if (typeof source !== "object") return target;
|
||||
if (typeof source != "object") return target;
|
||||
Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
|
||||
return target;
|
||||
};
|
||||
|
||||
Object.mixin[cell.DOC] = `Copy all property descriptors from 'source' into 'target'.
|
||||
|
||||
:param target: The object that will receive properties.
|
||||
:param source: The object whose properties are to be copied.
|
||||
:return: The updated 'target' object.
|
||||
`;
|
||||
|
||||
Object.defineProperty(Object.prototype, "mixin", {
|
||||
value: function mixin(obj) {
|
||||
if (typeof obj === "string") obj = use(obj);
|
||||
if (typeof obj == "string") obj = use(obj);
|
||||
if (obj) Object.mixin(this, obj);
|
||||
},
|
||||
});
|
||||
|
||||
(Object.prototype.mixin)[cell.DOC] = `Mix properties from 'obj' into the current object. If 'obj' is a string,
|
||||
it first calls 'use(obj)' to retrieve the object.
|
||||
|
||||
:param obj: The object (or string reference to an object) to mix in.
|
||||
:return: None
|
||||
`;
|
||||
|
||||
/* STRING DEFS */
|
||||
Object.defineProperty(String.prototype, "rm", {
|
||||
value: function (index, endidx = index + 1) {
|
||||
@@ -32,28 +18,14 @@ Object.defineProperty(String.prototype, "rm", {
|
||||
},
|
||||
});
|
||||
|
||||
(String.prototype.rm)[cell.DOC] = `Remove characters from this string between 'index' (inclusive)
|
||||
and 'endidx' (exclusive). If 'endidx' is omitted, it defaults to 'index + 1'.
|
||||
|
||||
:param index: The starting index to remove.
|
||||
:param endidx: The ending index (exclusive).
|
||||
:return: A new string with the specified characters removed.
|
||||
`;
|
||||
|
||||
Object.defineProperty(String.prototype, "tolast", {
|
||||
value: function (val) {
|
||||
var idx = this.lastIndexOf(val);
|
||||
if (idx === -1) return this.slice();
|
||||
if (idx == -1) return this.slice();
|
||||
return this.slice(0, idx);
|
||||
},
|
||||
});
|
||||
|
||||
(String.prototype.tolast)[cell.DOC] = `Return the substring of this string up to the last occurrence of 'val'.
|
||||
If 'val' is not found, the entire string is returned.
|
||||
|
||||
:param val: The substring to locate from the end.
|
||||
:return: A substring up to the last occurrence of 'val'.
|
||||
`;
|
||||
|
||||
Object.defineProperty(String.prototype, "dir", {
|
||||
value: function () {
|
||||
@@ -62,11 +34,6 @@ Object.defineProperty(String.prototype, "dir", {
|
||||
},
|
||||
});
|
||||
|
||||
(String.prototype.dir)[cell.DOC] = `Return everything before the last slash ('/') in the string.
|
||||
If no slash is found, return an empty string.
|
||||
|
||||
:return: The directory portion of the path.
|
||||
`;
|
||||
|
||||
Object.defineProperty(String.prototype, "next", {
|
||||
value: function (char, from) {
|
||||
@@ -75,7 +42,7 @@ Object.defineProperty(String.prototype, "next", {
|
||||
else if (!from) from = 0;
|
||||
|
||||
var find = this.slice(from).search(char[0]);
|
||||
if (find === -1) return -1;
|
||||
if (find == -1) return -1;
|
||||
else return from + find;
|
||||
|
||||
var i = 0;
|
||||
@@ -89,14 +56,6 @@ Object.defineProperty(String.prototype, "next", {
|
||||
},
|
||||
});
|
||||
|
||||
(String.prototype.next)[cell.DOC] = `Search for the next occurrence of 'char' in this string, starting at 'from'.
|
||||
If 'char' is an array, any of those characters qualifies. Return the matching index,
|
||||
or -1 if none is found.
|
||||
|
||||
:param char: A character (or array of characters) to locate.
|
||||
:param from: The index to start from.
|
||||
:return: The index of the next occurrence, or -1 if not found.
|
||||
`;
|
||||
|
||||
Object.defineProperty(String.prototype, "prev", {
|
||||
value: function (char, from, count = 0) {
|
||||
@@ -110,20 +69,11 @@ Object.defineProperty(String.prototype, "prev", {
|
||||
count--;
|
||||
}
|
||||
|
||||
if (find === -1) return 0;
|
||||
if (find == -1) return 0;
|
||||
else return find;
|
||||
},
|
||||
});
|
||||
|
||||
(String.prototype.prev)[cell.DOC] = `Search for the previous occurrence of 'char' before index 'from'.
|
||||
If 'count' is greater than 1, skip multiple occurrences going backward.
|
||||
Return the found index or 0 if not found.
|
||||
|
||||
:param char: The character to locate.
|
||||
:param from: The index to start from (defaults to the end of the string).
|
||||
:param count: How many occurrences to skip backward (default 0).
|
||||
:return: The index of the previous occurrence, or 0 if not found.
|
||||
`;
|
||||
|
||||
Object.defineProperty(String.prototype, "strip_ext", {
|
||||
value: function () {
|
||||
@@ -131,11 +81,6 @@ Object.defineProperty(String.prototype, "strip_ext", {
|
||||
},
|
||||
});
|
||||
|
||||
(String.prototype.strip_ext)[cell.DOC] = `Return the string up to (but not including) the last '.' character.
|
||||
If '.' is not found, the entire string is returned.
|
||||
|
||||
:return: The string without its last extension.
|
||||
`;
|
||||
|
||||
Object.defineProperty(String.prototype, "ext", {
|
||||
value: function () {
|
||||
@@ -143,11 +88,6 @@ Object.defineProperty(String.prototype, "ext", {
|
||||
},
|
||||
});
|
||||
|
||||
(String.prototype.ext)[cell.DOC] = `Return the substring after the last '.' in this string.
|
||||
If '.' is not found, return an empty string.
|
||||
|
||||
:return: The file extension or an empty string.
|
||||
`;
|
||||
|
||||
Object.defineProperty(String.prototype, "up_path", {
|
||||
value: function () {
|
||||
@@ -158,70 +98,42 @@ Object.defineProperty(String.prototype, "up_path", {
|
||||
},
|
||||
});
|
||||
|
||||
(String.prototype.up_path)[cell.DOC] = `Go up one directory level from the current path, preserving the file name at the end.
|
||||
|
||||
:return: A new path string one directory up, with the base filename preserved.
|
||||
`;
|
||||
|
||||
Object.defineProperty(String.prototype, "fromlast", {
|
||||
value: function (val) {
|
||||
var idx = this.lastIndexOf(val);
|
||||
if (idx === -1) return "";
|
||||
if (idx == -1) return "";
|
||||
return this.slice(idx + 1);
|
||||
},
|
||||
});
|
||||
|
||||
(String.prototype.fromlast)[cell.DOC] = `Return the substring that appears after the last occurrence of 'val'.
|
||||
If 'val' is not found, an empty string is returned.
|
||||
|
||||
:param val: The substring to locate.
|
||||
:return: The substring after the last occurrence of 'val'.
|
||||
`;
|
||||
|
||||
Object.defineProperty(String.prototype, "tofirst", {
|
||||
value: function (val) {
|
||||
var idx = this.indexOf(val);
|
||||
if (idx === -1) return this.slice();
|
||||
if (idx == -1) return this.slice();
|
||||
return this.slice(0, idx);
|
||||
},
|
||||
});
|
||||
|
||||
(String.prototype.tofirst)[cell.DOC] = `Return the substring from the start of this string up to the first occurrence
|
||||
of 'val' (excluded). If 'val' is not found, the entire string is returned.
|
||||
|
||||
:param val: The substring to locate.
|
||||
:return: A substring up to the first occurrence of 'val'.
|
||||
`;
|
||||
|
||||
Object.defineProperty(String.prototype, "fromfirst", {
|
||||
value: function (val) {
|
||||
var idx = this.indexOf(val);
|
||||
if (idx === -1) return this;
|
||||
if (idx == -1) return this;
|
||||
return this.slice(idx + val.length);
|
||||
},
|
||||
});
|
||||
|
||||
(String.prototype.fromfirst)[cell.DOC] = `Return the substring after the first occurrence of 'val'.
|
||||
If 'val' is not found, the entire string is returned.
|
||||
|
||||
:param val: The substring to locate.
|
||||
:return: The substring after 'val', or the entire string if 'val' not found.
|
||||
`;
|
||||
|
||||
Object.defineProperty(String.prototype, "name", {
|
||||
value: function () {
|
||||
var idx = this.indexOf("/");
|
||||
if (idx === -1) return this.tolast(".");
|
||||
if (idx == -1) return this.tolast(".");
|
||||
return this.fromlast("/").tolast(".");
|
||||
},
|
||||
});
|
||||
|
||||
(String.prototype.name)[cell.DOC] = `Return the "name" portion of the path without extension.
|
||||
If no slash is found, it's up to the last '.' in the entire string.
|
||||
If there is a slash, it's from the last slash up to (but not including) the last '.'.
|
||||
|
||||
:return: The name portion of the path without extension.
|
||||
`;
|
||||
|
||||
Object.defineProperty(String.prototype, "set_name", {
|
||||
value: function (name) {
|
||||
@@ -230,12 +142,6 @@ Object.defineProperty(String.prototype, "set_name", {
|
||||
},
|
||||
});
|
||||
|
||||
(String.prototype.set_name)[cell.DOC] = `Set the base name (excluding extension) of the path to 'name', preserving
|
||||
the original directory and extension.
|
||||
|
||||
:param name: The new name to use.
|
||||
:return: A new path string with the updated name.
|
||||
`;
|
||||
|
||||
Object.defineProperty(String.prototype, "base", {
|
||||
value: function () {
|
||||
@@ -243,25 +149,15 @@ Object.defineProperty(String.prototype, "base", {
|
||||
},
|
||||
});
|
||||
|
||||
(String.prototype.base)[cell.DOC] = `Return the portion of this string after the last '/' character.
|
||||
If no '/' is present, the entire string is returned.
|
||||
|
||||
:return: The base name of the path.
|
||||
`;
|
||||
|
||||
Object.defineProperty(String.prototype, "updir", {
|
||||
value: function () {
|
||||
if (this.lastIndexOf("/") === this.length - 1) return this.slice(0, this.length - 1);
|
||||
if (this.lastIndexOf("/") == this.length - 1) return this.slice(0, this.length - 1);
|
||||
var dir = (this + "/").dir();
|
||||
return dir.dir();
|
||||
},
|
||||
});
|
||||
|
||||
(String.prototype.updir)[cell.DOC] = `Go up one directory from the current path, removing the last directory name.
|
||||
If the path ends with a slash, remove it first. Then remove the final directory.
|
||||
|
||||
:return: A new string representing one directory level up.
|
||||
`;
|
||||
|
||||
/* ARRAY DEFS */
|
||||
Object.defineProperty(Array.prototype, "filter!", {
|
||||
@@ -276,28 +172,15 @@ Object.defineProperty(Array.prototype, "filter!", {
|
||||
},
|
||||
});
|
||||
|
||||
(Array.prototype["filter!"])[cell.DOC] = `Perform an in-place filter of this array using the provided callback 'fn'.
|
||||
Any element for which 'fn' returns a falsy value is removed. The array is modified
|
||||
and then returned.
|
||||
|
||||
:param fn: A callback function(element, index, array) => boolean.
|
||||
:return: The filtered (modified) array.
|
||||
`;
|
||||
|
||||
Object.defineProperty(Array.prototype, "delete", {
|
||||
value: function(item) {
|
||||
var idx = this.indexOf(item);
|
||||
if (idx > -1) this.splice(idx,1);
|
||||
return undefined;
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
(Array.prototype.delete)[cell.DOC] = `Remove the first occurrence of 'item' from the array, if it exists.
|
||||
Returns undefined.
|
||||
|
||||
:param item: The item to remove.
|
||||
:return: undefined
|
||||
`;
|
||||
|
||||
Object.defineProperty(Array.prototype, "copy", {
|
||||
value: function () {
|
||||
@@ -309,32 +192,21 @@ Object.defineProperty(Array.prototype, "copy", {
|
||||
},
|
||||
});
|
||||
|
||||
(Array.prototype.copy)[cell.DOC] = `Return a deep copy of this array by applying 'deep_copy' to each element.
|
||||
The resulting array is entirely new.
|
||||
|
||||
:return: A new array that is a deep copy of the original.
|
||||
`;
|
||||
|
||||
Object.defineProperty(Array.prototype, "equal", {
|
||||
value: function equal(b) {
|
||||
if (this.length !== b.length) return false;
|
||||
if (this.length != b.length) return false;
|
||||
if (b == null) return false;
|
||||
if (this === b) return true;
|
||||
return JSON.stringify(this) === JSON.stringify(b);
|
||||
if (this == b) return true;
|
||||
return JSON.stringify(this) == JSON.stringify(b);
|
||||
|
||||
for (var i = 0; i < this.length; i++) {
|
||||
if (!this[i] === b[i]) return false;
|
||||
if (!this[i] == b[i]) return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
});
|
||||
|
||||
(Array.prototype.equal)[cell.DOC] = `Check if this array and array 'b' have the same elements in the same order.
|
||||
If they are of different lengths, return false. Otherwise compare them via JSON.
|
||||
|
||||
:param b: Another array to compare against.
|
||||
:return: True if they match, false otherwise.
|
||||
`;
|
||||
|
||||
Object.defineProperty(Array.prototype, "last", {
|
||||
value: function () {
|
||||
@@ -342,10 +214,6 @@ Object.defineProperty(Array.prototype, "last", {
|
||||
},
|
||||
});
|
||||
|
||||
(Array.prototype.last)[cell.DOC] = `Return the last element of this array. If the array is empty, returns undefined.
|
||||
|
||||
:return: The last element of the array, or undefined if empty.
|
||||
`;
|
||||
|
||||
Object.defineProperty(Array.prototype, "wrapped", {
|
||||
value: function (x) {
|
||||
@@ -355,12 +223,6 @@ Object.defineProperty(Array.prototype, "wrapped", {
|
||||
},
|
||||
});
|
||||
|
||||
(Array.prototype.wrapped)[cell.DOC] = `Return a copy of the array with the first 'x' elements appended to the end.
|
||||
Does not modify the original array.
|
||||
|
||||
:param x: The number of leading elements to re-append.
|
||||
:return: A new array with the leading elements wrapped to the end.
|
||||
`;
|
||||
|
||||
Object.defineProperty(Array.prototype, "wrap_idx", {
|
||||
value: function (x) {
|
||||
@@ -371,12 +233,6 @@ Object.defineProperty(Array.prototype, "wrap_idx", {
|
||||
},
|
||||
});
|
||||
|
||||
(Array.prototype.wrap_idx)[cell.DOC] = `Wrap the integer 'x' around this array's length, ensuring the resulting index
|
||||
lies within [0, this.length - 1].
|
||||
|
||||
:param x: The index to wrap.
|
||||
:return: A wrapped index within this array's bounds.
|
||||
`;
|
||||
|
||||
Object.defineProperty(Array.prototype, "mirrored", {
|
||||
value: function (x) {
|
||||
@@ -387,9 +243,3 @@ Object.defineProperty(Array.prototype, "mirrored", {
|
||||
},
|
||||
});
|
||||
|
||||
(Array.prototype.mirrored)[cell.DOC] = `Return a new array that appends a reversed copy (excluding the last element)
|
||||
of itself to the end. For example, [1,2,3] -> [1,2,3,2,1]. If the array has length
|
||||
<= 1, a copy of it is returned directly.
|
||||
|
||||
:return: A new "mirrored" array.
|
||||
`;
|
||||
|
||||
@@ -40,7 +40,7 @@ function parse_key(key) {
|
||||
function get_nested(obj, path) {
|
||||
var current = obj
|
||||
for (var segment of path) {
|
||||
if (!current || typeof current !== 'object') return undefined
|
||||
if (!current || typeof current != 'object') return null
|
||||
current = current[segment]
|
||||
}
|
||||
return current
|
||||
@@ -51,7 +51,7 @@ function set_nested(obj, path, value) {
|
||||
var current = obj
|
||||
for (var i = 0; i < path.length - 1; i++) {
|
||||
var segment = path[i]
|
||||
if (!current[segment] || typeof current[segment] !== 'object') {
|
||||
if (!current[segment] || typeof current[segment] != 'object') {
|
||||
current[segment] = {}
|
||||
}
|
||||
current = current[segment]
|
||||
@@ -62,8 +62,8 @@ function set_nested(obj, path, value) {
|
||||
// Parse value string into appropriate type
|
||||
function parse_value(str) {
|
||||
// Boolean
|
||||
if (str === 'true') return true
|
||||
if (str === 'false') return false
|
||||
if (str == 'true') return true
|
||||
if (str == 'false') return false
|
||||
|
||||
// Number (including underscores)
|
||||
var num_str = str.replace(/_/g, '')
|
||||
@@ -76,8 +76,8 @@ function parse_value(str) {
|
||||
|
||||
// Format value for display
|
||||
function format_value(val) {
|
||||
if (typeof val === 'string') return '"' + val + '"'
|
||||
if (typeof val === 'number' && val >= 1000) {
|
||||
if (typeof val == 'string') return '"' + val + '"'
|
||||
if (typeof val == 'number' && val >= 1000) {
|
||||
// Add underscores to large numbers
|
||||
return val.toString().replace(/\B(?=(\d{3})+(?!\d))/g, '_')
|
||||
}
|
||||
@@ -90,7 +90,7 @@ function print_config(obj, prefix = '') {
|
||||
var val = obj[key]
|
||||
var full_key = prefix ? prefix + '.' + key : key
|
||||
|
||||
if (val && typeof val === 'object' && !Array.isArray(val)) {
|
||||
if (val && typeof val == 'object' && !Array.isArray(val)) {
|
||||
print_config(val, full_key)
|
||||
} else {
|
||||
log.console(full_key + ' = ' + format_value(val))
|
||||
@@ -99,7 +99,7 @@ function print_config(obj, prefix = '') {
|
||||
}
|
||||
|
||||
// Main command handling
|
||||
if (args.length === 0) {
|
||||
if (args.length == 0) {
|
||||
print_help()
|
||||
$_.stop()
|
||||
return
|
||||
@@ -137,9 +137,9 @@ switch (command) {
|
||||
var path = parse_key(key)
|
||||
var value = get_nested(config, path)
|
||||
|
||||
if (value === undefined) {
|
||||
if (value == null) {
|
||||
log.error("Key not found: " + key)
|
||||
} else if (value && typeof value === 'object' && !Array.isArray(value)) {
|
||||
} else if (value && typeof value == 'object' && !Array.isArray(value)) {
|
||||
// Print all nested values
|
||||
print_config(value, key)
|
||||
} else {
|
||||
@@ -159,7 +159,7 @@ switch (command) {
|
||||
var value = parse_value(value_str)
|
||||
|
||||
// Validate system keys
|
||||
if (path[0] === 'system') {
|
||||
if (path[0] == 'system') {
|
||||
var valid_system_keys = [
|
||||
'ar_timer', 'actor_memory', 'net_service',
|
||||
'reply_timeout', 'actor_max', 'stack_max'
|
||||
@@ -193,7 +193,7 @@ switch (command) {
|
||||
|
||||
switch (actor_cmd) {
|
||||
case 'list':
|
||||
if (Object.keys(config.actors[actor_name]).length === 0) {
|
||||
if (Object.keys(config.actors[actor_name]).length == 0) {
|
||||
log.console("No configuration for actor: " + actor_name)
|
||||
} else {
|
||||
log.console("# Configuration for actor: " + actor_name)
|
||||
@@ -212,7 +212,7 @@ switch (command) {
|
||||
var path = parse_key(key)
|
||||
var value = get_nested(config.actors[actor_name], path)
|
||||
|
||||
if (value === undefined) {
|
||||
if (value == null) {
|
||||
log.error("Key not found for actor " + actor_name + ": " + key)
|
||||
} else {
|
||||
log.console('actors.' + actor_name + '.' + key + ' = ' + format_value(value))
|
||||
|
||||
@@ -5,20 +5,20 @@ function docOf(obj, prop) {
|
||||
|
||||
// 1) If `block` is a string, that's the entire doc for `obj`.
|
||||
// If a sub-property is requested, we have nowhere to look → return ''.
|
||||
if (typeof block === 'string') {
|
||||
if (typeof block == 'string') {
|
||||
return prop ? '' : block;
|
||||
}
|
||||
|
||||
// 2) Otherwise, if `block` is an object:
|
||||
// (a) With no `prop`, return block.doc or block[cell.DOC].
|
||||
// (b) If `prop` is given, look for doc specifically for that property (just one level).
|
||||
if (typeof block === 'object') {
|
||||
if (typeof block == 'object') {
|
||||
// 2a) No property → top-level doc
|
||||
if (!prop) {
|
||||
if (typeof block.doc === 'string') {
|
||||
if (typeof block.doc == 'string') {
|
||||
return block.doc;
|
||||
}
|
||||
if (typeof block[cell.DOC] === 'string') {
|
||||
if (typeof block[cell.DOC] == 'string') {
|
||||
return block[cell.DOC];
|
||||
}
|
||||
return '';
|
||||
@@ -27,14 +27,14 @@ function docOf(obj, prop) {
|
||||
// 2b) If a prop is requested → see if there's a doc string or object for that property
|
||||
var subBlock = block[prop];
|
||||
if (!subBlock) return '';
|
||||
if (typeof subBlock === 'string') {
|
||||
if (typeof subBlock == 'string') {
|
||||
return subBlock;
|
||||
}
|
||||
if (typeof subBlock === 'object') {
|
||||
if (typeof subBlock.doc === 'string') {
|
||||
if (typeof subBlock == 'object') {
|
||||
if (typeof subBlock.doc == 'string') {
|
||||
return subBlock.doc;
|
||||
}
|
||||
if (typeof subBlock[cell.DOC] === 'string') {
|
||||
if (typeof subBlock[cell.DOC] == 'string') {
|
||||
return subBlock[cell.DOC];
|
||||
}
|
||||
return '';
|
||||
@@ -94,7 +94,7 @@ function parseDocStr(docStr) {
|
||||
|
||||
if (returnLines.length) {
|
||||
// If there were param lines, ensure blank line before the returns
|
||||
if (paramLines.length && returnLines[0] !== '') {
|
||||
if (paramLines.length && returnLines[0] != '') {
|
||||
final.push('');
|
||||
}
|
||||
final.push.apply(final, returnLines);
|
||||
@@ -131,14 +131,14 @@ function walkObject(obj, lines, level, name) {
|
||||
var propNames = Object.getOwnPropertyNames(obj);
|
||||
for (var i = 0; i < propNames.length; i++) {
|
||||
var prop = propNames[i];
|
||||
if (prop === 'constructor') continue;
|
||||
if (prop == 'constructor') continue;
|
||||
|
||||
var desc = Object.getOwnPropertyDescriptor(obj, prop);
|
||||
if (!desc) continue;
|
||||
|
||||
// Check if accessor property (getter/setter)
|
||||
var hasGetter = typeof desc.get === 'function';
|
||||
var hasSetter = typeof desc.set === 'function';
|
||||
var hasGetter = typeof desc.get == 'function';
|
||||
var hasSetter = typeof desc.set == 'function';
|
||||
|
||||
if (hasGetter || hasSetter) {
|
||||
writeProperty(lines, obj, prop, desc, level);
|
||||
@@ -150,11 +150,11 @@ function walkObject(obj, lines, level, name) {
|
||||
var val = desc.value;
|
||||
|
||||
// If it's a function, treat it like a method
|
||||
if (typeof val === 'function') {
|
||||
if (typeof val == 'function') {
|
||||
writeMethod(lines, obj, prop, val, level);
|
||||
}
|
||||
// If it's an object, just print doc for that object (no deep recursion)
|
||||
else if (val && typeof val === 'object') {
|
||||
else if (val && typeof val == 'object') {
|
||||
writeSubObject(lines, obj, prop, val, level);
|
||||
}
|
||||
// Otherwise, it's a primitive or something else
|
||||
@@ -192,8 +192,8 @@ function writeProperty(lines, parentObj, prop, desc, level) {
|
||||
var heading = '#'.repeat(level + 2) + ' ' + prop + ' <sub>accessor</sub>';
|
||||
lines.push(heading + '\n');
|
||||
|
||||
var hasGetter = typeof desc.get === 'function';
|
||||
var hasSetter = typeof desc.set === 'function';
|
||||
var hasGetter = typeof desc.get == 'function';
|
||||
var hasSetter = typeof desc.set == 'function';
|
||||
|
||||
if (hasGetter && !hasSetter) {
|
||||
lines.push('(read only)\n');
|
||||
|
||||
@@ -66,24 +66,24 @@ Angles in degrees or radians must first be converted prior to making a quaternio
|
||||
`;
|
||||
|
||||
prosperon.c_types.transform[cell.DOC].parent = `Get or set the transform's parent. If set, this transform becomes a child of
|
||||
the parent (re-parenting). Must be another transform object or undefined.
|
||||
the parent (re-parenting). Must be another transform object or null.
|
||||
|
||||
:param value: (when setting) Another transform or undefined.
|
||||
:param value: (when setting) Another transform or null.
|
||||
:return: The current parent transform (when getting), or None (when setting).
|
||||
`;
|
||||
|
||||
prosperon.c_types.transform[cell.DOC].change_hook = `A user-supplied function that's called whenever the transform's local matrix changes.
|
||||
If undefined, no hook is called.
|
||||
If null, no hook is called.
|
||||
|
||||
:param value: (when setting) A function.
|
||||
:return: The current function or undefined.
|
||||
:return: The current function or null.
|
||||
`;
|
||||
|
||||
prosperon.c_types.transform[cell.DOC].trs = `Set the transform's position, rotation, and scale in one call.
|
||||
|
||||
:param pos: [x,y,z] for position, or undefined to keep existing.
|
||||
:param quat: [qx,qy,qz,qw] for rotation, or undefined.
|
||||
:param scale: [sx,sy,sz] for scale, or undefined.
|
||||
:param pos: [x,y,z] for position, or null to keep existing.
|
||||
:param quat: [qx,qy,qz,qw] for rotation, or null.
|
||||
:param scale: [sx,sy,sz] for scale, or null.
|
||||
:return: None
|
||||
`;
|
||||
|
||||
@@ -231,7 +231,7 @@ prosperon.c_types.datastream[cell.DOC].framerate = `Return the framerate (FPS) o
|
||||
prosperon.c_types.datastream[cell.DOC].callback = `A function to call whenever a new frame is decoded. If not set, no callback is invoked.
|
||||
|
||||
:param fn: (when setting) A function that receives (surface).
|
||||
:return: The existing function or undefined if none.
|
||||
:return: The existing function or null if none.
|
||||
`;
|
||||
|
||||
|
||||
@@ -325,10 +325,10 @@ prosperon.c_types.SDL_Camera[cell.DOC] = {}
|
||||
prosperon.c_types.SDL_Camera[cell.DOC][cell.DOC] = `A handle to a physical camera device. Freed when references drop or camera is closed.
|
||||
`;
|
||||
|
||||
prosperon.c_types.SDL_Camera[cell.DOC].frame = `Acquire the latest camera frame (as an SDL_Surface). Returns undefined if no
|
||||
prosperon.c_types.SDL_Camera[cell.DOC].frame = `Acquire the latest camera frame (as an SDL_Surface). Returns null if no
|
||||
new frame is available yet. Throws on error.
|
||||
|
||||
:return: SDL_Surface or undefined.
|
||||
:return: SDL_Surface or null.
|
||||
`;
|
||||
|
||||
prosperon.c_types.SDL_Camera[cell.DOC].release_frame = `Release a frame surface previously acquired via camera.frame(). Must be
|
||||
@@ -376,9 +376,9 @@ prosperon.c_types.SDL_Window[cell.DOC].keyboard_shown = `Return whether the on-s
|
||||
:return: True if shown, false otherwise.
|
||||
`;
|
||||
|
||||
prosperon.c_types.SDL_Window[cell.DOC].theme = `Currently returns undefined. Placeholder for retrieving OS window theme info.
|
||||
prosperon.c_types.SDL_Window[cell.DOC].theme = `Currently returns null. Placeholder for retrieving OS window theme info.
|
||||
|
||||
:return: undefined
|
||||
:return: null
|
||||
`;
|
||||
|
||||
prosperon.c_types.SDL_Window[cell.DOC].safe_area = `Return a rect describing any OS-specific "safe" region for UI, e.g. on iPhone with a notch.
|
||||
@@ -502,7 +502,7 @@ prosperon.c_types.SDL_Renderer[cell.DOC].tile = `Tile a texture repeatedly withi
|
||||
:return: None
|
||||
`;
|
||||
|
||||
prosperon.c_types.SDL_Renderer[cell.DOC].get_image = `Read back the rendered pixels into a new SDL_Surface. If rect is undefined, capture entire output.
|
||||
prosperon.c_types.SDL_Renderer[cell.DOC].get_image = `Read back the rendered pixels into a new SDL_Surface. If rect is null, capture entire output.
|
||||
|
||||
:param rect: Optional {x,y,w,h}.
|
||||
:return: An SDL_Surface with the requested region's pixels.
|
||||
@@ -518,7 +518,7 @@ prosperon.c_types.SDL_Renderer[cell.DOC].fasttext = `Draw debug text using an in
|
||||
|
||||
prosperon.c_types.SDL_Renderer[cell.DOC].geometry = `Render custom geometry from a mesh object {pos, uv, color, indices, count} with an optional texture.
|
||||
|
||||
:param texture: The SDL_Texture or undefined.
|
||||
:param texture: The SDL_Texture or null.
|
||||
:param meshObject: The geometry data with typed arrays.
|
||||
:return: None
|
||||
`;
|
||||
@@ -536,15 +536,15 @@ For example, (320, 240) can auto-scale up to the window resolution.
|
||||
:return: None
|
||||
`;
|
||||
|
||||
prosperon.c_types.SDL_Renderer[cell.DOC].viewport = `Set the clipping viewport for rendering. Pass undefined to use the full render target.
|
||||
prosperon.c_types.SDL_Renderer[cell.DOC].viewport = `Set the clipping viewport for rendering. Pass null to use the full render target.
|
||||
|
||||
:param rect: {x, y, w, h}, or undefined.
|
||||
:param rect: {x, y, w, h}, or null.
|
||||
:return: None
|
||||
`;
|
||||
|
||||
prosperon.c_types.SDL_Renderer[cell.DOC].clip = `Set or clear the clipping rectangle for drawing. Pass undefined to clear.
|
||||
prosperon.c_types.SDL_Renderer[cell.DOC].clip = `Set or clear the clipping rectangle for drawing. Pass null to clear.
|
||||
|
||||
:param rect: {x, y, w, h} or undefined.
|
||||
:param rect: {x, y, w, h} or null.
|
||||
:return: None
|
||||
`;
|
||||
|
||||
@@ -579,9 +579,9 @@ prosperon.c_types.SDL_Renderer[cell.DOC].screen2world = `Convert a screen coordi
|
||||
:return: [wx, wy] in world space
|
||||
`;
|
||||
|
||||
prosperon.c_types.SDL_Renderer[cell.DOC].target = `Set or clear the current render target texture. Pass undefined to reset to the default/window.
|
||||
prosperon.c_types.SDL_Renderer[cell.DOC].target = `Set or clear the current render target texture. Pass null to reset to the default/window.
|
||||
|
||||
:param texture: An SDL_Texture or undefined
|
||||
:param texture: An SDL_Texture or null
|
||||
:return: None
|
||||
`;
|
||||
|
||||
|
||||
@@ -248,6 +248,7 @@ globalThis.use = function use(file, ...args) {
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
globalThis.json = use('json')
|
||||
var time = use('time')
|
||||
var st_now = time.number()
|
||||
@@ -303,7 +304,7 @@ function deepFreeze(object) {
|
||||
for (var name of propNames) {
|
||||
var value = object[name];
|
||||
|
||||
if ((value && typeof value === "object") || typeof value === "function") {
|
||||
if ((value && typeof value == "object") || typeof value == "function") {
|
||||
deepFreeze(value);
|
||||
}
|
||||
}
|
||||
@@ -374,10 +375,10 @@ $_.clock = function(fn) {
|
||||
$_.clock[cell.DOC] = "takes a function input value that will eventually be called with the current time in number form."
|
||||
|
||||
var underlings = new Set() // this is more like "all actors that are notified when we die"
|
||||
var overling = undefined
|
||||
var root = undefined
|
||||
var overling = null
|
||||
var root = null
|
||||
|
||||
var receive_fn = undefined
|
||||
var receive_fn = null
|
||||
var greeters = {} // Router functions for when messages are received for a specific actor
|
||||
|
||||
globalThis.is_actor = function is_actor(actor) {
|
||||
@@ -424,9 +425,9 @@ $_.connection[cell.DOC] = "The connection function takes a callback function, an
|
||||
|
||||
var peers = {}
|
||||
var id_address = {}
|
||||
var peer_queue = new WeakMap()
|
||||
var portal = undefined
|
||||
var portal_fn = undefined
|
||||
var peer_queue = {}
|
||||
var portal = null
|
||||
var portal_fn = null
|
||||
|
||||
$_.portal = function(fn, port) {
|
||||
if (portal) throw new Error(`Already started a portal listening on ${portal.port}`)
|
||||
@@ -451,7 +452,7 @@ function handle_host(e) {
|
||||
break
|
||||
case "disconnect":
|
||||
peer_queue.delete(e.peer)
|
||||
for (var id in peers) if (peers[id] === e.peer) delete peers[id]
|
||||
for (var id in peers) if (peers[id] == e.peer) delete peers[id]
|
||||
log.system('portal got disconnect from ' + e.peer.address + ":" + e.peer.port)
|
||||
break
|
||||
case "receive":
|
||||
@@ -461,7 +462,7 @@ function handle_host(e) {
|
||||
data.replycc[ACTORDATA].port = e.peer.port
|
||||
}
|
||||
function populate_actor_addresses(obj) {
|
||||
if (typeof obj !== 'object' || obj === null) return
|
||||
if (typeof obj != 'object' || obj == null) return
|
||||
if (obj[ACTORDATA] && !obj[ACTORDATA].address) {
|
||||
obj[ACTORDATA].address = e.peer.address
|
||||
obj[ACTORDATA].port = e.peer.port
|
||||
@@ -494,7 +495,7 @@ $_.start = function start(cb, program, ...args) {
|
||||
if (!program) return
|
||||
var id = guid()
|
||||
|
||||
if (args.length === 1 && Array.isArray(args[0]))
|
||||
if (args.length == 1 && Array.isArray(args[0]))
|
||||
args = args[0]
|
||||
|
||||
var startup = {
|
||||
@@ -543,7 +544,7 @@ $_.delay[cell.DOC] = "used to schedule the invocation of a function..."
|
||||
|
||||
var couplings = new Set()
|
||||
$_.couple = function couple(actor) {
|
||||
if (actor === $_) return // can't couple to self
|
||||
if (actor == $_) return // can't couple to self
|
||||
couplings.add(actor[ACTORDATA].id)
|
||||
sys_msg(actor, {kind:'couple', from: $_})
|
||||
log.system(`coupled to ${actor}`)
|
||||
@@ -569,10 +570,10 @@ function actor_send(actor, message) {
|
||||
|
||||
if (!is_actor(actor) && !is_actor(actor.replycc)) throw new Error(`Must send to an actor object. Attempted send to ${json.encode(actor)}`)
|
||||
|
||||
if (typeof message !== 'object') throw new Error('Must send an object record.')
|
||||
if (typeof message != 'object') throw new Error('Must send an object record.')
|
||||
|
||||
// message to self
|
||||
if (actor[ACTORDATA].id === cell.id) {
|
||||
if (actor[ACTORDATA].id == cell.id) {
|
||||
if (receive_fn) receive_fn(message.data)
|
||||
return
|
||||
}
|
||||
@@ -627,10 +628,10 @@ function send_messages() {
|
||||
var replies = {}
|
||||
|
||||
globalThis.send = function send(actor, message, reply) {
|
||||
if (typeof actor !== 'object')
|
||||
if (typeof actor != 'object')
|
||||
throw new Error('Must send to an actor object. Provided: ' + actor);
|
||||
|
||||
if (typeof message !== 'object')
|
||||
if (typeof message != 'object')
|
||||
throw new Error('Message must be an object')
|
||||
var send = {type:"user", data: message}
|
||||
|
||||
@@ -648,7 +649,7 @@ globalThis.send = function send(actor, message, reply) {
|
||||
replies[id] = reply
|
||||
$_.delay(_ => {
|
||||
if (replies[id]) {
|
||||
replies[id](undefined, "timeout")
|
||||
replies[id](null, "timeout")
|
||||
delete replies[id]
|
||||
}
|
||||
}, REPLYTIMEOUT)
|
||||
@@ -763,7 +764,7 @@ function handle_message(msg) {
|
||||
Object.defineProperty(letter, HEADER, {
|
||||
value: msg, enumerable: false
|
||||
})
|
||||
Object.defineProperty(letter, ACTORDATA, { // this is so is_actor === true
|
||||
Object.defineProperty(letter, ACTORDATA, { // this is so is_actor == true
|
||||
value: { reply: msg.reply }, enumerable: false
|
||||
})
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ var parsed = shop.parse_locator(locator)
|
||||
|
||||
// If no version specified, append @head
|
||||
if (!parsed) {
|
||||
if (locator.indexOf('@') === -1) {
|
||||
if (locator.indexOf('@') == -1) {
|
||||
locator = locator + '@head'
|
||||
parsed = shop.parse_locator(locator)
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ This function enqueues an HTTP GET request for the specified URL. It supports bo
|
||||
:param options: Either a callback function or an object with optional properties:
|
||||
- 'callback': A function invoked upon request completion, receiving an object with 'data' (string or null) and 'error' (string or null) properties.
|
||||
- 'on_data': A function invoked for each chunk of streaming data, receiving a string chunk as its argument. If supplied, 'callback.data' will be null.
|
||||
:return: undefined
|
||||
:return: null
|
||||
:throws:
|
||||
- An error if the URL is not a string or is invalid.
|
||||
- An error if the options argument is neither a function nor an object.
|
||||
|
||||
@@ -72,11 +72,11 @@ Throw on error.
|
||||
:return: None
|
||||
`
|
||||
|
||||
io.mount[cell.DOC] = `Mount a directory or archive at the specified mount point. An undefined mount
|
||||
io.mount[cell.DOC] = `Mount a directory or archive at the specified mount point. An null mount
|
||||
point mounts to '/'. Throw on error.
|
||||
|
||||
:param archiveOrDir: The directory or archive to mount.
|
||||
:param mountPoint: The path at which to mount. If omitted or undefined, '/' is used.
|
||||
:param mountPoint: The path at which to mount. If omitted or null, '/' is used.
|
||||
:return: None
|
||||
`
|
||||
|
||||
@@ -145,10 +145,10 @@ operations. Throw on error.
|
||||
`
|
||||
|
||||
io.realdir[cell.DOC] = `Return the actual, real directory (on the host filesystem) that contains the given
|
||||
file path. Return undefined if not found.
|
||||
file path. Return null if not found.
|
||||
|
||||
:param path: The file path whose real directory is requested.
|
||||
:return: A string with the real directory path, or undefined.
|
||||
:return: A string with the real directory path, or null.
|
||||
`
|
||||
|
||||
io.searchpath[cell.DOC] = `Return an array of all directories in the current paths.
|
||||
|
||||
@@ -71,21 +71,21 @@ function encode_key(key)
|
||||
function encode_val(b, val)
|
||||
{
|
||||
var type = typeof val
|
||||
if (type === 'number') {
|
||||
if (type == 'number') {
|
||||
b.write_blob(FP_HEADER)
|
||||
b.write_number(val)
|
||||
} else if (type === 'string') {
|
||||
} else if (type == 'string') {
|
||||
b.write_fit(utf8.byte_length(val), 56)
|
||||
b.write_blob(TEXT)
|
||||
b.write_blob(utf8.encode(val))
|
||||
} else if (type === 'boolean') {
|
||||
} else if (type == 'boolean') {
|
||||
if (val)
|
||||
b.write_blob(TRUE_SYMBOL)
|
||||
else
|
||||
b.write_blob(FALSE_SYMBOL)
|
||||
} else if (type === 'undefined') {
|
||||
} else if (type == 'null') {
|
||||
b.write_blob(NULL_SYMBOL)
|
||||
} else if (type === 'object') {
|
||||
} else if (type == 'object') {
|
||||
if (Array.isArray(val)) {
|
||||
b.write_fit(val.length, 56)
|
||||
b.write_blob(ARRAY)
|
||||
@@ -100,7 +100,7 @@ function encode_val(b, val)
|
||||
b.write_fit(keys.length, 56)
|
||||
b.write_blob(RECORD)
|
||||
for (var key of keys) {
|
||||
if (typeof val[key] === 'function') continue
|
||||
if (typeof val[key] == 'function') continue
|
||||
b.write_blob(encode_key(key))
|
||||
encode_val(b, val[key])
|
||||
}
|
||||
@@ -118,7 +118,7 @@ function encode(val)
|
||||
|
||||
function decode(b)
|
||||
{
|
||||
return undefined
|
||||
return null
|
||||
}
|
||||
|
||||
return { INT, FP_HEADER, ARRAY, RECORD, BLOB, TEXT, NULL_SYMBOL, FALSE_SYMBOL, TRUE_SYMBOL, PRIVATE_SYMBOL, SYSTEM_SYMBOL, encode, decode }
|
||||
@@ -16,7 +16,7 @@ if (!config) {
|
||||
}
|
||||
|
||||
// List dependencies
|
||||
if (!config.dependencies || Object.keys(config.dependencies).length === 0) {
|
||||
if (!config.dependencies || Object.keys(config.dependencies).length == 0) {
|
||||
log.console("No modules installed")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
var miniz = this
|
||||
|
||||
miniz.read[cell.DOC] = `Create a zip reader from the given ArrayBuffer containing an entire ZIP archive.
|
||||
Return undefined if the data is invalid.
|
||||
Return null if the data is invalid.
|
||||
|
||||
:param data: An ArrayBuffer with the entire ZIP file.
|
||||
:return: A 'zip reader' object with methods for reading from the archive (mod, exists, slurp).
|
||||
`
|
||||
|
||||
miniz.write[cell.DOC] = `Create a zip writer that writes to the specified file path. Overwrites the file if
|
||||
it already exists. Return undefined on error.
|
||||
it already exists. Return null on error.
|
||||
|
||||
:param path: The file path where the ZIP archive will be written.
|
||||
:return: A 'zip writer' object with methods for adding files to the archive (add_file).
|
||||
|
||||
@@ -60,7 +60,7 @@ uses.download = function()
|
||||
} else if (!io.exists(cache_path)) {
|
||||
log.console(`${mod}: cache missing, will download`)
|
||||
need_download = true
|
||||
} else if (remote_commit && (!lock.modules[mod].commit || lock.modules[mod].commit !== remote_commit)) {
|
||||
} else if (remote_commit && (!lock.modules[mod].commit || lock.modules[mod].commit != remote_commit)) {
|
||||
log.console(`${mod}: remote has new commit`)
|
||||
log.console(` local: ${lock.modules[mod].commit || 'unknown'}`)
|
||||
log.console(` remote: ${remote_commit}`)
|
||||
@@ -74,7 +74,7 @@ uses.download = function()
|
||||
var hash = crypto.hash(zip)
|
||||
var hash_b32 = text(hash, "t")
|
||||
|
||||
if (hash_b32 !== lock.modules[mod].hash) {
|
||||
if (hash_b32 != lock.modules[mod].hash) {
|
||||
log.console(`${mod}: hash mismatch, will redownload`)
|
||||
log.console(` expected: ${lock.modules[mod].hash}`)
|
||||
log.console(` actual: ${hash_b32}`)
|
||||
@@ -136,7 +136,7 @@ uses.download = function()
|
||||
|
||||
// Strip the module name prefix if present
|
||||
var prefix = mod + '/'
|
||||
if (filename.indexOf(prefix) === 0)
|
||||
if (filename.indexOf(prefix) == 0)
|
||||
filename = filename.substring(prefix.length)
|
||||
|
||||
// Skip if filename is empty after stripping
|
||||
|
||||
@@ -38,9 +38,9 @@ function resolve_relative(base, relative) {
|
||||
|
||||
for (var i = 0; i < rel_parts.length; i++) {
|
||||
var part = rel_parts[i]
|
||||
if (part === '.') {
|
||||
if (part == '.') {
|
||||
continue
|
||||
} else if (part === '..') {
|
||||
} else if (part == '..') {
|
||||
parts.pop()
|
||||
} else {
|
||||
parts.push(part)
|
||||
@@ -82,7 +82,7 @@ ModuleResolver.check_alias = function(request) {
|
||||
}
|
||||
|
||||
// Check for single-alias fallback
|
||||
if (config.dependencies && Object.keys(config.dependencies).length === 1) {
|
||||
if (config.dependencies && Object.keys(config.dependencies).length == 1) {
|
||||
// If only one dependency and no local file matches, route there
|
||||
var only_dep = Object.keys(config.dependencies)[0]
|
||||
return '/' + only_dep + '/' + request
|
||||
|
||||
@@ -31,10 +31,10 @@ This function serializes JavaScript values (such as numbers, strings, booleans,
|
||||
|
||||
nota.decode[cell.DOC] = `Decode a NOTA-encoded ArrayBuffer into a JavaScript value.
|
||||
|
||||
This function deserializes a NOTA-formatted ArrayBuffer into its corresponding JavaScript representation, such as a number, string, boolean, array, object, or ArrayBuffer. If the input is invalid or empty, it returns undefined.
|
||||
This function deserializes a NOTA-formatted ArrayBuffer into its corresponding JavaScript representation, such as a number, string, boolean, array, object, or ArrayBuffer. If the input is invalid or empty, it returns null.
|
||||
|
||||
:param buffer: An ArrayBuffer containing NOTA-encoded data to decode.
|
||||
:return: The decoded JavaScript value (e.g., number, string, boolean, array, object, or ArrayBuffer), or undefined if no argument is provided.
|
||||
:return: The decoded JavaScript value (e.g., number, string, boolean, array, object, or ArrayBuffer), or null if no argument is provided.
|
||||
`
|
||||
|
||||
return nota
|
||||
|
||||
@@ -14,18 +14,18 @@
|
||||
Each factory returns a **requestor** function as described by the spec.
|
||||
*/
|
||||
|
||||
const delay = arg[0] // may be undefined
|
||||
def delay = arg[0] // may be null
|
||||
|
||||
// ———————————————————————————————————————— helpers
|
||||
|
||||
function make_reason (factory, excuse, evidence) {
|
||||
const reason = new Error(`parseq.${factory}${excuse ? ': ' + excuse : ''}`)
|
||||
def reason = new Error(`parseq.${factory}${excuse ? ': ' + excuse : ''}`)
|
||||
reason.evidence = evidence
|
||||
return reason
|
||||
}
|
||||
|
||||
function is_requestor (fn) {
|
||||
return typeof fn === 'function' && (fn.length === 1 || fn.length === 2)
|
||||
return typeof fn == 'function' && (fn.length == 1 || fn.length == 2)
|
||||
}
|
||||
|
||||
function check_requestors (list, factory) {
|
||||
@@ -34,13 +34,13 @@ function check_requestors (list, factory) {
|
||||
}
|
||||
|
||||
function check_callback (cb, factory) {
|
||||
if (typeof cb !== 'function' || cb.length !== 2)
|
||||
if (typeof cb != 'function' || cb.length != 2)
|
||||
throw make_reason(factory, 'Not a callback.', cb)
|
||||
}
|
||||
|
||||
function schedule (fn, seconds) {
|
||||
if (seconds === undefined || seconds <= 0) return fn()
|
||||
if (typeof delay === 'function') return delay(fn, seconds)
|
||||
if (seconds == null || seconds <= 0) return fn()
|
||||
if (typeof delay == 'function') return delay(fn, seconds)
|
||||
throw make_reason('schedule', '@.delay capability required for timeouts.')
|
||||
}
|
||||
|
||||
@@ -52,41 +52,41 @@ function run (factory, requestors, initial, action, time_limit, throttle = 0) {
|
||||
let timer_cancel
|
||||
|
||||
function cancel (reason = make_reason(factory, 'Cancel.')) {
|
||||
if (timer_cancel) timer_cancel(), timer_cancel = undefined
|
||||
if (timer_cancel) timer_cancel(), timer_cancel = null
|
||||
if (!cancel_list) return
|
||||
cancel_list.forEach(c => { try { if (typeof c === 'function') c(reason) } catch (_) {} })
|
||||
cancel_list = undefined
|
||||
cancel_list.forEach(c => { try { if (typeof c == 'function') c(reason) } catch (_) {} })
|
||||
cancel_list = null
|
||||
}
|
||||
|
||||
function start_requestor (value) {
|
||||
if (!cancel_list || next >= requestors.length) return
|
||||
let idx = next++
|
||||
const req = requestors[idx]
|
||||
def req = requestors[idx]
|
||||
|
||||
try {
|
||||
cancel_list[idx] = req(function req_cb (val, reason) {
|
||||
if (!cancel_list || idx === undefined) return
|
||||
cancel_list[idx] = undefined
|
||||
if (!cancel_list || idx == null) return
|
||||
cancel_list[idx] = null
|
||||
action(val, reason, idx)
|
||||
idx = undefined
|
||||
if (factory === 'sequence') start_requestor(val)
|
||||
idx = null
|
||||
if (factory == 'sequence') start_requestor(val)
|
||||
else if (throttle) start_requestor(initial)
|
||||
}, value)
|
||||
} catch (ex) {
|
||||
action(undefined, ex, idx)
|
||||
idx = undefined
|
||||
if (factory === 'sequence') start_requestor(value)
|
||||
action(null, ex, idx)
|
||||
idx = null
|
||||
if (factory == 'sequence') start_requestor(value)
|
||||
else if (throttle) start_requestor(initial)
|
||||
}
|
||||
}
|
||||
|
||||
if (time_limit !== undefined) {
|
||||
if (typeof time_limit !== 'number' || time_limit < 0)
|
||||
if (time_limit != null) {
|
||||
if (typeof time_limit != 'number' || time_limit < 0)
|
||||
throw make_reason(factory, 'Bad time limit.', time_limit)
|
||||
if (time_limit > 0) timer_cancel = schedule(() => cancel(make_reason(factory, 'Timeout.', time_limit)), time_limit)
|
||||
}
|
||||
|
||||
const concurrent = throttle ? Math.min(throttle, requestors.length) : requestors.length
|
||||
def concurrent = throttle ? Math.min(throttle, requestors.length) : requestors.length
|
||||
for (let i = 0; i < concurrent; i++) start_requestor(initial)
|
||||
|
||||
return cancel
|
||||
@@ -96,9 +96,9 @@ function run (factory, requestors, initial, action, time_limit, throttle = 0) {
|
||||
|
||||
function _normalize (collection, factory) {
|
||||
if (Array.isArray(collection)) return { names: null, list: collection }
|
||||
if (collection && typeof collection === 'object') {
|
||||
const names = Object.keys(collection)
|
||||
const list = names.map(k => collection[k]).filter(is_requestor)
|
||||
if (collection && typeof collection == 'object') {
|
||||
def names = Object.keys(collection)
|
||||
def list = names.map(k => collection[k]).filter(is_requestor)
|
||||
return { names, list }
|
||||
}
|
||||
throw make_reason(factory, 'Expected array or record.', collection)
|
||||
@@ -106,29 +106,29 @@ function _normalize (collection, factory) {
|
||||
|
||||
function _denormalize (names, list) {
|
||||
if (!names) return list
|
||||
const obj = Object.create(null)
|
||||
def obj = Object.create(null)
|
||||
names.forEach((k, i) => { obj[k] = list[i] })
|
||||
return obj
|
||||
}
|
||||
|
||||
function par_all (collection, time_limit, throttle) {
|
||||
const factory = 'par_all'
|
||||
const { names, list } = _normalize(collection, factory)
|
||||
if (list.length === 0) return (cb, v) => cb(names ? {} : [])
|
||||
def factory = 'par_all'
|
||||
def { names, list } = _normalize(collection, factory)
|
||||
if (list.length == 0) return (cb, v) => cb(names ? {} : [])
|
||||
check_requestors(list, factory)
|
||||
|
||||
return function par_all_req (cb, initial) {
|
||||
check_callback(cb, factory)
|
||||
let pending = list.length
|
||||
const results = new Array(list.length)
|
||||
def results = new Array(list.length)
|
||||
|
||||
const cancel = run(factory, list, initial, (val, reason, idx) => {
|
||||
if (val === undefined) {
|
||||
def cancel = run(factory, list, initial, (val, reason, idx) => {
|
||||
if (val == null) {
|
||||
cancel(reason)
|
||||
return cb(undefined, reason)
|
||||
return cb(null, reason)
|
||||
}
|
||||
results[idx] = val
|
||||
if (--pending === 0) cb(_denormalize(names, results))
|
||||
if (--pending == 0) cb(_denormalize(names, results))
|
||||
}, time_limit, throttle)
|
||||
|
||||
return cancel
|
||||
@@ -136,24 +136,24 @@ function par_all (collection, time_limit, throttle) {
|
||||
}
|
||||
|
||||
function par_any (collection, time_limit, throttle) {
|
||||
const factory = 'par_any'
|
||||
const { names, list } = _normalize(collection, factory)
|
||||
if (list.length === 0) return (cb, v) => cb(names ? {} : [])
|
||||
def factory = 'par_any'
|
||||
def { names, list } = _normalize(collection, factory)
|
||||
if (list.length == 0) return (cb, v) => cb(names ? {} : [])
|
||||
check_requestors(list, factory)
|
||||
|
||||
return function par_any_req (cb, initial) {
|
||||
check_callback(cb, factory)
|
||||
let pending = list.length
|
||||
const successes = new Array(list.length)
|
||||
def successes = new Array(list.length)
|
||||
|
||||
const cancel = run(factory, list, initial, (val, reason, idx) => {
|
||||
def cancel = run(factory, list, initial, (val, reason, idx) => {
|
||||
pending--
|
||||
if (val !== undefined) successes[idx] = val
|
||||
if (successes.some(v => v !== undefined)) {
|
||||
if (val != null) successes[idx] = val
|
||||
if (successes.some(v => v != null)) {
|
||||
if (!pending) cancel(make_reason(factory, 'Finished.'))
|
||||
return cb(_denormalize(names, successes.filter(v => v !== undefined)))
|
||||
return cb(_denormalize(names, successes.filter(v => v != null)))
|
||||
}
|
||||
if (!pending) cb(undefined, make_reason(factory, 'No successes.'))
|
||||
if (!pending) cb(null, make_reason(factory, 'No successes.'))
|
||||
}, time_limit, throttle)
|
||||
|
||||
return cancel
|
||||
@@ -161,24 +161,24 @@ function par_any (collection, time_limit, throttle) {
|
||||
}
|
||||
|
||||
function race (list, time_limit, throttle) {
|
||||
const factory = throttle === 1 ? 'fallback' : 'race'
|
||||
if (!Array.isArray(list) || list.length === 0)
|
||||
def factory = throttle == 1 ? 'fallback' : 'race'
|
||||
if (!Array.isArray(list) || list.length == 0)
|
||||
throw make_reason(factory, 'No requestors.')
|
||||
check_requestors(list, factory)
|
||||
|
||||
return function race_req (cb, initial) {
|
||||
check_callback(cb, factory)
|
||||
let done = false
|
||||
const cancel = run(factory, list, initial, (val, reason, idx) => {
|
||||
def cancel = run(factory, list, initial, (val, reason, idx) => {
|
||||
if (done) return
|
||||
if (val !== undefined) {
|
||||
if (val != null) {
|
||||
done = true
|
||||
cancel(make_reason(factory, 'Loser.', idx))
|
||||
cb(val)
|
||||
} else if (--list.length === 0) {
|
||||
} else if (--list.length == 0) {
|
||||
done = true
|
||||
cancel(reason)
|
||||
cb(undefined, reason)
|
||||
cb(null, reason)
|
||||
}
|
||||
}, time_limit, throttle)
|
||||
return cancel
|
||||
@@ -190,10 +190,10 @@ function fallback (list, time_limit) {
|
||||
}
|
||||
|
||||
function sequence (list, time_limit) {
|
||||
const factory = 'sequence'
|
||||
def factory = 'sequence'
|
||||
if (!Array.isArray(list)) throw make_reason(factory, 'Not an array.', list)
|
||||
check_requestors(list, factory)
|
||||
if (list.length === 0) return (cb, v) => cb(v)
|
||||
if (list.length == 0) return (cb, v) => cb(v)
|
||||
|
||||
return function sequence_req (cb, initial) {
|
||||
check_callback(cb, factory)
|
||||
@@ -203,11 +203,11 @@ function sequence (list, time_limit) {
|
||||
if (idx >= list.length) return cb(value)
|
||||
try {
|
||||
list[idx++](function seq_cb (val, reason) {
|
||||
if (val === undefined) return cb(undefined, reason)
|
||||
if (val == null) return cb(null, reason)
|
||||
next(val)
|
||||
}, value)
|
||||
} catch (ex) {
|
||||
cb(undefined, ex)
|
||||
cb(null, ex)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ Shop.init = function() {
|
||||
// Parse module locator (e.g., "git.world/jj/mod@v0.6.3")
|
||||
Shop.parse_locator = function(locator) {
|
||||
var parts = locator.split('@')
|
||||
if (parts.length !== 2) {
|
||||
if (parts.length != 2) {
|
||||
return null
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
var def = arg
|
||||
|
||||
if (arg.length === 0)
|
||||
if (arg.length == 0)
|
||||
arg = [
|
||||
'send',
|
||||
'stop',
|
||||
|
||||
@@ -17,7 +17,7 @@ function to_radix(num, radix) {
|
||||
var negative = n < 0;
|
||||
n = Math.abs(n);
|
||||
|
||||
if (n === 0) return "0";
|
||||
if (n == 0) return "0";
|
||||
|
||||
while (n > 0) {
|
||||
result = digits[n % radix] + result;
|
||||
@@ -29,9 +29,9 @@ function to_radix(num, radix) {
|
||||
|
||||
// Insert separator every n digits from right
|
||||
function add_separator(str, sep, n) {
|
||||
if (!n || n === 0) return str;
|
||||
if (!n || n == 0) return str;
|
||||
|
||||
var negative = str[0] === '-';
|
||||
var negative = str[0] == '-';
|
||||
if (negative) str = str.substring(1);
|
||||
|
||||
var parts = str.split('.');
|
||||
@@ -41,7 +41,7 @@ function add_separator(str, sep, n) {
|
||||
// Add separators to integer part
|
||||
var result = "";
|
||||
for (var i = integer.length - 1, count = 0; i >= 0; i--) {
|
||||
if (count === n && i !== integer.length - 1) {
|
||||
if (count == n && i != integer.length - 1) {
|
||||
result = sep + result;
|
||||
count = 0;
|
||||
}
|
||||
@@ -55,14 +55,14 @@ function add_separator(str, sep, n) {
|
||||
|
||||
// Format number with separator from left
|
||||
function add_separator_left(str, sep, n) {
|
||||
if (!n || n === 0) return str;
|
||||
if (!n || n == 0) return str;
|
||||
|
||||
var negative = str[0] === '-';
|
||||
var negative = str[0] == '-';
|
||||
if (negative) str = str.substring(1);
|
||||
|
||||
var result = "";
|
||||
for (var i = 0, count = 0; i < str.length; i++) {
|
||||
if (count === n && i !== 0) {
|
||||
if (count == n && i != 0) {
|
||||
result += sep;
|
||||
count = 0;
|
||||
}
|
||||
@@ -75,7 +75,7 @@ function add_separator_left(str, sep, n) {
|
||||
|
||||
/* -------- main text function --------------------------------------- */
|
||||
|
||||
function text() {
|
||||
function text(...arguments) {
|
||||
var arg = arguments[0];
|
||||
|
||||
// Handle blob conversion
|
||||
@@ -87,7 +87,7 @@ function text() {
|
||||
var bit_length = arg.length;
|
||||
var result = "";
|
||||
|
||||
if (typeof format === 'string') {
|
||||
if (typeof format == 'string') {
|
||||
// Extract style from format
|
||||
var style = '';
|
||||
for (var i = 0; i < format.length; i++) {
|
||||
@@ -120,7 +120,7 @@ function text() {
|
||||
value = (value << 1) | (bit ? 1 : 0);
|
||||
bits++;
|
||||
|
||||
if (bits === 3) {
|
||||
if (bits == 3) {
|
||||
result += value.toString();
|
||||
bits = 0;
|
||||
value = 0;
|
||||
@@ -150,13 +150,13 @@ function text() {
|
||||
var all_codepoints = true;
|
||||
for (var i = 0; i < arg.length; i++) {
|
||||
var item = arg[i];
|
||||
if (!(typeof item === 'number' && item >= 0 && item <= 0x10FFFF && item === Math.floor(item))) {
|
||||
if (!(typeof item == 'number' && item >= 0 && item <= 0x10FFFF && item == Math.floor(item))) {
|
||||
all_codepoints = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (all_codepoints && separator === "") {
|
||||
if (all_codepoints && separator == "") {
|
||||
// Use utf8 module to convert codepoints to string
|
||||
return utf8.from_codepoints(arg);
|
||||
} else {
|
||||
@@ -166,7 +166,7 @@ function text() {
|
||||
if (i > 0) result += separator;
|
||||
|
||||
var item = arg[i];
|
||||
if (typeof item === 'number' && item >= 0 && item <= 0x10FFFF && item === Math.floor(item)) {
|
||||
if (typeof item == 'number' && item >= 0 && item <= 0x10FFFF && item == Math.floor(item)) {
|
||||
// Single codepoint - use utf8 module
|
||||
result += utf8.from_codepoints([item]);
|
||||
} else {
|
||||
@@ -178,16 +178,16 @@ function text() {
|
||||
}
|
||||
|
||||
// Handle number conversion
|
||||
if (typeof arg === 'number') {
|
||||
if (typeof arg == 'number') {
|
||||
var format = arguments[1];
|
||||
|
||||
// Simple radix conversion
|
||||
if (typeof format === 'number') {
|
||||
if (typeof format == 'number') {
|
||||
return to_radix(arg, format);
|
||||
}
|
||||
|
||||
// Format string conversion
|
||||
if (typeof format === 'string') {
|
||||
if (typeof format == 'string') {
|
||||
return format_number(arg, format);
|
||||
}
|
||||
|
||||
@@ -196,13 +196,13 @@ function text() {
|
||||
}
|
||||
|
||||
// Handle text operations
|
||||
if (typeof arg === 'string') {
|
||||
if (arguments.length === 1) return arg;
|
||||
if (typeof arg == 'string') {
|
||||
if (arguments.length == 1) return arg;
|
||||
|
||||
var from = arguments[1];
|
||||
var to = arguments[2];
|
||||
|
||||
if (typeof from !== 'number' || typeof to !== 'number') return arg;
|
||||
if (typeof from != 'number' || typeof to != 'number') return arg;
|
||||
|
||||
var len = arg.length;
|
||||
|
||||
@@ -211,8 +211,8 @@ function text() {
|
||||
if (to < 0) to += len;
|
||||
|
||||
// Default values
|
||||
if (from === undefined) from = 0;
|
||||
if (to === undefined) to = len;
|
||||
if (from == null) from = 0;
|
||||
if (to == null) to = len;
|
||||
|
||||
// Validate range
|
||||
if (from < 0 || from > to || to > len) return null;
|
||||
@@ -261,8 +261,8 @@ function format_number(num, format) {
|
||||
if (i < format.length) return null;
|
||||
|
||||
// Real number styles
|
||||
if (style === 'e' || style === 'n' || style === 's' ||
|
||||
style === 'u' || style === 'd' || style === 'v' || style === 'l') {
|
||||
if (style == 'e' || style == 'n' || style == 's' ||
|
||||
style == 'u' || style == 'd' || style == 'v' || style == 'l') {
|
||||
|
||||
var decimal_point = '.';
|
||||
var separator = '';
|
||||
@@ -314,15 +314,15 @@ function format_number(num, format) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (separation === 0) separation = default_separation;
|
||||
if (places === 0 && style !== 'e' && style !== 'n') places = default_places;
|
||||
if (separation == 0) separation = default_separation;
|
||||
if (places == 0 && style != 'e' && style != 'n') places = default_places;
|
||||
|
||||
// Format the number
|
||||
if (style === 'e') {
|
||||
if (style == 'e') {
|
||||
// Scientific notation
|
||||
var str = places > 0 ? num.toExponential(places) : num.toExponential();
|
||||
return str;
|
||||
} else if (style === 'n' && (Math.abs(num) >= 1e21 || (Math.abs(num) < 1e-6 && num !== 0))) {
|
||||
} else if (style == 'n' && (Math.abs(num) >= 1e21 || (Math.abs(num) < 1e-6 && num != 0))) {
|
||||
// Use scientific notation for extreme values
|
||||
return num.toExponential();
|
||||
} else {
|
||||
@@ -335,7 +335,7 @@ function format_number(num, format) {
|
||||
}
|
||||
|
||||
// Replace decimal point if needed
|
||||
if (decimal_point !== '.') {
|
||||
if (decimal_point != '.') {
|
||||
str = str.replace('.', decimal_point);
|
||||
}
|
||||
|
||||
@@ -349,8 +349,8 @@ function format_number(num, format) {
|
||||
}
|
||||
|
||||
// Integer styles
|
||||
if (style === 'i' || style === 'b' || style === 'o' ||
|
||||
style === 'h' || style === 't') {
|
||||
if (style == 'i' || style == 'b' || style == 'o' ||
|
||||
style == 'h' || style == 't') {
|
||||
|
||||
var radix = 10;
|
||||
var default_separation = 0;
|
||||
@@ -384,15 +384,15 @@ function format_number(num, format) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (separation === 0) separation = default_separation;
|
||||
if (places === 0) places = default_places;
|
||||
if (separation == 0) separation = default_separation;
|
||||
if (places == 0) places = default_places;
|
||||
|
||||
// Convert to integer
|
||||
var n = Math.trunc(num);
|
||||
var str = to_radix(n, radix).toUpperCase();
|
||||
|
||||
// Pad with zeros if needed
|
||||
var negative = str[0] === '-';
|
||||
var negative = str[0] == '-';
|
||||
if (negative) str = str.substring(1);
|
||||
|
||||
while (str.length < places) {
|
||||
|
||||
@@ -41,10 +41,10 @@ time.week2day = function() { return time.week / time.day; };
|
||||
/* leap-year helpers */
|
||||
time.yearsize = function yearsize(y)
|
||||
{
|
||||
if (y % 4 === 0 && (y % 100 !== 0 || y % 400 === 0)) return 366;
|
||||
if (y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) return 366;
|
||||
return 365;
|
||||
};
|
||||
time.isleap = function(y) { return time.yearsize(y) === 366; };
|
||||
time.isleap = function(y) { return time.yearsize(y) == 366; };
|
||||
|
||||
/* timecode utility */
|
||||
time.timecode = function(t, fps = 24)
|
||||
@@ -64,7 +64,7 @@ function record(num = now(),
|
||||
dst = computer_dst())
|
||||
{
|
||||
/* caller passed an existing record → return it verbatim */
|
||||
if (typeof num === "object") return num;
|
||||
if (typeof num == "object") return num;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* convert seconds-since-epoch → broken-down record */
|
||||
@@ -107,7 +107,7 @@ function record(num = now(),
|
||||
rec.yday = day;
|
||||
|
||||
/* month & month-day */
|
||||
if (time.yearsize(y) === 366) monthdays[1] = 29;
|
||||
if (time.yearsize(y) == 366) monthdays[1] = 29;
|
||||
var m = 0;
|
||||
for (; day >= monthdays[m]; m++) day -= monthdays[m];
|
||||
rec.month = m;
|
||||
@@ -119,11 +119,15 @@ function record(num = now(),
|
||||
function number(rec = now())
|
||||
{
|
||||
/* fall through for numeric input or implicit “now” */
|
||||
if (typeof rec === "number") return rec;
|
||||
if (typeof rec == "number") return rec;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* record → seconds-since-epoch */
|
||||
|
||||
log.console(typeof rec)
|
||||
log.console(rec)
|
||||
log.console(rec.minute)
|
||||
|
||||
var c = 0;
|
||||
var year = rec.year || 0;
|
||||
var hour = rec.hour || 0;
|
||||
@@ -165,15 +169,15 @@ function text(num = now(),
|
||||
zone = computer_zone(),
|
||||
dst = computer_dst())
|
||||
{
|
||||
var rec = (typeof num === "number") ? record(num, zone, dst) : num;
|
||||
var rec = (typeof num == "number") ? record(num, zone, dst) : num;
|
||||
zone = rec.zone;
|
||||
dst = rec.dst;
|
||||
|
||||
/* am/pm */
|
||||
if (fmt.includes("a")) {
|
||||
if (rec.hour >= 13) { rec.hour -= 12; fmt = fmt.replaceAll("a", "PM"); }
|
||||
else if (rec.hour === 12) { fmt = fmt.replaceAll("a", "PM"); }
|
||||
else if (rec.hour === 0) { rec.hour = 12; fmt = fmt.replaceAll("a", "AM"); }
|
||||
else if (rec.hour == 12) { fmt = fmt.replaceAll("a", "PM"); }
|
||||
else if (rec.hour == 0) { rec.hour = 12; fmt = fmt.replaceAll("a", "AM"); }
|
||||
else fmt = fmt.replaceAll("a", "AM");
|
||||
}
|
||||
|
||||
|
||||
@@ -42,9 +42,9 @@ function parse_toml(text) {
|
||||
} else if (value.startsWith('[') && value.endsWith(']')) {
|
||||
// Array
|
||||
current_section[key] = parse_array(value)
|
||||
} else if (value === 'true' || value === 'false') {
|
||||
} else if (value == 'true' || value == 'false') {
|
||||
// Boolean
|
||||
current_section[key] = value === 'true'
|
||||
current_section[key] = value == 'true'
|
||||
} else if (!isNaN(Number(value))) {
|
||||
// Number
|
||||
current_section[key] = Number(value)
|
||||
@@ -70,10 +70,10 @@ function parse_array(str) {
|
||||
for (var i = 0; i < str.length; i++) {
|
||||
var char = str[i]
|
||||
|
||||
if (char === '"' && (i === 0 || str[i-1] !== '\\')) {
|
||||
if (char == '"' && (i == 0 || str[i-1] != '\\')) {
|
||||
in_quotes = !in_quotes
|
||||
current += char
|
||||
} else if (char === ',' && !in_quotes) {
|
||||
} else if (char == ',' && !in_quotes) {
|
||||
items.push(parse_value(current.trim()))
|
||||
current = ''
|
||||
} else {
|
||||
@@ -91,8 +91,8 @@ function parse_array(str) {
|
||||
function parse_value(str) {
|
||||
if (str.startsWith('"') && str.endsWith('"')) {
|
||||
return str.slice(1, -1).replace(/\\"/g, '"')
|
||||
} else if (str === 'true' || str === 'false') {
|
||||
return str === 'true'
|
||||
} else if (str == 'true' || str == 'false') {
|
||||
return str == 'true'
|
||||
} else if (!isNaN(Number(str))) {
|
||||
return Number(str)
|
||||
} else {
|
||||
@@ -104,11 +104,11 @@ function encode_toml(obj) {
|
||||
var result = []
|
||||
|
||||
function encode_value(value) {
|
||||
if (typeof value === 'string') {
|
||||
if (typeof value == 'string') {
|
||||
return '"' + value.replace(/"/g, '\\"') + '"'
|
||||
} else if (typeof value === 'boolean') {
|
||||
} else if (typeof value == 'boolean') {
|
||||
return value ? 'true' : 'false'
|
||||
} else if (typeof value === 'number') {
|
||||
} else if (typeof value == 'number') {
|
||||
return String(value)
|
||||
} else if (Array.isArray(value)) {
|
||||
var items = []
|
||||
@@ -125,7 +125,7 @@ function encode_toml(obj) {
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
var key = keys[i]
|
||||
var value = obj[key]
|
||||
if (value === null || typeof value !== 'object' || Array.isArray(value)) {
|
||||
if (value == null || typeof value != 'object' || Array.isArray(value)) {
|
||||
result.push(key + ' = ' + encode_value(value))
|
||||
}
|
||||
}
|
||||
@@ -138,7 +138,7 @@ function encode_toml(obj) {
|
||||
var key = keys[i]
|
||||
var value = obj[key]
|
||||
|
||||
if (value !== null && typeof value === 'object' && !Array.isArray(value)) {
|
||||
if (value != null && typeof value == 'object' && !Array.isArray(value)) {
|
||||
// Nested object - create section
|
||||
var section_path = path ? path + '.' + key : key
|
||||
result.push('[' + section_path + ']')
|
||||
@@ -148,7 +148,7 @@ function encode_toml(obj) {
|
||||
for (var j = 0; j < section_keys.length; j++) {
|
||||
var sk = section_keys[j]
|
||||
var sv = value[sk]
|
||||
if (sv === null || typeof sv !== 'object' || Array.isArray(sv)) {
|
||||
if (sv == null || typeof sv != 'object' || Array.isArray(sv)) {
|
||||
result.push(sk + ' = ' + encode_value(sv))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ for (var alias in deps_to_check) {
|
||||
local_commit: null,
|
||||
remote_commit: remote_commit
|
||||
})
|
||||
} else if (local_commit !== remote_commit) {
|
||||
} else if (local_commit != remote_commit) {
|
||||
log.console(" Update available!")
|
||||
log.console(" Local: " + local_commit.substring(0, 8))
|
||||
log.console(" Remote: " + remote_commit.substring(0, 8))
|
||||
@@ -95,7 +95,7 @@ for (var alias in deps_to_check) {
|
||||
}
|
||||
}
|
||||
|
||||
if (updates_available.length === 0) {
|
||||
if (updates_available.length == 0) {
|
||||
log.console("\nAll dependencies are up to date!")
|
||||
$_.stop()
|
||||
return
|
||||
|
||||
@@ -4,7 +4,7 @@ return util
|
||||
|
||||
util.dainty_assign = function (target, source) {
|
||||
Object.keys(source).forEach(function (k) {
|
||||
if (typeof source[k] === "function") return
|
||||
if (typeof source[k] == "function") return
|
||||
if (!(k in target)) return
|
||||
if (Array.isArray(source[k])) target[k] = deep_copy(source[k])
|
||||
else if (Object.isObject(source[k])) Object.dainty_assign(target[k], source[k])
|
||||
@@ -13,41 +13,41 @@ util.dainty_assign = function (target, source) {
|
||||
}
|
||||
|
||||
util.get = function (obj, path, defValue) {
|
||||
if (!path) return undefined
|
||||
if (!path) return null
|
||||
var pathArray = Array.isArray(path) ? path : path.match(/([^[.\]])+/g)
|
||||
var result = pathArray.reduce((prevObj, key) => prevObj && prevObj[key], obj)
|
||||
return result === undefined ? defValue : result
|
||||
return result == null ? defValue : result
|
||||
}
|
||||
|
||||
util.isEmpty = function(o) {
|
||||
return Object.keys(o).length === 0
|
||||
return Object.keys(o).length == 0
|
||||
}
|
||||
|
||||
util.dig = function (obj, path, def = {}) {
|
||||
util.dig = function (obj, path, deflt = {}) {
|
||||
var pp = path.split(".")
|
||||
for (var i = 0; i < pp.length - 1; i++) {
|
||||
obj = obj[pp[i]] = obj[pp[i]] || {}
|
||||
}
|
||||
obj[pp[pp.length - 1]] = def
|
||||
return def
|
||||
obj[pp[pp.length - 1]] = deflt
|
||||
return deflt
|
||||
}
|
||||
|
||||
util.access = function (obj, name) {
|
||||
var dig = name.split(".")
|
||||
for (var i of dig) {
|
||||
obj = obj[i]
|
||||
if (!obj) return undefined
|
||||
if (!obj) return null
|
||||
}
|
||||
return obj
|
||||
}
|
||||
|
||||
util.mergekey = function (o1, o2, k) {
|
||||
if (!o2) return
|
||||
if (typeof o2[k] === "object") {
|
||||
if (typeof o2[k] == "object") {
|
||||
if (Array.isArray(o2[k])) o1[k] = deep_copy(o2[k])
|
||||
else {
|
||||
if (!o1[k]) o1[k] = {}
|
||||
if (typeof o1[k] === "object") util.merge(o1[k], o2[k])
|
||||
if (typeof o1[k] == "object") util.merge(o1[k], o2[k])
|
||||
else o1[k] = o2[k]
|
||||
}
|
||||
} else o1[k] = o2[k]
|
||||
@@ -74,15 +74,15 @@ util.obj_lerp = function(a,b,t) {
|
||||
}
|
||||
|
||||
util.normalizeSpacing = function normalizeSpacing(spacing) {
|
||||
if (typeof spacing === 'number') {
|
||||
if (typeof spacing == 'number') {
|
||||
return {l: spacing, r: spacing, t: spacing, b: spacing}
|
||||
} else if (Array.isArray(spacing)) {
|
||||
if (spacing.length === 2) {
|
||||
if (spacing.length == 2) {
|
||||
return {l: spacing[0], r: spacing[0], t: spacing[1], b: spacing[1]}
|
||||
} else if (spacing.length === 4) {
|
||||
} else if (spacing.length == 4) {
|
||||
return {l: spacing[0], r: spacing[1], t: spacing[2], b: spacing[3]}
|
||||
}
|
||||
} else if (typeof spacing === 'object') {
|
||||
} else if (typeof spacing == 'object') {
|
||||
return {l: spacing.l || 0, r: spacing.r || 0, t: spacing.t || 0, b: spacing.b || 0}
|
||||
} else {
|
||||
return {l:0, r:0, t:0, b:0}
|
||||
|
||||
@@ -33,11 +33,11 @@ This function serializes JavaScript values (such as numbers, strings, booleans,
|
||||
|
||||
wota.decode[cell.DOC] = `Decode a WOTA-encoded ArrayBuffer into a JavaScript value.
|
||||
|
||||
This function deserializes a WOTA-formatted ArrayBuffer into its corresponding JavaScript representation, such as a number, string, boolean, array, object, or ArrayBuffer. If the input is invalid or empty, it returns undefined.
|
||||
This function deserializes a WOTA-formatted ArrayBuffer into its corresponding JavaScript representation, such as a number, string, boolean, array, object, or ArrayBuffer. If the input is invalid or empty, it returns null.
|
||||
|
||||
:param buffer: An ArrayBuffer containing WOTA-encoded data to decode.
|
||||
:param reviver: An optional function that transforms the decoded values.
|
||||
:return: The decoded JavaScript value (e.g., number, string, boolean, array, object, or ArrayBuffer), or undefined if no argument is provided.
|
||||
:return: The decoded JavaScript value (e.g., number, string, boolean, array, object, or ArrayBuffer), or null if no argument is provided.
|
||||
`
|
||||
|
||||
return wota
|
||||
|
||||
105
source/cell.c
105
source/cell.c
@@ -378,7 +378,7 @@ void actor_unneeded(cell_rt *actor, JSValue fn, double seconds)
|
||||
JS_FreeValue(actor->context, actor->unneeded);
|
||||
|
||||
if (!JS_IsFunction(actor->context, fn)) {
|
||||
actor->unneeded = JS_UNDEFINED;
|
||||
actor->unneeded = JS_NULL;
|
||||
goto END;
|
||||
}
|
||||
|
||||
@@ -398,10 +398,10 @@ cell_rt *create_actor(void *wota)
|
||||
cell_rt *actor = calloc(sizeof(*actor), 1);
|
||||
actor->heap = mi_heap_new();
|
||||
actor->init_wota = wota;
|
||||
actor->idx_buffer = JS_UNDEFINED;
|
||||
actor->message_handle = JS_UNDEFINED;
|
||||
actor->unneeded = JS_UNDEFINED;
|
||||
actor->on_exception = JS_UNDEFINED;
|
||||
actor->idx_buffer = JS_NULL;
|
||||
actor->message_handle = JS_NULL;
|
||||
actor->unneeded = JS_NULL;
|
||||
actor->on_exception = JS_NULL;
|
||||
actor->actor_sym = JS_ATOM_NULL;
|
||||
|
||||
arrsetcap(actor->letters, 5);
|
||||
@@ -476,9 +476,9 @@ static Uint32 actor_remove_cb(cell_rt *actor, Uint32 id, Uint32 interval)
|
||||
{
|
||||
actor->disrupt = 1;
|
||||
|
||||
if (!JS_IsUndefined(actor->unneeded)) {
|
||||
if (!JS_IsNull(actor->unneeded)) {
|
||||
SDL_LockMutex(actor->mutex);
|
||||
JSValue ret = JS_Call(actor->context, actor->unneeded, JS_UNDEFINED, 0, NULL);
|
||||
JSValue ret = JS_Call(actor->context, actor->unneeded, JS_NULL, 0, NULL);
|
||||
uncaught_exception(actor->context, ret);
|
||||
SDL_UnlockMutex(actor->mutex);
|
||||
}
|
||||
@@ -574,11 +574,11 @@ void actor_turn(cell_rt *actor)
|
||||
size_t size = l.blob_data->length / 8; // Convert bits to bytes
|
||||
JSValue arg = js_new_blob_stoned_copy(actor->context, l.blob_data->data, size);
|
||||
blob_destroy(l.blob_data);
|
||||
result = JS_Call(actor->context, actor->message_handle, JS_UNDEFINED, 1, &arg);
|
||||
result = JS_Call(actor->context, actor->message_handle, JS_NULL, 1, &arg);
|
||||
uncaught_exception(actor->context, result);
|
||||
JS_FreeValue(actor->context, arg);
|
||||
} else if (l.type == LETTER_CALLBACK) {
|
||||
result = JS_Call(actor->context, l.callback, JS_UNDEFINED, 0, NULL);
|
||||
result = JS_Call(actor->context, l.callback, JS_NULL, 0, NULL);
|
||||
uncaught_exception(actor->context, result);
|
||||
JS_FreeValue(actor->context, l.callback);
|
||||
}
|
||||
@@ -627,7 +627,7 @@ JSValue js_actor_delay(JSContext *js, JSValue self, int argc, JSValue *argv)
|
||||
JS_ToFloat64(js, &seconds, argv[1]);
|
||||
if (seconds <= 0) {
|
||||
actor_clock(actor, argv[0]);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
SDL_LockMutex(actor->msg_mutex);
|
||||
@@ -643,11 +643,11 @@ JSValue js_actor_removetimer(JSContext *js, JSValue self, int argc, JSValue *arg
|
||||
cell_rt *actor = JS_GetContextOpaque(js);
|
||||
uint32_t timer_id;
|
||||
JS_ToUint32(js, &timer_id, argv[0]);
|
||||
if (timer_id == -1) return JS_UNDEFINED;
|
||||
if (timer_id == -1) return JS_NULL;
|
||||
|
||||
SDL_RemoveTimer(timer_id);
|
||||
|
||||
JSValue cb = JS_UNDEFINED;
|
||||
JSValue cb = JS_NULL;
|
||||
|
||||
SDL_LockMutex(actor->msg_mutex);
|
||||
int id = hmgeti(actor->timers, timer_id);
|
||||
@@ -659,7 +659,7 @@ JSValue js_actor_removetimer(JSContext *js, JSValue self, int argc, JSValue *arg
|
||||
|
||||
JS_FreeValue(js,cb);
|
||||
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
// Wrapper struct to keep the array pointer stable
|
||||
@@ -770,7 +770,7 @@ void script_startup(cell_rt *prt)
|
||||
data[stat.filesize] = 0;
|
||||
|
||||
prt->state = ACTOR_RUNNING;
|
||||
JSValue v = JS_Eval(js, data, (size_t)stat.filesize, ENGINE, JS_EVAL_FLAG_STRICT);
|
||||
JSValue v = JS_Eval(js, data, (size_t)stat.filesize, ENGINE, 0);
|
||||
uncaught_exception(js, v);
|
||||
prt->state = ACTOR_IDLE;
|
||||
set_actor_state(prt);
|
||||
@@ -788,7 +788,7 @@ int uncaught_exception(JSContext *js, JSValue v)
|
||||
}
|
||||
|
||||
JSValue exp = JS_GetException(js);
|
||||
JSValue ret = JS_Call(js, rt->on_exception, JS_UNDEFINED, 1, &exp);
|
||||
JSValue ret = JS_Call(js, rt->on_exception, JS_NULL, 1, &exp);
|
||||
JS_FreeValue(js,ret);
|
||||
JS_FreeValue(js, exp);
|
||||
JS_FreeValue(js,v);
|
||||
@@ -870,7 +870,80 @@ int main(int argc, char **argv)
|
||||
int profile_enabled = 0;
|
||||
int script_start = 1;
|
||||
|
||||
/* Check for --profile flag first */
|
||||
/* Check for --script flag - execute script directly without engine */
|
||||
if (argc > 2 && strcmp(argv[1], "--script") == 0) {
|
||||
/* Read and execute the script file */
|
||||
FILE *f = fopen(argv[2], "rb");
|
||||
if (!f) {
|
||||
perror("fopen");
|
||||
return 1;
|
||||
}
|
||||
|
||||
fseek(f, 0, SEEK_END);
|
||||
long size = ftell(f);
|
||||
if (size < 0) {
|
||||
perror("ftell");
|
||||
fclose(f);
|
||||
return 1;
|
||||
}
|
||||
|
||||
char *script = malloc(size + 1);
|
||||
if (!script) {
|
||||
perror("malloc");
|
||||
fclose(f);
|
||||
return 1;
|
||||
}
|
||||
|
||||
rewind(f);
|
||||
if (fread(script, 1, size, f) != size) {
|
||||
perror("fread");
|
||||
free(script);
|
||||
fclose(f);
|
||||
return 1;
|
||||
}
|
||||
fclose(f);
|
||||
script[size] = '\0';
|
||||
|
||||
/* Create minimal JS runtime */
|
||||
JSRuntime *rt = JS_NewRuntime();
|
||||
JSContext *js = JS_NewContextRaw(rt);
|
||||
|
||||
/* Add basic intrinsics */
|
||||
JS_AddIntrinsicBaseObjects(js);
|
||||
JS_AddIntrinsicEval(js);
|
||||
JS_AddIntrinsicRegExp(js);
|
||||
JS_AddIntrinsicJSON(js);
|
||||
JS_AddIntrinsicMapSet(js);
|
||||
JS_AddIntrinsicProxy(js);
|
||||
|
||||
cell_rt *prt = malloc(sizeof(*prt));
|
||||
JS_SetContextOpaque(js, prt);
|
||||
|
||||
/* Load FFI functions */
|
||||
ffi_load(js);
|
||||
|
||||
/* Execute the script */
|
||||
JSValue result = JS_Eval(js, script, size, argv[2], 0);
|
||||
free(script);
|
||||
|
||||
/* Check for exceptions */
|
||||
if (JS_IsException(result)) {
|
||||
JSValue exp = JS_GetException(js);
|
||||
const char *str = JS_ToCString(js, exp);
|
||||
if (str) {
|
||||
fprintf(stderr, "Exception: %s\n", str);
|
||||
JS_FreeCString(js, str);
|
||||
}
|
||||
JS_FreeValue(js, exp);
|
||||
}
|
||||
|
||||
JS_FreeValue(js, result);
|
||||
JS_FreeContext(js);
|
||||
JS_FreeRuntime(rt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check for --profile flag */
|
||||
if (argc > 1 && strcmp(argv[1], "--profile") == 0) {
|
||||
profile_enabled = 1; script_start = 2;
|
||||
}
|
||||
|
||||
118
source/jsffi.c
118
source/jsffi.c
@@ -170,33 +170,6 @@ typedef struct texture_vertex {
|
||||
uint8_t r, g, b,a;
|
||||
} texture_vertex;
|
||||
|
||||
|
||||
static inline size_t typed_array_bytes(JSTypedArrayEnum type) {
|
||||
switch(type) {
|
||||
case JS_TYPED_ARRAY_UINT8C:
|
||||
case JS_TYPED_ARRAY_INT8:
|
||||
case JS_TYPED_ARRAY_UINT8:
|
||||
return 1;
|
||||
|
||||
case JS_TYPED_ARRAY_INT16:
|
||||
case JS_TYPED_ARRAY_UINT16:
|
||||
return 2;
|
||||
|
||||
case JS_TYPED_ARRAY_INT32:
|
||||
case JS_TYPED_ARRAY_UINT32:
|
||||
case JS_TYPED_ARRAY_FLOAT32:
|
||||
return 4;
|
||||
|
||||
case JS_TYPED_ARRAY_BIG_INT64:
|
||||
case JS_TYPED_ARRAY_BIG_UINT64:
|
||||
case JS_TYPED_ARRAY_FLOAT64:
|
||||
return 8;
|
||||
|
||||
default:
|
||||
return 0; // Return 0 for unknown types
|
||||
}
|
||||
}
|
||||
|
||||
#define JS_GETNUM(JS,VAL,I,TO,TYPE) { \
|
||||
JSValue val = JS_GetPropertyUint32(JS,VAL,I); \
|
||||
TO = js2##TYPE(JS, val); \
|
||||
@@ -270,34 +243,36 @@ void free_gpu_buffer(JSRuntime *rt, void *opaque, void *ptr)
|
||||
JSValue make_gpu_buffer(JSContext *js, void *data, size_t size, int type, int elements, int copy, int index)
|
||||
{
|
||||
JSValue tstack[3];
|
||||
tstack[1] = JS_UNDEFINED;
|
||||
tstack[2] = JS_UNDEFINED;
|
||||
tstack[1] = JS_NULL;
|
||||
tstack[2] = JS_NULL;
|
||||
// TODO: always copying; implement "takeover"
|
||||
tstack[0] = js_new_blob_stoned_copy(js,data,size);//, make_gpu_buffer, NULL, 1);
|
||||
JSValue ret = JS_NewTypedArray(js, 3, tstack, type);
|
||||
JS_SetPropertyStr(js,ret,"stride", number2js(js,typed_array_bytes(type)*elements));
|
||||
JS_SetPropertyStr(js,ret,"elen", number2js(js,typed_array_bytes(type)));
|
||||
JS_SetPropertyStr(js,ret,"index", JS_NewBool(js,index));
|
||||
JS_FreeValue(js,tstack[0]);
|
||||
return ret;
|
||||
// JSValue ret = JS_NewTypedArray(js, 3, tstack, type);
|
||||
// JS_SetPropertyStr(js,ret,"stride", number2js(js,typed_array_bytes(type)*elements));
|
||||
// JS_SetPropertyStr(js,ret,"elen", number2js(js,typed_array_bytes(type)));
|
||||
// JS_SetPropertyStr(js,ret,"index", JS_NewBool(js,index));
|
||||
// JS_FreeValue(js,tstack[0]);
|
||||
// return ret;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
void *get_gpu_buffer(JSContext *js, JSValue argv, size_t *stride, size_t *size)
|
||||
{
|
||||
size_t o, len, bytes, msize;
|
||||
return NULL;
|
||||
/* size_t o, len, bytes, msize;
|
||||
JSValue buf = JS_GetTypedArrayBuffer(js, argv, &o, &len, &bytes);
|
||||
void *data = js_get_blob_data(js, &msize, buf);
|
||||
JS_FreeValue(js,buf);
|
||||
if (stride) *stride = js_getnum_str(js, argv, "stride");
|
||||
if (size) *size = msize;
|
||||
return data;
|
||||
return data;*/
|
||||
}
|
||||
|
||||
JSValue make_quad_indices_buffer(JSContext *js, int quads)
|
||||
{
|
||||
cell_rt *rt = JS_GetContextOpaque(js);
|
||||
int count = quads*6;
|
||||
if (!JS_IsUndefined(rt->idx_buffer) && rt->idx_count >= count)
|
||||
if (!JS_IsNull(rt->idx_buffer) && rt->idx_count >= count)
|
||||
return JS_DupValue(js,rt->idx_buffer);
|
||||
|
||||
int verts = quads*4;
|
||||
@@ -311,10 +286,10 @@ JSValue make_quad_indices_buffer(JSContext *js, int quads)
|
||||
indices[i+5] = v+1;
|
||||
}
|
||||
|
||||
if (!JS_IsUndefined(rt->idx_buffer))
|
||||
if (!JS_IsNull(rt->idx_buffer))
|
||||
JS_FreeValue(js,rt->idx_buffer);
|
||||
|
||||
rt->idx_buffer = make_gpu_buffer(js,indices, sizeof(*indices)*count, JS_TYPED_ARRAY_UINT16, 1,0,1);
|
||||
// rt->idx_buffer = make_gpu_buffer(js,indices, sizeof(*indices)*count, JS_TYPED_ARRAY_UINT16, 1,0,1);
|
||||
rt->idx_count = count;
|
||||
return JS_DupValue(js,rt->idx_buffer);
|
||||
}
|
||||
@@ -333,9 +308,9 @@ JSValue quads_to_mesh(JSContext *js, text_vert *buffer)
|
||||
color[i] = buffer[i].color;
|
||||
}
|
||||
|
||||
JSValue jspos = make_gpu_buffer(js, pos, sizeof(HMM_Vec2)*arrlen(buffer), JS_TYPED_ARRAY_FLOAT32, 2,0,0);
|
||||
JSValue jsuv = make_gpu_buffer(js, uv, sizeof(HMM_Vec2)*arrlen(buffer), JS_TYPED_ARRAY_FLOAT32, 2,0,0);
|
||||
JSValue jscolor = make_gpu_buffer(js, color, sizeof(HMM_Vec4)*arrlen(buffer), JS_TYPED_ARRAY_FLOAT32, 4,0,0);
|
||||
JSValue jspos = make_gpu_buffer(js, pos, sizeof(HMM_Vec2)*arrlen(buffer), 0, 2,0,0);
|
||||
JSValue jsuv = make_gpu_buffer(js, uv, sizeof(HMM_Vec2)*arrlen(buffer), 0, 2,0,0);
|
||||
JSValue jscolor = make_gpu_buffer(js, color, sizeof(HMM_Vec4)*arrlen(buffer), 0, 4,0,0);
|
||||
|
||||
size_t quads = verts/4;
|
||||
size_t count = verts/2*3;
|
||||
@@ -405,10 +380,10 @@ double js2angle(JSContext *js,JSValue v) {
|
||||
typedef HMM_Vec4 colorf;
|
||||
|
||||
colorf js2color(JSContext *js,JSValue v) {
|
||||
if (JS_IsUndefined(v)) return (colorf){1,1,1,1};
|
||||
if (JS_IsNull(v)) return (colorf){1,1,1,1};
|
||||
JSValue c[4];
|
||||
for (int i = 0; i < 4; i++) c[i] = JS_GetPropertyUint32(js,v,i);
|
||||
float a = JS_IsUndefined(c[3]) ? 1.0 : js2number(js,c[3]);
|
||||
float a = JS_IsNull(c[3]) ? 1.0 : js2number(js,c[3]);
|
||||
colorf color = {
|
||||
.r = js2number(js,c[0]),
|
||||
.g = js2number(js,c[1]),
|
||||
@@ -557,7 +532,7 @@ JSValue vecarr2js(JSContext *js,HMM_Vec2 *points, int n) {
|
||||
}
|
||||
|
||||
rect js2rect(JSContext *js,JSValue v) {
|
||||
if (JS_IsUndefined(v)) return (rect){0,0,1,1};
|
||||
if (JS_IsNull(v)) return (rect){0,0,1,1};
|
||||
rect rect;
|
||||
JS_GETATOM(js,rect.x,v,x,number)
|
||||
JS_GETATOM(js,rect.y,v,y,number)
|
||||
@@ -575,7 +550,7 @@ rect js2rect(JSContext *js,JSValue v) {
|
||||
|
||||
irect js2irect(JSContext *js, JSValue v)
|
||||
{
|
||||
if (JS_IsUndefined(v)) return (irect){0,0,1,1};
|
||||
if (JS_IsNull(v)) return (irect){0,0,1,1};
|
||||
irect rect;
|
||||
JS_GETATOM(js,rect.x,v,x,number)
|
||||
JS_GETATOM(js,rect.y,v,y,number)
|
||||
@@ -719,7 +694,7 @@ JSC_CCALL(os_make_text_buffer,
|
||||
JSValue js_util_camera_globals(JSContext *js, JSValue self, int argc, JSValue *argv)
|
||||
{
|
||||
JSValue camera = argv[0];
|
||||
if(JS_IsUndefined(camera)) return JS_UNDEFINED;
|
||||
if(JS_IsNull(camera)) return JS_NULL;
|
||||
|
||||
HMM_Vec2 size; HMM_Vec3 pos; HMM_Quat rotation;
|
||||
double fov = 0; int ortho; double near_z = 0; double far_z = 0;
|
||||
@@ -840,10 +815,10 @@ JSC_CCALL(array_lerp,
|
||||
)
|
||||
|
||||
JSValue js_array_get_x(JSContext *js, JSValue self) { return JS_GetPropertyUint32(js,self,0); }
|
||||
JSValue js_array_set_x(JSContext *js, JSValue self, JSValue val) { JS_SetPropertyUint32(js,self,0,val); return JS_UNDEFINED; }
|
||||
JSValue js_array_set_x(JSContext *js, JSValue self, JSValue val) { JS_SetPropertyUint32(js,self,0,val); return JS_NULL; }
|
||||
|
||||
JSValue js_array_get_y(JSContext *js, JSValue self) { return JS_GetPropertyUint32(js,self,1); }
|
||||
JSValue js_array_set_y(JSContext *js, JSValue self, JSValue val) { JS_SetPropertyUint32(js,self,1,val); return JS_UNDEFINED; }
|
||||
JSValue js_array_set_y(JSContext *js, JSValue self, JSValue val) { JS_SetPropertyUint32(js,self,1,val); return JS_NULL; }
|
||||
|
||||
JSValue js_array_get_xy(JSContext *js, JSValue self)
|
||||
{
|
||||
@@ -857,7 +832,7 @@ JSValue js_array_set_xy(JSContext *js, JSValue self, JSValue v)
|
||||
{
|
||||
JS_SetPropertyUint32(js,self,0,JS_GetPropertyUint32(js,v,0));
|
||||
JS_SetPropertyUint32(js,self,1,JS_GetPropertyUint32(js,v,1));
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
// Single-value accessors
|
||||
@@ -866,25 +841,25 @@ JSValue js_array_get_r(JSContext *js, JSValue self)
|
||||
{ return JS_GetPropertyUint32(js, self, 0); }
|
||||
|
||||
JSValue js_array_set_r(JSContext *js, JSValue self, JSValue val)
|
||||
{ JS_SetPropertyUint32(js, self, 0, val); return JS_UNDEFINED; }
|
||||
{ JS_SetPropertyUint32(js, self, 0, val); return JS_NULL; }
|
||||
|
||||
JSValue js_array_get_g(JSContext *js, JSValue self)
|
||||
{ return JS_GetPropertyUint32(js, self, 1); }
|
||||
|
||||
JSValue js_array_set_g(JSContext *js, JSValue self, JSValue val)
|
||||
{ JS_SetPropertyUint32(js, self, 1, val); return JS_UNDEFINED; }
|
||||
{ JS_SetPropertyUint32(js, self, 1, val); return JS_NULL; }
|
||||
|
||||
JSValue js_array_get_b(JSContext *js, JSValue self)
|
||||
{ return JS_GetPropertyUint32(js, self, 2); }
|
||||
|
||||
JSValue js_array_set_b(JSContext *js, JSValue self, JSValue val)
|
||||
{ JS_SetPropertyUint32(js, self, 2, val); return JS_UNDEFINED; }
|
||||
{ JS_SetPropertyUint32(js, self, 2, val); return JS_NULL; }
|
||||
|
||||
JSValue js_array_get_a(JSContext *js, JSValue self)
|
||||
{ return JS_GetPropertyUint32(js, self, 3); }
|
||||
|
||||
JSValue js_array_set_a(JSContext *js, JSValue self, JSValue val)
|
||||
{ JS_SetPropertyUint32(js, self, 3, val); return JS_UNDEFINED; }
|
||||
{ JS_SetPropertyUint32(js, self, 3, val); return JS_NULL; }
|
||||
|
||||
// Multi-value accessors
|
||||
|
||||
@@ -902,7 +877,7 @@ JSValue js_array_set_rgb(JSContext *js, JSValue self, JSValue val)
|
||||
JS_SetPropertyUint32(js, self, 0, JS_GetPropertyUint32(js, val, 0));
|
||||
JS_SetPropertyUint32(js, self, 1, JS_GetPropertyUint32(js, val, 1));
|
||||
JS_SetPropertyUint32(js, self, 2, JS_GetPropertyUint32(js, val, 2));
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
JSValue js_array_get_rgba(JSContext *js, JSValue self)
|
||||
@@ -921,7 +896,7 @@ JSValue js_array_set_rgba(JSContext *js, JSValue self, JSValue val)
|
||||
JS_SetPropertyUint32(js, self, 1, JS_GetPropertyUint32(js, val, 1));
|
||||
JS_SetPropertyUint32(js, self, 2, JS_GetPropertyUint32(js, val, 2));
|
||||
JS_SetPropertyUint32(js, self, 3, JS_GetPropertyUint32(js, val, 3));
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
static const JSCFunctionListEntry js_array_funcs[] = {
|
||||
@@ -1239,10 +1214,12 @@ JSValue make_color_buffer(JSContext *js, colorf c, int verts)
|
||||
for (int i = 0; i < verts; i++)
|
||||
colordata[i] = c;
|
||||
|
||||
return make_gpu_buffer(js, colordata, sizeof(*colordata)*verts, JS_TYPED_ARRAY_FLOAT32, 4, 0, 0);
|
||||
return make_gpu_buffer(js, colordata, sizeof(*colordata)*verts, 0, 4, 0, 0);
|
||||
}
|
||||
|
||||
JSC_CCALL(os_make_line_prim,
|
||||
return JS_NULL;
|
||||
/*
|
||||
JSValue prim = JS_NewObject(js);
|
||||
HMM_Vec2 *v = js2cpvec2arr(js,argv[0]);
|
||||
|
||||
@@ -1262,7 +1239,7 @@ JSC_CCALL(os_make_line_prim,
|
||||
.closed = JS_ToBool(js,argv[3])
|
||||
});
|
||||
|
||||
JS_SetPropertyStr(js, prim, "pos", make_gpu_buffer(js,m->positions,sizeof(*m->positions)*m->num_vertices, JS_TYPED_ARRAY_FLOAT32, 2,1,0));
|
||||
JS_SetPropertyStr(js, prim, "pos", make_gpu_buffer(js,m->positions,sizeof(*m->positions)*m->num_vertices, 0, 2,1,0));
|
||||
|
||||
JS_SetPropertyStr(js, prim, "indices", make_gpu_buffer(js,m->triangle_indices,sizeof(*m->triangle_indices)*m->num_triangles*3, JS_TYPED_ARRAY_UINT32, 1,1,1));
|
||||
|
||||
@@ -1272,7 +1249,7 @@ JSC_CCALL(os_make_line_prim,
|
||||
uv[i*2+1] = m->annotations[i].v_across_curve;
|
||||
}
|
||||
|
||||
JS_SetPropertyStr(js, prim, "uv", make_gpu_buffer(js, uv, sizeof(uv), JS_TYPED_ARRAY_FLOAT32,2,1,0));
|
||||
JS_SetPropertyStr(js, prim, "uv", make_gpu_buffer(js, uv, sizeof(uv), 0,2,1,0));
|
||||
JS_SetPropertyStr(js,prim,"vertices", number2js(js,m->num_vertices));
|
||||
JS_SetPropertyStr(js,prim,"color",make_color_buffer(js,js2color(js,argv[4]), m->num_vertices));
|
||||
JS_SetPropertyStr(js,prim,"num_indices", number2js(js,m->num_triangles*3));
|
||||
@@ -1281,10 +1258,11 @@ JSC_CCALL(os_make_line_prim,
|
||||
parsl_destroy_context(par_ctx);
|
||||
|
||||
return prim;
|
||||
*/
|
||||
)
|
||||
|
||||
static void render_frame(plm_t *mpeg, plm_frame_t *frame, datastream *ds) {
|
||||
if (JS_IsUndefined(ds->callback)) return;
|
||||
if (JS_IsNull(ds->callback)) return;
|
||||
uint8_t *rgb = malloc(frame->height*frame->width*4);
|
||||
memset(rgb,255,frame->height*frame->width*4);
|
||||
plm_frame_to_rgba(frame, rgb, frame->width*4);
|
||||
@@ -1300,7 +1278,7 @@ static void render_frame(plm_t *mpeg, plm_frame_t *frame, datastream *ds) {
|
||||
JSValue s[1];
|
||||
s[0] = surfData;
|
||||
JSValue cb = JS_DupValue(ds->js,ds->callback);
|
||||
JSValue ret = JS_Call(ds->js, cb, JS_UNDEFINED, 1, s);
|
||||
JSValue ret = JS_Call(ds->js, cb, JS_NULL, 1, s);
|
||||
JS_FreeValue(ds->js,cb);
|
||||
free(rgb);
|
||||
uncaught_exception(ds->js,ret);
|
||||
@@ -1312,7 +1290,7 @@ JSC_CCALL(os_make_video,
|
||||
datastream *ds = ds_openvideo(data, len);
|
||||
if (!ds) return JS_ThrowReferenceError(js, "Video file was not valid.");
|
||||
ds->js = js;
|
||||
ds->callback = JS_UNDEFINED;
|
||||
ds->callback = JS_NULL;
|
||||
plm_set_video_decode_callback(ds->plm, render_frame, ds);
|
||||
return datastream2js(js,ds);
|
||||
)
|
||||
@@ -1336,7 +1314,7 @@ JSC_CCALL(os_rectpack,
|
||||
int packed = stbrp_pack_rects(ctx, rects, num);
|
||||
|
||||
if (!packed) {
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
ret = JS_NewArray(js);
|
||||
@@ -1361,7 +1339,7 @@ JSC_CCALL(os_insertion_sort,
|
||||
while (j >= 0) {
|
||||
JSValue arr_j = JS_GetPropertyUint32(js, arr, j);
|
||||
|
||||
JSValue ret = JS_Call(js, cmp, JS_UNDEFINED, 2, (JSValue[]){ arr_j, key });
|
||||
JSValue ret = JS_Call(js, cmp, JS_NULL, 2, (JSValue[]){ arr_j, key });
|
||||
if (JS_IsException(ret)) {
|
||||
JS_FreeValue(js,arr_j);
|
||||
JS_FreeValue(js,key);
|
||||
@@ -1389,13 +1367,13 @@ JSC_CCALL(os_power_state,
|
||||
SDL_PowerState state = SDL_GetPowerInfo(NULL, NULL);
|
||||
switch(state) {
|
||||
case SDL_POWERSTATE_ERROR: return JS_ThrowTypeError(js, "Error determining power status");
|
||||
case SDL_POWERSTATE_UNKNOWN: return JS_UNDEFINED;
|
||||
case SDL_POWERSTATE_UNKNOWN: return JS_NULL;
|
||||
case SDL_POWERSTATE_ON_BATTERY: return JS_NewString(js, "on battery");
|
||||
case SDL_POWERSTATE_NO_BATTERY: return JS_NewString(js, "no battery");
|
||||
case SDL_POWERSTATE_CHARGING: return JS_NewString(js, "charging");
|
||||
case SDL_POWERSTATE_CHARGED: return JS_NewString(js, "charged");
|
||||
}
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
)
|
||||
|
||||
JSC_CCALL(os_cull_sprites,
|
||||
@@ -1530,7 +1508,6 @@ js_##NAME = JS_NewObject(js); \
|
||||
JS_SetPropertyFunctionList(js, js_##NAME, js_##NAME##_funcs, countof(js_##NAME##_funcs)); \
|
||||
JS_SetPrototype(js, js_##NAME, PARENT); \
|
||||
|
||||
JSValue js_layout_use(JSContext *js);
|
||||
JSValue js_miniz_use(JSContext *js);
|
||||
JSValue js_num_use(JSContext *js);
|
||||
|
||||
@@ -1569,6 +1546,7 @@ JSC_CCALL(os_value_id,
|
||||
#include "qjs_wota.h"
|
||||
#include "qjs_socket.h"
|
||||
#include "qjs_nota.h"
|
||||
#include "qjs_ffi.h"
|
||||
|
||||
//JSValue js_imgui_use(JSContext *js);
|
||||
#define MISTLINE(NAME) (ModuleEntry){#NAME, js_##NAME##_use}
|
||||
@@ -1604,6 +1582,7 @@ void ffi_load(JSContext *js)
|
||||
arrput(rt->module_registry, MISTLINE(text));
|
||||
arrput(rt->module_registry, MISTLINE(wota));
|
||||
arrput(rt->module_registry, MISTLINE(nota));
|
||||
arrput(rt->module_registry, MISTLINE(ffi));
|
||||
|
||||
// power user
|
||||
arrput(rt->module_registry, MISTLINE(js));
|
||||
@@ -1621,7 +1600,6 @@ void ffi_load(JSContext *js)
|
||||
arrput(rt->module_registry, MISTLINE(graphics));
|
||||
arrput(rt->module_registry, MISTLINE(video));
|
||||
arrput(rt->module_registry, MISTLINE(soloud));
|
||||
arrput(rt->module_registry, MISTLINE(layout));
|
||||
|
||||
// arrput(rt->module_registry, MISTLINE(imgui));
|
||||
arrput(rt->module_registry, ((ModuleEntry){"camera", js_camera_use}));
|
||||
@@ -1670,7 +1648,7 @@ void ffi_load(JSContext *js)
|
||||
|
||||
const char actorsym_script[] = "var sym = Symbol(`actordata`); sym;";
|
||||
|
||||
JSValue actorsym = JS_Eval(js, actorsym_script, sizeof(actorsym_script)-1, "internal", JS_EVAL_FLAG_STRICT);
|
||||
JSValue actorsym = JS_Eval(js, actorsym_script, sizeof(actorsym_script)-1, "internal", 0);
|
||||
|
||||
JS_SetPropertyStr(js, hidden_fn, "actorsym", actorsym);
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ cell_rt *js2actor(JSContext *js, JSValue v)
|
||||
cell_rt *crt = JS_GetContextOpaque(js);
|
||||
JSValue actor_data = JS_GetProperty(js, v, crt->actor_sym);
|
||||
|
||||
if (JS_IsUndefined(actor_data)) {
|
||||
if (JS_IsNull(actor_data)) {
|
||||
JS_FreeValue(js, actor_data);
|
||||
return NULL;
|
||||
}
|
||||
@@ -28,7 +28,7 @@ cell_rt *js2actor(JSContext *js, JSValue v)
|
||||
JSValue id_val = JS_GetPropertyStr(js, actor_data, "id");
|
||||
JS_FreeValue(js, actor_data);
|
||||
|
||||
if (JS_IsUndefined(id_val)) {
|
||||
if (JS_IsNull(id_val)) {
|
||||
JS_FreeValue(js, id_val);
|
||||
return NULL;
|
||||
}
|
||||
@@ -78,7 +78,7 @@ JSC_CCALL(os_createactor,
|
||||
if (rt->disrupt)
|
||||
return JS_ThrowInternalError(js, "Can't start a new actor while disrupting.");
|
||||
|
||||
void *startup = value2wota(js, argv[0], JS_UNDEFINED, NULL);
|
||||
void *startup = value2wota(js, argv[0], JS_NULL, NULL);
|
||||
create_actor(startup);
|
||||
)
|
||||
|
||||
@@ -98,7 +98,7 @@ JSC_CCALL(os_mailbox_push,
|
||||
JS_FreeCString(js,id);
|
||||
|
||||
/* JSValue sys = JS_GetPropertyStr(js, argv[1], "__SYSTEM__");
|
||||
if (!JS_IsUndefined(sys)) {
|
||||
if (!JS_IsNull(sys)) {
|
||||
const char *k = JS_ToCString(js,sys);
|
||||
int stop = 0;
|
||||
if (strcmp(k, "stop") == 0) {
|
||||
@@ -108,7 +108,7 @@ JSC_CCALL(os_mailbox_push,
|
||||
JS_FreeValue(js,sys);
|
||||
JS_FreeCString(js,k);
|
||||
|
||||
if (stop) return JS_UNDEFINED;
|
||||
if (stop) return JS_NULL;
|
||||
}
|
||||
*/
|
||||
size_t size;
|
||||
|
||||
@@ -60,7 +60,7 @@ static JSValue js_blob_constructor(JSContext *ctx, JSValueConst new_target,
|
||||
|
||||
size_t bits_written = 0;
|
||||
while (bits_written < length_bits) {
|
||||
JSValue randval = JS_Call(ctx, argv[1], JS_UNDEFINED, 0, NULL);
|
||||
JSValue randval = JS_Call(ctx, argv[1], JS_NULL, 0, NULL);
|
||||
if (JS_IsException(randval)) {
|
||||
blob_destroy(bd);
|
||||
return JS_EXCEPTION;
|
||||
@@ -151,7 +151,7 @@ static JSValue js_blob_write_bit(JSContext *ctx, JSValueConst this_val,
|
||||
if (blob_write_bit(bd, bit_val) < 0) {
|
||||
return JS_ThrowTypeError(ctx, "write_bit: cannot write (maybe stone or OOM)");
|
||||
}
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
// blob.write_blob(second_blob)
|
||||
@@ -173,7 +173,7 @@ static JSValue js_blob_write_blob(JSContext *ctx, JSValueConst this_val,
|
||||
return JS_ThrowTypeError(ctx, "write_blob: cannot write to stone blob or OOM");
|
||||
}
|
||||
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
// blob.write_dec64(number)
|
||||
@@ -194,7 +194,7 @@ static JSValue js_blob_write_number(JSContext *ctx, JSValueConst this_val,
|
||||
if (blob_write_dec64(bd, d) < 0)
|
||||
return JS_ThrowTypeError(ctx, "write_dec64: cannot write to stone blob or OOM");
|
||||
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
// blob.write_fit(value, len)
|
||||
@@ -217,7 +217,7 @@ static JSValue js_blob_write_fit(JSContext *ctx, JSValueConst this_val,
|
||||
return JS_ThrowTypeError(ctx, "write_fit: value doesn't fit in specified bits, stone blob, or OOM");
|
||||
}
|
||||
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
// blob.write_kim(fit)
|
||||
@@ -239,7 +239,7 @@ static JSValue js_blob_write_text(JSContext *ctx, JSValueConst this_val,
|
||||
}
|
||||
|
||||
JS_FreeCString(ctx,str);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
// blob.write_pad(block_size)
|
||||
@@ -258,7 +258,7 @@ static JSValue js_blob_write_pad(JSContext *ctx, JSValueConst this_val,
|
||||
if (blob_write_pad(bd, block_size) < 0)
|
||||
return JS_ThrowTypeError(ctx, "write_pad: cannot write (stone blob, OOM, or invalid block size)");
|
||||
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
// blob.read_logical(from)
|
||||
@@ -439,7 +439,7 @@ static JSValue js_blob_stone(JSContext *ctx, JSValueConst this_val,
|
||||
if (!bd->is_stone) {
|
||||
blob_make_stone(bd);
|
||||
}
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
static JSValue js_blob_stonep(JSContext *ctx, JSValueConst this_val,
|
||||
|
||||
@@ -73,7 +73,7 @@ JSValue js_dmon_watch(JSContext *js, JSValue self, int argc, JSValue *argv)
|
||||
return JS_ThrowReferenceError(js, "Already watching a directory.");
|
||||
|
||||
watched = dmon_watch(".", watch_cb, DMON_WATCHFLAGS_RECURSIVE, NULL);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
JSValue js_dmon_unwatch(JSContext *js, JSValue self, int argc, JSValue *argv)
|
||||
@@ -83,7 +83,7 @@ JSValue js_dmon_unwatch(JSContext *js, JSValue self, int argc, JSValue *argv)
|
||||
|
||||
dmon_unwatch(watched);
|
||||
watched.id = 0;
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
JSValue js_dmon_poll(JSContext *js, JSValueConst this_val, int argc, JSValueConst *argv) {
|
||||
@@ -110,9 +110,9 @@ JSValue js_dmon_poll(JSContext *js, JSValueConst this_val, int argc, JSValueCons
|
||||
JS_SetPropertyStr(js, jsevent, "root", JS_NewString(js, event.rootdir));
|
||||
JS_SetPropertyStr(js, jsevent, "file", JS_NewString(js, event.filepath));
|
||||
JS_SetPropertyStr(js, jsevent, "old", JS_NewString(js, event.oldfilepath));
|
||||
JS_Call(js, argv[0], JS_UNDEFINED, 1, &jsevent);
|
||||
JS_Call(js, argv[0], JS_NULL, 1, &jsevent);
|
||||
}
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
static const JSCFunctionListEntry js_dmon_funcs[] = {
|
||||
|
||||
@@ -34,13 +34,13 @@ static void js_enet_peer_finalizer(JSRuntime *rt, JSValue val)
|
||||
static JSValue js_enet_initialize(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
||||
{
|
||||
if (enet_initialize() != 0) return JS_ThrowInternalError(ctx, "Error initializing ENet");
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
static JSValue js_enet_deinitialize(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
||||
{
|
||||
enet_deinitialize();
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
static JSValue js_enet_host_create(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
||||
@@ -163,12 +163,12 @@ static JSValue js_enet_host_service(JSContext *ctx, JSValueConst this_val, int a
|
||||
break;
|
||||
}
|
||||
|
||||
uncaught_exception(ctx, JS_Call(ctx, callback, JS_UNDEFINED, 1, &event_obj));
|
||||
uncaught_exception(ctx, JS_Call(ctx, callback, JS_NULL, 1, &event_obj));
|
||||
JS_FreeValue(ctx, event_obj);
|
||||
}
|
||||
|
||||
JS_FreeValue(ctx, callback);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
/* Host connect: client -> connect to server */
|
||||
@@ -201,7 +201,7 @@ static JSValue js_enet_host_flush(JSContext *ctx, JSValueConst this_val, int arg
|
||||
ENetHost *host = JS_GetOpaque(this_val, enet_host_id);
|
||||
if (!host) return JS_EXCEPTION;
|
||||
enet_host_flush(host);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
/* Broadcast a string or ArrayBuffer */
|
||||
@@ -231,7 +231,7 @@ static JSValue js_enet_host_broadcast(JSContext *ctx, JSValueConst this_val, int
|
||||
if (!packet) return JS_ThrowInternalError(ctx, "Failed to create ENet packet");
|
||||
|
||||
enet_host_broadcast(host, 0, packet);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
static JSValue js_enet_host_get_port(JSContext *js, JSValueConst self, int argc, JSValueConst *argv)
|
||||
@@ -264,7 +264,7 @@ static JSValue js_enet_peer_disconnect(JSContext *ctx, JSValueConst this_val, in
|
||||
ENetPeer *peer = JS_GetOpaque(this_val, enet_peer_class_id);
|
||||
if (!peer) return JS_EXCEPTION;
|
||||
enet_peer_disconnect(peer, 0);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
/* Peer send must only accept string or ArrayBuffer */
|
||||
@@ -294,7 +294,7 @@ static JSValue js_enet_peer_send(JSContext *ctx, JSValueConst this_val, int argc
|
||||
if (!packet) return JS_ThrowInternalError(ctx, "Failed to create ENet packet");
|
||||
|
||||
if (enet_peer_send(peer, 0, packet) < 0) return JS_ThrowInternalError(ctx, "Unable to send packet");
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
static JSValue js_enet_peer_disconnect_now(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
||||
@@ -302,7 +302,7 @@ static JSValue js_enet_peer_disconnect_now(JSContext *ctx, JSValueConst this_val
|
||||
ENetPeer *peer = JS_GetOpaque(this_val, enet_peer_class_id);
|
||||
if (!peer) return JS_EXCEPTION;
|
||||
enet_peer_disconnect_now(peer, 0);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
static JSValue js_enet_peer_disconnect_later(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
||||
@@ -310,7 +310,7 @@ static JSValue js_enet_peer_disconnect_later(JSContext *ctx, JSValueConst this_v
|
||||
ENetPeer *peer = JS_GetOpaque(this_val, enet_peer_class_id);
|
||||
if (!peer) return JS_EXCEPTION;
|
||||
enet_peer_disconnect_later(peer, 0);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
static JSValue js_enet_peer_reset(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
||||
@@ -318,7 +318,7 @@ static JSValue js_enet_peer_reset(JSContext *ctx, JSValueConst this_val, int arg
|
||||
ENetPeer *peer = JS_GetOpaque(this_val, enet_peer_class_id);
|
||||
if (!peer) return JS_EXCEPTION;
|
||||
enet_peer_reset(peer);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
static JSValue js_enet_peer_ping(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
||||
@@ -326,7 +326,7 @@ static JSValue js_enet_peer_ping(JSContext *ctx, JSValueConst this_val, int argc
|
||||
ENetPeer *peer = JS_GetOpaque(this_val, enet_peer_class_id);
|
||||
if (!peer) return JS_EXCEPTION;
|
||||
enet_peer_ping(peer);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
static JSValue js_enet_peer_throttle_configure(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
||||
@@ -339,7 +339,7 @@ static JSValue js_enet_peer_throttle_configure(JSContext *ctx, JSValueConst this
|
||||
return JS_ThrowTypeError(ctx, "Expected 3 int arguments: interval, acceleration, deceleration");
|
||||
|
||||
enet_peer_throttle_configure(peer, interval, acceleration, deceleration);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
static JSValue js_enet_peer_timeout(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
||||
@@ -352,7 +352,7 @@ static JSValue js_enet_peer_timeout(JSContext *ctx, JSValueConst this_val, int a
|
||||
return JS_ThrowTypeError(ctx, "Expected 3 integer arguments: timeout_limit, timeout_min, timeout_max");
|
||||
|
||||
enet_peer_timeout(peer, timeout_limit, timeout_min, timeout_max);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
/* Class definitions */
|
||||
@@ -372,7 +372,7 @@ JSValue js_enet_resolve_hostname(JSContext *js, JSValue self, int argc, JSValue
|
||||
// TODO: implement
|
||||
const char *hostname = JS_ToCString(js, argv[0]);
|
||||
JS_FreeCString(js, hostname);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
/* Function lists */
|
||||
@@ -525,9 +525,6 @@ static const JSCFunctionListEntry js_enet_peer_funcs[] = {
|
||||
JS_CGETSET_DEF("address", js_enet_peer_get_address, NULL),
|
||||
};
|
||||
|
||||
/* Module entry point */
|
||||
static int js_enet_init(JSContext *ctx, JSModuleDef *m);
|
||||
|
||||
JSValue js_enet_use(JSContext *ctx)
|
||||
{
|
||||
JS_NewClassID(&enet_host_id);
|
||||
|
||||
@@ -147,7 +147,7 @@ JSC_CCALL(fd_fsync,
|
||||
if (fsync(fd) != 0)
|
||||
return JS_ThrowReferenceError(js, "fsync failed: %s", strerror(errno));
|
||||
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
)
|
||||
|
||||
JSC_CCALL(fd_close,
|
||||
@@ -157,7 +157,7 @@ JSC_CCALL(fd_close,
|
||||
if (close(fd) != 0)
|
||||
return JS_ThrowReferenceError(js, "close failed: %s", strerror(errno));
|
||||
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
)
|
||||
|
||||
JSC_CCALL(fd_fstat,
|
||||
|
||||
413
source/qjs_ffi.c
Normal file
413
source/qjs_ffi.c
Normal file
@@ -0,0 +1,413 @@
|
||||
/*
|
||||
* qjs_ffi.c – QuickJS ↔ libffi bridge
|
||||
*
|
||||
* Works on macOS / Linux / Windows. See examples/ffi_test.js.
|
||||
*/
|
||||
|
||||
#include "qjs_ffi.h"
|
||||
#include <ffi.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
#ifndef countof
|
||||
#define countof(x) (sizeof(x) / sizeof((x)[0]))
|
||||
#endif
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* internal structs */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
typedef struct {
|
||||
ffi_cif cif;
|
||||
ffi_type **arg_types;
|
||||
ffi_type *ret_type;
|
||||
void *fn_ptr;
|
||||
int nargs;
|
||||
} ffi_func;
|
||||
|
||||
typedef struct {
|
||||
void *ptr;
|
||||
int is_library; /* 1 => real dlopen/LoadLibrary handle */
|
||||
} ffi_pointer;
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* QuickJS class plumbing */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
static JSClassID js_ffi_func_id;
|
||||
static JSClassID js_ffi_pointer_id;
|
||||
|
||||
static void ffi_func_free(ffi_func *f)
|
||||
{
|
||||
if (!f) return;
|
||||
|
||||
if (f->arg_types) {
|
||||
for (int i = 0; i < f->nargs; i++) {
|
||||
ffi_type *t = f->arg_types[i];
|
||||
if (t && t != &ffi_type_void && t != &ffi_type_pointer &&
|
||||
t != &ffi_type_sint8 && t != &ffi_type_uint8 &&
|
||||
t != &ffi_type_sint16 && t != &ffi_type_uint16 &&
|
||||
t != &ffi_type_sint32 && t != &ffi_type_uint32 &&
|
||||
t != &ffi_type_sint64 && t != &ffi_type_uint64 &&
|
||||
t != &ffi_type_float && t != &ffi_type_double)
|
||||
free(t);
|
||||
}
|
||||
free(f->arg_types);
|
||||
}
|
||||
|
||||
ffi_type *rtp = f->ret_type;
|
||||
if (rtp && rtp != &ffi_type_void && rtp != &ffi_type_pointer &&
|
||||
rtp != &ffi_type_sint8 && rtp != &ffi_type_uint8 &&
|
||||
rtp != &ffi_type_sint16 && rtp != &ffi_type_uint16 &&
|
||||
rtp != &ffi_type_sint32 && rtp != &ffi_type_uint32 &&
|
||||
rtp != &ffi_type_sint64 && rtp != &ffi_type_uint64 &&
|
||||
rtp != &ffi_type_float && rtp != &ffi_type_double)
|
||||
free(rtp);
|
||||
|
||||
free(f);
|
||||
}
|
||||
|
||||
static void ffi_func_finalizer(JSRuntime *rt, JSValue val)
|
||||
{
|
||||
ffi_func *f = JS_GetOpaque(val, js_ffi_func_id);
|
||||
if (f) ffi_func_free(f);
|
||||
}
|
||||
|
||||
static void ffi_pointer_free(ffi_pointer *p)
|
||||
{
|
||||
if (p->is_library && p->ptr) {
|
||||
#ifdef _WIN32
|
||||
FreeLibrary((HMODULE)p->ptr);
|
||||
#else
|
||||
dlclose(p->ptr);
|
||||
#endif
|
||||
}
|
||||
free(p);
|
||||
}
|
||||
|
||||
static void ffi_pointer_finalizer(JSRuntime *rt, JSValue val)
|
||||
{
|
||||
ffi_pointer *f = JS_GetOpaque(val, js_ffi_pointer_id);
|
||||
if (!f) return;
|
||||
ffi_pointer_free(f);
|
||||
}
|
||||
|
||||
static JSClassDef js_ffi_func_class = { "FFIFunction", .finalizer = ffi_func_finalizer };
|
||||
static JSClassDef js_ffi_pointer_class = { "FFIPointer", .finalizer = ffi_pointer_finalizer };
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* helpers */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
static JSValue
|
||||
js_new_ffi_pointer(JSContext *ctx, void *ptr, int is_library)
|
||||
{
|
||||
JSValue obj = JS_NewObjectClass(ctx, js_ffi_pointer_id);
|
||||
if (JS_IsException(obj)) return obj;
|
||||
|
||||
ffi_pointer *p = malloc(sizeof *p);
|
||||
if (!p) { JS_FreeValue(ctx, obj); return JS_ThrowOutOfMemory(ctx); }
|
||||
|
||||
p->ptr = ptr;
|
||||
p->is_library = is_library;
|
||||
JS_SetOpaque(obj, p);
|
||||
return obj;
|
||||
}
|
||||
|
||||
static void *
|
||||
js_get_ffi_pointer(JSContext *ctx, JSValueConst val)
|
||||
{
|
||||
ffi_pointer *p = JS_GetOpaque2(ctx, val, js_ffi_pointer_id);
|
||||
return p ? p->ptr : NULL;
|
||||
}
|
||||
|
||||
static ffi_type *
|
||||
js_to_ffi_type(JSContext *ctx, const char *name)
|
||||
{
|
||||
if (!strcmp(name, "void")) return &ffi_type_void;
|
||||
if (!strcmp(name, "pointer")) return &ffi_type_pointer;
|
||||
if (!strcmp(name, "float")) return &ffi_type_float;
|
||||
if (!strcmp(name, "double")) return &ffi_type_double;
|
||||
if (!strcmp(name, "int8")) return &ffi_type_sint8;
|
||||
if (!strcmp(name, "uint8")) return &ffi_type_uint8;
|
||||
if (!strcmp(name, "int16")) return &ffi_type_sint16;
|
||||
if (!strcmp(name, "uint16")) return &ffi_type_uint16;
|
||||
if (!strcmp(name, "int32")) return &ffi_type_sint32;
|
||||
if (!strcmp(name, "uint32")) return &ffi_type_uint32;
|
||||
if (!strcmp(name, "int64")) return &ffi_type_sint64;
|
||||
if (!strcmp(name, "uint64")) return &ffi_type_uint64;
|
||||
|
||||
/* synonyms */
|
||||
if (!strcmp(name, "int")) return &ffi_type_sint32;
|
||||
if (!strcmp(name, "uint")) return &ffi_type_uint32;
|
||||
if (!strcmp(name, "char*") || !strcmp(name, "string"))
|
||||
return &ffi_type_pointer;
|
||||
|
||||
JS_ThrowTypeError(ctx, "unknown FFI type \"%s\"", name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* ffi.dlopen */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
static JSValue
|
||||
js_ffi_dlopen(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
if (argc < 1)
|
||||
return JS_ThrowTypeError(ctx, "dlopen: expected path or null");
|
||||
|
||||
const char *path = NULL;
|
||||
if (!JS_IsNull(argv[0])) {
|
||||
path = JS_ToCString(ctx, argv[0]);
|
||||
if (!path) return JS_EXCEPTION;
|
||||
}
|
||||
|
||||
void *h;
|
||||
#ifdef _WIN32
|
||||
h = path ? (void *)LoadLibraryA(path)
|
||||
: (void *)GetModuleHandle(NULL);
|
||||
#else
|
||||
h = path ? dlopen(path, RTLD_LAZY | RTLD_LOCAL)
|
||||
: dlopen(NULL, RTLD_LAZY | RTLD_LOCAL);
|
||||
#endif
|
||||
if (path) JS_FreeCString(ctx, path);
|
||||
if (!h) return JS_ThrowInternalError(ctx, "dlopen failed");
|
||||
|
||||
/* ------------- FIX: only real libraries get is_library = 1 ------------- */
|
||||
int is_library = (path != NULL); /* self handle must not be closed */
|
||||
return js_new_ffi_pointer(ctx, h, is_library);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* ffi.prepare (unchanged from previous answer) */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
static JSValue
|
||||
js_ffi_prepare(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
if (argc < 4)
|
||||
return JS_ThrowTypeError(ctx,
|
||||
"prepare: expected (lib, symbol, ret_type, arg_type_array)");
|
||||
|
||||
void *lib = js_get_ffi_pointer(ctx, argv[0]);
|
||||
if (!lib) return JS_ThrowTypeError(ctx, "invalid library handle");
|
||||
|
||||
const char *sym = JS_ToCString(ctx, argv[1]);
|
||||
if (!sym) return JS_EXCEPTION;
|
||||
|
||||
void *fn;
|
||||
#ifdef _WIN32
|
||||
fn = (void *)GetProcAddress((HMODULE)lib, sym);
|
||||
#else
|
||||
fn = dlsym(lib, sym);
|
||||
#endif
|
||||
if (!fn) {
|
||||
JS_FreeCString(ctx, sym);
|
||||
return JS_ThrowTypeError(ctx, "symbol \"%s\" not found", sym);
|
||||
}
|
||||
|
||||
const char *rt_name = JS_ToCString(ctx, argv[2]);
|
||||
if (!rt_name) { JS_FreeCString(ctx, sym); return JS_EXCEPTION; }
|
||||
ffi_type *ret_type = js_to_ffi_type(ctx, rt_name);
|
||||
JS_FreeCString(ctx, rt_name);
|
||||
if (!ret_type) { JS_FreeCString(ctx, sym); return JS_EXCEPTION; }
|
||||
|
||||
if (!JS_IsArray(ctx, argv[3])) {
|
||||
JS_FreeCString(ctx, sym);
|
||||
return JS_ThrowTypeError(ctx, "arg_types must be an array");
|
||||
}
|
||||
|
||||
uint32_t nargs = JS_ArrayLength(ctx, argv[3]);
|
||||
|
||||
ffi_func *f = calloc(1, sizeof *f);
|
||||
if (!f) { JS_FreeCString(ctx, sym); return JS_ThrowOutOfMemory(ctx); }
|
||||
|
||||
f->fn_ptr = fn;
|
||||
f->ret_type = ret_type;
|
||||
f->nargs = (int)nargs;
|
||||
|
||||
if (nargs) {
|
||||
f->arg_types = calloc(nargs, sizeof(ffi_type *));
|
||||
if (!f->arg_types) {
|
||||
JS_FreeCString(ctx, sym);
|
||||
ffi_func_free(f);
|
||||
return JS_ThrowOutOfMemory(ctx);
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < nargs; i++) {
|
||||
JSValue v = JS_GetPropertyUint32(ctx, argv[3], i);
|
||||
const char *tn = JS_ToCString(ctx, v);
|
||||
JS_FreeValue(ctx, v);
|
||||
if (!tn) { JS_FreeCString(ctx, sym); ffi_func_free(f); return JS_EXCEPTION; }
|
||||
|
||||
f->arg_types[i] = js_to_ffi_type(ctx, tn);
|
||||
JS_FreeCString(ctx, tn);
|
||||
if (!f->arg_types[i]) {
|
||||
JS_FreeCString(ctx, sym);
|
||||
ffi_func_free(f);
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JS_FreeCString(ctx, sym);
|
||||
|
||||
if (ffi_prep_cif(&f->cif, FFI_DEFAULT_ABI,
|
||||
f->nargs, f->ret_type, f->arg_types) != FFI_OK) {
|
||||
ffi_func_free(f);
|
||||
return JS_ThrowInternalError(ctx, "ffi_prep_cif failed");
|
||||
}
|
||||
|
||||
JSValue obj = JS_NewObjectClass(ctx, js_ffi_func_id);
|
||||
JS_SetOpaque(obj, f);
|
||||
return obj;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* box_result + js_ffi_call (unchanged) */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
static JSValue
|
||||
box_result(JSContext *ctx, ffi_type *t, void *data)
|
||||
{
|
||||
if (t == &ffi_type_void) return JS_NULL;
|
||||
if (t == &ffi_type_pointer) return data ? js_new_ffi_pointer(ctx, *(void **)data, 0)
|
||||
: JS_NULL;
|
||||
|
||||
if (t == &ffi_type_double) return JS_NewFloat64(ctx, *(double *)data);
|
||||
if (t == &ffi_type_float) return JS_NewFloat64(ctx, (double)*(float *)data);
|
||||
|
||||
if (t == &ffi_type_sint8) return JS_NewInt32(ctx, *(int8_t *)data);
|
||||
if (t == &ffi_type_uint8) return JS_NewUint32(ctx, *(uint8_t *)data);
|
||||
if (t == &ffi_type_sint16) return JS_NewInt32(ctx, *(int16_t *)data);
|
||||
if (t == &ffi_type_uint16) return JS_NewUint32(ctx, *(uint16_t *)data);
|
||||
if (t == &ffi_type_sint32) return JS_NewInt32(ctx, *(int32_t *)data);
|
||||
if (t == &ffi_type_uint32) return JS_NewUint32(ctx, *(uint32_t *)data);
|
||||
if (t == &ffi_type_sint64) return JS_NewFloat64(ctx, (double)*(int64_t *)data);
|
||||
if (t == &ffi_type_uint64) return JS_NewFloat64(ctx, (double)*(uint64_t *)data);
|
||||
|
||||
return JS_ThrowTypeError(ctx, "unsupported return type");
|
||||
}
|
||||
|
||||
static JSValue
|
||||
js_ffi_call(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
ffi_func *f = JS_GetOpaque2(ctx, this_val, js_ffi_func_id);
|
||||
if (!f) return JS_EXCEPTION;
|
||||
if (argc != f->nargs)
|
||||
return JS_ThrowTypeError(ctx, "expected %d arguments, got %d",
|
||||
f->nargs, argc);
|
||||
|
||||
/* one fixed stack block per argument ----------------------------------- */
|
||||
typedef union {
|
||||
double d;
|
||||
float f;
|
||||
int8_t i8; uint8_t u8;
|
||||
int16_t i16; uint16_t u16;
|
||||
int32_t i32; uint32_t u32;
|
||||
int64_t i64; uint64_t u64;
|
||||
void *p;
|
||||
} arg_data_t;
|
||||
|
||||
arg_data_t data[f->nargs];
|
||||
void *values[f->nargs];
|
||||
const char *tmp_cstr[f->nargs]; /* only for JS strings */
|
||||
memset(tmp_cstr, 0, sizeof tmp_cstr);
|
||||
|
||||
/* ---------- marshal JS → C (no malloc for scalars) ------------------- */
|
||||
for (int i = 0; i < f->nargs; i++) {
|
||||
ffi_type *t = f->arg_types[i];
|
||||
|
||||
/* numbers ------------------------------------------------------------ */
|
||||
if (t != &ffi_type_pointer) {
|
||||
double d;
|
||||
if (JS_ToFloat64(ctx, &d, argv[i]))
|
||||
goto arg_error;
|
||||
|
||||
if (t == &ffi_type_double) data[i].d = d;
|
||||
else if (t == &ffi_type_float) data[i].f = (float)d;
|
||||
else if (t == &ffi_type_sint8) data[i].i8 = (int8_t)d;
|
||||
else if (t == &ffi_type_uint8) data[i].u8 = (uint8_t)d;
|
||||
else if (t == &ffi_type_sint16) data[i].i16= (int16_t)d;
|
||||
else if (t == &ffi_type_uint16) data[i].u16= (uint16_t)d;
|
||||
else if (t == &ffi_type_sint32) data[i].i32= (int32_t)d;
|
||||
else if (t == &ffi_type_uint32) data[i].u32= (uint32_t)d;
|
||||
else if (t == &ffi_type_sint64) data[i].i64= (int64_t)d;
|
||||
else if (t == &ffi_type_uint64) data[i].u64= (uint64_t)d;
|
||||
else goto arg_error; /* should be unreachable */
|
||||
|
||||
values[i] = &data[i];
|
||||
continue;
|
||||
}
|
||||
|
||||
/* pointers ----------------------------------------------------------- */
|
||||
if (JS_IsString(argv[i])) {
|
||||
const char *s = JS_ToCString(ctx, argv[i]);
|
||||
if (!s) goto arg_error;
|
||||
tmp_cstr[i] = s; /* remember to free */
|
||||
data[i].p = (void *)s;
|
||||
} else {
|
||||
data[i].p = js_get_ffi_pointer(ctx, argv[i]);
|
||||
}
|
||||
values[i] = &data[i];
|
||||
}
|
||||
|
||||
/* ---------------------------- call ---------------------------------- */
|
||||
uint8_t ret_space[16] = {0};
|
||||
void *ret_buf = f->ret_type == &ffi_type_void ? NULL : (void *)ret_space;
|
||||
|
||||
ffi_call(&f->cif, FFI_FN(f->fn_ptr), ret_buf, values);
|
||||
JSValue js_ret = box_result(ctx, f->ret_type, ret_buf);
|
||||
|
||||
/* --------------------------- cleanup ---------------------------------- */
|
||||
for (int i = 0; i < f->nargs; i++)
|
||||
if (tmp_cstr[i]) JS_FreeCString(ctx, tmp_cstr[i]);
|
||||
|
||||
return js_ret;
|
||||
|
||||
arg_error:
|
||||
for (int i = 0; i < f->nargs; i++)
|
||||
if (tmp_cstr[i]) JS_FreeCString(ctx, tmp_cstr[i]);
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* module init */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
static const JSCFunctionListEntry js_ffi_funcs[] = {
|
||||
JS_CFUNC_DEF("dlopen", 1, js_ffi_dlopen),
|
||||
JS_CFUNC_DEF("prepare", 4, js_ffi_prepare),
|
||||
};
|
||||
|
||||
static const JSCFunctionListEntry js_ffi_func_funcs[] = {
|
||||
JS_CFUNC_DEF("call", 1, js_ffi_call),
|
||||
};
|
||||
|
||||
JSValue
|
||||
js_ffi_use(JSContext *ctx)
|
||||
{
|
||||
JS_NewClassID(&js_ffi_func_id);
|
||||
JS_NewClass(JS_GetRuntime(ctx), js_ffi_func_id, &js_ffi_func_class);
|
||||
|
||||
JSValue fn_proto = JS_NewObject(ctx);
|
||||
JS_SetPropertyFunctionList(ctx, fn_proto, js_ffi_func_funcs, countof(js_ffi_func_funcs));
|
||||
JS_SetClassProto(ctx, js_ffi_func_id, fn_proto);
|
||||
|
||||
JS_NewClassID(&js_ffi_pointer_id);
|
||||
JS_NewClass(JS_GetRuntime(ctx), js_ffi_pointer_id, &js_ffi_pointer_class);
|
||||
|
||||
JSValue mod = JS_NewObject(ctx);
|
||||
JS_SetPropertyFunctionList(ctx, mod, js_ffi_funcs, countof(js_ffi_funcs));
|
||||
return mod;
|
||||
}
|
||||
8
source/qjs_ffi.h
Normal file
8
source/qjs_ffi.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#ifndef QJS_FFI_H
|
||||
#define QJS_FFI_H
|
||||
|
||||
#include "cell.h"
|
||||
|
||||
JSValue js_ffi_use(JSContext *ctx);
|
||||
|
||||
#endif
|
||||
@@ -445,10 +445,10 @@ static BufferCheckResult get_or_extend_buffer(
|
||||
int copy,
|
||||
int index
|
||||
) {
|
||||
BufferCheckResult res = { JS_UNDEFINED, NULL, 0, 0 };
|
||||
if (!JS_IsUndefined(old_mesh)) {
|
||||
BufferCheckResult res = { JS_NULL, NULL, 0, 0 };
|
||||
if (!JS_IsNull(old_mesh)) {
|
||||
JSValue old_buf = JS_GetPropertyStr(js, old_mesh, prop);
|
||||
if (!JS_IsUndefined(old_buf)) {
|
||||
if (!JS_IsNull(old_buf)) {
|
||||
size_t old_size;
|
||||
void *data = get_gpu_buffer(js, old_buf, NULL, &old_size);
|
||||
if (data && old_size >= needed_size) {
|
||||
@@ -520,7 +520,7 @@ JSC_CCALL(gpu_make_sprite_mesh,
|
||||
}
|
||||
|
||||
// Check old mesh
|
||||
JSValue old_mesh = JS_UNDEFINED;
|
||||
JSValue old_mesh = JS_NULL;
|
||||
if (argc > 1)
|
||||
old_mesh = argv[1];
|
||||
|
||||
@@ -529,9 +529,9 @@ JSC_CCALL(gpu_make_sprite_mesh,
|
||||
size_t uv_size = sizeof(*uvdata)*verts;
|
||||
size_t color_size = sizeof(*colordata)*verts;
|
||||
|
||||
BufferCheckResult pos_chk = get_or_extend_buffer(js, old_mesh, "pos", pos_size, JS_TYPED_ARRAY_FLOAT32, 2, 1, 0);
|
||||
BufferCheckResult uv_chk = get_or_extend_buffer(js, old_mesh, "uv", uv_size, JS_TYPED_ARRAY_FLOAT32, 2, 1, 0);
|
||||
BufferCheckResult color_chk = get_or_extend_buffer(js, old_mesh, "color", color_size, JS_TYPED_ARRAY_FLOAT32, 4, 1, 0);
|
||||
BufferCheckResult pos_chk = get_or_extend_buffer(js, old_mesh, "pos", pos_size, 0, 2, 1, 0);
|
||||
BufferCheckResult uv_chk = get_or_extend_buffer(js, old_mesh, "uv", uv_size, 0, 2, 1, 0);
|
||||
BufferCheckResult color_chk = get_or_extend_buffer(js, old_mesh, "color", color_size, 0, 4, 1, 0);
|
||||
|
||||
int need_new_all = pos_chk.need_new || uv_chk.need_new || color_chk.need_new;
|
||||
|
||||
@@ -539,9 +539,9 @@ JSC_CCALL(gpu_make_sprite_mesh,
|
||||
|
||||
if (need_new_all) {
|
||||
// Create all new buffers
|
||||
JSValue new_pos = make_gpu_buffer(js, posdata, pos_size, JS_TYPED_ARRAY_FLOAT32, 2, 1,0);
|
||||
JSValue new_uv = make_gpu_buffer(js, uvdata, uv_size, JS_TYPED_ARRAY_FLOAT32, 2, 1,0);
|
||||
JSValue new_color = make_gpu_buffer(js, colordata, color_size, JS_TYPED_ARRAY_FLOAT32, 0, 1,0);
|
||||
JSValue new_pos = make_gpu_buffer(js, posdata, pos_size, 0, 2, 1,0);
|
||||
JSValue new_uv = make_gpu_buffer(js, uvdata, uv_size, 0, 2, 1,0);
|
||||
JSValue new_color = make_gpu_buffer(js, colordata, color_size, 0, 0, 1,0);
|
||||
|
||||
JS_SetPropertyStr(js, ret, "pos", new_pos);
|
||||
JS_SetPropertyStr(js, ret, "uv", new_uv);
|
||||
@@ -577,9 +577,9 @@ JSC_CCALL(gpu_make_sprite_mesh,
|
||||
free(colordata);
|
||||
|
||||
// Free old buffer values if they were fetched
|
||||
if (!JS_IsUndefined(pos_chk.val)) JS_FreeValue(js, pos_chk.val);
|
||||
if (!JS_IsUndefined(uv_chk.val)) JS_FreeValue(js, uv_chk.val);
|
||||
if (!JS_IsUndefined(color_chk.val)) JS_FreeValue(js, color_chk.val);
|
||||
if (!JS_IsNull(pos_chk.val)) JS_FreeValue(js, pos_chk.val);
|
||||
if (!JS_IsNull(uv_chk.val)) JS_FreeValue(js, uv_chk.val);
|
||||
if (!JS_IsNull(color_chk.val)) JS_FreeValue(js, color_chk.val);
|
||||
|
||||
return ret;
|
||||
)
|
||||
@@ -603,9 +603,9 @@ struct quad_buffers quad_buffers_new(int verts)
|
||||
|
||||
JSValue quadbuffers_to_mesh(JSContext *js, struct quad_buffers buffers)
|
||||
{
|
||||
JSValue jspos = make_gpu_buffer(js, buffers.pos, sizeof(HMM_Vec2)*buffers.verts, JS_TYPED_ARRAY_FLOAT32, 2, 0, 0);
|
||||
JSValue jsuv = make_gpu_buffer(js, buffers.uv, sizeof(HMM_Vec2)*buffers.verts, JS_TYPED_ARRAY_FLOAT32, 2,0,0);
|
||||
JSValue jscolor = make_gpu_buffer(js, buffers.color, sizeof(HMM_Vec4)*buffers.verts, JS_TYPED_ARRAY_FLOAT32, 4,0,0);
|
||||
JSValue jspos = make_gpu_buffer(js, buffers.pos, sizeof(HMM_Vec2)*buffers.verts, 0, 2, 0, 0);
|
||||
JSValue jsuv = make_gpu_buffer(js, buffers.uv, sizeof(HMM_Vec2)*buffers.verts, 0, 2,0,0);
|
||||
JSValue jscolor = make_gpu_buffer(js, buffers.color, sizeof(HMM_Vec4)*buffers.verts, 0, 4,0,0);
|
||||
|
||||
size_t quads = buffers.verts/4;
|
||||
size_t count = buffers.verts/2*3;
|
||||
@@ -685,11 +685,11 @@ JSC_CCALL(gpu_make_sprite_queue,
|
||||
|
||||
rect uv;
|
||||
rect uv_px;
|
||||
JSValue cur_img = JS_UNDEFINED;
|
||||
JSValue cur_img = JS_NULL;
|
||||
|
||||
for (size_t i = 0; i < quads; i++) {
|
||||
sprite *s = &sprites[i];
|
||||
if (JS_IsUndefined(cur_img) || !JS_StrictEq(js, s->image, cur_img)) {
|
||||
if (JS_IsNull(cur_img) || !JS_StrictEq(js, s->image, cur_img)) {
|
||||
cur_img = s->image;
|
||||
JS_GETATOM(js, uv, cur_img, rect, rect)
|
||||
JS_GETATOM(js, uv_px, cur_img, rect_px, rect)
|
||||
@@ -732,7 +732,7 @@ JSC_CCALL(gpu_make_sprite_queue,
|
||||
int first_index = 0;
|
||||
int count = 0;
|
||||
int n = 0;
|
||||
JSValue img = JS_UNDEFINED;
|
||||
JSValue img = JS_NULL;
|
||||
|
||||
for (int i = 0; i < quads; i++) {
|
||||
if (!JS_SameValue(js, sprites[i].image, img)) {
|
||||
@@ -832,7 +832,7 @@ JSC_CCALL(geometry_tilemap_to_data,
|
||||
int col_len = JS_ArrayLength(js, col);
|
||||
for (int y = 0; y < col_len; y++) {
|
||||
JSValue tile = JS_GetPropertyUint32(js, col, y);
|
||||
if (!JS_IsUndefined(tile) && !JS_IsNull(tile)) {
|
||||
if (!JS_IsNull(tile) && !JS_IsNull(tile)) {
|
||||
tile_count++;
|
||||
}
|
||||
JS_FreeValue(js, tile);
|
||||
@@ -865,7 +865,7 @@ JSC_CCALL(geometry_tilemap_to_data,
|
||||
int col_len = JS_ArrayLength(js, col);
|
||||
for (int y = 0; y < col_len; y++) {
|
||||
JSValue tile = JS_GetPropertyUint32(js, col, y);
|
||||
if (!JS_IsUndefined(tile) && !JS_IsNull(tile)) {
|
||||
if (!JS_IsNull(tile) && !JS_IsNull(tile)) {
|
||||
// Calculate world position
|
||||
float world_x = (x + offset_x) * size_x;
|
||||
float world_y = (y + offset_y) * size_y;
|
||||
@@ -895,7 +895,7 @@ JSC_CCALL(geometry_tilemap_to_data,
|
||||
SDL_FColor default_color = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||
if (JS_IsObject(tile)) {
|
||||
JSValue color_val = JS_GetPropertyStr(js, tile, "color");
|
||||
if (!JS_IsUndefined(color_val)) {
|
||||
if (!JS_IsNull(color_val)) {
|
||||
HMM_Vec4 color = js2color(js, color_val);
|
||||
default_color.r = color.r;
|
||||
default_color.g = color.g;
|
||||
|
||||
@@ -106,38 +106,38 @@ JSC_CCALL(imgui_window,
|
||||
const char *str = JS_ToCString(js,argv[0]);
|
||||
bool active = true;
|
||||
ImGui::Begin(str, &active);
|
||||
JS_Call(js, argv[1], JS_UNDEFINED, 0, NULL);
|
||||
JS_Call(js, argv[1], JS_NULL, 0, NULL);
|
||||
ImGui::End();
|
||||
JS_FreeCString(js,str);
|
||||
return JS_NewBool(js,active);
|
||||
)
|
||||
JSC_SCALL(imgui_menu,
|
||||
if (ImGui::BeginMenu(str)) {
|
||||
JS_Call(js, argv[1], JS_UNDEFINED, 0, NULL);
|
||||
JS_Call(js, argv[1], JS_NULL, 0, NULL);
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
)
|
||||
|
||||
JSC_CCALL(imgui_menubar,
|
||||
if (ImGui::BeginMenuBar()) {
|
||||
JS_Call(js, argv[0], JS_UNDEFINED, 0, NULL);
|
||||
JS_Call(js, argv[0], JS_NULL, 0, NULL);
|
||||
ImGui::EndMenuBar();
|
||||
}
|
||||
)
|
||||
|
||||
JSC_CCALL(imgui_mainmenubar,
|
||||
if (ImGui::BeginMainMenuBar()) {
|
||||
JS_Call(js, argv[0], JS_UNDEFINED, 0, NULL);
|
||||
JS_Call(js, argv[0], JS_NULL, 0, NULL);
|
||||
ImGui::EndMainMenuBar();
|
||||
}
|
||||
)
|
||||
|
||||
JSC_CCALL(imgui_menuitem,
|
||||
const char *name = JS_ToCString(js,argv[0]);
|
||||
const char *keyfn = JS_IsUndefined(argv[1]) ? NULL : JS_ToCString(js,argv[1]);
|
||||
bool on = JS_IsUndefined(argv[3]) ? false : JS_ToBool(js,argv[3]);
|
||||
const char *keyfn = JS_IsNull(argv[1]) ? NULL : JS_ToCString(js,argv[1]);
|
||||
bool on = JS_IsNull(argv[3]) ? false : JS_ToBool(js,argv[3]);
|
||||
if (ImGui::MenuItem(JS_ToBool(js,argv[0]) ? name : "##empty" ,keyfn, &on))
|
||||
JS_Call(js, argv[2], JS_UNDEFINED, 0, NULL);
|
||||
JS_Call(js, argv[2], JS_NULL, 0, NULL);
|
||||
|
||||
if (!JS_IsNull(argv[0])) JS_FreeCString(js,name);
|
||||
if (keyfn) JS_FreeCString(js,keyfn);
|
||||
@@ -147,7 +147,7 @@ JSC_CCALL(imgui_menuitem,
|
||||
|
||||
JSC_SCALL(imgui_plot,
|
||||
if (ImPlot::BeginPlot(str)) {
|
||||
JS_Call(js, argv[1], JS_UNDEFINED, 0, NULL);
|
||||
JS_Call(js, argv[1], JS_NULL, 0, NULL);
|
||||
ImPlot::EndPlot();
|
||||
}
|
||||
)
|
||||
@@ -173,7 +173,7 @@ void fill_plotdata(JSContext *js, JSValue v, JSValue last)
|
||||
else {
|
||||
// Fill it with the x axis being the array index
|
||||
for (int i = 0; i < JS_ArrayLength(js, v); i++) {
|
||||
if (JS_IsUndefined(js_getpropidx(v,i))) continue;
|
||||
if (JS_IsNull(js_getpropidx(v,i))) continue;
|
||||
ImVec2 c;
|
||||
c.x = i;
|
||||
c.y = js2number(js, js_getpropidx(v,i));
|
||||
@@ -181,7 +181,7 @@ void fill_plotdata(JSContext *js, JSValue v, JSValue last)
|
||||
}
|
||||
}
|
||||
|
||||
if (!JS_IsUndefined(last)) {
|
||||
if (!JS_IsNull(last)) {
|
||||
int frame = js2number(js, last);
|
||||
ImVec2 c = js2vec2(js,last);
|
||||
c.y = arrlast(plotdata).y;
|
||||
@@ -195,7 +195,7 @@ PLOT_FN(stairplot, PlotStairs,,ImPlotStairsFlags_Shaded)
|
||||
PLOT_FN(digitalplot, PlotDigital,,0)
|
||||
|
||||
JSC_SCALL(imgui_barplot,
|
||||
fill_plotdata(js, argv[1], JS_UNDEFINED);
|
||||
fill_plotdata(js, argv[1], JS_NULL);
|
||||
ImPlot::PlotBars(str, &plotdata[0].x, &plotdata[0].y, JS_ArrayLength(js, argv[1]), js2number(js, argv[2]), 0, 0, sizeof(ImVec2));
|
||||
)
|
||||
|
||||
@@ -243,7 +243,7 @@ JSC_CCALL(imgui_fitaxis,
|
||||
|
||||
JSC_SSCALL(imgui_textinput,
|
||||
char buffer[512];
|
||||
if (JS_IsUndefined(argv[1]))
|
||||
if (JS_IsNull(argv[1]))
|
||||
buffer[0] = 0;
|
||||
else
|
||||
strncpy(buffer, str2, sizeof(buffer)-1);
|
||||
@@ -257,7 +257,7 @@ JSC_SSCALL(imgui_textinput,
|
||||
|
||||
JSC_SSCALL(imgui_textbox,
|
||||
char buffer[512];
|
||||
if (JS_IsUndefined(argv[1]))
|
||||
if (JS_IsNull(argv[1]))
|
||||
buffer[0] = 0;
|
||||
else
|
||||
strncpy(buffer, str2, sizeof(buffer)-1);
|
||||
@@ -273,12 +273,12 @@ JSC_SCALL(imgui_text, ImGui::Text("%s", str) )
|
||||
|
||||
JSC_SCALL(imgui_button,
|
||||
if (ImGui::Button(str))
|
||||
JS_Call(js, argv[1], JS_UNDEFINED, 0, NULL);
|
||||
JS_Call(js, argv[1], JS_NULL, 0, NULL);
|
||||
)
|
||||
|
||||
JSC_SCALL(imgui_slider,
|
||||
/* float low = JS_IsUndefined(argv[2]) ? 0.0 : js2number(js, argv[2]);
|
||||
float high = JS_IsUndefined(argv[3]) ? 1.0 : js2number(js, argv[3]);
|
||||
/* float low = JS_IsNull(argv[2]) ? 0.0 : js2number(js, argv[2]);
|
||||
float high = JS_IsNull(argv[3]) ? 1.0 : js2number(js, argv[3]);
|
||||
|
||||
if (JS_IsArray(js, argv[1])) {
|
||||
int n = JS_ArrayLength(js, argv[1]);
|
||||
@@ -306,8 +306,8 @@ JSC_SCALL(imgui_slider,
|
||||
)
|
||||
|
||||
JSC_SCALL(imgui_intslider,
|
||||
int low = JS_IsUndefined(argv[2]) ? 0.0 : js2number(js, argv[2]);
|
||||
int high = JS_IsUndefined(argv[3]) ? 1.0 : js2number(js, argv[3]);
|
||||
int low = JS_IsNull(argv[2]) ? 0.0 : js2number(js, argv[2]);
|
||||
int high = JS_IsNull(argv[3]) ? 1.0 : js2number(js, argv[3]);
|
||||
|
||||
JSValue arr = JS_NewTypedArray(js, 1, &argv[1], JS_TYPED_ARRAY_INT32);
|
||||
size_t len;
|
||||
@@ -353,7 +353,7 @@ JSC_CCALL(imgui_image,
|
||||
JSC_SCALL(imgui_imagebutton,
|
||||
SDL_GPUTexture *tex = js2SDL_GPUTexture(js,argv[1]);
|
||||
if (ImGui::ImageButton(str, (ImTextureID)tex, ImVec2(100, 100)))
|
||||
JS_Call(js, argv[2], JS_UNDEFINED, 0, NULL);
|
||||
JS_Call(js, argv[2], JS_NULL, 0, NULL);
|
||||
)
|
||||
|
||||
JSC_CCALL(imgui_sameline, ImGui::SameLine(js2number(js, argv[0])) )
|
||||
@@ -364,21 +364,21 @@ JSC_SCALL(imgui_radio, ret = JS_NewBool(js,ImGui::RadioButton(str, JS_ToBool(js,
|
||||
|
||||
JSC_SCALL(imgui_tree,
|
||||
if (ImGui::TreeNode(str)) {
|
||||
JS_Call(js, argv[1],JS_UNDEFINED, 0,NULL);
|
||||
JS_Call(js, argv[1],JS_NULL, 0,NULL);
|
||||
ImGui::TreePop();
|
||||
}
|
||||
)
|
||||
|
||||
JSC_SCALL(imgui_tabbar,
|
||||
if (ImGui::BeginTabBar(str)) {
|
||||
JS_Call(js, argv[1],JS_UNDEFINED, 0,NULL);
|
||||
JS_Call(js, argv[1],JS_NULL, 0,NULL);
|
||||
ImGui::EndTabBar();
|
||||
}
|
||||
)
|
||||
|
||||
JSC_SCALL(imgui_tab,
|
||||
if (ImGui::BeginTabItem(str)) {
|
||||
JS_Call(js, argv[1],JS_UNDEFINED, 0,NULL);
|
||||
JS_Call(js, argv[1],JS_NULL, 0,NULL);
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
)
|
||||
@@ -407,7 +407,7 @@ JSC_SCALL(imgui_open_popup,
|
||||
|
||||
JSC_SCALL(imgui_popup,
|
||||
if (ImGui::BeginPopup(str)) {
|
||||
JS_Call(js, argv[1],JS_UNDEFINED, 0,NULL);
|
||||
JS_Call(js, argv[1],JS_NULL, 0,NULL);
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
)
|
||||
@@ -418,14 +418,14 @@ JSC_CCALL(imgui_close_popup,
|
||||
|
||||
JSC_SCALL(imgui_modal,
|
||||
if (ImGui::BeginPopupModal(str)) {
|
||||
JS_Call(js, argv[1],JS_UNDEFINED, 0,NULL);
|
||||
JS_Call(js, argv[1],JS_NULL, 0,NULL);
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
)
|
||||
|
||||
JSC_SCALL(imgui_context,
|
||||
if (ImGui::BeginPopupContextItem(str)) {
|
||||
JS_Call(js, argv[1],JS_UNDEFINED, 0,NULL);
|
||||
JS_Call(js, argv[1],JS_NULL, 0,NULL);
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
)
|
||||
@@ -433,11 +433,11 @@ JSC_SCALL(imgui_context,
|
||||
JSC_SCALL(imgui_table,
|
||||
int flags = ImGuiTableFlags_Resizable | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_SizingStretchProp;
|
||||
bool sort = false;
|
||||
if (!JS_IsUndefined(argv[3])) sort = true;
|
||||
if (!JS_IsNull(argv[3])) sort = true;
|
||||
|
||||
if (sort) flags |= ImGuiTableFlags_Sortable;
|
||||
if (ImGui::BeginTable(str, js2number(js, argv[1]), flags)) {
|
||||
JS_Call(js, argv[2], JS_UNDEFINED, 0, NULL);
|
||||
JS_Call(js, argv[2], JS_NULL, 0, NULL);
|
||||
|
||||
if (sort) {
|
||||
ImGuiTableSortSpecs* sort_specs = ImGui::TableGetSortSpecs();
|
||||
@@ -448,7 +448,7 @@ JSC_SCALL(imgui_table,
|
||||
JSValue send[2];
|
||||
send[0] = JS_NewInt32(js,spec->ColumnIndex);
|
||||
send[1] = JS_NewBool(js,spec->SortDirection == ImGuiSortDirection_Ascending);
|
||||
JS_Call(js, argv[3], JS_UNDEFINED, 2, send);
|
||||
JS_Call(js, argv[3], JS_NULL, 2, send);
|
||||
JS_FreeValue(js, send[0]);
|
||||
JS_FreeValue(js, send[1]);
|
||||
}
|
||||
@@ -470,7 +470,7 @@ JSC_SCALL(imgui_dnd,
|
||||
if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None)) {
|
||||
double n = js2number(js, argv[1]);
|
||||
ImGui::SetDragDropPayload(str, &n, sizeof(n));
|
||||
// JS_Call(js, argv[2], JS_UNDEFINED, 2, send);
|
||||
// JS_Call(js, argv[2], JS_NULL, 2, send);
|
||||
ImGui::EndDragDropSource();
|
||||
}
|
||||
)
|
||||
@@ -479,7 +479,7 @@ JSC_SCALL(imgui_dndtarget,
|
||||
if (ImGui::BeginDragDropTarget()) {
|
||||
if (const ImGuiPayload *payload = ImGui::AcceptDragDropPayload(str)) {
|
||||
JSValue n = JS_NewFloat64(js,*(double*)payload->Data);
|
||||
JS_Call(js, argv[1], JS_UNDEFINED, 1, &n);
|
||||
JS_Call(js, argv[1], JS_NULL, 1, &n);
|
||||
}
|
||||
ImGui::EndDragDropTarget();
|
||||
}
|
||||
@@ -500,7 +500,7 @@ JSC_SCALL(imgui_color,
|
||||
|
||||
JSC_CCALL(imgui_startnode,
|
||||
ImNodes::BeginNodeEditor();
|
||||
JS_Call(js, argv[0], JS_UNDEFINED, 0,NULL);
|
||||
JS_Call(js, argv[0], JS_NULL, 0,NULL);
|
||||
ImNodes::EndNodeEditor();
|
||||
int start_attr;
|
||||
int end_attr;
|
||||
@@ -509,7 +509,7 @@ JSC_CCALL(imgui_startnode,
|
||||
JSValue ab[2];
|
||||
ab[0] = JS_NewInt32(js,start_attr);
|
||||
ab[1] = JS_NewInt32(js,end_attr);
|
||||
JS_Call(js,argv[1], JS_UNDEFINED, 2, ab);
|
||||
JS_Call(js,argv[1], JS_NULL, 2, ab);
|
||||
|
||||
for (int i = 0; i < 2; i++) JS_FreeValue(js, ab[i]);
|
||||
}
|
||||
@@ -518,7 +518,7 @@ JSC_CCALL(imgui_startnode,
|
||||
if (ImNodes::IsNodeHovered(&node_id))
|
||||
{
|
||||
JSValue a = JS_NewInt32(js,node_id);
|
||||
JS_Call(js, argv[2], JS_UNDEFINED, 1,&a);
|
||||
JS_Call(js, argv[2], JS_NULL, 1,&a);
|
||||
JS_FreeValue(js,a);
|
||||
}
|
||||
|
||||
@@ -526,26 +526,26 @@ JSC_CCALL(imgui_startnode,
|
||||
if (ImNodes::IsLinkHovered(&link_id))
|
||||
{
|
||||
JSValue a = JS_NewInt32(js,link_id);
|
||||
JS_Call(js, argv[3], JS_UNDEFINED, 1,&a);
|
||||
JS_Call(js, argv[3], JS_NULL, 1,&a);
|
||||
JS_FreeValue(js,a);
|
||||
}
|
||||
)
|
||||
|
||||
JSC_CCALL(imgui_node,
|
||||
ImNodes::BeginNode(js2number(js, argv[0]));
|
||||
JS_Call(js, argv[1], JS_UNDEFINED, 0,NULL);
|
||||
JS_Call(js, argv[1], JS_NULL, 0,NULL);
|
||||
ImNodes::EndNode();
|
||||
)
|
||||
|
||||
JSC_CCALL(imgui_nodein,
|
||||
ImNodes::BeginInputAttribute(js2number(js, argv[0]));
|
||||
JS_Call(js, argv[1], JS_UNDEFINED, 0,NULL);
|
||||
JS_Call(js, argv[1], JS_NULL, 0,NULL);
|
||||
ImNodes::EndInputAttribute();
|
||||
)
|
||||
|
||||
JSC_CCALL(imgui_nodeout,
|
||||
ImNodes::BeginOutputAttribute(js2number(js, argv[0]));
|
||||
JS_Call(js, argv[1], JS_UNDEFINED, 0,NULL);
|
||||
JS_Call(js, argv[1], JS_NULL, 0,NULL);
|
||||
ImNodes::EndOutputAttribute();
|
||||
)
|
||||
|
||||
@@ -681,7 +681,7 @@ static JSValue axis_fmts[10];
|
||||
void jsformatter(double value, char *buff, int size, JSValue *fmt)
|
||||
{
|
||||
/* JSValue v = JS_NewFloat64(js,value);
|
||||
const char *str = JS_ToCString(js, JS_Call(js,*fmt, JS_UNDEFINED, 1, &v));
|
||||
const char *str = JS_ToCString(js, JS_Call(js,*fmt, JS_NULL, 1, &v));
|
||||
strncpy(buff,str, size);
|
||||
JS_FreeCString(js, str);*/
|
||||
}
|
||||
@@ -689,9 +689,9 @@ void jsformatter(double value, char *buff, int size, JSValue *fmt)
|
||||
JSC_CCALL(imgui_axisfmt,
|
||||
int y = num_to_yaxis(js2number(js, argv[0]));
|
||||
|
||||
if (!JS_IsUndefined(axis_fmts[y])) {
|
||||
if (!JS_IsNull(axis_fmts[y])) {
|
||||
JS_FreeValue(js, axis_fmts[y]);
|
||||
axis_fmts[y] = JS_UNDEFINED;
|
||||
axis_fmts[y] = JS_NULL;
|
||||
}
|
||||
|
||||
axis_fmts[y] = JS_DupValue(js,argv[1]);
|
||||
|
||||
@@ -159,14 +159,14 @@ JSC_SCALL(io_slurpwrite,
|
||||
JSC_CCALL(io_mount,
|
||||
const char *src = JS_ToCString(js, argv[0]);
|
||||
const char *mountpoint;
|
||||
if (JS_IsUndefined(argv[1]))
|
||||
if (JS_IsNull(argv[1]))
|
||||
mountpoint = NULL;
|
||||
else
|
||||
mountpoint = JS_ToCString(js, argv[1]);
|
||||
|
||||
int prepend = 0;
|
||||
|
||||
if (argc > 2 && !JS_IsUndefined(argv[2]))
|
||||
if (argc > 2 && !JS_IsNull(argv[2]))
|
||||
prepend = JS_ToBool(js, argv[2]);
|
||||
|
||||
if (!PHYSFS_mount(src, mountpoint, prepend))
|
||||
@@ -274,7 +274,7 @@ JSC_CCALL(io_globfs,
|
||||
data.globs = globs;
|
||||
|
||||
const char *path = NULL;
|
||||
if (!JS_IsUndefined(argv[1])) path = JS_ToCString(js,argv[1]);
|
||||
if (!JS_IsNull(argv[1])) path = JS_ToCString(js,argv[1]);
|
||||
PHYSFS_enumerate(path, globfs_cb, &data);
|
||||
|
||||
for (int i = 0; i < globs_len; i++)
|
||||
@@ -297,7 +297,7 @@ JSC_SCALL(io_enumerate,
|
||||
data.globs = NULL; /* not used here */
|
||||
data.recurse = 0;
|
||||
|
||||
if (!JS_IsUndefined(argv[1])) /* parse second arg if provided */
|
||||
if (!JS_IsNull(argv[1])) /* parse second arg if provided */
|
||||
data.recurse = JS_ToBool(js, argv[1]);
|
||||
|
||||
/* Enumerate the directory given by 'str'. */
|
||||
@@ -322,7 +322,7 @@ JSC_SCALL(io_open,
|
||||
JSC_SCALL(io_realdir,
|
||||
const char *real = PHYSFS_getRealDir(str);
|
||||
if (!real)
|
||||
ret = JS_UNDEFINED;
|
||||
ret = JS_NULL;
|
||||
else
|
||||
ret = JS_NewString(js,real);
|
||||
)
|
||||
|
||||
@@ -39,11 +39,11 @@ JSC_CCALL(os_calc_mem,
|
||||
)
|
||||
|
||||
JSC_SSCALL(os_eval,
|
||||
ret = JS_Eval(js,str2,strlen(str2),str, JS_EVAL_FLAG_STRICT);
|
||||
ret = JS_Eval(js,str2,strlen(str2),str, 0);
|
||||
)
|
||||
|
||||
JSC_SSCALL(js_compile,
|
||||
ret = JS_Eval(js, str2, strlen(str2), str, JS_EVAL_FLAG_STRICT | JS_EVAL_FLAG_COMPILE_ONLY);
|
||||
ret = JS_Eval(js, str2, strlen(str2), str, JS_EVAL_FLAG_COMPILE_ONLY);
|
||||
)
|
||||
|
||||
JSC_CCALL(js_eval_compile,
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
|
||||
#define JS_SETSIG JSContext *js, JSValue self, JSValue val
|
||||
#define JSC_CCALL(NAME, ...) static JSValue js_##NAME (JSContext *js, JSValue self, int argc, JSValue *argv) { \
|
||||
JSValue ret = JS_UNDEFINED; \
|
||||
JSValue ret = JS_NULL; \
|
||||
__VA_ARGS__ ;\
|
||||
return ret; \
|
||||
}
|
||||
|
||||
#define JSC_CCALL_EXTERN(NAME, ...) JSValue js_##NAME (JSContext *js, JSValue self, int argc, JSValue *argv) { \
|
||||
JSValue ret = JS_UNDEFINED; \
|
||||
JSValue ret = JS_NULL; \
|
||||
__VA_ARGS__ ;\
|
||||
return ret; \
|
||||
}
|
||||
@@ -25,8 +25,8 @@
|
||||
#define JSC_SSCALL(NAME, ...) JSC_CCALL(NAME, \
|
||||
const char *str = NULL; \
|
||||
const char *str2 = NULL; \
|
||||
if (!JS_IsUndefined(argv[0])) str = JS_ToCString(js,argv[0]); \
|
||||
if (!JS_IsUndefined(argv[1])) str2 = JS_ToCString(js,argv[1]); \
|
||||
if (!JS_IsNull(argv[0])) str = JS_ToCString(js,argv[0]); \
|
||||
if (!JS_IsNull(argv[1])) str2 = JS_ToCString(js,argv[1]); \
|
||||
__VA_ARGS__ ; \
|
||||
JS_FreeCString(js,str2); \
|
||||
JS_FreeCString(js,str); \
|
||||
@@ -41,21 +41,21 @@
|
||||
#define CGETSET_ADD(ID, ENTRY) MIST_CGETSET_DEF(#ENTRY, js_##ID##_get_##ENTRY, js_##ID##_set_##ENTRY)
|
||||
#define CGETSET_ADD_HID(ID, ENTRY) MIST_CGETSET_BASE(#ENTRY, js_##ID##_get_##ENTRY, js_##ID##_set_##ENTRY, JS_PROP_CONFIGURABLE)
|
||||
|
||||
#define JSC_DCALL(FN) JSValue js_##FN (JSContext *js, JSValue self, int argc, JSValue *argv) { FN(); return JS_UNDEFINED; }
|
||||
#define JSC_DCALL(FN) JSValue js_##FN (JSContext *js, JSValue self, int argc, JSValue *argv) { FN(); return JS_NULL; }
|
||||
|
||||
#define JSC_1CALL(FN) JSValue js_##FN (JSContext *js, JSValue self, int argc, JSValue *argv) { FN(js2number(js,argv[0])); return JS_UNDEFINED; }
|
||||
#define JSC_2CALL(FN) JSValue js_##FN (JSContext *js, JSValue self, int argc, JSValue *argv) { FN(js2number(js,argv[0]), js2number(js,argv[1])); return JS_UNDEFINED; }
|
||||
#define JSC_3CALL(FN) JSValue js_##FN (JSContext *js, JSValue self, int argc, JSValue *argv) { FN(js2number(js,argv[0]), js2number(js,argv[1]), js2number(js,argv[2])); return JS_UNDEFINED; }
|
||||
#define JSC_4CALL(FN) JSValue js_##FN (JSContext *js, JSValue self, int argc, JSValue *argv) { FN(js2number(js,argv[0]), js2number(js,argv[1]), js2number(js,argv[2]), js2number(js,argv[3])); return JS_UNDEFINED; }
|
||||
#define JSC_5CALL(FN) JSValue js_##FN (JSContext *js, JSValue self, int argc, JSValue *argv) { FN(js2number(js,argv[0]), js2number(js,argv[1]), js2number(js,argv[2]), js2number(js,argv[3]), js2number(js,argv[4])); return JS_UNDEFINED; }
|
||||
#define JSC_6CALL(FN) JSValue js_##FN (JSContext *js, JSValue self, int argc, JSValue *argv) { FN(js2number(js,argv[0]), js2number(js,argv[1]), js2number(js,argv[2]), js2number(js,argv[3]), js2number(js,argv[4]), js2number(js,argv[5])); return JS_UNDEFINED; }
|
||||
#define JSC_7CALL(FN) JSValue js_##FN (JSContext *js, JSValue self, int argc, JSValue *argv) { FN(js2number(js,argv[0]), js2number(js,argv[1]), js2number(js,argv[2]), js2number(js,argv[3]), js2number(js,argv[4]), js2number(js,argv[5]), js2number(js,argv[6])); return JS_UNDEFINED; }
|
||||
#define JSC_1CALL(FN) JSValue js_##FN (JSContext *js, JSValue self, int argc, JSValue *argv) { FN(js2number(js,argv[0])); return JS_NULL; }
|
||||
#define JSC_2CALL(FN) JSValue js_##FN (JSContext *js, JSValue self, int argc, JSValue *argv) { FN(js2number(js,argv[0]), js2number(js,argv[1])); return JS_NULL; }
|
||||
#define JSC_3CALL(FN) JSValue js_##FN (JSContext *js, JSValue self, int argc, JSValue *argv) { FN(js2number(js,argv[0]), js2number(js,argv[1]), js2number(js,argv[2])); return JS_NULL; }
|
||||
#define JSC_4CALL(FN) JSValue js_##FN (JSContext *js, JSValue self, int argc, JSValue *argv) { FN(js2number(js,argv[0]), js2number(js,argv[1]), js2number(js,argv[2]), js2number(js,argv[3])); return JS_NULL; }
|
||||
#define JSC_5CALL(FN) JSValue js_##FN (JSContext *js, JSValue self, int argc, JSValue *argv) { FN(js2number(js,argv[0]), js2number(js,argv[1]), js2number(js,argv[2]), js2number(js,argv[3]), js2number(js,argv[4])); return JS_NULL; }
|
||||
#define JSC_6CALL(FN) JSValue js_##FN (JSContext *js, JSValue self, int argc, JSValue *argv) { FN(js2number(js,argv[0]), js2number(js,argv[1]), js2number(js,argv[2]), js2number(js,argv[3]), js2number(js,argv[4]), js2number(js,argv[5])); return JS_NULL; }
|
||||
#define JSC_7CALL(FN) JSValue js_##FN (JSContext *js, JSValue self, int argc, JSValue *argv) { FN(js2number(js,argv[0]), js2number(js,argv[1]), js2number(js,argv[2]), js2number(js,argv[3]), js2number(js,argv[4]), js2number(js,argv[5]), js2number(js,argv[6])); return JS_NULL; }
|
||||
|
||||
#define GETSETPAIR(ID, ENTRY, TYPE, FN) \
|
||||
JSValue js_##ID##_set_##ENTRY (JS_SETSIG) { \
|
||||
js2##ID (js, self)->ENTRY = js2##TYPE (js,val); \
|
||||
{FN;} \
|
||||
return JS_UNDEFINED; \
|
||||
return JS_NULL; \
|
||||
} \
|
||||
\
|
||||
JSValue js_##ID##_get_##ENTRY (JSContext *js, JSValue self) { \
|
||||
@@ -67,9 +67,9 @@ JSValue js_##ID##_get_##ENTRY (JSContext *js, JSValue self) { \
|
||||
#define JSC_GETSET_CALLBACK(ID, ENTRY) \
|
||||
JSValue js_##ID##_set_##ENTRY (JS_SETSIG) { \
|
||||
JSValue fn = js2##ID (js, self)->ENTRY; \
|
||||
if (!JS_IsUndefined(fn)) JS_FreeValue(js, fn); \
|
||||
if (!JS_IsNull(fn)) JS_FreeValue(js, fn); \
|
||||
js2##ID (js, self)->ENTRY = JS_DupValue(js, val); \
|
||||
return JS_UNDEFINED; \
|
||||
return JS_NULL; \
|
||||
}\
|
||||
JSValue js_##ID##_get_##ENTRY (JSContext *js, JSValue self) { return JS_DupValue(js, js2##ID (js, self)->ENTRY); } \
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ static int gcd(int a, int b) {
|
||||
JSC_CCALL(math_rotate,
|
||||
HMM_Vec2 vec = js2vec2(js,argv[0]);
|
||||
double angle = js2angle(js, argv[1]);
|
||||
HMM_Vec2 pivot = JS_IsUndefined(argv[2]) ? v2zero : js2vec2(js,argv[2]);
|
||||
HMM_Vec2 pivot = JS_IsNull(argv[2]) ? v2zero : js2vec2(js,argv[2]);
|
||||
vec = HMM_SubV2(vec,pivot);
|
||||
|
||||
float r = HMM_LenV2(vec);
|
||||
@@ -254,7 +254,7 @@ JSC_CCALL(math_project,
|
||||
if (!a || !b) {
|
||||
free(a);
|
||||
free(b);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
// We'll work up to the smaller length
|
||||
@@ -262,7 +262,7 @@ JSC_CCALL(math_project,
|
||||
if (len == 0) {
|
||||
free(a);
|
||||
free(b);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
// Compute dot products: a·b and b·b
|
||||
@@ -299,14 +299,14 @@ JSC_CCALL(math_midpoint,
|
||||
if (!a || !b) {
|
||||
free(a);
|
||||
free(b);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
size_t len = (alen < blen) ? alen : blen;
|
||||
if (len == 0) {
|
||||
free(a);
|
||||
free(b);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
float *m = (float*)malloc(sizeof(float) * len);
|
||||
@@ -334,14 +334,14 @@ JSC_CCALL(math_reflect,
|
||||
if (!a || !b) {
|
||||
free(a);
|
||||
free(b);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
size_t len = (alen < blen) ? alen : blen;
|
||||
if (len == 0) {
|
||||
free(a);
|
||||
free(b);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
// Reflect vector a across normal b
|
||||
@@ -378,14 +378,14 @@ JSC_CCALL(math_direction,
|
||||
if (!a || !b) {
|
||||
free(a);
|
||||
free(b);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
size_t len = (alen < blen) ? alen : blen;
|
||||
if (len == 0) {
|
||||
free(a);
|
||||
free(b);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
// Direction vector from a to b (normalized)
|
||||
@@ -421,7 +421,7 @@ JSC_CCALL(math_angle,
|
||||
|
||||
if (!v || len < 2) {
|
||||
free(v);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
// Return angle in radians for 2D vector
|
||||
@@ -438,14 +438,14 @@ JSC_CCALL(math_distance,
|
||||
if (!a || !b) {
|
||||
free(a);
|
||||
free(b);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
size_t len = (alen < blen) ? alen : blen;
|
||||
if (len == 0) {
|
||||
free(a);
|
||||
free(b);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
float distSq = 0.0f;
|
||||
|
||||
@@ -166,10 +166,10 @@ static JSValue js_miniz_decompress(JSContext *js,
|
||||
JSValue ret;
|
||||
int asString = (argc > 1) && JS_ToBool(js, argv[1]);
|
||||
|
||||
if (asString)
|
||||
// if (asString)
|
||||
ret = JS_NewStringLen(js, (const char *)out_ptr, out_len);
|
||||
else
|
||||
ret = JS_NewArrayBufferCopy(js, out_ptr, out_len);
|
||||
// else
|
||||
// ret = JS_NewArrayBufferCopy(js, out_ptr, out_len);
|
||||
|
||||
#ifdef MZ_FREE
|
||||
MZ_FREE(out_ptr);
|
||||
@@ -210,7 +210,7 @@ JSValue js_writer_add_file(JSContext *js, JSValue self, int argc, JSValue *argv)
|
||||
if (!success)
|
||||
return JS_ThrowInternalError(js, "Failed to add memory to zip");
|
||||
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ static int nota_stack_has(NotaEncodeContext *enc, JSValueConst val)
|
||||
}
|
||||
|
||||
static JSValue apply_replacer(NotaEncodeContext *enc, JSValueConst holder, JSValueConst key, JSValueConst val) {
|
||||
if (JS_IsUndefined(enc->replacer)) return JS_DupValue(enc->ctx, val);
|
||||
if (JS_IsNull(enc->replacer)) return JS_DupValue(enc->ctx, val);
|
||||
|
||||
JSValue args[2] = { JS_DupValue(enc->ctx, key), JS_DupValue(enc->ctx, val) };
|
||||
JSValue result = JS_Call(enc->ctx, enc->replacer, holder, 2, args);
|
||||
@@ -103,17 +103,17 @@ char *js_do_nota_decode(JSContext *js, JSValue *tmp, char *nota, JSValue holder,
|
||||
nota = nota_read_sym(&b, nota);
|
||||
if (b == NOTA_PRIVATE) {
|
||||
JSValue inner;
|
||||
nota = js_do_nota_decode(js, &inner, nota, holder, JS_UNDEFINED, reviver);
|
||||
nota = js_do_nota_decode(js, &inner, nota, holder, JS_NULL, reviver);
|
||||
JSValue obj = JS_NewObject(js);
|
||||
cell_rt *crt = JS_GetContextOpaque(js);
|
||||
JS_SetProperty(js, obj, crt->actor_sym, inner);
|
||||
*tmp = obj;
|
||||
} else {
|
||||
switch(b) {
|
||||
case NOTA_NULL: *tmp = JS_UNDEFINED; break;
|
||||
case NOTA_NULL: *tmp = JS_NULL; break;
|
||||
case NOTA_FALSE: *tmp = JS_NewBool(js, 0); break;
|
||||
case NOTA_TRUE: *tmp = JS_NewBool(js, 1); break;
|
||||
default: *tmp = JS_UNDEFINED; break;
|
||||
default: *tmp = JS_NULL; break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -124,7 +124,7 @@ char *js_do_nota_decode(JSContext *js, JSValue *tmp, char *nota, JSValue holder,
|
||||
break;
|
||||
}
|
||||
|
||||
if (!JS_IsUndefined(reviver)) {
|
||||
if (!JS_IsNull(reviver)) {
|
||||
JSValue args[2] = { JS_DupValue(js, key), JS_DupValue(js, *tmp) };
|
||||
JSValue revived = JS_Call(js, reviver, holder, 2, args);
|
||||
JS_FreeValue(js, args[0]);
|
||||
@@ -170,7 +170,6 @@ static void nota_encode_value(NotaEncodeContext *enc, JSValueConst val, JSValueC
|
||||
else nota_write_sym(&enc->nb, NOTA_FALSE);
|
||||
break;
|
||||
case JS_TAG_NULL:
|
||||
case JS_TAG_UNDEFINED:
|
||||
nota_write_sym(&enc->nb, NOTA_NULL);
|
||||
break;
|
||||
case JS_TAG_OBJECT: {
|
||||
@@ -202,9 +201,9 @@ static void nota_encode_value(NotaEncodeContext *enc, JSValueConst val, JSValueC
|
||||
|
||||
cell_rt *crt = JS_GetContextOpaque(ctx);
|
||||
JSValue adata = JS_GetProperty(ctx, replaced, crt->actor_sym);
|
||||
if (!JS_IsUndefined(adata)) {
|
||||
if (!JS_IsNull(adata)) {
|
||||
nota_write_sym(&enc->nb, NOTA_PRIVATE);
|
||||
nota_encode_value(enc, adata, replaced, JS_UNDEFINED);
|
||||
nota_encode_value(enc, adata, replaced, JS_NULL);
|
||||
JS_FreeValue(ctx, adata);
|
||||
break;
|
||||
}
|
||||
@@ -275,10 +274,10 @@ void *value2nota(JSContext *ctx, JSValue v) {
|
||||
enc->ctx = ctx;
|
||||
enc->visitedStack = JS_NewArray(ctx);
|
||||
enc->cycle = 0;
|
||||
enc->replacer = JS_UNDEFINED;
|
||||
enc->replacer = JS_NULL;
|
||||
|
||||
nota_buffer_init(&enc->nb, 128);
|
||||
nota_encode_value(enc, v, JS_UNDEFINED, JS_NewString(ctx, ""));
|
||||
nota_encode_value(enc, v, JS_NULL, JS_NewString(ctx, ""));
|
||||
|
||||
if (enc->cycle) {
|
||||
JS_FreeValue(ctx, enc->visitedStack);
|
||||
@@ -294,10 +293,10 @@ void *value2nota(JSContext *ctx, JSValue v) {
|
||||
}
|
||||
|
||||
JSValue nota2value(JSContext *js, void *nota) {
|
||||
if (!nota) return JS_UNDEFINED;
|
||||
if (!nota) return JS_NULL;
|
||||
JSValue ret;
|
||||
JSValue holder = JS_NewObject(js);
|
||||
js_do_nota_decode(js, &ret, nota, holder, JS_NewString(js, ""), JS_UNDEFINED);
|
||||
js_do_nota_decode(js, &ret, nota, holder, JS_NewString(js, ""), JS_NULL);
|
||||
JS_FreeValue(js, holder);
|
||||
return ret;
|
||||
}
|
||||
@@ -309,10 +308,10 @@ static JSValue js_nota_encode(JSContext *ctx, JSValueConst this_val, int argc, J
|
||||
enc->ctx = ctx;
|
||||
enc->visitedStack = JS_NewArray(ctx);
|
||||
enc->cycle = 0;
|
||||
enc->replacer = (argc > 1 && JS_IsFunction(ctx, argv[1])) ? argv[1] : JS_UNDEFINED;
|
||||
enc->replacer = (argc > 1 && JS_IsFunction(ctx, argv[1])) ? argv[1] : JS_NULL;
|
||||
|
||||
nota_buffer_init(&enc->nb, 128);
|
||||
nota_encode_value(enc, argv[0], JS_UNDEFINED, JS_NewString(ctx, ""));
|
||||
nota_encode_value(enc, argv[0], JS_NULL, JS_NewString(ctx, ""));
|
||||
|
||||
if (enc->cycle) {
|
||||
JS_FreeValue(ctx, enc->visitedStack);
|
||||
@@ -330,13 +329,13 @@ static JSValue js_nota_encode(JSContext *ctx, JSValueConst this_val, int argc, J
|
||||
}
|
||||
|
||||
static JSValue js_nota_decode(JSContext *js, JSValueConst self, int argc, JSValueConst *argv) {
|
||||
if (argc < 1) return JS_UNDEFINED;
|
||||
if (argc < 1) return JS_NULL;
|
||||
|
||||
size_t len;
|
||||
unsigned char *nota = js_get_blob_data(js, &len, argv[0]);
|
||||
if (!nota) return JS_UNDEFINED;
|
||||
if (!nota) return JS_NULL;
|
||||
|
||||
JSValue reviver = (argc > 1 && JS_IsFunction(js, argv[1])) ? argv[1] : JS_UNDEFINED;
|
||||
JSValue reviver = (argc > 1 && JS_IsFunction(js, argv[1])) ? argv[1] : JS_NULL;
|
||||
JSValue ret;
|
||||
JSValue holder = JS_NewObject(js);
|
||||
js_do_nota_decode(js, &ret, (char*)nota, holder, JS_NewString(js, ""), reviver);
|
||||
|
||||
@@ -533,7 +533,7 @@ static JSValue js_array_slice(JSContext *js, JSValueConst self, int argc, JSValu
|
||||
int32_t end = arr->size;
|
||||
|
||||
// Parse start argument
|
||||
if (argc >= 1 && !JS_IsUndefined(argv[0])) {
|
||||
if (argc >= 1 && !JS_IsNull(argv[0])) {
|
||||
if (JS_ToInt32(js, &start, argv[0]))
|
||||
return JS_EXCEPTION;
|
||||
|
||||
@@ -547,7 +547,7 @@ static JSValue js_array_slice(JSContext *js, JSValueConst self, int argc, JSValu
|
||||
}
|
||||
|
||||
// Parse end argument
|
||||
if (argc >= 2 && !JS_IsUndefined(argv[1])) {
|
||||
if (argc >= 2 && !JS_IsNull(argv[1])) {
|
||||
if (JS_ToInt32(js, &end, argv[1]))
|
||||
return JS_EXCEPTION;
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ JSC_CCALL(os_totalmem, return number2js(js, SDL_GetSystemRAM()))
|
||||
JSC_CCALL(os_platform, return JS_NewString(js,SDL_GetPlatform()))
|
||||
|
||||
static JSValue js_os_hostname(JSContext *js, JSValue self, int argc, JSValue *argv) {
|
||||
JSValue ret = JS_UNDEFINED;
|
||||
JSValue ret = JS_NULL;
|
||||
#ifdef _WIN32
|
||||
TCHAR buffer[256] = TEXT("");
|
||||
DWORD size = sizeof(buffer) / sizeof(TCHAR);
|
||||
@@ -71,7 +71,7 @@ static JSValue js_os_hostname(JSContext *js, JSValue self, int argc, JSValue *ar
|
||||
}
|
||||
|
||||
static JSValue js_os_arch(JSContext *js, JSValue self, int argc, JSValue *argv) {
|
||||
JSValue ret = JS_UNDEFINED;
|
||||
JSValue ret = JS_NULL;
|
||||
#if defined(__x86_64__) || defined(_M_X64)
|
||||
return JS_NewString(js,"x64");
|
||||
#elif defined(__aarch64__) || defined(_M_ARM64)
|
||||
@@ -99,7 +99,7 @@ static JSValue js_os_arch(JSContext *js, JSValue self, int argc, JSValue *argv)
|
||||
}
|
||||
|
||||
static JSValue js_os_freemem(JSContext *js, JSValue self, int argc, JSValue *argv) {
|
||||
JSValue ret = JS_UNDEFINED;
|
||||
JSValue ret = JS_NULL;
|
||||
#ifdef _WIN32
|
||||
MEMORYSTATUSEX statex;
|
||||
statex.dwLength = sizeof(statex);
|
||||
@@ -126,7 +126,7 @@ static JSValue js_os_freemem(JSContext *js, JSValue self, int argc, JSValue *arg
|
||||
}
|
||||
|
||||
static JSValue js_os_version(JSContext *js, JSValue self, int argc, JSValue *argv) {
|
||||
JSValue ret = JS_UNDEFINED;
|
||||
JSValue ret = JS_NULL;
|
||||
#ifdef _WIN32
|
||||
typedef LONG (WINAPI *RtlGetVersionPtr)(PRTL_OSVERSIONINFOW);
|
||||
HMODULE h = GetModuleHandleA("ntdll.dll");
|
||||
@@ -200,7 +200,7 @@ JS_SetPropertyStr(js, OBJ, #FIELD, TYPE##2js(js,STRUCT.FIELD));\
|
||||
#define JSJMEMRET(FIELD) JSOBJ_ADD_FIELD(ret, jsmem, FIELD, number)
|
||||
|
||||
JSC_CCALL(os_mallinfo,
|
||||
ret = JS_UNDEFINED;
|
||||
ret = JS_NULL;
|
||||
/*struct mallinfo jsmem = mallinfo();
|
||||
ret = JS_NewObject(js);
|
||||
JSJMEMRET(arena);
|
||||
@@ -216,7 +216,7 @@ JSC_CCALL(os_mallinfo,
|
||||
)
|
||||
|
||||
static JSValue js_os_rusage(JSContext *js, JSValue self, int argc, JSValue *argv) {
|
||||
JSValue ret = JS_UNDEFINED;
|
||||
JSValue ret = JS_NULL;
|
||||
ret = JS_NewObject(js);
|
||||
|
||||
#ifndef _WIN32
|
||||
@@ -244,12 +244,12 @@ static JSValue js_os_rusage(JSContext *js, JSValue self, int argc, JSValue *argv
|
||||
#ifdef TRACY_ENABLE
|
||||
#include <tracy/TracyC.h>
|
||||
JSC_CCALL(os_frame,
|
||||
if (!tracy_profiling_enabled) return JS_UNDEFINED;
|
||||
if (!tracy_profiling_enabled) return JS_NULL;
|
||||
TracyCFrameMark
|
||||
)
|
||||
|
||||
JSC_CCALL(os_trace_img,
|
||||
if (!tracy_profiling_enabled) return JS_UNDEFINED;
|
||||
if (!tracy_profiling_enabled) return JS_NULL;
|
||||
size_t len;
|
||||
double width, height;
|
||||
JS_ToFloat64(js,&width,argv[1]);
|
||||
@@ -258,7 +258,7 @@ JSC_CCALL(os_trace_img,
|
||||
)
|
||||
|
||||
JSC_CCALL(os_trace_message,
|
||||
if (!tracy_profiling_enabled) return JS_UNDEFINED;
|
||||
if (!tracy_profiling_enabled) return JS_NULL;
|
||||
size_t len;
|
||||
const char *str = JS_ToCStringLen(js, &len, argv[0]);
|
||||
TracyCMessage(str,len);
|
||||
|
||||
@@ -24,11 +24,11 @@ static JSValue js_qr_encode(JSContext *js, JSValueConst this_val, int argc, JSVa
|
||||
int use_byte_mode = 0;
|
||||
|
||||
// Handle options object (argv[1])
|
||||
if (argc > 1 && !JS_IsUndefined(argv[1]) && JS_IsObject(argv[1])) {
|
||||
if (argc > 1 && !JS_IsNull(argv[1]) && JS_IsObject(argv[1])) {
|
||||
JSValue opt = argv[1];
|
||||
|
||||
JSValue m = JS_GetPropertyStr(js, opt, "mode");
|
||||
if (!JS_IsUndefined(m)) {
|
||||
if (!JS_IsNull(m)) {
|
||||
const char *smode = JS_ToCString(js, m);
|
||||
if (!smode) { JS_FreeValue(js, m); return JS_EXCEPTION; }
|
||||
if (!strcasecmp(smode, "byte") || !strcasecmp(smode, "binary"))
|
||||
@@ -45,7 +45,7 @@ static JSValue js_qr_encode(JSContext *js, JSValueConst this_val, int argc, JSVa
|
||||
|
||||
// Version (1-40)
|
||||
JSValue v = JS_GetPropertyStr(js, opt, "version");
|
||||
if (!JS_IsUndefined(v)) {
|
||||
if (!JS_IsNull(v)) {
|
||||
int32_t ver;
|
||||
if (JS_ToInt32(js, &ver, v) || ver < 0 || ver > 40) {
|
||||
JS_FreeValue(js, v);
|
||||
@@ -57,7 +57,7 @@ static JSValue js_qr_encode(JSContext *js, JSValueConst this_val, int argc, JSVa
|
||||
|
||||
// Error correction level ("l", "m", "q", "h")
|
||||
JSValue l = JS_GetPropertyStr(js, opt, "level");
|
||||
if (!JS_IsUndefined(l)) {
|
||||
if (!JS_IsNull(l)) {
|
||||
const char *level = JS_ToCString(js, l);
|
||||
if (!level) {
|
||||
JS_FreeValue(js, l);
|
||||
@@ -78,7 +78,7 @@ static JSValue js_qr_encode(JSContext *js, JSValueConst this_val, int argc, JSVa
|
||||
|
||||
// Case sensitivity (true/false)
|
||||
JSValue ci = JS_GetPropertyStr(js, opt, "caseinsensitive");
|
||||
if (!JS_IsUndefined(ci)) {
|
||||
if (!JS_IsNull(ci)) {
|
||||
int bool_val;
|
||||
if (JS_ToBool(js, ci)) {
|
||||
bool_val = 0; // qrencode: 0 = case-insensitive
|
||||
@@ -239,7 +239,7 @@ static JSValue js_qr_rgba(JSContext *js, JSValueConst self, int argc, JSValueCon
|
||||
if (argc > 2) JS_ToUint32(js, &off, argv[2]);
|
||||
|
||||
JSValue js_w = JS_GetPropertyStr(js, mods, "width");
|
||||
if (JS_IsUndefined(js_w)) {
|
||||
if (JS_IsNull(js_w)) {
|
||||
JS_FreeValue(js, js_w);
|
||||
return JS_ThrowTypeError(js, "mods.width missing");
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ JSC_CCALL(SDL_Renderer_draw_color,
|
||||
|
||||
JSC_CCALL(SDL_Renderer_rect,
|
||||
SDL_Renderer *r = js2SDL_Renderer(js,self);
|
||||
if (!JS_IsUndefined(argv[1])) {
|
||||
if (!JS_IsNull(argv[1])) {
|
||||
colorf color = js2color(js,argv[1]);
|
||||
SDL_SetRenderDrawColorFloat(r, color.r, color.g, color.b, color.a);
|
||||
}
|
||||
@@ -62,7 +62,7 @@ JSC_CCALL(SDL_Renderer_rect,
|
||||
JS_FreeValue(js,val);
|
||||
}
|
||||
SDL_RenderRects(r,rects,len);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
rect rect = js2rect(js,argv[0]);
|
||||
@@ -85,7 +85,7 @@ JSC_CCALL(renderer_load_texture,
|
||||
|
||||
JSC_CCALL(SDL_Renderer_fillrect,
|
||||
SDL_Renderer *r = js2SDL_Renderer(js,self);
|
||||
if (!JS_IsUndefined(argv[1])) {
|
||||
if (!JS_IsNull(argv[1])) {
|
||||
colorf color = js2color(js,argv[1]);
|
||||
SDL_SetRenderDrawColorFloat(r, color.r, color.g, color.b, color.a);
|
||||
}
|
||||
@@ -112,12 +112,12 @@ JSC_CCALL(renderer_texture,
|
||||
SDL_Texture *tex = js2SDL_Texture(js,argv[0]);
|
||||
rect dst = transform_rect(js2rect(js,argv[1]), &cam_mat);
|
||||
|
||||
if (!JS_IsUndefined(argv[3])) {
|
||||
if (!JS_IsNull(argv[3])) {
|
||||
colorf color = js2color(js,argv[3]);
|
||||
SDL_SetTextureColorModFloat(tex, color.r, color.g, color.b);
|
||||
SDL_SetTextureAlphaModFloat(tex,color.a);
|
||||
}
|
||||
if (JS_IsUndefined(argv[2]))
|
||||
if (JS_IsNull(argv[2]))
|
||||
SDL_RenderTexture(renderer,tex,NULL,&dst);
|
||||
else {
|
||||
|
||||
@@ -137,7 +137,7 @@ JSC_CCALL(renderer_tile,
|
||||
if (!dst.h) dst.h = tex->h;
|
||||
float scale = js2number(js,argv[3]);
|
||||
if (!scale) scale = 1;
|
||||
if (JS_IsUndefined(argv[2]))
|
||||
if (JS_IsNull(argv[2]))
|
||||
SDL_RenderTextureTiled(renderer,tex,NULL,scale, &dst);
|
||||
else {
|
||||
rect src = js2rect(js,argv[2]);
|
||||
@@ -154,15 +154,15 @@ JSC_CCALL(renderer_slice9,
|
||||
dst = transform_rect(js2rect(js,argv[1]), &cam_mat);
|
||||
|
||||
SDL_RenderTexture9Grid(renderer, tex,
|
||||
JS_IsUndefined(argv[3]) ? NULL : &src,
|
||||
JS_IsNull(argv[3]) ? NULL : &src,
|
||||
bounds.l, bounds.r, bounds.t, bounds.b, 0.0,
|
||||
JS_IsUndefined(argv[1]) ? NULL : &dst);
|
||||
JS_IsNull(argv[1]) ? NULL : &dst);
|
||||
)
|
||||
|
||||
JSC_CCALL(renderer_get_image,
|
||||
SDL_Renderer *r = js2SDL_Renderer(js,self);
|
||||
SDL_Surface *surf = NULL;
|
||||
if (!JS_IsUndefined(argv[0])) {
|
||||
if (!JS_IsNull(argv[0])) {
|
||||
rect rect = js2rect(js,argv[0]);
|
||||
surf = SDL_RenderReadPixels(r,&rect);
|
||||
} else
|
||||
@@ -173,7 +173,7 @@ JSC_CCALL(renderer_get_image,
|
||||
|
||||
JSC_SCALL(renderer_fasttext,
|
||||
SDL_Renderer *r = js2SDL_Renderer(js,self);
|
||||
if (!JS_IsUndefined(argv[2])) {
|
||||
if (!JS_IsNull(argv[2])) {
|
||||
colorf color = js2color(js,argv[2]);
|
||||
SDL_SetRenderDrawColorFloat(r, color.r, color.g, color.b, color.a);
|
||||
}
|
||||
@@ -185,7 +185,7 @@ JSC_SCALL(renderer_fasttext,
|
||||
|
||||
JSC_CCALL(renderer_line,
|
||||
SDL_Renderer *r = js2SDL_Renderer(js,self);
|
||||
if (!JS_IsUndefined(argv[1])) {
|
||||
if (!JS_IsNull(argv[1])) {
|
||||
colorf color = js2color(js,argv[1]);
|
||||
SDL_SetRenderDrawColorFloat(r, color.r, color.g, color.b, color.a);
|
||||
}
|
||||
@@ -205,7 +205,7 @@ JSC_CCALL(renderer_line,
|
||||
|
||||
JSC_CCALL(renderer_point,
|
||||
SDL_Renderer *r = js2SDL_Renderer(js,self);
|
||||
if (!JS_IsUndefined(argv[1])) {
|
||||
if (!JS_IsNull(argv[1])) {
|
||||
colorf color = js2color(js,argv[1]);
|
||||
SDL_SetRenderDrawColorFloat(r, color.r, color.g, color.b, color.a);
|
||||
}
|
||||
@@ -220,7 +220,7 @@ JSC_CCALL(renderer_point,
|
||||
JS_FreeValue(js,val);
|
||||
}
|
||||
SDL_RenderPoints(r, points, len);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
HMM_Vec2 point = transform_point(r, js2vec2(js,argv[0]), &cam_mat);
|
||||
@@ -297,7 +297,7 @@ JSC_CCALL(renderer_logical_size,
|
||||
|
||||
JSC_CCALL(renderer_viewport,
|
||||
SDL_Renderer *r = js2SDL_Renderer(js,self);
|
||||
if (JS_IsUndefined(argv[0]))
|
||||
if (JS_IsNull(argv[0]))
|
||||
SDL_SetRenderViewport(r,NULL);
|
||||
else {
|
||||
rect view = js2rect(js,argv[0]);
|
||||
@@ -319,7 +319,7 @@ JSC_CCALL(renderer_get_viewport,
|
||||
|
||||
JSC_CCALL(renderer_clip,
|
||||
SDL_Renderer *r = js2SDL_Renderer(js,self);
|
||||
if (JS_IsUndefined(argv[0]))
|
||||
if (JS_IsNull(argv[0]))
|
||||
SDL_SetRenderClipRect(r,NULL);
|
||||
else {
|
||||
rect view = js2rect(js,argv[0]);
|
||||
@@ -376,7 +376,7 @@ JSC_CCALL(renderer_screen2world,
|
||||
|
||||
JSC_CCALL(renderer_target,
|
||||
SDL_Renderer *r = js2SDL_Renderer(js,self);
|
||||
if (JS_IsUndefined(argv[0]))
|
||||
if (JS_IsNull(argv[0]))
|
||||
SDL_SetRenderTarget(r, NULL);
|
||||
else {
|
||||
SDL_Texture *tex = js2SDL_Texture(js,argv[0]);
|
||||
@@ -408,12 +408,12 @@ JSC_CCALL(renderer_make_sprite_mesh,
|
||||
HMM_Vec4 color;
|
||||
|
||||
rect src;
|
||||
if (JS_IsUndefined(jssrc))
|
||||
if (JS_IsNull(jssrc))
|
||||
src = (rect){.x = 0, .y = 0, .w = 1, .h = 1};
|
||||
else
|
||||
src = js2rect(js,jssrc);
|
||||
|
||||
if (JS_IsUndefined(jscolor))
|
||||
if (JS_IsNull(jscolor))
|
||||
color = (HMM_Vec4){1,1,1,1};
|
||||
else
|
||||
color = js2vec4(js,jscolor);
|
||||
|
||||
@@ -105,7 +105,7 @@ struct rtree_each
|
||||
|
||||
int rtree_foreach(const NUMTYPE *min, const NUMTYPE *max, const JSValue *value, struct rtree_each *each)
|
||||
{
|
||||
JSValue ret = JS_Call(each->js, each->fn, JS_UNDEFINED, 0, NULL);
|
||||
JSValue ret = JS_Call(each->js, each->fn, JS_NULL, 0, NULL);
|
||||
uncaught_exception(each->js, ret);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -183,7 +183,7 @@ static SDL_CameraSpec js2cameraspec(JSContext *js, JSValue obj) {
|
||||
JSValue v;
|
||||
|
||||
v = JS_GetPropertyStr(js, obj, "format");
|
||||
if (!JS_IsUndefined(v)) {
|
||||
if (!JS_IsNull(v)) {
|
||||
const char *s = JS_ToCString(js, v);
|
||||
spec.format = str2pixelformat(s);
|
||||
JS_FreeCString(js, s);
|
||||
@@ -191,23 +191,23 @@ static SDL_CameraSpec js2cameraspec(JSContext *js, JSValue obj) {
|
||||
JS_FreeValue(js, v);
|
||||
|
||||
v = JS_GetPropertyStr(js, obj, "colorspace");
|
||||
if (!JS_IsUndefined(v)) JS_ToInt32(js, &spec.colorspace, v);
|
||||
if (!JS_IsNull(v)) JS_ToInt32(js, &spec.colorspace, v);
|
||||
JS_FreeValue(js, v);
|
||||
|
||||
v = JS_GetPropertyStr(js, obj, "width");
|
||||
if (!JS_IsUndefined(v)) JS_ToInt32(js, &spec.width, v);
|
||||
if (!JS_IsNull(v)) JS_ToInt32(js, &spec.width, v);
|
||||
JS_FreeValue(js, v);
|
||||
|
||||
v = JS_GetPropertyStr(js, obj, "height");
|
||||
if (!JS_IsUndefined(v)) JS_ToInt32(js, &spec.height, v);
|
||||
if (!JS_IsNull(v)) JS_ToInt32(js, &spec.height, v);
|
||||
JS_FreeValue(js, v);
|
||||
|
||||
v = JS_GetPropertyStr(js, obj, "framerate_numerator");
|
||||
if (!JS_IsUndefined(v)) JS_ToInt32(js, &spec.framerate_numerator, v);
|
||||
if (!JS_IsNull(v)) JS_ToInt32(js, &spec.framerate_numerator, v);
|
||||
JS_FreeValue(js, v);
|
||||
|
||||
v = JS_GetPropertyStr(js, obj, "framerate_denominator");
|
||||
if (!JS_IsUndefined(v)) JS_ToInt32(js, &spec.framerate_denominator, v);
|
||||
if (!JS_IsNull(v)) JS_ToInt32(js, &spec.framerate_denominator, v);
|
||||
JS_FreeValue(js, v);
|
||||
|
||||
return spec;
|
||||
@@ -229,7 +229,7 @@ JSC_CCALL(camera_open,
|
||||
SDL_CameraSpec spec;
|
||||
|
||||
// Check if a format spec was provided
|
||||
if (argc > 1 && !JS_IsUndefined(argv[1])) {
|
||||
if (argc > 1 && !JS_IsNull(argv[1])) {
|
||||
spec = js2cameraspec(js, argv[1]);
|
||||
spec_ptr = &spec;
|
||||
}
|
||||
@@ -300,7 +300,7 @@ JSC_CCALL(camera_capture,
|
||||
const char *msg = SDL_GetError();
|
||||
if (msg[0] != 0)
|
||||
return JS_ThrowReferenceError(js,"Could not get camera frame: %s", SDL_GetError());
|
||||
else return JS_UNDEFINED;
|
||||
else return JS_NULL;
|
||||
}
|
||||
|
||||
// Create a copy of the surface
|
||||
@@ -330,7 +330,7 @@ JSC_CCALL(camera_get_driver,
|
||||
if (!cam) return JS_ThrowReferenceError(js,"Self was not a camera: %s", SDL_GetError());
|
||||
|
||||
const char *driver = SDL_GetCurrentCameraDriver();
|
||||
if (!driver) return JS_UNDEFINED;
|
||||
if (!driver) return JS_NULL;
|
||||
|
||||
return JS_NewString(js, driver);
|
||||
)
|
||||
@@ -415,7 +415,7 @@ static SDL_AudioSpec js2audiospec(JSContext *js, JSValue obj)
|
||||
JSValue v;
|
||||
|
||||
v = JS_GetPropertyStr(js, obj, "format");
|
||||
if (!JS_IsUndefined(v)) {
|
||||
if (!JS_IsNull(v)) {
|
||||
const char *s = JS_ToCString(js, v);
|
||||
format_str_to_enum(s, &spec.format);
|
||||
JS_FreeCString(js, s);
|
||||
@@ -423,11 +423,11 @@ static SDL_AudioSpec js2audiospec(JSContext *js, JSValue obj)
|
||||
JS_FreeValue(js, v);
|
||||
|
||||
v = JS_GetPropertyStr(js, obj, "channels");
|
||||
if (!JS_IsUndefined(v)) JS_ToInt32(js, &spec.channels, v);
|
||||
if (!JS_IsNull(v)) JS_ToInt32(js, &spec.channels, v);
|
||||
JS_FreeValue(js, v);
|
||||
|
||||
v = JS_GetPropertyStr(js, obj, "samplerate");
|
||||
if (!JS_IsUndefined(v)) JS_ToInt32(js, &spec.freq, v);
|
||||
if (!JS_IsNull(v)) JS_ToInt32(js, &spec.freq, v);
|
||||
JS_FreeValue(js, v);
|
||||
|
||||
return spec;
|
||||
@@ -461,7 +461,7 @@ JSC_CCALL(sdl_audio_open_stream,
|
||||
|
||||
SDL_AudioStream *st;
|
||||
|
||||
if (JS_IsUndefined(argv[1]))
|
||||
if (JS_IsNull(argv[1]))
|
||||
st = SDL_OpenAudioDeviceStream(devid, NULL, NULL, NULL);
|
||||
else {
|
||||
SDL_AudioSpec want = js2audiospec(js, argv[1]);
|
||||
@@ -496,11 +496,11 @@ JSC_CCALL(sdl_audiostream_set_format,
|
||||
const SDL_AudioSpec *src_ptr=NULL,*dst_ptr=NULL;
|
||||
SDL_AudioSpec src={0},dst={0};
|
||||
|
||||
if(argc>0&&!JS_IsUndefined(argv[0])){
|
||||
if(argc>0&&!JS_IsNull(argv[0])){
|
||||
src=js2audiospec(js,argv[0]);
|
||||
src_ptr=&src;
|
||||
}
|
||||
if(argc>1&&!JS_IsUndefined(argv[1])){
|
||||
if(argc>1&&!JS_IsNull(argv[1])){
|
||||
dst=js2audiospec(js,argv[1]);
|
||||
dst_ptr=&dst;
|
||||
}
|
||||
@@ -508,7 +508,7 @@ JSC_CCALL(sdl_audiostream_set_format,
|
||||
if(!SDL_SetAudioStreamFormat(as,src_ptr,dst_ptr))
|
||||
return JS_ThrowInternalError(js,"%s",SDL_GetError());
|
||||
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
)
|
||||
|
||||
JSC_CCALL(sdl_audiostream_resume,
|
||||
@@ -516,21 +516,21 @@ JSC_CCALL(sdl_audiostream_resume,
|
||||
if (!SDL_ResumeAudioStreamDevice(as))
|
||||
return JS_ThrowInternalError(js,"%s",SDL_GetError());
|
||||
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
)
|
||||
|
||||
JSC_CCALL(sdl_audiostream_clear,
|
||||
SDL_AudioStream *as=js2SDL_AudioStream(js,self);
|
||||
if (!SDL_ClearAudioStream(as))
|
||||
return JS_ThrowInternalError(js,"%s",SDL_GetError());
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
)
|
||||
|
||||
JSC_CCALL(sdl_audiostream_flush,
|
||||
SDL_AudioStream *as=js2SDL_AudioStream(js,self);
|
||||
if(!SDL_FlushAudioStream(as))
|
||||
return JS_ThrowInternalError(js,"%s",SDL_GetError());
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
)
|
||||
|
||||
JSC_CCALL(sdl_audiostream_available,
|
||||
@@ -557,7 +557,7 @@ JSC_CCALL(sdl_audiostream_put,
|
||||
|
||||
if (!SDL_PutAudioStreamData(as,buf,len))
|
||||
return JS_ThrowInternalError(js, "%s", SDL_GetError());
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
)
|
||||
|
||||
JSC_CCALL(sdl_audiostream_get,
|
||||
@@ -587,7 +587,7 @@ JSC_CCALL(sdl_audiostream_set_gain,
|
||||
SDL_AudioStream *as=js2SDL_AudioStream(js,self);
|
||||
double g; JS_ToFloat64(js,&g,argv[0]);
|
||||
SDL_SetAudioStreamGain(as,(float)g);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
)
|
||||
|
||||
JSC_CCALL(sdl_audiostream_get_freq_ratio,
|
||||
@@ -599,7 +599,7 @@ JSC_CCALL(sdl_audiostream_set_freq_ratio,
|
||||
SDL_AudioStream *as=js2SDL_AudioStream(js,self);
|
||||
double r; JS_ToFloat64(js,&r,argv[0]);
|
||||
SDL_SetAudioStreamFrequencyRatio(as,(float)r);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
)
|
||||
|
||||
/* ---------- JS export list -------------------------------------------- */
|
||||
|
||||
@@ -70,7 +70,7 @@ SDL_GPUSampleCount js2SDL_GPUSampleCount(JSContext *js, JSValue v)
|
||||
|
||||
#define JS2ENUM(NAME, RETS, VALS) \
|
||||
int js2##NAME(JSContext *js, JSValue v) { \
|
||||
if (JS_IsUndefined(v)) return 0; \
|
||||
if (JS_IsNull(v)) return 0; \
|
||||
const char *str = JS_ToCString(js, v); \
|
||||
int *rets = (RETS); \
|
||||
const char **vals = (VALS); \
|
||||
@@ -728,19 +728,19 @@ SDL_GPUStencilOpState js2SDL_GPUStencilOpState(JSContext *js, JSValue v)
|
||||
memset(&state, 0, sizeof(state));
|
||||
|
||||
JSValue compare_val = JS_GetPropertyStr(js, v, "compare");
|
||||
if(!JS_IsUndefined(compare_val)) state.compare_op = js2SDL_GPUCompareOp(js, compare_val);
|
||||
if(!JS_IsNull(compare_val)) state.compare_op = js2SDL_GPUCompareOp(js, compare_val);
|
||||
JS_FreeValue(js, compare_val);
|
||||
|
||||
JSValue fail_val = JS_GetPropertyStr(js, v, "fail");
|
||||
if(!JS_IsUndefined(fail_val)) state.fail_op = js2SDL_GPUStencilOp(js, fail_val);
|
||||
if(!JS_IsNull(fail_val)) state.fail_op = js2SDL_GPUStencilOp(js, fail_val);
|
||||
JS_FreeValue(js, fail_val);
|
||||
|
||||
JSValue depth_fail_val = JS_GetPropertyStr(js, v, "depth_fail");
|
||||
if(!JS_IsUndefined(depth_fail_val)) state.depth_fail_op = js2SDL_GPUStencilOp(js, depth_fail_val);
|
||||
if(!JS_IsNull(depth_fail_val)) state.depth_fail_op = js2SDL_GPUStencilOp(js, depth_fail_val);
|
||||
JS_FreeValue(js, depth_fail_val);
|
||||
|
||||
JSValue pass_val = JS_GetPropertyStr(js, v, "pass");
|
||||
if(!JS_IsUndefined(pass_val)) state.pass_op = js2SDL_GPUStencilOp(js, pass_val);
|
||||
if(!JS_IsNull(pass_val)) state.pass_op = js2SDL_GPUStencilOp(js, pass_val);
|
||||
JS_FreeValue(js, pass_val);
|
||||
|
||||
return state;
|
||||
@@ -798,8 +798,8 @@ JSC_CCALL(cmd_acquire_swapchain,
|
||||
Uint32 w,h;
|
||||
SDL_GPUTexture *texture;
|
||||
SDL_AcquireGPUSwapchainTexture(cmds,global_window, &texture, &w, &h);
|
||||
if (!texture) return JS_UNDEFINED;
|
||||
JSValue swap = JS_UNDEFINED;
|
||||
if (!texture) return JS_NULL;
|
||||
JSValue swap = JS_NULL;
|
||||
|
||||
JSValue *js_swapchains = ((cell_rt*)JS_GetContextOpaque(js))->js_swapchains;
|
||||
|
||||
@@ -810,7 +810,7 @@ JSC_CCALL(cmd_acquire_swapchain,
|
||||
}
|
||||
}
|
||||
|
||||
if (JS_IsUndefined(swap)) {
|
||||
if (JS_IsNull(swap)) {
|
||||
swap = SDL_GPUTexture2js(js,texture);
|
||||
arrput(js_swapchains,swap);
|
||||
}
|
||||
@@ -1580,7 +1580,7 @@ JSC_CCALL(gpu_upload,
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
JSValue js_buf = JS_GetPropertyUint32(js, js_buffers, i);
|
||||
|
||||
if (JS_IsUndefined(js_buf))
|
||||
if (JS_IsNull(js_buf))
|
||||
continue;
|
||||
|
||||
gpu_buffer_unpack(js, gpu, js_buf, &items[i].size, &items[i].data, &items[i].gpu_buffer);
|
||||
@@ -1883,7 +1883,7 @@ JSC_CCALL(cmd_render_pass,
|
||||
|
||||
// Optional depth_stencil
|
||||
JSValue depthval = JS_GetPropertyStr(js, passObj, "depth_stencil");
|
||||
if (!JS_IsUndefined(depthval)) {
|
||||
if (!JS_IsNull(depthval)) {
|
||||
has_depth = 1;
|
||||
JS_GETPROP(js, depthtar.texture, depthval, texture, SDL_GPUTexture)
|
||||
JS_GETPROP(js, depthtar.load_op, depthval, load, SDL_GPULoadOp)
|
||||
@@ -2243,7 +2243,7 @@ SDL_GPUSampleCount js2SDL_GPUSampleCount(JSContext *js, JSValue v)
|
||||
// Enum conversion macro and definitions
|
||||
#define JS2ENUM(NAME, RETS, VALS) \
|
||||
int js2##NAME(JSContext *js, JSValue v) { \
|
||||
if (JS_IsUndefined(v)) return 0; \
|
||||
if (JS_IsNull(v)) return 0; \
|
||||
const char *str = JS_ToCString(js, v); \
|
||||
int *rets = (RETS); \
|
||||
const char **vals = (VALS); \
|
||||
@@ -2431,5 +2431,5 @@ JSValue js_sdl_gpu_use(JSContext *js)
|
||||
{
|
||||
// GPU classes are registered via the main FFI loading system
|
||||
// This module doesn't export its own functions, it just provides class definitions
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ JSValue pixelformat2js(JSContext *js, SDL_PixelFormat fmt)
|
||||
|
||||
SDL_PixelFormat js2pixelformat(JSContext *js, JSValue v)
|
||||
{
|
||||
if (JS_IsUndefined(v)) return SDL_PIXELFORMAT_UNKNOWN;
|
||||
if (JS_IsNull(v)) return SDL_PIXELFORMAT_UNKNOWN;
|
||||
const char *s = JS_ToCString(js, v);
|
||||
if (!s) return SDL_PIXELFORMAT_UNKNOWN;
|
||||
|
||||
@@ -41,7 +41,7 @@ static JSValue scalemode2js(JSContext *js, SDL_ScaleMode mode){
|
||||
}
|
||||
|
||||
SDL_ScaleMode js2SDL_ScaleMode(JSContext *js, JSValue v){
|
||||
if(JS_IsUndefined(v)) return SDL_SCALEMODE_NEAREST;
|
||||
if(JS_IsNull(v)) return SDL_SCALEMODE_NEAREST;
|
||||
const char *s = JS_ToCString(js, v);
|
||||
if(!s) return SDL_SCALEMODE_NEAREST;
|
||||
const scale_entry *it;
|
||||
@@ -66,14 +66,14 @@ JSC_CCALL(surface_blit,
|
||||
SDL_Surface *dst = js2SDL_Surface(js, self);
|
||||
|
||||
irect dr = {0}, *pdr = NULL;
|
||||
if(!JS_IsUndefined(argv[0])){ dr = js2irect(js, argv[0]); pdr = &dr; }
|
||||
if(!JS_IsNull(argv[0])){ dr = js2irect(js, argv[0]); pdr = &dr; }
|
||||
|
||||
SDL_Surface *src = js2SDL_Surface(js, argv[1]);
|
||||
if (!src)
|
||||
return JS_ThrowReferenceError(js, "Argument must be a surface.");
|
||||
|
||||
irect sr = {0}, *psr = NULL;
|
||||
if(!JS_IsUndefined(argv[2])){ sr = js2irect(js, argv[2]); psr = &sr; }
|
||||
if(!JS_IsNull(argv[2])){ sr = js2irect(js, argv[2]); psr = &sr; }
|
||||
|
||||
SDL_ScaleMode mode = js2SDL_ScaleMode(js, argv[3]);
|
||||
|
||||
@@ -241,14 +241,14 @@ JSC_CCALL(surface_constructor,
|
||||
// Check for pixel format
|
||||
SDL_PixelFormat format = SDL_PIXELFORMAT_RGBA32; // default
|
||||
JSValue format_val = JS_GetPropertyStr(js, argv[0], "format");
|
||||
if (!JS_IsUndefined(format_val)) {
|
||||
if (!JS_IsNull(format_val)) {
|
||||
format = js2pixelformat(js, format_val);
|
||||
}
|
||||
JS_FreeValue(js, format_val);
|
||||
|
||||
// Check for pixel data
|
||||
JSValue pixels_val = JS_GetPropertyStr(js, argv[0], "pixels");
|
||||
if (!JS_IsUndefined(pixels_val)) {
|
||||
if (!JS_IsNull(pixels_val)) {
|
||||
// Create surface from pixel data
|
||||
size_t len;
|
||||
void *raw = js_get_blob_data(js, &len, pixels_val);
|
||||
@@ -261,7 +261,7 @@ JSC_CCALL(surface_constructor,
|
||||
// Get pitch if provided, otherwise calculate it
|
||||
int pitch;
|
||||
JSValue pitch_val = JS_GetPropertyStr(js, argv[0], "pitch");
|
||||
if (!JS_IsUndefined(pitch_val)) {
|
||||
if (!JS_IsNull(pitch_val)) {
|
||||
pitch = js2number(js, pitch_val);
|
||||
JS_FreeValue(js, pitch_val);
|
||||
} else {
|
||||
|
||||
@@ -87,7 +87,7 @@ static JSValue js_window_constructor(JSContext *js, JSValueConst new_target, int
|
||||
// Get basic properties (defaults are handled in JavaScript)
|
||||
const char *title = NULL;
|
||||
JSValue title_val = JS_GetPropertyStr(js, opts, "title");
|
||||
if (!JS_IsUndefined(title_val) && !JS_IsNull(title_val)) {
|
||||
if (!JS_IsNull(title_val) && !JS_IsNull(title_val)) {
|
||||
title = JS_ToCString(js, title_val);
|
||||
}
|
||||
JS_FreeValue(js, title_val);
|
||||
@@ -98,14 +98,14 @@ static JSValue js_window_constructor(JSContext *js, JSValueConst new_target, int
|
||||
|
||||
int width = 640;
|
||||
JSValue width_val = JS_GetPropertyStr(js, opts, "width");
|
||||
if (!JS_IsUndefined(width_val) && !JS_IsNull(width_val)) {
|
||||
if (!JS_IsNull(width_val) && !JS_IsNull(width_val)) {
|
||||
width = js2number(js, width_val);
|
||||
}
|
||||
JS_FreeValue(js, width_val);
|
||||
|
||||
int height = 480;
|
||||
JSValue height_val = JS_GetPropertyStr(js, opts, "height");
|
||||
if (!JS_IsUndefined(height_val) && !JS_IsNull(height_val)) {
|
||||
if (!JS_IsNull(height_val) && !JS_IsNull(height_val)) {
|
||||
height = js2number(js, height_val);
|
||||
}
|
||||
JS_FreeValue(js, height_val);
|
||||
@@ -120,7 +120,7 @@ static JSValue js_window_constructor(JSContext *js, JSValueConst new_target, int
|
||||
|
||||
// Handle window position
|
||||
JSValue x_val = JS_GetPropertyStr(js, opts, "x");
|
||||
if (!JS_IsUndefined(x_val)) {
|
||||
if (!JS_IsNull(x_val)) {
|
||||
if (JS_IsString(x_val)) {
|
||||
const char *pos = JS_ToCString(js, x_val);
|
||||
if (strcmp(pos, "centered") == 0)
|
||||
@@ -135,7 +135,7 @@ static JSValue js_window_constructor(JSContext *js, JSValueConst new_target, int
|
||||
JS_FreeValue(js, x_val);
|
||||
|
||||
JSValue y_val = JS_GetPropertyStr(js, opts, "y");
|
||||
if (!JS_IsUndefined(y_val)) {
|
||||
if (!JS_IsNull(y_val)) {
|
||||
if (JS_IsString(y_val)) {
|
||||
const char *pos = JS_ToCString(js, y_val);
|
||||
if (strcmp(pos, "centered") == 0)
|
||||
@@ -152,7 +152,7 @@ static JSValue js_window_constructor(JSContext *js, JSValueConst new_target, int
|
||||
// Helper function to check and set boolean properties
|
||||
#define SET_BOOL_PROP(js_name, sdl_prop) do { \
|
||||
JSValue val = JS_GetPropertyStr(js, opts, js_name); \
|
||||
if (!JS_IsUndefined(val)) { \
|
||||
if (!JS_IsNull(val)) { \
|
||||
SDL_SetBooleanProperty(props, sdl_prop, JS_ToBool(js, val)); \
|
||||
} \
|
||||
JS_FreeValue(js, val); \
|
||||
@@ -180,14 +180,14 @@ static JSValue js_window_constructor(JSContext *js, JSValueConst new_target, int
|
||||
|
||||
// Handle focusable (inverse logic)
|
||||
JSValue focusable_val = JS_GetPropertyStr(js, opts, "focusable");
|
||||
if (!JS_IsUndefined(focusable_val)) {
|
||||
if (!JS_IsNull(focusable_val)) {
|
||||
SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_FOCUSABLE_BOOLEAN, JS_ToBool(js, focusable_val));
|
||||
}
|
||||
JS_FreeValue(js, focusable_val);
|
||||
|
||||
// Handle notFocusable (for backwards compatibility)
|
||||
JSValue not_focusable_val = JS_GetPropertyStr(js, opts, "notFocusable");
|
||||
if (!JS_IsUndefined(not_focusable_val)) {
|
||||
if (!JS_IsNull(not_focusable_val)) {
|
||||
SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_FOCUSABLE_BOOLEAN, !JS_ToBool(js, not_focusable_val));
|
||||
}
|
||||
JS_FreeValue(js, not_focusable_val);
|
||||
@@ -196,7 +196,7 @@ static JSValue js_window_constructor(JSContext *js, JSValueConst new_target, int
|
||||
|
||||
// Handle parent window
|
||||
JSValue parent_val = JS_GetPropertyStr(js, opts, "parent");
|
||||
if (!JS_IsUndefined(parent_val) && !JS_IsNull(parent_val)) {
|
||||
if (!JS_IsNull(parent_val) && !JS_IsNull(parent_val)) {
|
||||
SDL_Window *parent = js2SDL_Window(js, parent_val);
|
||||
if (parent) {
|
||||
SDL_SetPointerProperty(props, SDL_PROP_WINDOW_CREATE_PARENT_POINTER, parent);
|
||||
@@ -224,22 +224,22 @@ static JSValue js_window_constructor(JSContext *js, JSValueConst new_target, int
|
||||
// These will be applied through the property setters
|
||||
|
||||
JSValue opacity_val = JS_GetPropertyStr(js, opts, "opacity");
|
||||
if (!JS_IsUndefined(opacity_val)) {
|
||||
if (!JS_IsNull(opacity_val)) {
|
||||
JS_SetPropertyStr(js, window_obj, "opacity", opacity_val);
|
||||
}
|
||||
|
||||
JSValue min_size_val = JS_GetPropertyStr(js, opts, "minimumSize");
|
||||
if (!JS_IsUndefined(min_size_val)) {
|
||||
if (!JS_IsNull(min_size_val)) {
|
||||
JS_SetPropertyStr(js, window_obj, "minimumSize", min_size_val);
|
||||
}
|
||||
|
||||
JSValue max_size_val = JS_GetPropertyStr(js, opts, "maximumSize");
|
||||
if (!JS_IsUndefined(max_size_val)) {
|
||||
if (!JS_IsNull(max_size_val)) {
|
||||
JS_SetPropertyStr(js, window_obj, "maximumSize", max_size_val);
|
||||
}
|
||||
|
||||
JSValue pos_val = JS_GetPropertyStr(js, opts, "position");
|
||||
if (!JS_IsUndefined(pos_val)) {
|
||||
if (!JS_IsNull(pos_val)) {
|
||||
JS_SetPropertyStr(js, window_obj, "position", pos_val);
|
||||
}
|
||||
|
||||
@@ -275,7 +275,7 @@ JSValue js_SDL_Window_keyboard_shown(JSContext *js, JSValue self) {
|
||||
|
||||
JSValue js_window_theme(JSContext *js, JSValue self)
|
||||
{
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
JSValue js_window_safe_area(JSContext *js, JSValue self)
|
||||
@@ -290,7 +290,7 @@ JSValue js_window_bordered(JSContext *js, JSValue self, int argc, JSValue *argv)
|
||||
{
|
||||
SDL_Window *w = js2SDL_Window(js,self);
|
||||
SDL_SetWindowBordered(w, JS_ToBool(js,argv[0]));
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
JSValue js_window_get_title(JSContext *js, JSValue self)
|
||||
@@ -306,7 +306,7 @@ JSValue js_window_set_title(JSContext *js, JSValue self, JSValue val)
|
||||
const char *title = JS_ToCString(js,val);
|
||||
SDL_SetWindowTitle(w,title);
|
||||
JS_FreeCString(js,title);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
JSValue js_window_get_size(JSContext *js, JSValue self)
|
||||
@@ -322,7 +322,7 @@ JSValue js_window_set_size(JSContext *js, JSValue self, JSValue val)
|
||||
SDL_Window *w = js2SDL_Window(js,self);
|
||||
HMM_Vec2 size = js2vec2(js,val);
|
||||
SDL_SetWindowSize(w,size.x,size.y);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
JSValue js_window_set_icon(JSContext *js, JSValue self, int argc, JSValue *argv)
|
||||
@@ -331,7 +331,7 @@ JSValue js_window_set_icon(JSContext *js, JSValue self, int argc, JSValue *argv)
|
||||
SDL_Surface *s = js2SDL_Surface(js,argv[0]);
|
||||
if (!SDL_SetWindowIcon(w,s))
|
||||
return JS_ThrowReferenceError(js, "could not set window icon: %s", SDL_GetError());
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
// Position getter/setter
|
||||
@@ -348,7 +348,7 @@ JSValue js_window_set_position(JSContext *js, JSValue self, JSValue val)
|
||||
SDL_Window *w = js2SDL_Window(js,self);
|
||||
HMM_Vec2 pos = js2vec2(js,val);
|
||||
SDL_SetWindowPosition(w,pos.x,pos.y);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
// Mouse grab getter/setter
|
||||
@@ -362,7 +362,7 @@ JSValue js_window_set_mouseGrab(JSContext *js, JSValue self, JSValue val)
|
||||
{
|
||||
SDL_Window *w = js2SDL_Window(js,self);
|
||||
SDL_SetWindowMouseGrab(w, JS_ToBool(js,val));
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
// Keyboard grab getter/setter
|
||||
@@ -376,7 +376,7 @@ JSValue js_window_set_keyboardGrab(JSContext *js, JSValue self, JSValue val)
|
||||
{
|
||||
SDL_Window *w = js2SDL_Window(js,self);
|
||||
SDL_SetWindowKeyboardGrab(w, JS_ToBool(js,val));
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
// Opacity getter/setter
|
||||
@@ -391,7 +391,7 @@ JSValue js_window_set_opacity(JSContext *js, JSValue self, JSValue val)
|
||||
SDL_Window *w = js2SDL_Window(js,self);
|
||||
float opacity = js2number(js,val);
|
||||
SDL_SetWindowOpacity(w, opacity);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
// Minimum size getter/setter
|
||||
@@ -408,7 +408,7 @@ JSValue js_window_set_minimumSize(JSContext *js, JSValue self, JSValue val)
|
||||
SDL_Window *w = js2SDL_Window(js,self);
|
||||
HMM_Vec2 size = js2vec2(js,val);
|
||||
SDL_SetWindowMinimumSize(w,size.x,size.y);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
// Maximum size getter/setter
|
||||
@@ -425,7 +425,7 @@ JSValue js_window_set_maximumSize(JSContext *js, JSValue self, JSValue val)
|
||||
SDL_Window *w = js2SDL_Window(js,self);
|
||||
HMM_Vec2 size = js2vec2(js,val);
|
||||
SDL_SetWindowMaximumSize(w,size.x,size.y);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
// Resizable setter (read from flags)
|
||||
@@ -440,7 +440,7 @@ JSValue js_window_set_resizable(JSContext *js, JSValue self, JSValue val)
|
||||
{
|
||||
SDL_Window *w = js2SDL_Window(js,self);
|
||||
SDL_SetWindowResizable(w, JS_ToBool(js,val));
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
// Bordered getter/setter
|
||||
@@ -455,7 +455,7 @@ JSValue js_window_set_bordered(JSContext *js, JSValue self, JSValue val)
|
||||
{
|
||||
SDL_Window *w = js2SDL_Window(js,self);
|
||||
SDL_SetWindowBordered(w, JS_ToBool(js,val));
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
// Always on top getter/setter
|
||||
@@ -470,7 +470,7 @@ JSValue js_window_set_alwaysOnTop(JSContext *js, JSValue self, JSValue val)
|
||||
{
|
||||
SDL_Window *w = js2SDL_Window(js,self);
|
||||
SDL_SetWindowAlwaysOnTop(w, JS_ToBool(js,val));
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
// Fullscreen getter/setter
|
||||
@@ -485,7 +485,7 @@ JSValue js_window_set_fullscreen(JSContext *js, JSValue self, JSValue val)
|
||||
{
|
||||
SDL_Window *w = js2SDL_Window(js,self);
|
||||
SDL_SetWindowFullscreen(w, JS_ToBool(js,val));
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
// Focusable setter
|
||||
@@ -500,7 +500,7 @@ JSValue js_window_set_focusable(JSContext *js, JSValue self, JSValue val)
|
||||
{
|
||||
SDL_Window *w = js2SDL_Window(js,self);
|
||||
SDL_SetWindowFocusable(w, JS_ToBool(js,val));
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
// Modal setter
|
||||
@@ -515,7 +515,7 @@ JSValue js_window_set_modal(JSContext *js, JSValue self, JSValue val)
|
||||
{
|
||||
SDL_Window *w = js2SDL_Window(js,self);
|
||||
SDL_SetWindowModal(w, JS_ToBool(js,val));
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
// Hidden/visible state
|
||||
@@ -533,7 +533,7 @@ JSValue js_window_set_visible(JSContext *js, JSValue self, JSValue val)
|
||||
SDL_ShowWindow(w);
|
||||
else
|
||||
SDL_HideWindow(w);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
// Minimized state
|
||||
@@ -551,7 +551,7 @@ JSValue js_window_set_minimized(JSContext *js, JSValue self, JSValue val)
|
||||
SDL_MinimizeWindow(w);
|
||||
else
|
||||
SDL_RestoreWindow(w);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
// Maximized state
|
||||
@@ -569,7 +569,7 @@ JSValue js_window_set_maximized(JSContext *js, JSValue self, JSValue val)
|
||||
SDL_MaximizeWindow(w);
|
||||
else
|
||||
SDL_RestoreWindow(w);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
// Other window methods
|
||||
@@ -577,14 +577,14 @@ JSValue js_window_raise(JSContext *js, JSValue self, int argc, JSValue *argv)
|
||||
{
|
||||
SDL_Window *w = js2SDL_Window(js,self);
|
||||
SDL_RaiseWindow(w);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
JSValue js_window_restore(JSContext *js, JSValue self, int argc, JSValue *argv)
|
||||
{
|
||||
SDL_Window *w = js2SDL_Window(js,self);
|
||||
SDL_RestoreWindow(w);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
JSValue js_window_flash(JSContext *js, JSValue self, int argc, JSValue *argv)
|
||||
@@ -599,14 +599,14 @@ JSValue js_window_flash(JSContext *js, JSValue self, int argc, JSValue *argv)
|
||||
JS_FreeCString(js,operation);
|
||||
}
|
||||
SDL_FlashWindow(w, op);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
JSValue js_window_destroy(JSContext *js, JSValue self, int argc, JSValue *argv)
|
||||
{
|
||||
SDL_Window *w = js2SDL_Window(js,self);
|
||||
SDL_DestroyWindow(w);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
JSValue js_window_get_id(JSContext *js, JSValue self)
|
||||
@@ -627,10 +627,10 @@ JSValue js_window_set_parent(JSContext *js, JSValue self, JSValue val)
|
||||
{
|
||||
SDL_Window *w = js2SDL_Window(js,self);
|
||||
SDL_Window *parent = NULL;
|
||||
if (!JS_IsNull(val) && !JS_IsUndefined(val))
|
||||
if (!JS_IsNull(val) && !JS_IsNull(val))
|
||||
parent = js2SDL_Window(js,val);
|
||||
SDL_SetWindowParent(w, parent);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
JSValue js_window_get_pixelDensity(JSContext *js, JSValue self)
|
||||
@@ -667,7 +667,7 @@ JSValue js_window_updateSurface(JSContext *js, JSValue self, int argc, JSValue *
|
||||
SDL_Window *w = js2SDL_Window(js,self);
|
||||
if (!SDL_UpdateWindowSurface(w))
|
||||
return JS_ThrowReferenceError(js, "Failed to update window surface: %s", SDL_GetError());
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
JSValue js_window_updateSurfaceRects(JSContext *js, JSValue self, int argc, JSValue *argv)
|
||||
@@ -689,7 +689,7 @@ JSValue js_window_updateSurfaceRects(JSContext *js, JSValue self, int argc, JSVa
|
||||
|
||||
if (!SDL_UpdateWindowSurfaceRects(w, rects, len))
|
||||
return JS_ThrowReferenceError(js, "Failed to update window surface rects: %s", SDL_GetError());
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
JSValue js_window_get_flags(JSContext *js, JSValue self)
|
||||
@@ -702,7 +702,7 @@ JSValue js_window_sync(JSContext *js, JSValue self, int argc, JSValue *argv)
|
||||
{
|
||||
SDL_Window *w = js2SDL_Window(js,self);
|
||||
SDL_SyncWindow(w);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
static const JSCFunctionListEntry js_SDL_Window_funcs[] = {
|
||||
@@ -768,7 +768,7 @@ JSC_CCALL(renderer_load_texture,
|
||||
JSC_CCALL(renderer_get_image,
|
||||
SDL_Renderer *r = js2SDL_Renderer(js,self);
|
||||
SDL_Surface *surf = NULL;
|
||||
if (!JS_IsUndefined(argv[0])) {
|
||||
if (!JS_IsNull(argv[0])) {
|
||||
rect rect = js2rect(js,argv[0]);
|
||||
surf = SDL_RenderReadPixels(r,&rect);
|
||||
} else
|
||||
@@ -812,7 +812,7 @@ JSC_CCALL(renderer_point,
|
||||
pts[i] = (SDL_FPoint){pt.x, pt.y};
|
||||
}
|
||||
SDL_RenderPoints(r, pts, len);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
HMM_Vec2 pt = js2vec2(js, argv[0]);
|
||||
@@ -839,7 +839,7 @@ JSC_CCALL(renderer_rects,
|
||||
/* array-of-rectangles case */
|
||||
if (JS_IsArray(js, argv[0])) {
|
||||
int len = JS_ArrayLength(js, argv[0]);
|
||||
if (len <= 0) return JS_UNDEFINED;
|
||||
if (len <= 0) return JS_NULL;
|
||||
|
||||
SDL_FRect rects[len];
|
||||
|
||||
@@ -852,7 +852,7 @@ JSC_CCALL(renderer_rects,
|
||||
|
||||
if (!SDL_RenderFillRects(r, rects, len))
|
||||
return JS_ThrowReferenceError(js, "SDL_RenderFillRects: %s", SDL_GetError());
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
/* single-rect path */
|
||||
@@ -893,7 +893,7 @@ JSC_CCALL(renderer_geometry_raw,
|
||||
|
||||
// argv[0] is texture
|
||||
SDL_Texture *tex = NULL;
|
||||
if (argc > 0 && !JS_IsNull(argv[0]) && !JS_IsUndefined(argv[0]))
|
||||
if (argc > 0 && !JS_IsNull(argv[0]) && !JS_IsNull(argv[0]))
|
||||
tex = js2SDL_Texture(js,argv[0]);
|
||||
|
||||
// Get blob data
|
||||
@@ -1045,7 +1045,7 @@ static JSValue logicalpresentation2js(JSContext *js,
|
||||
|
||||
static SDL_RendererLogicalPresentation
|
||||
js2SDL_LogicalPresentation(JSContext *js, JSValue v){
|
||||
if(JS_IsUndefined(v)) return SDL_LOGICAL_PRESENTATION_DISABLED;
|
||||
if(JS_IsNull(v)) return SDL_LOGICAL_PRESENTATION_DISABLED;
|
||||
const char *s = JS_ToCString(js, v);
|
||||
if(!s) return SDL_LOGICAL_PRESENTATION_DISABLED;
|
||||
const pres_entry *it;
|
||||
@@ -1069,13 +1069,13 @@ JSValue js_renderer_get_target(JSContext *js, JSValue self)
|
||||
JSValue js_renderer_set_target(JSContext *js, JSValue self, JSValue val)
|
||||
{
|
||||
SDL_Renderer *r = js2SDL_Renderer(js,self);
|
||||
if (JS_IsNull(val) || JS_IsUndefined(val))
|
||||
if (JS_IsNull(val) || JS_IsNull(val))
|
||||
SDL_SetRenderTarget(r, NULL);
|
||||
else {
|
||||
SDL_Texture *tex = js2SDL_Texture(js,val);
|
||||
SDL_SetRenderTarget(r,tex);
|
||||
}
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
// Logical presentation getter/setter
|
||||
@@ -1101,7 +1101,7 @@ JSValue js_renderer_set_logicalPresentation(JSContext *js, JSValue self, JSValue
|
||||
SDL_RendererLogicalPresentation mode = js2SDL_LogicalPresentation(js, mode_val);
|
||||
JS_FreeValue(js, mode_val);
|
||||
SDL_SetRenderLogicalPresentation(r, w, h, mode);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
// Viewport getter/setter
|
||||
@@ -1116,13 +1116,13 @@ JSValue js_renderer_get_viewport(JSContext *js, JSValue self)
|
||||
JSValue js_renderer_set_viewport(JSContext *js, JSValue self, JSValue val)
|
||||
{
|
||||
SDL_Renderer *r = js2SDL_Renderer(js,self);
|
||||
if (JS_IsNull(val) || JS_IsUndefined(val))
|
||||
if (JS_IsNull(val) || JS_IsNull(val))
|
||||
SDL_SetRenderViewport(r,NULL);
|
||||
else {
|
||||
rect view = js2rect(js,val);
|
||||
SDL_SetRenderViewport(r,&view);
|
||||
}
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
// Clip rect getter/setter
|
||||
@@ -1137,13 +1137,13 @@ JSValue js_renderer_get_clipRect(JSContext *js, JSValue self)
|
||||
JSValue js_renderer_set_clipRect(JSContext *js, JSValue self, JSValue val)
|
||||
{
|
||||
SDL_Renderer *r = js2SDL_Renderer(js,self);
|
||||
if (JS_IsNull(val) || JS_IsUndefined(val))
|
||||
if (JS_IsNull(val) || JS_IsNull(val))
|
||||
SDL_SetRenderClipRect(r,NULL);
|
||||
else {
|
||||
rect clip = js2rect(js,val);
|
||||
SDL_SetRenderClipRect(r,&clip);
|
||||
}
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
// Scale getter/setter
|
||||
@@ -1160,7 +1160,7 @@ JSValue js_renderer_set_scale(JSContext *js, JSValue self, JSValue val)
|
||||
SDL_Renderer *r = js2SDL_Renderer(js,self);
|
||||
HMM_Vec2 scale = js2vec2(js,val);
|
||||
SDL_SetRenderScale(r, scale.x, scale.y);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
// Draw color getter/setter (float version)
|
||||
@@ -1182,7 +1182,7 @@ JSValue js_renderer_set_drawColor(JSContext *js, JSValue self, JSValue val)
|
||||
SDL_Renderer *r = js2SDL_Renderer(js,self);
|
||||
colorf color = js2color(js,val);
|
||||
SDL_SetRenderDrawColorFloat(r, color.r, color.g, color.b, color.a);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
// Color scale getter/setter
|
||||
@@ -1199,7 +1199,7 @@ JSValue js_renderer_set_colorScale(JSContext *js, JSValue self, JSValue val)
|
||||
SDL_Renderer *r = js2SDL_Renderer(js,self);
|
||||
float scale = js2number(js,val);
|
||||
SDL_SetRenderColorScale(r, scale);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
// Draw blend mode getter/setter
|
||||
@@ -1216,7 +1216,7 @@ JSValue js_renderer_set_drawBlendMode(JSContext *js, JSValue self, JSValue val)
|
||||
SDL_Renderer *r = js2SDL_Renderer(js,self);
|
||||
SDL_BlendMode mode = js2blendmode(js,val);
|
||||
SDL_SetRenderDrawBlendMode(r, mode);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
// VSync getter/setter
|
||||
@@ -1233,7 +1233,7 @@ JSValue js_renderer_set_vsync(JSContext *js, JSValue self, JSValue val)
|
||||
SDL_Renderer *r = js2SDL_Renderer(js,self);
|
||||
int vsync = js2number(js,val);
|
||||
SDL_SetRenderVSync(r, vsync);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
// Read-only properties
|
||||
@@ -1360,7 +1360,7 @@ JSC_CCALL(renderer_textureTiled,
|
||||
SDL_Texture *tex = js2SDL_Texture(js, argv[0]);
|
||||
|
||||
rect src_rect = {0};
|
||||
if (argc > 1 && !JS_IsNull(argv[1]) && !JS_IsUndefined(argv[1]))
|
||||
if (argc > 1 && !JS_IsNull(argv[1]) && !JS_IsNull(argv[1]))
|
||||
src_rect = js2rect(js, argv[1]);
|
||||
|
||||
float scale = 1.0f;
|
||||
@@ -1368,7 +1368,7 @@ JSC_CCALL(renderer_textureTiled,
|
||||
scale = js2number(js, argv[2]);
|
||||
|
||||
rect dst_rect = {0};
|
||||
if (argc > 3 && !JS_IsNull(argv[3]) && !JS_IsUndefined(argv[3]))
|
||||
if (argc > 3 && !JS_IsNull(argv[3]) && !JS_IsNull(argv[3]))
|
||||
dst_rect = js2rect(js, argv[3]);
|
||||
|
||||
if (!SDL_RenderTextureTiled(r, tex,
|
||||
@@ -1393,7 +1393,7 @@ JSC_CCALL(renderer_debugText,
|
||||
JSC_CCALL(renderer_readPixels,
|
||||
SDL_Renderer *r = js2SDL_Renderer(js,self);
|
||||
rect read_rect = {0};
|
||||
if (argc >= 1 && !JS_IsNull(argv[0]) && !JS_IsUndefined(argv[0]))
|
||||
if (argc >= 1 && !JS_IsNull(argv[0]) && !JS_IsNull(argv[0]))
|
||||
read_rect = js2rect(js, argv[0]);
|
||||
|
||||
SDL_Surface *surf = SDL_RenderReadPixels(r,
|
||||
@@ -1513,13 +1513,13 @@ static JSValue js_texture_constructor(JSContext *js, JSValueConst new_target, in
|
||||
|
||||
JSValue format_val = JS_GetPropertyStr(js, obj, "format");
|
||||
SDL_PixelFormat format = SDL_PIXELFORMAT_RGBA8888;
|
||||
if (!JS_IsUndefined(format_val))
|
||||
if (!JS_IsNull(format_val))
|
||||
format = js2pixelformat(js, format_val);
|
||||
JS_FreeValue(js, format_val);
|
||||
|
||||
// Check for pixels data
|
||||
JSValue pixels_val = JS_GetPropertyStr(js, obj, "pixels");
|
||||
if (!JS_IsUndefined(pixels_val)) {
|
||||
if (!JS_IsNull(pixels_val)) {
|
||||
// Create surface first, then texture
|
||||
size_t size;
|
||||
uint8_t *pixels = js_get_blob_data(js, &size, pixels_val);
|
||||
@@ -1611,7 +1611,7 @@ JSValue js_texture_set_alphaMod(JSContext *js, JSValue self, JSValue val)
|
||||
SDL_Texture *tex = js2SDL_Texture(js,self);
|
||||
float alpha = js2number(js,val);
|
||||
SDL_SetTextureAlphaModFloat(tex, alpha);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
// Color mod getter/setter
|
||||
@@ -1632,7 +1632,7 @@ JSValue js_texture_set_colorMod(JSContext *js, JSValue self, JSValue val)
|
||||
SDL_Texture *tex = js2SDL_Texture(js,self);
|
||||
colorf color = js2color(js,val);
|
||||
SDL_SetTextureColorModFloat(tex, color.r, color.g, color.b);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
// Blend mode getter/setter
|
||||
@@ -1649,7 +1649,7 @@ JSValue js_texture_set_blendMode(JSContext *js, JSValue self, JSValue val)
|
||||
SDL_Texture *tex = js2SDL_Texture(js,self);
|
||||
SDL_BlendMode mode = js2blendmode(js,val);
|
||||
SDL_SetTextureBlendMode(tex, mode);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
// Scale mode getter/setter
|
||||
@@ -1668,7 +1668,7 @@ JSValue js_texture_set_scaleMode(JSContext *js, JSValue self, JSValue val)
|
||||
SDL_Texture *tex = js2SDL_Texture(js,self);
|
||||
SDL_ScaleMode mode = js2SDL_ScaleMode(js,val);
|
||||
SDL_SetTextureScaleMode(tex, mode);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
// Size getter (read-only)
|
||||
@@ -1687,7 +1687,7 @@ JSC_CCALL(texture_update,
|
||||
void *pixels = NULL;
|
||||
int pitch = 0;
|
||||
|
||||
if (argc >= 1 && !JS_IsNull(argv[0]) && !JS_IsUndefined(argv[0]))
|
||||
if (argc >= 1 && !JS_IsNull(argv[0]) && !JS_IsNull(argv[0]))
|
||||
update_rect = js2rect(js, argv[0]);
|
||||
|
||||
if (argc >= 2) {
|
||||
@@ -1713,7 +1713,7 @@ JSC_CCALL(texture_lock,
|
||||
void *pixels;
|
||||
int pitch;
|
||||
|
||||
if (argc >= 1 && !JS_IsNull(argv[0]) && !JS_IsUndefined(argv[0]))
|
||||
if (argc >= 1 && !JS_IsNull(argv[0]) && !JS_IsNull(argv[0]))
|
||||
lock_rect = js2rect(js, argv[0]);
|
||||
|
||||
if (!SDL_LockTexture(tex,
|
||||
|
||||
@@ -35,10 +35,10 @@ JSC_CCALL(socket_getaddrinfo,
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
|
||||
if (!JS_IsNull(argv[0]) && !JS_IsUndefined(argv[0]))
|
||||
if (!JS_IsNull(argv[0]) && !JS_IsNull(argv[0]))
|
||||
node = JS_ToCString(js, argv[0]);
|
||||
|
||||
if (!JS_IsNull(argv[1]) && !JS_IsUndefined(argv[1]))
|
||||
if (!JS_IsNull(argv[1]) && !JS_IsNull(argv[1]))
|
||||
service = JS_ToCString(js, argv[1]);
|
||||
|
||||
// Parse optional hints object
|
||||
@@ -46,7 +46,7 @@ JSC_CCALL(socket_getaddrinfo,
|
||||
JSValue val;
|
||||
|
||||
val = JS_GetPropertyStr(js, argv[2], "family");
|
||||
if (!JS_IsUndefined(val)) {
|
||||
if (!JS_IsNull(val)) {
|
||||
const char *family = JS_ToCString(js, val);
|
||||
if (strcmp(family, "AF_INET") == 0) hints.ai_family = AF_INET;
|
||||
else if (strcmp(family, "AF_INET6") == 0) hints.ai_family = AF_INET6;
|
||||
@@ -55,7 +55,7 @@ JSC_CCALL(socket_getaddrinfo,
|
||||
JS_FreeValue(js, val);
|
||||
|
||||
val = JS_GetPropertyStr(js, argv[2], "socktype");
|
||||
if (!JS_IsUndefined(val)) {
|
||||
if (!JS_IsNull(val)) {
|
||||
const char *socktype = JS_ToCString(js, val);
|
||||
if (strcmp(socktype, "SOCK_STREAM") == 0) hints.ai_socktype = SOCK_STREAM;
|
||||
else if (strcmp(socktype, "SOCK_DGRAM") == 0) hints.ai_socktype = SOCK_DGRAM;
|
||||
@@ -64,7 +64,7 @@ JSC_CCALL(socket_getaddrinfo,
|
||||
JS_FreeValue(js, val);
|
||||
|
||||
val = JS_GetPropertyStr(js, argv[2], "flags");
|
||||
if (!JS_IsUndefined(val)) {
|
||||
if (!JS_IsNull(val)) {
|
||||
hints.ai_flags = js2number(js, val);
|
||||
}
|
||||
JS_FreeValue(js, val);
|
||||
@@ -192,7 +192,7 @@ JSC_CCALL(socket_bind,
|
||||
}
|
||||
}
|
||||
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
)
|
||||
|
||||
JSC_CCALL(socket_connect,
|
||||
@@ -220,7 +220,7 @@ JSC_CCALL(socket_connect,
|
||||
}
|
||||
}
|
||||
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
)
|
||||
|
||||
JSC_CCALL(socket_listen,
|
||||
@@ -236,7 +236,7 @@ JSC_CCALL(socket_listen,
|
||||
return JS_ThrowReferenceError(js, "listen failed: %s", strerror(errno));
|
||||
}
|
||||
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
)
|
||||
|
||||
JSC_CCALL(socket_accept,
|
||||
@@ -448,7 +448,7 @@ JSC_CCALL(socket_shutdown,
|
||||
return JS_ThrowReferenceError(js, "shutdown failed: %s", strerror(errno));
|
||||
}
|
||||
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
)
|
||||
|
||||
JSC_CCALL(socket_getpeername,
|
||||
@@ -538,7 +538,7 @@ JSC_CCALL(socket_setsockopt,
|
||||
return JS_ThrowTypeError(js, "Invalid option value");
|
||||
}
|
||||
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
)
|
||||
|
||||
JSC_CCALL(socket_close,
|
||||
@@ -548,7 +548,7 @@ JSC_CCALL(socket_close,
|
||||
if (close(sockfd) != 0)
|
||||
return JS_ThrowReferenceError(js, "close failed: %s", strerror(errno));
|
||||
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
)
|
||||
|
||||
static const JSCFunctionListEntry js_socket_funcs[] = {
|
||||
|
||||
@@ -147,7 +147,7 @@ static const JSCFunctionListEntry *js_Wav_funcs;
|
||||
static JSValue js_voice_set_##ENTRY (JSContext *js, JSValueConst self, JSValue val) { \
|
||||
unsigned int voice = *js2voice(js, self); \
|
||||
Soloud_set##ENTRY(soloud, voice, js2##TYPE(js, val)); \
|
||||
return JS_UNDEFINED; \
|
||||
return JS_NULL; \
|
||||
} \
|
||||
static JSValue js_voice_get_##ENTRY (JSContext *js, JSValueConst self) { \
|
||||
unsigned int voice = *js2voice(js,self); \
|
||||
@@ -158,14 +158,14 @@ static JSValue js_voice_seek(JSContext *js, JSValue self, int argc, JSValue *arg
|
||||
{
|
||||
unsigned int voice = *js2voice(js, self);
|
||||
Soloud_seek(soloud, voice, js2number(js, argv[0]));
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
static JSValue js_voice_stop(JSContext *js, JSValue self, int argc, JSValue *argv)
|
||||
{
|
||||
unsigned int voice = *js2voice(js, self);
|
||||
Soloud_stop(soloud, voice);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
static JSValue js_voice_setInaudibleBehavior(JSContext *js, JSValueConst self, int argc, JSValue *argv)
|
||||
@@ -174,7 +174,7 @@ static JSValue js_voice_setInaudibleBehavior(JSContext *js, JSValueConst self, i
|
||||
int mustTick = js2bool(js, argv[0]);
|
||||
int kill = js2bool(js, argv[1]);
|
||||
Soloud_setInaudibleBehavior(soloud, voice, mustTick, kill);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
SOLOUD_GETSET(Volume, number);
|
||||
|
||||
@@ -31,7 +31,7 @@ JSC_CCALL(spline_catmull,
|
||||
HMM_Vec2 *samples = catmull_rom_ma_v2(points, param);
|
||||
|
||||
if (!samples)
|
||||
ret = JS_UNDEFINED;
|
||||
ret = JS_NULL;
|
||||
else
|
||||
ret = vecarr2js(js, samples, arrlen(samples));
|
||||
|
||||
@@ -45,7 +45,7 @@ JSC_CCALL(spline_bezier,
|
||||
HMM_Vec2 *samples = bezier_cb_ma_v2(points, param);
|
||||
|
||||
if (!samples)
|
||||
ret = JS_UNDEFINED;
|
||||
ret = JS_NULL;
|
||||
else
|
||||
ret = vecarr2js(js, samples, arrlen(samples));
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ JSC_CCALL(sprite_set_affine,
|
||||
|
||||
JSC_CCALL(sprite_set_image,
|
||||
sprite *sp = js2sprite(js,self);
|
||||
if (!JS_IsUndefined(sp->image))
|
||||
if (!JS_IsNull(sp->image))
|
||||
JS_FreeValue(js,sp->image);
|
||||
sp->image = JS_DupValue(js, argv[0]);
|
||||
)
|
||||
@@ -75,7 +75,7 @@ static JSValue js_sprite_constructor(JSContext *js, JSValueConst new_target, int
|
||||
JS_GETATOM(js, sp->color, argv[0], color, color)
|
||||
|
||||
JSValue image = JS_GetProperty(js, argv[0], JS_NewAtom(js, "image"));
|
||||
if (!JS_IsUndefined(image)) {
|
||||
if (!JS_IsNull(image)) {
|
||||
sp->image = image; // Transfer ownership, no need to dup
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,14 +49,14 @@ JSC_CCALL(steam_shutdown,
|
||||
SteamAPI_Shutdown();
|
||||
steam_initialized = false;
|
||||
}
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
)
|
||||
|
||||
JSC_CCALL(steam_run_callbacks,
|
||||
if (steam_initialized) {
|
||||
SteamAPI_RunCallbacks();
|
||||
}
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
)
|
||||
|
||||
// USER STATS & ACHIEVEMENTS
|
||||
@@ -84,7 +84,7 @@ JSC_CCALL(stats_get_int,
|
||||
bool success = SteamAPI_ISteamUserStats_GetStatInt32(steam_stats, name, &value);
|
||||
JS_FreeCString(js, name);
|
||||
|
||||
if (!success) return JS_UNDEFINED;
|
||||
if (!success) return JS_NULL;
|
||||
return JS_NewInt32(js, value);
|
||||
)
|
||||
|
||||
@@ -98,7 +98,7 @@ JSC_CCALL(stats_get_float,
|
||||
bool success = SteamAPI_ISteamUserStats_GetStatFloat(steam_stats, name, &value);
|
||||
JS_FreeCString(js, name);
|
||||
|
||||
if (!success) return JS_UNDEFINED;
|
||||
if (!success) return JS_NULL;
|
||||
return JS_NewFloat64(js, value);
|
||||
)
|
||||
|
||||
@@ -143,7 +143,7 @@ JSC_CCALL(achievement_get,
|
||||
bool success = SteamAPI_ISteamUserStats_GetAchievement(steam_stats, name, &achieved);
|
||||
JS_FreeCString(js, name);
|
||||
|
||||
if (!success) return JS_UNDEFINED;
|
||||
if (!success) return JS_NULL;
|
||||
return JS_NewBool(js, achieved);
|
||||
)
|
||||
|
||||
@@ -185,7 +185,7 @@ JSC_CCALL(achievement_name,
|
||||
JS_ToUint32(js, &index, argv[0]);
|
||||
|
||||
const char *name = SteamAPI_ISteamUserStats_GetAchievementName(steam_stats, index);
|
||||
if (!name) return JS_UNDEFINED;
|
||||
if (!name) return JS_NULL;
|
||||
|
||||
return JS_NewString(js, name);
|
||||
)
|
||||
@@ -307,7 +307,7 @@ JSC_CCALL(cloud_enable,
|
||||
|
||||
bool enable = JS_ToBool(js, argv[0]);
|
||||
SteamAPI_ISteamRemoteStorage_SetCloudEnabledForApp(steam_remote, enable);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
)
|
||||
|
||||
JSC_CCALL(cloud_quota,
|
||||
@@ -316,7 +316,7 @@ JSC_CCALL(cloud_quota,
|
||||
uint64 total, available;
|
||||
bool success = SteamAPI_ISteamRemoteStorage_GetQuota(steam_remote, &total, &available);
|
||||
|
||||
if (!success) return JS_UNDEFINED;
|
||||
if (!success) return JS_NULL;
|
||||
|
||||
JSValue obj = JS_NewObject(js);
|
||||
JS_SetPropertyStr(js, obj, "total", JS_NewBigUint64(js, total));
|
||||
@@ -367,7 +367,7 @@ JSC_CCALL(cloud_read,
|
||||
int32 size = SteamAPI_ISteamRemoteStorage_GetFileSize(steam_remote, filename);
|
||||
if (size <= 0) {
|
||||
JS_FreeCString(js, filename);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
uint8_t *buffer = (uint8_t*)js_malloc(js, size);
|
||||
@@ -381,7 +381,7 @@ JSC_CCALL(cloud_read,
|
||||
|
||||
if (read != size) {
|
||||
js_free(js, buffer);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
JSValue result = js_new_blob_stoned_copy(js, buffer, size);
|
||||
@@ -509,6 +509,6 @@ extern "C" JSValue js_steam_use(JSContext *js) {
|
||||
#else
|
||||
// Stub when Steam is disabled
|
||||
extern "C" JSValue js_steam_use(JSContext *js) {
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -35,23 +35,23 @@ static JSValue js_transform_get_change_hook(JSContext *js, JSValueConst self)
|
||||
static JSValue js_transform_set_change_hook(JSContext *js, JSValueConst self, JSValue v)
|
||||
{
|
||||
transform *t = js2transform(js,self);
|
||||
if (!JS_IsUndefined(v) && !JS_IsFunction(js,v)) return JS_ThrowReferenceError(js, "Hook must be a function.");
|
||||
if (!JS_IsNull(v) && !JS_IsFunction(js,v)) return JS_ThrowReferenceError(js, "Hook must be a function.");
|
||||
JS_FreeValue(js,t->change_hook);
|
||||
t->change_hook = JS_DupValue(js,v);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
static JSValue js_transform_get_parent(JSContext *js, JSValueConst self)
|
||||
{
|
||||
transform *t = js2transform(js,self);
|
||||
if (t->parent) return JS_DupValue(js,t->jsparent);
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
static JSValue js_transform_set_parent(JSContext *js, JSValueConst self, JSValue v)
|
||||
{
|
||||
transform *p = js2transform(js,v);
|
||||
if (!JS_IsUndefined(v) && !p)
|
||||
if (!JS_IsNull(v) && !p)
|
||||
return JS_ThrowReferenceError(js,"Parent must be another transform.");
|
||||
|
||||
transform *t = js2transform(js,self);
|
||||
@@ -62,7 +62,7 @@ static JSValue js_transform_set_parent(JSContext *js, JSValueConst self, JSValue
|
||||
if (t->parent) {
|
||||
transform *cur_parent = t->parent;
|
||||
JS_FreeValue(js,t->jsparent);
|
||||
t->jsparent = JS_UNDEFINED;
|
||||
t->jsparent = JS_NULL;
|
||||
|
||||
for (int i = 0; i < arrlen(cur_parent->children); i++) {
|
||||
if (cur_parent->children[i] == t) {
|
||||
@@ -91,7 +91,7 @@ static JSValue js_transform_set_parent(JSContext *js, JSValueConst self, JSValue
|
||||
|
||||
transform_apply(t);
|
||||
|
||||
return JS_UNDEFINED;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
// TRANSFORM ACTION FUNCTIONS
|
||||
@@ -152,9 +152,9 @@ JSC_CCALL(transform_unit,
|
||||
|
||||
JSC_CCALL(transform_trs,
|
||||
transform *t = js2transform(js,self);
|
||||
t->pos = JS_IsUndefined(argv[0]) ? v3zero : js2vec3(js,argv[0]);
|
||||
t->rotation = JS_IsUndefined(argv[1]) ? QUAT1 : js2quat(js,argv[1]);
|
||||
t->scale = JS_IsUndefined(argv[2]) ? v3one : js2vec3(js,argv[2]);
|
||||
t->pos = JS_IsNull(argv[0]) ? v3zero : js2vec3(js,argv[0]);
|
||||
t->rotation = JS_IsNull(argv[1]) ? QUAT1 : js2quat(js,argv[1]);
|
||||
t->scale = JS_IsNull(argv[2]) ? v3one : js2vec3(js,argv[2]);
|
||||
transform_apply(t);
|
||||
)
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user