jsc 0.2.0 → 0.2.1

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.
data/TODO.org ADDED
@@ -0,0 +1,12 @@
1
+ * jsc
2
+ ** colourful output in shell!
3
+ ** come far uscire un carattere sotto la lettera dove c'è l'errore
4
+ ** ann with bones + ann on ruby-talk?
5
+ ** test jsc bin file
6
+ (15:02:14) @jabber.org: eh appunto con cucumber
7
+ (15:02:23) @jabber.org: guarda le features di rake-compiler
8
+ (15:02:28) @jabber.org: sono scritte bene
9
+ (15:02:29) @jabber.org: oppure
10
+ (15:02:36) @jabber.org: quelle di ffi-swig-generator
11
+ oppure con aruba http://github.com/aslakhellesoy/aruba
12
+ ** newgem http://newgem.rubyforge.org/ o jeweler http://github.com/technicalpickles/jeweler
data/bin/#jsc# ADDED
@@ -0,0 +1,119 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'getoptlong'
4
+ require 'rdoc/usage'
5
+
6
+ require File.expand_path(
7
+ File.join(File.dirname(__FILE__), %w[.. lib jsc]))
8
+
9
+ USAGE_PREAMBLE = <<-EOU
10
+
11
+ jsc, JavaScript Compiler.
12
+
13
+ This command compiles your JavaScript code throught Google Closure Compiler Service.
14
+ Look at http://gemcutter.org/gems/jsc for more info.
15
+
16
+ == Usage
17
+
18
+ jsc [options] ... ARG
19
+
20
+ --code x, -c x:
21
+ compile code x
22
+
23
+ --errors, -e:
24
+ check for errors
25
+
26
+ --warns, -w:
27
+ check for warnings
28
+
29
+ --stats, -s:
30
+ get statistics for compiled code
31
+
32
+ --all, -a:
33
+ execute every check for this code
34
+
35
+ --level value, -l value:
36
+ compile with level value
37
+ If this option is not supplied, SIMPLE_OPTIMIZATIONS will be used
38
+ (look at Google API for accepted values).
39
+
40
+ --version, -v:
41
+ show version
42
+
43
+ --help, -h:
44
+ this help
45
+
46
+ ARG: A path to a javascript file or the code that will be compiled.
47
+
48
+ If one of the following options is not specified
49
+
50
+ -e, -w, -s, -a
51
+
52
+ the code will be first compiled for errors and only if no errors are found
53
+ it will return the compiled code
54
+ EOU
55
+
56
+ opts = GetoptLong.new(
57
+ [ '--help', '-h', GetoptLong::NO_ARGUMENT ],
58
+ [ '--version', '-v', GetoptLong::NO_ARGUMENT ],
59
+ [ '--code', '-c', GetoptLong::OPTIONAL_ARGUMENT ],
60
+ [ '--errors', '-e', GetoptLong::NO_ARGUMENT ],
61
+ [ '--warns', '-w', GetoptLong::NO_ARGUMENT ],
62
+ [ '--stats', '-s', GetoptLong::NO_ARGUMENT ],
63
+ [ '--all', '-a', GetoptLong::NO_ARGUMENT ],
64
+ [ '--level','-l', GetoptLong::REQUIRED_ARGUMENT ]
65
+ )
66
+
67
+ file = true
68
+ output_info, level, code = ""
69
+
70
+ opts.each do |opt, arg|
71
+ case opt
72
+ when '--help'
73
+ puts USAGE_PREAMBLE
74
+ exit 0
75
+ when '--version'
76
+ puts JSCompiler::VERSION
77
+ exit 0
78
+ when '--code'
79
+ file = false
80
+ code = arg
81
+ when '--level'
82
+ if arg == ''
83
+ level = "SIMPLE_OPTIMIZATIONS"
84
+ else
85
+ level = arg
86
+ end
87
+ when '--errors'
88
+ output_info = "errors"
89
+ when '--warns'
90
+ output_info = "warnings"
91
+ when '--stats'
92
+ output_info = "statistics"
93
+ when '--all'
94
+ output_info = "all"
95
+ end
96
+ end
97
+
98
+ # -f option or CODE arg requested
99
+ unless ARGV.length > 0 or code
100
+ puts "Missing any argume
101
+
102
+ nt (try --help)"
103
+ exit 0
104
+ end
105
+
106
+ arg = code.blank? ? ARGV.shift : code
107
+
108
+ if output_info.eql?("all")
109
+ puts JSCompiler.full_compile(arg, file, level)
110
+ elsif output_info.blank?
111
+ errors_output = JSCompiler.compile(arg, file, "errors", level)
112
+ unless errors_output.eql?("No errors")
113
+ puts errors_output
114
+ else
115
+ puts JSCompiler.compile(arg, file, "", level)
116
+ end
117
+ else
118
+ puts JSCompiler.compile(arg, file, output_info, level)
119
+ end
@@ -0,0 +1,559 @@
1
+ /*
2
+ AlcaDialer_IM: Modulo di messagistica istantanea
3
+
4
+ Configurazione dei parametri di una connessione,
5
+ configurazione degli handlers,
6
+ connessione e disconnessione,
7
+ invio di dati,
8
+ amministrazione pubsub,
9
+ iscrizione e ricezione pubsub
10
+ */
11
+
12
+ // REQUIRE: jQuery e StropheJS
13
+ //
14
+ // jQuery: XML parsing
15
+ // StropheJS: XMPP
16
+
17
+ // NOTE: create a module private context
18
+ (function(){
19
+ var base_im_config = {
20
+ max_conn_retry: 0,
21
+ username: null,
22
+ password: null,
23
+ jid: null,
24
+ fulljid: null,
25
+ hostname: null,
26
+ boshurl: null,
27
+ resource: "AlcaBosh"
28
+ };
29
+
30
+ var dummy_handler = function() { };
31
+
32
+ var base_call_callbacks = {
33
+ ok: dummy_handler,
34
+ fail: dummy_handler
35
+ };
36
+
37
+ var base_global_callbacks = {
38
+ connected: dummy_handler,
39
+ connection_error: dummy_handler,
40
+ disconnecting: dummy_handler,
41
+ disconnected: dummy_handler,
42
+ receive_message: dummy_handler,
43
+ receive_pubsub_item: dummy_handler
44
+ };
45
+
46
+ var DEBUG = false;
47
+
48
+ var NS_PUBSUB = 'http://jabber.org/protocol/pubsub';
49
+
50
+ // NOTE: current configuration
51
+ var im_config = null;
52
+ // NOTE: current connection
53
+ var im_conn = null;
54
+ // NOTE: current persistent exported handlers
55
+ var im_handlers = null;
56
+
57
+ // AlcaDialer_IM constructor
58
+ var AlcaDialer_IM = mixin({}, {
59
+ init: IM_init,
60
+ connect: IM_connect,
61
+ disconnect: IM_disconnect,
62
+ send_message: IM_send_message,
63
+ ping: IM_ping,
64
+ create_user: IM_create_user,
65
+ flush: IM_flush,
66
+ pubsub: {
67
+ create_node: PUBSUB_create_node,
68
+ remove_node: PUBSUB_remove_node,
69
+ list_nodes: PUBSUB_list_nodes,
70
+ publish_item: PUBSUB_publish_item,
71
+ subscribe: PUBSUB_subscribe,
72
+ list_subscribed: PUBSUB_list_subscribed,
73
+ unsubscribe: PUBSUB_unsubscribe,
74
+ unsubscribe_all: PUBSUB_unsubscribe_all
75
+ },
76
+ get_connection: function() { return im_conn; },
77
+ jid: jid,
78
+ fulljid: fulljid,
79
+ STATUS: Strophe.Status // Export Strophe Status consts
80
+ });
81
+
82
+ // NOTE: Export AlcaDialer_IM
83
+ window.AlcaDialer_IM = AlcaDialer_IM;
84
+
85
+ // PUBLIC NETHODS IMPLEMENTATIONS
86
+ function jid(config) {
87
+ var cfg = config ? config : im_config;
88
+
89
+ return cfg.username+"@"+cfg.hostname;
90
+ }
91
+
92
+ function fulljid(config) {
93
+ var cfg = config ? config : im_config;
94
+
95
+ return jid(cfg)+'/'+cfg.resource;
96
+ }
97
+
98
+ function IM_init(config) {
99
+ // Mix configuration parameters
100
+ im_config = mixin({}, base_im_config, config);
101
+ im_config.fulljid = fulljid(im_config);
102
+ im_config.jid = jid(im_config);
103
+ im_handlers = mixin({}, base_global_callbacks, config.handlers);
104
+
105
+ return true;
106
+ }
107
+
108
+ function IM_connect() {
109
+ var fulljid = im_config.fulljid;
110
+
111
+ im_conn = new Strophe.Connection(im_config.boshurl);
112
+ // AlcaBosh.conn.rawInput = AlcaBosh._raw_input;
113
+ // AlcaBosh.conn.rawOutput = AlcaBosh._raw_output;
114
+ im_conn.connect(fulljid, im_config.password, _IM_connection_manager);
115
+ }
116
+
117
+ function IM_disconnect(reason) {
118
+ im_conn.flush();
119
+ im_conn.disconnect(reason);
120
+ im_config.conn_retry = 0;
121
+ }
122
+
123
+ function IM_create_user(callbacks) {
124
+ var cb = mixin({},base_call_callbacks,callbacks);
125
+ var xmpp_id = im_conn.getUniqueId('reg');
126
+
127
+ var xmpp = $iq(
128
+ {
129
+ "id": xmpp_id,
130
+ "type": "set",
131
+ "to": im_config.hostname
132
+ }).
133
+ c("query", {"xmlns": "jabber:iq:register"}).
134
+ c("username").t(im_config.username).
135
+ up().c("password").t(im_config.password);
136
+
137
+ _IM_sendSysIQ(xmpp, cb.ok, cb.fail);
138
+ im_conn.flush();
139
+ }
140
+
141
+ function IM_ping() {
142
+ _IM_send_data($iq({
143
+ type: 'get',
144
+ id: im_conn.getUniqueId('ping')
145
+ }).c('ping', { xmlns: 'urn:xmpp:ping' }));
146
+
147
+ im_conn.flush();
148
+ // don't remove the time handler
149
+ return true;
150
+ }
151
+
152
+ function IM_flush() {
153
+ im_conn.flush();
154
+ }
155
+
156
+ function IM_send_message(to, text) {
157
+ _IM_send_data(
158
+ $msg({ to: to, type: 'chat'}).
159
+ c('body').t(text)
160
+ );
161
+ }
162
+
163
+ function PUBSUB_list_nodes(rootnode, callbacks) {
164
+ var cb = mixin({},base_call_callbacks,callbacks);
165
+ var xmpp_id = im_conn.getUniqueId('list');
166
+ var xmpp = $iq(
167
+ {
168
+ id: xmpp_id,
169
+ type: 'get',
170
+ from: im_config.fulljid,
171
+ to: im_config.pubsub
172
+ }).
173
+ c('query',
174
+ {
175
+ xmlns: Strophe.NS.DISCO_ITEMS,
176
+ node: rootnode
177
+ });
178
+
179
+ // TODO: import from first prototype
180
+ _IM_sendIQ(xmpp, ok, fail);
181
+ function ok(data) {
182
+ var content = [];
183
+ $(data).find('item').each(function() {
184
+ content.push($(this).attr('node'));
185
+ });
186
+ cb.ok(content);
187
+ }
188
+ function fail(data) {
189
+ cb.fail(data);
190
+ }
191
+ }
192
+
193
+ /*
194
+ NOTE: xml fragment generation con jquery
195
+
196
+ var iq = $iq({ id: "12312312", type: "set"});
197
+ $(iq.tree()).append( $("<c xmlns='test'>"));
198
+ $('c', iq.tree()).append($("<value pippo='34'/>"));
199
+ iq.toString();
200
+
201
+ ====> <iq id='12312312' type='set' xmlns='jabber:client'><c xmlns='test'><value pippo='34'/></c></iq>
202
+ */
203
+
204
+ function PUBSUB_create_node(node, callbacks) {
205
+ var cb = mixin({},base_call_callbacks,callbacks);
206
+ var xmpp_id = im_conn.getUniqueId('list');
207
+ /* TODO: TOOOOOOO BIG */
208
+ var xmpp_iq = $iq(
209
+ {
210
+ id: xmpp_id,
211
+ type: 'set',
212
+ from: im_config.fulljid,
213
+ to: im_config.pubsub,
214
+ xmlns: Strophe.NS.CLIENT
215
+ }).
216
+ c('pubsub',{xmlns: NS_PUBSUB}).
217
+ c('create',{node: node});
218
+
219
+ // NOTE: Crea i fragment xml con gli helper strophe
220
+ var xmpp_configure = $build("configure", {node: node}).
221
+ c('x', {'type': 'submit', 'xmlns': 'jabber:x:data'});
222
+
223
+ var xmpp_field_formtype = $build('field', {'type': 'hidden', 'var': 'FORM_TYPE'}).
224
+ c('value').t('http://jabber.org/protocol/pubsub#node_config');
225
+
226
+ var xmpp_field_lastpub = $build('field', {'var': 'pubsub#send_last_published_item'}).
227
+ c('value').t('never');
228
+
229
+ var xmpp_field_presencedelivery = $build('field', {'var': 'pubsub#presence_based_delivery'}).
230
+ c('value').t('1');
231
+
232
+ var xmpp_field_publishmodel = $build('field', {'var': 'pubsub#publish_model'}).
233
+ c('value').t('open');
234
+
235
+ // NOTE: Assembla il pacchetto xml dai fragment mediante jQuery
236
+ $('pubsub', xmpp_iq.tree()).append(xmpp_configure.tree());
237
+ $('x', xmpp_configure.tree()).
238
+ append(xmpp_field_formtype.tree()).
239
+ append(xmpp_field_lastpub.tree()).
240
+ append(xmpp_field_presencedelivery.tree()).
241
+ append(xmpp_field_publishmodel.tree());
242
+
243
+ _IM_sendIQ(xmpp_iq, cb.ok, cb.fail);
244
+
245
+ return xmpp_id;
246
+ }
247
+
248
+ function PUBSUB_remove_node(node, callbacks) {
249
+ var cb = mixin({},base_call_callbacks,callbacks);
250
+ var xmpp_id = im_conn.getUniqueId('del');
251
+ var xmpp_iq = $iq(
252
+ {
253
+ 'type':'set',
254
+ 'from': im_config.fulljid,
255
+ 'to': im_config.pubsub,
256
+ 'id': xmpp_id
257
+ }).
258
+ c('pubsub', {'xmlns': 'http://jabber.org/protocol/pubsub#owner'}).
259
+ c('delete', {'node': node});
260
+
261
+ _IM_sendIQ(xmpp_iq, cb.ok, cb.fail);
262
+ }
263
+
264
+ function PUBSUB_publish_item(node, text, callbacks) {
265
+ var cb = mixin({},base_call_callbacks,callbacks);
266
+ var xmpp_id = im_conn.getUniqueId('pub');
267
+ var xmpp_iq = $iq(
268
+ {
269
+ 'type':'set',
270
+ 'from': im_config.fulljid,
271
+ 'to': im_config.pubsub,
272
+ 'id': xmpp_id
273
+ }).
274
+ c('pubsub', {'xmlns': 'http://jabber.org/protocol/pubsub'}).
275
+ c('publish', {'node': node }).
276
+ c('item').t(text);
277
+
278
+ _IM_sendIQ(xmpp_iq, cb.ok, cb.fail);
279
+ }
280
+
281
+
282
+ function PUBSUB_subscribe(node, callbacks) {
283
+ var cb = mixin({},base_call_callbacks,callbacks);
284
+ var xmpp_id = im_conn.getUniqueId('sub');
285
+ var bare_jid = Strophe.getBareJidFromJid(im_config.fulljid);
286
+ var xmpp_iq = $iq(
287
+ {
288
+ 'type':'set',
289
+ 'from': im_config.fulljid,
290
+ 'to': im_config.pubsub,
291
+ 'id': xmpp_id
292
+ }).
293
+ c('pubsub', {'xmlns': 'http://jabber.org/protocol/pubsub'}).
294
+ c('subscribe', {'node': node, 'jid': bare_jid});
295
+
296
+ _IM_sendIQ(xmpp_iq, parse_subscribe_ok, parse_subscribe_fail);
297
+
298
+ var result = { node: node, success: false };
299
+
300
+ function parse_subscribe_ok(data) {
301
+ result.success = true;
302
+ cb.ok(result);
303
+ }
304
+ function parse_subscribe_fail(data) {
305
+ //NOTE: result.success is already false
306
+ cb.ok(result);
307
+ }
308
+ }
309
+
310
+ function PUBSUB_unsubscribe(node, callbacks) {
311
+ var cb = mixin({},base_call_callbacks,callbacks);
312
+ var xmpp_id = im_conn.getUniqueId('unsub');
313
+ var bare_jid = Strophe.getBareJidFromJid(im_config.fulljid);
314
+ var xmpp_iq = $iq(
315
+ {
316
+ 'type':'set',
317
+ 'from': im_config.fulljid,
318
+ 'to': im_config.pubsub,
319
+ 'id': xmpp_id
320
+ }).
321
+ c('pubsub', {'xmlns': 'http://jabber.org/protocol/pubsub'}).
322
+ c('unsubscribe', {'node': node, 'jid': bare_jid});
323
+
324
+ _IM_sendIQ(xmpp_iq, parse_unsubscribe_ok, parse_unsubscribe_fail);
325
+
326
+ var result = { node: node, success: false };
327
+
328
+ function parse_unsubscribe_ok(data) {
329
+ result.success = true;
330
+ cb.ok(result);
331
+ }
332
+ function parse_unsubscribe_fail(data) {
333
+ //NOTE: result.success is already false
334
+ cb.ok(result);
335
+ }
336
+ return xmpp_id;
337
+ }
338
+
339
+ function PUBSUB_list_subscribed(callbacks) {
340
+ var cb = mixin({},base_call_callbacks,callbacks);
341
+ var xmpp_id = im_conn.getUniqueId('list');
342
+ var bare_jid = Strophe.getBareJidFromJid(im_config.fulljid);
343
+ var xmpp_iq = $iq(
344
+ {
345
+ 'type':'get',
346
+ 'from': im_config.fulljid,
347
+ 'to': im_config.pubsub,
348
+ 'id': xmpp_id
349
+ }).
350
+ c('pubsub', {'xmlns': 'http://jabber.org/protocol/pubsub'}).
351
+ c('subscriptions');
352
+
353
+ _IM_sendIQ(xmpp_iq, parse_subscriptions, cb.fail);
354
+ function parse_subscriptions(data) {
355
+ var content = [];
356
+
357
+ $(data).find('subscription').each(function () {
358
+ content.push($(this).attr('node'));
359
+ });
360
+
361
+ cb.ok(content);
362
+ }
363
+
364
+ }
365
+
366
+ // TODO: dovrebbe controllare l'effetivo esito delle desottoscrizioni richieste
367
+ function PUBSUB_unsubscribe_all(callbacks) {
368
+ var cb = mixin({},base_call_callbacks,callbacks);
369
+
370
+ PUBSUB_list_subscribed({
371
+ ok: function(data) {
372
+ var nodes = [];
373
+ var result = true;
374
+ $(data).each(function() {
375
+ PUBSUB_unsubscribe(this, {
376
+ ok: function(unsub_reply) {
377
+ nodes.push(unsub_reply);
378
+ if(nodes.length === data.length) {
379
+ if(result === true)
380
+ cb.ok(nodes);
381
+ else
382
+ cb.fail(nodes);
383
+ }
384
+ },
385
+ fail: function(unsub_reply) {
386
+ result = false;
387
+ nodes.push(unsub_reply);
388
+ if(nodes.length === data.length)
389
+ cb.fail(nodes);
390
+ }
391
+ });
392
+ im_conn.flush();
393
+ });
394
+
395
+
396
+ im_conn.flush();
397
+ }
398
+ });
399
+ }
400
+
401
+ // PRIVATE FUNCTIONS
402
+
403
+ function _IM_sendIQ(data, cb_ok, cb_fail) {
404
+ im_conn.sendIQ(data, cb_ok, cb_fail);
405
+ }
406
+
407
+ // NOTE: this helper send an IQ with attached system handlers which don't require
408
+ // an authenticated session
409
+ function _IM_sendSysIQ(elem, callback, errback, timeout) {
410
+ var timeoutHandler = null;
411
+ var that = im_conn;
412
+
413
+ if (typeof(elem.tree) === "function") {
414
+ elem = elem.tree();
415
+ }
416
+ var id = elem.getAttribute('id');
417
+
418
+ // inject id if not found
419
+ if (!id) {
420
+ id = im_conn.getUniqueId("sendIQ");
421
+ elem.setAttribute("id", id);
422
+ }
423
+
424
+ var handler = im_conn._addSysHandler(function (stanza) {
425
+
426
+ // remove timeout handler if there is one
427
+ if (timeoutHandler) {
428
+ that.deleteTimedHandler(timeoutHandler);
429
+ }
430
+
431
+ var iqtype = stanza.getAttribute('type');
432
+
433
+ if (iqtype === 'result') {
434
+ if (callback) {
435
+ callback(stanza);
436
+ }
437
+ } else if (iqtype === 'error') {
438
+ if (errback) {
439
+ errback(stanza);
440
+ }
441
+ } else {
442
+ throw {
443
+ name: "StropheError",
444
+ message: "Got bad IQ type of " + iqtype
445
+ };
446
+ }
447
+ }, null, 'iq', null, id);
448
+
449
+ // if timeout specified, setup timeout handler.
450
+ if (timeout) {
451
+ timeoutHandler = im_conn.addTimedHandler(timeout, function () {
452
+ // get rid of normal handler
453
+ that.deleteHandler(handler);
454
+
455
+ // call errback on timeout with null stanza
456
+ if (errback) {
457
+ errback(null);
458
+ }
459
+ return false;
460
+ });
461
+ }
462
+
463
+ im_conn.send(elem);
464
+
465
+ return id;
466
+ }
467
+
468
+ function _IM_connection_manager(status, reason) {
469
+ var fulljid = im_config.fulljid;
470
+ var fail_event = {
471
+ fulljid: fulljid,
472
+ status: status,
473
+ error: reason
474
+ };
475
+
476
+ switch(status) {
477
+ case Strophe.Status.ERROR:
478
+ im_handlers.connection_error(fail_event);
479
+ break;
480
+ case Strophe.Status.CONNFAIL:
481
+ im_handlers.connection_error(fail_event);
482
+ break;
483
+ case Strophe.Status.AUTHFAIL:
484
+ //im_conn.flush();
485
+ fail_event.error = "Authentication Error";
486
+ im_handlers.connection_error(fail_event);
487
+ break;
488
+ case Strophe.Status.CONNECTED:
489
+ _IM_connected();
490
+ im_handlers.connected({fulljid: fulljid});
491
+ break;
492
+ case Strophe.Status.DISCONNECTING:
493
+ im_handlers.disconnecting({
494
+ fulljid: fulljid,
495
+ reason: reason
496
+ });
497
+ break;
498
+ case Strophe.Status.DISCONNECTED:
499
+ im_handlers.disconnected({
500
+ fulljid: fulljid,
501
+ reason: reason
502
+ });
503
+ break;
504
+ }
505
+ }
506
+
507
+ function _IM_connected() {
508
+ // Install Message XMPP Stanzas receiver
509
+ im_conn.addHandler(_IM_receive_message, null, 'message',null,null,null,null);
510
+ // Send presence XMPP Stanzas
511
+ _IM_send_data($pres());
512
+ // Set periodic 5 min ping to confirm our presence
513
+ im_conn.addTimedHandler(5*60*1000, IM_ping);
514
+ }
515
+
516
+ function _IM_send_data(data) {
517
+ im_conn.send(data);
518
+ }
519
+
520
+ function _IM_receive_message(data) {
521
+ var message = $(data);
522
+ var from = message.attr('from');
523
+ var to = message.attr('to');
524
+ var type = message.attr('type');
525
+
526
+ var content = [];
527
+
528
+ if (from.match(/pubsub/i)) {
529
+ var items = $(message.find('items')[0]);
530
+ var node = items.attr('node');
531
+ message.find('item').each(function () {
532
+ content.push($(this).text());
533
+ });
534
+
535
+ if (content.length > 0)
536
+ im_handlers.receive_pubsub_item({node: node, content: content});
537
+ }
538
+ else if (type === "chat") {
539
+ content.push($(message.find('body')[0]).text());
540
+ im_handlers.receive_message({from: from, content: content});
541
+ }
542
+
543
+ return true;
544
+ }
545
+
546
+ // NOTE: simple (non-deep) mixin utility function
547
+ function mixin(target) {
548
+ var src=null;
549
+ for (var i=1; i<arguments.length; i++) {
550
+ src = arguments[i];
551
+ for (var j in src) {
552
+ target[j] = src[j];
553
+ }
554
+ }
555
+
556
+ return target;
557
+ }
558
+
559
+ })();