duktape 1.3.0.4 → 1.3.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/README.md +11 -0
- data/ext/duktape/duktape_ext.c +95 -2
- data/ext/duktape/extconf.rb +1 -0
- data/lib/duktape/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 28cb600087093cad9368ab6b897a04c555f17572
|
4
|
+
data.tar.gz: f768cc0a2b9d71f6a4df6dbed8a216ef5a8b7acb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 505392082298a898dfe7658e5d518deeba13843edd47c31c55a57a14aa71e555b42adab9c8433e48406f974b9d6de345a53b3743d33980270159fef0215018df
|
7
|
+
data.tar.gz: 20ca551193c9403aa527804963487249b889f505483a11efeab923aa28aee902e96140f95cf7b8f7f263ebf7984cbc2aff7ed67cbf15b265f4fe555864c4c6ea
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,13 @@
|
|
1
1
|
# ChangeLog
|
2
2
|
|
3
|
+
## v1.3.0.6 (2016-03-27)
|
4
|
+
|
5
|
+
* Implement `#define_function` (#16, judofyr, did)
|
6
|
+
|
7
|
+
## v1.3.0.5 (2016-01-22)
|
8
|
+
|
9
|
+
* Convert symbols to strings (judofyr, Jean-Baptiste Aviat)
|
10
|
+
|
3
11
|
## v1.3.0.4 (2015-11-23)
|
4
12
|
|
5
13
|
* Support Illumos and Solaris (#33, F4S4K4N)
|
data/README.md
CHANGED
@@ -52,6 +52,17 @@ ctx.call_prop('process', 'some data', a: 1, b: 2)
|
|
52
52
|
- `call_prop` - Call a defined function with the given parameters and return
|
53
53
|
the value as a Ruby Object.
|
54
54
|
|
55
|
+
### Defining functions
|
56
|
+
|
57
|
+
You can define simple functions in Ruby that can be called from
|
58
|
+
JavaScript:
|
59
|
+
|
60
|
+
```ruby
|
61
|
+
ctx.define_function("leftpad") do |str, n, ch=' '|
|
62
|
+
str.rjust(n, ch)
|
63
|
+
end
|
64
|
+
```
|
65
|
+
|
55
66
|
### Exceptions
|
56
67
|
|
57
68
|
Executing JS may raise two classes of errors: `Duktape::Error` and
|
data/ext/duktape/duktape_ext.c
CHANGED
@@ -40,6 +40,7 @@ struct state {
|
|
40
40
|
duk_context *ctx;
|
41
41
|
VALUE complex_object;
|
42
42
|
int was_complex;
|
43
|
+
VALUE blocks;
|
43
44
|
};
|
44
45
|
|
45
46
|
static void ctx_dealloc(void *ptr)
|
@@ -52,6 +53,7 @@ static void ctx_dealloc(void *ptr)
|
|
52
53
|
static void ctx_mark(struct state *state)
|
53
54
|
{
|
54
55
|
rb_gc_mark(state->complex_object);
|
56
|
+
rb_gc_mark(state->blocks);
|
55
57
|
}
|
56
58
|
|
57
59
|
static VALUE ctx_alloc(VALUE klass)
|
@@ -67,6 +69,7 @@ static VALUE ctx_alloc(VALUE klass)
|
|
67
69
|
struct state *state = malloc(sizeof(struct state));
|
68
70
|
state->ctx = ctx;
|
69
71
|
state->complex_object = oComplexObject;
|
72
|
+
state->blocks = rb_ary_new();
|
70
73
|
return Data_Wrap_Struct(klass, ctx_mark, ctx_dealloc, state);
|
71
74
|
}
|
72
75
|
|
@@ -255,6 +258,14 @@ static void ctx_push_ruby_object(struct state *state, VALUE obj)
|
|
255
258
|
duk_push_number(ctx, NUM2DBL(obj));
|
256
259
|
return;
|
257
260
|
|
261
|
+
case T_SYMBOL:
|
262
|
+
#ifdef HAVE_RB_SYM2STR
|
263
|
+
obj = rb_sym2str(obj);
|
264
|
+
#else
|
265
|
+
obj = rb_id2str(SYM2ID(obj));
|
266
|
+
#endif
|
267
|
+
// Intentional fall-through:
|
268
|
+
|
258
269
|
case T_STRING:
|
259
270
|
str = encode_cesu8(state, obj);
|
260
271
|
duk_push_lstring(ctx, RSTRING_PTR(str), RSTRING_LEN(str));
|
@@ -298,8 +309,15 @@ static int ctx_push_hash_element(VALUE key, VALUE val, VALUE extra)
|
|
298
309
|
struct state *state = (struct state*) extra;
|
299
310
|
duk_context *ctx = state->ctx;
|
300
311
|
|
301
|
-
|
302
|
-
|
312
|
+
switch (TYPE(key)) {
|
313
|
+
case T_SYMBOL:
|
314
|
+
case T_STRING:
|
315
|
+
ctx_push_ruby_object(state, key);
|
316
|
+
break;
|
317
|
+
default:
|
318
|
+
clean_raise(ctx, rb_eTypeError, "invalid key type %s", rb_obj_classname(key));
|
319
|
+
}
|
320
|
+
|
303
321
|
ctx_push_ruby_object(state, val);
|
304
322
|
duk_put_prop(ctx, -3);
|
305
323
|
return ST_CONTINUE;
|
@@ -519,6 +537,80 @@ static VALUE ctx_call_prop(int argc, VALUE* argv, VALUE self)
|
|
519
537
|
return res;
|
520
538
|
}
|
521
539
|
|
540
|
+
static duk_ret_t ctx_call_pushed_function(duk_context *ctx) {
|
541
|
+
VALUE block; // the block to yield
|
542
|
+
struct state *state;
|
543
|
+
int nargs = duk_get_top(ctx); // number of arguments of the block (arity)
|
544
|
+
VALUE args = rb_ary_new(); // the block to yield needs an array of arguments
|
545
|
+
VALUE result; // the result returned by yielding the block
|
546
|
+
|
547
|
+
duk_push_current_function(ctx);
|
548
|
+
|
549
|
+
// get the block which is a property of the pushed function
|
550
|
+
duk_get_prop_string(ctx, -1, "block");
|
551
|
+
block = (VALUE) duk_get_pointer(ctx, -1);
|
552
|
+
duk_pop(ctx);
|
553
|
+
|
554
|
+
// get the state so that we don't need to a create a new one
|
555
|
+
duk_get_prop_string(ctx, -1, "state");
|
556
|
+
state = (struct state *) duk_get_pointer(ctx, -1);
|
557
|
+
duk_pop(ctx);
|
558
|
+
|
559
|
+
// before pushing each argument to the array, each one needs to be converted into a ruby value
|
560
|
+
for (int i = 0; i < nargs; i++)
|
561
|
+
rb_ary_push(args, ctx_stack_to_value(state, i));
|
562
|
+
|
563
|
+
result = rb_proc_call(block, args); // yield
|
564
|
+
ctx_push_ruby_object(state, result);
|
565
|
+
|
566
|
+
return 1;
|
567
|
+
}
|
568
|
+
|
569
|
+
/*
|
570
|
+
* call-seq:
|
571
|
+
* ctx_define_function(name, &block) -> nil
|
572
|
+
*
|
573
|
+
* Define a function defined in the global scope and identified by a name.
|
574
|
+
*
|
575
|
+
* ctx.ctx_define_function("hello_world") { |ctx| 'Hello world' } #=> nil
|
576
|
+
*
|
577
|
+
*/
|
578
|
+
static VALUE ctx_define_function(VALUE self, VALUE prop)
|
579
|
+
{
|
580
|
+
VALUE block;
|
581
|
+
struct state *state;
|
582
|
+
duk_context *ctx;
|
583
|
+
|
584
|
+
// a block is required
|
585
|
+
if (!rb_block_given_p())
|
586
|
+
rb_raise(rb_eArgError, "Expected block");
|
587
|
+
|
588
|
+
// get the context
|
589
|
+
Data_Get_Struct(self, struct state, state);
|
590
|
+
ctx = state->ctx;
|
591
|
+
|
592
|
+
// the c function is available in the global scope
|
593
|
+
duk_push_global_object(ctx);
|
594
|
+
|
595
|
+
duk_push_c_function(ctx, ctx_call_pushed_function, DUK_VARARGS);
|
596
|
+
|
597
|
+
block = rb_block_proc();
|
598
|
+
rb_ary_push(state->blocks, block); // block will be properly garbage collected
|
599
|
+
|
600
|
+
// both block and state are required by the pushed function
|
601
|
+
duk_push_string(ctx, "block");
|
602
|
+
duk_push_pointer(ctx, (void *) block);
|
603
|
+
duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_HAVE_WRITABLE | 0);
|
604
|
+
|
605
|
+
duk_push_string(ctx, "state");
|
606
|
+
duk_push_pointer(ctx, (void *) state);
|
607
|
+
duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_HAVE_WRITABLE | 0);
|
608
|
+
|
609
|
+
duk_put_prop_string(ctx, -2, StringValueCStr(prop));
|
610
|
+
|
611
|
+
return Qnil;
|
612
|
+
}
|
613
|
+
|
522
614
|
/*
|
523
615
|
* :nodoc:
|
524
616
|
*
|
@@ -624,6 +716,7 @@ void Init_duktape_ext()
|
|
624
716
|
rb_define_method(cContext, "exec_string", ctx_exec_string, -1);
|
625
717
|
rb_define_method(cContext, "get_prop", ctx_get_prop, 1);
|
626
718
|
rb_define_method(cContext, "call_prop", ctx_call_prop, -1);
|
719
|
+
rb_define_method(cContext, "define_function", ctx_define_function, 1);
|
627
720
|
rb_define_method(cContext, "_valid?", ctx_is_valid, 0);
|
628
721
|
|
629
722
|
oComplexObject = rb_obj_alloc(cComplexObject);
|
data/ext/duktape/extconf.rb
CHANGED
data/lib/duktape/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: duktape
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.3.0.
|
4
|
+
version: 1.3.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Magnus Holm
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-03-27 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description:
|
14
14
|
email: judofyr@gmail.com
|