lively.vm
Version:
Controlled JavaScript code execution and instrumentation.
1,659 lines (1,417 loc) • 1.1 MB
JavaScript
// INLINED /home/robertkrahn/projects/lively/lively.next-node_modules/babel-regenerator-runtime/6.5.0/runtime.js
/**
* Copyright (c) 2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* https://raw.github.com/facebook/regenerator/master/LICENSE file. An
* additional grant of patent rights can be found in the PATENTS file in
* the same directory.
*/
!(function(global) {
"use strict";
var hasOwn = Object.prototype.hasOwnProperty;
var undefined; // More compressible than void 0.
var iteratorSymbol =
typeof Symbol === "function" && Symbol.iterator || "@@iterator";
var inModule = typeof module === "object";
var runtime = global.regeneratorRuntime;
if (runtime) {
if (inModule) {
// If regeneratorRuntime is defined globally and we're in a module,
// make the exports object identical to regeneratorRuntime.
module.exports = runtime;
}
// Don't bother evaluating the rest of this file if the runtime was
// already defined globally.
return;
}
// Define the runtime globally (as expected by generated code) as either
// module.exports (if we're in a module) or a new, empty object.
runtime = global.regeneratorRuntime = inModule ? module.exports : {};
function wrap(innerFn, outerFn, self, tryLocsList) {
// If outerFn provided, then outerFn.prototype instanceof Generator.
var generator = Object.create((outerFn || Generator).prototype);
var context = new Context(tryLocsList || []);
// The ._invoke method unifies the implementations of the .next,
// .throw, and .return methods.
generator._invoke = makeInvokeMethod(innerFn, self, context);
return generator;
}
runtime.wrap = wrap;
// Try/catch helper to minimize deoptimizations. Returns a completion
// record like context.tryEntries[i].completion. This interface could
// have been (and was previously) designed to take a closure to be
// invoked without arguments, but in all the cases we care about we
// already have an existing method we want to call, so there's no need
// to create a new function object. We can even get away with assuming
// the method takes exactly one argument, since that happens to be true
// in every case, so we don't have to touch the arguments object. The
// only additional allocation required is the completion record, which
// has a stable shape and so hopefully should be cheap to allocate.
function tryCatch(fn, obj, arg) {
try {
return { type: "normal", arg: fn.call(obj, arg) };
} catch (err) {
return { type: "throw", arg: err };
}
}
var GenStateSuspendedStart = "suspendedStart";
var GenStateSuspendedYield = "suspendedYield";
var GenStateExecuting = "executing";
var GenStateCompleted = "completed";
// Returning this object from the innerFn has the same effect as
// breaking out of the dispatch switch statement.
var ContinueSentinel = {};
// Dummy constructor functions that we use as the .constructor and
// .constructor.prototype properties for functions that return Generator
// objects. For full spec compliance, you may wish to configure your
// minifier not to mangle the names of these two functions.
function Generator() {}
function GeneratorFunction() {}
function GeneratorFunctionPrototype() {}
var Gp = GeneratorFunctionPrototype.prototype = Generator.prototype;
GeneratorFunction.prototype = Gp.constructor = GeneratorFunctionPrototype;
GeneratorFunctionPrototype.constructor = GeneratorFunction;
GeneratorFunction.displayName = "GeneratorFunction";
// Helper for defining the .next, .throw, and .return methods of the
// Iterator interface in terms of a single ._invoke method.
function defineIteratorMethods(prototype) {
["next", "throw", "return"].forEach(function(method) {
prototype[method] = function(arg) {
return this._invoke(method, arg);
};
});
}
runtime.isGeneratorFunction = function(genFun) {
var ctor = typeof genFun === "function" && genFun.constructor;
return ctor
? ctor === GeneratorFunction ||
// For the native GeneratorFunction constructor, the best we can
// do is to check its .name property.
(ctor.displayName || ctor.name) === "GeneratorFunction"
: false;
};
runtime.mark = function(genFun) {
if (Object.setPrototypeOf) {
Object.setPrototypeOf(genFun, GeneratorFunctionPrototype);
} else {
genFun.__proto__ = GeneratorFunctionPrototype;
}
genFun.prototype = Object.create(Gp);
return genFun;
};
// Within the body of any async function, `await x` is transformed to
// `yield regeneratorRuntime.awrap(x)`, so that the runtime can test
// `value instanceof AwaitArgument` to determine if the yielded value is
// meant to be awaited. Some may consider the name of this method too
// cutesy, but they are curmudgeons.
runtime.awrap = function(arg) {
return new AwaitArgument(arg);
};
function AwaitArgument(arg) {
this.arg = arg;
}
function AsyncIterator(generator) {
// This invoke function is written in a style that assumes some
// calling function (or Promise) will handle exceptions.
function invoke(method, arg) {
var result = generator[method](arg);
var value = result.value;
return value instanceof AwaitArgument
? Promise.resolve(value.arg).then(invokeNext, invokeThrow)
: Promise.resolve(value).then(function(unwrapped) {
// When a yielded Promise is resolved, its final value becomes
// the .value of the Promise<{value,done}> result for the
// current iteration. If the Promise is rejected, however, the
// result for this iteration will be rejected with the same
// reason. Note that rejections of yielded Promises are not
// thrown back into the generator function, as is the case
// when an awaited Promise is rejected. This difference in
// behavior between yield and await is important, because it
// allows the consumer to decide what to do with the yielded
// rejection (swallow it and continue, manually .throw it back
// into the generator, abandon iteration, whatever). With
// await, by contrast, there is no opportunity to examine the
// rejection reason outside the generator function, so the
// only option is to throw it from the await expression, and
// let the generator function handle the exception.
result.value = unwrapped;
return result;
});
}
if (typeof process === "object" && process.domain) {
invoke = process.domain.bind(invoke);
}
var invokeNext = invoke.bind(generator, "next");
var invokeThrow = invoke.bind(generator, "throw");
var invokeReturn = invoke.bind(generator, "return");
var previousPromise;
function enqueue(method, arg) {
function callInvokeWithMethodAndArg() {
return invoke(method, arg);
}
return previousPromise =
// If enqueue has been called before, then we want to wait until
// all previous Promises have been resolved before calling invoke,
// so that results are always delivered in the correct order. If
// enqueue has not been called before, then it is important to
// call invoke immediately, without waiting on a callback to fire,
// so that the async generator function has the opportunity to do
// any necessary setup in a predictable way. This predictability
// is why the Promise constructor synchronously invokes its
// executor callback, and why async functions synchronously
// execute code before the first await. Since we implement simple
// async functions in terms of async generators, it is especially
// important to get this right, even though it requires care.
previousPromise ? previousPromise.then(
callInvokeWithMethodAndArg,
// Avoid propagating failures to Promises returned by later
// invocations of the iterator.
callInvokeWithMethodAndArg
) : new Promise(function (resolve) {
resolve(callInvokeWithMethodAndArg());
});
}
// Define the unified helper method that is used to implement .next,
// .throw, and .return (see defineIteratorMethods).
this._invoke = enqueue;
}
defineIteratorMethods(AsyncIterator.prototype);
// Note that simple async functions are implemented on top of
// AsyncIterator objects; they just return a Promise for the value of
// the final result produced by the iterator.
runtime.async = function(innerFn, outerFn, self, tryLocsList) {
var iter = new AsyncIterator(
wrap(innerFn, outerFn, self, tryLocsList)
);
return runtime.isGeneratorFunction(outerFn)
? iter // If outerFn is a generator, return the full iterator.
: iter.next().then(function(result) {
return result.done ? result.value : iter.next();
});
};
function makeInvokeMethod(innerFn, self, context) {
var state = GenStateSuspendedStart;
return function invoke(method, arg) {
if (state === GenStateExecuting) {
throw new Error("Generator is already running");
}
if (state === GenStateCompleted) {
if (method === "throw") {
throw arg;
}
// Be forgiving, per 25.3.3.3.3 of the spec:
// https://people.mozilla.org/~jorendorff/es6-draft.html#sec-generatorresume
return doneResult();
}
while (true) {
var delegate = context.delegate;
if (delegate) {
if (method === "return" ||
(method === "throw" && delegate.iterator[method] === undefined)) {
// A return or throw (when the delegate iterator has no throw
// method) always terminates the yield* loop.
context.delegate = null;
// If the delegate iterator has a return method, give it a
// chance to clean up.
var returnMethod = delegate.iterator["return"];
if (returnMethod) {
var record = tryCatch(returnMethod, delegate.iterator, arg);
if (record.type === "throw") {
// If the return method threw an exception, let that
// exception prevail over the original return or throw.
method = "throw";
arg = record.arg;
continue;
}
}
if (method === "return") {
// Continue with the outer return, now that the delegate
// iterator has been terminated.
continue;
}
}
var record = tryCatch(
delegate.iterator[method],
delegate.iterator,
arg
);
if (record.type === "throw") {
context.delegate = null;
// Like returning generator.throw(uncaught), but without the
// overhead of an extra function call.
method = "throw";
arg = record.arg;
continue;
}
// Delegate generator ran and handled its own exceptions so
// regardless of what the method was, we continue as if it is
// "next" with an undefined arg.
method = "next";
arg = undefined;
var info = record.arg;
if (info.done) {
context[delegate.resultName] = info.value;
context.next = delegate.nextLoc;
} else {
state = GenStateSuspendedYield;
return info;
}
context.delegate = null;
}
if (method === "next") {
context._sent = arg;
if (state === GenStateSuspendedYield) {
context.sent = arg;
} else {
context.sent = undefined;
}
} else if (method === "throw") {
if (state === GenStateSuspendedStart) {
state = GenStateCompleted;
throw arg;
}
if (context.dispatchException(arg)) {
// If the dispatched exception was caught by a catch block,
// then let that catch block handle the exception normally.
method = "next";
arg = undefined;
}
} else if (method === "return") {
context.abrupt("return", arg);
}
state = GenStateExecuting;
var record = tryCatch(innerFn, self, context);
if (record.type === "normal") {
// If an exception is thrown from innerFn, we leave state ===
// GenStateExecuting and loop back for another invocation.
state = context.done
? GenStateCompleted
: GenStateSuspendedYield;
var info = {
value: record.arg,
done: context.done
};
if (record.arg === ContinueSentinel) {
if (context.delegate && method === "next") {
// Deliberately forget the last sent value so that we don't
// accidentally pass it on to the delegate.
arg = undefined;
}
} else {
return info;
}
} else if (record.type === "throw") {
state = GenStateCompleted;
// Dispatch the exception by looping back around to the
// context.dispatchException(arg) call above.
method = "throw";
arg = record.arg;
}
}
};
}
// Define Generator.prototype.{next,throw,return} in terms of the
// unified ._invoke helper method.
defineIteratorMethods(Gp);
Gp[iteratorSymbol] = function() {
return this;
};
Gp.toString = function() {
return "[object Generator]";
};
function pushTryEntry(locs) {
var entry = { tryLoc: locs[0] };
if (1 in locs) {
entry.catchLoc = locs[1];
}
if (2 in locs) {
entry.finallyLoc = locs[2];
entry.afterLoc = locs[3];
}
this.tryEntries.push(entry);
}
function resetTryEntry(entry) {
var record = entry.completion || {};
record.type = "normal";
delete record.arg;
entry.completion = record;
}
function Context(tryLocsList) {
// The root entry object (effectively a try statement without a catch
// or a finally block) gives us a place to store values thrown from
// locations where there is no enclosing try statement.
this.tryEntries = [{ tryLoc: "root" }];
tryLocsList.forEach(pushTryEntry, this);
this.reset(true);
}
runtime.keys = function(object) {
var keys = [];
for (var key in object) {
keys.push(key);
}
keys.reverse();
// Rather than returning an object with a next method, we keep
// things simple and return the next function itself.
return function next() {
while (keys.length) {
var key = keys.pop();
if (key in object) {
next.value = key;
next.done = false;
return next;
}
}
// To avoid creating an additional object, we just hang the .value
// and .done properties off the next function object itself. This
// also ensures that the minifier will not anonymize the function.
next.done = true;
return next;
};
};
function values(iterable) {
if (iterable) {
var iteratorMethod = iterable[iteratorSymbol];
if (iteratorMethod) {
return iteratorMethod.call(iterable);
}
if (typeof iterable.next === "function") {
return iterable;
}
if (!isNaN(iterable.length)) {
var i = -1, next = function next() {
while (++i < iterable.length) {
if (hasOwn.call(iterable, i)) {
next.value = iterable[i];
next.done = false;
return next;
}
}
next.value = undefined;
next.done = true;
return next;
};
return next.next = next;
}
}
// Return an iterator with no values.
return { next: doneResult };
}
runtime.values = values;
function doneResult() {
return { value: undefined, done: true };
}
Context.prototype = {
constructor: Context,
reset: function(skipTempReset) {
this.prev = 0;
this.next = 0;
this.sent = undefined;
this.done = false;
this.delegate = null;
this.tryEntries.forEach(resetTryEntry);
if (!skipTempReset) {
for (var name in this) {
// Not sure about the optimal order of these conditions:
if (name.charAt(0) === "t" &&
hasOwn.call(this, name) &&
!isNaN(+name.slice(1))) {
this[name] = undefined;
}
}
}
},
stop: function() {
this.done = true;
var rootEntry = this.tryEntries[0];
var rootRecord = rootEntry.completion;
if (rootRecord.type === "throw") {
throw rootRecord.arg;
}
return this.rval;
},
dispatchException: function(exception) {
if (this.done) {
throw exception;
}
var context = this;
function handle(loc, caught) {
record.type = "throw";
record.arg = exception;
context.next = loc;
return !!caught;
}
for (var i = this.tryEntries.length - 1; i >= 0; --i) {
var entry = this.tryEntries[i];
var record = entry.completion;
if (entry.tryLoc === "root") {
// Exception thrown outside of any try block that could handle
// it, so set the completion value of the entire function to
// throw the exception.
return handle("end");
}
if (entry.tryLoc <= this.prev) {
var hasCatch = hasOwn.call(entry, "catchLoc");
var hasFinally = hasOwn.call(entry, "finallyLoc");
if (hasCatch && hasFinally) {
if (this.prev < entry.catchLoc) {
return handle(entry.catchLoc, true);
} else if (this.prev < entry.finallyLoc) {
return handle(entry.finallyLoc);
}
} else if (hasCatch) {
if (this.prev < entry.catchLoc) {
return handle(entry.catchLoc, true);
}
} else if (hasFinally) {
if (this.prev < entry.finallyLoc) {
return handle(entry.finallyLoc);
}
} else {
throw new Error("try statement without catch or finally");
}
}
}
},
abrupt: function(type, arg) {
for (var i = this.tryEntries.length - 1; i >= 0; --i) {
var entry = this.tryEntries[i];
if (entry.tryLoc <= this.prev &&
hasOwn.call(entry, "finallyLoc") &&
this.prev < entry.finallyLoc) {
var finallyEntry = entry;
break;
}
}
if (finallyEntry &&
(type === "break" ||
type === "continue") &&
finallyEntry.tryLoc <= arg &&
arg <= finallyEntry.finallyLoc) {
// Ignore the finally entry if control is not jumping to a
// location outside the try/catch block.
finallyEntry = null;
}
var record = finallyEntry ? finallyEntry.completion : {};
record.type = type;
record.arg = arg;
if (finallyEntry) {
this.next = finallyEntry.finallyLoc;
} else {
this.complete(record);
}
return ContinueSentinel;
},
complete: function(record, afterLoc) {
if (record.type === "throw") {
throw record.arg;
}
if (record.type === "break" ||
record.type === "continue") {
this.next = record.arg;
} else if (record.type === "return") {
this.rval = record.arg;
this.next = "end";
} else if (record.type === "normal" && afterLoc) {
this.next = afterLoc;
}
},
finish: function(finallyLoc) {
for (var i = this.tryEntries.length - 1; i >= 0; --i) {
var entry = this.tryEntries[i];
if (entry.finallyLoc === finallyLoc) {
this.complete(entry.completion, entry.afterLoc);
resetTryEntry(entry);
return ContinueSentinel;
}
}
},
"catch": function(tryLoc) {
for (var i = this.tryEntries.length - 1; i >= 0; --i) {
var entry = this.tryEntries[i];
if (entry.tryLoc === tryLoc) {
var record = entry.completion;
if (record.type === "throw") {
var thrown = record.arg;
resetTryEntry(entry);
}
return thrown;
}
}
// The context.catch method must only be called with a location
// argument that corresponds to a known catch block.
throw new Error("illegal catch attempt");
},
delegateYield: function(iterable, resultName, nextLoc) {
this.delegate = {
iterator: values(iterable),
resultName: resultName,
nextLoc: nextLoc
};
return ContinueSentinel;
}
};
})(
// Among the various tricks for obtaining a reference to the global
// object, this seems to be the most reliable technique that does not
// use indirect eval (which violates Content Security Policy).
typeof global === "object" ? global :
typeof window === "object" ? window :
typeof self === "object" ? self : this
);
// INLINED END /home/robertkrahn/projects/lively/lively.next-node_modules/babel-regenerator-runtime/6.5.0/runtime.js
// INLINED /home/robertkrahn/projects/lively/lively.lang/dist/lively.lang.js
(function() {
var GLOBAL = typeof window !== "undefined" ? window :
typeof global!=="undefined" ? global :
typeof self!=="undefined" ? self : this;
if (typeof GLOBAL.lively === "undefined") GLOBAL.lively = {};
(function() {
this.lively = this.lively || {};
(function (exports) {
'use strict';
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
return typeof obj;
} : function (obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};
var asyncGenerator = function () {
function AwaitValue(value) {
this.value = value;
}
function AsyncGenerator(gen) {
var front, back;
function send(key, arg) {
return new Promise(function (resolve, reject) {
var request = {
key: key,
arg: arg,
resolve: resolve,
reject: reject,
next: null
};
if (back) {
back = back.next = request;
} else {
front = back = request;
resume(key, arg);
}
});
}
function resume(key, arg) {
try {
var result = gen[key](arg);
var value = result.value;
if (value instanceof AwaitValue) {
Promise.resolve(value.value).then(function (arg) {
resume("next", arg);
}, function (arg) {
resume("throw", arg);
});
} else {
settle(result.done ? "return" : "normal", result.value);
}
} catch (err) {
settle("throw", err);
}
}
function settle(type, value) {
switch (type) {
case "return":
front.resolve({
value: value,
done: true
});
break;
case "throw":
front.reject(value);
break;
default:
front.resolve({
value: value,
done: false
});
break;
}
front = front.next;
if (front) {
resume(front.key, front.arg);
} else {
back = null;
}
}
this._invoke = send;
if (typeof gen.return !== "function") {
this.return = undefined;
}
}
if (typeof Symbol === "function" && Symbol.asyncIterator) {
AsyncGenerator.prototype[Symbol.asyncIterator] = function () {
return this;
};
}
AsyncGenerator.prototype.next = function (arg) {
return this._invoke("next", arg);
};
AsyncGenerator.prototype.throw = function (arg) {
return this._invoke("throw", arg);
};
AsyncGenerator.prototype.return = function (arg) {
return this._invoke("return", arg);
};
return {
wrap: function (fn) {
return function () {
return new AsyncGenerator(fn.apply(this, arguments));
};
},
await: function (value) {
return new AwaitValue(value);
}
};
}();
var classCallCheck = function (instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
};
var createClass = function () {
function defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
return function (Constructor, protoProps, staticProps) {
if (protoProps) defineProperties(Constructor.prototype, protoProps);
if (staticProps) defineProperties(Constructor, staticProps);
return Constructor;
};
}();
var get$1 = function get$1(object, property, receiver) {
if (object === null) object = Function.prototype;
var desc = Object.getOwnPropertyDescriptor(object, property);
if (desc === undefined) {
var parent = Object.getPrototypeOf(object);
if (parent === null) {
return undefined;
} else {
return get$1(parent, property, receiver);
}
} else if ("value" in desc) {
return desc.value;
} else {
var getter = desc.get;
if (getter === undefined) {
return undefined;
}
return getter.call(receiver);
}
};
var set$1 = function set$1(object, property, value, receiver) {
var desc = Object.getOwnPropertyDescriptor(object, property);
if (desc === undefined) {
var parent = Object.getPrototypeOf(object);
if (parent !== null) {
set$1(parent, property, value, receiver);
}
} else if ("value" in desc && desc.writable) {
desc.value = value;
} else {
var setter = desc.set;
if (setter !== undefined) {
setter.call(receiver, value);
}
}
return value;
};
var slicedToArray = function () {
function sliceIterator(arr, i) {
var _arr = [];
var _n = true;
var _d = false;
var _e = undefined;
try {
for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
_arr.push(_s.value);
if (i && _arr.length === i) break;
}
} catch (err) {
_d = true;
_e = err;
} finally {
try {
if (!_n && _i["return"]) _i["return"]();
} finally {
if (_d) throw _e;
}
}
return _arr;
}
return function (arr, i) {
if (Array.isArray(arr)) {
return arr;
} else if (Symbol.iterator in Object(arr)) {
return sliceIterator(arr, i);
} else {
throw new TypeError("Invalid attempt to destructure non-iterable instance");
}
};
}();
var toConsumableArray = function (arr) {
if (Array.isArray(arr)) {
for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];
return arr2;
} else {
return Array.from(arr);
}
};
// A `Closure` is a representation of a JavaScript function that controls what
// values are bound to out-of-scope variables. By default JavaScript has no
// reflection capabilities over closed values in functions. When needing to
// serialize execution or when behavior should become part of the state of a
// system it is often necessary to have first-class control over this language
// aspect.
//
// Typically closures aren't created directly but with the help of [`asScriptOf`](#)
//
// Example:
// function func(a) { return a + b; }
// var closureFunc = Closure.fromFunction(func, {b: 3}).recreateFunc();
// closureFunc(4) // => 7
// var closure = closureFunc.livelyClosure // => {
// // varMapping: { b: 3 },
// // originalFunc: function func(a) {/*...*/}
// // }
// closure.lookup("b") // => 3
// closure.getFuncSource() // => "function func(a) { return a + b; }"
var parameterRegex = /function[^\(]*\(([^\)]*)\)|\(?([^\)=]*)\)?\s*=>/;
var Closure = function () {
createClass(Closure, null, [{
key: "fromFunction",
value: function fromFunction(func, varMapping) {
/*show-in-doc*/
return new this(func, varMapping || {});
}
}, {
key: "fromSource",
value: function fromSource(source, varMapping) {
/*show-in-doc*/
return new this(null, varMapping || {}, source);
}
}]);
function Closure(func, varMapping, source, funcProperties) {
classCallCheck(this, Closure);
this.originalFunc = func;
this.varMapping = varMapping || {};
this.setFuncSource(source || func);
this.setFuncProperties(func || funcProperties);
}
createClass(Closure, [{
key: "setFuncSource",
// accessing
value: function setFuncSource(src) {
/*show-in-doc*/
src = typeof lively !== "undefined" && lively.sourceTransform && typeof lively.sourceTransform.stringifyFunctionWithoutToplevelRecorder === "function" ? lively.sourceTransform.stringifyFunctionWithoutToplevelRecorder(src) : String(src);
return this.source = src;
}
}, {
key: "getFuncSource",
value: function getFuncSource() {
/*show-in-doc*/
return this.source || this.setFuncSource(this.originalFunc);
}
}, {
key: "hasFuncSource",
value: function hasFuncSource() {
/*show-in-doc*/
return this.source && true;
}
}, {
key: "getFunc",
value: function getFunc() {
/*show-in-doc*/
return this.originalFunc || this.recreateFunc();
}
}, {
key: "getFuncProperties",
value: function getFuncProperties() {
// ignore-in-doc
// a function may have state attached
return this.funcProperties || (this.funcProperties = {});
}
}, {
key: "setFuncProperties",
value: function setFuncProperties(obj) {
// ignore-in-doc
var props = this.getFuncProperties();
for (var name in obj) {
// The AST implementation assumes that Function objects are some
// kind of value object. When their identity changes cached state
// should not be carried over to new function instances. This is a
// pretty intransparent way to invalidate attributes that are used
// for caches.
// @cschuster, can you please fix this by making invalidation more
// explicit?
if (obj.hasOwnProperty(name)) props[name] = obj[name];
}
}
}, {
key: "lookup",
value: function lookup(name) {
/*show-in-doc*/
return this.varMapping[name];
}
}, {
key: "parameterNames",
value: function parameterNames(methodString) {
// ignore-in-doc
if (typeof lively !== "undefined" && lively.ast && lively.ast.parseFunction) {
return (lively.ast.parseFunction(methodString).params || []).map(function (ea) {
if (ea.type === "Identifier") return ea.name;
if (ea.left && ea.left.type === "Identifier") return ea.left.name;
return null;
}).filter(Boolean);
}
var paramsMatch = parameterRegex.exec(methodString);
if (!paramsMatch) return [];
var paramsString = paramsMatch[1] || paramsMatch[2] || "";
return paramsString.split(",").map(function (ea) {
return ea.trim();
});
}
}, {
key: "firstParameter",
value: function firstParameter(src) {
// ignore-in-doc
return this.parameterNames(src)[0] || null;
}
// -=-=-=-=-=-=-=-=-=-
// function creation
// -=-=-=-=-=-=-=-=-=-
}, {
key: "recreateFunc",
value: function recreateFunc() {
// Creates a real function object
return this.recreateFuncFromSource(this.getFuncSource(), this.originalFunc);
}
}, {
key: "recreateFuncFromSource",
value: function recreateFuncFromSource(funcSource, optFunc) {
// ignore-in-doc
// what about objects that are copied by value, e.g. numbers?
// when those are modified after the originalFunc we captured
// varMapping then we will have divergent state
var closureVars = [],
thisFound = false,
specificSuperHandling = this.firstParameter(funcSource) === '$super';
for (var name in this.varMapping) {
if (!this.varMapping.hasOwnProperty(name)) continue;
if (name == 'this') {
thisFound = true;continue;
}
// closureVars.push(`var ${name} = this.varMapping.${name};\n`);
closureVars.push("var " + name + " = this.varMapping." + name + ";\n");
}
var src = "";
if (closureVars.length > 0) src += closureVars.join("\n");
if (specificSuperHandling) src += '(function superWrapperForClosure() { return ';
src += "(" + funcSource + ")";
if (specificSuperHandling) src += '.apply(this, [$super.bind(this)]' + '.concat(Array.from(arguments))) })';
try {
var func = evalJS.call(this, src) || this.couldNotCreateFunc(src);
this.addFuncProperties(func);
this.originalFunc = func;
return func;
} catch (e) {
// var msg = `Cannot create function ${e} src: ${src}`;
var msg = "Cannot create function " + e + " src: " + src;
console.error(msg);
throw new Error(msg);
}
}
}, {
key: "addFuncProperties",
value: function addFuncProperties(func) {
// ignore-in-doc
var props = this.getFuncProperties();
for (var name in props) {
if (props.hasOwnProperty(name)) func[name] = props[name];
}this.addClosureInformation(func);
}
}, {
key: "couldNotCreateFunc",
value: function couldNotCreateFunc(src) {
// ignore-in-doc
var msg = 'Could not recreate closure from source: \n' + src;
console.error(msg);
return function () {
throw new Error(msg);
};
}
// -=-=-=-=-=-
// conversion
// -=-=-=-=-=-
}, {
key: "asFunction",
value: function asFunction() {
/*ignore-in-doc*/
return this.recreateFunc();
}
// -=-=-=-=-=-=-=-=-=-=-=-
// function modification
// -=-=-=-=-=-=-=-=-=-=-=-
}, {
key: "addClosureInformation",
value: function addClosureInformation(f) {
/*ignore-in-doc-in-doc*/
f.hasLivelyClosure = true;
f.livelyClosure = this;
return f;
}
}, {
key: "isLivelyClosure",
get: function get() {
return true;
}
// serialization
}, {
key: "doNotSerialize",
get: function get() {
return ['originalFunc'];
}
}]);
return Closure;
}();
/*global clearTimeout, setTimeout*/
/*
* Abstractions around first class functions like augmenting and inspecting
* functions as well as to control function calls like dealing with asynchronous
* control flows.
*/
// -=-=-=-=-=-=-=-=-
// static functions
// -=-=-=-=-=-=-=-=-
function Empty() {
/*`function() {}`*/return function () {};
}
function K() {
/*`function(arg) { return arg; }`*/return function (arg) {
return arg;
};
}
function Null() {
/*`function() { return null; }`*/return function () {
return null;
};
}
function False() {
/*`function() { return false; }`*/return function () {
return false;
};
}
function True() {
/*`function() { return true; }`*/return function () {
return true;
};
}
function notYetImplemented() {
return function () {
throw new Error('Not yet implemented');
};
}
// -=-=-=-=-=-
// accessing
// -=-=-=-=-=-
function all(object) {
// Returns all property names of `object` that reference a function.
// Example:
// var obj = {foo: 23, bar: function() { return 42; }};
// all(obj) // => ["bar"]
var a = [];
for (var name in object) {
if (!object.__lookupGetter__(name) && typeof object[name] === 'function') a.push(name);
}
return a;
}
function own(object) {
// Returns all local (non-prototype) property names of `object` that
// reference a function.
// Example:
// var obj1 = {foo: 23, bar: function() { return 42; }};
// var obj2 = {baz: function() { return 43; }};
// obj2.__proto__ = obj1
// own(obj2) // => ["baz"]
// /*vs.*/ all(obj2) // => ["baz","bar"]
var a = [];
for (var name in object) {
if (!object.__lookupGetter__(name) && object.hasOwnProperty(name) && typeof object[name] === 'function') a.push(name);
}
return a;
}
// -=-=-=-=-=-
// inspection
// -=-=-=-=-=-
function argumentNames(f) {
// Example:
// argumentNames(function(arg1, arg2) {}) // => ["arg1","arg2"]
// argumentNames(function(/*var args*/) {}) // => []
if (f.superclass) return []; // it's a class...
var src = f.toString(),
names = "",
arrowMatch = src.match(/(?:\(([^\)]*)\)|([^\(\)-+!]+))\s*=>/);
if (arrowMatch) names = arrowMatch[1] || arrowMatch[2] || "";else {
var headerMatch = src.match(/^[\s\(]*function[^(]*\(([^)]*)\)/);
if (headerMatch && headerMatch[1]) names = headerMatch[1];
}
return names.replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g, '').replace(/\s+/g, '').split(',').map(function (ea) {
return ea.trim();
}).filter(function (name) {
return !!name;
});
}
function qualifiedMethodName(f) {
// ignore-in-doc
var objString = "";
if (f.declaredClass) {
objString += f.declaredClass + '>>';
} else if (f.declaredObject) {
objString += f.declaredObject + '.';
}
return objString + (f.methodName || f.displayName || f.name || "anonymous");
}
function extractBody(func) {
// superflous indent. Useful when you have to stringify code but not want
// to construct strings by hand.
// Example:
// extractBody(function(arg) {
// var x = 34;
// alert(2 + arg);
// }) => "var x = 34;\nalert(2 + arg);"
var codeString = String(func).replace(/^function[^\{]+\{\s*/, '').replace(/\}$/, '').trim(),
lines = codeString.split(/\n|\r/),
indent = undefined;
for (var i = 0; i < lines.length; i++) {
var m = lines[i].match(/^(\s+)[^\s]/);
if (m && (indent === undefined || m[1].length < indent.length)) indent = m[1];
}
return indent ? codeString.replace(new RegExp("^" + indent, 'gm'), '') : codeString;
}
// -=-=-=-
// timing
// -=-=-=-
function timeToRun(func) {
// returns synchronous runtime of calling `func` in ms
// Example:
// timeToRun(function() { new WebResource("http://google.de").beSync().get() });
// // => 278 (or something else...)
var startTime = Date.now();
func();
return Date.now() - startTime;
}
function timeToRunN$1(func, n) {
// Like `timeToRun` but calls function `n` times instead of once. Returns
// the average runtime of a call in ms.
var startTime = Date.now();
for (var i = 0; i < n; i++) {
func();
}return (Date.now() - startTime) / n;
}
function delay(func, timeout /*, arg1...argN*/) {
// Delays calling `func` for `timeout` seconds(!).
// Example:
// (function() { alert("Run in the future!"); }).delay(1);
var args = Array.prototype.slice.call(arguments),
__method = args.shift(),
timeout = args.shift() * 1000;
return setTimeout(function delayed() {
return __method.apply(__method, args);
}, timeout);
}
// these last two methods are Underscore.js 1.3.3 and are slightly adapted
// Underscore.js license:
// (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc.
// Underscore is distributed under the MIT license.
function throttle(func, wait) {
// Exec func at most once every wait ms even when called more often
// useful to calm down eagerly running updaters and such.
// Example:
// var i = 0;
// var throttled = throttle(function() { alert(++i + '-' + Date.now()) }, 500);
// Array.range(0,100).forEach(function(n) { throttled() });
var context,
args,
timeout,
throttling,
more,
result,
whenDone = debounce(wait, function () {
more = throttling = false;
});
return function () {
context = this;args = arguments;
var later = function later() {
timeout = null;
if (more) func.apply(context, args);
whenDone();
};
if (!timeout) timeout = setTimeout(later, wait);
if (throttling) {
more = true;
} else {
result = func.apply(context, args);
}
whenDone();
throttling = true;
return result;
};
}
function debounce(wait, func, immediate) {
// Call `func` after `wait` milliseconds elapsed since the last invocation.
// Unlike `throttle` an invocation will restart the wait period. This is
// useful if you have a stream of events that you want to wait for to finish
// and run a subsequent function afterwards. When you pass arguments to the
// debounced functions then the arguments from the last call will be use for
// the invocation.
//
// With `immediate` set to true, immediately call `func` but when called again during `wait` before
// wait ms are done nothing happens. E.g. to not exec a user invoked
// action twice accidentally.
// Example:
// var start = Date.now();
// var f = debounce(200, function(arg1) {
// alert("running after " + (Date.now()-start) + "ms with arg " + arg1);
// });
// f("call1");
// delay(f.curry("call2"), 0.1);
// delay(f.curry("call3"), 0.15);
// // => Will eventually output: "running after 352ms with arg call3"
var timeout;
return function () {
var context = this,
args = arguments;
var later = function later() {
timeout = null;
if (!immediate) func.apply(context, args);
};
if (immediate && !timeout) func.apply(context, args);
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
}
var _throttledByName = {};
function throttleNamed(name, wait, func) {
// Like `throttle` but remembers the throttled function once created and
// repeated calls to `throttleNamed` with the identical name will use the same
// throttled function. This allows to throttle functions in a central place
// that might be called various times in different contexts without having to
// manually store the throttled function.
var store = _throttledByName;
if (store[name]) return store[name];
function throttleNamedWrapper() {
// ignore-in-doc, cleaning up
debounceNamed(name, wait, function () {
delete store[name];
})();
func.apply(this, arguments);
}
return store[name] = throttle(throttleNamedWrapper, wait);
}
var _debouncedByName = {};
function debounceNamed(name, wait, func, immediate) {
// Like `debounce` but remembers the debounced function once created and
// repeated calls to `debounceNamed` with the identical name will use the same
// debounced function. This allows to debounce functions in a central place
// that might be called various times in different contexts without having to
// manually store the debounced function.
var store = _debouncedByName;
if (store[name]) return store[name];
function debounceNamedWrapper() {
// ignore-in-doc, cleaning up
delete store[name];
func.apply(this, arguments);
}
return store[name] = debounce(wait, debounceNamedWrapper, immediate);
}
var _queues = {};
function createQueue(id, workerFunc) {
// A simple queue with an attached asynchronous `workerFunc` to process
// queued tasks. Calling `createQueue` will return an object with the
// following interface:
// ```js
// {
// push: function(task) {/**/},
// pushAll: function(tasks) {/**/},
// handleError: function(err) {}, // Overwrite to handle errors
// dran: function() {}, // Overwrite to react when the queue empties
// }
// Example:
// var sum = 0;
// var q = createQueue("example-queue", function(arg, thenDo) { sum += arg; thenDo(); });
// q.pushAll([1,2,3]);
// queues will be remembered by their name
// createQueue("example-queue").push(4);
// sum // => 6
var store = _queues;
var queue = store[id] || (store[id] = {
_workerActive: false,
worker: workerFunc, tasks: [],
drain: null, // can be overwritten by a function
push: function push(task) {
queue.tasks.push(task);
queue.activateWorker();
},
pushAll: function pushAll(tasks) {
tasks.forEach(function (ea) {
queue.tasks.push(ea);
});
queue.activateWorker();
},
pushNoActivate: function pushNoActivate(task) {
queue.tasks.push(task);
},
handleError: function handleError(err) {
// can be overwritten
err && console.error('Error in queue: ' + err);
},
activateWorker: function activateWorker() {
function callback(err) {
queue.handleError(err);queue.activateWorker();
}
var tasks = queue.tasks,
active = queue._workerActive;
if (tasks.length === 0) {
if (active) {
queue._workerActive = false;
if (typeof queue.drain === 'function') queue.drain();
}
delete store[id];
} else {
if (!active) queue._workerActive = true;
try {
queue.worker(tasks.shift(), callback);
} catch (err) {
callback(err);
}
}
}
});
return queue;
}
var _queueUntilCallbacks = {};
function workerWithCallbackQueue(id, workerFunc, optTimeout) {
// This functions helps when you have a long running computation that
// multiple call sites (independent from each other) depend on. This
// function does the housekeeping to start the long running computation
// just once and returns an object that allows to schedule callbacks
// once the workerFunc is done.
// Example:
// var worker = workerWithCallbackQueue("example",
// function slowFunction(thenDo) {
// var theAnswer = 42;
// setTimeout(function() { thenDo(null, theAnswer); });
// });
// // all "call sites" depend on `slowFunction` but don't have to know about
// // each other
// worker.whenDone(function callsite1(err, theAnswer) { alert("callback1: " + theAnswer); })
// worker.whenDone(function callsite2(err, theAnswer) { alert("callback2: " + theAnswer); })
// workerWithCallbackQueue("example").whenDone(function callsite3(err, theAnswer) { alert("callback3: " + theAnswer); })
// // => Will eventually show: callback1: 42, callback2: 42 and callback3: 42
// ignore-in-doc
// This is how it works:
// If `id` does not exist, workerFunc is called, otherwise ignored.
// workerFunc is expected to call thenDoFunc with arguments: error, arg1, ..., argN
// if called subsequently before workerFunc is done, the other thenDoFunc
// will "pile up" and called with the same arguments as the first
// thenDoFunc once workerFunc is done
var store = _queueUntilCallbacks,
queueCallbacks = store[id],
isRunning = !!queueCallbacks;
if (isRunning) return queueCallbacks;
var callbacksRun = false,
canceled = false;
function cleanup() {
if (timeoutProc) clearTimeout(timeoutProc);
callbacksRun = true;
delete store[id];
}
function runCallbacks(args) {
if (callbacksRun) return;
cleanup();
queueCallbacks.callbacks.forEach(function (cb) {
try {
cb.apply(null, args);
} catch (e) {
console.error("Error when invoking callbacks in queueUntil [" + id + "]:\n" + String(e.stack || e));
}
});
}
// timeout
if (optTimeout) {
var timeoutProc = setTimeout(function () {
if (callbacksRun) return;
runCallbacks([new Error("timeout")]);
}, optTimeout);
}
// init the store
queueCallbacks = store[id] = {
callbacks: [],
cancel: function cancel() {
canceled = true;
cleanup();
},
whenDone: function whenDone(cb) {
queueCallbacks.callbacks.push(cb);
return queueCallbacks;
}
};
// call worker, but delay so we can immediately return
setTimeout(function () {
if (canceled) return;
try {
workerFunc(function () /*args*/{
runCallbacks(arguments);
});
} catch (e) {
runCallbacks([e]);
}
}, 0);
return queueCallbacks;
}
function _composeAsyncDefaultEndCallback(err, arg1 /*err + args*/) {
if (err) console.error("lively.lang.composeAsync error", err);
}
function composeAsync() /*functions*/{
// Composes functions that are asynchronous and expecting continuations to
// be called in node.js callback style (error is first argument, real
// arguments follow).
// A call like `composeAsync(f,g,h)(arg1, arg2)` has a flow of control like:
// `f(arg1, arg2, thenDo1)` -> `thenDo1(err, fResult)`
// -> `g(fResult, thenDo2)` -> `thenDo2(err, gResult)` ->
// -> `h(fResult, thenDo3)` -> `thenDo2(err, hResult)`
// Example:
// composeAsync(
// function(a,b, thenDo) { thenDo(null, a+b); },
// function(x, thenDo) { thenDo(x*4); }
// )(3,2, function(err, result) { alert(result); });
var toArray$$1 = Array.prototype.slice,
functions = toArray$$1.call(arguments),
defaultEndCb = _composeAsyncDefaultEndCallback,
endCallback = defaultEndCb,
endSuccess,
endFailure,
endPromise = new Promise(function (resolve, reject) {
endSuccess = resolve;endFailure = reject;
});
return functions.reverse().reduce(function (prevFunc, funcOrPromise, i) {
var nextActivated = false;
return function () {
var args = toArray$$1.call(arguments);
// ignore-in-doc
// the last arg needs to be function, discard all non-args
// following it. This allows to have an optional callback func that can
// even be `undefined`, e.g. when calling this func from a callsite