Skip to content

Commit 16f20c1

Browse files
committed
Use basic instead of scalar
1 parent d038ec4 commit 16f20c1

File tree

3 files changed

+85
-55
lines changed

3 files changed

+85
-55
lines changed

py_mini_racer/extension/mini_racer_extension.cc

Lines changed: 71 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ typedef struct {
163163
unsigned long timeout;
164164
EvalResult* result;
165165
size_t max_memory;
166+
bool basic_only;
166167
} EvalParams;
167168

168169
enum IsolateData {
@@ -413,39 +414,80 @@ static BinaryValue *heap_stats(ContextInfo *context_info) {
413414
}
414415

415416

416-
static BinaryValue *convert_v8_to_binary(Isolate * isolate,
417-
Local<Context> context,
418-
Local<Value> value)
417+
static BinaryValue *convert_basic_v8_to_binary(Isolate * isolate,
418+
Local<Context> context,
419+
Local<Value> value)
419420
{
420-
Isolate::Scope isolate_scope(isolate);
421+
Isolate::Scope isolate_scope(isolate);
421422
HandleScope scope(isolate);
422423

423424
BinaryValue *res = new (xalloc(res)) BinaryValue();
424425

425426
if (value->IsNull() || value->IsUndefined()) {
426427
res->type = type_null;
427428
}
428-
429429
else if (value->IsInt32()) {
430430
res->type = type_integer;
431431
auto val = value->Uint32Value(context).ToChecked();
432432
res->int_val = val;
433433
}
434-
435434
// ECMA-262, 4.3.20
436435
// http://www.ecma-international.org/ecma-262/5.1/#sec-4.3.19
437436
else if (value->IsNumber()) {
438437
res->type = type_double;
439438
double val = value->NumberValue(context).ToChecked();
440439
res->double_val = val;
441440
}
442-
443441
else if (value->IsBoolean()) {
444442
res->type = type_bool;
445443
res->int_val = (value->IsTrue() ? 1 : 0);
446444
}
445+
else if (value->IsFunction()){
446+
res->type = type_function;
447+
}
448+
else if (value->IsSymbol()){
449+
res->type = type_symbol;
450+
}
451+
else if (value->IsDate()) {
452+
res->type = type_date;
453+
Local<Date> date = Local<Date>::Cast(value);
454+
455+
double timestamp = date->ValueOf();
456+
res->double_val = timestamp;
457+
}
458+
else if (value->IsString()) {
459+
Local<String> rstr = value->ToString(context).ToLocalChecked();
460+
461+
res->type = type_str_utf8;
462+
res->len = size_t(rstr->Utf8Length(isolate)); // in bytes
463+
size_t capacity = res->len + 1;
464+
res->str_val = xalloc(res->str_val, capacity);
465+
rstr->WriteUtf8(isolate, res->str_val);
466+
}
467+
else {
468+
BinaryValueFree(res);
469+
res = nullptr;
470+
}
471+
return res;
472+
}
473+
474+
475+
static BinaryValue *convert_v8_to_binary(Isolate * isolate,
476+
Local<Context> context,
477+
Local<Value> value)
478+
{
479+
Isolate::Scope isolate_scope(isolate);
480+
HandleScope scope(isolate);
481+
BinaryValue *res;
447482

448-
else if (value->IsArray()) {
483+
res = convert_basic_v8_to_binary(isolate, context, value);
484+
if (res) {
485+
return res;
486+
}
487+
488+
res = new (xalloc(res)) BinaryValue();
489+
490+
if (value->IsArray()) {
449491
Local<Array> arr = Local<Array>::Cast(value);
450492
uint32_t len = arr->Length();
451493

@@ -466,23 +508,6 @@ static BinaryValue *convert_v8_to_binary(Isolate * isolate,
466508
ary[i] = bin_value;
467509
}
468510
}
469-
470-
else if (value->IsFunction()){
471-
res->type = type_function;
472-
}
473-
474-
else if (value->IsSymbol()){
475-
res->type = type_symbol;
476-
}
477-
478-
else if (value->IsDate()) {
479-
res->type = type_date;
480-
Local<Date> date = Local<Date>::Cast(value);
481-
482-
double timestamp = date->ValueOf();
483-
res->double_val = timestamp;
484-
}
485-
486511
else if (value->IsObject()) {
487512
res->type = type_hash;
488513

@@ -528,16 +553,8 @@ static BinaryValue *convert_v8_to_binary(Isolate * isolate,
528553
res->len++;
529554
}
530555
} // else empty hash
531-
}
532-
533-
else {
534-
Local<String> rstr = value->ToString(context).ToLocalChecked();
535-
536-
res->type = type_str_utf8;
537-
res->len = size_t(rstr->Utf8Length(isolate)); // in bytes
538-
size_t capacity = res->len + 1;
539-
res->str_val = xalloc(res->str_val, capacity);
540-
rstr->WriteUtf8(isolate, res->str_val);
556+
} else {
557+
goto err;
541558
}
542559
return res;
543560

@@ -547,6 +564,16 @@ static BinaryValue *convert_v8_to_binary(Isolate * isolate,
547564
}
548565

549566

567+
static BinaryValue *convert_basic_v8_to_binary(Isolate * isolate,
568+
const Persistent<Context> & context,
569+
Local<Value> value)
570+
{
571+
HandleScope scope(isolate);
572+
return convert_basic_v8_to_binary(isolate,
573+
Local<Context>::New(isolate, context),
574+
value);
575+
}
576+
550577
static BinaryValue *convert_v8_to_binary(Isolate * isolate,
551578
const Persistent<Context> & context,
552579
Local<Value> value)
@@ -610,7 +637,7 @@ ContextInfo *MiniRacer_init_context()
610637
static BinaryValue* MiniRacer_eval_context_unsafe(
611638
ContextInfo *context_info,
612639
char *utf_str, int str_len,
613-
unsigned long timeout, size_t max_memory)
640+
unsigned long timeout, size_t max_memory, bool basic_only)
614641
{
615642
EvalParams eval_params;
616643
EvalResult eval_result{};
@@ -643,6 +670,7 @@ static BinaryValue* MiniRacer_eval_context_unsafe(
643670
eval_params.result = &eval_result;
644671
eval_params.timeout = 0;
645672
eval_params.max_memory = 0;
673+
eval_params.basic_only = basic_only;
646674
if (timeout > 0) {
647675
eval_params.timeout = timeout;
648676
}
@@ -732,7 +760,11 @@ static BinaryValue* MiniRacer_eval_context_unsafe(
732760
HandleScope handle_scope(context_info->isolate);
733761

734762
Local<Value> tmp = Local<Value>::New(context_info->isolate, *eval_result.value);
735-
result = convert_v8_to_binary(context_info->isolate, *context_info->context, tmp);
763+
if (eval_params.basic_only) {
764+
result = convert_basic_v8_to_binary(context_info->isolate, *context_info->context, tmp);
765+
} else {
766+
result = convert_v8_to_binary(context_info->isolate, *context_info->context, tmp);
767+
}
736768
}
737769

738770
BinaryValueFree(bmessage);
@@ -767,8 +799,8 @@ class BufferOutputStream: public OutputStream {
767799

768800
extern "C" {
769801

770-
LIB_EXPORT BinaryValue * mr_eval_context(ContextInfo *context_info, char *str, int len, unsigned long timeout, size_t max_memory) {
771-
BinaryValue *res = MiniRacer_eval_context_unsafe(context_info, str, len, timeout, max_memory);
802+
LIB_EXPORT BinaryValue * mr_eval_context(ContextInfo *context_info, char *str, int len, unsigned long timeout, size_t max_memory, bool basic_only) {
803+
BinaryValue *res = MiniRacer_eval_context_unsafe(context_info, str, len, timeout, max_memory, basic_only);
772804
return res;
773805
}
774806

py_mini_racer/py_mini_racer.py

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,8 @@ def _fetch_ext_handle():
101101
ctypes.c_char_p,
102102
ctypes.c_int,
103103
ctypes.c_ulong,
104-
ctypes.c_size_t]
104+
ctypes.c_size_t,
105+
ctypes.c_bool]
105106
_ext_handle.mr_eval_context.restype = ctypes.POINTER(PythonValue)
106107

107108
_ext_handle.mr_free_value.argtypes = [ctypes.c_void_p]
@@ -130,6 +131,8 @@ class MiniRacer(object):
130131
https://docs.python.org/2/library/ctypes.html
131132
"""
132133

134+
basic_types_only = False
135+
133136
def __init__(self):
134137
""" Init a JS context """
135138

@@ -171,7 +174,8 @@ def eval(self, js_str, timeout=0, max_memory=0):
171174
bytes_val,
172175
len(bytes_val),
173176
ctypes.c_ulong(timeout),
174-
ctypes.c_size_t(max_memory))
177+
ctypes.c_size_t(max_memory),
178+
ctypes.c_bool(self.basic_types_only))
175179

176180
if bool(res) is False:
177181
raise JSConversionException()
@@ -232,11 +236,12 @@ def _eval_return(res):
232236

233237
class StrictMiniRacer(MiniRacer):
234238
"""
235-
A stricter version of MiniRacer accepting only scalars as a return value
236-
(boolean, integer, strings, ...).
239+
A stricter version of MiniRacer accepting only basic types as a return value
240+
(boolean, integer, strings, ...), array and mapping are disallowed.
237241
"""
238242

239243
json_impl = json
244+
basic_types_only = True
240245

241246
def execute(self, expr, **kwargs):
242247
""" Stricter Execute with JSON serialization of returned value.
@@ -259,7 +264,7 @@ def call(self, identifier, *args, **kwargs):
259264

260265
@staticmethod
261266
def _eval_return(res):
262-
return res.contents.scalar_to_python()
267+
return res.contents.basic_to_python()
263268

264269

265270
class PythonTypes(object):
@@ -312,14 +317,7 @@ def _raise_from_error(self):
312317
msg = ctypes.c_char_p(self.value).value
313318
raise JSTimeoutException(msg)
314319

315-
def string_to_python(self, **kwargs):
316-
self._raise_from_error()
317-
if self.type != PythonTypes.str_utf8:
318-
raise WrongReturnTypeException(
319-
"returned value is not a unicode string")
320-
return self.scalar_to_python()
321-
322-
def scalar_to_python(self):
320+
def basic_to_python(self):
323321
self._raise_from_error()
324322
result = None
325323
if self.type == PythonTypes.null:
@@ -346,7 +344,7 @@ def scalar_to_python(self):
346344
elif self.type == PythonTypes.symbol:
347345
result = JSSymbol()
348346
else:
349-
raise WrongReturnTypeException("unknown type %d" % self.type)
347+
raise JSConversionException()
350348
return result
351349

352350
def to_python(self):
@@ -375,5 +373,5 @@ def to_python(self):
375373
res[pkey.to_python()] = pval.to_python()
376374
result = res
377375
else:
378-
result = self.scalar_to_python()
376+
result = self.basic_to_python()
379377
return result

tests/test_strict.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ def test_basic_array(self):
2222
self.assertEqual([1, 2, 3], self.mr.execute('[1, 2, 3]'))
2323

2424
def test_not_allowed_type(self):
25-
with self.assertRaises(py_mini_racer.WrongReturnTypeException):
25+
with self.assertRaises(py_mini_racer.JSConversionException):
2626
self.mr.eval("Object()")
2727

2828
def test_call(self):

0 commit comments

Comments
 (0)