UNPKG

lively.vm

Version:

Controlled JavaScript code execution and instrumentation.

1,659 lines (1,417 loc) 1.1 MB
// 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