duktape 1.3.0.4 → 1.3.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a83f9f94bcb9062672ab5f4b394379b3c6b3bb3a
4
- data.tar.gz: 61109c31d8865a66852a004a4a393c1edb72ca7b
3
+ metadata.gz: 28cb600087093cad9368ab6b897a04c555f17572
4
+ data.tar.gz: f768cc0a2b9d71f6a4df6dbed8a216ef5a8b7acb
5
5
  SHA512:
6
- metadata.gz: 6564704f5eaa7bdfd87894ba1bb70d854d2818a68740d984fe96e4f249fe2991ce4369a91bbeadb4538cbe09f2cb00572a94221339d73ec328c825776978d9c3
7
- data.tar.gz: 9f42fbed534b7c41ff92dfac44a08227301e701297eea9cbc7c6d7f7ca07ae89465aebe630e0c82d05ecf1d77ef11b5b4f7411de1ba99a3d95e292748540f540
6
+ metadata.gz: 505392082298a898dfe7658e5d518deeba13843edd47c31c55a57a14aa71e555b42adab9c8433e48406f974b9d6de345a53b3743d33980270159fef0215018df
7
+ data.tar.gz: 20ca551193c9403aa527804963487249b889f505483a11efeab923aa28aee902e96140f95cf7b8f7f263ebf7984cbc2aff7ed67cbf15b265f4fe555864c4c6ea
@@ -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
@@ -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
- Check_Type(key, T_STRING);
302
- duk_push_lstring(ctx, RSTRING_PTR(key), RSTRING_LEN(key));
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);
@@ -2,5 +2,6 @@ require 'mkmf'
2
2
  require 'zlib'
3
3
 
4
4
  $CFLAGS += ' -std=c99'
5
+ have_func 'rb_sym2str'
5
6
  create_makefile 'duktape_ext'
6
7
 
@@ -1,3 +1,3 @@
1
1
  module Duktape
2
- VERSION = "1.3.0.4"
2
+ VERSION = "1.3.0.6"
3
3
  end
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
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: 2015-11-23 00:00:00.000000000 Z
11
+ date: 2016-03-27 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email: judofyr@gmail.com