Skip to content

Commit

Permalink
Fix more tests
Browse files Browse the repository at this point in the history
  • Loading branch information
hoodmane committed Oct 22, 2023
1 parent a02466b commit 4019571
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 55 deletions.
26 changes: 0 additions & 26 deletions src/core/hiwire.c
Original file line number Diff line number Diff line change
Expand Up @@ -463,32 +463,6 @@ hiwire_get_length(JsRef idobj)
return -1;
}

EM_JS_BOOL(bool, hiwire_get_bool, (JsRef idobj), {
let val = Hiwire.get_value(idobj);
// clang-format off
if (!val) {
return false;
}
// We want to return false on container types with size 0.
if (val.size === 0) {
if(/HTML[A-Za-z]*Element/.test(getTypeTag(val))){
// HTMLSelectElement and HTMLInputElement can have size 0 but we still
// want to return true.
return true;
}
// I think other things with a size are container types.
return false;
}
if (val.length === 0 && JsArray_Check(idobj)) {
return false;
}
if (val.byteLength === 0) {
return false;
}
return true;
// clang-format on
});

EM_JS_BOOL(bool, hiwire_is_generator, (JsRef idobj), {
// clang-format off
return getTypeTag(Hiwire.get_value(idobj)) === "[object Generator]";
Expand Down
33 changes: 26 additions & 7 deletions src/core/jslib.c
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
#include "jslib.h"
#include "error_handling.h"
#include "jsmemops.h"

// ==================== Conversions between JsRef and JsVal ====================

JsVal
Jsv_pop_ref(JsRef ref)
JsRef_pop(JsRef ref)
{
if (ref == NULL) {
return JS_NULL;
Expand All @@ -11,14 +14,24 @@ Jsv_pop_ref(JsRef ref)
}

JsVal
Jsv_from_ref(JsRef ref)
JsRef_toVal(JsRef ref)
{
if (ref == NULL) {
return JS_NULL;
}
return hiwire_get(ref);
}

JsRef
JsRef_new(JsVal v) {
if (JsvNull_Check(v)) {
return NULL;
}
return hiwire_new(v);
}

// ==================== Primitive Conversions ====================

EM_JS(JsVal, JsvInt, (int x), { return x; })

EM_JS(bool, Jsv_to_bool, (JsVal x), { return !!x; })
Expand Down Expand Up @@ -56,7 +69,13 @@ EM_JS_BOOL(bool, JsvArray_Check, (JsVal obj), {
});

EM_JS_VAL(JsVal, JsvArray_Get, (JsVal arr, int idx), {
return nullToUndefined(arr[idx]);
const result = arr[idx];
// clang-format off
if (result === undefined && !(idx in arr)) {
// clang-format on
return null;
}
return nullToUndefined(result);
});

EM_JS_NUM(errcode, JsvArray_Set, (JsVal arr, int idx, JsVal val), {
Expand All @@ -67,16 +86,16 @@ EM_JS_VAL(JsVal, JsvArray_Delete, (JsVal arr, int idx), {
// Weird edge case: allow deleting an empty entry, but we raise a key error if
// access is attempted.
if (idx < 0 || idx >= arr.length) {
return ERROR_NUM;
return null;
}
return arr.splice(idx, 1)[0];
});

// clang-format off
EM_JS(int, JsvArray_Push, (JsVal arr, JsVal obj), {
return arr.push(obj);
});

// clang-format off
EM_JS(void, JsvArray_Extend, (JsVal arr, JsVal vals), {
arr.push(...vals);
});
Expand Down Expand Up @@ -117,11 +136,11 @@ JsvArray_slice_assign,
obj.splice(start, slicelength, ...jsvalues);
} else {
if(values !== 0) {
for(const i = 0; i < slicelength; i ++){
for(let i = 0; i < slicelength; i ++){
obj.splice(start + i * step, 1, jsvalues[i]);
}
} else {
for(const i = slicelength - 1; i >= 0; i --){
for(let i = slicelength - 1; i >= 0; i --){
obj.splice(start + i * step, 1);
}
}
Expand Down
24 changes: 22 additions & 2 deletions src/core/jslib.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,25 @@
#define JSLIB_H
#include "hiwire.h"

// ==================== JS_NULL ====================

#define JS_NULL __builtin_wasm_ref_null_extern()

int JsvNull_Check(JsVal);

// ==================== Conversions between JsRef and JsVal ====================

JsRef
JsRef_new(JsVal v);

JsVal
Jsv_pop_ref(JsRef ref);
JsRef_pop(JsRef ref);

JsVal
Jsv_from_ref(JsRef ref);
JsRef_toVal(JsRef ref);


// ==================== Primitive Conversions ====================

JsVal
JsvInt(int x);
Expand All @@ -21,6 +31,8 @@ Jsv_to_bool(JsVal x);
JsVal
JsvUTF8ToString(const char*);

// ==================== JsvArray API ====================

JsVal
JsvArray_New();

Expand Down Expand Up @@ -55,6 +67,9 @@ JsvArray_slice_assign(JsVal idobj,
int values_length,
PyObject** values);


// ==================== JsvObject API ====================

JsVal
JsvObject_New();

Expand All @@ -76,6 +91,9 @@ JsvObject_CallMethodId_TwoArgs(JsVal obj,
JsVal arg1,
JsVal arg2);


// ==================== JsvFunction API ====================

bool
JsvFunction_Check(JsVal obj);

Expand All @@ -85,6 +103,8 @@ JsvFunction_CallBound(JsVal func, JsVal this, JsVal args);
JsVal
JsvFunction_Construct(JsVal func, JsVal args);

// ==================== Miscellaneous ====================

bool
JsvPromise_Check(JsVal obj);

Expand Down
36 changes: 30 additions & 6 deletions src/core/jsproxy.c
Original file line number Diff line number Diff line change
Expand Up @@ -2459,8 +2459,8 @@ JsProxy_toPy(PyObject* self,
}
PyObject* result =
js2python_convert(JsProxy_REF(self), depth, default_converter_js);
if (pyproxy_Check(Jsv_from_ref(default_converter_js))) {
destroy_proxy(Jsv_from_ref(default_converter_js), NULL);
if (pyproxy_Check(JsRef_toVal(default_converter_js))) {
destroy_proxy(JsRef_toVal(default_converter_js), NULL);
}
hiwire_decref(default_converter_js);
return result;
Expand All @@ -2472,6 +2472,31 @@ static PyMethodDef JsProxy_toPy_MethodDef = {
METH_FASTCALL | METH_KEYWORDS,
};

EM_JS_BOOL(bool, JsProxy_Bool_js, (JsVal val), {
// clang-format off
if (!val) {
return false;
}
// We want to return false on container types with size 0.
if (val.size === 0) {
if(/HTML[A-Za-z]*Element/.test(getTypeTag(val))){
// HTMLSelectElement and HTMLInputElement can have size 0 but we still
// want to return true.
return true;
}
// I think other things with a size are container types.
return false;
}
if (val.length === 0 && JsvArray_Check(val)) {
return false;
}
if (val.byteLength === 0) {
return false;
}
return true;
// clang-format on
});

/**
* Overload for bool(proxy), implemented for every JsProxy. Return `False` if
* the object is falsey in JavaScript, or if it has a `size` field equal to 0,
Expand All @@ -2482,10 +2507,9 @@ static PyMethodDef JsProxy_toPy_MethodDef = {
* be falsey.
*/
static int
JsProxy_Bool(PyObject* o)
JsProxy_Bool(PyObject* self)
{
JsProxy* self = (JsProxy*)o;
return hiwire_get_bool(self->js) ? 1 : 0;
return JsProxy_Bool_js(JsProxy_VAL(self));
}

/**
Expand Down Expand Up @@ -3138,7 +3162,7 @@ JsMethod_Vectorcall(PyObject* self,
JsMethod_ConvertArgs(pyargs, PyVectorcall_NARGS(nargsf), kwnames, proxies);
FAIL_IF_JS_NULL(jsargs);
jsresult = JsvFunction_CallBound(
JsProxy_VAL(self), Jsv_from_ref(JsMethod_THIS(self)), jsargs);
JsProxy_VAL(self), JsRef_toVal(JsMethod_THIS(self)), jsargs);
FAIL_IF_JS_NULL(jsresult);
// various cases where we want to extend the lifetime of the arguments:
// 1. if the return value is a promise we extend arguments lifetime until the
Expand Down
2 changes: 1 addition & 1 deletion src/core/pyproxy.c
Original file line number Diff line number Diff line change
Expand Up @@ -565,7 +565,7 @@ _pyproxy_slice_assign(PyObject* pyobj,
FAIL_IF_NULL(pyresult);
FAIL_IF_MINUS_ONE(PySequence_SetSlice(pyobj, start, stop, pyval));
JsVal proxies = JsvArray_New();
jsresult = Jsv_pop_ref(python2js_with_depth(pyresult, 1, proxies));
jsresult = JsRef_pop(python2js_with_depth(pyresult, 1, proxies));

finally:
Py_CLEAR(pyresult);
Expand Down
17 changes: 9 additions & 8 deletions src/core/python2js.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,13 @@ typedef struct ConversionContext_s
JsRef
_python2js(ConversionContext context, PyObject* x);

// clang-format off
EM_JS(void,
_python2js_addto_postprocess_list,
(JsVal idlist, JsVal idparent, JsVal idkey, PyObject* value),
{
list.push([ parent, key, value ]);
});
_python2js_addto_postprocess_list,
(JsVal list, JsVal parent, JsVal key, PyObject* value), {
list.push([ parent, key, value ]);
});
// clang-format on

EM_JS(void, _python2js_handle_postprocess_list, (JsRef idlist, JsRef idcache), {
const list = Hiwire.get_value(idlist);
Expand Down Expand Up @@ -710,7 +711,7 @@ python2js_custom(PyObject* x,
JsRef postprocess_list = hiwire_new(JsvArray_New());
ConversionContext context = { .cache = cache,
.depth = depth,
.proxies = hiwire_new(proxies),
.proxies = JsRef_new(proxies),
.jscontext = NULL,
.default_converter = false,
.jspostprocess_list = postprocess_list };
Expand Down Expand Up @@ -847,10 +848,10 @@ to_js(PyObject* self,
py_result = js2python(js_result);
}
finally:
if (pyproxy_Check(Jsv_from_ref(js_dict_converter))) {
if (pyproxy_Check(JsRef_toVal(js_dict_converter))) {
destroy_proxy(hiwire_get(js_dict_converter), NULL);
}
if (pyproxy_Check(Jsv_from_ref(js_default_converter))) {
if (pyproxy_Check(JsRef_toVal(js_default_converter))) {
destroy_proxy(hiwire_get(js_default_converter), NULL);
}
hiwire_CLEAR(js_dict_converter);
Expand Down
11 changes: 6 additions & 5 deletions src/tests/test_jsproxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,16 +105,16 @@ def test_jsproxy_document(selenium):
@pytest.mark.parametrize(
"js,result",
[
("{}", False),
("{}", True),
("{a:1}", True),
("[]", False),
("[1]", True),
("new Map()", False),
("new Map([[0, 0]])", True),
("new Set()", False),
("new Set([0])", True),
("class T {}; T", True),
("class T {}; new T()", True),
("class T {}", True),
("new (class T {})", True),
("new Uint8Array(0)", False),
("new Uint8Array(1)", True),
("new ArrayBuffer(0)", False),
Expand All @@ -125,7 +125,7 @@ def test_jsproxy_document(selenium):
def test_jsproxy_bool(selenium, js, result):
from pyodide.code import run_js

assert bool(run_js(js)) == result
assert bool(run_js(f"({js})")) == result


@pytest.mark.xfail_browsers(node="No document in node")
Expand Down Expand Up @@ -271,6 +271,7 @@ def test_jsproxy_call1(selenium):
== list(range(10))
)


@run_in_pyodide
def test_jsproxy_call2(selenium):
from pyodide.code import run_js
Expand Down Expand Up @@ -915,7 +916,7 @@ def test_mixins_errors_1(selenium):
set(){ return false; },
delete(){ return false; },
};
await pyodide.runPythonAsync(`
pyodide.runPython(`
from unittest import TestCase
raises = TestCase().assertRaises
from js import a, b
Expand Down

0 comments on commit 4019571

Please sign in to comment.