How do I make a function declared in a closure, global ? This is for a google apps script, hence no window.
There is documentation on how to use closures in google apps scripts, but the example declares an object instead of a function.
http://code.google.com/googleapps/appsscript/articles/appengine.html
var JSON = JSON || {};
// foo = function(){}
(function ()
{
...
foo = function (a, b)
{
...
}
foo.prototype =
{
...
}
// window.foo = foo; // Not Possible
}());
This should work:
var globalFoo;
(function ()
{
...
foo = function (a, b)
{
...
}
foo.prototype =
{
...
}
globalFoo = foo;
// window.foo = foo; // Not Possible
}());
I've made a test in a regular html running on the browser and is works fine. Here is the example:
var globalFoo;
console.log("O1")
console.log(globalFoo);
(function(){
console.log("I1")
console.log(globalFoo);
var x = 13;
var foo = function() {
console.log('foo caled ' + x);
x++;
return true;
}
foo();
globalFoo = foo;
console.log("I2")
console.log(globalFoo);
})();
console.log("O1")
console.log(globalFoo);
console.log(globalFoo());
The firebug output to that is:
O1
undefined
I1
undefined
foo caled 13
I2
function()
O1
function()
foo caled 14
true
Related
I've been going through ziglearn and have made my way to ArrayList. I understand the example given there but when I try something a bit more complex I run into errors. Based on the error it seems like my array doesn't have valid memory when it goes to append the new element, but I've set the initial capacity to 10. What am I doing wrong?
const std = #import("std");
const page_allocator = std.heap.page_allocator;
const Allocator = std.mem.Allocator;
const C = struct {
list: std.ArrayList(A),
pub fn init(allocator: Allocator) !*C {
var a = try std.ArrayList(A).initCapacity(allocator, 10);
return &C{ .list = a };
}
pub fn info(self: *C) void {
std.log.info("len {} cap {}", .{ self.list.items.len, self.list.capacity });
}
pub fn addElement(self: *C, a: A) !*C {
try self.list.append(a);
return self;
}
};
const A = struct { e: []const u8 };
test "with arraylist" {
var foo = try C.init(page_allocator);
foo.info();
_ = try foo.addElement(.{ .e = "bar" });
}
Can see below the initial capacity is not 10, it changes with each run pointing to its uninitialized. Am I missing a step to initialize memory for the ArrayList?
[default] (info): len 0 cap 140728248984328
Segmentation fault at address 0x0
/home/john/zig/zig-linux-x86_64-0.10.0/lib/std/mem/Allocator.zig:159:30: 0x219c3c in reallocAdvancedWithRetAddr__anon_4653 (test)
return self.vtable.resize(self.ptr, buf, buf_align, new_len, len_align, ret_addr);
^
/home/john/zig/zig-linux-x86_64-0.10.0/lib/std/mem/Allocator.zig:356:43: 0x216faf in reallocAtLeast__anon_3534 (test)
return self.reallocAdvancedWithRetAddr(old_mem, old_alignment, new_n, .at_least, #returnAddress());
^
/home/john/zig/zig-linux-x86_64-0.10.0/lib/std/array_list.zig:353:89: 0x215697 in ensureTotalCapacityPrecise (test)
const new_memory = try self.allocator.reallocAtLeast(self.allocatedSlice(), new_capacity);
^
/home/john/zig/zig-linux-x86_64-0.10.0/lib/std/array_list.zig:338:55: 0x2170f6 in ensureTotalCapacity (test)
return self.ensureTotalCapacityPrecise(better_capacity);
^
/home/john/zig/zig-linux-x86_64-0.10.0/lib/std/array_list.zig:377:41: 0x21577c in addOne (test)
try self.ensureTotalCapacity(newlen);
^
/home/john/zig/zig-linux-x86_64-0.10.0/lib/std/array_list.zig:167:49: 0x213c16 in append (test)
const new_item_ptr = try self.addOne();
^
src/main.zig:154:29: 0x213b86 in addElement (test)
try self.list.append(a);
^
src/main.zig:165:27: 0x213ce7 in test.with arraylist (test)
_ = try foo.addElement(.{ .e = "bar" });
^
/home/john/zig/zig-linux-x86_64-0.10.0/lib/test_runner.zig:63:28: 0x2164f0 in main (test)
} else test_fn.func();
^
/home/john/zig/zig-linux-x86_64-0.10.0/lib/std/start.zig:596:22: 0x21463b in posixCallMainAndExit (test)
root.main();
^
/home/john/zig/zig-linux-x86_64-0.10.0/lib/std/start.zig:368:5: 0x214101 in _start (test)
#call(.{ .modifier = .never_inline }, posixCallMainAndExit, .{});
^
Your C.init function returns a pointer to C which is on the stack of the init function. This pointer becomes invalid as soon as the function exits.
Just don't return it as a pointer:
pub fn init(allocator: Allocator) !C {
var a = try std.ArrayList(A).initCapacity(allocator, 10);
return C{ .list = a };
}
Or, alternatively, you could put C into the allocator's memory:
pub fn init(allocator: Allocator) !*C {
var result = try allocator.create(C);
result.list = try std.ArrayList(A).initCapacity(allocator, 10);
return result;
}
But avoid doing this unless you have a good reason, as it limits what you can do with C.
Im migrating my config from another library to node-config.
I have two questions:
The old library uses config.get('a:b'); to get some value, but node-config use a single dot as a delimiter: config.get('a.b');.
Is there is a way to configure it to use : to save my time and refactor my code?
Is there is a way to set a runtime values. e.g. config.set('key', 'val');?
Done it by:
1. wrap node-config in a new js file
2. proxied the get, has and set methods methods
Something like that:
const config = require('config');
const inMemDict = {};
const toNewKey = key => {
return key && key.split(':').join('.');
};
const { get: origGet, has: origHas } = config;
config.get = function (key, ...args) {
key = toNewKey(key);
if(typeof inMemDict[key] !== 'undefined') {
return inMemDict[key];
}
return origGet.apply(config, [key, ...args]);
};
config.has = function (key, ...args) {
key = toNewKey(key);
if(typeof inMemDict[key] !== 'undefined') {
return inMemDict[key];
}
return origHas.apply(config, [key, ...args]);
};
config.set = function (key, val) {
if(!key) return;
inMemDict[toNewKey(key)] = val;
};
module.exports = config;
I'm using frida on an APK and I'm trying to print out which function is being called, and especially which parameters are sent to it. My environment is set correctly as I can print out classes, and perform various actions in accordance to the docs.
This is the closest i've found:
https://codeshare.frida.re/#razaina/get-a-stack-trace-in-your-hook/
But the code gives out errors (ThreadDef undefined and so on)
And the frida docs didn't help me get where I'm trying to.
Any guidance? suggestions? help?
The code from codeshare#razaina has bugs which can be easily fixed (threadef != ThreadDef)
var printBacktrace = function () {
Java.perform(function() {
var JLog = Java.use('android.util.Log'), JException = Java.use('java.lang.Exception');
// getting stacktrace by throwing an exception
console.warn(JLog.getStackTraceString(JException.$new()));
});
};
Just call printBacktrace() w/e you want to see who called your hooked function.
If you want to hook all the methods of Java class you can use this snippet;
var Color = {
RESET: "\x1b[39;49;00m", Black: "0;01", Blue: "4;01", Cyan: "6;01", Gray: "7;11", Green: "2;01", Purple: "5;01", Red: "1;01", Yellow: "3;01",
Light: {
Black: "0;11", Blue: "4;11", Cyan: "6;11", Gray: "7;01", Green: "2;11", Purple: "5;11", Red: "1;11", Yellow: "3;11"
}
};
/**
*
* #param input.
* If an object is passed it will print as json
* #param kwargs options map {
* -l level: string; log/warn/error
* -i indent: boolean; print JSON prettify
* -c color: #see ColorMap
* }
*/
var LOG = function (input, kwargs) {
kwargs = kwargs || {};
var logLevel = kwargs['l'] || 'log', colorPrefix = '\x1b[3', colorSuffix = 'm';
if (typeof input === 'object')
input = JSON.stringify(input, null, kwargs['i'] ? 2 : null);
if (kwargs['c'])
input = colorPrefix + kwargs['c'] + colorSuffix + input + Color.RESET;
console[logLevel](input);
};
var printBacktrace = function () {
Java.perform(function() {
var android_util_Log = Java.use('android.util.Log'), java_lang_Exception = Java.use('java.lang.Exception');
// getting stacktrace by throwing an exception
LOG(android_util_Log.getStackTraceString(java_lang_Exception.$new()), { c: Color.Gray });
});
};
function traceClass(targetClass) {
var hook;
try {
hook = Java.use(targetClass);
} catch (e) {
console.error("trace class failed", e);
return;
}
var methods = hook.class.getDeclaredMethods();
hook.$dispose();
var parsedMethods = [];
methods.forEach(function (method) {
var methodStr = method.toString();
var methodReplace = methodStr.replace(targetClass + ".", "TOKEN").match(/\sTOKEN(.*)\(/)[1];
parsedMethods.push(methodReplace);
});
uniqBy(parsedMethods, JSON.stringify).forEach(function (targetMethod) {
traceMethod(targetClass + '.' + targetMethod);
});
}
function traceMethod(targetClassMethod) {
var delim = targetClassMethod.lastIndexOf('.');
if (delim === -1)
return;
var targetClass = targetClassMethod.slice(0, delim);
var targetMethod = targetClassMethod.slice(delim + 1, targetClassMethod.length);
var hook = Java.use(targetClass);
var overloadCount = hook[targetMethod].overloads.length;
LOG({ tracing: targetClassMethod, overloaded: overloadCount }, { c: Color.Green });
for (var i = 0; i < overloadCount; i++) {
hook[targetMethod].overloads[i].implementation = function () {
var log = { '#': targetClassMethod, args: [] };
for (var j = 0; j < arguments.length; j++) {
var arg = arguments[j];
// quick&dirty fix for java.io.StringWriter char[].toString() impl because frida prints [object Object]
if (j === 0 && arguments[j]) {
if (arguments[j].toString() === '[object Object]') {
var s = [];
for (var k = 0, l = arguments[j].length; k < l; k++) {
s.push(arguments[j][k]);
}
arg = s.join('');
}
}
log.args.push({ i: j, o: arg, s: arg ? arg.toString(): 'null'});
}
var retval;
try {
retval = this[targetMethod].apply(this, arguments); // might crash (Frida bug?)
log.returns = { val: retval, str: retval ? retval.toString() : null };
} catch (e) {
console.error(e);
}
LOG(log, { c: Color.Blue });
return retval;
}
}
}
// remove duplicates from array
function uniqBy(array, key) {
var seen = {};
return array.filter(function (item) {
var k = key(item);
return seen.hasOwnProperty(k) ? false : (seen[k] = true);
});
}
var Main = function() {
Java.perform(function () { // avoid java.lang.ClassNotFoundException
[
// "java.io.File",
'java.net.Socket',
'com.package.MyCustomClass'
].forEach(traceClass);
});
};
Java.perform(Main);
I am building an advanced search UI similar to the TFS query builder web interface. Using knockout for the client side implementation and have everything more or less working except the final validation to make certain required items are basically selected. It sort-of works as far as giving me a validation error if I select an item and then de-select the item. Which is fine, but I would like to have the form validate when hitting the search button.
I am pretty sure I need to make use of the ko.validatedobservable method, I'm just not sure exactly how. Anyway, I have a fiddle to look at: http://jsfiddle.net/sstolp/uXBSA/ if anyone has the time or inclination to help me out. I would deeply appreciate it.
Thank you for your time.
scvm.SearchLine = function () {
var self = this;
self.selectedField = ko.observable().extend({ required: true });
self.selectedOperator = ko.observable().extend({ required: true });
self.firstdate = ko.observable(new Date());
self.lastdate = ko.observable(new Date());
self.thedate = ko.observable(new Date());
return self;};
scvm.Criteria = function () {
var self = this,
lines = ko.observableArray([]),
// Put one line in by default
loadInitialData = function () {
lines.push(new scvm.SearchLine());
},
rowcount = ko.computed(function () {
return lines().length;
}),
// Operations
addLine = function () {
lines.push(new scvm.SearchLine());
},
removeLine = function (line) {
lines.remove(line);
},
search = function () {
var data = $.map(lines(), function (line) {
return line.selectedField() ? {
selectedField: line.selectedField().searchfield,
selectedOperator: line.selectedOperator().name,
} : undefined
});
alert("Send to server: " + JSON.stringify(data));
},
clear = function () {
lines.removeAll();
};
return {
lines: lines,
loadInitialData: loadInitialData,
rowcount: rowcount,
addLine: addLine,
removeLine: removeLine,
search: search,
clear: clear
};
}();
Yes, all your SearchLine objects must be wrapped into ko.validatedObservable. Also you should implement computed property which will check isValid() for each criteria line and return global validity flag.
scvm.SearchLine = function () {
var self = this;
self.selectedField = ko.observable().extend({ required: true });
self.selectedOperator = ko.observable().extend({ required: true });
self.firstdate = ko.observable(new Date());
self.lastdate = ko.observable(new Date());
self.thedate = ko.observable(new Date());
return ko.validatedObservable(self);
};
scvm.Criteria = function () {
// ...
return {
lines: lines,
loadInitialData: loadInitialData,
rowcount: rowcount,
addLine: addLine,
removeLine: removeLine,
search: search,
clear: clear,
// new property that indicates validity of all lines
linesValid: ko.computed(function(){
var items = lines();
for (var i = 0, l = items.length; i < l; i++)
if (!items[i].isValid()) return false;
return true;
})
};
}();
This new property can be used in enable binding of you "Search" button:
<input type="button"
data-bind="enable: linesValid, click: search"
title="Clicking this button will run a search."
value="Search" />
I've modified your fiddle. Take a look: http://jsfiddle.net/ostgals/uXBSA/8/
Update:
Also we should slightly modify Criteria.search method, since our line array contains observables rather than objects:
//...
search = function () {
var data = $.map(lines(), function (line) {
line = ko.utils.unwrapObservable(line);
return line.selectedField() ? {
selectedField: line.selectedField().searchfield,
selectedOperator: line.selectedOperator().name,
} : undefined
});
alert("Send to server: " + JSON.stringify(data));
},
//...
I am new in google closure compiler,and after read the documents in the closure tools site,I create a js and make the test.
However I found that even I use the Advanced Compilation level,the compiled codes are still easy to decompilated.
For example,this is the codes:
//2
window["_NameSpace_"]={};
window["_NameSpaceInternal_"]={};
(function() {
_NameSpaceInternal_.Class = function() {
var clazz = function() {
this["init"] && this["init"].apply(this, arguments);
};
var pros = {}, arg;
for(var c = 0, k = arguments.length; c < k; ++c) {
arg = arguments[c];
if( typeof arg === 'function') {
if(c == 0 && k > 1) {
var F = function() {
};
F.prototype = arg.prototype;
pros = new F;
arg = arg.prototype;
}
} else {
if(arg.init) {
clazz = arg["init"];
delete arg["init"]
}
}
}
for(var p in arg)
pros[p] = arg[p]
clazz.prototype = pros;
return clazz;
};
})();
(function(d){
d["Person"]=_NameSpaceInternal_.Class({
"init":function(name){
this.name=name;
},
"whatever":function(aaa){
}
});
})(_NameSpace_);
After compiled(I make a pretty format for human reading):
window.__MapNS__ = {};
window.__MapNSImpl__ = {};
__MapNSImpl__.a = function() {
function c() {
this.init && this.init.apply(this, arguments)
}
for (var b = {}, a, d = 0, e = arguments.length; d < e; ++d) if (a = arguments[d], "function" === typeof a) 0 == d && 1 < e && (b = function() {}, b.prototype = a.prototype, b = new b, a = a.prototype);
else {
a.b && (c = a.init, delete a.init)
}
if (!b || !a) throw Error("You must provide an object to copy from and to");
for (var f in a) b[f] = a[f];
c.prototype = b;
return c
};
(function(c) {
c.Person = __MapNSImpl__.a({
init: function(b) {
this.name = b
},
whatever:function(x){
}
})
})(__MapNS__);
Now,taks the class defination for "Person" for example, after compiled,all the methods for "Person" are clearly for hacker even these method have to be exposed.
But I wonder if I can make the compiled codes like this;
...........
var xx="init",xxx="whatever",xxxx=="Person";
c[xxxx] = __MapNSImpl__.a({
xx: function(b) {
this.name = b
},
xxx:function(x){
}
})
...........
Just like the google map's compress.
Any idea?
The exact answer you are looking for is to enable the AliasStrings pass in the compiler by either using the Java API or by making a custom build of the compiler. The pass is not enabled by default as it tends to produce larger code when accounting for gzip.
To actually get the same effect that most google products achieve, you'll need to make substantial changes to your code.
Define your objects and methods in the global scope. Assign them to namespaces after declaring them globally. You can use the output_wrapper flag to wrap the compiled code in a function to prevent global scope collisions. Example:
function a() {}; window['Namespace']['obj'] = a;
Define your objects directly - don't use a helper method. So instead of
var a = _NameSpaceInternal_.Class({"init":function(name){ this.name=name; });
You would use something like:
function a(){}; a.prototype.name = ""; a.prototype.init = function(name) { this.name=name; };
This avoids using quoted syntax and allows the compiler to rename your properties and methods.
For many more examples of coding style that compiles/renames optimally with Closure-compiler, see the Closure Library.