Skip to content

Commit 220e9fb

Browse files
committed
Add DEFER feature.
1 parent 773d38a commit 220e9fb

3 files changed

Lines changed: 95 additions & 21 deletions

File tree

changes.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
- added: `U.upload(files, url, [callback], [cookies], [headers], [method], [timeout])` for multiple uploading files
1919
- added: `RESTBuilder.redirect(true/false)` enables/disables auto-redirect (default: enabled)
2020
- added: new schema aliases (`$QUERY()`, `$GET()`, `$WORKFLOW()`, '$TRANSFORM()' and `$OPERATION()`)
21+
- added: `F.config['allow-defer']` enables deferring functions with `DEFER` keyword (default: true)
22+
- added: `DEFER` feature
2123

2224
- updated: `F.route()`, `F.websocket()` and `F.file()` --> now returns `FrameworkRoute` instance instead of `Framework` instance (more in docs)
2325
- updated: `F.load(debug, [types], [path])` supports a new type `service` which enables `F.on('service')`

index.js

Lines changed: 82 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,7 @@ function Framework() {
571571
'allow-performance': false,
572572
'allow-custom-titles': false,
573573
'allow-cache-snapshot': false,
574+
'allow-defer': true,
574575
'disable-strict-server-certificate-validation': true,
575576
'disable-clear-temporary-directory': false,
576577

@@ -667,7 +668,8 @@ function Framework() {
667668
other: {},
668669
internal: {}, // controllers/modules names for the routing
669670
owners: {},
670-
ready: {}
671+
ready: {},
672+
defer: {}
671673
};
672674

673675
this.stats = {
@@ -2750,6 +2752,12 @@ F.error = function(err, name, uri) {
27502752
F.errors.length > 50 && F.errors.shift();
27512753
}
27522754

2755+
if (!name && !uri && err.stack) {
2756+
var defer = err.stack.match(/\/\w+\/defer\-.*?\.js/);
2757+
if (defer)
2758+
err.stack = err.stack.replace(defer, defer.toString()).replace(/\/\w+\/defer\-/, '/').split('$').join('/');
2759+
}
2760+
27532761
F.onError(err, name, uri);
27542762
return F;
27552763
};
@@ -3243,7 +3251,7 @@ F.install = function(type, name, declaration, options, callback, internal, useRe
32433251

32443252
if (type === 'middleware') {
32453253

3246-
F.routes.middleware[name] = typeof(declaration) === 'function' ? declaration : eval(declaration);
3254+
F.routes.middleware[name] = typeof(declaration) === 'function' ? declaration : eval(parseDefer(declaration));
32473255
F._length_middleware = Object.keys(F.routes.middleware).length;
32483256

32493257
next && next();
@@ -3362,7 +3370,7 @@ F.install = function(type, name, declaration, options, callback, internal, useRe
33623370
try {
33633371
var filecomponent = F.path.temp('component-' + name + '.js');
33643372
_owner = (packageName ? packageName + '@' : '') + type + '#' + name;
3365-
Fs.writeFileSync(filecomponent, content.install.trim());
3373+
Fs.writeFileSync(filecomponent, parseDefer(content.install.trim()));
33663374
obj = require(filecomponent);
33673375

33683376
(function(name) {
@@ -3444,6 +3452,7 @@ F.install = function(type, name, declaration, options, callback, internal, useRe
34443452
if (type === 'theme') {
34453453

34463454
_owner = (packageName ? packageName + '@' : '') + type + '#' + name;
3455+
declaration = parseDeferFile(type, declaration);
34473456
obj = require(declaration);
34483457
obj.$owner = _owner;
34493458
F.temporary.owners[_owner] = true;
@@ -3525,6 +3534,7 @@ F.install = function(type, name, declaration, options, callback, internal, useRe
35253534
try {
35263535

35273536
if (useRequired) {
3537+
declaration = parseDeferFile(type, declaration);
35283538
delete require.cache[require.resolve(declaration)];
35293539
obj = require(declaration);
35303540

@@ -3533,7 +3543,7 @@ F.install = function(type, name, declaration, options, callback, internal, useRe
35333543
})(require.resolve(declaration));
35343544
}
35353545
else
3536-
obj = typeof(declaration) === 'function' ? eval('(' + declaration.toString() + ')()') : eval(declaration);
3546+
obj = typeof(declaration) === 'function' ? eval('(' + parseDefer(declaration.toString()) + ')()') : eval(parseDefer(declaration));
35373547

35383548
} catch (ex) {
35393549
err = ex;
@@ -3572,6 +3582,7 @@ F.install = function(type, name, declaration, options, callback, internal, useRe
35723582
}
35733583

35743584
if (useRequired) {
3585+
declaration = parseDeferFile(type, declaration);
35753586
delete require.cache[require.resolve(declaration)];
35763587
obj = require(declaration);
35773588
content = Fs.readFileSync(declaration).toString(ENCODING);
@@ -3580,7 +3591,7 @@ F.install = function(type, name, declaration, options, callback, internal, useRe
35803591
})(require.resolve(declaration));
35813592
}
35823593
else {
3583-
obj = typeof(declaration) === 'function' ? eval('(' + declaration.toString() + ')()') : eval(declaration);
3594+
obj = typeof(declaration) === 'function' ? eval('(' + parseDefer(declaration.toString()) + ')()') : eval(parseDefer(declaration));
35843595
content = declaration.toString();
35853596
}
35863597

@@ -3633,6 +3644,7 @@ F.install = function(type, name, declaration, options, callback, internal, useRe
36333644
try {
36343645

36353646
if (useRequired) {
3647+
declaration = parseDeferFile(type, declaration);
36363648
obj = require(declaration);
36373649
(function(name) {
36383650
setTimeout(() => delete require.cache[name], 1000);
@@ -3650,7 +3662,7 @@ F.install = function(type, name, declaration, options, callback, internal, useRe
36503662
}
36513663

36523664
var filename = F.path.temporary(plus + 'installed-' + type + '-' + U.GUID(10) + '.js');
3653-
Fs.writeFileSync(filename, declaration);
3665+
Fs.writeFileSync(filename, parseDefer(declaration));
36543666
obj = require(filename);
36553667

36563668
(function(name, filename) {
@@ -3733,6 +3745,7 @@ F.install = function(type, name, declaration, options, callback, internal, useRe
37333745

37343746
try {
37353747
if (useRequired) {
3748+
declaration = parseDeferFile(type, declaration);
37363749
obj = require(declaration);
37373750
(function(name) {
37383751
setTimeout(function() {
@@ -3751,7 +3764,7 @@ F.install = function(type, name, declaration, options, callback, internal, useRe
37513764
}
37523765

37533766
filename = F.path.temporary(plus + 'installed-' + type + '-' + U.GUID(10) + '.js');
3754-
Fs.writeFileSync(filename, declaration);
3767+
Fs.writeFileSync(filename, parseDefer(declaration));
37553768
obj = require(filename);
37563769
(function(name, filename) {
37573770
setTimeout(function() {
@@ -3965,7 +3978,8 @@ F.$restart = function() {
39653978
other: {},
39663979
internal: {},
39673980
owners: {},
3968-
ready: {}
3981+
ready: {},
3982+
defer: {}
39693983
};
39703984

39713985
F.modificators = null;
@@ -4854,6 +4868,7 @@ F.usage = function(detailed) {
48544868
var staticNotfound = Object.keys(F.temporary.notfound);
48554869
var staticRange = Object.keys(F.temporary.range);
48564870
var redirects = Object.keys(F.routes.redirects);
4871+
var defer = Object.keys(F.temporary.defer);
48574872
var output = {};
48584873

48594874
output.framework = {
@@ -4895,7 +4910,8 @@ F.usage = function(detailed) {
48954910
streaming: staticRange.length,
48964911
modificator: F.modificators ? F.modificators.length : 0,
48974912
viewphrases: $VIEWCACHE.length,
4898-
uptodates: F.uptodates ? F.uptodates.length : 0
4913+
uptodates: F.uptodates ? F.uptodates.length : 0,
4914+
defer: defer.length
48994915
};
49004916

49014917
output.routing = {
@@ -15260,6 +15276,63 @@ function parseSchema(name) {
1526015276
return schema;
1526115277
}
1526215278

15279+
function parseDefer(code) {
15280+
15281+
if (!F.config['allow-defer'])
15282+
return code;
15283+
15284+
var beg = code.indexOf('function DEFER(');
15285+
if (beg === -1)
15286+
return code;
15287+
15288+
var b = code.indexOf('{', beg);
15289+
var end = -1;
15290+
var count = 0;
15291+
var indexer = b + 1;
15292+
15293+
while (true) {
15294+
var c = code[indexer++];
15295+
15296+
if (!c)
15297+
break;
15298+
15299+
if (c === '{') {
15300+
count++;
15301+
continue;
15302+
}
15303+
15304+
if (c === '}') {
15305+
if (count) {
15306+
count--;
15307+
continue;
15308+
}
15309+
end = indexer;
15310+
break;
15311+
}
15312+
}
15313+
15314+
if (end === -1)
15315+
return code;
15316+
15317+
var scope = code.substring(beg, end);
15318+
var id = 'D' + scope.hash().toString().replace('-', '_');
15319+
code = code.replace(scope, 'F.temporary.defer.' + id);
15320+
scope = U.minifyScript(scope.trim().replace(' DEFER(', '('));
15321+
F.temporary.defer[id] = new Function('return ' + parseDefer(scope))();
15322+
return parseDefer(code);
15323+
}
15324+
15325+
function parseDeferFile(type, filename) {
15326+
if (!F.config['allow-defer'])
15327+
return filename;
15328+
var data = Fs.readFileSync(filename).toString(ENCODING);
15329+
if (data.indexOf(' DEFER(') === -1)
15330+
return filename;
15331+
var tmp = F.path.temp('defer-' + type + '$' + U.getName(filename));
15332+
Fs.writeFileSync(tmp, parseDefer(data));
15333+
return tmp;
15334+
}
15335+
1526315336
// Because of controller prototypes
1526415337
// It's used in F.view() and F.viewCompile()
1526515338
const EMPTYCONTROLLER = new Controller('', null, null, null, '');

test/controllers/default.js

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ exports.install = function() {
44

55
F.localize('/templates/');
66

7-
F.route(function(url, req, flags) {
7+
F.route(function DEFER(url, req, flags) {
88
return url === '/custom/route/';
9-
}, function() {
9+
}, function DEFER() {
1010
this.plain('CUSTOM');
1111
});
1212

@@ -22,7 +22,7 @@ exports.install = function() {
2222
this.plain('OK');
2323
}, ['unauthorize']);
2424
*/
25-
F.route('/', function() {
25+
F.route('/', function DEFER() {
2626
this.plain('ROBOT');
2727
}, ['robot']);
2828

@@ -67,7 +67,7 @@ exports.install = function() {
6767
F.route('/translate/', viewTranslate);
6868
F.route('/test-view/', view_test_view);
6969
F.route('/login/google/callback/', aa);
70-
F.route('/timeout/', function() {}, [50]);
70+
F.route('/timeout/', function DEFER() {}, [50]);
7171

7272
F.route('/get/', plain_get);
7373
F.route('/post/raw/', plain_post_raw, ['post', 'raw']);
@@ -91,7 +91,7 @@ exports.install = function() {
9191

9292
F.redirect('http://www.google.sk', 'http://www.petersirka.sk');
9393

94-
F.route('#408', function() {
94+
F.route('#408', function DEFER() {
9595
var self = this;
9696
F.global.timeout++;
9797
self.plain('408');
@@ -243,8 +243,7 @@ function file_plain_status(req, res, isValidation) {
243243

244244
function resize_image(req, res) {
245245
var fs = require('fs');
246-
this.responseImage(req, res, fs.createReadStream(this.path.public(req.url)), function(image) {
247-
//this.responseImageWithoutCache(req, res, this.path.public(req.url), function(image) {
246+
this.responseImage(req, res, fs.createReadStream(this.path.public(req.url)), function DEFER(image) {
248247
image.resize('20%');
249248
});
250249
}
@@ -335,30 +334,30 @@ function viewCustomTesting() {/*
335334
B: true
336335
}]));*/
337336
this.plain(this.template('new', [{ tag: '<b>A</b>' }, { tag: '<b>B</b>' }]));
338-
setTimeout(function() {
337+
setTimeout(function DEFER() {
339338
framework.stop();
340339
}, 500);
341340
}
342341

343342
function socket(self, framework) {
344343

345-
self.on('open', function(client) {
344+
self.on('open', function DEFER(client) {
346345
console.log('open ->', client.id);
347346
console.log(client.get);
348347
});
349348

350-
self.on('close', function(client) {
349+
self.on('close', function DEFER(client) {
351350
console.log('close ->', client.id);
352351
});
353352

354-
self.on('message', function(client, message) {
353+
self.on('message', function DEFER(client, message) {
355354
console.log('message ->', client.id, message);
356355

357356
if (message === 'disconnect')
358357
client.close();
359358
});
360359

361-
self.on('error', function(error, client) {
360+
self.on('error', function DEFER(error, client) {
362361
console.log('error –>', error);
363362
});
364363
}

0 commit comments

Comments
 (0)