// INLINED /Users/user/git/lively.vm/node_modules/babel-regenerator-runtime/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 /Users/user/git/lively.vm/node_modules/babel-regenerator-runtime/runtime.js // INLINED /Users/user/git/lively.vm/node_modules/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,lively_sourceTransform) { '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 // using var args; if (endCallback === defaultEndCb && i === functions.length - 1 /*first function*/) { while (args.length && typeof args[args.length - 1] !== 'function') { args.pop(); }if (typeof args[args.length - 1] === 'function') endCallback = args.pop(); } function next() /*err and args*/{ nextActivated = true; var args = toArray$$1.call(arguments), err = args.shift(); if (err) { endCallback(err);endFailure(err); } else prevFunc.apply(null, args); } if (typeof funcOrPromise === "function") { try { var result = funcOrPromise.apply(this, args.concat([next])); if (result && typeof result.then === "function" && typeof result.catch === "function") { result.then(function (value) { return next(null, value); }).catch(function (err) { return next(err); }); } } catch (e) { console.error('composeAsync: ', e.stack || e); if (!nextActivated) { endCallback(e);endFailure(e); } } } else if (funcOrPromise && typeof funcOrPromise.then === "function" && typeof funcOrPromise.catch === "function") { funcOrPromise.then(function (value) { next(null, value); }).catch(function (err) { next(err); }); } else { var err = new Error("Invalid argument to composeAsync: " + funcOrPromise); endCallback(err); endFailure(err); } return endPromise; }; }, function () { var args = toArray$$1.call(arguments); endCallback.apply(null, [null].concat(args)); endSuccess(args[0]); }); } function compose() /*functions*/{ // Composes synchronousefunctions: // `compose(f,g,h)(arg1, arg2)` = `h(g(f(arg1, arg2)))` // Example: // compose( // function(a,b) { return a+b; }, // function(x) {return x*4} // )(3,2) // => 20 var functions = Array.prototype.slice.call(arguments); return functions.reverse().reduce(function (prevFunc, func) { return function () { return prevFunc(func.apply(this, arguments)); }; }, function (x) { return x; }); } function flip(f) { // Swaps the first two args // Example: // flip(function(a, b, c) { // return a + b + c; })(' World', 'Hello', '!') // => "Hello World!" return function flipped() /*args*/{ var args = Array.prototype.slice.call(arguments), flippedArgs = [args[1], args[0]].concat(args.slice(2)); return f.apply(null, flippedArgs); }; } function withNull(func) { // returns a modified version of func that will have `null` always curried // as first arg. Usful e.g. to make a nodejs-style callback work with a // then-able: // Example: // promise.then(withNull(cb)).catch(cb); func = func || function () {}; return function () /*args*/{ var args = lively.lang.arr.from(arguments); func.apply(null, [null].concat(args)); }; } function waitFor(timeoutMs, waitTesterFunc, thenDo) { // Wait for waitTesterFunc to return true, then run thenDo, passing // failure/timout err as first parameter. A timout occurs after // timeoutMs. During the wait period waitTesterFunc might be called // multiple times. var start = Date.now(); var timeStep = 50; if (!thenDo) { thenDo = waitTesterFunc; waitTesterFunc = timeoutMs; timeoutMs = undefined; } (function test() { if (waitTesterFunc()) return thenDo(); if (timeoutMs) { var duration = Date.now() - start, timeLeft = timeoutMs - duration; if (timeLeft <= 0) return thenDo(new Error('timeout')); if (timeLeft < timeStep) timeStep = timeLeft; } setTimeout(test, timeStep); })(); } function waitForAll(options, funcs, thenDo) { // Wait for multiple asynchronous functions. Once all have called the // continuation, call `thenDo`. // options can be: `{timeout: NUMBER}` (how long to wait in milliseconds). if (!thenDo) { thenDo = funcs;funcs = options;options = null; } options = options || {}; var results = funcs.map(function () { return null; }); if (!funcs.length) { thenDo(null, results);return; } var leftFuncs = Array.prototype.slice.call(funcs); funcs.forEach(function (f, i) { try { f(function () /*err and args*/{ var args = Array.prototype.slice.call(arguments); var err = args.shift(); markAsDone(f, i, err, args); }); } catch (e) { markAsDone(f, i, e, null); } }); if (options.timeout) { setTimeout(function () { if (!leftFuncs.length) return; var missing = results.map(function (ea, i) { return ea === null && i; }).filter(function (ea) { return typeof ea === 'number'; }).join(', '); var err = new Error("waitForAll timed out, functions at " + missing + " not done"); markAsDone(null, null, err, null); }, options.timeout); } function markAsDone(f, i, err, result) { if (!leftFuncs.length) return; var waitForAllErr = null; var fidx = leftFuncs.indexOf(f); fidx > -1 && leftFuncs.splice(fidx, 1); if (err) { leftFuncs.length = 0; waitForAllErr = new Error("in waitForAll at" + (typeof i === 'number' ? " " + i : "") + ": \n" + (err.stack || String(err))); } else if (result) results[i] = result; if (!leftFuncs.length) setTimeout(function () { thenDo(waitForAllErr, results); }, 0); } } // -=-=-=-=- // wrapping // -=-=-=-=- function curry(func, arg1, arg2, argN /*func and curry args*/) { // Return a version of `func` with args applied. // Example: // var add1 = (function(a, b) { return a + b; }).curry(1); // add1(3) // => 4 if (arguments.length <= 1) return arguments[0]; var args = Array.prototype.slice.call(arguments), func = args.shift(); function wrappedFunc() { return func.apply(this, args.concat(Array.prototype.slice.call(arguments))); } wrappedFunc.isWrapper = true; wrappedFunc.originalFunction = func; return wrappedFunc; } function wrap(func, wrapper) { // A `wrapper` is another function that is being called with the arguments // of `func` and a proceed function that, when called, runs the originally // wrapped function. // Example: // function original(a, b) { return a+b } // var wrapped = wrap(original, function logWrapper(proceed, a, b) { // alert("original called with " + a + "and " + b); // return proceed(a, b); // }) // wrapped(3,4) // => 7 and a message will pop up var __method = func; var wrappedFunc = function wrapped() { var args = Array.prototype.slice.call(arguments); var wrapperArgs = wrapper.isWrapper ? args : [__method.bind(this)].concat(args); return wrapper.apply(this, wrapperArgs); }; wrappedFunc.isWrapper = true; wrappedFunc.originalFunction = __method; return wrappedFunc; } function getOriginal(func) { // Get the original function that was augmented by `wrap`. `getOriginal` // will traversed as many wrappers as necessary. while (func.originalFunction) { func = func.originalFunction; }return func; } function wrapperChain(method) { // Function wrappers used for wrapping, cop, and other method // manipulations attach a property "originalFunction" to the wrapper. By // convention this property references the wrapped method like wrapper // -> cop wrapper -> real method. // tThis method gives access to the linked list starting with the outmost // wrapper. var result = []; do { result.push(method); method = method.originalFunction; } while (method); return result; } function replaceMethodForOneCall(obj, methodName, replacement) { // Change an objects method for a single invocation. // Example: // var obj = {foo: function() { return "foo"}}; // lively.lang.replaceMethodForOneCall(obj, "foo", function() { return "bar"; }); // obj.foo(); // => "bar" // obj.foo(); // => "foo" replacement.originalFunction = obj[methodName]; var reinstall = obj.hasOwnProperty(methodName); obj[methodName] = function () { if (reinstall) obj[methodName] = replacement.originalFunction;else delete obj[methodName]; return replacement.apply(this, arguments); }; return obj; } function once(func) { // Ensure that `func` is only executed once. Multiple calls will not call // `func` again but will return the original result. if (!func) return undefined; if (typeof func !== 'function') throw new Error("once() expecting a function"); var invoked = false, result; return function () { if (invoked) return result; invoked = true; return result = func.apply(this, arguments); }; } function either() /*funcs*/{ // Accepts multiple functions and returns an array of wrapped // functions. Those wrapped functions ensure that only one of the original // function is run (the first on to be invoked). // // This is useful if you have multiple asynchronous choices of how the // control flow might continue but want to ensure that a continuation // is only triggered once, like in a timeout situation: // // ```js // function outerFunction(callback) { // function timeoutAction() { callback(new Error('timeout!')); } // function otherAction() { callback(null, "All OK"); } // setTimeout(timeoutAction, 200); // doSomethingAsync(otherAction); // } // ``` // // To ensure that `callback` only runs once you would normally have to write boilerplate like this: // // ```js // var ran = false; // function timeoutAction() { if (ran) return; ran = true; callback(new Error('timeout!')); } // function otherAction() { if (ran) return; ran = true; callback(null, "All OK"); } // ``` // // Since this can get tedious an error prone, especially if more than two choices are involved, `either` can be used like this: // Example: // function outerFunction(callback) { // var actions = either( // function() { callback(new Error('timeout!')); }, // function() { callback(null, "All OK"); }); // setTimeout(actions[0], 200); // doSomethingAsync(actions[1]); // } var funcs = Array.prototype.slice.call(arguments), wasCalled = false; return funcs.map(function (func) { return function () { if (wasCalled) return undefined; wasCalled = true; return func.apply(this, arguments); }; }); } var _eitherNameRegistry = {}; function eitherNamed(name, func) { // Works like [`either`](#) but usage does not require to wrap all // functions at once: // Example: // var log = "", name = "either-example-" + Date.now(); // function a() { log += "aRun"; }; // function b() { log += "bRun"; }; // function c() { log += "cRun"; }; // setTimeout(eitherNamed(name, a), 100); // setTimeout(eitherNamed(name, b), 40); // setTimeout(eitherNamed(name, c), 80); // setTimeout(function() { alert(log); /* => "bRun" */ }, 150); var funcs = Array.prototype.slice.call(arguments); var registry = _eitherNameRegistry; var name = funcs.shift(); var eitherCall = registry[name] || (registry[name] = { wasCalled: false, callsLeft: 0 }); eitherCall.callsLeft++; return function () { eitherCall.callsLeft--; // cleanup the storage if all registered functions fired if (eitherCall.callsLeft <= 0) delete registry[name]; if (eitherCall.wasCalled) return undefined; eitherCall.wasCalled = true; return func.apply(this, arguments); }; } // -=-=-=-=- // creation // -=-=-=-=- function evalJS(src) { return eval(src); } function fromString(funcOrString) { // Example: // fromString("function() { return 3; }")() // => 3 return evalJS('(' + funcOrString.toString() + ');'); } function asScript(func, optVarMapping) { // Lifts `func` to become a `Closure`, that is that free variables referenced // in `func` will be bound to the values of an object that can be passed in as // the second parameter. Keys of this object are mapped to the free variables. // // Please see [`Closure`](#) for a more detailed explanation and examples. return Closure.fromFunction(func, optVarMapping).recreateFunc(); } function asScriptOf(f, obj, optName, optMapping) { // Like `asScript` but makes `f` a method of `obj` as `optName` or the name // of the function. var name = optName || f.name; if (!name) { throw Error("Function that wants to be a script needs a name: " + this); } var proto = Object.getPrototypeOf(obj), mapping = { "this": obj }; if (optMapping) mapping = merge([mapping, optMapping]); if (proto && proto[name]) { var superFunc = function superFunc() { try { // FIXME super is supposed to be static return Object.getPrototypeOf(obj)[name].apply(obj, arguments); } catch (e) { if (typeof $world !== "undefined") $world.logError(e, 'Error in $super call');else console.error('Error in $super call: ' + e + '\n' + e.stack); return null; } }; mapping["$super"] = Closure.fromFunction(superFunc, { obj: obj, name: name }).recreateFunc(); } return addToObject(asScript(f, mapping), obj, name); } // -=-=-=-=-=-=-=-=- // closure related // -=-=-=-=-=-=-=-=- function addToObject(f, obj, name) { // ignore-in-doc f.displayName = name; var methodConnections = obj.attributeConnections ? obj.attributeConnections.filter(function (con) { return con.getSourceAttrName() === 'update'; }) : []; if (methodConnections) methodConnections.forEach(function (ea) { ea.disconnect(); }); obj[name] = f; if (typeof obj === "undefined" ? "undefined" : _typeof(obj)) f.declaredObject = safeToString(obj); // suppport for tracing if (typeof lively !== "undefined" && obj && lively.Tracing && lively.Tracing.stackTracingEnabled) { lively.Tracing.instrumentMethod(obj, name, { declaredObject: safeToString(obj) }); } if (methodConnections) methodConnections.forEach(function (ea) { ea.connect(); }); return f; } function binds(f, varMapping) { // ignore-in-doc // convenience function return Closure.fromFunction(f, varMapping || {}).recreateFunc(); } function setLocalVarValue(f, name, value) { // ignore-in-doc if (f.hasLivelyClosure) f.livelyClosure.funcProperties[name] = value; } function getVarMapping(f) { // ignore-in-doc if (f.hasLivelyClosure) return f.livelyClosure.varMapping; if (f.isWrapper) return f.originalFunction.varMapping; if (f.varMapping) return f.varMapping; return {}; } function setProperty(func, name, value) { func[name] = value; if (func.hasLivelyClosure) func.livelyClosure.funcProperties[name] = value; } // -=-=-=-=-=-=-=-=-=-=-=-=- // class-related functions // -=-=-=-=-=-=-=-=-=-=-=-=- function functionNames(klass) { // Treats passed function as class (constructor). // Example: // var Klass1 = function() {} // Klass1.prototype.foo = function(a, b) { return a + b; }; // Klass1.prototype.bar = function(a) { return this.foo(a, 3); }; // Klass1.prototype.baz = 23; // functionNames(Klass1); // => ["bar","foo"] var result = [], lookupObj = klass.prototype; while (lookupObj) { result = Object.keys(lookupObj).reduce(function (result, name) { if (typeof lookupObj[name] === 'function' && result.indexOf(name) === -1) result.push(name); return result; }, result); lookupObj = Object.getPrototypeOf(lookupObj); } return result; } function localFunctionNames(func) { return Object.keys(func.prototype).filter(function (name) { return typeof func.prototype[name] === 'function'; }); } // -=-=-=-=-=-=-=-=-=-=- // tracing and logging // -=-=-=-=-=-=-=-=-=-=- function logErrors(func, prefix) { var advice = function logErrorsAdvice(proceed /*,args*/) { var args = Array.prototype.slice.call(arguments); args.shift(); try { return proceed.apply(func, args); } catch (er) { if (typeof lively !== "undefined" && lively.morphic && lively.morphic.World && lively.morphic.World.current()) { lively.morphic.World.current().logError(er); throw er; } if (prefix) console.warn("ERROR: %s.%s(%s): err: %s %s", func, prefix, args, er, er.stack || "");else console.warn("ERROR: %s %s", er, er.stack || ""); throw er; } }; advice.methodName = "$logErrorsAdvice"; var result = wrap(func, advice); result.originalFunction = func; result.methodName = "$logErrorsWrapper"; return result; } function logCompletion(func, module) { var advice = function logCompletionAdvice(proceed) { var args = Array.prototype.slice.call(arguments); args.shift(); try { var result = proceed.apply(func, args); } catch (er) { console.warn('failed to load ' + module + ': ' + er); if (typeof lively !== 'undefined' && lively.lang.Execution) lively.lang.Execution.showStack(); throw er; } console.log('completed ' + module); return result; }; advice.methodName = "$logCompletionAdvice::" + module; var result = wrap(func, advice); result.methodName = "$logCompletionWrapper::" + module; result.originalFunction = func; return result; } function logCalls(func, isUrgent) { var original = func, advice = function logCallsAdvice(proceed) { var args = Array.prototype.slice.call(arguments); args.shift(), result = proceed.apply(func, args); if (isUrgent) { console.warn('%s(%s) -> %s', qualifiedMethodName(original), args, result); } else { console.log('%s(%s) -> %s', qualifiedMethodName(original), args, result); } return result; }; advice.methodName = "$logCallsAdvice::" + qualifiedMethodName(func); var result = wrap(func, advice); result.originalFunction = func; result.methodName = "$logCallsWrapper::" + qualifiedMethodName(func); return result; } function traceCalls(func, stack) { var advice = function traceCallsAdvice(proceed) { var args = Array.prototype.slice.call(arguments); args.shift(); stack.push(args); var result = proceed.apply(func, args); stack.pop(); return result; }; return wrap(func, advice); } function webkitStack() { // this won't work in every browser try { throw new Error(); } catch (e) { // remove "Error" and this function from stack, rewrite it nicely return String(e.stack).split(/\n/).slice(2).map(function (line) { return line.replace(/^\s*at\s*([^\s]+).*/, '$1'); }).join('\n'); } } var fun = Object.freeze({ Empty: Empty, K: K, Null: Null, False: False, True: True, notYetImplemented: notYetImplemented, withNull: withNull, all: all, own: own, argumentNames: argumentNames, qualifiedMethodName: qualifiedMethodName, extractBody: extractBody, timeToRun: timeToRun, timeToRunN: timeToRunN$1, delay: delay, throttle: throttle, debounce: debounce, throttleNamed: throttleNamed, debounceNamed: debounceNamed, createQueue: createQueue, workerWithCallbackQueue: workerWithCallbackQueue, composeAsync: composeAsync, compose: compose, waitFor: waitFor, waitForAll: waitForAll, flip: flip, curry: curry, wrap: wrap, binds: binds, getOriginal: getOriginal, wrapperChain: wrapperChain, replaceMethodForOneCall: replaceMethodForOneCall, once: once, either: either, eitherNamed: eitherNamed, evalJS: evalJS, fromString: fromString, asScript: asScript, asScriptOf: asScriptOf, addToObject: addToObject, setLocalVarValue: setLocalVarValue, getVarMapping: getVarMapping, setProperty: setProperty, functionNames: functionNames, localFunctionNames: localFunctionNames, logErrors: logErrors, logCompletion: logCompletion, logCalls: logCalls, traceCalls: traceCalls, webkitStack: webkitStack }); // show-in-doc // A Grouping is created by arr.groupBy and maps keys to Arrays. var Group = function () { function Group() { classCallCheck(this, Group); } createClass(Group, [{ key: "toArray", value: function toArray() { // Example: // var group = arr.groupBy([1,2,3,4,5], function(n) { return n % 2; }) // group.toArray(); // => [[2,4],[1,3,5]] return this.reduceGroups(function (all$$1, _, group) { return all$$1.concat([group]); }, []); } }, { key: "forEach", value: function forEach(iterator, context) { // Iteration for each item in each group, called like `iterator(groupKey, groupItem)` var groups = this; Object.keys(groups).forEach(function (groupName) { groups[groupName].forEach(iterator.bind(context, groupName)); }); return groups; } }, { key: "forEachGroup", value: function forEachGroup(iterator, context) { // Iteration for each group, called like `iterator(groupKey, group)` var groups = this; Object.keys(groups).forEach(function (groupName) { iterator.call(context, groupName, groups[groupName]); }); return groups; } }, { key: "map", value: function map(iterator, context) { // Map for each item in each group, called like `iterator(groupKey, group)` var result = new Group(); this.forEachGroup(function (groupName, group) { result[groupName] = group.map(iterator.bind(context, groupName)); }); return result; } }, { key: "mapGroups", value: function mapGroups(iterator, context) { // Map for each group, called like `iterator(groupKey, group)` var result = new Group(); this.forEachGroup(function (groupName, group) { result[groupName] = iterator.call(context, groupName, group); }); return result; } }, { key: "keys", value: function keys() { // show-in-docs return Object.keys(this); } }, { key: "reduceGroups", value: function reduceGroups(iterator, carryOver, context) { // Reduce/fold for each group, called like `iterator(carryOver, groupKey, group)` this.forEachGroup(function (groupName, group) { carryOver = iterator.call(context, carryOver, groupName, group); }); return carryOver; } }, { key: "count", value: function count() { // counts the elements of each group return this.reduceGroups(function (groupCount, groupName, group) { groupCount[groupName] = group.length; return groupCount; }, {}); } }], [{ key: "fromArray", value: function fromArray(array, hashFunc, context) { // Example: // Group.fromArray([1,2,3,4,5,6], function(n) { return n % 2; }) // // => {"0": [2,4,6], "1": [1,3,5]} var grouping = new Group(); for (var i = 0, len = array.length; i < len; i++) { var hash = hashFunc.call(context, array[i], i); if (!grouping[hash]) grouping[hash] = []; grouping[hash].push(array[i]); } return grouping; } }, { key: "by", get: function get() { return groupBy; } }]); return Group; }(); /*global System, global*/ /* * Methods to make working with arrays more convenient and collection-like * abstractions for groups, intervals, grids. */ var GLOBAL$1 = typeof System !== "undefined" ? System.global : typeof window !== 'undefined' ? window : global; var features$1 = { from: !!Array.from, filter: !!Array.prototype.filter, find: !!Array.prototype.find, findIndex: !!Array.prototype.findIndex, includes: !!Array.prototype.includes }; // variety of functions for Arrays // -=-=-=-=-=-=-=- // array creations // -=-=-=-=-=-=-=- function range(begin, end, step) { // Examples: // arr.range(0,5) // => [0,1,2,3,4,5] // arr.range(0,10,2) // => [0,2,4,6,8,10] step = step || 0; var result = []; if (begin <= end) { if (step <= 0) step = -step || 1; for (var i = begin; i <= end; i += step) { result.push(i); } } else { if (step >= 0) step = -step || -1; for (var i = begin; i >= end; i += step) { result.push(i); } } return result; } var from = features$1.from ? Array.from : function (iterable) { // Makes JS arrays out of array like objects like `arguments` or DOM `childNodes` if (!iterable) return []; if (Array.isArray(iterable)) return iterable; if (iterable.toArray) return iterable.toArray(); var length = iterable.length, results = new Array(length); while (length--) { results[length] = iterable[length]; }return results; }; function withN(n, obj) { // Example: // arr.withN(3, "Hello") // => ["Hello","Hello","Hello"] var result = new Array(n); while (n > 0) { result[--n] = obj; }return result; } function genN(n, generator) { // Number -> Function -> Array // Takes a generator function that is called for each `n`. // Example: // arr.genN(3, num.random) // => [46,77,95] var result = new Array(n); while (n > 0) { result[--n] = generator(n); }return result; } // -=-=-=-=- // filtering // -=-=-=-=- function filter(array, iterator, context) { // [a] -> (a -> Boolean) -> c? -> [a] // Calls `iterator` for each element in `array` and returns a subset of it // including the elements for which `iterator` returned a truthy value. // Like `Array.prototype.filter`. return array.filter(iterator, context); } var detect = features$1.find ? function (arr, iterator, context) { return arr.find(iterator, context); } : function (arr, iterator, context) { // [a] -> (a -> Boolean) -> c? -> a // returns the first occurrence of an element in `arr` for which iterator // returns a truthy value for (var value, i = 0, len = arr.length; i < len; i++) { value = arr[i]; if (iterator.call(context, value, i)) return value; } return undefined; }; var findIndex = features$1.findIndex ? function (arr, iterator, context) { return arr.findIndex(iterator, context); } : function (arr, iterator, context) { var i = -1; return arr.find(function (ea, j) { i = j;return iterator.call(ea, context); }) ? i : -1; }; function findAndGet(arr, iterator) { // find the first occurence for which `iterator` returns a truthy value and // return *this* value, i.e. unlike find the iterator result and not the // element of the list is returned var result; arr.find(function (ea, i) { return result = iterator(ea, i); }); return result; } function filterByKey(arr, key) { // [a] -> String -> [a] // Example: // var objects = [{x: 3}, {y: 4}, {x:5}] // arr.filterByKey(objects, "x") // => [{x: 3},{x: 5}] return arr.filter(function (ea) { return !!ea[key]; }); } function grep(arr, filter, context) { // [a] -> String|RegExp -> [a] // `filter` can be a String or RegExp. Will stringify each element in // Example: // ["Hello", "World", "Lively", "User"].grep("l") // => ["Hello","World","Lively"] if (typeof filter === 'string') filter = new RegExp(filter, 'i'); return arr.filter(filter.test.bind(filter)); } function mask(array, mask) { // select every element in array for which array's element is truthy // Example: [1,2,3].mask([false, true, false]) => [2] return array.filter(function (_, i) { return !!mask[i]; }); } function reject(array, func, context) { // show-in-doc function iterator(val, i) { return !func.call(context, val, i); } return array.filter(iterator); } function rejectByKey(array, key) { // show-in-doc return array.filter(function (ea) { return !ea[key]; }); } function without(array, elem) { // non-mutating // Example: // arr.without([1,2,3,4,5,6], 3) // => [1,2,4,5,6] return array.filter(function (val) { return val !== elem; }); } function withoutAll(array, otherArr) { // non-mutating // Example: // arr.withoutAll([1,2,3,4,5,6], [3,4]) // => [1,2,5,6] return array.filter(function (val) { return otherArr.indexOf(val) === -1; }); } function uniq(array, sorted) { // non-mutating // Removes duplicates from array. // if sorted == true then assume array is sorted which allows uniq to be more // efficient // uniq([3,5,6,2,3,4,2,6,4]) if (!array.length) return array; var result = [array[0]]; if (sorted) { for (var i = 1; i < array.length; i++) { var val = array[i]; if (val !== result[result.length]) result.push(val); } } else { for (var _i = 1; _i < array.length; _i++) { var _val = array[_i]; if (result.indexOf(_val) === -1) result.push(_val); } } return result; } function uniqBy(array, comparator, context) { // like `arr.uniq` but with custom equality: `comparator(a,b)` returns // BOOL. True if a and be should be regarded equal, false otherwise. var result = array.slice(); for (var i = result.length; i--;) { var item = array[i]; for (var j = i + 1; j < result.length; j++) { if (comparator.call(context, item, result[j])) result.splice(j--, 1); } } return result; } function uniqByKey(array, key) { // like `arr.uniq` but with equality based on item[key] var seen = {}, result = []; for (var i = 0; i < array.length; i++) { var item = array[i]; if (!seen[item[key]]) { seen[item[key]] = true; result.push(item); } } return result; } function compact(array) { // removes falsy values // Example: // arr.compact([1,2,undefined,4,0]) // => [1,2,4] return array.filter(Boolean); } function mutableCompact(array) { // fix gaps that were created with 'delete' var i = 0, j = 0, len = array.length; while (i < len) { if (array.hasOwnProperty(i)) array[j++] = array[i]; i++; } while (j++ < len) { array.pop(); }return array; } // -=-=-=-=- // iteration // -=-=-=-=- function forEach$1(array, iterator, context) { // [a] -> (a -> Undefined) -> c? -> Undefined // `iterator` is called on each element in `array` for side effects. Like // `Array.prototype.forEach`. return array.forEach(iterator, context); } function zip() /*arr, arr2, arr3*/{ // Takes any number of lists as arguments. Combines them elment-wise. // Example: // arr.zip([1,2,3], ["a", "b", "c"], ["A", "B"]) // // => [[1,"a","A"],[2,"b","B"],[3,"c",undefined]] var args = Array.from(arguments), array = args.shift(), iterator = typeof last(args) === 'function' ? args.pop() : function (x) { return x; }, collections = [array].concat(args).map(function (ea) { return Array.from(ea); }); return array.map(function (value, index) { return iterator(pluck(collections, index), index); }); } function flatten(array, optDepth) { // Turns a nested collection into a flat one. // Example: // arr.flatten([1, [2, [3,4,5], [6]], 7,8]) // // => [1,2,3,4,5,6,7,8] if (typeof optDepth === "number") { if (optDepth <= 0) return array; optDepth--; } return array.reduce(function (flattened, value) { return flattened.concat(Array.isArray(value) ? flatten(value, optDepth) : [value]); }, []); } function flatmap(array, it, ctx) { // the simple version // Array.prototype.concat.apply([], array.map(it, ctx)); // causes stack overflows with really big arrays var results = []; for (var i = 0; i < array.length; i++) { results.push.apply(results, it.call(ctx, array[i], i)); } return results; } function interpose(array, delim) { // Injects delim between elements of array // Example: // lively.lang.arr.interpose(["test", "abc", 444], "aha")); // // => ["test","aha","abc","aha",444] return array.reduce(function (xs, x) { if (xs.length > 0) xs.push(delim); xs.push(x);return xs; }, []); } function delimWith(array, delim) { // ignore-in-doc // previously used, use interpose now! return interpose(array, delim); } // -=-=-=-=- // mapping // -=-=-=-=- function map$1(array, iterator, context) { // [a] -> (a -> b) -> c? -> [b] // Applies `iterator` to each element of `array` and returns a new Array // with the results of those calls. Like `Array.prototype.some`. return array.map(iterator, context); } function invoke(array, method, arg1, arg2, arg3, arg4, arg5, arg6) { // Calls `method` on each element in `array`, passing all arguments. Often // a handy way to avoid verbose `map` calls. // Example: arr.invoke(["hello", "world"], "toUpperCase") // => ["HELLO","WORLD"] return array.map(function (ea) { return ea[method](arg1, arg2, arg3, arg4, arg5, arg6); }); } function pluck(array, property) { // Returns `property` or undefined from each element of array. For quick // `map`s and similar to `invoke`. // Example: arr.pluck(["hello", "world"], 0) // => ["h","w"] return array.map(function (ea) { return ea[property]; }); } // -=-=-=-=- // folding // -=-=-=-=- function reduce(array, iterator, memo, context) { // Array -> Function -> Object? -> Object? -> Object? // Applies `iterator` to each element of `array` and returns a new Array // with the results of those calls. Like `Array.prototype.some`. return array.reduce(iterator, memo, context); } function reduceRight(array, iterator, memo, context) { // show-in-doc return array.reduceRight(iterator, memo, context); } // -=-=-=-=- // testing // -=-=-=-=- var isArray$1 = Array.isArray; var includes$1 = features$1.includes ? function (array, object) { return array.includes(object); } : function (array, object) { // Example: arr.include([1,2,3], 2) // => true return array.indexOf(object) !== -1; }; var include$1 = includes$1; function some(array, iterator, context) { // [a] -> (a -> Boolean) -> c? -> Boolean // Returns true if there is at least one abject in `array` for which // `iterator` returns a truthy result. Like `Array.prototype.some`. return array.some(iterator, context); } function every(array, iterator, context) { // [a] -> (a -> Boolean) -> c? -> Boolean // Returns true if for all abjects in `array` `iterator` returns a truthy // result. Like `Array.prototype.every`. return array.every(iterator, context); } function equals$2(array, otherArray) { // Returns true iff each element in `array` is equal (`==`) to its // corresponding element in `otherArray` var len = array.length; if (!otherArray || len !== otherArray.length) return false; for (var i = 0; i < len; i++) { if (array[i] && otherArray[i] && array[i].equals && otherArray[i].equals) { if (!array[i].equals(otherArray[i])) { return false; } else { continue; } } if (array[i] != otherArray[i]) return false; } return true; } function deepEquals(array, otherArray) { // Returns true iff each element in `array` is structurally equal // (`lang.obj.equals`) to its corresponding element in `otherArray` var len = array.length; if (!otherArray || len !== otherArray.length) return false; for (var i = 0; i < len; i++) { if (!equals$1(array[i], otherArray[i])) return false; } return true; } // -=-=-=-=- // sorting // -=-=-=-=- function isSorted(array, descending) { if (descending) { for (var i = 1; i < array.length; i++) { if (array[i - 1] < array[i]) return false; } } else { for (var i = 1; i < array.length; i++) { if (array[i - 1] > array[i]) return false; } } return true; } function sort(array, sortFunc) { // [a] -> (a -> Number)? -> [a] // Just `Array.prototype.sort` return array.sort(sortFunc); } function sortBy(array, iterator, context) { // Example: // arr.sortBy(["Hello", "Lively", "User"], function(ea) { // return ea.charCodeAt(ea.length-1); }) // => ["Hello","User","Lively"] return pluck(array.map(function (value, index) { return { value: value, criteria: iterator.call(context, value, index) }; }).sort(function (left, right) { var a = left.criteria, b = right.criteria; return a < b ? -1 : a > b ? 1 : 0; }), 'value'); } function sortByKey(array, key) { // Example: // lively.lang.arr.sortByKey([{x: 3}, {x: 2}, {x: 8}], "x") // // => [{x: 2},{x: 3},{x: 8}] return sortBy(array, function (ea) { return ea[key]; }); } function reverse(array) { return array.reverse(); } function reversed(array) { return array.slice().reverse(); } // -=-=-=-=-=-=-=-=-=-=-=-=- // RegExp / String matching // -=-=-=-=-=-=-=-=-=-=-=-=- function reMatches$1(arr, re, stringifier) { // result might include null items if re did not match (usful for masking) // Example: // var morphs = $world.withAllSubmorphsDo(function(x) { return x; ; // morphs.mask(morphs.reMatches(/code/i)) stringifier = stringifier || String; return arr.map(function (ea) { return stringifier(ea).match(re); }); } // -=-=-=-=-=- // accessors // -=-=-=-=-=- function first(array) { return array[0]; } function last(array) { return array[array.length - 1]; } // -=-=-=-=-=-=-=- // Set operations // -=-=-=-=-=-=-=- function intersect(array1, array2) { // set-like intersection return uniq(array1).filter(function (item) { return array2.indexOf(item) > -1; }); } function union(array1, array2) { // set-like union var result = array1.slice(); for (var i = 0; i < array2.length; i++) { var item = array2[i]; if (result.indexOf(item) === -1) result.push(item); } return result; } function pushAt(array, item, index) { // inserts `item` at `index`, mutating array.splice(index, 0, item); } function removeAt(array, index) { // inserts item at `index`, mutating array.splice(index, 1); } function remove(array, item) { // removes first occurrence of item in `array`, mutating var index = array.indexOf(item); if (index >= 0) removeAt(array, index); return item; } function pushAll$1(array, items) { // appends all `items`, mutating array.push.apply(array, items); return array; } function pushAllAt(array, items, idx) { // inserts all `items` at `idx`, mutating array.splice.apply(array, [idx, 0].concat(items)); } function pushIfNotIncluded(array, item) { // only appends `item` if its not already in `array`, mutating if (!array.includes(item)) array.push(item); } function replaceAt(array, item, index) { // mutating array.splice(index, 1, item); } function clear(array) { // removes all items, mutating array.length = 0;return array; } function isSubset(list1, list2) { // are all elements in list1 in list2? for (var i = 0; i < list1.length; i++) { if (!list2.includes(list1[i])) return false; }return true; } // -=-=-=-=-=-=-=-=-=-=-=- // asynchronous iteration // -=-=-=-=-=-=-=-=-=-=-=- function doAndContinue(array, iterator, endFunc, context) { // Iterates over array but instead of consecutively calling iterator, // iterator gets passed in the invocation for the next iteration step // as a function as first parameter. This allows to wait arbitrarily // between operation steps, great for managing dependencies between tasks. // Related is [`fun.composeAsync`](). // Example: // arr.doAndContinue([1,2,3,4], function(next, n) { // alert("At " + n); // setTimeout(next, 100); // }, function() { alert("Done"); }) // // If the elements are functions you can leave out the iterator: // arr.doAndContinue([ // function(next) { alert("At " + 1); next(); }, // function(next) { alert("At " + 2); next(); } // ], null, function() { alert("Done"); }); endFunc = endFunc || Null; context = context || GLOBAL$1; iterator = iterator || function (next, ea, idx) { ea.call(context, next, idx); }; return array.reduceRight(function (nextFunc, ea, idx) { return function () { iterator.call(context, nextFunc, ea, idx); }; }, endFunc)(); } function nestedDelay(array, iterator, waitSecs, endFunc, context, optSynchronChunks) { // Calls `iterator` for every element in `array` and waits between iterator // calls `waitSecs`. Eventually `endFunc` is called. When passing a number n // as `optSynchronChunks`, only every nth iteration is delayed. endFunc = endFunc || function () {}; return array.clone().reverse().reduce(function (nextFunc, ea, idx) { return function () { iterator.call(context || GLOBAL$1, ea, idx); // only really delay every n'th call optionally if (optSynchronChunks && idx % optSynchronChunks !== 0) { nextFunc(); } else { nextFunc.delay(waitSecs); } }; }, endFunc)(); } function forEachShowingProgress() /*array, progressBar, iterator, labelFunc, whenDoneFunc, context or spec*/{ // ignore-in-doc var args = Array.from(arguments), array = args.shift(), steps = array.length, progressBar, iterator, labelFunc, whenDoneFunc, context, progressBarAdded = false; // init args if (args.length === 1) { progressBar = args[0].progressBar; iterator = args[0].iterator; labelFunc = args[0].labelFunction; whenDoneFunc = args[0].whenDone; context = args[0].context; } else { progressBar = args[0]; iterator = args[1]; labelFunc = args[2]; whenDoneFunc = args[3]; context = args[4]; } if (!context) context = typeof window !== 'undefined' ? window : global; if (!labelFunc) labelFunc = function labelFunc(x) { return x; }; // init progressbar if (!progressBar) { progressBarAdded = true; var Global = typeof window !== 'undefined' ? window : global; var world = Global.lively && lively.morphic && lively.morphic.World.current(); progressBar = world ? world.addProgressBar() : { setValue: function setValue(val) {}, setLabel: function setLabel() {}, remove: function remove() {} }; } progressBar.setValue(0); // nest functions so that the iterator calls the next after a delay array.reduceRight(function (nextFunc, item, idx) { return function () { try { progressBar.setValue(idx / steps); if (labelFunc) progressBar.setLabel(labelFunc.call(context, item, idx)); iterator.call(context, item, idx); } catch (e) { console.error('Error in forEachShowingProgress at %s (%s)\n%s\n%s', idx, item, e, e.stack); } nextFunc.delay(0); }; }, function () { progressBar.setValue(1); if (progressBarAdded) (function () { progressBar.remove(); }).delay(0); if (whenDoneFunc) whenDoneFunc.call(context); })(); return array; } function swap(array, index1, index2) { // mutating // Example: // var a = [1,2,3,4]; // arr.swap(a, 3, 1); // a // => [1,4,3,2] if (index1 < 0) index1 = array.length + index1; if (index2 < 0) index2 = array.length + index2; var temp = array[index1]; array[index1] = array[index2]; array[index2] = temp; return array; } function rotate(array, times) { // non-mutating // Example: // arr.rotate([1,2,3]) // => [2,3,1] times = times || 1; return array.slice(times).concat(array.slice(0, times)); } // -=-=-=-=- // grouping // -=-=-=-=- function groupBy(array, iterator, context) { // Applies `iterator` to each element in `array`, and puts the return value // into a collection (the group) associated to it's stringified representation // (the "hash"). // See [`Group.prototype`] for available operations on groups. // Example: // Example 1: Groups characters by how often they occur in a string: // var chars = arr.from("Hello World"); // arr.groupBy(arr.uniq(chars), function(c) { // return arr.count(chars, c); }) // // => { // // "1": ["H","e"," ","W","r","d"], // // "2": ["o"], // // "3": ["l"] // // } // // Example 2: Group numbers by a custom qualifier: // arr.groupBy([3,4,1,7,4,3,8,4], function(n) { // if (n <= 3) return "small"; // if (n <= 7) return "medium"; // return "large"; // }); // // => { // // large: [8], // // medium: [4,7,4,4], // // small: [3,1,3] // // } return Group.fromArray(array, iterator, context); } function groupByKey(array, key) { // var objects = [{x: }] // arr.groupBy(arr.uniq(chars), function(c) { // return arr.count(chars, c); }) // // => { // // "1": ["H","e"," ","W","r","d"], // // "2": ["o"], // // "3": ["l"] // // } return groupBy(array, function (ea) { return ea[key]; }); } function partition(array, iterator, context) { // Example: // var array = [1,2,3,4,5,6]; // arr.partition(array, function(ea) { return ea > 3; }) // // => [[1,2,3,4],[5,6]] iterator = iterator || function (x) { return x; }; var trues = [], falses = []; array.forEach(function (value, index) { (iterator.call(context, value, index) ? trues : falses).push(value); }); return [trues, falses]; } function batchify(array, constrainedFunc, context) { // Takes elements and fits them into subarrays (= batches) so that for // each batch constrainedFunc returns true. Note that contrained func // should at least produce 1-length batches, otherwise an error is raised // Example: // // Assume you have list of things that have different sizes and you want to // // create sub-arrays of these things, with each sub-array having if possible // // less than a `batchMaxSize` of combined things in it: // var sizes = [ // Math.pow(2, 15), // 32KB // Math.pow(2, 29), // 512MB // Math.pow(2, 29), // 512MB // Math.pow(2, 27), // 128MB // Math.pow(2, 26), // 64MB // Math.pow(2, 26), // 64MB // Math.pow(2, 24), // 16MB // Math.pow(2, 26)] // 64MB // var batchMaxSize = Math.pow(2, 28)/*256MB*/; // function batchConstrained(batch) { // return batch.length == 1 || batch.sum() < batchMaxSize; // } // var batches = sizes.batchify(batchConstrained); // batches.pluck('length') // => [4,1,1,2] // batches.map(arr.sum).map(num.humanReadableByteSize) // => ["208.03MB","512MB","512MB","128MB"] return findBatches([], array); // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- function extractBatch(batch, sizes) { // ignore-in-doc // Array -> Array -> Array[Array,Array] // case 1: no sizes to distribute, we are done if (!sizes.length) return [batch, []]; var first = sizes[0], rest = sizes.slice(1); // if batch is empty we have to take at least one // if batch and first still fits, add first var candidate = batch.concat([first]); if (constrainedFunc.call(context, candidate)) return extractBatch(candidate, rest); // otherwise leave first out for now var batchAndSizes = extractBatch(batch, rest); return [batchAndSizes[0], [first].concat(batchAndSizes[1])]; } function findBatches(batches, sizes) { if (!sizes.length) return batches; var extracted = extractBatch([], sizes); if (!extracted[0].length) throw new Error('Batchify constrained does not ensure consumption ' + 'of at least one item per batch!'); return findBatches(batches.concat([extracted[0]]), extracted[1]); } } function toTuples(array, tupleLength) { // Creates sub-arrays with length `tupleLength` // Example: // arr.toTuples(["H","e","l","l","o"," ","W","o","r","l","d"], 4) // // => [["H","e","l","l"],["o"," ","W","o"],["r","l","d"]] tupleLength = tupleLength || 1; return range(0, Math.ceil(array.length / tupleLength) - 1).map(function (n) { return array.slice(n * tupleLength, n * tupleLength + tupleLength); }, array); } var permutations = function () { function computePermutations(restArray, values$$1) { return !restArray.length ? [values$$1] : flatmap(restArray, function (ea, i) { return computePermutations(restArray.slice(0, i).concat(restArray.slice(i + 1)), values$$1.concat([ea])); }); } return function (array) { return computePermutations(array, []); }; }(); function combinationsPick(listOfListsOfValues, pickIndices) { // Given a "listOfListsOfValues" in the form of an array of arrays and // `pickIndices` list with the size of the number of arrays which indicates what // values to pick from each of the arrays, return a list with two values: // 1. values picked from each of the arrays, 2. the next pickIndices or null if at end // Example: // var searchSpace = [["a", "b", "c"], [1,2]]; // arr.combinationsPick(searchSpace, [0,1]); // // => [["a",2], [1,0]] // arr.combinationsPick(searchSpace, [1,0]); // // => [["b",1], [1,1]] var values$$1 = listOfListsOfValues.map(function (subspace, i) { return subspace[pickIndices[i]]; }), nextState = pickIndices.slice(); for (var i = listOfListsOfValues.length; i--; i >= 0) { var subspace = listOfListsOfValues[i], nextIndex = nextState[i] + 1; if (subspace[nextIndex]) { nextState[i] = nextIndex;break; } else if (i === 0) { nextState = undefined;break; } else { nextState[i] = 0; } } return [values$$1, nextState]; } function combinations(listOfListsOfValues) { // Given a "listOfListsOfValues" in the form of an array of arrays, // retrieve all the combinations by picking one item from each array. // This basically creates a search tree, traverses it and gathers all node // values whenever a leaf node is reached. // Example: // lively.lang.arr.combinations([['a', 'b', 'c'], [1, 2]]) // // => [["a", 1], ["a", 2], ["b", 1], ["b", 2], ["c", 1], ["c", 2]] var size = listOfListsOfValues.reduce(function (prod, space) { return prod * space.length; }, 1), searchState = listOfListsOfValues.map(function (_) { return 0; }), results = new Array(size); for (var i = 0; i < size; i++) { var result = combinationsPick(listOfListsOfValues, searchState); results[i] = result[0]; searchState = result[1]; } return results; } function take(arr, n) { return arr.slice(0, n); } function drop(arr, n) { return arr.slice(n); } function takeWhile(arr, fun, context) { var i = 0; for (; i < arr.length; i++) { if (!fun.call(context, arr[i], i)) break; }return arr.slice(0, i); } function dropWhile(arr, fun, context) { var i = 0; for (; i < arr.length; i++) { if (!fun.call(context, arr[i], i)) break; }return arr.slice(i); } // -=-=-=-=-=- // randomness // -=-=-=-=-=- function shuffle(array) { // Ramdomize the order of elements of array. Does not mutate array. // Example: // shuffle([1,2,3,4,5]) // => [3,1,2,5,4] var unusedIndexes = range(0, array.length - 1), shuffled = Array(array.length); for (var i = 0; i < array.length; i++) { var shuffledIndex = unusedIndexes.splice(Math.round(Math.random() * (unusedIndexes.length - 1)), 1); shuffled[shuffledIndex] = array[i]; } return shuffled; } // -=-=-=-=-=-=-=- // Number related // -=-=-=-=-=-=-=- function max(array, iterator, context) { // Example: // var array = [{x:3,y:2}, {x:5,y:1}, {x:1,y:5}]; // arr.max(array, function(ea) { return ea.x; }) // => {x: 5, y: 1} iterator = iterator || function (x) { return x; }; var result; array.reduce(function (max, ea, i) { var val = iterator.call(context, ea, i); if (typeof val !== "number" || val <= max) return max; result = ea;return val; }, -Infinity); return result; } function min(array, iterator, context) { // Similar to `arr.max`. iterator = iterator || function (x) { return x; }; return max(array, function (ea, i) { return -iterator.call(context, ea, i); }); } function sum(array) { // show-in-doc var sum = 0; for (var i = 0; i < array.length; i++) { sum += array[i]; }return sum; } function count$1(array, item) { return array.reduce(function (count, ea) { return ea === item ? count + 1 : count; }, 0); } function size$1(array) { return array.length; } function histogram(data, binSpec) { // ignore-in-doc // Without a `binSpec` argument partition the data // var numbers = arr.genN(10, num.random); // var numbers = arr.withN(10, "a"); // => [65,73,34,94,92,31,27,55,95,48] // => [[65,73],[34,94],[92,31],[27,55],[95,48]] // => [[82,50,16],[25,43,77],[40,64,31],[51,39,13],[17,34,87],[51,33,30]] if (typeof binSpec === 'undefined' || typeof binSpec === 'number') { var binNumber = binSpec || function sturge() { return Math.ceil(Math.log(data.length) / Math.log(2) + 1); }(data); var binSize = Math.ceil(Math.round(data.length / binNumber)); return range(0, binNumber - 1).map(function (i) { return data.slice(i * binSize, (i + 1) * binSize); }); } else if (binSpec instanceof Array) { // ignore-in-doc // bins specifies n threshold values that will create n-1 bins. // Each data value d is placed inside a bin i if: // threshold[i] >= d && threshold[i+1] < d var thresholds = binSpec; return data.reduce(function (bins, d) { if (d < thresholds[1]) { bins[0].push(d);return bins; } for (var i = 1; i < thresholds.length; i++) { if (d >= thresholds[i] && (!thresholds[i + 1] || d <= thresholds[i + 1])) { bins[i].push(d);return bins; } } throw new Error("Histogram creation: Cannot group data " + d + " into thresholds " + thresholds); }, range(1, thresholds.length).map(function () { return []; })); } } // -=-=-=-=- // Copying // -=-=-=-=- function clone$1(array) { // shallow copy return [].concat(array); } // -=-=-=-=-=- // conversion // -=-=-=-=-=- function toArray$3(array) { return from(array); } // -=-=-=-=-=- // DEPRECATED // -=-=-=-=-=- function each(arr, iterator, context) { return arr.forEach(iterator, context); } function all$1(arr, iterator, context) { return arr.every(iterator, context); } function any(arr, iterator, context) { return arr.some(iterator, context); } function collect(arr, iterator, context) { return arr.map(iterator, context); } function findAll(arr, iterator, context) { return arr.filter(iterator, context); } function inject(array, memo, iterator, context) { if (context) iterator = iterator.bind(context); return array.reduce(iterator, memo); } // asynch methods function mapAsyncSeries(array, iterator, callback) { // Apply `iterator` over `array`. Unlike `mapAsync` the invocation of // the iterator happens step by step in the order of the items of the array // and not concurrently. // ignore-in-doc // Could simply be: // return exports.arr.mapAsync(array, {parallel: 1}, iterator, callback); // but the version below is 2x faster var result = [], callbackTriggered = false; return array.reduceRight(function (nextFunc, ea, idx) { if (callbackTriggered) return; return function (err, eaResult) { if (err) return maybeDone(err); if (idx > 0) result.push(eaResult); try { iterator(ea, idx, once(nextFunc)); } catch (e) { maybeDone(e); } }; }, function (err, eaResult) { result.push(eaResult); maybeDone(err, true); })(); function maybeDone(err, finalCall) { if (callbackTriggered || !err && !finalCall) return; callbackTriggered = true; try { callback(err, result); } catch (e) { console.error("Error in mapAsyncSeries - callback invocation error:\n" + (e.stack || e)); } } } function mapAsync(array, options, iterator, callback) { // Apply `iterator` over `array`. In each iterator gets a callback as third // argument that should be called when the iteration is done. After all // iterators have called their callbacks, the main `callback` function is // invoked with the result array. // Example: // lively.lang.arr.mapAsync([1,2,3,4], // function(n, i, next) { setTimeout(function() { next(null, n + i); }, 20); }, // function(err, result) { /* result => [1,3,5,7] */ }); if (typeof options === "function") { callback = iterator; iterator = options; options = null; } options = options || {}; if (!array.length) return callback && callback(null, []); if (!options.parallel) options.parallel = Infinity; var results = [], completed = [], callbackTriggered = false, lastIteratorIndex = 0, nActive = 0; var iterators = array.map(function (item, i) { return function () { nActive++; try { iterator(item, i, once(function (err, result) { results[i] = err || result; maybeDone(i, err); })); } catch (e) { maybeDone(i, e); } }; }); return activate(); // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- function activate() { while (nActive < options.parallel && lastIteratorIndex < array.length) { iterators[lastIteratorIndex++](); } } function maybeDone(idx, err) { if (completed.indexOf(idx) > -1) return; completed.push(idx); nActive--; if (callbackTriggered) return; if (!err && completed.length < array.length) { activate();return; } callbackTriggered = true; try { callback && callback(err, results); } catch (e) { console.error("Error in mapAsync - main callback invocation error:\n" + (e.stack || e)); } } } // poly-filling... if (!features$1.from) Array.from = from; if (!features$1.filter) Array.prototype.filter = function (it, ctx) { return filter(this, it, ctx); }; if (!features$1.find) Array.prototype.find = function (it, ctx) { return detect(this, it, ctx); }; if (!features$1.findIndex) Array.prototype.findIndex = function (it, ctx) { return findIndex(this, it, ctx); }; if (!features$1.includes) Array.prototype.includes = function (x) { return includes$1(this, x); }; var arr = Object.freeze({ range: range, from: from, withN: withN, genN: genN, filter: filter, detect: detect, findIndex: findIndex, findAndGet: findAndGet, filterByKey: filterByKey, grep: grep, mask: mask, reject: reject, rejectByKey: rejectByKey, without: without, withoutAll: withoutAll, uniq: uniq, uniqBy: uniqBy, uniqByKey: uniqByKey, compact: compact, mutableCompact: mutableCompact, forEach: forEach$1, zip: zip, flatten: flatten, flatmap: flatmap, interpose: interpose, delimWith: delimWith, map: map$1, invoke: invoke, pluck: pluck, reduce: reduce, reduceRight: reduceRight, isArray: isArray$1, includes: includes$1, include: include$1, some: some, every: every, equals: equals$2, deepEquals: deepEquals, isSorted: isSorted, sort: sort, sortBy: sortBy, sortByKey: sortByKey, reverse: reverse, reversed: reversed, reMatches: reMatches$1, first: first, last: last, intersect: intersect, union: union, pushAt: pushAt, removeAt: removeAt, remove: remove, pushAll: pushAll$1, pushAllAt: pushAllAt, pushIfNotIncluded: pushIfNotIncluded, replaceAt: replaceAt, clear: clear, isSubset: isSubset, doAndContinue: doAndContinue, nestedDelay: nestedDelay, forEachShowingProgress: forEachShowingProgress, swap: swap, rotate: rotate, groupBy: groupBy, groupByKey: groupByKey, partition: partition, batchify: batchify, toTuples: toTuples, permutations: permutations, combinationsPick: combinationsPick, combinations: combinations, take: take, drop: drop, takeWhile: takeWhile, dropWhile: dropWhile, shuffle: shuffle, max: max, min: min, sum: sum, count: count$1, size: size$1, histogram: histogram, clone: clone$1, toArray: toArray$3, each: each, all: all$1, any: any, collect: collect, findAll: findAll, inject: inject, mapAsyncSeries: mapAsyncSeries, mapAsync: mapAsync }); /* * Utility functions that help to inspect, enumerate, and create JS objects */ // -=-=-=-=-=-=-=-=- // internal helper // -=-=-=-=-=-=-=-=- // serveral methods in lib/object.js are inspired or derived from // Prototype JavaScript framework, version 1.6.0_rc1 // (c) 2005-2007 Sam Stephenson // Prototype is freely distributable under the terms of an MIT-style license. // For details, see the Prototype web site: http://www.prototypejs.org/ function print$1(object) { if (object && Array.isArray(object)) { return '[' + object.map(print$1) + ']'; } if (typeof object !== "string") { return String(object); } var result = String(object); result = result.replace(/\n/g, '\\n\\\n'); result = result.replace(/(")/g, '\\$1'); result = '\"' + result + '\"'; return result; } function indent$1(str, indentString, depth) { if (!depth || depth <= 0) return str; while (depth > 0) { depth--;str = indentString + str; } return str; } var getOwnPropertyDescriptors = typeof Object.prototype.getOwnPropertyDescriptors === "function" ? Object.prototype.getOwnPropertyDescriptors : function getOwnPropertyDescriptors(object) { var descriptors = {}; for (var name in object) { if (!Object.prototype.hasOwnProperty.call(object, name)) continue; Object.defineProperty(descriptors, name, { configurable: true, enumerable: true, writable: true, value: Object.getOwnPropertyDescriptor(object, name) }); } return descriptors; }; // show-in-doc // -=-=-=-=- // testing // -=-=-=-=- function isArray$$1(obj) { /*show-in-doc*/return Array.isArray(obj); } function isElement(object) { /*show-in-doc*/return object && object.nodeType == 1; } function isFunction(object) { /*show-in-doc*/return object instanceof Function; } function isBoolean(object) { /*show-in-doc*/return typeof object == "boolean"; } function isString(object) { /*show-in-doc*/return typeof object == "string"; } function isNumber(object) { /*show-in-doc*/return typeof object == "number"; } function isUndefined(object) { /*show-in-doc*/return typeof object == "undefined"; } function isRegExp(object) { /*show-in-doc*/return object instanceof RegExp; } function isObject(object) { /*show-in-doc*/return (typeof object === "undefined" ? "undefined" : _typeof(object)) == "object"; } function isPrimitive(obj) { // show-in-doc if (!obj) return true; switch (typeof obj === "undefined" ? "undefined" : _typeof(obj)) { case "string": case "number": case "boolean": return true; } return false; } function isEmpty(object) { /*show-in-doc*/ for (var key in object) { if (object.hasOwnProperty(key)) return false; }return true; } function equals$1(a, b) { // Is object `a` structurally equivalent to object `b`? Deep comparison. if (a === b) return true; if (!a || !b) return a == b; if (Array.isArray(a)) return deepEquals(a, b); switch (a.constructor) { case String: case Date: case Boolean: case Number: return a == b; } if (typeof a.isEqualNode === "function") return a.isEqualNode(b); if (typeof a.equals === "function") return a.equals(b); var seenInA = []; for (var name in a) { seenInA.push(name); if (typeof a[name] === "function") continue; if (!equals$1(a[name], b[name])) return false; } for (var name in b) { if (seenInA.indexOf(name) !== -1) continue; if (typeof b[name] === "function") continue; if (!equals$1(b[name], a[name])) return false; } return true; } // -=-=-=-=-=- // accessing // -=-=-=-=-=- var keys$1 = Object.keys; function values(object) { // Example: // var obj1 = {x: 22}, obj2 = {x: 23, y: {z: 3}}; // obj2.__proto__ = obj1; // obj.values(obj1) // => [22] // obj.values(obj2) // => [23,{z: 3}] return object ? Object.keys(object).map(function (k) { return object[k]; }) : []; } function select(obj, keys) { // return a new object that copies all properties with `keys` from `obj` var selected = {}; for (var i = 0; i < keys.length; i++) { selected[keys[i]] = obj[keys[i]]; }return selected; } function dissoc(object, keys) { object = object || {}; var descriptors = getOwnPropertyDescriptors(object); for (var i = 0; i < keys.length; i++) { if (keys[i] in descriptors) delete descriptors[keys[i]]; } return Object.defineProperties({}, descriptors); } function addScript(object, funcOrString, optName, optMapping) { var func = fromString(funcOrString); return asScriptOf(func, object, optName, optMapping); } // -=-=-=-=- // mutation // -=-=-=-=- function extend(destination, source) { // Add all properties of `source` to `destination`. // Example: // var dest = {x: 22}, src = {x: 23, y: 24} // obj.extend(dest, src); // dest // => {x: 23,y: 24} var currentCategoryNames = null; for (var i = 1; i < arguments.length; i++) { if (typeof arguments[i] == "string") { var catName = arguments[i]; if (!destination.categories) destination.categories = {}; if (!destination.categories[catName]) destination.categories[catName] = []; currentCategoryNames = destination.categories[catName]; continue; } var source = arguments[i]; for (var property in source) { var getter = source.__lookupGetter__(property), setter = source.__lookupSetter__(property); if (getter) destination.__defineGetter__(property, getter); if (setter) destination.__defineSetter__(property, setter); if (getter || setter) continue; var sourceObj = source[property]; destination[property] = sourceObj; if (currentCategoryNames) currentCategoryNames.push(property); if (typeof sourceObj === "function") { if (!sourceObj.displayName) sourceObj.displayName = property; // remember the module that contains the definition if (typeof lively !== "undefined" && lively.Module && lively.Module.current) sourceObj.sourceModule = lively.Module.current(); } } } return destination; } // -=-=-=-=- // clone // -=-=-=-=- function clone$$1(object) { // Shallow copy if (isPrimitive(object)) return object; if (Array.isArray(object)) return Array.prototype.slice.call(object); var clone$$1 = {}; for (var key in object) { if (object.hasOwnProperty(key)) clone$$1[key] = object[key]; } return clone$$1; } function extract(object, properties, mapFunc) { // Takes a list of properties and returns a new object with those // properties shallow-copied from object var copied = {}; for (var i = 0; i < properties.length; i++) { if (properties[i] in object) copied[properties[i]] = mapFunc ? mapFunc(properties[i], object[properties[i]]) : object[properties[i]]; } return copied; } // -=-=-=-=-=- // inspection // -=-=-=-=-=- function inspect(object, options, depth) { // Prints a human-readable representation of `obj`. The printed // representation will be syntactically correct JavaScript but will not // necessarily evaluate to a structurally identical object. `inspect` is // meant to be used while interactivively exploring JavaScript programs and // state. // // `options` can be { // printFunctionSource: BOOLEAN, // escapeKeys: BOOLEAN, // maxDepth: NUMBER, // customPrinter: FUNCTION, // maxNumberOfKeys: NUMBER // } options = options || {}; depth = depth || 0; if (options.customPrinter) { var ignoreSignal = options._ignoreSignal || (options._ignoreSignal = {}), continueInspectFn = function continueInspectFn(obj) { return inspect(obj, options, depth + 1); }, customInspected = options.customPrinter(object, ignoreSignal, continueInspectFn); if (customInspected !== ignoreSignal) return customInspected; } if (!object) return print$1(object); // print function if (typeof object === 'function') { return options.printFunctionSource ? String(object) : 'function' + (object.name ? ' ' + object.name : '') + '(' + argumentNames(object).join(',') + ') {/*...*/}'; } // print "primitive" switch (object.constructor) { case String: case Boolean: case RegExp: case Number: return print$1(object); } if (typeof object.serializeExpr === 'function') return object.serializeExpr(); var isArray$$1 = object && Array.isArray(object), openBr = isArray$$1 ? '[' : '{', closeBr = isArray$$1 ? ']' : '}'; if (options.maxDepth && depth >= options.maxDepth) return openBr + '/*...*/' + closeBr; var printedProps = []; if (isArray$$1) { printedProps = object.map(function (ea) { return inspect(ea, options, depth + 1); }); } else { var propsToPrint = Object.keys(object).sort(function (a, b) { var aIsFunc = typeof object[a] === 'function', bIsFunc = typeof object[b] === 'function'; if (aIsFunc === bIsFunc) { if (a < b) return -1; if (a > b) return 1; return 0; } return aIsFunc ? 1 : -1; }); for (var i = 0; i < propsToPrint.length; i++) { if (i > (options.maxNumberOfKeys || Infinity)) { var hiddenEntryCount = propsToPrint.length - i; printedProps.push("..." + hiddenEntryCount + " hidden " + (hiddenEntryCount > 1 ? 'entries' : 'entry') + "..."); break; } var key = propsToPrint[i]; if (isArray$$1) inspect(object[key], options, depth + 1); var printedVal = inspect(object[key], options, depth + 1); printedProps.push((options.escapeKeys ? JSON.stringify(key) : key) + ": " + printedVal); } } if (printedProps.length === 0) { return openBr + closeBr; } var printedPropsJoined = printedProps.join(', '), useNewLines = (!isArray$$1 || options.newLineInArrays) && (!options.minLengthForNewLine || printedPropsJoined.length >= options.minLengthForNewLine), ind = indent$1('', options.indent || ' ', depth), propIndent = indent$1('', options.indent || ' ', depth + 1), startBreak = useNewLines && !isArray$$1 ? '\n' + propIndent : '', eachBreak = useNewLines ? '\n' + propIndent : '', endBreak = useNewLines && !isArray$$1 ? '\n' + ind : ''; if (useNewLines) printedPropsJoined = printedProps.join(',' + eachBreak); return openBr + startBreak + printedPropsJoined + endBreak + closeBr; } // -=-=-=-=- // merging // -=-=-=-=- function merge(objs) { // `objs` can be a list of objects. The return value will be a new object, // containing all properties of all objects. If the same property exist in // multiple objects, the right-most property takes precedence. // // Like `extend` but will not mutate objects in `objs`. // if objs are arrays just concat them // if objs are real objs then merge propertdies if (arguments.length > 1) { return merge(Array.prototype.slice.call(arguments)); } if (Array.isArray(objs[0])) { // test for all? return Array.prototype.concat.apply([], objs); } return objs.reduce(function (merged, ea) { for (var name in ea) { if (ea.hasOwnProperty(name)) merged[name] = ea[name]; }return merged; }, {}); } function deepMerge(objA, objB) { // `objs` can be a list of objects. The return value will be a new object, // containing all properties of all objects. If the same property exist in // multiple objects, the right-most property takes precedence. // // Like `extend` but will not mutate objects in `objs`. // if objs are arrays just concat them // if objs are real objs then merge propertdies if (!objA) return objB; if (!objB) return objA; if (Array.isArray(objA)) { if (!Array.isArray(objB)) return objB; var merged = objA.map(function (ea, i) { return deepMerge(ea, objB[i]); }); if (objB.length > objA.length) merged = merged.concat(objB.slice(objA.length)); return merged; } if ((typeof objA === "undefined" ? "undefined" : _typeof(objA)) !== "object" || (typeof objB === "undefined" ? "undefined" : _typeof(objB)) !== "object") return objB; return Object.keys(objA).concat(Object.keys(objB)).reduce(function (merged, name) { if (!objA[name]) merged[name] = objB[name];else if (!objB[name]) merged[name] = objA[name];else if (_typeof(objA[name]) !== "object" || _typeof(objB[name]) !== "object") merged[name] = objB[name];else merged[name] = deepMerge(objA[name], objB[name]); return merged; }, {}); } function sortKeysWithBeforeAndAfterConstraints(properties) { var throwErrorOnMissing = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; // Expects `properties` to be a map of keys to objects having optional // before/after attributes that, if present, should be lists of other property // keys. `sortProperties` will return an ordered list of property keys so // that the before / after requirements are fullfilled. If a cyclic // dependency is encountered an error will be thrown. // Example: // ``` // sortProperties({foo: {}, bar: {after: ["foo"], before: ["baz"]}, "baz": {after: ["foo"]}}) // // => ["foo","bar","baz"] // ``` // ignore-in-doc // 1. convert "before" requirement into "after" and check if all properties // mentioned in after/before are actually there var keys = [], props = [], remaining = []; for (var key in properties) { var prop = properties[key], before = prop.hasOwnProperty("before") ? prop.before : prop.before = [], after = prop.hasOwnProperty("after") ? prop.after : prop.after = []; keys.push(key); props.push(prop); for (var i = before.length; i--;) { var beforePropName = before[i]; var beforeProp = properties[beforePropName]; if (!beforeProp) { console.warn("[initializeProperties] " + this + " sortProperties: " + ("Property " + key + " requires to be initialized before " + beforePropName + " ") + "but that property cannot be found."); before.splice(i, 1); continue; } if (!beforeProp.hasOwnProperty("after")) beforeProp.after = []; beforeProp.after.push(key); } for (var _i = after.length; _i--;) { var afterPropName = after[_i]; var afterProp = properties[afterPropName]; if (!afterProp) { console.warn("[initializeProperties] " + this + " sortProperties: " + ("Property " + key + " requires to be initialized after " + afterPropName + " ") + "but that property cannot be found."); after.splice(_i, 1); } } remaining.push(key); } // ignore-in-doc // compute order var resolvedGroups = [], resolvedKeys = [], lastLength = remaining.length + 1; while (remaining.length) { if (lastLength === remaining.length) throw new Error("Circular dependencies in handler order, could not resolve properties " + remaining.map(function (key) { var before = properties[key].before, after = properties[key].after; if ((!before || !before.length) && (!after || !after.length)) return ""; var report = key + "\n"; if (before && before.length) report += " - before " + before.join(",") + "\n"; if (after && after.length) report += " - after " + after.join(",") + "\n"; return report; }).join("")); lastLength = remaining.length; var resolvedGroup = []; for (var _i2 = remaining.length; _i2--;) { var _key = remaining[_i2]; if (isSubset(properties[_key].after, resolvedKeys)) { remaining.splice(_i2, 1); resolvedKeys.push(_key); resolvedGroup.push(_key); } } resolvedGroups.push(resolvedGroup); } return flatten(resolvedGroups, 1); } // -=-=-=-=-=-=- // inheritance // -=-=-=-=-=-=- function inherit(obj) { return Object.create(obj); } function valuesInPropertyHierarchy(obj, name) { // Lookup all properties named name in the proto hierarchy of obj. // Example: // var a = {foo: 3}, b = Object.create(a), c = Object.create(b); // c.foo = 4; // obj.valuesInPropertyHierarchy(c, "foo") // => [3,4] var result = [], lookupObj = obj; while (lookupObj) { if (lookupObj.hasOwnProperty(name)) result.unshift(lookupObj[name]); lookupObj = Object.getPrototypeOf(lookupObj); } return result; } function mergePropertyInHierarchy(obj, propName) { // like `merge` but automatically gets all definitions of the value in the // prototype chain and merges those. // Example: // var o1 = {x: {foo: 23}}, o2 = {x: {foo: 24, bar: 15}}, o3 = {x: {baz: "zork"}}; // o2.__proto__ = o1; o3.__proto__ = o2; // obj.mergePropertyInHierarchy(o3, "x"); // // => {bar: 15, baz: "zork",foo: 24} return merge(valuesInPropertyHierarchy(obj, propName)); } function deepCopy(object) { // Recursively traverses `object` and its properties to create a copy. if (!object || (typeof object === "undefined" ? "undefined" : _typeof(object)) !== "object" || object instanceof RegExp) return object; var result = Array.isArray(object) ? Array(object.length) : {}; for (var key in object) { if (object.hasOwnProperty(key)) result[key] = deepCopy(object[key]); } return result; } // -=-=-=-=-=-=-=-=- // stringification // -=-=-=-=-=-=-=-=- function typeStringOf(obj) { // ignore-in-doc if (obj === null) return "null"; if (typeof obj === "undefined") return "undefined"; return obj.constructor.name; } function shortPrintStringOf(obj) { // ignore-in-doc // primitive values if (!isMutableType(obj)) return safeToString(obj); // constructed objects if (obj.constructor.name !== 'Object' && !Array.isArray(obj)) { if (obj.constructor.name) return obj.constructor.name ? obj.constructor.name : Object.prototype.toString.call(obj).split(" ")[1].split("]")[0]; } // arrays or plain objects var typeString = ""; function displayTypeAndLength(obj, collectionType, firstBracket, secondBracket) { if (obj.constructor.name === collectionType) { typeString += firstBracket; if (obj.length || Object.keys(obj).length) typeString += "..."; typeString += secondBracket; } } displayTypeAndLength(obj, "Object", "{", "}"); displayTypeAndLength(obj, "Array", "[", "]"); return typeString; } function isMutableType(obj) { // Is `obj` a value or mutable type? var immutableTypes = ["null", "undefined", "Boolean", "Number", "String"]; return immutableTypes.indexOf(typeStringOf(obj)) === -1; } function safeToString(obj) { // Like `toString` but catches errors. try { return (obj ? obj.toString() : String(obj)).replace('\n', ''); } catch (e) { return ''; } } function asObject(obj) { switch (typeof obj === "undefined" ? "undefined" : _typeof(obj)) { case 'string': return new String(obj); case 'boolean': return new Boolean(obj); case 'number': return new Number(obj); default: return obj; } } function newKeyIn(obj) { var base = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "_"; var i = 1, key; do { key = base + "-" + i++; } while (key in obj); return key; } var obj = Object.freeze({ isArray: isArray$$1, isElement: isElement, isFunction: isFunction, isBoolean: isBoolean, isString: isString, isNumber: isNumber, isUndefined: isUndefined, isRegExp: isRegExp, isObject: isObject, isPrimitive: isPrimitive, isEmpty: isEmpty, equals: equals$1, keys: keys$1, values: values, select: select, dissoc: dissoc, addScript: addScript, extend: extend, clone: clone$$1, extract: extract, inspect: inspect, merge: merge, deepMerge: deepMerge, inherit: inherit, valuesInPropertyHierarchy: valuesInPropertyHierarchy, mergePropertyInHierarchy: mergePropertyInHierarchy, sortKeysWithBeforeAndAfterConstraints: sortKeysWithBeforeAndAfterConstraints, deepCopy: deepCopy, typeStringOf: typeStringOf, shortPrintStringOf: shortPrintStringOf, isMutableType: isMutableType, safeToString: safeToString, asObject: asObject, newKeyIn: newKeyIn }); /*global btoa,JsDiff*/ /*lively.vm dontTransform: ["btoa"]*/ // String utility methods for printing, parsing, and converting strings. var features = { repeat: !!String.prototype.repeat, includes: !!String.prototype.includes, startsWith: !!String.prototype.startsWith, endsWith: !!String.prototype.endsWith }; // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- // printing and formatting strings // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- function format() { // String+ -> String // Takes a variable number of arguments. The first argument is the format // string. Placeholders in the format string are marked with `"%s"`. // Example: // lively.lang.string.format("Hello %s!", "Lively User"); // => "Hello Lively User!" return formatFromArray(Array.prototype.slice.call(arguments)); } function formatFromArray(objects) { var self = objects.shift(); if (!self) { console.log("Error in Strings>>formatFromArray, first arg is undefined"); } function appendText(object, string) { return "" + object; } function appendInteger(value, string) { return value.toString(); } function appendFloat(value, string, precision) { if (precision > -1) return value.toFixed(precision);else return value.toString(); } function appendObject(value, string) { return inspect(value); } var appenderMap = { s: appendText, d: appendInteger, i: appendInteger, f: appendFloat, o: appendObject }; var reg = /((^%|[^\\]%)(\d+)?(\.)([a-zA-Z]))|((^%|[^\\]%)([a-zA-Z]))/; function parseFormat(fmt) { var oldFmt = fmt; var parts = []; for (var m = reg.exec(fmt); m; m = reg.exec(fmt)) { var type = m[8] || m[5], appender = type in appenderMap ? appenderMap[type] : appendObject, precision = m[3] ? parseInt(m[3]) : m[4] == "." ? -1 : 0; parts.push(fmt.substr(0, m[0][0] == "%" ? m.index : m.index + 1)); parts.push({ appender: appender, precision: precision }); fmt = fmt.substr(m.index + m[0].length); } if (fmt) parts.push(fmt.toString()); return parts; } var parts = parseFormat(self), str = "", objIndex = 0; for (var i = 0; i < parts.length; ++i) { var part = parts[i]; if (part && (typeof part === "undefined" ? "undefined" : _typeof(part)) == "object") { var object = objects[objIndex++]; str += (part.appender || appendText)(object, str, part.precision); } else { str += appendText(part, str); } } return str; } function indent(str, indentString, depth) { // String -> String -> String? -> String // Example: // string.indent("Hello", " ", 2) // => " Hello" if (!depth || depth <= 0) return str; var indent = "";while (depth > 0) { depth--;indent += indentString; } return lines(str).map(function (line) { return indent + line; }).join("\n"); } function minIndent(str, indentString) { // Find out what the minum indentation of the text in str is // Example: // minIndent(" Hello", " ") // => 2 if (!indentString) indentString = " "; var indentRe = new RegExp("^(" + indentString + ")*", "gm"); return min(str.match(indentRe).map(function (ea) { return Math.floor(ea.length / indentString.length); })); } function changeIndent(str, indentString, depth) { // Add or remove indent from lines in str to match depth // Example: // string.changeIndent(" Hello", " ", 1) // => " Hello" if (!indentString) indentString = " "; if (!depth) depth = 0; var existingIndent = minIndent(str, indentString); if (existingIndent === depth) return str; if (existingIndent < depth) return indent(str, indentString, depth - existingIndent); var prefixToRemove = indentString.repeat(existingIndent - depth); return lines(str).map(function (line) { return line.slice(prefixToRemove.length); }).join("\n"); } function quote(str) { // Example: // string.print("fo\"o") // => "\"fo\\\"o\"" return '"' + str.replace(/"/g, '\\"') + '"'; } function print(obj) { // Prints Arrays and escapes quotations. See `obj.inspect` for how to // completely print / inspect JavaScript data strcutures // Example: // string.print([[1,2,3], "string", {foo: 23}]) // // => [[1,2,3],"string",[object Object]] if (obj && Array.isArray(obj)) return '[' + obj.map(print) + ']'; if (typeof obj !== "string") return String(obj); var result = String(obj); result = result.replace(/\n/g, '\\n\\\n'); result = result.replace(/(")/g, '\\$1'); result = '\"' + result + '\"'; return result; } function printNested(list, depth) { // Example: // string.printNested([1,2,[3,4,5]]) // => "1\n2\n 3\n 4\n 5\n" depth = depth || 0; return list.reduce(function (s, ea) { return s += Array.isArray(ea) ? printNested(ea, depth + 1) : indent(ea + "\n", ' ', depth); }, ""); } function pad(string, n, left) { // Examples: // pad("Foo", 2) // => "Foo " // pad("Foo", 2, true) // => " Foo" return left ? ' '.repeat(n) + string : string + ' '.repeat(n); } function printTable(tableArray, options) { // Array -> Object? -> String // Takes a 2D Array and prints a table string. Kind of the reverse // operation to `tableize` // Example: // string.printTable([["aaa", "b", "c"], ["d", "e","f"]]) // // => // // aaa b c // // d e f var columnWidths = [], separator = options && options.separator || ' ', alignLeftAll = !options || !options.align || options.align === 'left', alignRightAll = options && options.align === 'right'; function alignRight(columnIndex) { if (alignLeftAll) return false; if (alignRightAll) return true; return options && Array.isArray(options.align) && options.align[columnIndex] === 'right'; } tableArray.forEach(function (row) { row.forEach(function (cellVal, i) { if (columnWidths[i] === undefined) columnWidths[i] = 0; columnWidths[i] = Math.max(columnWidths[i], String(cellVal).length); }); }); return tableArray.map(function (row) { return row.map(function (cellVal, i) { var cellString = String(cellVal); return pad(cellString, columnWidths[i] - cellString.length, alignRight(i)); }).join(separator); }).join('\n'); } function printTree(rootNode, nodePrinter, childGetter, indent) { // Object -> Function -> Function -> Number? -> String // A generic function to print a tree representation from a nested data structure. // Receives three arguments: // - `rootNode` an object representing the root node of the tree // - `nodePrinter` is a function that gets a tree node and should return stringified version of it // - `childGetter` is a function that gets a tree node and should return a list of child nodes // Example: // var root = {name: "a", subs: [{name: "b", subs: [{name: "c"}]}, {name: "d"}]}; // string.printTree(root, function(n) { return n.name; }, function(n) { return n.subs; }); // // => // // a // // |-b // // | \-c // // \-d var nodeList = []; indent = indent || ' '; iterator(0, 0, rootNode); return nodeList.join('\n'); // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- function iterator(depth, index, node) { // ignore-in-doc // 1. Create stringified representation of node nodeList[index] = indent.repeat(depth) + nodePrinter(node, depth); var children = childGetter(node, depth), childIndex = index + 1; if (!children || !children.length) return childIndex; // 2. If there are children then assemble those linear inside nodeList // The childIndex is the pointer of the current items of childList into // nodeList. var lastIndex = childIndex, lastI = children.length - 1; children.forEach(function (ea, i) { childIndex = iterator(depth + 1, childIndex, ea); // 3. When we have printed the recursive version then augment the // printed version of the direct children with horizontal slashes // directly in front of the represented representation var isLast = lastI === i, cs = nodeList[lastIndex].split(''), fromSlash = depth * indent.length + 1, toSlash = depth * indent.length + indent.length; for (var i = fromSlash; i < toSlash; i++) { cs[i] = '-'; }if (isLast) cs[depth * indent.length] = '\\'; nodeList[lastIndex] = cs.join(''); // 4. For all children (direct and indirect) except for the // last one (itself and all its children) add vertical bars in // front of each at position of the current nodes depth. This // makes is much easier to see which child node belongs to which // parent if (!isLast) nodeList.slice(lastIndex, childIndex).forEach(function (ea, i) { var cs2 = ea.split(''); cs2[depth * indent.length] = '|'; nodeList[lastIndex + i] = cs2.join(''); }); lastIndex = childIndex; }); return childIndex; } } function toArray$1(s) { // Example: // string.toArray("fooo") // => ["f","o","o","o"] return s.split(''); } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- // parsing strings into other entities // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- function lines(str) { // Example: string.lines("foo\nbar\n\rbaz") // => ["foo","bar","baz"] return str.split(/\n\r?/); } function paragraphs(string, options) { // Examples: // var text = "Hello, this is a pretty long sentence\nthat even includes new lines." // + "\n\n\nThis is a sentence in a new paragraph."; // string.paragraphs(text) // => [ // // "Hello, this is a pretty long sentence\nthat even includes new lines.", // // "This is a sentence in a new paragraph."] // string.paragraphs(text, {keepEmptyLines: true}) // => [ // // "Hello, this is a pretty long sentence\n that even includes new lines.", // // "\n ", // // "This is a sentence in a new paragraph."] var sep = options ? options.sep : '\n\n'; if (!options || !options.keepEmptyLines) return string.split(new RegExp(sep + '+')); function isWhiteSpace(s) { return (/^\s*$/.test(s) ); } return string.split('\n').concat('').reduce(function (parasAndLast, line) { var paras = parasAndLast[0], last$$1 = parasAndLast[1]; if (isWhiteSpace(last$$1) === isWhiteSpace(line)) { last$$1 += '\n' + line; } else { last$$1.length && paras.push(last$$1);last$$1 = line; } return [paras, last$$1]; }, [[], ''])[0]; } function nonEmptyLines(str) { // Example: string.nonEmptyLines("foo\n\nbar\n") // => ["foo","bar"] return lines(str).compact(); } function tokens(str, regex) { // Example: // string.tokens(' a b c') => ['a', 'b', 'c'] return str.split(regex || /\s+/).filter(function (tok) { return !/^\s*$/.test(tok); }); } function tableize(s, options) { // String -> Object? -> Array // Takes a String representing a "table" and parses it into a 2D-Array (as // accepted by the `collection.Grid` methods or `string.printTable`) // ```js // options = { // convertTypes: BOOLEAN, // automatically convert to Numbers, Dates, ...? // cellSplitter: REGEXP // how to recognize "cells", by default just spaces // } // ``` // Examples: // string.tableize('a b c\nd e f') // // => [["a","b","c"],["d","e","f"]] // // can also parse csv like // var csv = '"Symbol","Name","LastSale",\n' // + '"FLWS","1-800 FLOWERS.COM, Inc.","5.65",\n' // + '"FCTY","1st Century Bancshares, Inc","5.65",' // string.tableize(csv, {cellSplitter: /^\s*"|","|",?\s*$/g}) // // => [["Symbol","Name","LastSale"], // // ["FLWS","1-800 FLOWERS.COM, Inc.",5.65], // // ["FCTY","1st Century Bancshares, Inc",5.65]] options = options || {}; var splitter = options.cellSplitter || /\s+/, emptyStringRe = /^\s*$/, convertTypes = options.hasOwnProperty('convertTypes') ? !!options.convertTypes : true, _lines = lines(s), table = []; for (var i = 0; i < _lines.length; i++) { var _tokens = tokens(_lines[i], splitter); if (convertTypes) { _tokens = _tokens.map(function (tok) { if (tok.match(emptyStringRe)) return tok; var num = Number(tok); if (!isNaN(num)) return num; var date = new Date(tok); if (!isNaN(+date)) return date; return tok.trim(); }); } if (_tokens.length > 0) table.push(_tokens); } return table; } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- // (un)escape / encoding / decoding // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- function unescapeCharacterEntities(s) { // Converts [character entities](http://dev.w3.org/html5/html-author/charref) // into utf-8 strings // Example: // string.unescapeCharacterEntities("foo && bar") // => "foo && bar" if (typeof document === 'undefined') throw new Error("Cannot unescapeCharacterEntities"); var div = document.createElement('div'); div.innerHTML = s; return div.textContent; } function toQueryParams(s, separator) { // Example: // string.toQueryParams("http://example.com?foo=23&bar=test") // // => {bar: "test", foo: "23"} var match = s.trim().match(/([^?#]*)(#.*)?$/); if (!match) return {}; var hash = match[1].split(separator || '&').inject({}, function (hash, pair) { if ((pair = pair.split('='))[0]) { var key = decodeURIComponent(pair.shift()); var value = pair.length > 1 ? pair.join('=') : pair[0]; if (value != undefined) value = decodeURIComponent(value); if (key in hash) { if (!Array.isArray(hash[key])) hash[key] = [hash[key]]; hash[key].push(value); } else hash[key] = value; } return hash; }); return hash; } // -=-=-=-=-=-=-=-=-=-=-=-=- // file system path support // -=-=-=-=-=-=-=-=-=-=-=-=- var pathDotRe = /\/\.\//g; var pathDoubleDotRe = /\/[^\/]+\/\.\./; var pathDoubleSlashRe = /(^|[^:])[\/]+/g; var urlStartRe = /^[a-z0-9-_\.]+:\/\//; function normalizePath$1(pathString) { var urlStartMatch = pathString.match(urlStartRe), urlStart = urlStartMatch ? urlStartMatch[0] : null, result = urlStart ? pathString.slice(urlStart.length) : pathString; // /foo/../bar --> /bar do { pathString = result; result = pathString.replace(pathDoubleDotRe, ''); } while (result != pathString); // foo//bar --> foo/bar result = result.replace(pathDoubleSlashRe, '$1/'); // foo/./bar --> foo/bar result = result.replace(pathDotRe, '/'); if (urlStart) result = urlStart + result; return result; } function joinPath() /*paths*/{ // Joins the strings passed as paramters together so that ea string is // connected via a single "/". // Example: // string.joinPath("foo", "bar") // => "foo/bar"; return normalizePath$1(Array.prototype.slice.call(arguments).reduce(function (path, ea) { return typeof ea === "string" ? path.replace(/\/*$/, "") + "/" + ea.replace(/^\/*/, "") : path; })); } // -=-=-=-=-=-=-=-=- // ids and hashing // -=-=-=-=-=-=-=-=- var newUUIDTemplate = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'; var newUUIDRe = /[xy]/g; var newUUIDReplacer = function newUUIDReplacer(c) { var r = Math.random() * 16 | 0, v = c == 'x' ? r : r & 0x3 | 0x8; return v.toString(16); }; function newUUID() { // Example: // newUUID() // => "3B3E74D0-85EA-45F2-901C-23ECF3EAB9FB" return newUUIDTemplate.replace(newUUIDRe, newUUIDReplacer).toUpperCase(); } function createDataURI(content, mimeType) { // String -> String -> String // Takes some string representing content and a mime type. // For a list of mime types see: [http://www.iana.org/assignments/media-types/media-types.xhtml]() // More about data URIs: [https://developer.mozilla.org/en-US/docs/Web/HTTP/data_URIs]() // Example: // window.open(string.createDataURI('

test

', 'text/html')); mimeType = mimeType || "text/plain"; return "data:" + mimeType + ";base64," + btoa(content); } function hashCode(s) { // [http://werxltd.com/wp/2010/05/13/javascript-implementation-of-javas-string-hashcode-method/]() // Example: string.hashCode("foo") // => 101574 var hash = 0, len = s.length; if (len == 0) return hash; for (var i = 0; i < len; i++) { var c = s.charCodeAt(i); hash = (hash << 5) - hash + c; hash = hash & hash; // Convert to 32bit integer } return hash; } function md5(string) { // © Joseph Myers [http://www.myersdaily.org/joseph/javascript/md5-text.html]() // Example: // string.md5("foo") // => "acbd18db4cc2f85cedef654fccc4a4d8" /* ignore-in-doc this function is much faster, so if possible we use it. Some IEs are the only ones I know of that need the idiotic second function, generated by an if clause. */ // var add32 = hex(md51("hello")) === "5d41402abc4b2a76b9719d911017c592" ? // function add32(a, b) { return (a + b) & 0xFFFFFFFF; } : var add32 = function add32(x, y) { var lsw = (x & 0xFFFF) + (y & 0xFFFF), msw = (x >> 16) + (y >> 16) + (lsw >> 16); return msw << 16 | lsw & 0xFFFF; }; function cmn(q, a, b, x, s, t) { a = add32(add32(a, q), add32(x, t)); return add32(a << s | a >>> 32 - s, b); } function ff(a, b, c, d, x, s, t) { return cmn(b & c | ~b & d, a, b, x, s, t); } function gg(a, b, c, d, x, s, t) { return cmn(b & d | c & ~d, a, b, x, s, t); } function hh(a, b, c, d, x, s, t) { return cmn(b ^ c ^ d, a, b, x, s, t); } function ii(a, b, c, d, x, s, t) { return cmn(c ^ (b | ~d), a, b, x, s, t); } function md5cycle(x, k) { var a = x[0], b = x[1], c = x[2], d = x[3]; a = ff(a, b, c, d, k[0], 7, -680876936); d = ff(d, a, b, c, k[1], 12, -389564586); c = ff(c, d, a, b, k[2], 17, 606105819); b = ff(b, c, d, a, k[3], 22, -1044525330); a = ff(a, b, c, d, k[4], 7, -176418897); d = ff(d, a, b, c, k[5], 12, 1200080426); c = ff(c, d, a, b, k[6], 17, -1473231341); b = ff(b, c, d, a, k[7], 22, -45705983); a = ff(a, b, c, d, k[8], 7, 1770035416); d = ff(d, a, b, c, k[9], 12, -1958414417); c = ff(c, d, a, b, k[10], 17, -42063); b = ff(b, c, d, a, k[11], 22, -1990404162); a = ff(a, b, c, d, k[12], 7, 1804603682); d = ff(d, a, b, c, k[13], 12, -40341101); c = ff(c, d, a, b, k[14], 17, -1502002290); b = ff(b, c, d, a, k[15], 22, 1236535329); a = gg(a, b, c, d, k[1], 5, -165796510); d = gg(d, a, b, c, k[6], 9, -1069501632); c = gg(c, d, a, b, k[11], 14, 643717713); b = gg(b, c, d, a, k[0], 20, -373897302); a = gg(a, b, c, d, k[5], 5, -701558691); d = gg(d, a, b, c, k[10], 9, 38016083); c = gg(c, d, a, b, k[15], 14, -660478335); b = gg(b, c, d, a, k[4], 20, -405537848); a = gg(a, b, c, d, k[9], 5, 568446438); d = gg(d, a, b, c, k[14], 9, -1019803690); c = gg(c, d, a, b, k[3], 14, -187363961); b = gg(b, c, d, a, k[8], 20, 1163531501); a = gg(a, b, c, d, k[13], 5, -1444681467); d = gg(d, a, b, c, k[2], 9, -51403784); c = gg(c, d, a, b, k[7], 14, 1735328473); b = gg(b, c, d, a, k[12], 20, -1926607734); a = hh(a, b, c, d, k[5], 4, -378558); d = hh(d, a, b, c, k[8], 11, -2022574463); c = hh(c, d, a, b, k[11], 16, 1839030562); b = hh(b, c, d, a, k[14], 23, -35309556); a = hh(a, b, c, d, k[1], 4, -1530992060); d = hh(d, a, b, c, k[4], 11, 1272893353); c = hh(c, d, a, b, k[7], 16, -155497632); b = hh(b, c, d, a, k[10], 23, -1094730640); a = hh(a, b, c, d, k[13], 4, 681279174); d = hh(d, a, b, c, k[0], 11, -358537222); c = hh(c, d, a, b, k[3], 16, -722521979); b = hh(b, c, d, a, k[6], 23, 76029189); a = hh(a, b, c, d, k[9], 4, -640364487); d = hh(d, a, b, c, k[12], 11, -421815835); c = hh(c, d, a, b, k[15], 16, 530742520); b = hh(b, c, d, a, k[2], 23, -995338651); a = ii(a, b, c, d, k[0], 6, -198630844); d = ii(d, a, b, c, k[7], 10, 1126891415); c = ii(c, d, a, b, k[14], 15, -1416354905); b = ii(b, c, d, a, k[5], 21, -57434055); a = ii(a, b, c, d, k[12], 6, 1700485571); d = ii(d, a, b, c, k[3], 10, -1894986606); c = ii(c, d, a, b, k[10], 15, -1051523); b = ii(b, c, d, a, k[1], 21, -2054922799); a = ii(a, b, c, d, k[8], 6, 1873313359); d = ii(d, a, b, c, k[15], 10, -30611744); c = ii(c, d, a, b, k[6], 15, -1560198380); b = ii(b, c, d, a, k[13], 21, 1309151649); a = ii(a, b, c, d, k[4], 6, -145523070); d = ii(d, a, b, c, k[11], 10, -1120210379); c = ii(c, d, a, b, k[2], 15, 718787259); b = ii(b, c, d, a, k[9], 21, -343485551); x[0] = add32(a, x[0]); x[1] = add32(b, x[1]); x[2] = add32(c, x[2]); x[3] = add32(d, x[3]); } function md51(s) { var n = s.length, state = [1732584193, -271733879, -1732584194, 271733878], i; for (i = 64; i <= n; i += 64) { md5cycle(state, md5blk(s.substring(i - 64, i))); } s = s.substring(i - 64); var tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], sl = s.length; for (i = 0; i < sl; i++) { tail[i >> 2] |= s.charCodeAt(i) << (i % 4 << 3); }tail[i >> 2] |= 0x80 << (i % 4 << 3); if (i > 55) { md5cycle(state, tail); i = 16; while (i--) { tail[i] = 0; } // for (i=0; i<16; i++) tail[i] = 0; } tail[14] = n * 8; md5cycle(state, tail); return state; } /* ignore-in-doc * there needs to be support for Unicode here, * unless we pretend that we can redefine the MD-5 * algorithm for multi-byte characters (perhaps * by adding every four 16-bit characters and * shortening the sum to 32 bits). Otherwise * I suggest performing MD-5 as if every character * was two bytes--e.g., 0040 0025 = @%--but then * how will an ordinary MD-5 sum be matched? * There is no way to standardize text to something * like UTF-8 before transformation; speed cost is * utterly prohibitive. The JavaScript standard * itself needs to look at this: it should start * providing access to strings as preformed UTF-8 * 8-bit unsigned value arrays. */ function md5blk(s) { // ignore-in-doc /* I figured global was faster. */ var md5blks = [], i; /* Andy King said do it this way. */ for (i = 0; i < 64; i += 4) { md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24); } return md5blks; } var hex_chr = '0123456789abcdef'.split(''); function rhex(n) { var s = '', j = 0; for (; j < 4; j++) { s += hex_chr[n >> j * 8 + 4 & 0x0F] + hex_chr[n >> j * 8 & 0x0F]; }return s; } function hex(x) { var l = x.length; for (var i = 0; i < l; i++) { x[i] = rhex(x[i]); }return x.join(''); } return hex(md51(string)); } // -=-=-=-=-=-=-=-=-=-=-=-=-=- // matching strings / regexps // -=-=-=-=-=-=-=-=-=-=-=-=-=- function reMatches$$1(string, re) { // Different to the native `match` function this method returns an object // with `start`, `end`, and `match` fields // Example: // string.reMatches("Hello World", /o/g) // // => [{start: 4, end: 5, match: "o"},{start: 7, end: 8, match: "o"}] var matches = []; string.replace(re, function (match, idx) { matches.push({ match: match, start: idx, end: idx + match.length }); }); return matches; } function stringMatch(s, patternString, options) { // returns `{matched: true}` if success otherwise // `{matched: false, error: EXPLANATION, pattern: STRING|RE, pos: NUMBER}` // Example: // string.stringMatch("foo 123 bar", "foo __/[0-9]+/__ bar") // => {matched: true} // string.stringMatch("foo aaa bar", "foo __/[0-9]+/__ bar") // // => { // // error: "foo <--UNMATCHED-->aaa bar", // // matched: false, // // pattern: /[0-9]+/, // // pos: 4 // // } options = options || {}; if (!!options.normalizeWhiteSpace) s = s.replace(/\s+/g, ' '); if (!!options.ignoreIndent) { s = s.replace(/^\s+/gm, ''); patternString = patternString.replace(/^\s+/gm, ''); } return s == patternString ? { matched: true } : embeddedReMatch(s, patternString); // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- function splitInThree(string, start, end, startGap, endGap) { // ignore-in-doc // split string at start and end // return (0, start), (start, end), (end, ...) startGap = startGap || 0;endGap = endGap || 0; return [string.slice(0, start), string.slice(start + startGap, end - endGap), string.slice(end)]; } function matchStringForward(s, pattern) { // ignore-in-doc // try to match pattern at beginning of string. if matched, return // result object with { // match: STRING, // REST: STRING -- remaining string after pattern was consumed // } if (pattern.constructor !== RegExp) { var idx = s.indexOf(pattern); if (idx === 0) return { match: pattern, rest: s.slice(pattern.length) }; // no match for (var i = 0; i < pattern.length; i++) { // figure out where we failed if (pattern[i] != s[i]) return { match: null, pos: i }; }return { match: null }; } var matches = reMatches$$1(s, pattern); // show(matches) // show(string.slice(matches[0].end)); return !matches || !matches.length || matches[0].start !== 0 ? { match: null } : { match: matches[0].match, rest: s.slice(matches[0].end) }; } function matchStringForwardWithAllPatterns(s, patterns) { // ignore-in-doc // like matchStringForward, just apply list of patterns var pos = 0; for (var i = 0; i < patterns.length; i++) { var p = patterns[i], result = matchStringForward(s, p); if (!result.match) return { matched: false, pos: pos + (result.pos || 0), pattern: p }; pos += result.match.length; s = result.rest; } return s.length ? { matched: false, pos: pos } : { matched: true }; } function splitIntoPatterns(matcher) { var starts = reMatches$$1(matcher, /__\//g), ends = reMatches$$1(matcher, /\/__/g); if (starts.length !== ends.length) { throw new Error("pattern invalid: " + matcher + " cannot be split into __/.../__ embedded RegExps" + "\nstarts: " + JSON.stringify(starts) + '\nvs ends:\n' + JSON.stringify(ends)); } var consumed = 0; return starts.reduce(function (patterns, start, i) { var end = ends[i]; var matcher = patterns.pop(); var splitted = splitInThree(matcher, start.start - consumed, end.end - consumed, 3, 3); if (splitted[0].length) { patterns.push(splitted[0]); consumed += splitted[0].length; } try { if (splitted[1].length) { patterns.push(new RegExp(splitted[1])); consumed += splitted[1].length + 3 + 3; } } catch (e) { throw new Error("Cannot create pattern re from: " + inspect(splitted)); } if (splitted[2].length) { patterns.push(splitted[2]); } return patterns; }, [matcher]); } function embeddedReMatch(s, patternString) { // ignore-in-doc // the main match func var patterns = splitIntoPatterns(patternString); var result = matchStringForwardWithAllPatterns(s, patterns); if (result.matched) return result; result.error = s.slice(0, result.pos) + '<--UNMATCHED-->' + s.slice(result.pos); return result; } } function peekRight(s, start, needle) { // Finds the next occurence of `needle` (String or RegExp). Returns delta // index. // Example: // peekRight("Hello World", 0, /o/g) // => 4 // peekRight("Hello World", 5, /o/) // => 2 s = s.slice(start); if (typeof needle === 'string') { var idx = s.indexOf(needle); return idx === -1 ? null : idx + start; } else if (needle.constructor === RegExp) { var matches = reMatches$$1(s, needle); return matches[0] ? matches[0].start : null; } return null; } function peekLeft(s, start, needle) { // Similar to `peekRight` s = s.slice(0, start); if (typeof needle === 'string') { var idx = s.lastIndexOf(needle); return idx === -1 ? null : idx; } else if (needle.constructor === RegExp) { var matches = reMatches$$1(s, needle); return last(matches) ? last(matches).start : null; } return null; } function lineIndexComputer(s) { // String -> Function // For converting character positions to line numbers. // Returns a function accepting char positions. If the char pos is outside // of the line ranges -1 is returned. // Example: // var idxComp = lineIndexComputer("Hello\nWorld\n\nfoo"); // idxComp(3) // => 0 (index 3 is "l") // idxComp(6) // => 1 (index 6 is "W") // idxComp(12) // => 2 (index 12 is "\n") // ignore-in-doc // line ranges: list of numbers, each line has two entries: // i -> start of line, i+1 -> end of line var _lineRanges = lineRanges(s); // ignore-in-doc // FIXME, this is O(n). Make cumputation more efficient, binary lookup? return function (pos) { for (var line = 0; line < _lineRanges.length; line++) { var lineRange = _lineRanges[line]; if (pos >= lineRange[0] && pos < lineRange[1]) return line; } return -1; }; } function lineNumberToIndexesComputer(s) { // String -> Function // For converting line numbers to [startIndex, endIndex] // Example: // var idxComp = lineNumberToIndexesComputer("Hello\nWorld\n\nfoo"); // idxComp(1) // => [6,12] return function (lineNo) { return lineRanges(s)[lineNo]; }; } function lineRanges(s) { var from$$1 = 0, to = 0, linesOfS = lines(s), result = []; for (var i = 0; i < linesOfS.length; i++) { var line = linesOfS[i]; to = from$$1 + line.length + 1; result.push([from$$1, to]); from$$1 = to; } return result; } function findLineWithIndexInLineRanges(lineRanges, idx) { // given a list of `lineRanges` (produced by // `livley.lang.string.lineRanges(string)`) like lineRanges = [[0, 12], [12, 33]] // and an string index `idx` into `string`, find the line no (the index into // `lineRanges`) that includes idx. The index intervals include start and exclude end: // Example: // findLineWithIndex2(lineRanges, 2); // => 0 // findLineWithIndex2(lineRanges, 12); // => 1 // findLineWithIndex2(lineRanges, 33); // => 1 // findLineWithIndex2(lineRanges, 34); // => -1 // findLineWithIndex2(lineRanges, -4); // => -1 var nRows = lineRanges.length; if (nRows === 0) return -1; // let currentRow = Math.floor(nRows/2), lastRow = nRows; var startRow = 0, endRow = nRows; while (true) { var middle = startRow + Math.floor((endRow - startRow) / 2), _lineRanges$middle = slicedToArray(lineRanges[middle], 2), from$$1 = _lineRanges$middle[0], to = _lineRanges$middle[1]; if (idx < from$$1) { if (middle === 0) return -1; endRow = middle; continue; } if (idx > to) { startRow = middle;continue; } return middle; } return -1; } function regexIndexOf(string, regex) { var startpos = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; var indexOf = this.substring(startpos || 0).search(regex); return indexOf >= 0 ? indexOf + (startpos || 0) : indexOf; } function regexLastIndexOf(string, regex) { var startpos = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : string.length; regex = regex.global ? regex : new RegExp(regex.source, "g" + (regex.ignoreCase ? "i" : "") + (regex.multiLine ? "m" : "")); var stringToWorkWith = this.substring(0, startpos + 1), lastIndexOf = -1, nextStop = 0, result; while ((result = regex.exec(stringToWorkWith)) != null) { lastIndexOf = result.index; regex.lastIndex = ++nextStop; } return lastIndexOf; } // -=-=-=-=- // diffing // -=-=-=-=- function diff(s1, s2) { if (typeof JsDiff === "undefined") return 'diff not supported'; return JsDiff.convertChangesToXML(JsDiff.diffWordsWithSpace(s1, s2)); } // -=-=-=-=- // testing // -=-=-=-=- function empty(s) { // show-in-doc return s == ''; } var includes$$1 = features.includes ? function (s, pattern) { return s.includes(pattern); } : function (s, pattern) { // Example: // include("fooo!", "oo") // => true return s.indexOf(pattern) > -1; }; var include$$1 = includes$$1; var startsWith = features.startsWith ? function (s, pattern) { return s.startsWith(pattern); } : function (s, pattern) { // Example: // startsWith("fooo!", "foo") // => true return s.indexOf(pattern) === 0; }; function startsWithVowel(s) { // show-in-doc var c = s[0]; return c === 'A' || c === 'E' || c === 'I' || c === 'O' || c === 'U' || c === 'a' || c === 'e' || c === 'i' || c === 'o' || c === 'u' || false; } var endsWith = features.endsWith ? function (s, pattern) { return s.endsWith(pattern); } : function (s, pattern) { // Example: // endsWith("fooo!", "o!") // => true var d = s.length - pattern.length; return d >= 0 && s.lastIndexOf(pattern) === d; }; // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- // string conversion and manipulation // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- function withDecimalPrecision(str, precision) { // String -> Number -> String // Example: withDecimalPrecision("1.12345678", 3) // => "1.123" var floatValue = parseFloat(str); return isNaN(floatValue) ? str : floatValue.toFixed(precision); } function capitalize(s) { // Example: // capitalize("foo bar") // => "Foo bar" return s.length ? s.charAt(0).toUpperCase() + s.slice(1) : s; } function camelCaseString(s) { // Spaces to camels, including first char // Example: camelCaseString("foo bar baz") // => "FooBarBaz" return s.split(" ").map(capitalize).join(""); } function camelize(s) { // Dashes to camels, excluding first char // Example: camelize("foo-bar-baz") // => "fooBarBaz" var parts = s.split('-'), len = parts.length; if (len == 1) return parts[0]; var camelized = s.charAt(0) == '-' ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1) : parts[0]; for (var i = 1; i < len; i++) { camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1); }return camelized; } function truncate(s, length, truncation) { // Enforces that s is not more then `length` characters long. // Example: // truncate("123456789", 5) // => "12..." length = length || 30; truncation = truncation === undefined ? '...' : truncation; return s.length > length ? s.slice(0, length - truncation.length) + truncation : String(s); } function truncateLeft(s, length, truncation) { // Enforces that s is not more then `length` characters long. // Example: // truncate("123456789", 5) // => "12..." length = length || 30; truncation = truncation === undefined ? '...' : truncation; return s.length > length ? truncation + s.slice(-length) : String(s); } function regExpEscape(s) { // For creating RegExps from strings and not worrying about proper escaping // of RegExp special characters to literally match those. // Example: // var re = new RegExp(regExpEscape("fooo{20}")); // re.test("fooo") // => false // re.test("fooo{20}") // => true return s.replace(/([-()\[\]{}+?*.$\^|,:# "b" // succ("Z") // => "[" return s.slice(0, s.length - 1) + String.fromCharCode(s.charCodeAt(s.length - 1) + 1); } function digitValue(s) { // ignore-in-doc return s.charCodeAt(0) - "0".charCodeAt(0); } var times = features.repeat ? function (s, count$$1) { return s.repeat(count$$1); } : function (s, count$$1) { // Example: // string.times("test", 3) // => "testtesttest" return count$$1 < 1 ? '' : new Array(count$$1 + 1).join(s); }; function longestCommonSubstring(a, b) { // Example: // longestCommonSubstring("bar foo barrr", "hello fooo world"); // => {indexA: 3, indexB: 5, length: 4, string: " foo"} var lcs = []; for (var i = 0; i < a.length; i++) { lcs[i] = []; for (var j = 0; j < b.length; j++) { lcs[i][j] = 0; } } // if B is null then LCS of A, B =0 for (var _i = 0; _i < a.length; _i++) { lcs[_i][0] = 0; } // fill the rest of the matrix for (var _i2 = 1; _i2 < a.length; _i2++) { for (var _j = 1; _j < b.length; _j++) { lcs[_i2][_j] = a[_i2 - 1] == b[_j - 1] ? lcs[_i2 - 1][_j - 1] + 1 : 0; } } var maxLength = -1, indexA = -1, indexB = -1; for (var _i3 = 0; _i3 < a.length; _i3++) { for (var _j2 = 0; _j2 < b.length; _j2++) { var length = lcs[_i3][_j2]; if (maxLength < length) { maxLength = length; indexA = _i3 - length; indexB = _j2 - length; } } } return { length: maxLength, indexA: indexA, indexB: indexB, string: maxLength > 0 ? a.slice(indexA, indexA + maxLength) : "" }; } function applyChange(string, change) { // change is of the form // `{start: Number, end: Number, lines: [String], action: "insert"|"remove"}` if (change.action === "insert") { return string.slice(0, change.start) + change.lines.join("\n") + string.slice(change.start); } else if (change.action === "remove") { return string.slice(0, change.start) + string.slice(change.end); } return string; } function applyChanges(s, changes) { return changes.reduce(function (result, change) { return applyChange(s, change); }, s); } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- // diffing / comparing function levenshtein(a, b) { // How many edit operations separate string a from b? // MIT licensed, https://gist.github.com/andrei- // Copyright (c) 2011 Andrei Mackenzie and https://github.com/kigiri if (a.length === 0) return b.length; if (b.length === 0) return a.length; var tmp, i, j, prev, val, row; // swap to save some memory O(min(a,b)) instead of O(a) if (a.length > b.length) { tmp = a;a = b;b = tmp; } row = Array(a.length + 1); // init the row for (i = 0; i <= a.length; i++) { row[i] = i; } // fill in the rest for (i = 1; i <= b.length; i++) { prev = i; for (j = 1; j <= a.length; j++) { if (b[i - 1] === a[j - 1]) { val = row[j - 1]; // match } else { val = Math.min(row[j - 1] + 1, // substitution Math.min(prev + 1, // insertion row[j] + 1)); // deletion } row[j - 1] = prev; prev = val; } row[a.length] = prev; } return row[a.length]; } var string = Object.freeze({ format: format, formatFromArray: formatFromArray, indent: indent, minIndent: minIndent, changeIndent: changeIndent, quote: quote, print: print, printNested: printNested, pad: pad, printTable: printTable, printTree: printTree, toArray: toArray$1, lines: lines, paragraphs: paragraphs, nonEmptyLines: nonEmptyLines, tokens: tokens, tableize: tableize, unescapeCharacterEntities: unescapeCharacterEntities, toQueryParams: toQueryParams, normalizePath: normalizePath$1, joinPath: joinPath, newUUID: newUUID, createDataURI: createDataURI, hashCode: hashCode, md5: md5, reMatches: reMatches$$1, stringMatch: stringMatch, peekRight: peekRight, peekLeft: peekLeft, lineIndexComputer: lineIndexComputer, lineNumberToIndexesComputer: lineNumberToIndexesComputer, findLineWithIndexInLineRanges: findLineWithIndexInLineRanges, regexIndexOf: regexIndexOf, regexLastIndexOf: regexLastIndexOf, lineRanges: lineRanges, diff: diff, empty: empty, includes: includes$$1, include: include$$1, startsWith: startsWith, startsWithVowel: startsWithVowel, endsWith: endsWith, withDecimalPrecision: withDecimalPrecision, capitalize: capitalize, camelCaseString: camelCaseString, camelize: camelize, truncate: truncate, truncateLeft: truncateLeft, regExpEscape: regExpEscape, succ: succ, digitValue: digitValue, times: times, longestCommonSubstring: longestCommonSubstring, applyChange: applyChange, applyChanges: applyChanges, levenshtein: levenshtein }); /* * Utility functions for JS Numbers. */ function random(min, max) { // random number between (and including) `min` and `max` min = min || 0; max = max || 100; return Math.round(Math.random() * (max - min) + min); } var normalRandom = function (mean, stdDev) { // returns randomized numbers in a normal distribution that can be // controlled ising the `mean` and `stdDev` parameters var spare, isSpareReady = false; return function (mean, stdDev) { if (isSpareReady) { isSpareReady = false; return spare * stdDev + mean; } else { var u, v, s; do { u = Math.random() * 2 - 1; v = Math.random() * 2 - 1; s = u * u + v * v; } while (s >= 1 || s == 0); var mul = Math.sqrt(-2.0 * Math.log(s) / s); spare = v * mul; isSpareReady = true; return mean + stdDev * u * mul; } }; }(); function randomSmallerInteger(n) { return Math.floor(Math.random() * n); } function humanReadableByteSize(n) { // interpret `n` as byte size and print a more readable version // Example: // num.humanReadableByteSize(Math.pow(2,32)) // => "4096MB" function round(n) { return Math.round(n * 100) / 100; } if (n < 1000) return String(round(n)) + 'B'; n = n / 1024; if (n < 1000) return String(round(n)) + 'KB'; n = n / 1024; return String(round(n)) + 'MB'; } function average(numbers) { // show-in-doc return numbers.reduce(function (sum, n) { return sum + n; }, 0) / numbers.length; } function averageInc(newVal, oldAvg, n) { // show-in-doc // Example: // let nums = range(0, 10).map(() => random(0, 10)) // nums.reduce((avg, ea, i) => avgInc(ea, avg, i+1), 0); return (newVal - oldAvg) / n + oldAvg; } function median(numbers) { // show-in-doc var sorted = numbers.sort(function (a, b) { return b - a; }), len = numbers.length; return len % 2 === 0 ? 0.5 * (sorted[len / 2 - 1] + sorted[len / 2]) : sorted[(len - 1) / 2]; } function between(x, a, b, eps) { // is `a` <= `x` <= `y`? eps = eps || 0; var min, max; if (a < b) { min = a, max = b; } else { max = a, min = b; } return max - x + eps >= 0 && min - x - eps <= 0; } function sort$1(arr) { // numerical sort, JavaScript native `sort` function is lexical by default. return arr.sort(function (a, b) { return a - b; }); } function parseLength(string, toUnit) { // This converts the length value to pixels or the specified `toUnit`. // length converstion, supported units are: mm, cm, in, px, pt, pc // Examples: // num.parseLength('3cm') // => 113.38582677165354 // num.parseLength('3cm', "in") // => 1.1811023622047243 toUnit = toUnit || 'px'; var match = string.match(/([0-9\.]+)\s*(.*)/); if (!match || !match[1]) return undefined; var length = parseFloat(match[1]), fromUnit = match[2]; return convertLength(length, fromUnit, toUnit); } var convertLength = function () { // ignore-in-doc // num.convertLength(20, 'px', 'pt').roundTo(0.01) function toCm(n, unit) { // as defined in http://www.w3.org/TR/css3-values/#absolute-lengths if (unit === 'cm') return n;else if (unit === 'mm') return n * 0.1;else if (unit === 'in') return n * 2.54;else if (unit === 'px') return n * toCm(1 / 96, 'in');else if (unit === 'pt') return n * toCm(1 / 72, 'in');else if (unit === 'pc') return n * toCm(12, 'pt'); } return function to(length, fromUnit, toUnit) { if (fromUnit === toUnit) return length;else if (toUnit === "cm") return toCm(length, fromUnit);else if (fromUnit === "cm") return length / toCm(1, toUnit);else return to(to(length, fromUnit, 'cm'), 'cm', toUnit); }; }(); function roundTo(n, quantum) { // `quantum` is something like 0.01, // for JS rounding to work we need the reciprocal quantum = 1 / quantum; return Math.round(n * quantum) / quantum; } function detent(n, detent, grid, snap) { // This function is useful to implement smooth transitions and snapping. // Map all values that are within detent/2 of any multiple of grid to // that multiple. Otherwise, if snap is true, return self, meaning that // the values in the dead zone will never be returned. If snap is // false, then expand the range between dead zone so that it covers the // range between multiples of the grid, and scale the value by that // factor. // Examples: // // With snapping: // num.detent(0.11, 0.2, 0.5, true) // => 0.11 // num.detent(0.39, 0.2, 0.5, true) // => 0.39 // num.detent(0.55, 0.2, 0.5, true) // => 0.5 // num.detent(0.61, 0.2, 0.5, true) // => 0.61 // // Smooth transitions without snapping: // num.detent(0.1, 0.2, 0.5) // => 0 // num.detent(0.11, 0.2, 0.5) // => 0.0166666 // num.detent(0.34, 0.2, 0.5) // => 0.4 // num.detent(0.39, 0.2, 0.5) // => 0.4833334 // num.detent(0.4, 0.2, 0.5) // => 0.5 // num.detent(0.6, 0.2, 0.5) // => 0.5 var r1 = roundTo(n, grid); // Nearest multiple of grid if (Math.abs(n - r1) < detent / 2) return r1; // Snap to that multiple... if (snap) return n; // ...and return n // or compute nearest end of dead zone var r2 = n < r1 ? r1 - detent / 2 : r1 + detent / 2; // and scale values between dead zones to fill range between multiples return r1 + (n - r2) * grid / (grid - detent); } function toDegrees(n) { // Example: // num.toDegrees(Math.PI/2) // => 90 return n * 180 / Math.PI % 360; } function toRadians(n) { // Example: // num.toRadians(180) // => 3.141592653589793 return n / 180 * Math.PI; } function backoff(attempt) /*ms*/{ var base = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 5; var cap = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 30000; // exponential backoff function // https://www.awsarchitectureblog.com/2015/03/backoff.html var temp = Math.min(cap, base * Math.pow(2, attempt)), sleep = temp / 2 + Math.round(Math.random() * (temp / 2)); return Math.min(cap, base + Math.random() * (sleep * 3 - base)); } function interpolate(i, a, b) { return a + i * (b - a); } var num = Object.freeze({ random: random, normalRandom: normalRandom, randomSmallerInteger: randomSmallerInteger, humanReadableByteSize: humanReadableByteSize, average: average, averageInc: averageInc, median: median, between: between, sort: sort$1, parseLength: parseLength, convertLength: convertLength, roundTo: roundTo, detent: detent, toDegrees: toDegrees, toRadians: toRadians, backoff: backoff, interpolate: interpolate }); function all$2(object, predicate) { // ignore-in-doc var a = []; for (var name in object) { if ((object.__lookupGetter__(name) || typeof object[name] !== 'function') && (predicate ? predicate(name, object) : true)) a.push(name); } return a; } function allOwnPropertiesOrFunctions(obj, predicate) { // ignore-in-doc return Object.getOwnPropertyNames(obj).reduce(function (result, name) { if (predicate ? predicate(obj, name) : true) result.push(name); return result; }, []); } function own$1(object) { // ignore-in-doc var a = []; for (var name in object) { if (object.hasOwnProperty(name) && (object.__lookupGetter__(name) || object[name] !== 'function')) a.push(name); } return a; } function forEachOwn(object, func, context) { // ignore-in-doc var result = []; for (var name in object) { if (!object.hasOwnProperty(name)) continue; var value = object[name]; if (value !== 'function') { result.push(func.call(context || this, name, value)); } } return result; } function nameFor(object, value) { // ignore-in-doc for (var name in object) { if (object[name] === value) return name; }return undefined; } function values$1(obj) { // ignore-in-doc var values = []; for (var name in obj) { values.push(obj[name]); }return values; } function ownValues(obj) { // ignore-in-doc var values = []; for (var name in obj) { if (obj.hasOwnProperty(name)) values.push(obj[name]); }return values; } function any$1(obj, predicate) { // ignore-in-doc for (var name in obj) { if (predicate(obj, name)) return true; }return false; } function allProperties(obj, predicate) { // ignore-in-doc var result = []; for (var name in obj) { if (predicate ? predicate(obj, name) : true) result.push(name); }return result; } function hash(obj) { // ignore-in-doc // Using the property names of `obj` to generate a hash value. return Object.keys(obj).sort().join('').hashCode(); } var properties = Object.freeze({ all: all$2, allOwnPropertiesOrFunctions: allOwnPropertiesOrFunctions, own: own$1, forEachOwn: forEachOwn, nameFor: nameFor, values: values$1, ownValues: ownValues, any: any$1, allProperties: allProperties, hash: hash }); /* * Util functions to print and work with JS date objects. */ var dateFormat = function setupDateFormat() { /* * Date Format 1.2.3 * (c) 2007-2009 Steven Levithan * MIT license * * Includes enhancements by Scott Trenda * and Kris Kowal * * Accepts a date, a mask, or a date and a mask. * Returns a formatted version of the given date. * The date defaults to the current date/time. * The mask defaults to dateFormat.masks.default. */ // http://blog.stevenlevithan.com/archives/date-time-format var dateFormat = function () { var token = /d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZ]|"[^"]*"|'[^']*'/g, timezone = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g, timezoneClip = /[^-+\dA-Z]/g, pad = function pad(val, len) { val = String(val); len = len || 2; while (val.length < len) { val = "0" + val; }return val; }; // Regexes and supporting functions are cached through closure return function (date, mask, utc) { var dF = dateFormat; // You can't provide utc if you skip other args (use the "UTC:" mask prefix) if (arguments.length == 1 && Object.prototype.toString.call(date) == "[object String]" && !/\d/.test(date)) { mask = date; date = undefined; } // Passing date through Date applies Date.parse, if necessary date = date ? new Date(date) : new Date(); if (isNaN(date)) throw SyntaxError("invalid date"); mask = String(dF.masks[mask] || mask || dF.masks["default"]); // Allow setting the utc argument via the mask if (mask.slice(0, 4) == "UTC:") { mask = mask.slice(4); utc = true; } var _ = utc ? "getUTC" : "get", d = date[_ + "Date"](), D = date[_ + "Day"](), m = date[_ + "Month"](), y = date[_ + "FullYear"](), H = date[_ + "Hours"](), M = date[_ + "Minutes"](), s = date[_ + "Seconds"](), L = date[_ + "Milliseconds"](), o = utc ? 0 : date.getTimezoneOffset(), flags = { d: d, dd: pad(d), ddd: dF.i18n.dayNames[D], dddd: dF.i18n.dayNames[D + 7], m: m + 1, mm: pad(m + 1), mmm: dF.i18n.monthNames[m], mmmm: dF.i18n.monthNames[m + 12], yy: String(y).slice(2), yyyy: y, h: H % 12 || 12, hh: pad(H % 12 || 12), H: H, HH: pad(H), M: M, MM: pad(M), s: s, ss: pad(s), l: pad(L, 3), L: pad(L > 99 ? Math.round(L / 10) : L), t: H < 12 ? "a" : "p", tt: H < 12 ? "am" : "pm", T: H < 12 ? "A" : "P", TT: H < 12 ? "AM" : "PM", Z: utc ? "UTC" : (String(date).match(timezone) || [""]).pop().replace(timezoneClip, ""), o: (o > 0 ? "-" : "+") + pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4), S: ["th", "st", "nd", "rd"][d % 10 > 3 ? 0 : (d % 100 - d % 10 != 10) * d % 10] }; return mask.replace(token, function ($0) { return $0 in flags ? flags[$0] : $0.slice(1, $0.length - 1); }); }; }(); // Some common format strings dateFormat.masks = { "default": "ddd mmm dd yyyy HH:MM:ss", shortDate: "m/d/yy", mediumDate: "mmm d, yyyy", longDate: "mmmm d, yyyy", fullDate: "dddd, mmmm d, yyyy", shortTime: "h:MM TT", mediumTime: "h:MM:ss TT", longTime: "h:MM:ss TT Z", isoDate: "yyyy-mm-dd", isoTime: "HH:MM:ss", isoDateTime: "yyyy-mm-dd'T'HH:MM:ss", isoUtcDateTime: "UTC:yyyy-mm-dd'T'HH:MM:ss'Z'" }; // Internationalization strings dateFormat.i18n = { dayNames: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], monthNames: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"] }; return dateFormat; }(); // end of setupDateFormat function format$1(date, mask, utc) { // Custom date / time stringifier. Provides default masks: // // Mask | Pattern // ---------------|-------------------------------- // default | `"ddd mmm dd yyyy HH:MM:ss"` // shortDate | `"m/d/yy"` // mediumDate | `"mmm d, yyyy"` // longDate | `"mmmm d, yyyy"` // fullDate | `"dddd, mmmm d, yyyy"` // shortTime | `"h:MM TT"` // mediumTime | `"h:MM:ss TT"` // longTime | `"h:MM:ss TT Z"` // isoDate | `"yyyy-mm-dd"` // isoTime | `"HH:MM:ss"` // isoDateTime | `"yyyy-mm-dd'T'HH:MM:ss"` // isoUtcDateTime | `"UTC:yyyy-mm-dd'T'HH:MM:ss'Z'"` // // and internationalized strings via `date.format.i18n.dayNames` // and `date.format.i18n.dayNames` // Examples: // date.format(new Date(), date.format.masks.longTime) // => "7:13:31 PM PDT" // date.format(new Date(), "yyyy/mm/dd") // => "2014/10/09" return dateFormat(date, mask, utc); } function equals$3(date, otherDate) { // show-in-doc return otherDate && otherDate instanceof Date && otherDate.getTime() === date.getTime(); } function relativeTo(date, otherDate) { // Prints a human readable difference of two Date objects. The older date // goes first. // Examples: // var now = new Date(); // date.relativeTo(new Date(now-2000), now) // => "2 secs" // date.relativeTo(new Date("10/11/2014"), new Date("10/12/2014")) // => "1 day" if (!(otherDate instanceof Date)) return ''; if (otherDate < date) return ''; if (otherDate === date) return 'now'; var minuteString = 'min', secondString = 'sec', hourString = 'hour', dayString = 'day', diff = otherDate - date, totalSecs = Math.round(diff / 1000), secs = totalSecs % 60, mins = Math.floor(totalSecs / 60) % 60, hours = Math.floor(totalSecs / 60 / 60) % 24, days = Math.floor(totalSecs / 60 / 60 / 24), parts = []; if (days > 0) { parts.push(days); if (days > 1) dayString += 's'; parts.push(dayString); } if (hours > 0 && days < 2) { parts.push(hours); if (hours > 1) hourString += 's'; parts.push(hourString); } if (mins > 0 && hours < 3 && days === 0) { parts.push(mins); if (mins > 1) minuteString += 's'; parts.push(minuteString); } if (secs > 0 && mins < 3 && hours === 0 && days === 0) { parts.push(secs); if (secs > 1) secondString += 's'; parts.push(secondString); } return parts.join(' '); } var date = Object.freeze({ format: format$1, equals: equals$3, relativeTo: relativeTo }); /*global require, process, Promise, System*/ /* * Methods helping with promises (Promise/A+ model). Not a promise shim. */ function promise(obj) { // Promise object / function converter // Example: // promise("foo"); // // => Promise({state: "fullfilled", value: "foo"}) // lively.lang.promise({then: (resolve, reject) => resolve(23)}) // // => Promise({state: "fullfilled", value: 23}) // lively.lang.promise(function(val, thenDo) { thenDo(null, val + 1) })(3) // // => Promise({state: "fullfilled", value: 4}) return typeof obj === "function" ? promise.convertCallbackFun(obj) : Promise.resolve(obj); } function delay$1(ms, resolveVal) { // Like `Promise.resolve(resolveVal)` but waits for `ms` milliseconds // before resolving return new Promise(function (resolve) { return setTimeout(resolve, ms, resolveVal); }); } function delayReject(ms, rejectVal) { // like `promise.delay` but rejects return new Promise(function (_, reject$$1) { return setTimeout(reject$$1, ms, rejectVal); }); } function timeout(ms, promise) { // Takes a promise and either resolves to the value of the original promise // when it succeeds before `ms` milliseconds passed or fails with a timeout // error return new Promise(function (resolve, reject$$1) { var done = false; setTimeout(function () { return !done && (done = true) && reject$$1(new Error('Promise timed out')); }, ms); promise.then(function (val) { return !done && (done = true) && resolve(val); }, function (err) { return !done && (done = true) && reject$$1(err); }); }); } function waitFor$1(ms, tester, timeoutObj) { // Tests for a condition calling function `tester` until the result is // truthy. Resolves with last return value of `tester`. If `ms` is defined // and `ms` milliseconds passed, reject with timeout error // if timeoutObj is passed will resolve(!) with this object instead of raise // an error if (typeof ms === "function") { tester = ms;ms = undefined; } return new Promise(function (resolve, reject$$1) { var stopped = false, timedout = false, timeoutValue = undefined, error = undefined, value = undefined, i = setInterval(function () { if (stopped) return clearInterval(i); try { value = tester(); } catch (e) { error = e; } if (!value && !error && !timedout) return; stopped = true; clearInterval(i); if (error) return reject$$1(error); if (timedout) return typeof timeoutObj === "undefined" ? reject$$1(new Error("timeout")) : resolve(timeoutObj); return resolve(value); }, 10); if (typeof ms === "number") setTimeout(function () { return timedout = true; }, ms); }); } function deferred() { // returns an object // `{resolve: FUNCTION, reject: FUNCTION, promise: PROMISE}` // that separates the resolve/reject handling from the promise itself // Similar to the deprecated `Promise.defer()` var resolve, reject$$1, promise = new Promise(function (_resolve, _reject) { resolve = _resolve;reject$$1 = _reject; }); return { resolve: resolve, reject: reject$$1, promise: promise }; } function convertCallbackFun(func) { // Takes a function that accepts a nodejs-style callback function as a last // parameter and converts it to a function *not* taking the callback but // producing a promise instead. The promise will be resolved with the // *first* non-error argument. // nodejs callback convention: a function that takes as first parameter an // error arg and second+ parameters are the result(s). // Example: // var fs = require("fs"), // readFile = promise.convertCallbackFun(fs.readFile); // readFile("./some-file.txt") // .then(content => console.log(String(content))) // .catch(err => console.error("Could not read file!", err)); return function promiseGenerator() /*args*/{ var args = Array.from(arguments), self = this; return new Promise(function (resolve, reject$$1) { args.push(function (err, result) { return err ? reject$$1(err) : resolve(result); }); func.apply(self, args); }); }; } function convertCallbackFunWithManyArgs(func) { // like convertCallbackFun but the promise will be resolved with the // all non-error arguments wrapped in an array. return function promiseGenerator() /*args*/{ var args = Array.from(arguments), self = this; return new Promise(function (resolve, reject$$1) { args.push(function () /*err + args*/{ var args = Array.from(arguments), err = args.shift(); return err ? reject$$1(err) : resolve(args); }); func.apply(self, args); }); }; } function _chainResolveNext(promiseFuncs, prevResult, akku, resolve, reject$$1) { var next = promiseFuncs.shift(); if (!next) resolve(prevResult);else { try { Promise.resolve(next(prevResult, akku)).then(function (result) { return _chainResolveNext(promiseFuncs, result, akku, resolve, reject$$1); }).catch(function (err) { reject$$1(err); }); } catch (err) { reject$$1(err); } } } function chain$1(promiseFuncs) { // Similar to Promise.all but takes a list of promise-producing functions // (instead of Promises directly) that are run sequentially. Each function // gets the result of the previous promise and a shared "state" object passed // in. The function should return either a value or a promise. The result of // the entire chain call is a promise itself that either resolves to the last // returned value or rejects with an error that appeared somewhere in the // promise chain. In case of an error the chain stops at that point. // Example: // lively.lang.promise.chain([ // () => Promise.resolve(23), // (prevVal, state) => { state.first = prevVal; return prevVal + 2 }, // (prevVal, state) => { state.second = prevVal; return state } // ]).then(result => console.log(result)); // // => prints {first: 23,second: 25} return new Promise(function (resolve, reject$$1) { return _chainResolveNext(promiseFuncs.slice(), undefined, {}, resolve, reject$$1); }); } function promise_finally(promise, finallyFn) { return Promise.resolve(promise).then(function (result) { try { finallyFn(); } catch (err) { console.error("Error in promise finally: " + err.stack || err); }return result; }).catch(function (err) { try { finallyFn(); } catch (err) { console.error("Error in promise finally: " + err.stack || err); }throw err; }); } function parallel(promiseGenFns) { var parallelLimit = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Infinity; // Starts functions from promiseGenFns that are expected to return a promise // Once `parallelLimit` promises are unresolved at the same time, stops // spawning further promises until a running promise resolves if (!promiseGenFns.length) return Promise.resolve([]); var results = [], error = null, index = 0, left = promiseGenFns.length, resolve = void 0, reject$$1 = void 0; return new Promise(function (res, rej) { resolve = function resolve() { return res(results); }; reject$$1 = function reject$$1(err) { return rej(error = err); }; spawnMore(); }); function spawn() { parallelLimit--; try { (function () { var i = index++, prom = promiseGenFns[i](); prom.then(function (result) { parallelLimit++; results[i] = result; if (--left === 0) resolve();else spawnMore(); }).catch(function (err) { return reject$$1(err); }); })(); } catch (err) { reject$$1(err); } } function spawnMore() { while (!error && left > 0 && index < promiseGenFns.length && parallelLimit > 0) { spawn(); } } } // FIXME! Object.assign(promise, { delay: delay$1, delayReject: delayReject, timeout: timeout, waitFor: waitFor$1, deferred: deferred, convertCallbackFun: convertCallbackFun, convertCallbackFunWithManyArgs: convertCallbackFunWithManyArgs, chain: chain$1, "finally": promise_finally, parallel: parallel }); // -=-=-=-=-=-=-=-=-=-=-=-=-=- // js object path accessor // -=-=-=-=-=-=-=-=-=-=-=-=-=- // show-in-doc // A `Path` is an objectified chain of property names (kind of a "complex" // getter and setter). Path objects can make access and writes into deeply nested // structures more convenient. `Path` provide "safe" get and set operations and // can be used for debugging by providing a hook that allows users to find out // when get/set operations happen. function Path(p, splitter) { if (p instanceof Path) return p; if (!(this instanceof Path)) return new Path(p, splitter); this.setSplitter(splitter || '.'); this.fromPath(p); } Object.assign(Path.prototype, { get isPathAccessor() { return true; }, fromPath: function fromPath(path) { // ignore-in-doc if (typeof path === "string" && path !== '' && path !== this.splitter) { this._parts = path.split(this.splitter); this._path = path; } else if (Array.isArray(path)) { this._parts = [].concat(path); this._path = path.join(this.splitter); } else { this._parts = []; this._path = ''; } return this; }, setSplitter: function setSplitter(splitter) { // ignore-in-doc if (splitter) this.splitter = splitter; return this; }, parts: function parts() { /*key names as array*/return this._parts; }, size: function size() { /*show-in-doc*/return this._parts.length; }, slice: function slice(n, m) { /*show-in-doc*/return Path(this.parts().slice(n, m)); }, normalizePath: function normalizePath() { // ignore-in-doc // FIXME: define normalization return this._path; }, isRoot: function isRoot(obj) { return this._parts.length === 0; }, isIn: function isIn(obj) { // Does the Path resolve to a value when applied to `obj`? if (this.isRoot()) return true; var parent = this.get(obj, -1); return parent && parent.hasOwnProperty(this._parts[this._parts.length - 1]); }, equals: function equals(obj) { // Example: // var p1 = Path("foo.1.bar.baz"), p2 = Path(["foo", 1, "bar", "baz"]); // // Path's can be both created via strings or pre-parsed with keys in a list. // p1.equals(p2) // => true return obj && obj.isPathAccessor && this.parts().equals(obj.parts()); }, isParentPathOf: function isParentPathOf(otherPath) { // Example: // var p1 = Path("foo.1.bar.baz"), p2 = Path("foo.1.bar"); // p2.isParentPathOf(p1) // => true // p1.isParentPathOf(p2) // => false otherPath = otherPath && otherPath.isPathAccessor ? otherPath : Path(otherPath); var parts = this.parts(), otherParts = otherPath.parts(); for (var i = 0; i < parts.length; i++) { if (parts[i] != otherParts[i]) return false; } return true; }, relativePathTo: function relativePathTo(otherPath) { // Example: // var p1 = Path("foo.1.bar.baz"), p2 = Path("foo.1"); // p2.relativePathTo(p1) // => Path(["bar","baz"]) // p1.relativePathTo(p2) // => undefined otherPath = Path(otherPath); return this.isParentPathOf(otherPath) ? otherPath.slice(this.size(), otherPath.size()) : undefined; }, del: function del(obj) { if (this.isRoot()) return false; var parent = obj; for (var i = 0; i < this._parts.length - 1; i++) { var part = this._parts[i]; if (parent.hasOwnProperty(part)) { parent = parent[part]; } else return false; } return delete parent[this._parts[this._parts.length - 1]]; }, withParentAndKeyDo: function withParentAndKeyDo(obj, ensure, doFunc) { // Deeply resolve path in `obj`, not fully, however, only to the parent // element of the last part of path. Take the parent, the key (the last // part of path) and pass it to `doFunc`. When `ensure` is true, create // objects along path it path does not resolve if (this.isRoot()) return doFunc(null, null); var parent = obj; for (var i = 0; i < this._parts.length - 1; i++) { var part = this._parts[i]; if (parent.hasOwnProperty(part) && (_typeof(parent[part]) === "object" || typeof parent[part] === "function")) { parent = parent[part]; } else if (ensure) { parent = parent[part] = {}; } else { return doFunc(null, part); } } return doFunc(parent, this._parts[this._parts.length - 1]); }, set: function set(obj, val, ensure) { // Deeply resolve path in `obj` and set the resulting property to `val`. If // `ensure` is true, create nested structure in between as necessary. // Example: // var o1 = {foo: {bar: {baz: 42}}}; // var path = Path("foo.bar.baz"); // path.set(o1, 43) // o1 // => {foo: {bar: {baz: 43}}} // var o2 = {foo: {}}; // path.set(o2, 43, true) // o2 // => {foo: {bar: {baz: 43}}} return this.withParentAndKeyDo(obj, ensure, function (parent, key) { return parent ? parent[key] = val : undefined; }); }, defineProperty: function defineProperty(obj, propertySpec, ensure) { // like `Path>>set`, however uses Objeect.defineProperty return this.withParentAndKeyDo(obj, ensure, function (parent, key) { return parent ? Object.defineProperty(parent, key, propertySpec) : undefined; }); }, get: function get(obj, n) { // show-in-doc var parts = n ? this._parts.slice(0, n) : this._parts; return parts.reduce(function (current, pathPart) { return current ? current[pathPart] : current; }, obj); }, concat: function concat(p, splitter) { // show-in-doc return Path(this.parts().concat(Path(p, splitter).parts())); }, toString: function toString() { return this.normalizePath(); }, serializeExpr: function serializeExpr() { // ignore-in-doc return 'lively.lang.Path(' + inspect(this.parts()) + ')'; }, watch: function watch(options) { // React or be notified on reads or writes to a path in a `target`. Options: // ```js // { // target: OBJECT, // uninstall: BOOLEAN, // onGet: FUNCTION, // onSet: FUNCTION, // haltWhenChanged: BOOLEAN, // verbose: BOOLEAN // } // ``` // Example: // // Quite useful for debugging to find out what call-sites change an object. // var o = {foo: {bar: 23}}; // Path("foo.bar").watch({target: o, verbose: true}); // o.foo.bar = 24; // => You should see: "[object Object].bar changed: 23 -> 24" if (!options || this.isRoot()) return; var target = options.target, parent = this.get(target, -1), propName = this.parts().slice(-1)[0], newPropName = 'propertyWatcher$' + propName, watcherIsInstalled = parent && parent.hasOwnProperty(newPropName), uninstall = options.uninstall, haltWhenChanged = options.haltWhenChanged, showStack = options.showStack, getter = parent.__lookupGetter__(propName), setter = parent.__lookupSetter__(propName); if (!target || !propName || !parent) return; if (uninstall) { if (!watcherIsInstalled) return; delete parent[propName]; parent[propName] = parent[newPropName]; delete parent[newPropName]; var msg = 'Watcher for ' + parent + '.' + propName + ' uninstalled'; show(msg); return; } if (watcherIsInstalled) { var msg = 'Watcher for ' + parent + '.' + propName + ' already installed'; show(msg); return; } if (getter || setter) { var msg = parent + '["' + propName + '"] is a getter/setter, watching not support'; console.log(msg); if (typeof show === "undefined") show(msg); return; } // observe slots, for debugging parent[newPropName] = parent[propName]; parent.__defineSetter__(propName, function (v) { var oldValue = parent[newPropName]; if (options.onSet) options.onSet(v, oldValue); var msg = parent + "." + propName + " changed: " + oldValue + " -> " + v; if (showStack) msg += '\n' + (typeof lively !== "undefined" ? lively.printStack() : console.trace()); if (options.verbose) { console.log(msg); if (typeof show !== 'undefined') show(msg); } if (haltWhenChanged) debugger; return parent[newPropName] = v; }); parent.__defineGetter__(propName, function () { if (options.onGet) options.onGet(parent[newPropName]); return parent[newPropName]; }); var msg = 'Watcher for ' + parent + '.' + propName + ' installed'; console.log(msg); if (typeof show !== 'undefined') show(msg); }, debugFunctionWrapper: function debugFunctionWrapper(options) { // ignore-in-doc // options = {target, [haltWhenChanged, showStack, verbose, uninstall]} var target = options.target, parent = this.get(target, -1), funcName = this.parts().slice(-1)[0], uninstall = options.uninstall, haltWhenChanged = options.haltWhenChanged === undefined ? true : options.haltWhenChanged, showStack = options.showStack, func = parent && funcName && parent[funcName], debuggerInstalled = func && func.isDebugFunctionWrapper; if (!target || !funcName || !func || !parent) return; if (uninstall) { if (!debuggerInstalled) return; parent[funcName] = parent[funcName].debugTargetFunction; var msg = 'Uninstalled debugFunctionWrapper for ' + parent + '.' + funcName; console.log(msg); if (typeof show !== 'undefined') show(msg); show(msg); return; } if (debuggerInstalled) { var msg = 'debugFunctionWrapper for ' + parent + '.' + funcName + ' already installed'; console.log(msg); if (typeof show !== 'undefined') show(msg); return; } var debugFunc = parent[funcName] = func.wrap(function (proceed) { var args = Array.from(arguments); if (haltWhenChanged) debugger; if (showStack) show(lively.printStack()); if (options.verbose) show(funcName + ' called'); return args.shift().apply(parent, args); }); debugFunc.isDebugFunctionWrapper = true; debugFunc.debugTargetFunction = func; var msg = 'debugFunctionWrapper for ' + parent + '.' + funcName + ' installed'; console.log(msg); if (typeof show !== 'undefined') show(msg); } }); /* Computation over graphs. Unless otherwise specified a graph is a simple JS object whose properties are interpreted as nodes that refer to arrays whose elements describe edges. Example: ```js var testGraph = { "a": ["b", "c"], "b": ["c", "d", "e", "f"], "d": ["c", "f"], "e": ["a", "f"], "f": [] } ``` */ // show-in-doc function clone$2(graph) { // return a copy of graph map var cloned = {}; for (var id in graph) { cloned[id] = graph[id].slice(); }return cloned; } function without$1(graph, ids) { // return a copy of graph map with ids removed var cloned = {}; for (var id in graph) { if (ids.includes(id)) continue; cloned[id] = []; var refs = graph[id]; for (var i = 0; i < refs.length; i++) { var ref = refs[i]; if (!ids.includes(ref)) cloned[id].push(ref); } } return cloned; } function hull(g, id) { var ignoredKeyList = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : []; var maxDepth = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : Infinity; // Takes a graph in object format and a start id and then traverses the // graph and gathers all nodes that can be reached from that start id. // Returns a list of those nodes. // Optionally use `ignore` list to filter out certain nodes that shouldn't // be considered and maxDepth to stop early. By default a maxDepth of 20 is // used. // Example: // var testGraph = { // "a": ["b", "c"], // "b": ["c", "d", "e", "f"], // "d": ["c", "f"], // "e": ["a", "f"], // "f": [] // } // hull(testGraph, "d") // => ["c", "f"] // hull(testGraph, "e") // => ['a', 'f', 'b', 'c', 'd', 'e'] // hull(testGraph, "e", ["b"]) // => ["a", "f", "c"] // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- // below is an optimized variant, the functional but slow version: // return uniq( // flatten( // values( // subgraphReachableBy( // graphMap, id, ignore, maxDepth)))); if (!Array.isArray(g[id])) return []; var hull = [], visited = {}; var ignoredKeys = {}; for (var i = 0; i < ignoredKeyList.length; i++) { ignoredKeys[ignoredKeyList[i]] = true; }var toVisitList = g[id].slice(), toVisitMapAndDistFromRoot = {}; for (var _i = toVisitList.length; _i--;) { var key = toVisitList[_i]; if (key in ignoredKeys) toVisitList.splice(_i, 1);else toVisitMapAndDistFromRoot[key] = 1; } if (ignoredKeyList) while (true) { if (toVisitList.length === 0) break; for (var _i2 = 0; _i2 < toVisitList.length; _i2++) { var _key = toVisitList.shift(); if (_key in visited || _key in ignoredKeys) continue; var dist = toVisitMapAndDistFromRoot[_key] || 0; if (dist > maxDepth) continue; hull.push(_key); visited[_key] = true; var refs = g[_key]; if (!refs) continue; for (var j = 0; j < refs.length; j++) { var refKey = refs[j]; if (refKey in visited || refKey in toVisitMapAndDistFromRoot) continue; toVisitMapAndDistFromRoot[refKey] = dist + 1; toVisitList.push(refKey); } } } return hull; } function subgraphReachableBy(graphMap, startId, ignore) { var maxDepth = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : Infinity; // show-in-doc // Like hull but returns subgraph map of `graphMap` // Example: // subgraphReachableBy(testGraph, "e", [], 2); // // => {e: [ 'a', 'f' ], a: [ 'b', 'c' ], f: []} if (ignore) graphMap = without$1(graphMap, ignore); var ids = [startId], step = 0, subgraph = {}; while (ids.length && step++ < maxDepth) { var id = ids.shift(); if (subgraph[id]) continue; var newIds = graphMap[id] || []; subgraph[id] = newIds; ids.push.apply(ids, toConsumableArray(newIds)); } return subgraph; } function invert(g) { // inverts the references of graph object `g`. // Example: // invert({a: ["b"], b: ["a", "c"]}) // // => {a: ["b"], b: ["a"], c: ["b"]} var inverted = {}; for (var key in g) { var refs = g[key]; for (var i = 0; i < refs.length; i++) { var key2 = refs[i]; if (!inverted[key2]) inverted[key2] = [key];else inverted[key2].push(key); } } return inverted; } function sortByReference(depGraph, startNode) { // Sorts graph into an array of arrays. Each "bucket" contains the graph // nodes that have no other incoming nodes than those already visited. This // means, we start with the leaf nodes and then walk our way up. // This is useful for computing how to traverse a dependency graph: You get // a sorted list of dependencies that also allows circular references. // Example: // var depGraph = {a: ["b", "c"], b: ["c"], c: ["b"]}; // sortByReference(depGraph, "a"); // // => [["c"], ["b"], ["a"]] // establish unique list of keys var remaining = [], remainingSeen = {}, uniqDepGraph = {}, inverseDepGraph = {}; for (var _key2 in depGraph) { if (!remainingSeen.hasOwnProperty(_key2)) { remainingSeen[_key2] = true; remaining.push(_key2); } var deps = depGraph[_key2], uniqDeps = {}; if (deps) { uniqDepGraph[_key2] = []; var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = deps[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var dep = _step.value; if (uniqDeps.hasOwnProperty(dep) || _key2 === dep) continue; var inverse = inverseDepGraph[dep] || (inverseDepGraph[dep] = []); if (!inverse.includes(_key2)) inverse.push(_key2); uniqDeps[dep] = true; uniqDepGraph[_key2].push(dep); if (!remainingSeen.hasOwnProperty(dep)) { remainingSeen[dep] = true; remaining.push(dep); } } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } } } // for each iteration find the keys with the minimum number of dependencies // and add them to the result group list var groups = []; while (remaining.length) { var minDepCount = Infinity, minKeys = [], minKeyIndexes = [], affectedKeys = []; for (var i = 0; i < remaining.length; i++) { var key = remaining[i]; var _deps = uniqDepGraph[key] || []; if (_deps.length > minDepCount) continue; // if (deps.length === minDepCount && !minKeys.some(ea => deps.includes(ea))) { if (_deps.length === minDepCount && !_deps.some(function (ea) { return minKeys.includes(ea); })) { var _affectedKeys; minKeys.push(key); minKeyIndexes.push(i); (_affectedKeys = affectedKeys).push.apply(_affectedKeys, toConsumableArray(inverseDepGraph[key] || [])); continue; } minDepCount = _deps.length; minKeys = [key]; minKeyIndexes = [i]; affectedKeys = (inverseDepGraph[key] || []).slice(); } for (var i = minKeyIndexes.length; i--;) { var key = remaining[minKeyIndexes[i]]; inverseDepGraph[key] = []; remaining.splice(minKeyIndexes[i], 1); } var _iteratorNormalCompletion2 = true; var _didIteratorError2 = false; var _iteratorError2 = undefined; try { for (var _iterator2 = affectedKeys[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { var key = _step2.value; uniqDepGraph[key] = uniqDepGraph[key].filter(function (ea) { return !minKeys.includes(ea); }); } } catch (err) { _didIteratorError2 = true; _iteratorError2 = err; } finally { try { if (!_iteratorNormalCompletion2 && _iterator2.return) { _iterator2.return(); } } finally { if (_didIteratorError2) { throw _iteratorError2; } } } groups.push(minKeys); } return groups; } function reduce$1(doFunc, graph, rootNode, carryOver, ignore, context) { // Starts with `rootNode` and visits all (in)directly related nodes, calling // `doFunc` at each node. The result of `doFunc` is passed as first // argument to the next iterator call. For the first call the value // `carryOver` is used. // Example: // var depGraph = {a: ["b", "c"],b: ["c"]} // graphReduce((_, ea, i) => console.log("%s %s", ea, i), depGraph, "a") var visitedNodes = ignore || [], index = 0; iterator(rootNode); return carryOver; function iterator(currentNode) { if (visitedNodes.indexOf(currentNode) > -1) return; carryOver = doFunc.call(context, carryOver, currentNode, index++); visitedNodes = visitedNodes.concat([currentNode]); var next = withoutAll(graph[currentNode] || [], visitedNodes); next.forEach(function (ea) { return iterator(ea); }); } } function random$1() { var nKeys = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 10; var g = {}, keys$$1 = range(1, nKeys).map(String); for (var i = 0; i < keys$$1.length; i++) { var r = Math.floor(Math.random() * nKeys); g[keys$$1[i]] = shuffle(keys$$1).slice(0, r); } return g; } var graph = Object.freeze({ clone: clone$2, without: without$1, hull: hull, subgraphReachableBy: subgraphReachableBy, invert: invert, sortByReference: sortByReference, reduce: reduce$1, random: random$1 }); /*global System, global*/ // show-in-doc // Intervals are arrays whose first two elements are numbers and the // first element should be less or equal the second element, see // [`interval.isInterval`](). This abstraction is useful when working with text // ranges in rich text, for example. var GLOBAL$2 = typeof System !== "undefined" ? System.global : typeof window !== 'undefined' ? window : global; function isInterval(object) { // Example: // interval.isInterval([1,12]) // => true // interval.isInterval([1,12, {property: 23}]) // => true // interval.isInterval([1]) // => false // interval.isInterval([12, 1]) // => false return Array.isArray(object) && object.length >= 2 && object[0] <= object[1]; } function sort$2(intervals) { // Sorts intervals according to rules defined in [`interval.compare`](). return intervals.sort(compare); } function compare(a, b) { // How [`interval.sort`]() compares. // We assume that `a[0] <= a[1] and b[0] <= b[1]` according to `isInterval` // ``` // -3: a < b and non-overlapping, e.g [1,2] and [3,4] // -2: a < b and intervals border at each other, e.g [1,3] and [3,4] // -1: a < b and overlapping, e.g, [1,3] and [2,4] or [1,3] and [1,4] // 0: a = b, e.g. [1,2] and [1,2] // 1: a > b and overlapping, e.g. [2,4] and [1,3] // 2: a > b and share border, e.g [1,4] and [0,1] // 3: a > b and non-overlapping, e.g [2,4] and [0,1] // ``` if (a[0] < b[0]) { // -3 || -2 || -1 if (a[1] < b[0]) return -3; if (a[1] === b[0]) return -2; return -1; } if (a[0] === b[0]) { // -1 || 0 || 1 if (a[1] === b[1]) return 0; return a[1] < b[1] ? -1 : 1; } // we know a[0] > b[0], 1 || 2 || 3 return -1 * compare(b, a); } function coalesce(interval1, interval2, optMergeCallback) { // Turns two interval into one iff compare(interval1, interval2) ∈ [-2, // -1,0,1, 2] (see [`inerval.compare`]()). // Otherwise returns null. Optionally uses merge function. // Examples: // interval.coalesce([1,4], [5,7]) // => null // interval.coalesce([1,2], [1,2]) // => [1,2] // interval.coalesce([1,4], [3,6]) // => [1,6] // interval.coalesce([3,6], [4,5]) // => [3,6] var cmpResult = this.compare(interval1, interval2); switch (cmpResult) { case -3: case 3: return null; case 0: optMergeCallback && optMergeCallback(interval1, interval2, interval1); return interval1; case 2: case 1: var temp = interval1;interval1 = interval2;interval2 = temp; // swap case -2: case -1: var coalesced = [interval1[0], Math.max(interval1[1], interval2[1])]; optMergeCallback && optMergeCallback(interval1, interval2, coalesced); return coalesced; default: throw new Error("Interval compare failed"); } } function coalesceOverlapping(intervals, mergeFunc) { // Like `coalesce` but accepts an array of intervals. // Example: // interval.coalesceOverlapping([[9,10], [1,8], [3, 7], [15, 20], [14, 21]]) // // => [[1,8],[9,10],[14,21]] var condensed = [], len = intervals.length; while (len > 0) { var ival = intervals.shift();len--; for (var i = 0; i < len; i++) { var otherInterval = intervals[i], coalesced = coalesce(ival, otherInterval, mergeFunc); if (coalesced) { ival = coalesced; intervals.splice(i, 1); len--;i--; } } condensed.push(ival); } return this.sort(condensed); } function mergeOverlapping(intervalsA, intervalsB, mergeFunc) { var result = []; while (intervalsA.length > 0) { var intervalA = intervalsA.shift(); var toMerge = intervalsB.map(function (intervalB) { var cmp = compare(intervalA, intervalB); return cmp === -1 || cmp === 0 || cmp === 1; }); result.push(mergeFunc(intervalA, toMerge[0])); result.push(intervalA); } return result; } function intervalsInRangeDo(start, end, intervals, iterator, mergeFunc, context) { // Merges and iterates through sorted intervals. Will "fill up" // intervals. This is currently used for computing text chunks in // lively.morphic.TextCore. // Example: // interval.intervalsInRangeDo( // 2, 10, [[0, 1], [5,8], [2,4]], // function(i, isNew) { i.push(isNew); return i; }) // // => [[2,4,false],[4,5,true],[5,8,false],[8,10,true]] context = context || GLOBAL$2; // need to be sorted for the algorithm below intervals = this.sort(intervals); var free = [], nextInterval, collected = []; // merged intervals are already sorted, simply "negate" the interval array; while (nextInterval = intervals.shift()) { if (nextInterval[1] < start) continue; if (nextInterval[0] < start) { nextInterval = Array.prototype.slice.call(nextInterval); nextInterval[0] = start; } var nextStart = end < nextInterval[0] ? end : nextInterval[0]; if (start < nextStart) { collected.push(iterator.call(context, [start, nextStart], true)); } if (end < nextInterval[1]) { nextInterval = Array.prototype.slice.call(nextInterval); nextInterval[1] = end; } // special case, the newly constructed interval has length 0, // happens when intervals contains doubles at the start if (nextInterval[0] === nextInterval[1]) { var prevInterval; if (mergeFunc && (prevInterval = collected.slice(-1)[0])) { // arguments: a, b, merged, like in the callback of #merge mergeFunc.call(context, prevInterval, nextInterval, prevInterval); } } else { collected.push(iterator.call(context, nextInterval, false)); } start = nextInterval[1]; if (start >= end) break; } if (start < end) collected.push(iterator.call(context, [start, end], true)); return collected; } function intervalsInbetween(start, end, intervals) { // Computes "free" intervals between the intervals given in range start - end // currently used for computing text chunks in lively.morphic.TextCore // Example: // interval.intervalsInbetween(0, 10,[[1,4], [5,8]]) // // => [[0,1],[4,5],[8,10]] return intervalsInRangeDo(start, end, coalesceOverlapping(Array.prototype.slice.call(intervals)), function (interval, isNew) { return isNew ? interval : null; }).filter(Boolean); } function mapToMatchingIndexes(intervals, intervalsToFind) { // Returns an array of indexes of the items in intervals that match // items in `intervalsToFind`. // Note: We expect intervals and intervals to be sorted according to [`interval.compare`]()! // This is the optimized version of: // ``` // return intervalsToFind.collect(function findOne(toFind) { // var startIdx, endIdx; // var start = intervals.detect(function(ea, i) { // startIdx = i; return ea[0] === toFind[0]; }); // if (start === undefined) return []; // var end = intervals.detect(function(ea, i) { // endIdx = i; return ea[1] === toFind[1]; }); // if (end === undefined) return []; // return Array.range(startIdx, endIdx); // }); // ``` var startIntervalIndex = 0, endIntervalIndex, currentInterval; return intervalsToFind.map(function (toFind) { while (currentInterval = intervals[startIntervalIndex]) { if (currentInterval[0] < toFind[0]) { startIntervalIndex++;continue; } break; } if (currentInterval && currentInterval[0] === toFind[0]) { endIntervalIndex = startIntervalIndex; while (currentInterval = intervals[endIntervalIndex]) { if (currentInterval[1] < toFind[1]) { endIntervalIndex++;continue; } break; } if (currentInterval && currentInterval[1] === toFind[1]) { return range(startIntervalIndex, endIntervalIndex); } } return []; }); } var interval = Object.freeze({ isInterval: isInterval, sort: sort$2, compare: compare, coalesce: coalesce, coalesceOverlapping: coalesceOverlapping, mergeOverlapping: mergeOverlapping, intervalsInRangeDo: intervalsInRangeDo, intervalsInbetween: intervalsInbetween, mapToMatchingIndexes: mapToMatchingIndexes }); // show-in-doc // Accessor to sub-ranges of arrays. This is used, for example, for rendering // large lists or tables in which only a part of the items should be used for // processing or rendering. An array projection provides convenient access and // can apply operations to sub-ranges. function create(array, length, optStartIndex) { // Example: // arrayProjection.create([1,2,3,4,5,6,7,8,9], 4, 1) // // => { array: [/*...*/], from: 1, to: 5 } var startIndex = optStartIndex || 0; if (startIndex + length > array.length) startIndex -= startIndex + length - array.length; return { array: array, from: startIndex, to: startIndex + length }; } function toArray$4(projection) { // show-in-doc return projection.array.slice(projection.from, projection.to); } function originalToProjectedIndex(projection, index) { // Maps index from original Array to projection. // Example: // var proj = arrayProjection.create([1,2,3,4,5,6,7,8,9], 4, 3); // arrayProjection.originalToProjectedIndex(proj, 1) // => null // arrayProjection.originalToProjectedIndex(proj, 3) // => 0 // arrayProjection.originalToProjectedIndex(proj, 5) // => 2 return index < projection.from || index >= projection.to ? null : index - projection.from; } function projectedToOriginalIndex(projection, index) { // Inverse to `originalToProjectedIndex`. // Example: // var proj = arrayProjection.create([1,2,3,4,5,6,7,8,9], 4, 3); // arrayProjection.projectedToOriginalIndex(proj, 1) // => 4 if (index < 0 || index > projection.to - projection.from) return null; return projection.from + index; } function transformToIncludeIndex(projection, index) { // Computes how the projection needs to shift minimally (think "scroll" // down or up) so that index becomes "visible" in projection. // Example: // var proj = arrayProjection.create([1,2,3,4,5,6,7,8,9], 4, 3); // arrayProjection.transformToIncludeIndex(proj, 1) // // => { array: [/*...*/], from: 1, to: 5 } if (!(index in projection.array)) return null; var delta = 0; if (index < projection.from) delta = -projection.from + index; if (index >= projection.to) delta = index - projection.to + 1; if (delta === 0) return projection; return create(projection.array, projection.to - projection.from, projection.from + delta); } var arrayProjection = Object.freeze({ create: create, toArray: toArray$4, originalToProjectedIndex: originalToProjectedIndex, projectedToOriginalIndex: projectedToOriginalIndex, transformToIncludeIndex: transformToIncludeIndex }); // show-in-doc // A grid is a two-dimaensional array, representing a table-like data function get$2(grid, nRow, nCol) { var row = grid[nRow]; return row ? row[nCol] : undefined; } function set$2(grid, nRow, nCol, obj) { var row = grid[nRow]; if (row) row[nCol] = obj; return obj; } function getRow(grid, nRow) { return grid[nRow]; } function setRow(grid, nRow, newRow) { return grid[nRow] = newRow; } function getCol(grid, nCol) { return grid.reduce(function (col, row) { col.push(row[nCol]);return col; }, []); } function setCol(grid, nCol, newCol) { return grid.map(function (row, i) { return row[nCol] ? row[nCol] = newCol[i] : undefined; }); } function create$1(rows, columns, initialObj) { // Example: // grid.create(3, 2, "empty") // // => [["empty","empty"], // // ["empty","empty"], // // ["empty","empty"]] var result = new Array(rows); while (rows > 0) { result[--rows] = withN(columns, initialObj); }return result; } function mapCreate(rows, cols, func, context) { // like `grid.create` but takes generator function for cells var result = new Array(rows); for (var i = 0; i < rows; i++) { result[i] = new Array(cols); for (var j = 0; j < cols; j++) { result[i][j] = func.call(context || this, i, j); } } return result; } function forEach$2(grid, func, context) { // iterate, `func` is called as `func(cellValue, i, j)` grid.forEach(function (row, i) { row.forEach(function (val, j) { func.call(context || this, val, i, j); }); }); } function map$2(grid, func, context) { // map, `func` is called as `func(cellValue, i, j)` var result = new Array(grid.length); grid.forEach(function (row, i) { result[i] = new Array(row.length); row.forEach(function (val, j) { result[i][j] = func.call(context || this, val, i, j); }); }); return result; } function toObjects(grid) { // The first row of the grid defines the propNames // for each following row create a new object with those porperties // mapped to the cells of the row as values // Example: // grid.toObjects([['a', 'b'],[1,2],[3,4]]) // // => [{a:1,b:2},{a:3,b:4}] var props = grid[0], objects = new Array(grid.length - 1); for (var i = 1; i < grid.length; i++) { var obj = objects[i - 1] = {}; for (var j = 0; j < props.length; j++) { obj[props[j]] = grid[i][j]; } } return objects; } function tableFromObjects(objects, valueForUndefined) { // Reverse operation to `grid.toObjects`. Useful for example to convert objectified // SQL result sets into tables that can be printed via Strings.printTable. // Objects are key/values like [{x:1,y:2},{x:3},{z:4}]. Keys are interpreted as // column names and objects as rows. // Example: // grid.tableFromObjects([{x:1,y:2},{x:3},{z:4}]) // // => [["x","y","z"], // // [1,2,null], // // [3,null,null], // // [null,null,4]] if (!Array.isArray(objects)) objects = [objects]; var table = [[]], columns = table[0], rows = objects.reduce(function (rows, ea) { return rows.concat([Object.keys(ea).reduce(function (row, col) { var colIdx = columns.indexOf(col); if (colIdx === -1) { colIdx = columns.length;columns.push(col); } row[colIdx] = ea[col]; return row; }, [])]); }, []); valueForUndefined = arguments.length === 1 ? null : valueForUndefined; rows.forEach(function (row) { // fill cells with no value with null for (var i = 0; i < columns.length; i++) { if (!row[i]) row[i] = valueForUndefined; } }); return table.concat(rows); } var grid = Object.freeze({ get: get$2, set: set$2, getRow: getRow, setRow: setRow, getCol: getCol, setCol: setCol, create: create$1, mapCreate: mapCreate, forEach: forEach$2, map: map$2, toObjects: toObjects, tableFromObjects: tableFromObjects }); /* * Methods for traversing and transforming tree structures. */ function prewalk(treeNode, iterator, childGetter) { var counter = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : { i: 0 }; var depth = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 0; var i = counter.i++; iterator(treeNode, i, depth); (childGetter(treeNode, i, depth) || []).forEach(function (ea) { return prewalk(ea, iterator, childGetter, counter, depth + 1); }); } function postwalk(treeNode, iterator, childGetter) { var counter = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : { i: 0 }; var depth = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 0; var i = counter.i++; (childGetter(treeNode, i, depth) || []).forEach(function (ea) { return postwalk(ea, iterator, childGetter, counter, depth); }); iterator(treeNode, i, depth); } function find(treeNode, testFunc, childGetter) { // Traverses a `treeNode` recursively and returns the first node for which // `testFunc` returns true. `childGetter` is a function to retrieve the // children from a node. if (testFunc(treeNode)) return treeNode; var children = childGetter(treeNode); if (!children || !children.length) return undefined; for (var i = 0; i < children.length; i++) { var found = find(children[i], testFunc, childGetter); if (found) return found; } return undefined; } var detect$1 = find; function filter$1(treeNode, testFunc, childGetter) { // Traverses a `treeNode` recursively and returns all nodes for which // `testFunc` returns true. `childGetter` is a function to retrieve the // children from a node. var result = []; if (testFunc(treeNode)) result.push(treeNode); return result.concat(flatten((childGetter(treeNode) || []).map(function (n) { return filter$1(n, testFunc, childGetter); }))); } function map$3(treeNode, mapFunc, childGetter) { var depth = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0; // Traverses a `treeNode` recursively and call `mapFunc` on each node. The // return values of all mapFunc calls is the result. `childGetter` is a // function to retrieve the children from a node. return [mapFunc(treeNode, depth)].concat(flatten((childGetter(treeNode) || []).map(function (n) { return map$3(n, mapFunc, childGetter, depth + 1); }))); } function mapTree(treeNode, mapFunc, childGetter) { var depth = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0; // Traverses the tree and creates a structurally identical tree but with // mapped nodes var mappedNodes = (childGetter(treeNode) || []).map(function (n) { return mapTree(n, mapFunc, childGetter, depth + 1); }); return mapFunc(treeNode, mappedNodes, depth); } var tree = Object.freeze({ prewalk: prewalk, postwalk: postwalk, find: find, detect: detect$1, filter: filter$1, map: map$3, mapTree: mapTree }); /*global process, require*/ /* * A simple node.js-like cross-platform event emitter implementation that can * be used as a mixin. Emitters support the methods: `on(eventName, handlerFunc)`, * `once(eventName, handlerFunc)`, `emit(eventName, eventData)`, * `removeListener(eventName, handlerFunc)`, `removeAllListeners(eventName)` * Example: * var emitter = events.makeEmitter({}); * var log = []; * emitter.on("test", function() { log.push("listener1"); }); * emitter.once("test", function() { log.push("listener2"); }); * emitter.emit("test"); * emitter.emit("test"); * log // => ["listener1","listener2","listener1"] * emitter.removeAllListeners("test"); * emitter.emit("test"); * log // => is still ["listener1","listener2","listener1"] */ var isNode$1 = typeof process !== 'undefined' && process.versions && process.versions.node; var makeEmitter = isNode$1 ? function (obj, options) { if (obj.on && obj.removeListener) return obj; var events = typeof System !== "undefined" ? System._nodeRequire("events") : require("events"); Object.assign(obj, events.EventEmitter.prototype); events.EventEmitter.call(obj); if (options && options.maxListenerLimit) obj.setMaxListeners(options.maxListenerLimit); return obj; } : function (obj) { if (obj.on && obj.removeListener) return obj; obj.listeners = {}; obj.on = function (type, handler) { if (!handler) return; if (!obj.listeners[type]) obj.listeners[type] = []; obj.listeners[type].push(handler); }; obj.once = function (type, handler) { if (!handler) return; function onceHandler /*ignore-in-docs args*/() { obj.removeListener(type, onceHandler); handler.apply(this, arguments); } obj.on(type, onceHandler); }; obj.removeListener = function (type, handler) { if (!obj.listeners[type]) return; obj.listeners[type] = obj.listeners[type].filter(function (h) { return h !== handler; }); }; obj.removeAllListeners = function (type) { if (!obj.listeners[type]) return; obj.listeners[type] = []; }; obj.emit = function () /*type and args*/{ var args = Array.prototype.slice.call(arguments), type = args.shift(), handlers = obj.listeners[type]; if (!handlers || !handlers.length) return; handlers.forEach(function (handler) { try { handler.apply(null, args); } catch (e) { console.error("Error in event handler: %s", e.stack || String(e)); } }); }; return obj; }; var events = Object.freeze({ makeEmitter: makeEmitter }); /*global clearTimeout, setTimeout, clearInterval, setInterval*/ /* * A pluggable interface to provide asynchronous, actor-like message * communication between JavaScript systems. Provides a unified message protocol * and send / receive methods. */ var OFFLINE = 'offline'; var ONLINE = 'online'; /* TODO: move to promises! include broadcast API renames: listen() => open() id() => id */ /* A messenger is an object that provides a common, message-based interface. Messengers expect you to provide an implementation of a small number of methods: `send`, `listen`, `close`, and `isOnline`. A messenger will then provide a unified interface for sending and receiving messages. Common boilerplate functionality such as queuing messages, error handling, dealing with instable connections, heartbeats, etc. is handled by the messenger object automatically (and can be parameterized). This allows to use a single interface across a range of heterogeneous objects without having to implement every detail of the abstraction repeatedly. This is especially valuable when dealing with asynchronous or remote communication (web workers, XHR requests, WebSockets, node.js processes, ...). To see a minimal example of how to use messengers for the local communication between JavaScript objects [see this example](#messenger-example). A more sophisticated example of messengers is [the worker implementation](worker.js) which provides an actor-like worker interface that uses web workers in web browsers and child_process.fork in node.js. ```js var msger = lively.lang.messenger.create({ send: function(msg, onSendDone) { console.log(msg); onSendDone(); }, listen: function(thenDo) { thenDo(); }, close: function(thenDo) { thenDo(); }, isOnline: function() { return true } }); ``` #### Messenger interface The interface methods are build to enable an user to send and receive messages. Each messenger provides the following methods: ##### msger.id() Each msger has an id that can either be defined by the user when the msger is created or is automatically assigned. The id should be unique for each messenger in a messenger network. It is used as the `target` attribute to address messages and internally in the messaging implementation for routing. See the [message protocol](#messenger-message-protocol) description for more info. ##### msger.isOnline() Can the msger send and receive messages right now? ##### msger.heartbeatEnabled() Does the msger send automated heartbeat messages? ##### msger.listen(optionalCallback) Brings the messenger "online": Starts listening for messages and brings it into a state to send messages. `optionalCallback` is a function that is called when listening begins. It should accept one argument `error` that is null if no error occured when listening was started, an Error object otherwise. ##### msger.send(msg, onReceiveFunc) Sends a message. The message should be structured according to the [message protocol](#messenger-message-protocol). `onReceiveFunc` is triggered when the `msg` is being answered. `onReceiveFunc` should take two arguments: `error` and `answer`. `answer` is itself a message object. ##### msger.sendTo(target, action, data, onReceiveFunc) A simpler `send`, the `msg` object is automatically assembled. `target` should be an id of the receiver and `action` a string naming the service that should be triggered on the receiver. ##### msger.answer(msg, data, expectMore, whenSend) Assembles an answer message for `msg` that includes `data`. `expectMore` should be truthy when multiple answers should be send (a streaming response, see the [messaging protocol](#messenger-message-protocol)). ##### msger.close(thenDo) Stops listening. ##### msger.whenOnline(thenDo) Registers a callback that is triggered as soon as a listen attempt succeeds (or when the messenger is listening already then it succeeds immediately). ##### msger.outgoingMessages() Returns the messages that are currently inflight or not yet send. ##### msger.addServices(serviceSpec) Add services to the messenger. `serviceSpec` should be JS object whose keys correspond to message actions: ```js msg.addServices({ helloWorld: function(msg, messenger) { messenger.answer(msg, "received a message!"); } }); ``` See the examples below for more information. ##### *[event]* msger.on("message") To allow users to receive messages that were not initiated by a send, messengers are [event emitters](events.js) that emit `"message"` events whenever they receive a new message. The messenger object is used to create new messenger interfaces and ties them to a specific implementation. Please see [worker.js]() for examples of how web workers and node.js processes are wrapped to provide a cross-platform interface to a worker abstraction. #### Message protocol A message is a JSON object with the following fields: ```js var messageSchema = { // REQUIRED selector for service lookup. By convention action gets // postfixed with "Result" for response messages action: STRING, // REQUIRED target of the message, the id of the receiver target: UUID, // OPTIONAL arguments data: OBJECT, // OPTIONAL identifier of the message, will be provided if not set by user messageId: UUID, // OPTIONAL sender of the message, will be provided if not set by user sender: UUID, // OPTIONAL identifier of a message that this message answers, will be provided inResponseTo: UUID, // OPTIONAL if message is an answer. Can be interpreted by the receiver as // a streaming response. Lively participants (tracker and clients) will // trigger data bindings and fire callbacks for a message for every streaming // response expectMoreResponses: BOOL, // EXPERIMENTAL UUIDs of trackers/sessions handlers that forwarded this // message route: ARRAY } ``` The `sendTo` and `answer` methods of messengers will automatically create these messages. If the user invokes the `send` method then a JS object according to the schema above should be passed as the first argument. #### Messenger examples The following code implements what is needed to use a messenger to communicate between any number of local JavaScript objects. Instead of dispatching methods using a local list of messengers you will most likely use an existing networking / messaging mechanism. See the [worker](#) and [its implementation](worker.js) for a real use case in which forking processes in the browser using Web Workers and in node.js using child_process.fork is unified. ```js // spec that defines message sending in terms of receivers in the messengers list var messengers = []; var messengerSpec = { send: function(msg, onSendDone) { var err = null, recv = arr.detect(messengers, function(ea) { return ea.id() === msg.target; }); if (recv) recv.onMessage(msg); else err = new Error("Could not find receiver " + msg.target); onSendDone(err); }, listen: function(thenDo) { arr.pushIfNotIncluded(messengers, this); }, close: function(thenDo) { arr.remove(messengers, this); }, isOnline: function() { return arr.include(messengers, this); } }; // Create the messengers and add a simple "service" var msger1 = messenger.create(messengerSpec); var msger2 = messenger.create(messengerSpec); msger2.addServices({ add: function(msg, msger) { msger.answer(msg, {result: msg.data.a + msg.data.b}); } }); // turn'em on... msger1.listen(); msger2.listen(); // ...and action! msger1.sendTo(msger2.id(), 'add', {a: 3, b: 4}, function(err, answer) { alert(answer.data.result); }); ``` */ function create$2(spec) { var expectedMethods = [{ name: "send", args: ['msg', 'callback'] }, { name: "listen", args: ['messenger', 'callback'] }, { name: "close", args: ['messenger', 'callback'] }, { name: "isOnline", args: [] }]; var ignoredAttributes = expectedMethods.map(function (ea) { return ea.name; }).concat(["id", "sendHeartbeat", "heartbeatInterval", "ignoreUnknownMessages", "allowConcurrentSends", "sendTimeout", "services"]); expectedMethods.forEach(function (exp) { if (spec[exp.name]) return; var msg = "message implementation needs function " + exp.name + "(" + exp.args.join(',') + ")"; throw new Error(msg); }); var heartbeatInterval = spec.sendHeartbeat && (spec.heartbeatInterval || 1000); var ignoreUnknownMessages = spec.hasOwnProperty("ignoreUnknownMessages") ? spec.ignoreUnknownMessages : false; var messenger = { _outgoing: [], _inflight: [], _id: spec.id || newUUID(), _ignoreUnknownMessages: ignoreUnknownMessages, _services: {}, _messageCounter: 0, _messageResponseCallbacks: {}, _whenOnlineCallbacks: [], _statusWatcherProc: null, _startHeartbeatProcessProc: null, _listenInProgress: null, _heartbeatInterval: heartbeatInterval, _status: OFFLINE, // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- _runWhenOnlineCallbacks: function _runWhenOnlineCallbacks() { var cbs = messenger._whenOnlineCallbacks.slice(); messenger._whenOnlineCallbacks = []; cbs.forEach(function (ea) { try { ea.call(null, null, messenger); } catch (e) { console.error("error in _runWhenOnlineCallbacks: %s", e); } }); }, _ensureStatusWatcher: function _ensureStatusWatcher() { if (messenger._statusWatcherProc) return; messenger._statusWatcherProc = setInterval(function () { if (messenger.isOnline() && messenger._whenOnlineCallbacks.length) messenger._runWhenOnlineCallbacks(); var prevStatus = messenger._status; messenger._status = messenger.isOnline() ? ONLINE : OFFLINE; if (messenger._status !== ONLINE && messenger._statusWatcherProc) { messenger.reconnect(); } if (messenger._status !== prevStatus && messenger.onStatusChange) { messenger.onStatusChange(); } }, 20); }, _addMissingData: function _addMissingData(msg) { if (!msg.target) throw new Error("Message needs target!"); if (!msg.action) throw new Error("Message needs action!"); if (!msg.data) msg.data = null; if (!msg.messageId) msg.messageId = newUUID(); msg.sender = messenger.id(); msg.messageIndex = messenger._messageCounter++; return msg; }, _queueSend: function _queueSend(msg, onReceiveFunc) { if (onReceiveFunc && typeof onReceiveFunc !== 'function') throw new Error("Expecing a when send callback, got: " + onReceiveFunc); messenger._outgoing.push([msg, onReceiveFunc]); }, _deliverMessageQueue: function _deliverMessageQueue() { if (!spec.allowConcurrentSends && messenger._inflight.length) return; var queued = messenger._outgoing.shift(); if (!queued) return; messenger._inflight.push(queued); if (messenger.isOnline()) deliver(queued);else messenger.whenOnline(function () { deliver(queued); }); startTimeoutProc(queued); if (spec.allowConcurrentSends && messenger._outgoing.length) messenger._deliverMessageQueue(); // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- function deliver(queued) { // ignore-in-doc if (messenger._inflight.indexOf(queued) === -1) return; // timed out var msg = queued[0], callback = queued[1]; if (callback) messenger._messageResponseCallbacks[msg.messageId] = callback; spec.send.call(messenger, msg, function (err) { remove(messenger._inflight, queued); if (err) onSendError(err, queued); messenger._deliverMessageQueue(); }); } function startTimeoutProc(queued) { if (typeof spec.sendTimeout !== 'number') return; setTimeout(function () { if (messenger._inflight.indexOf(queued) === -1) return; // delivered remove(messenger._inflight, queued); onSendError(new Error('Timeout sending message'), queued); messenger._deliverMessageQueue(); }, spec.sendTimeout); } function onSendError(err, queued) { var msg = queued[0], callback = queued[1]; delete messenger._messageResponseCallbacks[msg.messageId]; console.error(err); callback && callback(err); } }, _startHeartbeatProcess: function _startHeartbeatProcess() { if (messenger._startHeartbeatProcessProc) return; messenger._startHeartbeatProcessProc = setTimeout(function () { spec.sendHeartbeat.call(messenger, function (err, result) { messenger._startHeartbeatProcessProc = null; messenger._startHeartbeatProcess(); }); }, messenger._heartbeatInterval); }, // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- id: function id() { return messenger._id; }, isOnline: function isOnline() { return spec.isOnline.call(messenger); }, heartbeatEnabled: function heartbeatEnabled() { return typeof messenger._heartbeatInterval === 'number'; }, listen: function listen(thenDo) { if (messenger._listenInProgress) return; messenger._listenInProgress = true; messenger._ensureStatusWatcher(); return spec.listen.call(messenger, function (err) { messenger._listenInProgress = null; thenDo && thenDo(err); if (messenger.heartbeatEnabled()) messenger._startHeartbeatProcess(); }); return messenger; }, reconnect: function reconnect() { if (messenger._status === ONLINE) return; messenger.listen(); return messenger; }, send: function send(msg, onReceiveFunc) { messenger._addMissingData(msg); messenger._queueSend(msg, onReceiveFunc); messenger._deliverMessageQueue(); return msg; }, sendTo: function sendTo(target, action, data, onReceiveFunc) { var msg = { target: target, action: action, data: data }; return messenger.send(msg, onReceiveFunc); }, onMessage: function onMessage(msg) { messenger.emit("message", msg); if (msg.inResponseTo) { var cb = messenger._messageResponseCallbacks[msg.inResponseTo]; if (cb && !msg.expectMoreResponses) delete messenger._messageResponseCallbacks[msg.inResponseTo]; if (cb) cb(null, msg); } else { var action = messenger._services[msg.action]; if (action) { try { action.call(null, msg, messenger); } catch (e) { var errmMsg = String(e.stack || e); console.error("Error invoking service: " + errmMsg); messenger.answer(msg, { error: errmMsg }); } } else if (!messenger._ignoreUnknownMessages) { var err = new Error("messageNotUnderstood: " + msg.action); messenger.answer(msg, { error: String(err) }); } } }, answer: function answer(msg, data, expectMore, whenSend) { if (typeof expectMore === 'function') { whenSend = expectMore;expectMore = false; } var answer = { target: msg.sender, action: msg.action + 'Result', inResponseTo: msg.messageId, data: data }; if (expectMore) answer.expectMoreResponses = true; return messenger.send(answer, whenSend); }, close: function close(thenDo) { clearInterval(messenger._statusWatcherProc); messenger._statusWatcherProc = null; spec.close.call(messenger, function (err) { messenger._status = OFFLINE; thenDo && thenDo(err); }); return messenger; }, whenOnline: function whenOnline(thenDo) { messenger._whenOnlineCallbacks.push(thenDo); if (messenger.isOnline()) messenger._runWhenOnlineCallbacks(); return messenger; }, outgoingMessages: function outgoingMessages() { return pluck(messenger._inflight.concat(messenger._outgoing), 0); }, addServices: function addServices(serviceSpec) { Object.assign(messenger._services, serviceSpec); return messenger; } }; if (spec.services) messenger.addServices(spec.services); makeEmitter(messenger); for (var name in spec) { if (ignoredAttributes.indexOf(name) === -1 && spec.hasOwnProperty(name)) { messenger[name] = spec[name]; } } return messenger; } var messenger = Object.freeze({ create: create$2 }); /*global, require, Worker, URL, webkitURL, Blob, BlobBuilder, process, require,self,global,remoteWorker,postMessage,XMLHttpRequest,__FUNCTIONDECLARATIONS__,initBrowserGlobals,loadDependenciesBrowser,initOnMessageHandler,initWorkerInterface,initWorkerMessenger,loadDependenciesNodejs,importScripts*/ /* * A platform-independent worker interface that will spawn new processes per * worker (if the platform you use it on supports it). */ var isNodejs = typeof require !== 'undefined' && typeof process !== 'undefined'; // ignore-in-doc // Code in worker setup is evaluated in the context of workers, it will get to // workers in a stringified form(!). var WorkerSetup = { loadDependenciesBrowser: function loadDependenciesBrowser(options) { var me = typeof self !== "undefined" ? self : this; importScripts.apply(me, options.scriptsToLoad || []); }, loadDependenciesNodejs: function loadDependenciesNodejs(options) { var lv = global.lively || (global.lively = {}); lv.lang = require(require("path").join(options.libLocation, "index")); }, // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- // yoshiki and robert, 05/08/13: Inserted code that sets up the lively context // and globals of Lively and other required objects: initBrowserGlobals: function initBrowserGlobals(options) { remoteWorker.send = function (msg) { postMessage(msg); }; var me = typeof self !== "undefined" ? self : this; var Global = me.Global = me; Global.window = Global; Global.console = Global.console || function () { var c = {}; ['log', 'error', 'warn'].forEach(function (name) { c[name] = function () /*args*/{ var string = arguments[0]; for (var i = 1; i < arguments.length; i++) { string = string.replace('%s', arguments[i]); }remoteWorker.send({ type: name, message: ['[', name.toUpperCase(), '] ', string].join('') }); }; }); return c; }(); }, initOnMessageHandler: function initOnMessageHandler(options) { if (remoteWorker.on) remoteWorker.on('message', onMessage);else remoteWorker.onmessage = onMessage; function onMessage(msg) { msg = msg.data.data ? msg.data : msg; if (remoteWorker.messenger) remoteWorker.messenger.onMessage(msg);else if (msg.action == "close") { remoteWorker.send({ type: "closed", workerReady: false }); remoteWorker.close(); return; } } }, initWorkerInterface: function initWorkerInterface(options) { remoteWorker.callStringifiedFunction = function (stringifiedFunc, args, thenDo) { // ignore-in-doc // runs stringified function and passing args. stringifiedFunc might // be asynchronous if it takes an addaitional argument. In this case a // callback to call when the work is done is passed, otherwise thenDo // will be called immediatelly after creating and calling the function var func; try { func = eval('(' + stringifiedFunc + ')'); } catch (e) { thenDo(new Error("Cannot create function from string: " + e.stack || e)); return; } // ignore-in-doc // when it takes one more arg then we assume that this is the callback // to be called by the run func when it considers to be done var usesCallback = func.length === args.length + 1; var whenDone = lively.lang.fun.once(function (err, result) { remoteWorker.isBusy = false;thenDo(err, result); }); remoteWorker.isBusy = true; if (usesCallback) args.push(whenDone); try { var result = func.apply(remoteWorker, args.concat([whenDone])); } catch (e) { whenDone(e, null);return; } if (!usesCallback) whenDone(null, result); }; remoteWorker.httpRequest = function (options) { if (!options.url) { console.log("Error, httpRequest needs url"); return; } var req = new XMLHttpRequest(), method = options.method || 'GET'; function handleStateChange() { if (req.readyState === 4) { // req.status options.done && options.done(req); } } req.onreadystatechange = handleStateChange; req.open(method, options.url); req.send(); }; remoteWorker.terminateIfNotBusyIn = function (ms) { setTimeout(function () { if (remoteWorker.isBusy) { remoteWorker.terminateIfNotBusyIn(ms);return; } remoteWorker.send({ type: "closed", workerReady: false }); remoteWorker.close(); }, ms); }; }, // ignore-in-doc // setting up the worker messenger interface, this is how the worker // should be communicated with initWorkerMessenger: function initWorkerMessenger(options) { if (!options.useMessenger) return null; if (!lively.lang.messenger) throw new Error("worker.create requires messenger.js to be loaded!"); if (!lively.lang.events) throw new Error("worker.create requires events.js to be loaded!"); return remoteWorker.messenger = lively.lang.messenger.create({ services: { remoteEval: function remoteEval(msg, messenger) { var result; try { result = eval(msg.data.expr); } catch (e) { result = e.stack || e; } messenger.answer(msg, { result: String(result) }); }, run: function run(msg, messenger) { var funcString = msg.data.func, args = msg.data.args; if (!funcString) { messenger.answer(msg, { error: 'no funcString' });return; } remoteWorker.callStringifiedFunction(funcString, args, function (err, result) { messenger.answer(msg, { error: err ? String(err) : null, result: result }); }); }, close: function close(msg, messenger) { messenger.answer(msg, { status: "OK" }); remoteWorker.send({ type: "closed", workerReady: false }); remoteWorker.close(); } }, isOnline: function isOnline() { return true; }, send: function send(msg, whenSend) { remoteWorker.send(msg);whenSend(); }, listen: function listen(whenListening) { whenListening(); }, close: function close(whenClosed) { remoteWorker.send({ type: "closed", workerReady: false });remoteWorker.close(); } }); } }; var BrowserWorker = { create: function create$3(options) { // ignore-in-doc // this function instantiates a browser worker object. We provide a // messenger-based interface to the pure Worker. Please use create to get an // improved interface to a worker options = options || {}; // ignore-in-doc // figure out where the other lang libs can be loaded from if (!options.libLocation && !options.scriptsToLoad) { var workerScript = document.querySelector("script[src$=\"worker.js\"]"); if (!workerScript) throw new Error("Cannot find library path to start worker. Use worker.create({libLocation: \"...\"}) to explicitly define the path!"); options.libLocation = workerScript.src.replace(/worker.js$/, ''); } var workerSetupCode = String(workerSetupFunction).replace("__FUNCTIONDECLARATIONS__", [WorkerSetup.initBrowserGlobals, WorkerSetup.loadDependenciesBrowser, WorkerSetup.initOnMessageHandler, WorkerSetup.initWorkerInterface, WorkerSetup.initWorkerMessenger].join('\n')); var workerCode = '(' + lively_sourceTransform.stringifyFunctionWithoutToplevelRecorder(workerSetupCode) + ')();'; var worker = new Worker(makeDataURI(workerCode)); init(options, worker); return worker; // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- // ignore-in-doc // This code is triggered in the UI process directly after the // creation of the worker and sends the setup message to the worker // for initializing it. function init(options, worker) { makeEmitter(worker); if (!options.scriptsToLoad) { options.scriptsToLoad = ['base.js', 'events.js', 'object.js', 'collection.js', 'function.js', 'string.js', 'number.js', 'date.js', 'messenger.js', 'worker.js'].map(function (ea) { return options.libLocation + ea; }); } var workerOptions = Object.keys(options).reduce(function (opts, key) { if (typeof options[key] !== 'function') opts[key] = options[key]; return opts; }, {}); worker.onmessage = function (evt) { if (evt.data.workerReady !== undefined) { worker.ready = !!evt.data.workerReady; if (worker.ready) worker.emit("ready");else worker.emit("close"); } else worker.emit('message', evt.data); }; worker.errors = []; worker.onerror = function (evt) { console.error(evt); worker.errors.push(evt); worker.emit("error", evt); }; worker.postMessage({ action: 'setup', options: workerOptions }); } // ignore-in-doc // This code is run inside the worker and bootstraps the messenger // interface. It also installs a console.log method since since this is not // available by default. function workerSetupFunction() { var remoteWorker = self; remoteWorker.onmessage = function (evt) { if (evt.data.action !== "setup") { throw new Error("expected setup to be first message but got " + JSON.stringify(evt.data)); } var options = evt.data.options || {}; initBrowserGlobals(options); loadDependenciesBrowser(options); initOnMessageHandler(options); initWorkerInterface(options); initWorkerMessenger(options); postMessage({ workerReady: true }); }; __FUNCTIONDECLARATIONS__; } function makeDataURI(codeToInclude) { // ignore-in-doc // see http://stackoverflow.com/questions/10343913/how-to-create-a-web-worker-from-a-string var blob; try { blob = new Blob([codeToInclude], { type: "text/javascript" }); } catch (e) { /* ignore-in-doc Backwards-compatibility*/ window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder; blob = new BlobBuilder(); blob.append(codeToInclude); blob = blob.getBlob(); } var urlInterface = typeof webkitURL !== 'undefined' ? webkitURL : URL; return urlInterface.createObjectURL(blob); } } }; var NodejsWorker = { debug: false, initCodeFileCreated: false, create: function create$3(options) { options = options || {}; // ignore-in-doc // figure out where the other lang libs can be loaded from // if (!options.libLocation && !options.scriptsToLoad) { // var workerScript = document.querySelector("script[src$=\"worker.js\"]"); // if (!workerScript) throw new Error("Cannot find library path to start worker. Use worker.create({libLocation: \"...\"}) to explicitly define the path!"); // options.libLocation = workerScript.src.replace(/worker.js$/, ''); // } var workerProc; var worker = makeEmitter({ ready: false, errors: [], postMessage: function postMessage(msg) { if (!workerProc) { worker.emit("error", new Error('nodejs worker process not yet created')); return; } if (!worker.ready) { worker.emit("error", new Error('nodejs worker process not ready or already closed')); return; } workerProc.send(msg); } }); NodejsWorker.startWorker(options, function (err, _workerProc) { if (err) { worker.ready = false;worker.emit("error", err);return; } workerProc = _workerProc; workerProc.on('message', function (m) { NodejsWorker.debug && console.log('[WORKER PARENT] got message:', m); worker.emit("message", m); }); workerProc.on('close', function () { console.log("[WORKER PARENT] worker closed"); worker.emit("close"); }); workerProc.on('error', function (err) { console.log("[WORKER PARENT] error ", err); worker.errors.push(err); worker.emit("error", err); }); worker.ready = true; worker.emit("ready"); }); return worker; }, // this code is run in the context of the worker process workerSetupFunction: function workerSetupFunction() { var remoteWorker = process; var debug = true; var close = false; debug && console.log("[WORKER] Starting init"); // ignore-in-doc // process.on('message', function(m) { // debug && console.log('[WORKER] got message:', m); // if (m.action === 'ping') process.send({action: 'pong', data: m}); // else if (m.action === 'close') close = true; // else if (m.action === 'setup') setup(m.data); // else console.error('[WORKER] unknown message: ', m); // }); remoteWorker.on("message", function (msg) { if (msg.action !== "setup") { throw new Error("expected setup to be first message but got " + JSON.stringify(msg.data)); } remoteWorker.removeAllListeners("message"); var options = msg.data.options || {}; debug && console.log("[WORKER] running setup with options", options); loadDependenciesNodejs(options); initOnMessageHandler(options); initWorkerInterface(options); initWorkerMessenger(options); remoteWorker.send({ workerReady: true }); }); __FUNCTIONDECLARATIONS__; }, ensureInitCodeFile: function ensureInitCodeFile(options, initCode, thenDo) { var path = require("path"); var os = require("os"); var fs = require("fs"); var workerTmpDir = path.join(os.tmpDir(), 'lively-nodejs-workers/'); var fn = path.join(workerTmpDir, 'nodejs-worker-init.js'); if (!NodejsWorker.initCodeFileCreated) NodejsWorker.createWorkerCodeFile(options, fn, initCode, thenDo);else fs.exists(fn, function (exists) { if (exists) thenDo(null, fn);else NodejsWorker.createWorkerCodeFile(options, fn, initCode, thenDo); }); }, createWorkerCodeFile: function createWorkerCodeFile(options, fileName, initCode, thenDo) { var path = require("path"); var fs = require("fs"); var exec = require("child_process").exec; exec("mkdir -p " + path.dirname(fileName), function (code, out, err) { if (code) { thenDo(new Error(["[WORKER PARENT] Could not create worker temp dir:", out, err].join('\n'))); return; } fs.writeFile(fileName, initCode, function (err) { NodejsWorker.debug && console.log('worker code file %s created', fileName); NodejsWorker.initCodeFileCreated = true; thenDo(err, fileName); }); }); }, startWorker: function startWorker(options, thenDo) { var util = require("util"); var fork = require("child_process").fork; var workerSetupCode = String(NodejsWorker.workerSetupFunction).replace("__FUNCTIONDECLARATIONS__", [WorkerSetup.loadDependenciesNodejs, WorkerSetup.initOnMessageHandler, WorkerSetup.initWorkerInterface, WorkerSetup.initWorkerMessenger].join('\n')); var initCode = util.format("(%s)();\n", workerSetupCode); NodejsWorker.ensureInitCodeFile(options, initCode, function (err, codeFileName) { if (err) return thenDo(err); var worker = fork(codeFileName, {}); NodejsWorker.debug && console.log('worker forked'); worker.on('message', function (m) { if (m.action === 'pong') console.log("[WORKER pong] ", m);else if (m.action === 'log') console.log("[Message from WORKER] ", m.data); }); worker.once('message', function (m) { NodejsWorker.debug && console.log('worker setup done'); thenDo(null, worker, m); }); worker.on('close', function () { NodejsWorker.debug && console.log("[WORKER PARENT] worker closed"); }); worker.send({ action: "setup", data: { options: options } }); global.WORKER = worker; }); } }; // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- // the worker interface, usable both in browser and node.js contexts // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- /* Worker objects allow to fork processes in both Web and node.js JavaScript environments. They provide this mechanism using web workers in the browser and node.js child processes in node.js. The interface is unified for all platforms. */ function fork(options, workerFunc, thenDo) { // Fork automatically starts a worker and calls `workerFunc`. `workerFunc` // gets as a last paramter a callback, that, when invoked with an error and // result object, ends the worker execution. // // Options are the same as in `create` except for an `args` property that // can be an array of objects. These objects will be passed to `workerFunc` // as arguments. // // Note: `workerFunc` will not be able to capture outside variables (create a // closure). // // Example: // // When running this inside a browser: Note how the UI does not block. // worker.fork({args: [40]}, // function(n, thenDo) { // function fib(n) { return n <= 1 ? n : fib(n-1) + fib(n-2); } // thenDo(null, fib(n)); // }, // function(err, result) { show(err ? err.stack : result); }) if (!thenDo) { thenDo = workerFunc;workerFunc = options;options = null; } options = options || {}; var args = options.args || []; var w = create$3(options); w.run.apply(w, [workerFunc].concat(args).concat(thenDo)); return w; } function create$3(options) { // Explicitly creates a first-class worker. Options: // ```js // { // workerId: STRING, // optional, id for worker, will be auto assigned if not provided // libLocation: STRING, // optional, path to where the lively.lang lib is located. Worker will try to find it automatically if not provided. // scriptsToLoad: ARRAY // optional, list of path/urls to load. Overwrites `libLocation` // } // ``` // // Example: // // this is just a helper function // function resultHandler(err, result) { alert(err ? String(err) : result); } // // // 1. Create the worker // var worker = lively.lang.worker.create({libLocation: baseURL}); // // // 2. You can evaluate arbitrary JS code // worker.eval("1+2", function(err, result) { show(err ? String(err) : result); }); // // // 3. Arbitrary functions can be called inside the worker context. // // Note: functions shouldn't be closures / capture local state!) and passing // // in arguments! // worker.run( // function(a, b, thenDo) { setTimeout(function() { thenDo(null, a+b); }, 300); }, // 19, 4, resultHandler); // // // 4. You can also install your own messenger services... // worker.run( // function(thenDo) { // self.messenger.addServices({ // foo: function(msg, messenger) { messenger.answer(msg, "bar!"); } // }); // thenDo(null, "Service installed!"); // }, resultHandler); // // // ... and call them via the messenger interface // worker.sendTo("worker", "foo", {}, resultHandler); // // // 5. afterwards: shut it down // worker.close(function(err) { err && show(String(err)); alertOK("worker shutdown"); }) options = options || {}; options.useMessenger = true; // if (!exports.messenger) // throw new Error("worker.create requires messenger.js to be loaded!") // if (!exports.events) // throw new Error("worker.create requires events.js to be loaded!") // if (!exports.obj) // throw new Error("worker.create requires object.js to be loaded!") var workerId = options.workerId || newUUID(); var messenger = create$2({ sendTimeout: 5000, send: function send(msg, whenSend) { messenger.worker.postMessage(msg); whenSend(); }, listen: function listen(whenListening) { var w = messenger.worker = isNodejs ? NodejsWorker.create(options) : BrowserWorker.create(options); w.on("message", function (msg) { messenger.onMessage(msg); }); w.on('ready', function () { NodejsWorker.debug && console.log("WORKER READY!!!"); }); w.on('close', function () { NodejsWorker.debug && console.log("WORKER CLOSED...!!!"); }); w.once('ready', whenListening); }, close: function close(whenClosed) { if (!messenger.worker.ready) return whenClosed(null); return messenger.sendTo(workerId, 'close', {}, function (err, answer) { err = err || answer.data.error; err && console.error("Error in worker messenger close: " + err.stack || err); if (err) whenClosed(err);else { var closed = false; messenger.worker.once('close', function () { closed = true; }); waitFor(1000, function () { return !!closed; }, whenClosed); } }); }, isOnline: function isOnline() { return messenger.worker && messenger.worker.ready; } }); Object.assign(messenger, { eval: function _eval(code, thenDo) { messenger.sendTo(workerId, "remoteEval", { expr: code }, function (err, answer) { thenDo(err, answer ? answer.data.result : null); }); }, run: function run() /*runFunc, arg1, ... argN, thenDo*/{ var args = Array.prototype.slice.call(arguments), workerFunc = args.shift(), thenDo = args.pop(); if (typeof workerFunc !== "function") throw new Error("run: no function that should run in worker passed"); if (typeof thenDo !== "function") throw new Error("run: no callback passed"); return messenger.sendTo(workerId, 'run', { func: String(workerFunc), args: args }, function (err, answer) { thenDo(err || answer.data.error, answer ? answer.data.result : null); }); } }); messenger.listen(); return messenger; } var worker = Object.freeze({ fork: fork, create: create$3 }); var GLOBAL = typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : undefined; var isNode = typeof process !== "undefined" && process.env && typeof process.exit === "function"; var globalInterfaceSpec = [{ action: "installMethods", target: "Array", sources: ["arr"], methods: ["from", "genN", "range", "withN"] }, { action: "installMethods", target: "Array.prototype", sources: ["arr"], methods: ["all", "any", "batchify", "clear", "clone", "collect", "compact", "delimWith", "detect", "doAndContinue", "each", "equals", "filterByKey", "findAll", "first", "flatten", "forEachShowingProgress", "grep", "groupBy", "groupByKey", "histogram", "include", "inject", "intersect", "invoke", "last", "mapAsync", "mapAsyncSeries", "mask", "max", "min", "mutableCompact", "nestedDelay", "partition", "pluck", "pushAll", "pushAllAt", "pushAt", "pushIfNotIncluded", "reMatches", "reject", "rejectByKey", "remove", "removeAt", "replaceAt", "rotate", "shuffle", "size", "sortBy", "sortByKey", "sum", "swap", "toArray", "toTuples", "union", "uniq", "uniqBy", "without", "withoutAll", "zip"], alias: [["select", "filter"]] }, { action: "installMethods", target: "Date", sources: ["date"], methods: [/*"parse"*/] }, { action: "installMethods", target: "Date.prototype", sources: ["date"], methods: ["equals", "format", "relativeTo"] }, { action: "installMethods", target: "Function", sources: ["fun"], methods: ["fromString"] }, { action: "installMethods", target: "Function.prototype", sources: ["fun"], methods: [/*"addProperties",*/"addToObject", "argumentNames", "asScript", "asScriptOf", "binds", "curry", "delay", "functionNames", "localFunctionNames", "getOriginal", "getVarMapping", "logCalls", "logCompletion", "logErrors", "qualifiedMethodName", "setProperty", "traceCalls", "wrap"] }, { action: "installMethods", target: "Number", sources: ["num"], methods: [] }, { action: "installMethods", target: "Number.prototype", sources: ["num"], methods: ["detent", "randomSmallerInteger", "roundTo", "toDegrees", "toRadians"] }, { action: "installMethods", target: "Object", sources: ["obj"], methods: ["addScript", "clone", "deepCopy", "extend", "inherit", "isArray", "isBoolean", "isElement", "isEmpty", "isFunction", "isNumber", "isObject", "isRegExp", "isString", "isUndefined", "merge", "mergePropertyInHierarchy", "values", "valuesInPropertyHierarchy"] }, { action: "installMethods", target: "Object.prototype", sources: ["obj"], methods: [] }, { action: "installMethods", target: "String.prototype", sources: ["string"], methods: ["camelize", "capitalize", "digitValue", "empty", "hashCode", "include", "pad", "regExpEscape", "startsWithVowel", "succ", "times", "toArray", "toQueryParams", "truncate"] }, { action: "installObject", target: "Numbers", source: "num", methods: ["average", "between", "convertLength", "humanReadableByteSize", "median", "normalRandom", "parseLength", "random", "sort"] }, { action: "installObject", target: "Properties", source: "properties", methods: ["all", "allOwnPropertiesOrFunctions", "allProperties", "any", "forEachOwn", "hash", "nameFor", "own", "ownValues", "values"] }, { action: "installObject", target: "Strings", source: "string", methods: ["camelCaseString", "createDataURI", "diff", "format", "formatFromArray", "indent", "lineIndexComputer", "lines", "md5", "newUUID", "nonEmptyLines", "pad", "paragraphs", "peekLeft", "peekRight", "print", "printNested", "printTable", "printTree", "quote", "reMatches", "stringMatch", "tableize", "tokens", "unescapeCharacterEntities", "withDecimalPrecision"] }, { action: "installObject", target: "Objects", source: "obj", methods: ["asObject", "equals", "inspect", "isMutableType", "safeToString", "shortPrintStringOf", "typeStringOf"] }, { action: "installObject", target: "Functions", source: "fun", methods: ["all", "compose", "composeAsync", "createQueue", "debounce", "debounceNamed", "either", "extractBody", "flip", "notYetImplemented", "once", "own", "throttle", "throttleNamed", "timeToRun", "timeToRunN", "waitFor", "workerWithCallbackQueue", "wrapperChain"] }, { action: "installObject", target: "Grid", source: "grid" }, { action: "installObject", target: "Interval", source: "interval" }, { action: "installObject", target: "lively.ArrayProjection", source: "arrayProjection" }, { action: "installObject", target: "lively.Closure", source: "Closure" }, { action: "installObject", target: "lively.Grouping", source: "Group" }, { action: "installObject", target: "lively.PropertyPath", source: "Path" }, { action: "installObject", target: "lively.Worker", source: "worker" }, { action: "installObject", target: "lively.Class", source: "classHelper" }]; function createLivelyLangObject() { return { chain: chain$$1, noConflict: noConflict, installGlobals: installGlobals, uninstallGlobals: uninstallGlobals, globalInterfaceSpec: globalInterfaceSpec, toString: function toString() { return "[object lively.lang]"; } }; } var livelyLang = createLivelyLangObject(); function chain$$1(object) { if (!object) return object; var chained; if (Array.isArray(object)) return createChain(arr, object); if (object.constructor.name === "Date") return createChain(date, object); switch (typeof object === "undefined" ? "undefined" : _typeof(object)) { case 'string': return createChain(string, object); case 'object': return createChain(obj, object); case 'function': return createChain(fun, object); case 'number': return createChain(num, object); } throw new Error("Chain for object " + object + " (" + object.constructor.name + ") no supported"); } function createChain(interfaceObj, obj) { return Object.keys(interfaceObj).reduce(function (chained, methodName) { chained[methodName] = function () /*args*/{ var args = Array.prototype.slice.call(arguments), result = interfaceObj[methodName].apply(null, [obj].concat(args)); return chain$$1(result); }; return chained; }, { value: function value() { return obj; } }); } function noConflict() { if (!isNode) { var keepLivelyNS = livelyLang._prevLivelyGlobal; if (!keepLivelyNS) delete GLOBAL.lively;else delete GLOBAL.lively.lang; } return livelyLang; } function installGlobals() { Object.assign(livelyLang, { worker: worker, messenger: messenger, events: events, tree: tree, grid: grid, arrayProjection: arrayProjection, interval: interval, graph: graph, date: date, properties: properties, obj: obj, arr: arr, fun: fun, num: num, string: string, Closure: Closure, promise: promise, Path: Path, Group: Group }); globalInterfaceSpec.forEach(function (ea) { if (ea.action === "installMethods") { var targetPath = Path(ea.target); if (!targetPath.isIn(GLOBAL)) targetPath.set(GLOBAL, {}, true); var sourcePath = Path(ea.sources[0]); ea.methods.forEach(function (name) { installProperty(sourcePath.concat([name]), targetPath.concat([name])); }); if (ea.alias) ea.alias.forEach(function (mapping) { installProperty(sourcePath.concat([mapping[1]]), targetPath.concat([mapping[0]])); }); } else if (ea.action === "installObject") { var targetPath = Path(ea.target); var source = Path(ea.source).get(livelyLang); targetPath.set(GLOBAL, source, true); } else throw new Error("Cannot deal with global setup action: " + ea.action); }); } function installProperty(sourcePath, targetPath) { if (!sourcePath.isIn(livelyLang)) { var err = new Error("property not provided by lively.lang: " + sourcePath); console.error(err.stack || err); throw err; } var prop = sourcePath.get(livelyLang); if (typeof prop === "function" && targetPath.slice(-2, -1).toString() === "prototype") { var origFunc = prop; prop = function prop() /*this and args*/{ var args = Array.prototype.slice.call(arguments); args.unshift(this); return origFunc.apply(null, args); }; prop.toString = function () { return origFunc.toString(); }; } targetPath.set(GLOBAL, prop, true); } function uninstallGlobals() { globalInterfaceSpec.forEach(function (ea) { if (ea.action === "installMethods") { var p = Path(ea.target); var source = Path(ea.source).get(livelyLang); var target = p.get(GLOBAL); if (!target) return; ea.methods.filter(function (name) { return source === target[name]; }).forEach(function (name) { delete target[name]; }); if (ea.alias) ea.alias.filter(function (name) { return source === target[name]; }).forEach(function (mapping) { delete target[mapping[0]]; }); } else if (ea.action === "installObject") { var p = Path(ea.target); p.del(GLOBAL); } else throw new Error("Cannot deal with global setup action: " + ea.action); }); } exports.worker = worker; exports.messenger = messenger; exports.events = events; exports.tree = tree; exports.grid = grid; exports.arrayProjection = arrayProjection; exports.interval = interval; exports.graph = graph; exports.date = date; exports.properties = properties; exports.obj = obj; exports.arr = arr; exports.fun = fun; exports.num = num; exports.string = string; exports.Closure = Closure; exports.promise = promise; exports.Path = Path; exports.Group = Group; exports.livelyLang = livelyLang; exports.chain = chain$$1; exports.noConflict = noConflict; exports.installGlobals = installGlobals; exports.uninstallGlobals = uninstallGlobals; }((this.lively.lang = this.lively.lang || {}),lively.sourceTransform)); }).call(GLOBAL); if (typeof module !== "undefined" && module.exports) module.exports = GLOBAL.lively.lang; })(); // INLINED END /Users/user/git/lively.vm/node_modules/lively.lang/dist/lively.lang.js // INLINED /Users/user/git/lively.vm/node_modules/lively.notifications/dist/lively.notifications.js (function() { var GLOBAL = typeof window !== "undefined" ? window : typeof global!=="undefined" ? global : typeof self!=="undefined" ? self : this; this.lively = this.lively || {}; (function (exports,lively_lang) { 'use strict'; /*global System*/ // type EventType = string // type EventTime = number // type Notification = {type: EventType, time: EventTime, ...}; // type Handler = Notification -> () // type Notifications = { [number]: Notification, limit: number } // type Emitter = {isRecording: boolean, isLogging: boolean, ... } // type Env = {emitter: Emitter, notifications: Notifications} var env = void 0; function getEnv(_System) { // System? -> Env if (_System === undefined) { if (typeof System === "undefined") { // fallback if not System is available if (env !== undefined) return env; return env || (env = { emitter: lively_lang.events.makeEmitter({}, { maxListenerLimit: 10000 }), notifications: [] }); } _System = System; } var livelyEnv = _System.get("@lively-env"); if (!livelyEnv) _System.set("@lively-env", _System.newModule({ options: {} })); var options = livelyEnv.options; if (!options) throw new Error("@lively-env registered read-only"); if (!options.emitter) { Object.assign(options, { emitter: _System["__lively.notifications_emitter"] || (_System["__lively.notifications_emitter"] = lively_lang.events.makeEmitter({}, { maxListenerLimit: 10000 })), notifications: _System["__lively.notifications_notifications"] || (_System["__lively.notifications_notifications"] = []) }); } var emitter = options.emitter, notifications = options.notifications; return { emitter: emitter, notifications: notifications }; } function subscribe(type, handler, system) { // EventType, Handler, System? -> Handler getEnv(system).emitter.on(type, handler); return handler; } function subscribeOnce(type, handler, system) { // EventType, Handler, System? -> Handler getEnv(system).emitter.once(type, handler); return handler; } function emit(type) { var data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var time = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : Date.now(); var system = arguments[3]; // EventType, Notification?, EventTime?, System? -> Notification var notification = Object.assign({ type: type, time: time }, data), _getEnv = getEnv(system), emitter = _getEnv.emitter, notifications = _getEnv.notifications; emitter.emit(type, notification); if (emitter.isLogging) log(notification); if (emitter.isRecording) record(notifications, notification); return notification; } function unsubscribe(type, handler, system) { // EventType, Handler, System? -> Handler getEnv(system).emitter.removeListener(type, handler); return handler; } function unsubscribeAll(type, system) { // EventType, System? -> () getEnv(system).emitter.removeAllListeners(type); } function record(notifications, notification) { // Array, Notification -> () notifications.push(notification); if (notifications.limit) { notifications.splice(0, notifications.length - notifications.limit); } } function startRecording(system) { // System? -> () getEnv(system).emitter.isRecording = true; } function stopRecording(system) { // System? -> () getEnv(system).emitter.isRecording = false; } function clearRecord(system) { // System? -> () var _getEnv2 = getEnv(system), notifications = _getEnv2.notifications; notifications.splice(0, notifications.length); } function getRecord(system) { // System? -> Notifications return getEnv(system).notifications; } function log(notification) { // Notification -> () var padded = notification.type + " ".repeat(Math.max(0, 32 - notification.type.length)); console.log(padded + " " + lively_lang.obj.inspect(notification, { maxDepth: 2 })); } function startLogging(system) { // System? -> () getEnv(system).emitter.isLogging = true; } function stopLogging(system) { // System? -> () getEnv(system).emitter.isLogging = false; } exports.subscribe = subscribe; exports.subscribeOnce = subscribeOnce; exports.emit = emit; exports.unsubscribe = unsubscribe; exports.unsubscribeAll = unsubscribeAll; exports.startRecording = startRecording; exports.stopRecording = stopRecording; exports.clearRecord = clearRecord; exports.getRecord = getRecord; exports.startLogging = startLogging; exports.stopLogging = stopLogging; }((this.lively.notifications = this.lively.notifications || {}),lively.lang)); if (typeof module !== "undefined" && module.exports) module.exports = GLOBAL.lively.classes; })(); // INLINED END /Users/user/git/lively.vm/node_modules/lively.notifications/dist/lively.notifications.js // INLINED /Users/user/git/lively.vm/node_modules/lively.ast/dist/lively.ast.js ;(function() { var GLOBAL = typeof window !== "undefined" ? window : typeof global!=="undefined" ? global : typeof self!=="undefined" ? self : this; if (GLOBAL.define) { var __define_suckz__ = GLOBAL; delete GLOBAL.define; } (function() { var module = undefined, require = undefined, define = undefined; (function() { var module = undefined, require = undefined, define = undefined; (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (factory((global.acorn = global.acorn || {}))); }(this, (function (exports) { 'use strict'; // Reserved word lists for various dialects of the language var reservedWords = { 3: "abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile", 5: "class enum extends super const export import", 6: "enum", strict: "implements interface let package private protected public static yield", strictBind: "eval arguments" }; // And the keywords var ecma5AndLessKeywords = "break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this"; var keywords = { 5: ecma5AndLessKeywords, 6: ecma5AndLessKeywords + " const class extends export import super" }; // ## Character categories // Big ugly regular expressions that match characters in the // whitespace, identifier, and identifier-start categories. These // are only applied when a character is found to actually have a // code point above 128. // Generated by `bin/generate-identifier-regex.js`. var nonASCIIidentifierStartChars = "\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u037f\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u052f\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0-\u08b4\u08b6-\u08bd\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0af9\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c39\u0c3d\u0c58-\u0c5a\u0c60\u0c61\u0c80\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d54-\u0d56\u0d5f-\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f5\u13f8-\u13fd\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f8\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191e\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1c80-\u1c88\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2118-\u211d\u2124\u2126\u2128\u212a-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309b-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fd5\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua69d\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua7ae\ua7b0-\ua7b7\ua7f7-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua8fd\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\ua9e0-\ua9e4\ua9e6-\ua9ef\ua9fa-\ua9fe\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa7e-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uab30-\uab5a\uab5c-\uab65\uab70-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc"; var nonASCIIidentifierChars = "\u200c\u200d\xb7\u0300-\u036f\u0387\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u0669\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u06f0-\u06f9\u0711\u0730-\u074a\u07a6-\u07b0\u07c0-\u07c9\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u08d4-\u08e1\u08e3-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09cb-\u09cd\u09d7\u09e2\u09e3\u09e6-\u09ef\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c00-\u0c03\u0c3e-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0c66-\u0c6f\u0c81-\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0ce6-\u0cef\u0d01-\u0d03\u0d3e-\u0d44\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0d62\u0d63\u0d66-\u0d6f\u0d82\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0de6-\u0def\u0df2\u0df3\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0e50-\u0e59\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e\u0f3f\u0f71-\u0f84\u0f86\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102b-\u103e\u1040-\u1049\u1056-\u1059\u105e-\u1060\u1062-\u1064\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u1369-\u1371\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b4-\u17d3\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u18a9\u1920-\u192b\u1930-\u193b\u1946-\u194f\u19d0-\u19da\u1a17-\u1a1b\u1a55-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1ab0-\u1abd\u1b00-\u1b04\u1b34-\u1b44\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1b82\u1ba1-\u1bad\u1bb0-\u1bb9\u1be6-\u1bf3\u1c24-\u1c37\u1c40-\u1c49\u1c50-\u1c59\u1cd0-\u1cd2\u1cd4-\u1ce8\u1ced\u1cf2-\u1cf4\u1cf8\u1cf9\u1dc0-\u1df5\u1dfb-\u1dff\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua620-\ua629\ua66f\ua674-\ua67d\ua69e\ua69f\ua6f0\ua6f1\ua802\ua806\ua80b\ua823-\ua827\ua880\ua881\ua8b4-\ua8c5\ua8d0-\ua8d9\ua8e0-\ua8f1\ua900-\ua909\ua926-\ua92d\ua947-\ua953\ua980-\ua983\ua9b3-\ua9c0\ua9d0-\ua9d9\ua9e5\ua9f0-\ua9f9\uaa29-\uaa36\uaa43\uaa4c\uaa4d\uaa50-\uaa59\uaa7b-\uaa7d\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uaaeb-\uaaef\uaaf5\uaaf6\uabe3-\uabea\uabec\uabed\uabf0-\uabf9\ufb1e\ufe00-\ufe0f\ufe20-\ufe2f\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f"; var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]"); var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]"); nonASCIIidentifierStartChars = nonASCIIidentifierChars = null; // These are a run-length and offset encoded representation of the // >0xffff code points that are a valid part of identifiers. The // offset starts at 0x10000, and each pair of numbers represents an // offset to the next range, and then a size of the range. They were // generated by bin/generate-identifier-regex.js // eslint-disable-next-line comma-spacing var astralIdentifierStartCodes = [0,11,2,25,2,18,2,1,2,14,3,13,35,122,70,52,268,28,4,48,48,31,17,26,6,37,11,29,3,35,5,7,2,4,43,157,19,35,5,35,5,39,9,51,157,310,10,21,11,7,153,5,3,0,2,43,2,1,4,0,3,22,11,22,10,30,66,18,2,1,11,21,11,25,71,55,7,1,65,0,16,3,2,2,2,26,45,28,4,28,36,7,2,27,28,53,11,21,11,18,14,17,111,72,56,50,14,50,785,52,76,44,33,24,27,35,42,34,4,0,13,47,15,3,22,0,2,0,36,17,2,24,85,6,2,0,2,3,2,14,2,9,8,46,39,7,3,1,3,21,2,6,2,1,2,4,4,0,19,0,13,4,159,52,19,3,54,47,21,1,2,0,185,46,42,3,37,47,21,0,60,42,86,25,391,63,32,0,449,56,264,8,2,36,18,0,50,29,881,921,103,110,18,195,2749,1070,4050,582,8634,568,8,30,114,29,19,47,17,3,32,20,6,18,881,68,12,0,67,12,65,0,32,6124,20,754,9486,1,3071,106,6,12,4,8,8,9,5991,84,2,70,2,1,3,0,3,1,3,3,2,11,2,0,2,6,2,64,2,3,3,7,2,6,2,27,2,3,2,4,2,0,4,6,2,339,3,24,2,24,2,30,2,24,2,30,2,24,2,30,2,24,2,30,2,24,2,7,4149,196,60,67,1213,3,2,26,2,1,2,0,3,0,2,9,2,3,2,0,2,0,7,0,5,0,2,0,2,0,2,2,2,1,2,0,3,0,2,0,2,0,2,0,2,0,2,1,2,0,3,3,2,6,2,3,2,3,2,0,2,9,2,16,6,2,2,4,2,16,4421,42710,42,4148,12,221,3,5761,10591,541]; // eslint-disable-next-line comma-spacing var astralIdentifierCodes = [509,0,227,0,150,4,294,9,1368,2,2,1,6,3,41,2,5,0,166,1,1306,2,54,14,32,9,16,3,46,10,54,9,7,2,37,13,2,9,52,0,13,2,49,13,10,2,4,9,83,11,7,0,161,11,6,9,7,3,57,0,2,6,3,1,3,2,10,0,11,1,3,6,4,4,193,17,10,9,87,19,13,9,214,6,3,8,28,1,83,16,16,9,82,12,9,9,84,14,5,9,423,9,838,7,2,7,17,9,57,21,2,13,19882,9,135,4,60,6,26,9,1016,45,17,3,19723,1,5319,4,4,5,9,7,3,6,31,3,149,2,1418,49,513,54,5,49,9,0,15,0,23,4,2,14,1361,6,2,16,3,6,2,1,2,4,2214,6,110,6,6,9,792487,239]; // This has a complexity linear to the value of the code. The // assumption is that looking up astral identifier characters is // rare. function isInAstralSet(code, set) { var pos = 0x10000; for (var i = 0; i < set.length; i += 2) { pos += set[i]; if (pos > code) { return false } pos += set[i + 1]; if (pos >= code) { return true } } } // Test whether a given character code starts an identifier. function isIdentifierStart(code, astral) { if (code < 65) { return code === 36 } if (code < 91) { return true } if (code < 97) { return code === 95 } if (code < 123) { return true } if (code <= 0xffff) { return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code)) } if (astral === false) { return false } return isInAstralSet(code, astralIdentifierStartCodes) } // Test whether a given character is part of an identifier. function isIdentifierChar(code, astral) { if (code < 48) { return code === 36 } if (code < 58) { return true } if (code < 65) { return false } if (code < 91) { return true } if (code < 97) { return code === 95 } if (code < 123) { return true } if (code <= 0xffff) { return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code)) } if (astral === false) { return false } return isInAstralSet(code, astralIdentifierStartCodes) || isInAstralSet(code, astralIdentifierCodes) } // ## Token types // The assignment of fine-grained, information-carrying type objects // allows the tokenizer to store the information it has about a // token in a way that is very cheap for the parser to look up. // All token type variables start with an underscore, to make them // easy to recognize. // The `beforeExpr` property is used to disambiguate between regular // expressions and divisions. It is set on all token types that can // be followed by an expression (thus, a slash after them would be a // regular expression). // // The `startsExpr` property is used to check if the token ends a // `yield` expression. It is set on all token types that either can // directly start an expression (like a quotation mark) or can // continue an expression (like the body of a string). // // `isLoop` marks a keyword as starting a loop, which is important // to know when parsing a label, in order to allow or disallow // continue jumps to that label. var TokenType = function TokenType(label, conf) { if ( conf === void 0 ) conf = {}; this.label = label; this.keyword = conf.keyword; this.beforeExpr = !!conf.beforeExpr; this.startsExpr = !!conf.startsExpr; this.isLoop = !!conf.isLoop; this.isAssign = !!conf.isAssign; this.prefix = !!conf.prefix; this.postfix = !!conf.postfix; this.binop = conf.binop || null; this.updateContext = null; }; function binop(name, prec) { return new TokenType(name, {beforeExpr: true, binop: prec}) } var beforeExpr = {beforeExpr: true}; var startsExpr = {startsExpr: true}; // Map keyword names to token types. var keywords$1 = {}; // Succinct definitions of keyword token types function kw(name, options) { if ( options === void 0 ) options = {}; options.keyword = name; return keywords$1[name] = new TokenType(name, options) } var types = { num: new TokenType("num", startsExpr), regexp: new TokenType("regexp", startsExpr), string: new TokenType("string", startsExpr), name: new TokenType("name", startsExpr), eof: new TokenType("eof"), // Punctuation token types. bracketL: new TokenType("[", {beforeExpr: true, startsExpr: true}), bracketR: new TokenType("]"), braceL: new TokenType("{", {beforeExpr: true, startsExpr: true}), braceR: new TokenType("}"), parenL: new TokenType("(", {beforeExpr: true, startsExpr: true}), parenR: new TokenType(")"), comma: new TokenType(",", beforeExpr), semi: new TokenType(";", beforeExpr), colon: new TokenType(":", beforeExpr), dot: new TokenType("."), question: new TokenType("?", beforeExpr), arrow: new TokenType("=>", beforeExpr), template: new TokenType("template"), invalidTemplate: new TokenType("invalidTemplate"), ellipsis: new TokenType("...", beforeExpr), backQuote: new TokenType("`", startsExpr), dollarBraceL: new TokenType("${", {beforeExpr: true, startsExpr: true}), // Operators. These carry several kinds of properties to help the // parser use them properly (the presence of these properties is // what categorizes them as operators). // // `binop`, when present, specifies that this operator is a binary // operator, and will refer to its precedence. // // `prefix` and `postfix` mark the operator as a prefix or postfix // unary operator. // // `isAssign` marks all of `=`, `+=`, `-=` etcetera, which act as // binary operators with a very low precedence, that should result // in AssignmentExpression nodes. eq: new TokenType("=", {beforeExpr: true, isAssign: true}), assign: new TokenType("_=", {beforeExpr: true, isAssign: true}), incDec: new TokenType("++/--", {prefix: true, postfix: true, startsExpr: true}), prefix: new TokenType("!/~", {beforeExpr: true, prefix: true, startsExpr: true}), logicalOR: binop("||", 1), logicalAND: binop("&&", 2), bitwiseOR: binop("|", 3), bitwiseXOR: binop("^", 4), bitwiseAND: binop("&", 5), equality: binop("==/!=/===/!==", 6), relational: binop("/<=/>=", 7), bitShift: binop("<>/>>>", 8), plusMin: new TokenType("+/-", {beforeExpr: true, binop: 9, prefix: true, startsExpr: true}), modulo: binop("%", 10), star: binop("*", 10), slash: binop("/", 10), starstar: new TokenType("**", {beforeExpr: true}), // Keyword token types. _break: kw("break"), _case: kw("case", beforeExpr), _catch: kw("catch"), _continue: kw("continue"), _debugger: kw("debugger"), _default: kw("default", beforeExpr), _do: kw("do", {isLoop: true, beforeExpr: true}), _else: kw("else", beforeExpr), _finally: kw("finally"), _for: kw("for", {isLoop: true}), _function: kw("function", startsExpr), _if: kw("if"), _return: kw("return", beforeExpr), _switch: kw("switch"), _throw: kw("throw", beforeExpr), _try: kw("try"), _var: kw("var"), _const: kw("const"), _while: kw("while", {isLoop: true}), _with: kw("with"), _new: kw("new", {beforeExpr: true, startsExpr: true}), _this: kw("this", startsExpr), _super: kw("super", startsExpr), _class: kw("class", startsExpr), _extends: kw("extends", beforeExpr), _export: kw("export"), _import: kw("import"), _null: kw("null", startsExpr), _true: kw("true", startsExpr), _false: kw("false", startsExpr), _in: kw("in", {beforeExpr: true, binop: 7}), _instanceof: kw("instanceof", {beforeExpr: true, binop: 7}), _typeof: kw("typeof", {beforeExpr: true, prefix: true, startsExpr: true}), _void: kw("void", {beforeExpr: true, prefix: true, startsExpr: true}), _delete: kw("delete", {beforeExpr: true, prefix: true, startsExpr: true}) }; // Matches a whole line break (where CRLF is considered a single // line break). Used to count lines. var lineBreak = /\r\n?|\n|\u2028|\u2029/; var lineBreakG = new RegExp(lineBreak.source, "g"); function isNewLine(code) { return code === 10 || code === 13 || code === 0x2028 || code === 0x2029 } var nonASCIIwhitespace = /[\u1680\u180e\u2000-\u200a\u202f\u205f\u3000\ufeff]/; var skipWhiteSpace = /(?:\s|\/\/.*|\/\*[^]*?\*\/)*/g; var ref = Object.prototype; var hasOwnProperty = ref.hasOwnProperty; var toString = ref.toString; // Checks if an object has a property. function has(obj, propName) { return hasOwnProperty.call(obj, propName) } var isArray = Array.isArray || (function (obj) { return ( toString.call(obj) === "[object Array]" ); }); // These are used when `options.locations` is on, for the // `startLoc` and `endLoc` properties. var Position = function Position(line, col) { this.line = line; this.column = col; }; Position.prototype.offset = function offset (n) { return new Position(this.line, this.column + n) }; var SourceLocation = function SourceLocation(p, start, end) { this.start = start; this.end = end; if (p.sourceFile !== null) { this.source = p.sourceFile; } }; // The `getLineInfo` function is mostly useful when the // `locations` option is off (for performance reasons) and you // want to find the line/column position for a given character // offset. `input` should be the code string that the offset refers // into. function getLineInfo(input, offset) { for (var line = 1, cur = 0;;) { lineBreakG.lastIndex = cur; var match = lineBreakG.exec(input); if (match && match.index < offset) { ++line; cur = match.index + match[0].length; } else { return new Position(line, offset - cur) } } } // A second optional argument can be given to further configure // the parser process. These options are recognized: var defaultOptions = { // `ecmaVersion` indicates the ECMAScript version to parse. Must // be either 3, 5, 6 (2015), 7 (2016), or 8 (2017). This influences support // for strict mode, the set of reserved words, and support for // new syntax features. The default is 7. ecmaVersion: 7, // `sourceType` indicates the mode the code should be parsed in. // Can be either `"script"` or `"module"`. This influences global // strict mode and parsing of `import` and `export` declarations. sourceType: "script", // `onInsertedSemicolon` can be a callback that will be called // when a semicolon is automatically inserted. It will be passed // th position of the comma as an offset, and if `locations` is // enabled, it is given the location as a `{line, column}` object // as second argument. onInsertedSemicolon: null, // `onTrailingComma` is similar to `onInsertedSemicolon`, but for // trailing commas. onTrailingComma: null, // By default, reserved words are only enforced if ecmaVersion >= 5. // Set `allowReserved` to a boolean value to explicitly turn this on // an off. When this option has the value "never", reserved words // and keywords can also not be used as property names. allowReserved: null, // When enabled, a return at the top level is not considered an // error. allowReturnOutsideFunction: false, // When enabled, import/export statements are not constrained to // appearing at the top of the program. allowImportExportEverywhere: false, // When enabled, hashbang directive in the beginning of file // is allowed and treated as a line comment. allowHashBang: false, // When `locations` is on, `loc` properties holding objects with // `start` and `end` properties in `{line, column}` form (with // line being 1-based and column 0-based) will be attached to the // nodes. locations: false, // A function can be passed as `onToken` option, which will // cause Acorn to call that function with object in the same // format as tokens returned from `tokenizer().getToken()`. Note // that you are not allowed to call the parser from the // callback—that will corrupt its internal state. onToken: null, // A function can be passed as `onComment` option, which will // cause Acorn to call that function with `(block, text, start, // end)` parameters whenever a comment is skipped. `block` is a // boolean indicating whether this is a block (`/* */`) comment, // `text` is the content of the comment, and `start` and `end` are // character offsets that denote the start and end of the comment. // When the `locations` option is on, two more parameters are // passed, the full `{line, column}` locations of the start and // end of the comments. Note that you are not allowed to call the // parser from the callback—that will corrupt its internal state. onComment: null, // Nodes have their start and end characters offsets recorded in // `start` and `end` properties (directly on the node, rather than // the `loc` object, which holds line/column data. To also add a // [semi-standardized][range] `range` property holding a `[start, // end]` array with the same numbers, set the `ranges` option to // `true`. // // [range]: https://bugzilla.mozilla.org/show_bug.cgi?id=745678 ranges: false, // It is possible to parse multiple files into a single AST by // passing the tree produced by parsing the first file as // `program` option in subsequent parses. This will add the // toplevel forms of the parsed file to the `Program` (top) node // of an existing parse tree. program: null, // When `locations` is on, you can pass this to record the source // file in every node's `loc` object. sourceFile: null, // This value, if given, is stored in every node, whether // `locations` is on or off. directSourceFile: null, // When enabled, parenthesized expressions are represented by // (non-standard) ParenthesizedExpression nodes preserveParens: false, plugins: {} }; // Interpret and default an options object function getOptions(opts) { var options = {}; for (var opt in defaultOptions) { options[opt] = opts && has(opts, opt) ? opts[opt] : defaultOptions[opt]; } if (options.ecmaVersion >= 2015) { options.ecmaVersion -= 2009; } if (options.allowReserved == null) { options.allowReserved = options.ecmaVersion < 5; } if (isArray(options.onToken)) { var tokens = options.onToken; options.onToken = function (token) { return tokens.push(token); }; } if (isArray(options.onComment)) { options.onComment = pushComment(options, options.onComment); } return options } function pushComment(options, array) { return function(block, text, start, end, startLoc, endLoc) { var comment = { type: block ? "Block" : "Line", value: text, start: start, end: end }; if (options.locations) { comment.loc = new SourceLocation(this, startLoc, endLoc); } if (options.ranges) { comment.range = [start, end]; } array.push(comment); } } // Registered plugins var plugins = {}; function keywordRegexp(words) { return new RegExp("^(?:" + words.replace(/ /g, "|") + ")$") } var Parser = function Parser(options, input, startPos) { this.options = options = getOptions(options); this.sourceFile = options.sourceFile; this.keywords = keywordRegexp(keywords[options.ecmaVersion >= 6 ? 6 : 5]); var reserved = ""; if (!options.allowReserved) { for (var v = options.ecmaVersion;; v--) { if (reserved = reservedWords[v]) { break } } if (options.sourceType == "module") { reserved += " await"; } } this.reservedWords = keywordRegexp(reserved); var reservedStrict = (reserved ? reserved + " " : "") + reservedWords.strict; this.reservedWordsStrict = keywordRegexp(reservedStrict); this.reservedWordsStrictBind = keywordRegexp(reservedStrict + " " + reservedWords.strictBind); this.input = String(input); // Used to signal to callers of `readWord1` whether the word // contained any escape sequences. This is needed because words with // escape sequences must not be interpreted as keywords. this.containsEsc = false; // Load plugins this.loadPlugins(options.plugins); // Set up token state // The current position of the tokenizer in the input. if (startPos) { this.pos = startPos; this.lineStart = this.input.lastIndexOf("\n", startPos - 1) + 1; this.curLine = this.input.slice(0, this.lineStart).split(lineBreak).length; } else { this.pos = this.lineStart = 0; this.curLine = 1; } // Properties of the current token: // Its type this.type = types.eof; // For tokens that include more information than their type, the value this.value = null; // Its start and end offset this.start = this.end = this.pos; // And, if locations are used, the {line, column} object // corresponding to those offsets this.startLoc = this.endLoc = this.curPosition(); // Position information for the previous token this.lastTokEndLoc = this.lastTokStartLoc = null; this.lastTokStart = this.lastTokEnd = this.pos; // The context stack is used to superficially track syntactic // context to predict whether a regular expression is allowed in a // given position. this.context = this.initialContext(); this.exprAllowed = true; // Figure out if it's a module code. this.inModule = options.sourceType === "module"; this.strict = this.inModule || this.strictDirective(this.pos); // Used to signify the start of a potential arrow function this.potentialArrowAt = -1; // Flags to track whether we are in a function, a generator, an async function. this.inFunction = this.inGenerator = this.inAsync = false; // Positions to delayed-check that yield/await does not exist in default parameters. this.yieldPos = this.awaitPos = 0; // Labels in scope. this.labels = []; // If enabled, skip leading hashbang line. if (this.pos === 0 && options.allowHashBang && this.input.slice(0, 2) === "#!") { this.skipLineComment(2); } // Scope tracking for duplicate variable names (see scope.js) this.scopeStack = []; this.enterFunctionScope(); }; // DEPRECATED Kept for backwards compatibility until 3.0 in case a plugin uses them Parser.prototype.isKeyword = function isKeyword (word) { return this.keywords.test(word) }; Parser.prototype.isReservedWord = function isReservedWord (word) { return this.reservedWords.test(word) }; Parser.prototype.extend = function extend (name, f) { this[name] = f(this[name]); }; Parser.prototype.loadPlugins = function loadPlugins (pluginConfigs) { var this$1 = this; for (var name in pluginConfigs) { var plugin = plugins[name]; if (!plugin) { throw new Error("Plugin '" + name + "' not found") } plugin(this$1, pluginConfigs[name]); } }; Parser.prototype.parse = function parse () { var node = this.options.program || this.startNode(); this.nextToken(); return this.parseTopLevel(node) }; var pp = Parser.prototype; // ## Parser utilities var literal = /^(?:'((?:\\.|[^'])*?)'|"((?:\\.|[^"])*?)"|;)/; pp.strictDirective = function(start) { var this$1 = this; for (;;) { skipWhiteSpace.lastIndex = start; start += skipWhiteSpace.exec(this$1.input)[0].length; var match = literal.exec(this$1.input.slice(start)); if (!match) { return false } if ((match[1] || match[2]) == "use strict") { return true } start += match[0].length; } }; // Predicate that tests whether the next token is of the given // type, and if yes, consumes it as a side effect. pp.eat = function(type) { if (this.type === type) { this.next(); return true } else { return false } }; // Tests whether parsed token is a contextual keyword. pp.isContextual = function(name) { return this.type === types.name && this.value === name }; // Consumes contextual keyword if possible. pp.eatContextual = function(name) { return this.value === name && this.eat(types.name) }; // Asserts that following token is given contextual keyword. pp.expectContextual = function(name) { if (!this.eatContextual(name)) { this.unexpected(); } }; // Test whether a semicolon can be inserted at the current position. pp.canInsertSemicolon = function() { return this.type === types.eof || this.type === types.braceR || lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) }; pp.insertSemicolon = function() { if (this.canInsertSemicolon()) { if (this.options.onInsertedSemicolon) { this.options.onInsertedSemicolon(this.lastTokEnd, this.lastTokEndLoc); } return true } }; // Consume a semicolon, or, failing that, see if we are allowed to // pretend that there is a semicolon at this position. pp.semicolon = function() { if (!this.eat(types.semi) && !this.insertSemicolon()) { this.unexpected(); } }; pp.afterTrailingComma = function(tokType, notNext) { if (this.type == tokType) { if (this.options.onTrailingComma) { this.options.onTrailingComma(this.lastTokStart, this.lastTokStartLoc); } if (!notNext) { this.next(); } return true } }; // Expect a token of a given type. If found, consume it, otherwise, // raise an unexpected token error. pp.expect = function(type) { this.eat(type) || this.unexpected(); }; // Raise an unexpected token error. pp.unexpected = function(pos) { this.raise(pos != null ? pos : this.start, "Unexpected token"); }; function DestructuringErrors() { this.shorthandAssign = this.trailingComma = this.parenthesizedAssign = this.parenthesizedBind = -1; } pp.checkPatternErrors = function(refDestructuringErrors, isAssign) { if (!refDestructuringErrors) { return } if (refDestructuringErrors.trailingComma > -1) { this.raiseRecoverable(refDestructuringErrors.trailingComma, "Comma is not permitted after the rest element"); } var parens = isAssign ? refDestructuringErrors.parenthesizedAssign : refDestructuringErrors.parenthesizedBind; if (parens > -1) { this.raiseRecoverable(parens, "Parenthesized pattern"); } }; pp.checkExpressionErrors = function(refDestructuringErrors, andThrow) { var pos = refDestructuringErrors ? refDestructuringErrors.shorthandAssign : -1; if (!andThrow) { return pos >= 0 } if (pos > -1) { this.raise(pos, "Shorthand property assignments are valid only in destructuring patterns"); } }; pp.checkYieldAwaitInDefaultParams = function() { if (this.yieldPos && (!this.awaitPos || this.yieldPos < this.awaitPos)) { this.raise(this.yieldPos, "Yield expression cannot be a default value"); } if (this.awaitPos) { this.raise(this.awaitPos, "Await expression cannot be a default value"); } }; pp.isSimpleAssignTarget = function(expr) { if (expr.type === "ParenthesizedExpression") { return this.isSimpleAssignTarget(expr.expression) } return expr.type === "Identifier" || expr.type === "MemberExpression" }; var pp$1 = Parser.prototype; // ### Statement parsing // Parse a program. Initializes the parser, reads any number of // statements, and wraps them in a Program node. Optionally takes a // `program` argument. If present, the statements will be appended // to its body instead of creating a new node. pp$1.parseTopLevel = function(node) { var this$1 = this; var exports = {}; if (!node.body) { node.body = []; } while (this.type !== types.eof) { var stmt = this$1.parseStatement(true, true, exports); node.body.push(stmt); } this.adaptDirectivePrologue(node.body); this.next(); if (this.options.ecmaVersion >= 6) { node.sourceType = this.options.sourceType; } return this.finishNode(node, "Program") }; var loopLabel = {kind: "loop"}; var switchLabel = {kind: "switch"}; pp$1.isLet = function() { if (this.type !== types.name || this.options.ecmaVersion < 6 || this.value != "let") { return false } skipWhiteSpace.lastIndex = this.pos; var skip = skipWhiteSpace.exec(this.input); var next = this.pos + skip[0].length, nextCh = this.input.charCodeAt(next); if (nextCh === 91 || nextCh == 123) { return true } // '{' and '[' if (isIdentifierStart(nextCh, true)) { var pos = next + 1; while (isIdentifierChar(this.input.charCodeAt(pos), true)) { ++pos; } var ident = this.input.slice(next, pos); if (!this.isKeyword(ident)) { return true } } return false }; // check 'async [no LineTerminator here] function' // - 'async /*foo*/ function' is OK. // - 'async /*\n*/ function' is invalid. pp$1.isAsyncFunction = function() { if (this.type !== types.name || this.options.ecmaVersion < 8 || this.value != "async") { return false } skipWhiteSpace.lastIndex = this.pos; var skip = skipWhiteSpace.exec(this.input); var next = this.pos + skip[0].length; return !lineBreak.test(this.input.slice(this.pos, next)) && this.input.slice(next, next + 8) === "function" && (next + 8 == this.input.length || !isIdentifierChar(this.input.charAt(next + 8))) }; // Parse a single statement. // // If expecting a statement and finding a slash operator, parse a // regular expression literal. This is to handle cases like // `if (foo) /blah/.exec(foo)`, where looking at the previous token // does not help. pp$1.parseStatement = function(declaration, topLevel, exports) { var starttype = this.type, node = this.startNode(), kind; if (this.isLet()) { starttype = types._var; kind = "let"; } // Most types of statements are recognized by the keyword they // start with. Many are trivial to parse, some require a bit of // complexity. switch (starttype) { case types._break: case types._continue: return this.parseBreakContinueStatement(node, starttype.keyword) case types._debugger: return this.parseDebuggerStatement(node) case types._do: return this.parseDoStatement(node) case types._for: return this.parseForStatement(node) case types._function: if (!declaration && this.options.ecmaVersion >= 6) { this.unexpected(); } return this.parseFunctionStatement(node, false) case types._class: if (!declaration) { this.unexpected(); } return this.parseClass(node, true) case types._if: return this.parseIfStatement(node) case types._return: return this.parseReturnStatement(node) case types._switch: return this.parseSwitchStatement(node) case types._throw: return this.parseThrowStatement(node) case types._try: return this.parseTryStatement(node) case types._const: case types._var: kind = kind || this.value; if (!declaration && kind != "var") { this.unexpected(); } return this.parseVarStatement(node, kind) case types._while: return this.parseWhileStatement(node) case types._with: return this.parseWithStatement(node) case types.braceL: return this.parseBlock() case types.semi: return this.parseEmptyStatement(node) case types._export: case types._import: if (!this.options.allowImportExportEverywhere) { if (!topLevel) { this.raise(this.start, "'import' and 'export' may only appear at the top level"); } if (!this.inModule) { this.raise(this.start, "'import' and 'export' may appear only with 'sourceType: module'"); } } return starttype === types._import ? this.parseImport(node) : this.parseExport(node, exports) // If the statement does not start with a statement keyword or a // brace, it's an ExpressionStatement or LabeledStatement. We // simply start parsing an expression, and afterwards, if the // next token is a colon and the expression was a simple // Identifier node, we switch to interpreting it as a label. default: if (this.isAsyncFunction() && declaration) { this.next(); return this.parseFunctionStatement(node, true) } var maybeName = this.value, expr = this.parseExpression(); if (starttype === types.name && expr.type === "Identifier" && this.eat(types.colon)) { return this.parseLabeledStatement(node, maybeName, expr) } else { return this.parseExpressionStatement(node, expr) } } }; pp$1.parseBreakContinueStatement = function(node, keyword) { var this$1 = this; var isBreak = keyword == "break"; this.next(); if (this.eat(types.semi) || this.insertSemicolon()) { node.label = null; } else if (this.type !== types.name) { this.unexpected(); } else { node.label = this.parseIdent(); this.semicolon(); } // Verify that there is an actual destination to break or // continue to. var i = 0; for (; i < this.labels.length; ++i) { var lab = this$1.labels[i]; if (node.label == null || lab.name === node.label.name) { if (lab.kind != null && (isBreak || lab.kind === "loop")) { break } if (node.label && isBreak) { break } } } if (i === this.labels.length) { this.raise(node.start, "Unsyntactic " + keyword); } return this.finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement") }; pp$1.parseDebuggerStatement = function(node) { this.next(); this.semicolon(); return this.finishNode(node, "DebuggerStatement") }; pp$1.parseDoStatement = function(node) { this.next(); this.labels.push(loopLabel); node.body = this.parseStatement(false); this.labels.pop(); this.expect(types._while); node.test = this.parseParenExpression(); if (this.options.ecmaVersion >= 6) { this.eat(types.semi); } else { this.semicolon(); } return this.finishNode(node, "DoWhileStatement") }; // Disambiguating between a `for` and a `for`/`in` or `for`/`of` // loop is non-trivial. Basically, we have to parse the init `var` // statement or expression, disallowing the `in` operator (see // the second parameter to `parseExpression`), and then check // whether the next token is `in` or `of`. When there is no init // part (semicolon immediately after the opening parenthesis), it // is a regular `for` loop. pp$1.parseForStatement = function(node) { this.next(); this.labels.push(loopLabel); this.enterLexicalScope(); this.expect(types.parenL); if (this.type === types.semi) { return this.parseFor(node, null) } var isLet = this.isLet(); if (this.type === types._var || this.type === types._const || isLet) { var init$1 = this.startNode(), kind = isLet ? "let" : this.value; this.next(); this.parseVar(init$1, true, kind); this.finishNode(init$1, "VariableDeclaration"); if ((this.type === types._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) && init$1.declarations.length === 1 && !(kind !== "var" && init$1.declarations[0].init)) { return this.parseForIn(node, init$1) } return this.parseFor(node, init$1) } var refDestructuringErrors = new DestructuringErrors; var init = this.parseExpression(true, refDestructuringErrors); if (this.type === types._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) { this.toAssignable(init); this.checkLVal(init); this.checkPatternErrors(refDestructuringErrors, true); return this.parseForIn(node, init) } else { this.checkExpressionErrors(refDestructuringErrors, true); } return this.parseFor(node, init) }; pp$1.parseFunctionStatement = function(node, isAsync) { this.next(); return this.parseFunction(node, true, false, isAsync) }; pp$1.isFunction = function() { return this.type === types._function || this.isAsyncFunction() }; pp$1.parseIfStatement = function(node) { this.next(); node.test = this.parseParenExpression(); // allow function declarations in branches, but only in non-strict mode node.consequent = this.parseStatement(!this.strict && this.isFunction()); node.alternate = this.eat(types._else) ? this.parseStatement(!this.strict && this.isFunction()) : null; return this.finishNode(node, "IfStatement") }; pp$1.parseReturnStatement = function(node) { if (!this.inFunction && !this.options.allowReturnOutsideFunction) { this.raise(this.start, "'return' outside of function"); } this.next(); // In `return` (and `break`/`continue`), the keywords with // optional arguments, we eagerly look for a semicolon or the // possibility to insert one. if (this.eat(types.semi) || this.insertSemicolon()) { node.argument = null; } else { node.argument = this.parseExpression(); this.semicolon(); } return this.finishNode(node, "ReturnStatement") }; pp$1.parseSwitchStatement = function(node) { var this$1 = this; this.next(); node.discriminant = this.parseParenExpression(); node.cases = []; this.expect(types.braceL); this.labels.push(switchLabel); this.enterLexicalScope(); // Statements under must be grouped (by label) in SwitchCase // nodes. `cur` is used to keep the node that we are currently // adding statements to. var cur; for (var sawDefault = false; this.type != types.braceR;) { if (this$1.type === types._case || this$1.type === types._default) { var isCase = this$1.type === types._case; if (cur) { this$1.finishNode(cur, "SwitchCase"); } node.cases.push(cur = this$1.startNode()); cur.consequent = []; this$1.next(); if (isCase) { cur.test = this$1.parseExpression(); } else { if (sawDefault) { this$1.raiseRecoverable(this$1.lastTokStart, "Multiple default clauses"); } sawDefault = true; cur.test = null; } this$1.expect(types.colon); } else { if (!cur) { this$1.unexpected(); } cur.consequent.push(this$1.parseStatement(true)); } } this.exitLexicalScope(); if (cur) { this.finishNode(cur, "SwitchCase"); } this.next(); // Closing brace this.labels.pop(); return this.finishNode(node, "SwitchStatement") }; pp$1.parseThrowStatement = function(node) { this.next(); if (lineBreak.test(this.input.slice(this.lastTokEnd, this.start))) { this.raise(this.lastTokEnd, "Illegal newline after throw"); } node.argument = this.parseExpression(); this.semicolon(); return this.finishNode(node, "ThrowStatement") }; // Reused empty array added for node fields that are always empty. var empty = []; pp$1.parseTryStatement = function(node) { this.next(); node.block = this.parseBlock(); node.handler = null; if (this.type === types._catch) { var clause = this.startNode(); this.next(); this.expect(types.parenL); clause.param = this.parseBindingAtom(); this.enterLexicalScope(); this.checkLVal(clause.param, "let"); this.expect(types.parenR); clause.body = this.parseBlock(false); this.exitLexicalScope(); node.handler = this.finishNode(clause, "CatchClause"); } node.finalizer = this.eat(types._finally) ? this.parseBlock() : null; if (!node.handler && !node.finalizer) { this.raise(node.start, "Missing catch or finally clause"); } return this.finishNode(node, "TryStatement") }; pp$1.parseVarStatement = function(node, kind) { this.next(); this.parseVar(node, false, kind); this.semicolon(); return this.finishNode(node, "VariableDeclaration") }; pp$1.parseWhileStatement = function(node) { this.next(); node.test = this.parseParenExpression(); this.labels.push(loopLabel); node.body = this.parseStatement(false); this.labels.pop(); return this.finishNode(node, "WhileStatement") }; pp$1.parseWithStatement = function(node) { if (this.strict) { this.raise(this.start, "'with' in strict mode"); } this.next(); node.object = this.parseParenExpression(); node.body = this.parseStatement(false); return this.finishNode(node, "WithStatement") }; pp$1.parseEmptyStatement = function(node) { this.next(); return this.finishNode(node, "EmptyStatement") }; pp$1.parseLabeledStatement = function(node, maybeName, expr) { var this$1 = this; for (var i$1 = 0, list = this$1.labels; i$1 < list.length; i$1 += 1) { var label = list[i$1]; if (label.name === maybeName) { this$1.raise(expr.start, "Label '" + maybeName + "' is already declared"); } } var kind = this.type.isLoop ? "loop" : this.type === types._switch ? "switch" : null; for (var i = this.labels.length - 1; i >= 0; i--) { var label$1 = this$1.labels[i]; if (label$1.statementStart == node.start) { label$1.statementStart = this$1.start; label$1.kind = kind; } else { break } } this.labels.push({name: maybeName, kind: kind, statementStart: this.start}); node.body = this.parseStatement(true); if (node.body.type == "ClassDeclaration" || node.body.type == "VariableDeclaration" && node.body.kind != "var" || node.body.type == "FunctionDeclaration" && (this.strict || node.body.generator)) { this.raiseRecoverable(node.body.start, "Invalid labeled declaration"); } this.labels.pop(); node.label = expr; return this.finishNode(node, "LabeledStatement") }; pp$1.parseExpressionStatement = function(node, expr) { node.expression = expr; this.semicolon(); return this.finishNode(node, "ExpressionStatement") }; // Parse a semicolon-enclosed block of statements, handling `"use // strict"` declarations when `allowStrict` is true (used for // function bodies). pp$1.parseBlock = function(createNewLexicalScope) { var this$1 = this; if ( createNewLexicalScope === void 0 ) createNewLexicalScope = true; var node = this.startNode(); node.body = []; this.expect(types.braceL); if (createNewLexicalScope) { this.enterLexicalScope(); } while (!this.eat(types.braceR)) { var stmt = this$1.parseStatement(true); node.body.push(stmt); } if (createNewLexicalScope) { this.exitLexicalScope(); } return this.finishNode(node, "BlockStatement") }; // Parse a regular `for` loop. The disambiguation code in // `parseStatement` will already have parsed the init statement or // expression. pp$1.parseFor = function(node, init) { node.init = init; this.expect(types.semi); node.test = this.type === types.semi ? null : this.parseExpression(); this.expect(types.semi); node.update = this.type === types.parenR ? null : this.parseExpression(); this.expect(types.parenR); this.exitLexicalScope(); node.body = this.parseStatement(false); this.labels.pop(); return this.finishNode(node, "ForStatement") }; // Parse a `for`/`in` and `for`/`of` loop, which are almost // same from parser's perspective. pp$1.parseForIn = function(node, init) { var type = this.type === types._in ? "ForInStatement" : "ForOfStatement"; this.next(); node.left = init; node.right = this.parseExpression(); this.expect(types.parenR); this.exitLexicalScope(); node.body = this.parseStatement(false); this.labels.pop(); return this.finishNode(node, type) }; // Parse a list of variable declarations. pp$1.parseVar = function(node, isFor, kind) { var this$1 = this; node.declarations = []; node.kind = kind; for (;;) { var decl = this$1.startNode(); this$1.parseVarId(decl, kind); if (this$1.eat(types.eq)) { decl.init = this$1.parseMaybeAssign(isFor); } else if (kind === "const" && !(this$1.type === types._in || (this$1.options.ecmaVersion >= 6 && this$1.isContextual("of")))) { this$1.unexpected(); } else if (decl.id.type != "Identifier" && !(isFor && (this$1.type === types._in || this$1.isContextual("of")))) { this$1.raise(this$1.lastTokEnd, "Complex binding patterns require an initialization value"); } else { decl.init = null; } node.declarations.push(this$1.finishNode(decl, "VariableDeclarator")); if (!this$1.eat(types.comma)) { break } } return node }; pp$1.parseVarId = function(decl, kind) { decl.id = this.parseBindingAtom(kind); this.checkLVal(decl.id, kind, false); }; // Parse a function declaration or literal (depending on the // `isStatement` parameter). pp$1.parseFunction = function(node, isStatement, allowExpressionBody, isAsync) { this.initFunction(node); if (this.options.ecmaVersion >= 6 && !isAsync) { node.generator = this.eat(types.star); } if (this.options.ecmaVersion >= 8) { node.async = !!isAsync; } if (isStatement) { node.id = isStatement === "nullableID" && this.type != types.name ? null : this.parseIdent(); if (node.id) { this.checkLVal(node.id, "var"); } } var oldInGen = this.inGenerator, oldInAsync = this.inAsync, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldInFunc = this.inFunction; this.inGenerator = node.generator; this.inAsync = node.async; this.yieldPos = 0; this.awaitPos = 0; this.inFunction = true; this.enterFunctionScope(); if (!isStatement) { node.id = this.type == types.name ? this.parseIdent() : null; } this.parseFunctionParams(node); this.parseFunctionBody(node, allowExpressionBody); this.inGenerator = oldInGen; this.inAsync = oldInAsync; this.yieldPos = oldYieldPos; this.awaitPos = oldAwaitPos; this.inFunction = oldInFunc; return this.finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression") }; pp$1.parseFunctionParams = function(node) { this.expect(types.parenL); node.params = this.parseBindingList(types.parenR, false, this.options.ecmaVersion >= 8); this.checkYieldAwaitInDefaultParams(); }; // Parse a class declaration or literal (depending on the // `isStatement` parameter). pp$1.parseClass = function(node, isStatement) { var this$1 = this; this.next(); this.parseClassId(node, isStatement); this.parseClassSuper(node); var classBody = this.startNode(); var hadConstructor = false; classBody.body = []; this.expect(types.braceL); while (!this.eat(types.braceR)) { if (this$1.eat(types.semi)) { continue } var method = this$1.startNode(); var isGenerator = this$1.eat(types.star); var isAsync = false; var isMaybeStatic = this$1.type === types.name && this$1.value === "static"; this$1.parsePropertyName(method); method.static = isMaybeStatic && this$1.type !== types.parenL; if (method.static) { if (isGenerator) { this$1.unexpected(); } isGenerator = this$1.eat(types.star); this$1.parsePropertyName(method); } if (this$1.options.ecmaVersion >= 8 && !isGenerator && !method.computed && method.key.type === "Identifier" && method.key.name === "async" && this$1.type !== types.parenL && !this$1.canInsertSemicolon()) { isAsync = true; this$1.parsePropertyName(method); } method.kind = "method"; var isGetSet = false; if (!method.computed) { var key = method.key; if (!isGenerator && !isAsync && key.type === "Identifier" && this$1.type !== types.parenL && (key.name === "get" || key.name === "set")) { isGetSet = true; method.kind = key.name; key = this$1.parsePropertyName(method); } if (!method.static && (key.type === "Identifier" && key.name === "constructor" || key.type === "Literal" && key.value === "constructor")) { if (hadConstructor) { this$1.raise(key.start, "Duplicate constructor in the same class"); } if (isGetSet) { this$1.raise(key.start, "Constructor can't have get/set modifier"); } if (isGenerator) { this$1.raise(key.start, "Constructor can't be a generator"); } if (isAsync) { this$1.raise(key.start, "Constructor can't be an async method"); } method.kind = "constructor"; hadConstructor = true; } } this$1.parseClassMethod(classBody, method, isGenerator, isAsync); if (isGetSet) { var paramCount = method.kind === "get" ? 0 : 1; if (method.value.params.length !== paramCount) { var start = method.value.start; if (method.kind === "get") { this$1.raiseRecoverable(start, "getter should have no params"); } else { this$1.raiseRecoverable(start, "setter should have exactly one param"); } } else { if (method.kind === "set" && method.value.params[0].type === "RestElement") { this$1.raiseRecoverable(method.value.params[0].start, "Setter cannot use rest params"); } } } } node.body = this.finishNode(classBody, "ClassBody"); return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression") }; pp$1.parseClassMethod = function(classBody, method, isGenerator, isAsync) { method.value = this.parseMethod(isGenerator, isAsync); classBody.body.push(this.finishNode(method, "MethodDefinition")); }; pp$1.parseClassId = function(node, isStatement) { node.id = this.type === types.name ? this.parseIdent() : isStatement === true ? this.unexpected() : null; }; pp$1.parseClassSuper = function(node) { node.superClass = this.eat(types._extends) ? this.parseExprSubscripts() : null; }; // Parses module export declaration. pp$1.parseExport = function(node, exports) { var this$1 = this; this.next(); // export * from '...' if (this.eat(types.star)) { this.expectContextual("from"); node.source = this.type === types.string ? this.parseExprAtom() : this.unexpected(); this.semicolon(); return this.finishNode(node, "ExportAllDeclaration") } if (this.eat(types._default)) { // export default ... this.checkExport(exports, "default", this.lastTokStart); var isAsync; if (this.type === types._function || (isAsync = this.isAsyncFunction())) { var fNode = this.startNode(); this.next(); if (isAsync) { this.next(); } node.declaration = this.parseFunction(fNode, "nullableID", false, isAsync); } else if (this.type === types._class) { var cNode = this.startNode(); node.declaration = this.parseClass(cNode, "nullableID"); } else { node.declaration = this.parseMaybeAssign(); this.semicolon(); } return this.finishNode(node, "ExportDefaultDeclaration") } // export var|const|let|function|class ... if (this.shouldParseExportStatement()) { node.declaration = this.parseStatement(true); if (node.declaration.type === "VariableDeclaration") { this.checkVariableExport(exports, node.declaration.declarations); } else { this.checkExport(exports, node.declaration.id.name, node.declaration.id.start); } node.specifiers = []; node.source = null; } else { // export { x, y as z } [from '...'] node.declaration = null; node.specifiers = this.parseExportSpecifiers(exports); if (this.eatContextual("from")) { node.source = this.type === types.string ? this.parseExprAtom() : this.unexpected(); } else { // check for keywords used as local names for (var i = 0, list = node.specifiers; i < list.length; i += 1) { var spec = list[i]; this$1.checkUnreserved(spec.local); } node.source = null; } this.semicolon(); } return this.finishNode(node, "ExportNamedDeclaration") }; pp$1.checkExport = function(exports, name, pos) { if (!exports) { return } if (has(exports, name)) { this.raiseRecoverable(pos, "Duplicate export '" + name + "'"); } exports[name] = true; }; pp$1.checkPatternExport = function(exports, pat) { var this$1 = this; var type = pat.type; if (type == "Identifier") { this.checkExport(exports, pat.name, pat.start); } else if (type == "ObjectPattern") { for (var i = 0, list = pat.properties; i < list.length; i += 1) { var prop = list[i]; this$1.checkPatternExport(exports, prop.value); } } else if (type == "ArrayPattern") { for (var i$1 = 0, list$1 = pat.elements; i$1 < list$1.length; i$1 += 1) { var elt = list$1[i$1]; if (elt) { this$1.checkPatternExport(exports, elt); } } } else if (type == "AssignmentPattern") { this.checkPatternExport(exports, pat.left); } else if (type == "ParenthesizedExpression") { this.checkPatternExport(exports, pat.expression); } }; pp$1.checkVariableExport = function(exports, decls) { var this$1 = this; if (!exports) { return } for (var i = 0, list = decls; i < list.length; i += 1) { var decl = list[i]; this$1.checkPatternExport(exports, decl.id); } }; pp$1.shouldParseExportStatement = function() { return this.type.keyword === "var" || this.type.keyword === "const" || this.type.keyword === "class" || this.type.keyword === "function" || this.isLet() || this.isAsyncFunction() }; // Parses a comma-separated list of module exports. pp$1.parseExportSpecifiers = function(exports) { var this$1 = this; var nodes = [], first = true; // export { x, y as z } [from '...'] this.expect(types.braceL); while (!this.eat(types.braceR)) { if (!first) { this$1.expect(types.comma); if (this$1.afterTrailingComma(types.braceR)) { break } } else { first = false; } var node = this$1.startNode(); node.local = this$1.parseIdent(true); node.exported = this$1.eatContextual("as") ? this$1.parseIdent(true) : node.local; this$1.checkExport(exports, node.exported.name, node.exported.start); nodes.push(this$1.finishNode(node, "ExportSpecifier")); } return nodes }; // Parses import declaration. pp$1.parseImport = function(node) { this.next(); // import '...' if (this.type === types.string) { node.specifiers = empty; node.source = this.parseExprAtom(); } else { node.specifiers = this.parseImportSpecifiers(); this.expectContextual("from"); node.source = this.type === types.string ? this.parseExprAtom() : this.unexpected(); } this.semicolon(); return this.finishNode(node, "ImportDeclaration") }; // Parses a comma-separated list of module imports. pp$1.parseImportSpecifiers = function() { var this$1 = this; var nodes = [], first = true; if (this.type === types.name) { // import defaultObj, { x, y as z } from '...' var node = this.startNode(); node.local = this.parseIdent(); this.checkLVal(node.local, "let"); nodes.push(this.finishNode(node, "ImportDefaultSpecifier")); if (!this.eat(types.comma)) { return nodes } } if (this.type === types.star) { var node$1 = this.startNode(); this.next(); this.expectContextual("as"); node$1.local = this.parseIdent(); this.checkLVal(node$1.local, "let"); nodes.push(this.finishNode(node$1, "ImportNamespaceSpecifier")); return nodes } this.expect(types.braceL); while (!this.eat(types.braceR)) { if (!first) { this$1.expect(types.comma); if (this$1.afterTrailingComma(types.braceR)) { break } } else { first = false; } var node$2 = this$1.startNode(); node$2.imported = this$1.parseIdent(true); if (this$1.eatContextual("as")) { node$2.local = this$1.parseIdent(); } else { this$1.checkUnreserved(node$2.imported); node$2.local = node$2.imported; } this$1.checkLVal(node$2.local, "let"); nodes.push(this$1.finishNode(node$2, "ImportSpecifier")); } return nodes }; // Set `ExpressionStatement#directive` property for directive prologues. pp$1.adaptDirectivePrologue = function(statements) { for (var i = 0; i < statements.length && this.isDirectiveCandidate(statements[i]); ++i) { statements[i].directive = statements[i].expression.raw.slice(1, -1); } }; pp$1.isDirectiveCandidate = function(statement) { return ( statement.type === "ExpressionStatement" && statement.expression.type === "Literal" && typeof statement.expression.value === "string" && // Reject parenthesized strings. (this.input[statement.start] === "\"" || this.input[statement.start] === "'") ) }; var pp$2 = Parser.prototype; // Convert existing expression atom to assignable pattern // if possible. pp$2.toAssignable = function(node, isBinding) { var this$1 = this; if (this.options.ecmaVersion >= 6 && node) { switch (node.type) { case "Identifier": if (this.inAsync && node.name === "await") { this.raise(node.start, "Can not use 'await' as identifier inside an async function"); } break case "ObjectPattern": case "ArrayPattern": break case "ObjectExpression": node.type = "ObjectPattern"; for (var i = 0, list = node.properties; i < list.length; i += 1) { var prop = list[i]; if (prop.kind !== "init") { this$1.raise(prop.key.start, "Object pattern can't contain getter or setter"); } this$1.toAssignable(prop.value, isBinding); } break case "ArrayExpression": node.type = "ArrayPattern"; this.toAssignableList(node.elements, isBinding); break case "AssignmentExpression": if (node.operator === "=") { node.type = "AssignmentPattern"; delete node.operator; this.toAssignable(node.left, isBinding); // falls through to AssignmentPattern } else { this.raise(node.left.end, "Only '=' operator can be used for specifying default value."); break } case "AssignmentPattern": break case "ParenthesizedExpression": this.toAssignable(node.expression, isBinding); break case "MemberExpression": if (!isBinding) { break } default: this.raise(node.start, "Assigning to rvalue"); } } return node }; // Convert list of expression atoms to binding list. pp$2.toAssignableList = function(exprList, isBinding) { var this$1 = this; var end = exprList.length; if (end) { var last = exprList[end - 1]; if (last && last.type == "RestElement") { --end; } else if (last && last.type == "SpreadElement") { last.type = "RestElement"; var arg = last.argument; this.toAssignable(arg, isBinding); --end; } if (this.options.ecmaVersion === 6 && isBinding && last && last.type === "RestElement" && last.argument.type !== "Identifier") { this.unexpected(last.argument.start); } } for (var i = 0; i < end; i++) { var elt = exprList[i]; if (elt) { this$1.toAssignable(elt, isBinding); } } return exprList }; // Parses spread element. pp$2.parseSpread = function(refDestructuringErrors) { var node = this.startNode(); this.next(); node.argument = this.parseMaybeAssign(false, refDestructuringErrors); return this.finishNode(node, "SpreadElement") }; pp$2.parseRestBinding = function() { var node = this.startNode(); this.next(); // RestElement inside of a function parameter must be an identifier if (this.options.ecmaVersion === 6 && this.type !== types.name) { this.unexpected(); } node.argument = this.parseBindingAtom(); return this.finishNode(node, "RestElement") }; // Parses lvalue (assignable) atom. pp$2.parseBindingAtom = function() { if (this.options.ecmaVersion >= 6) { switch (this.type) { case types.bracketL: var node = this.startNode(); this.next(); node.elements = this.parseBindingList(types.bracketR, true, true); return this.finishNode(node, "ArrayPattern") case types.braceL: return this.parseObj(true) } } return this.parseIdent() }; pp$2.parseBindingList = function(close, allowEmpty, allowTrailingComma) { var this$1 = this; var elts = [], first = true; while (!this.eat(close)) { if (first) { first = false; } else { this$1.expect(types.comma); } if (allowEmpty && this$1.type === types.comma) { elts.push(null); } else if (allowTrailingComma && this$1.afterTrailingComma(close)) { break } else if (this$1.type === types.ellipsis) { var rest = this$1.parseRestBinding(); this$1.parseBindingListItem(rest); elts.push(rest); if (this$1.type === types.comma) { this$1.raise(this$1.start, "Comma is not permitted after the rest element"); } this$1.expect(close); break } else { var elem = this$1.parseMaybeDefault(this$1.start, this$1.startLoc); this$1.parseBindingListItem(elem); elts.push(elem); } } return elts }; pp$2.parseBindingListItem = function(param) { return param }; // Parses assignment pattern around given atom if possible. pp$2.parseMaybeDefault = function(startPos, startLoc, left) { left = left || this.parseBindingAtom(); if (this.options.ecmaVersion < 6 || !this.eat(types.eq)) { return left } var node = this.startNodeAt(startPos, startLoc); node.left = left; node.right = this.parseMaybeAssign(); return this.finishNode(node, "AssignmentPattern") }; // Verify that a node is an lval — something that can be assigned // to. // bindingType can be either: // 'var' indicating that the lval creates a 'var' binding // 'let' indicating that the lval creates a lexical ('let' or 'const') binding // 'none' indicating that the binding should be checked for illegal identifiers, but not for duplicate references pp$2.checkLVal = function(expr, bindingType, checkClashes) { var this$1 = this; switch (expr.type) { case "Identifier": if (this.strict && this.reservedWordsStrictBind.test(expr.name)) { this.raiseRecoverable(expr.start, (bindingType ? "Binding " : "Assigning to ") + expr.name + " in strict mode"); } if (checkClashes) { if (has(checkClashes, expr.name)) { this.raiseRecoverable(expr.start, "Argument name clash"); } checkClashes[expr.name] = true; } if (bindingType && bindingType !== "none") { if ( bindingType === "var" && !this.canDeclareVarName(expr.name) || bindingType !== "var" && !this.canDeclareLexicalName(expr.name) ) { this.raiseRecoverable(expr.start, ("Identifier '" + (expr.name) + "' has already been declared")); } if (bindingType === "var") { this.declareVarName(expr.name); } else { this.declareLexicalName(expr.name); } } break case "MemberExpression": if (bindingType) { this.raiseRecoverable(expr.start, (bindingType ? "Binding" : "Assigning to") + " member expression"); } break case "ObjectPattern": for (var i = 0, list = expr.properties; i < list.length; i += 1) { var prop = list[i]; this$1.checkLVal(prop.value, bindingType, checkClashes); } break case "ArrayPattern": for (var i$1 = 0, list$1 = expr.elements; i$1 < list$1.length; i$1 += 1) { var elem = list$1[i$1]; if (elem) { this$1.checkLVal(elem, bindingType, checkClashes); } } break case "AssignmentPattern": this.checkLVal(expr.left, bindingType, checkClashes); break case "RestElement": this.checkLVal(expr.argument, bindingType, checkClashes); break case "ParenthesizedExpression": this.checkLVal(expr.expression, bindingType, checkClashes); break default: this.raise(expr.start, (bindingType ? "Binding" : "Assigning to") + " rvalue"); } }; // A recursive descent parser operates by defining functions for all // syntactic elements, and recursively calling those, each function // advancing the input stream and returning an AST node. Precedence // of constructs (for example, the fact that `!x[1]` means `!(x[1])` // instead of `(!x)[1]` is handled by the fact that the parser // function that parses unary prefix operators is called first, and // in turn calls the function that parses `[]` subscripts — that // way, it'll receive the node for `x[1]` already parsed, and wraps // *that* in the unary operator node. // // Acorn uses an [operator precedence parser][opp] to handle binary // operator precedence, because it is much more compact than using // the technique outlined above, which uses different, nesting // functions to specify precedence, for all of the ten binary // precedence levels that JavaScript defines. // // [opp]: http://en.wikipedia.org/wiki/Operator-precedence_parser var pp$3 = Parser.prototype; // Check if property name clashes with already added. // Object/class getters and setters are not allowed to clash — // either with each other or with an init property — and in // strict mode, init properties are also not allowed to be repeated. pp$3.checkPropClash = function(prop, propHash) { if (this.options.ecmaVersion >= 6 && (prop.computed || prop.method || prop.shorthand)) { return } var key = prop.key; var name; switch (key.type) { case "Identifier": name = key.name; break case "Literal": name = String(key.value); break default: return } var kind = prop.kind; if (this.options.ecmaVersion >= 6) { if (name === "__proto__" && kind === "init") { if (propHash.proto) { this.raiseRecoverable(key.start, "Redefinition of __proto__ property"); } propHash.proto = true; } return } name = "$" + name; var other = propHash[name]; if (other) { var redefinition; if (kind === "init") { redefinition = this.strict && other.init || other.get || other.set; } else { redefinition = other.init || other[kind]; } if (redefinition) { this.raiseRecoverable(key.start, "Redefinition of property"); } } else { other = propHash[name] = { init: false, get: false, set: false }; } other[kind] = true; }; // ### Expression parsing // These nest, from the most general expression type at the top to // 'atomic', nondivisible expression types at the bottom. Most of // the functions will simply let the function(s) below them parse, // and, *if* the syntactic construct they handle is present, wrap // the AST node that the inner parser gave them in another node. // Parse a full expression. The optional arguments are used to // forbid the `in` operator (in for loops initalization expressions) // and provide reference for storing '=' operator inside shorthand // property assignment in contexts where both object expression // and object pattern might appear (so it's possible to raise // delayed syntax error at correct position). pp$3.parseExpression = function(noIn, refDestructuringErrors) { var this$1 = this; var startPos = this.start, startLoc = this.startLoc; var expr = this.parseMaybeAssign(noIn, refDestructuringErrors); if (this.type === types.comma) { var node = this.startNodeAt(startPos, startLoc); node.expressions = [expr]; while (this.eat(types.comma)) { node.expressions.push(this$1.parseMaybeAssign(noIn, refDestructuringErrors)); } return this.finishNode(node, "SequenceExpression") } return expr }; // Parse an assignment expression. This includes applications of // operators like `+=`. pp$3.parseMaybeAssign = function(noIn, refDestructuringErrors, afterLeftParse) { if (this.inGenerator && this.isContextual("yield")) { return this.parseYield() } var ownDestructuringErrors = false, oldParenAssign = -1, oldTrailingComma = -1; if (refDestructuringErrors) { oldParenAssign = refDestructuringErrors.parenthesizedAssign; oldTrailingComma = refDestructuringErrors.trailingComma; refDestructuringErrors.parenthesizedAssign = refDestructuringErrors.trailingComma = -1; } else { refDestructuringErrors = new DestructuringErrors; ownDestructuringErrors = true; } var startPos = this.start, startLoc = this.startLoc; if (this.type == types.parenL || this.type == types.name) { this.potentialArrowAt = this.start; } var left = this.parseMaybeConditional(noIn, refDestructuringErrors); if (afterLeftParse) { left = afterLeftParse.call(this, left, startPos, startLoc); } if (this.type.isAssign) { this.checkPatternErrors(refDestructuringErrors, true); if (!ownDestructuringErrors) { DestructuringErrors.call(refDestructuringErrors); } var node = this.startNodeAt(startPos, startLoc); node.operator = this.value; node.left = this.type === types.eq ? this.toAssignable(left) : left; refDestructuringErrors.shorthandAssign = -1; // reset because shorthand default was used correctly this.checkLVal(left); this.next(); node.right = this.parseMaybeAssign(noIn); return this.finishNode(node, "AssignmentExpression") } else { if (ownDestructuringErrors) { this.checkExpressionErrors(refDestructuringErrors, true); } } if (oldParenAssign > -1) { refDestructuringErrors.parenthesizedAssign = oldParenAssign; } if (oldTrailingComma > -1) { refDestructuringErrors.trailingComma = oldTrailingComma; } return left }; // Parse a ternary conditional (`?:`) operator. pp$3.parseMaybeConditional = function(noIn, refDestructuringErrors) { var startPos = this.start, startLoc = this.startLoc; var expr = this.parseExprOps(noIn, refDestructuringErrors); if (this.checkExpressionErrors(refDestructuringErrors)) { return expr } if (this.eat(types.question)) { var node = this.startNodeAt(startPos, startLoc); node.test = expr; node.consequent = this.parseMaybeAssign(); this.expect(types.colon); node.alternate = this.parseMaybeAssign(noIn); return this.finishNode(node, "ConditionalExpression") } return expr }; // Start the precedence parser. pp$3.parseExprOps = function(noIn, refDestructuringErrors) { var startPos = this.start, startLoc = this.startLoc; var expr = this.parseMaybeUnary(refDestructuringErrors, false); if (this.checkExpressionErrors(refDestructuringErrors)) { return expr } return expr.start == startPos && expr.type === "ArrowFunctionExpression" ? expr : this.parseExprOp(expr, startPos, startLoc, -1, noIn) }; // Parse binary operators with the operator precedence parsing // algorithm. `left` is the left-hand side of the operator. // `minPrec` provides context that allows the function to stop and // defer further parser to one of its callers when it encounters an // operator that has a lower precedence than the set it is parsing. pp$3.parseExprOp = function(left, leftStartPos, leftStartLoc, minPrec, noIn) { var prec = this.type.binop; if (prec != null && (!noIn || this.type !== types._in)) { if (prec > minPrec) { var logical = this.type === types.logicalOR || this.type === types.logicalAND; var op = this.value; this.next(); var startPos = this.start, startLoc = this.startLoc; var right = this.parseExprOp(this.parseMaybeUnary(null, false), startPos, startLoc, prec, noIn); var node = this.buildBinary(leftStartPos, leftStartLoc, left, right, op, logical); return this.parseExprOp(node, leftStartPos, leftStartLoc, minPrec, noIn) } } return left }; pp$3.buildBinary = function(startPos, startLoc, left, right, op, logical) { var node = this.startNodeAt(startPos, startLoc); node.left = left; node.operator = op; node.right = right; return this.finishNode(node, logical ? "LogicalExpression" : "BinaryExpression") }; // Parse unary operators, both prefix and postfix. pp$3.parseMaybeUnary = function(refDestructuringErrors, sawUnary) { var this$1 = this; var startPos = this.start, startLoc = this.startLoc, expr; if (this.inAsync && this.isContextual("await")) { expr = this.parseAwait(); sawUnary = true; } else if (this.type.prefix) { var node = this.startNode(), update = this.type === types.incDec; node.operator = this.value; node.prefix = true; this.next(); node.argument = this.parseMaybeUnary(null, true); this.checkExpressionErrors(refDestructuringErrors, true); if (update) { this.checkLVal(node.argument); } else if (this.strict && node.operator === "delete" && node.argument.type === "Identifier") { this.raiseRecoverable(node.start, "Deleting local variable in strict mode"); } else { sawUnary = true; } expr = this.finishNode(node, update ? "UpdateExpression" : "UnaryExpression"); } else { expr = this.parseExprSubscripts(refDestructuringErrors); if (this.checkExpressionErrors(refDestructuringErrors)) { return expr } while (this.type.postfix && !this.canInsertSemicolon()) { var node$1 = this$1.startNodeAt(startPos, startLoc); node$1.operator = this$1.value; node$1.prefix = false; node$1.argument = expr; this$1.checkLVal(expr); this$1.next(); expr = this$1.finishNode(node$1, "UpdateExpression"); } } if (!sawUnary && this.eat(types.starstar)) { return this.buildBinary(startPos, startLoc, expr, this.parseMaybeUnary(null, false), "**", false) } else { return expr } }; // Parse call, dot, and `[]`-subscript expressions. pp$3.parseExprSubscripts = function(refDestructuringErrors) { var startPos = this.start, startLoc = this.startLoc; var expr = this.parseExprAtom(refDestructuringErrors); var skipArrowSubscripts = expr.type === "ArrowFunctionExpression" && this.input.slice(this.lastTokStart, this.lastTokEnd) !== ")"; if (this.checkExpressionErrors(refDestructuringErrors) || skipArrowSubscripts) { return expr } var result = this.parseSubscripts(expr, startPos, startLoc); if (refDestructuringErrors && result.type === "MemberExpression") { if (refDestructuringErrors.parenthesizedAssign >= result.start) { refDestructuringErrors.parenthesizedAssign = -1; } if (refDestructuringErrors.parenthesizedBind >= result.start) { refDestructuringErrors.parenthesizedBind = -1; } } return result }; pp$3.parseSubscripts = function(base, startPos, startLoc, noCalls) { var this$1 = this; var maybeAsyncArrow = this.options.ecmaVersion >= 8 && base.type === "Identifier" && base.name === "async" && this.lastTokEnd == base.end && !this.canInsertSemicolon(); for (var computed = (void 0);;) { if ((computed = this$1.eat(types.bracketL)) || this$1.eat(types.dot)) { var node = this$1.startNodeAt(startPos, startLoc); node.object = base; node.property = computed ? this$1.parseExpression() : this$1.parseIdent(true); node.computed = !!computed; if (computed) { this$1.expect(types.bracketR); } base = this$1.finishNode(node, "MemberExpression"); } else if (!noCalls && this$1.eat(types.parenL)) { var refDestructuringErrors = new DestructuringErrors, oldYieldPos = this$1.yieldPos, oldAwaitPos = this$1.awaitPos; this$1.yieldPos = 0; this$1.awaitPos = 0; var exprList = this$1.parseExprList(types.parenR, this$1.options.ecmaVersion >= 8, false, refDestructuringErrors); if (maybeAsyncArrow && !this$1.canInsertSemicolon() && this$1.eat(types.arrow)) { this$1.checkPatternErrors(refDestructuringErrors, false); this$1.checkYieldAwaitInDefaultParams(); this$1.yieldPos = oldYieldPos; this$1.awaitPos = oldAwaitPos; return this$1.parseArrowExpression(this$1.startNodeAt(startPos, startLoc), exprList, true) } this$1.checkExpressionErrors(refDestructuringErrors, true); this$1.yieldPos = oldYieldPos || this$1.yieldPos; this$1.awaitPos = oldAwaitPos || this$1.awaitPos; var node$1 = this$1.startNodeAt(startPos, startLoc); node$1.callee = base; node$1.arguments = exprList; base = this$1.finishNode(node$1, "CallExpression"); } else if (this$1.type === types.backQuote) { var node$2 = this$1.startNodeAt(startPos, startLoc); node$2.tag = base; node$2.quasi = this$1.parseTemplate({isTagged: true}); base = this$1.finishNode(node$2, "TaggedTemplateExpression"); } else { return base } } }; // Parse an atomic expression — either a single token that is an // expression, an expression started by a keyword like `function` or // `new`, or an expression wrapped in punctuation like `()`, `[]`, // or `{}`. pp$3.parseExprAtom = function(refDestructuringErrors) { var node, canBeArrow = this.potentialArrowAt == this.start; switch (this.type) { case types._super: if (!this.inFunction) { this.raise(this.start, "'super' outside of function or class"); } node = this.startNode(); this.next(); // The `super` keyword can appear at below: // SuperProperty: // super [ Expression ] // super . IdentifierName // SuperCall: // super Arguments if (this.type !== types.dot && this.type !== types.bracketL && this.type !== types.parenL) { this.unexpected(); } return this.finishNode(node, "Super") case types._this: node = this.startNode(); this.next(); return this.finishNode(node, "ThisExpression") case types.name: var startPos = this.start, startLoc = this.startLoc; var id = this.parseIdent(this.type !== types.name); if (this.options.ecmaVersion >= 8 && id.name === "async" && !this.canInsertSemicolon() && this.eat(types._function)) { return this.parseFunction(this.startNodeAt(startPos, startLoc), false, false, true) } if (canBeArrow && !this.canInsertSemicolon()) { if (this.eat(types.arrow)) { return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], false) } if (this.options.ecmaVersion >= 8 && id.name === "async" && this.type === types.name) { id = this.parseIdent(); if (this.canInsertSemicolon() || !this.eat(types.arrow)) { this.unexpected(); } return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], true) } } return id case types.regexp: var value = this.value; node = this.parseLiteral(value.value); node.regex = {pattern: value.pattern, flags: value.flags}; return node case types.num: case types.string: return this.parseLiteral(this.value) case types._null: case types._true: case types._false: node = this.startNode(); node.value = this.type === types._null ? null : this.type === types._true; node.raw = this.type.keyword; this.next(); return this.finishNode(node, "Literal") case types.parenL: var start = this.start, expr = this.parseParenAndDistinguishExpression(canBeArrow); if (refDestructuringErrors) { if (refDestructuringErrors.parenthesizedAssign < 0 && !this.isSimpleAssignTarget(expr)) { refDestructuringErrors.parenthesizedAssign = start; } if (refDestructuringErrors.parenthesizedBind < 0) { refDestructuringErrors.parenthesizedBind = start; } } return expr case types.bracketL: node = this.startNode(); this.next(); node.elements = this.parseExprList(types.bracketR, true, true, refDestructuringErrors); return this.finishNode(node, "ArrayExpression") case types.braceL: return this.parseObj(false, refDestructuringErrors) case types._function: node = this.startNode(); this.next(); return this.parseFunction(node, false) case types._class: return this.parseClass(this.startNode(), false) case types._new: return this.parseNew() case types.backQuote: return this.parseTemplate() default: this.unexpected(); } }; pp$3.parseLiteral = function(value) { var node = this.startNode(); node.value = value; node.raw = this.input.slice(this.start, this.end); this.next(); return this.finishNode(node, "Literal") }; pp$3.parseParenExpression = function() { this.expect(types.parenL); var val = this.parseExpression(); this.expect(types.parenR); return val }; pp$3.parseParenAndDistinguishExpression = function(canBeArrow) { var this$1 = this; var startPos = this.start, startLoc = this.startLoc, val, allowTrailingComma = this.options.ecmaVersion >= 8; if (this.options.ecmaVersion >= 6) { this.next(); var innerStartPos = this.start, innerStartLoc = this.startLoc; var exprList = [], first = true, lastIsComma = false; var refDestructuringErrors = new DestructuringErrors, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, spreadStart, innerParenStart; this.yieldPos = 0; this.awaitPos = 0; while (this.type !== types.parenR) { first ? first = false : this$1.expect(types.comma); if (allowTrailingComma && this$1.afterTrailingComma(types.parenR, true)) { lastIsComma = true; break } else if (this$1.type === types.ellipsis) { spreadStart = this$1.start; exprList.push(this$1.parseParenItem(this$1.parseRestBinding())); if (this$1.type === types.comma) { this$1.raise(this$1.start, "Comma is not permitted after the rest element"); } break } else { if (this$1.type === types.parenL && !innerParenStart) { innerParenStart = this$1.start; } exprList.push(this$1.parseMaybeAssign(false, refDestructuringErrors, this$1.parseParenItem)); } } var innerEndPos = this.start, innerEndLoc = this.startLoc; this.expect(types.parenR); if (canBeArrow && !this.canInsertSemicolon() && this.eat(types.arrow)) { this.checkPatternErrors(refDestructuringErrors, false); this.checkYieldAwaitInDefaultParams(); if (innerParenStart) { this.unexpected(innerParenStart); } this.yieldPos = oldYieldPos; this.awaitPos = oldAwaitPos; return this.parseParenArrowList(startPos, startLoc, exprList) } if (!exprList.length || lastIsComma) { this.unexpected(this.lastTokStart); } if (spreadStart) { this.unexpected(spreadStart); } this.checkExpressionErrors(refDestructuringErrors, true); this.yieldPos = oldYieldPos || this.yieldPos; this.awaitPos = oldAwaitPos || this.awaitPos; if (exprList.length > 1) { val = this.startNodeAt(innerStartPos, innerStartLoc); val.expressions = exprList; this.finishNodeAt(val, "SequenceExpression", innerEndPos, innerEndLoc); } else { val = exprList[0]; } } else { val = this.parseParenExpression(); } if (this.options.preserveParens) { var par = this.startNodeAt(startPos, startLoc); par.expression = val; return this.finishNode(par, "ParenthesizedExpression") } else { return val } }; pp$3.parseParenItem = function(item) { return item }; pp$3.parseParenArrowList = function(startPos, startLoc, exprList) { return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList) }; // New's precedence is slightly tricky. It must allow its argument to // be a `[]` or dot subscript expression, but not a call — at least, // not without wrapping it in parentheses. Thus, it uses the noCalls // argument to parseSubscripts to prevent it from consuming the // argument list. var empty$1 = []; pp$3.parseNew = function() { var node = this.startNode(); var meta = this.parseIdent(true); if (this.options.ecmaVersion >= 6 && this.eat(types.dot)) { node.meta = meta; node.property = this.parseIdent(true); if (node.property.name !== "target") { this.raiseRecoverable(node.property.start, "The only valid meta property for new is new.target"); } if (!this.inFunction) { this.raiseRecoverable(node.start, "new.target can only be used in functions"); } return this.finishNode(node, "MetaProperty") } var startPos = this.start, startLoc = this.startLoc; node.callee = this.parseSubscripts(this.parseExprAtom(), startPos, startLoc, true); if (this.eat(types.parenL)) { node.arguments = this.parseExprList(types.parenR, this.options.ecmaVersion >= 8, false); } else { node.arguments = empty$1; } return this.finishNode(node, "NewExpression") }; // Parse template expression. pp$3.parseTemplateElement = function(ref) { var isTagged = ref.isTagged; var elem = this.startNode(); if (this.type === types.invalidTemplate) { if (!isTagged) { this.raiseRecoverable(this.start, "Bad escape sequence in untagged template literal"); } elem.value = { raw: this.value, cooked: null }; } else { elem.value = { raw: this.input.slice(this.start, this.end).replace(/\r\n?/g, "\n"), cooked: this.value }; } this.next(); elem.tail = this.type === types.backQuote; return this.finishNode(elem, "TemplateElement") }; pp$3.parseTemplate = function(ref) { var this$1 = this; if ( ref === void 0 ) ref = {}; var isTagged = ref.isTagged; if ( isTagged === void 0 ) isTagged = false; var node = this.startNode(); this.next(); node.expressions = []; var curElt = this.parseTemplateElement({isTagged: isTagged}); node.quasis = [curElt]; while (!curElt.tail) { this$1.expect(types.dollarBraceL); node.expressions.push(this$1.parseExpression()); this$1.expect(types.braceR); node.quasis.push(curElt = this$1.parseTemplateElement({isTagged: isTagged})); } this.next(); return this.finishNode(node, "TemplateLiteral") }; pp$3.isAsyncProp = function(prop) { return !prop.computed && prop.key.type === "Identifier" && prop.key.name === "async" && (this.type === types.name || this.type === types.num || this.type === types.string || this.type === types.bracketL || this.type.keyword) && !lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) }; // Parse an object literal or binding pattern. pp$3.parseObj = function(isPattern, refDestructuringErrors) { var this$1 = this; var node = this.startNode(), first = true, propHash = {}; node.properties = []; this.next(); while (!this.eat(types.braceR)) { if (!first) { this$1.expect(types.comma); if (this$1.afterTrailingComma(types.braceR)) { break } } else { first = false; } var prop = this$1.parseProperty(isPattern, refDestructuringErrors); this$1.checkPropClash(prop, propHash); node.properties.push(prop); } return this.finishNode(node, isPattern ? "ObjectPattern" : "ObjectExpression") }; pp$3.parseProperty = function(isPattern, refDestructuringErrors) { var prop = this.startNode(), isGenerator, isAsync, startPos, startLoc; if (this.options.ecmaVersion >= 6) { prop.method = false; prop.shorthand = false; if (isPattern || refDestructuringErrors) { startPos = this.start; startLoc = this.startLoc; } if (!isPattern) { isGenerator = this.eat(types.star); } } this.parsePropertyName(prop); if (!isPattern && this.options.ecmaVersion >= 8 && !isGenerator && this.isAsyncProp(prop)) { isAsync = true; this.parsePropertyName(prop, refDestructuringErrors); } else { isAsync = false; } this.parsePropertyValue(prop, isPattern, isGenerator, isAsync, startPos, startLoc, refDestructuringErrors); return this.finishNode(prop, "Property") }; pp$3.parsePropertyValue = function(prop, isPattern, isGenerator, isAsync, startPos, startLoc, refDestructuringErrors) { if ((isGenerator || isAsync) && this.type === types.colon) { this.unexpected(); } if (this.eat(types.colon)) { prop.value = isPattern ? this.parseMaybeDefault(this.start, this.startLoc) : this.parseMaybeAssign(false, refDestructuringErrors); prop.kind = "init"; } else if (this.options.ecmaVersion >= 6 && this.type === types.parenL) { if (isPattern) { this.unexpected(); } prop.kind = "init"; prop.method = true; prop.value = this.parseMethod(isGenerator, isAsync); } else if (!isPattern && this.options.ecmaVersion >= 5 && !prop.computed && prop.key.type === "Identifier" && (prop.key.name === "get" || prop.key.name === "set") && (this.type != types.comma && this.type != types.braceR)) { if (isGenerator || isAsync) { this.unexpected(); } prop.kind = prop.key.name; this.parsePropertyName(prop); prop.value = this.parseMethod(false); var paramCount = prop.kind === "get" ? 0 : 1; if (prop.value.params.length !== paramCount) { var start = prop.value.start; if (prop.kind === "get") { this.raiseRecoverable(start, "getter should have no params"); } else { this.raiseRecoverable(start, "setter should have exactly one param"); } } else { if (prop.kind === "set" && prop.value.params[0].type === "RestElement") { this.raiseRecoverable(prop.value.params[0].start, "Setter cannot use rest params"); } } } else if (this.options.ecmaVersion >= 6 && !prop.computed && prop.key.type === "Identifier") { this.checkUnreserved(prop.key); prop.kind = "init"; if (isPattern) { prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key); } else if (this.type === types.eq && refDestructuringErrors) { if (refDestructuringErrors.shorthandAssign < 0) { refDestructuringErrors.shorthandAssign = this.start; } prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key); } else { prop.value = prop.key; } prop.shorthand = true; } else { this.unexpected(); } }; pp$3.parsePropertyName = function(prop) { if (this.options.ecmaVersion >= 6) { if (this.eat(types.bracketL)) { prop.computed = true; prop.key = this.parseMaybeAssign(); this.expect(types.bracketR); return prop.key } else { prop.computed = false; } } return prop.key = this.type === types.num || this.type === types.string ? this.parseExprAtom() : this.parseIdent(true) }; // Initialize empty function node. pp$3.initFunction = function(node) { node.id = null; if (this.options.ecmaVersion >= 6) { node.generator = false; node.expression = false; } if (this.options.ecmaVersion >= 8) { node.async = false; } }; // Parse object or class method. pp$3.parseMethod = function(isGenerator, isAsync) { var node = this.startNode(), oldInGen = this.inGenerator, oldInAsync = this.inAsync, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldInFunc = this.inFunction; this.initFunction(node); if (this.options.ecmaVersion >= 6) { node.generator = isGenerator; } if (this.options.ecmaVersion >= 8) { node.async = !!isAsync; } this.inGenerator = node.generator; this.inAsync = node.async; this.yieldPos = 0; this.awaitPos = 0; this.inFunction = true; this.enterFunctionScope(); this.expect(types.parenL); node.params = this.parseBindingList(types.parenR, false, this.options.ecmaVersion >= 8); this.checkYieldAwaitInDefaultParams(); this.parseFunctionBody(node, false); this.inGenerator = oldInGen; this.inAsync = oldInAsync; this.yieldPos = oldYieldPos; this.awaitPos = oldAwaitPos; this.inFunction = oldInFunc; return this.finishNode(node, "FunctionExpression") }; // Parse arrow function expression with given parameters. pp$3.parseArrowExpression = function(node, params, isAsync) { var oldInGen = this.inGenerator, oldInAsync = this.inAsync, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldInFunc = this.inFunction; this.enterFunctionScope(); this.initFunction(node); if (this.options.ecmaVersion >= 8) { node.async = !!isAsync; } this.inGenerator = false; this.inAsync = node.async; this.yieldPos = 0; this.awaitPos = 0; this.inFunction = true; node.params = this.toAssignableList(params, true); this.parseFunctionBody(node, true); this.inGenerator = oldInGen; this.inAsync = oldInAsync; this.yieldPos = oldYieldPos; this.awaitPos = oldAwaitPos; this.inFunction = oldInFunc; return this.finishNode(node, "ArrowFunctionExpression") }; // Parse function body and check parameters. pp$3.parseFunctionBody = function(node, isArrowFunction) { var isExpression = isArrowFunction && this.type !== types.braceL; var oldStrict = this.strict, useStrict = false; if (isExpression) { node.body = this.parseMaybeAssign(); node.expression = true; this.checkParams(node, false); } else { var nonSimple = this.options.ecmaVersion >= 7 && !this.isSimpleParamList(node.params); if (!oldStrict || nonSimple) { useStrict = this.strictDirective(this.end); // If this is a strict mode function, verify that argument names // are not repeated, and it does not try to bind the words `eval` // or `arguments`. if (useStrict && nonSimple) { this.raiseRecoverable(node.start, "Illegal 'use strict' directive in function with non-simple parameter list"); } } // Start a new scope with regard to labels and the `inFunction` // flag (restore them to their old value afterwards). var oldLabels = this.labels; this.labels = []; if (useStrict) { this.strict = true; } // Add the params to varDeclaredNames to ensure that an error is thrown // if a let/const declaration in the function clashes with one of the params. this.checkParams(node, !oldStrict && !useStrict && !isArrowFunction && this.isSimpleParamList(node.params)); node.body = this.parseBlock(false); node.expression = false; this.adaptDirectivePrologue(node.body.body); this.labels = oldLabels; } this.exitFunctionScope(); if (this.strict && node.id) { // Ensure the function name isn't a forbidden identifier in strict mode, e.g. 'eval' this.checkLVal(node.id, "none"); } this.strict = oldStrict; }; pp$3.isSimpleParamList = function(params) { for (var i = 0, list = params; i < list.length; i += 1) { var param = list[i]; if (param.type !== "Identifier") { return false } } return true }; // Checks function params for various disallowed patterns such as using "eval" // or "arguments" and duplicate parameters. pp$3.checkParams = function(node, allowDuplicates) { var this$1 = this; var nameHash = {}; for (var i = 0, list = node.params; i < list.length; i += 1) { var param = list[i]; this$1.checkLVal(param, "var", allowDuplicates ? null : nameHash); } }; // Parses a comma-separated list of expressions, and returns them as // an array. `close` is the token type that ends the list, and // `allowEmpty` can be turned on to allow subsequent commas with // nothing in between them to be parsed as `null` (which is needed // for array literals). pp$3.parseExprList = function(close, allowTrailingComma, allowEmpty, refDestructuringErrors) { var this$1 = this; var elts = [], first = true; while (!this.eat(close)) { if (!first) { this$1.expect(types.comma); if (allowTrailingComma && this$1.afterTrailingComma(close)) { break } } else { first = false; } var elt = (void 0); if (allowEmpty && this$1.type === types.comma) { elt = null; } else if (this$1.type === types.ellipsis) { elt = this$1.parseSpread(refDestructuringErrors); if (refDestructuringErrors && this$1.type === types.comma && refDestructuringErrors.trailingComma < 0) { refDestructuringErrors.trailingComma = this$1.start; } } else { elt = this$1.parseMaybeAssign(false, refDestructuringErrors); } elts.push(elt); } return elts }; pp$3.checkUnreserved = function(ref) { var start = ref.start; var end = ref.end; var name = ref.name; if (this.inGenerator && name === "yield") { this.raiseRecoverable(start, "Can not use 'yield' as identifier inside a generator"); } if (this.inAsync && name === "await") { this.raiseRecoverable(start, "Can not use 'await' as identifier inside an async function"); } if (this.isKeyword(name)) { this.raise(start, ("Unexpected keyword '" + name + "'")); } if (this.options.ecmaVersion < 6 && this.input.slice(start, end).indexOf("\\") != -1) { return } var re = this.strict ? this.reservedWordsStrict : this.reservedWords; if (re.test(name)) { this.raiseRecoverable(start, ("The keyword '" + name + "' is reserved")); } }; // Parse the next token as an identifier. If `liberal` is true (used // when parsing properties), it will also convert keywords into // identifiers. pp$3.parseIdent = function(liberal, isBinding) { var node = this.startNode(); if (liberal && this.options.allowReserved == "never") { liberal = false; } if (this.type === types.name) { node.name = this.value; } else if (this.type.keyword) { node.name = this.type.keyword; // To fix https://github.com/ternjs/acorn/issues/575 // `class` and `function` keywords push new context into this.context. // But there is no chance to pop the context if the keyword is consumed as an identifier such as a property name. // If the previous token is a dot, this does not apply because the context-managing code already ignored the keyword if ((node.name === "class" || node.name === "function") && (this.lastTokEnd !== this.lastTokStart + 1 || this.input.charCodeAt(this.lastTokStart) !== 46)) { this.context.pop(); } } else { this.unexpected(); } this.next(); this.finishNode(node, "Identifier"); if (!liberal) { this.checkUnreserved(node); } return node }; // Parses yield expression inside generator. pp$3.parseYield = function() { if (!this.yieldPos) { this.yieldPos = this.start; } var node = this.startNode(); this.next(); if (this.type == types.semi || this.canInsertSemicolon() || (this.type != types.star && !this.type.startsExpr)) { node.delegate = false; node.argument = null; } else { node.delegate = this.eat(types.star); node.argument = this.parseMaybeAssign(); } return this.finishNode(node, "YieldExpression") }; pp$3.parseAwait = function() { if (!this.awaitPos) { this.awaitPos = this.start; } var node = this.startNode(); this.next(); node.argument = this.parseMaybeUnary(null, true); return this.finishNode(node, "AwaitExpression") }; var pp$4 = Parser.prototype; // This function is used to raise exceptions on parse errors. It // takes an offset integer (into the current `input`) to indicate // the location of the error, attaches the position to the end // of the error message, and then raises a `SyntaxError` with that // message. pp$4.raise = function(pos, message) { var loc = getLineInfo(this.input, pos); message += " (" + loc.line + ":" + loc.column + ")"; var err = new SyntaxError(message); err.pos = pos; err.loc = loc; err.raisedAt = this.pos; throw err }; pp$4.raiseRecoverable = pp$4.raise; pp$4.curPosition = function() { if (this.options.locations) { return new Position(this.curLine, this.pos - this.lineStart) } }; var pp$5 = Parser.prototype; // Object.assign polyfill var assign = Object.assign || function(target) { var sources = [], len = arguments.length - 1; while ( len-- > 0 ) sources[ len ] = arguments[ len + 1 ]; for (var i = 0, list = sources; i < list.length; i += 1) { var source = list[i]; for (var key in source) { if (has(source, key)) { target[key] = source[key]; } } } return target }; // The functions in this module keep track of declared variables in the current scope in order to detect duplicate variable names. pp$5.enterFunctionScope = function() { // var: a hash of var-declared names in the current lexical scope // lexical: a hash of lexically-declared names in the current lexical scope // childVar: a hash of var-declared names in all child lexical scopes of the current lexical scope (within the current function scope) // parentLexical: a hash of lexically-declared names in all parent lexical scopes of the current lexical scope (within the current function scope) this.scopeStack.push({var: {}, lexical: {}, childVar: {}, parentLexical: {}}); }; pp$5.exitFunctionScope = function() { this.scopeStack.pop(); }; pp$5.enterLexicalScope = function() { var parentScope = this.scopeStack[this.scopeStack.length - 1]; var childScope = {var: {}, lexical: {}, childVar: {}, parentLexical: {}}; this.scopeStack.push(childScope); assign(childScope.parentLexical, parentScope.lexical, parentScope.parentLexical); }; pp$5.exitLexicalScope = function() { var childScope = this.scopeStack.pop(); var parentScope = this.scopeStack[this.scopeStack.length - 1]; assign(parentScope.childVar, childScope.var, childScope.childVar); }; /** * A name can be declared with `var` if there are no variables with the same name declared with `let`/`const` * in the current lexical scope or any of the parent lexical scopes in this function. */ pp$5.canDeclareVarName = function(name) { var currentScope = this.scopeStack[this.scopeStack.length - 1]; return !has(currentScope.lexical, name) && !has(currentScope.parentLexical, name) }; /** * A name can be declared with `let`/`const` if there are no variables with the same name declared with `let`/`const` * in the current scope, and there are no variables with the same name declared with `var` in the current scope or in * any child lexical scopes in this function. */ pp$5.canDeclareLexicalName = function(name) { var currentScope = this.scopeStack[this.scopeStack.length - 1]; return !has(currentScope.lexical, name) && !has(currentScope.var, name) && !has(currentScope.childVar, name) }; pp$5.declareVarName = function(name) { this.scopeStack[this.scopeStack.length - 1].var[name] = true; }; pp$5.declareLexicalName = function(name) { this.scopeStack[this.scopeStack.length - 1].lexical[name] = true; }; var Node = function Node(parser, pos, loc) { this.type = ""; this.start = pos; this.end = 0; if (parser.options.locations) { this.loc = new SourceLocation(parser, loc); } if (parser.options.directSourceFile) { this.sourceFile = parser.options.directSourceFile; } if (parser.options.ranges) { this.range = [pos, 0]; } }; // Start an AST node, attaching a start offset. var pp$6 = Parser.prototype; pp$6.startNode = function() { return new Node(this, this.start, this.startLoc) }; pp$6.startNodeAt = function(pos, loc) { return new Node(this, pos, loc) }; // Finish an AST node, adding `type` and `end` properties. function finishNodeAt(node, type, pos, loc) { node.type = type; node.end = pos; if (this.options.locations) { node.loc.end = loc; } if (this.options.ranges) { node.range[1] = pos; } return node } pp$6.finishNode = function(node, type) { return finishNodeAt.call(this, node, type, this.lastTokEnd, this.lastTokEndLoc) }; // Finish node at given position pp$6.finishNodeAt = function(node, type, pos, loc) { return finishNodeAt.call(this, node, type, pos, loc) }; // The algorithm used to determine whether a regexp can appear at a // given point in the program is loosely based on sweet.js' approach. // See https://github.com/mozilla/sweet.js/wiki/design var TokContext = function TokContext(token, isExpr, preserveSpace, override, generator) { this.token = token; this.isExpr = !!isExpr; this.preserveSpace = !!preserveSpace; this.override = override; this.generator = !!generator; }; var types$1 = { b_stat: new TokContext("{", false), b_expr: new TokContext("{", true), b_tmpl: new TokContext("${", false), p_stat: new TokContext("(", false), p_expr: new TokContext("(", true), q_tmpl: new TokContext("`", true, true, function (p) { return p.tryReadTemplateToken(); }), f_stat: new TokContext("function", false), f_expr: new TokContext("function", true), f_expr_gen: new TokContext("function", true, false, null, true), f_gen: new TokContext("function", false, false, null, true) }; var pp$7 = Parser.prototype; pp$7.initialContext = function() { return [types$1.b_stat] }; pp$7.braceIsBlock = function(prevType) { var parent = this.curContext(); if (parent === types$1.f_expr || parent === types$1.f_stat) { return true } if (prevType === types.colon && (parent === types$1.b_stat || parent === types$1.b_expr)) { return !parent.isExpr } // The check for `tt.name && exprAllowed` detects whether we are // after a `yield` or `of` construct. See the `updateContext` for // `tt.name`. if (prevType === types._return || prevType == types.name && this.exprAllowed) { return lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) } if (prevType === types._else || prevType === types.semi || prevType === types.eof || prevType === types.parenR || prevType == types.arrow) { return true } if (prevType == types.braceL) { return parent === types$1.b_stat } if (prevType == types._var || prevType == types.name) { return false } return !this.exprAllowed }; pp$7.inGeneratorContext = function() { var this$1 = this; for (var i = this.context.length - 1; i >= 1; i--) { var context = this$1.context[i]; if (context.token === "function") { return context.generator } } return false }; pp$7.updateContext = function(prevType) { var update, type = this.type; if (type.keyword && prevType == types.dot) { this.exprAllowed = false; } else if (update = type.updateContext) { update.call(this, prevType); } else { this.exprAllowed = type.beforeExpr; } }; // Token-specific context update code types.parenR.updateContext = types.braceR.updateContext = function() { if (this.context.length == 1) { this.exprAllowed = true; return } var out = this.context.pop(); if (out === types$1.b_stat && this.curContext().token === "function") { out = this.context.pop(); } this.exprAllowed = !out.isExpr; }; types.braceL.updateContext = function(prevType) { this.context.push(this.braceIsBlock(prevType) ? types$1.b_stat : types$1.b_expr); this.exprAllowed = true; }; types.dollarBraceL.updateContext = function() { this.context.push(types$1.b_tmpl); this.exprAllowed = true; }; types.parenL.updateContext = function(prevType) { var statementParens = prevType === types._if || prevType === types._for || prevType === types._with || prevType === types._while; this.context.push(statementParens ? types$1.p_stat : types$1.p_expr); this.exprAllowed = true; }; types.incDec.updateContext = function() { // tokExprAllowed stays unchanged }; types._function.updateContext = types._class.updateContext = function(prevType) { if (prevType.beforeExpr && prevType !== types.semi && prevType !== types._else && !((prevType === types.colon || prevType === types.braceL) && this.curContext() === types$1.b_stat)) { this.context.push(types$1.f_expr); } else { this.context.push(types$1.f_stat); } this.exprAllowed = false; }; types.backQuote.updateContext = function() { if (this.curContext() === types$1.q_tmpl) { this.context.pop(); } else { this.context.push(types$1.q_tmpl); } this.exprAllowed = false; }; types.star.updateContext = function(prevType) { if (prevType == types._function) { var index = this.context.length - 1; if (this.context[index] === types$1.f_expr) { this.context[index] = types$1.f_expr_gen; } else { this.context[index] = types$1.f_gen; } } this.exprAllowed = true; }; types.name.updateContext = function(prevType) { var allowed = false; if (this.options.ecmaVersion >= 6) { if (this.value == "of" && !this.exprAllowed || this.value == "yield" && this.inGeneratorContext()) { allowed = true; } } this.exprAllowed = allowed; }; // Object type used to represent tokens. Note that normally, tokens // simply exist as properties on the parser object. This is only // used for the onToken callback and the external tokenizer. var Token = function Token(p) { this.type = p.type; this.value = p.value; this.start = p.start; this.end = p.end; if (p.options.locations) { this.loc = new SourceLocation(p, p.startLoc, p.endLoc); } if (p.options.ranges) { this.range = [p.start, p.end]; } }; // ## Tokenizer var pp$8 = Parser.prototype; // Are we running under Rhino? var isRhino = typeof Packages == "object" && Object.prototype.toString.call(Packages) == "[object JavaPackage]"; // Move to the next token pp$8.next = function() { if (this.options.onToken) { this.options.onToken(new Token(this)); } this.lastTokEnd = this.end; this.lastTokStart = this.start; this.lastTokEndLoc = this.endLoc; this.lastTokStartLoc = this.startLoc; this.nextToken(); }; pp$8.getToken = function() { this.next(); return new Token(this) }; // If we're in an ES6 environment, make parsers iterable if (typeof Symbol !== "undefined") { pp$8[Symbol.iterator] = function() { var this$1 = this; return { next: function () { var token = this$1.getToken(); return { done: token.type === types.eof, value: token } } } }; } // Toggle strict mode. Re-reads the next number or string to please // pedantic tests (`"use strict"; 010;` should fail). pp$8.curContext = function() { return this.context[this.context.length - 1] }; // Read a single token, updating the parser object's token-related // properties. pp$8.nextToken = function() { var curContext = this.curContext(); if (!curContext || !curContext.preserveSpace) { this.skipSpace(); } this.start = this.pos; if (this.options.locations) { this.startLoc = this.curPosition(); } if (this.pos >= this.input.length) { return this.finishToken(types.eof) } if (curContext.override) { return curContext.override(this) } else { this.readToken(this.fullCharCodeAtPos()); } }; pp$8.readToken = function(code) { // Identifier or keyword. '\uXXXX' sequences are allowed in // identifiers, so '\' also dispatches to that. if (isIdentifierStart(code, this.options.ecmaVersion >= 6) || code === 92 /* '\' */) { return this.readWord() } return this.getTokenFromCode(code) }; pp$8.fullCharCodeAtPos = function() { var code = this.input.charCodeAt(this.pos); if (code <= 0xd7ff || code >= 0xe000) { return code } var next = this.input.charCodeAt(this.pos + 1); return (code << 10) + next - 0x35fdc00 }; pp$8.skipBlockComment = function() { var this$1 = this; var startLoc = this.options.onComment && this.curPosition(); var start = this.pos, end = this.input.indexOf("*/", this.pos += 2); if (end === -1) { this.raise(this.pos - 2, "Unterminated comment"); } this.pos = end + 2; if (this.options.locations) { lineBreakG.lastIndex = start; var match; while ((match = lineBreakG.exec(this.input)) && match.index < this.pos) { ++this$1.curLine; this$1.lineStart = match.index + match[0].length; } } if (this.options.onComment) { this.options.onComment(true, this.input.slice(start + 2, end), start, this.pos, startLoc, this.curPosition()); } }; pp$8.skipLineComment = function(startSkip) { var this$1 = this; var start = this.pos; var startLoc = this.options.onComment && this.curPosition(); var ch = this.input.charCodeAt(this.pos += startSkip); while (this.pos < this.input.length && !isNewLine(ch)) { ch = this$1.input.charCodeAt(++this$1.pos); } if (this.options.onComment) { this.options.onComment(false, this.input.slice(start + startSkip, this.pos), start, this.pos, startLoc, this.curPosition()); } }; // Called at the start of the parse and after every token. Skips // whitespace and comments, and. pp$8.skipSpace = function() { var this$1 = this; loop: while (this.pos < this.input.length) { var ch = this$1.input.charCodeAt(this$1.pos); switch (ch) { case 32: case 160: // ' ' ++this$1.pos; break case 13: if (this$1.input.charCodeAt(this$1.pos + 1) === 10) { ++this$1.pos; } case 10: case 8232: case 8233: ++this$1.pos; if (this$1.options.locations) { ++this$1.curLine; this$1.lineStart = this$1.pos; } break case 47: // '/' switch (this$1.input.charCodeAt(this$1.pos + 1)) { case 42: // '*' this$1.skipBlockComment(); break case 47: this$1.skipLineComment(2); break default: break loop } break default: if (ch > 8 && ch < 14 || ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) { ++this$1.pos; } else { break loop } } } }; // Called at the end of every token. Sets `end`, `val`, and // maintains `context` and `exprAllowed`, and skips the space after // the token, so that the next one's `start` will point at the // right position. pp$8.finishToken = function(type, val) { this.end = this.pos; if (this.options.locations) { this.endLoc = this.curPosition(); } var prevType = this.type; this.type = type; this.value = val; this.updateContext(prevType); }; // ### Token reading // This is the function that is called to fetch the next token. It // is somewhat obscure, because it works in character codes rather // than characters, and because operator parsing has been inlined // into it. // // All in the name of speed. // pp$8.readToken_dot = function() { var next = this.input.charCodeAt(this.pos + 1); if (next >= 48 && next <= 57) { return this.readNumber(true) } var next2 = this.input.charCodeAt(this.pos + 2); if (this.options.ecmaVersion >= 6 && next === 46 && next2 === 46) { // 46 = dot '.' this.pos += 3; return this.finishToken(types.ellipsis) } else { ++this.pos; return this.finishToken(types.dot) } }; pp$8.readToken_slash = function() { // '/' var next = this.input.charCodeAt(this.pos + 1); if (this.exprAllowed) { ++this.pos; return this.readRegexp() } if (next === 61) { return this.finishOp(types.assign, 2) } return this.finishOp(types.slash, 1) }; pp$8.readToken_mult_modulo_exp = function(code) { // '%*' var next = this.input.charCodeAt(this.pos + 1); var size = 1; var tokentype = code === 42 ? types.star : types.modulo; // exponentiation operator ** and **= if (this.options.ecmaVersion >= 7 && code == 42 && next === 42) { ++size; tokentype = types.starstar; next = this.input.charCodeAt(this.pos + 2); } if (next === 61) { return this.finishOp(types.assign, size + 1) } return this.finishOp(tokentype, size) }; pp$8.readToken_pipe_amp = function(code) { // '|&' var next = this.input.charCodeAt(this.pos + 1); if (next === code) { return this.finishOp(code === 124 ? types.logicalOR : types.logicalAND, 2) } if (next === 61) { return this.finishOp(types.assign, 2) } return this.finishOp(code === 124 ? types.bitwiseOR : types.bitwiseAND, 1) }; pp$8.readToken_caret = function() { // '^' var next = this.input.charCodeAt(this.pos + 1); if (next === 61) { return this.finishOp(types.assign, 2) } return this.finishOp(types.bitwiseXOR, 1) }; pp$8.readToken_plus_min = function(code) { // '+-' var next = this.input.charCodeAt(this.pos + 1); if (next === code) { if (next == 45 && !this.inModule && this.input.charCodeAt(this.pos + 2) == 62 && (this.lastTokEnd === 0 || lineBreak.test(this.input.slice(this.lastTokEnd, this.pos)))) { // A `-->` line comment this.skipLineComment(3); this.skipSpace(); return this.nextToken() } return this.finishOp(types.incDec, 2) } if (next === 61) { return this.finishOp(types.assign, 2) } return this.finishOp(types.plusMin, 1) }; pp$8.readToken_lt_gt = function(code) { // '<>' var next = this.input.charCodeAt(this.pos + 1); var size = 1; if (next === code) { size = code === 62 && this.input.charCodeAt(this.pos + 2) === 62 ? 3 : 2; if (this.input.charCodeAt(this.pos + size) === 61) { return this.finishOp(types.assign, size + 1) } return this.finishOp(types.bitShift, size) } if (next == 33 && code == 60 && !this.inModule && this.input.charCodeAt(this.pos + 2) == 45 && this.input.charCodeAt(this.pos + 3) == 45) { // `" + line.slice(column), betterErr = new SyntaxError(newMessage); betterErr.loc = { line: row, column: column }; betterErr.pos = pos; throw betterErr; } else throw err; } if (options.addSource) addSource(parsed, source); if (options.addAstIndex && !parsed.hasOwnProperty('astIndex')) addAstIndex(parsed); if (parsed && comments) attachCommentsToAST({ ast: parsed, comments: comments, nodesWithComments: [] }); return parsed; // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- function attachCommentsToAST(commentData) { // for each comment: assign the comment to a block-level AST node commentData = mergeComments(assignCommentsToBlockNodes(commentData)); parsed.allComments = commentData.comments; } function assignCommentsToBlockNodes(commentData) { comments.forEach(function (comment) { var node = lively_lang.arr.detect(nodesAt(comment.start, parsed).reverse(), function (node) { return node.type === 'BlockStatement' || node.type === 'Program'; }); if (!node) node = parsed; if (!node.comments) node.comments = []; node.comments.push(comment); commentData.nodesWithComments.push(node); }); return commentData; } function mergeComments(commentData) { // coalesce non-block comments (multiple following lines of "// ...") into one comment. // This only happens if line comments aren't seperated by newlines commentData.nodesWithComments.forEach(function (blockNode) { lively_lang.arr.clone(blockNode.comments).reduce(function (coalesceData, comment) { if (comment.isBlock) { coalesceData.lastComment = null; return coalesceData; } if (!coalesceData.lastComment) { coalesceData.lastComment = comment; return coalesceData; } // if the comments are seperated by a statement, don't merge var last = coalesceData.lastComment; var nodeInbetween = lively_lang.arr.detect(blockNode.body, function (node) { return node.start >= last.end && node.end <= comment.start; }); if (nodeInbetween) { coalesceData.lastComment = comment; return coalesceData; } // if the comments are seperated by a newline, don't merge var codeInBetween = source.slice(last.end, comment.start); if (/[\n\r][\n\r]+/.test(codeInBetween)) { coalesceData.lastComment = comment; return coalesceData; } // merge comments into one last.text += "\n" + comment.text; last.end = comment.end; lively_lang.arr.remove(blockNode.comments, comment); lively_lang.arr.remove(commentData.comments, comment); return coalesceData; }, { lastComment: null }); }); return commentData; } } /*global process, global, exports*/ var methods = { withMozillaAstDo: function withMozillaAstDo(parsed, state, func) { // simple interface to mozilla AST visitor. function gets passed three // arguments: // acceptNext, -- continue visiting // node, -- current node being visited // state -- state variable that is passed along var vis = new Visitor(), origAccept = vis.accept; vis.accept = function (node, st, path) { var next = function next() { origAccept.call(vis, node, st, path); }; state = func(next, node, st, path); return node; }; vis.accept(parsed, state, []); return state; }, printAst: function printAst(astOrSource, options) { options = options || {}; var printSource = options.printSource || false, printPositions = options.printPositions || false, printIndex = options.printIndex || false, source, parsed, tree$$1 = []; if (typeof astOrSource === "string") { source = astOrSource; parsed = parse(astOrSource); } else { parsed = astOrSource;source = options.source || parsed.source; } if (printSource && !parsed.source) { // ensure that nodes have source attached if (!source) { source = stringify(parsed); parsed = parse(source); } addSource(parsed, source); } function printFunc(ea) { var line = ea.path + ':' + ea.node.type, additional = []; if (printIndex) { additional.push(ea.index); } if (printPositions) { additional.push(ea.node.start + '-' + ea.node.end); } if (printSource) { var src = ea.node.source || source.slice(ea.node.start, ea.node.end), printed = lively_lang.string.print(src.truncate(60).replace(/\n/g, '').replace(/\s+/g, ' ')); additional.push(printed); } if (additional.length) { line += '(' + additional.join(',') + ')'; } return line; } new PrinterVisitor().accept(parsed, { index: 0, tree: tree$$1 }, []); return lively_lang.string.printTree(tree$$1[0], printFunc, function (ea) { return ea.children; }, ' '); }, compareAst: function compareAst(node1, node2) { if (!node1 || !node2) throw new Error('node' + (node1 ? '1' : '2') + ' not defined'); var state = { completePath: [], comparisons: { errors: [] } }; new ComparisonVisitor().accept(node1, node2, state, []); return !state.comparisons.errors.length ? null : state.comparisons.errors.pluck('msg'); }, pathToNode: function pathToNode(parsed, index, options) { options = options || {}; if (!parsed.astIndex) addAstIndex(parsed); var vis = new Visitor(), found = null; (vis.accept = function (node, pathToHere, state, path) { if (found) return; var fullPath = pathToHere.concat(path); if (node.astIndex === index) { var pathString = fullPath.map(function (ea) { return typeof ea === 'string' ? '.' + ea : '[' + ea + ']'; }).join(''); found = { pathString: pathString, path: fullPath, node: node }; } return this['visit' + node.type](node, fullPath, state, path); }).call(vis, parsed, [], {}, []); return found; }, rematchAstWithSource: function rematchAstWithSource(parsed, source, addLocations, subTreePath) { addLocations = !!addLocations; var parsed2 = parse(source, addLocations ? { locations: true } : undefined), visitor = new Visitor(); if (subTreePath) parsed2 = lively_lang.Path(subTreePath).get(parsed2); visitor.accept = function (node, state, path) { path = path || []; var node2 = path.reduce(function (node, pathElem) { return node[pathElem]; }, parsed); node2.start = node.start; node2.end = node.end; if (addLocations) node2.loc = node.loc; return this['visit' + node.type](node, state, path); }; visitor.accept(parsed2); } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- };var withMozillaAstDo = methods.withMozillaAstDo; var printAst = methods.printAst; var compareAst = methods.compareAst; var pathToNode = methods.pathToNode; var rematchAstWithSource = methods.rematchAstWithSource; // obj.extend(ast, methods); // FIXME! Don't extend acorn object! // obj.extend(ast.acorn, methods); var identifierRe = /[_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*$/; function isIdentifier(string$$1) { // Note: It's not so easy... // http://wiki.ecmascript.org/doku.php?id=strawman:identifier_identification // https://mathiasbynens.be/notes/javascript-identifiers-es6 return identifierRe.test(string$$1) && string$$1.indexOf("-") === -1; } function id(name) { return name === "this" ? { type: "ThisExpression" } : { name: String(name), type: "Identifier" }; } function literal(value) { return { type: "Literal", value: value }; } function exprStmt(expression) { return { type: "ExpressionStatement", expression: expression }; } function returnStmt(expr) { return { type: "ReturnStatement", argument: expr }; } function empty() { return { type: "EmptyStatement" }; } function binaryExpr(left, op, right) { return { left: left, right: right, operator: op, type: "BinaryExpression" }; } function funcExpr(_ref) { for (var _len = arguments.length, statements = Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) { statements[_key - 2] = arguments[_key]; } var arrow = _ref.arrow, funcId = _ref.id, expression = _ref.expression, generator = _ref.generator; var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; // lively.ast.stringify(funcExpr({id: "foo"}, ["a"], exprStmt(id("3")))) // // => "function foo(a) { 3; }" params = params.map(function (ea) { return typeof ea === "string" ? id(ea) : ea; }); return { type: (arrow ? "Arrow" : "") + "FunctionExpression", id: funcId ? typeof funcId === "string" ? id(funcId) : funcId : undefined, params: params, body: expression && statements.length === 1 ? statements[0] : { body: statements, type: "BlockStatement" }, expression: expression || false, generator: generator || false }; } function funcCall(callee) { for (var _len2 = arguments.length, args = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { args[_key2 - 1] = arguments[_key2]; } if (typeof callee === "string") callee = id(callee); return { type: "CallExpression", callee: callee, arguments: args }; } function varDecl(id, init, kind) { if (typeof id === "string") id = { name: id, type: "Identifier" }; return { type: "VariableDeclaration", kind: kind || "var", declarations: [{ type: "VariableDeclarator", id: id, init: init }] }; } function member(obj$$1, prop, computed) { // Example: // lively.ast.stringify(member("foo", "bar")) // // => "foo.bar" // lively.ast.stringify(member("foo", "b-a-r")) // // => "foo['b-a-r']" // lively.ast.stringify(member("foo", "zork", true)) // // => "foo['zork']" // lively.ast.stringify(member("foo", 0)) // // => "foo[0]" if (typeof obj$$1 === "string") obj$$1 = id(obj$$1); if (typeof prop === "string") { if (!computed && !isIdentifier(prop)) computed = true; prop = computed ? literal(prop) : id(prop); } else if (typeof prop === "number") { prop = literal(prop); computed = true; } else if (prop.type === "Literal") { computed = true; } return { type: "MemberExpression", computed: !!computed, object: obj$$1, property: prop }; } function memberChain(first) { for (var _len3 = arguments.length, rest = Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) { rest[_key3 - 1] = arguments[_key3]; } // lively.ast.stringify(memberChain("foo", "bar", 0, "baz-zork")); // // => "foo.bar[0]['baz-zork']" return rest.reduce(function (memberExpr, key) { return member(memberExpr, key); }, (typeof first === "undefined" ? "undefined" : _typeof(first)) === "object" ? first : id(first)); } function assign(left, right) { // lively.ast.stringify(assign("a", "x")) // // => "a = x" // lively.ast.stringify(assign(member("a", "x"), literal(23))) // // => "a.x = 23" return { type: "AssignmentExpression", operator: "=", right: right ? typeof right === "string" ? id(right) : right : id("undefined"), left: typeof left === "string" ? id(left) : left }; } function block$1() { for (var _len4 = arguments.length, body = Array(_len4), _key4 = 0; _key4 < _len4; _key4++) { body[_key4] = arguments[_key4]; } return { body: Array.isArray(body[0]) ? body[0] : body, type: "BlockStatement" }; } function program() { return Object.assign(block$1.apply(undefined, arguments), { sourceType: "module", type: "Program" }); } function tryStmt(exName, handlerBody, finalizerBody) { for (var _len5 = arguments.length, body = Array(_len5 > 3 ? _len5 - 3 : 0), _key5 = 3; _key5 < _len5; _key5++) { body[_key5 - 3] = arguments[_key5]; } // Example: // var stmt = exprStmt(binaryExpr(literal(3), "+", literal(2))); // lively.ast.stringify(tryStmt("err", [stmt], [stmt], stmt, stmt)) // // => "try { 3 + 2; 3 + 2; } catch (err) { 3 + 2; } finally { 3 + 2; }" if (!Array.isArray(finalizerBody)) { body.unshift(finalizerBody); finalizerBody = null; } return { block: block$1(body), finalizer: finalizerBody ? block$1(finalizerBody) : null, handler: { body: block$1(handlerBody), param: id(exName), type: "CatchClause" }, type: "TryStatement" }; } function prop(key, value) { return { type: "Property", key: key, computed: key.type !== "Identifier", shorthand: false, value: value }; } function objectLiteral(keysAndValues) { var props = []; for (var i = 0; i < keysAndValues.length; i += 2) { var key = keysAndValues[i]; if (typeof key === "string") key = id(key); props.push(prop(key, keysAndValues[i + 1])); } return { properties: props, type: "ObjectExpression" }; } function ifStmt(test) { var consequent = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : block$1(); var alternate = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : block$1(); return { consequent: consequent, alternate: alternate, test: test, type: "IfStatement" }; } function forIn(varDeclOrName, objExprOrName, body) { return { type: "ForInStatement", left: typeof varDeclOrName === "string" ? varDecl(varDeclOrName) : varDeclOrName, right: typeof objExprOrName === "string" ? id(objExprOrName) : objExprOrName, body: body }; } function conditional(test) { var consequent = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : id("undefined"); var alternate = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : id("undefined"); return { consequent: consequent, alternate: alternate, test: test, type: "ConditionalExpression" }; } function logical(op, left, right) { return { operator: op, left: left, right: right, type: "LogicalExpression" }; } var nodes = Object.freeze({ isIdentifier: isIdentifier, id: id, literal: literal, objectLiteral: objectLiteral, prop: prop, exprStmt: exprStmt, returnStmt: returnStmt, empty: empty, binaryExpr: binaryExpr, funcExpr: funcExpr, funcCall: funcCall, varDecl: varDecl, member: member, memberChain: memberChain, assign: assign, block: block$1, program: program, tryStmt: tryStmt, ifStmt: ifStmt, forIn: forIn, conditional: conditional, logical: logical }); // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- var helpers = { declIds: function declIds(nodes) { var result = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; for (var i = 0; i < nodes.length; i++) { var node = nodes[i]; if (!node) continue;else if (node.type === "Identifier") result.push(node);else if (node.type === "RestElement") result.push(node.argument); // AssignmentPattern: default arg like function(local = defaultVal) {} else if (node.type === "AssignmentPattern") helpers.declIds([node.left], result);else if (node.type === "ObjectPattern") { for (var j = 0; j < node.properties.length; j++) { var prop = node.properties[j]; helpers.declIds([prop.value || prop], result); } } else if (node.type === "ArrayPattern") helpers.declIds(node.elements, result); } return result; }, varDecls: function varDecls(scope) { var result = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = scope.varDecls[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var varDecl = _step.value; var _iteratorNormalCompletion2 = true; var _didIteratorError2 = false; var _iteratorError2 = undefined; try { for (var _iterator2 = varDecl.declarations[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { var decl = _step2.value; var _iteratorNormalCompletion3 = true; var _didIteratorError3 = false; var _iteratorError3 = undefined; try { for (var _iterator3 = helpers.declIds([decl.id])[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) { var id = _step3.value; result.push([decl, id]); } } catch (err) { _didIteratorError3 = true; _iteratorError3 = err; } finally { try { if (!_iteratorNormalCompletion3 && _iterator3.return) { _iterator3.return(); } } finally { if (_didIteratorError3) { throw _iteratorError3; } } } } } catch (err) { _didIteratorError2 = true; _iteratorError2 = err; } finally { try { if (!_iteratorNormalCompletion2 && _iterator2.return) { _iterator2.return(); } } finally { if (_didIteratorError2) { throw _iteratorError2; } } } } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } return result; }, varDeclIds: function varDeclIds(scope) { var result = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; var _iteratorNormalCompletion4 = true; var _didIteratorError4 = false; var _iteratorError4 = undefined; try { for (var _iterator4 = scope.varDecls[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) { var varDecl = _step4.value; var _iteratorNormalCompletion5 = true; var _didIteratorError5 = false; var _iteratorError5 = undefined; try { for (var _iterator5 = varDecl.declarations[Symbol.iterator](), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) { var decl = _step5.value; helpers.declIds([decl.id], result); } } catch (err) { _didIteratorError5 = true; _iteratorError5 = err; } finally { try { if (!_iteratorNormalCompletion5 && _iterator5.return) { _iterator5.return(); } } finally { if (_didIteratorError5) { throw _iteratorError5; } } } } } catch (err) { _didIteratorError4 = true; _iteratorError4 = err; } finally { try { if (!_iteratorNormalCompletion4 && _iterator4.return) { _iterator4.return(); } } finally { if (_didIteratorError4) { throw _iteratorError4; } } } return result; }, objPropertiesAsList: function objPropertiesAsList(objExpr, path, onlyLeafs) { var result = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : []; // takes an obj expr like {x: 23, y: [{z: 4}]} an returns the key and value // nodes as a list var _iteratorNormalCompletion6 = true; var _didIteratorError6 = false; var _iteratorError6 = undefined; try { for (var _iterator6 = objExpr.properties[Symbol.iterator](), _step6; !(_iteratorNormalCompletion6 = (_step6 = _iterator6.next()).done); _iteratorNormalCompletion6 = true) { var prop = _step6.value; var key = prop.key.name, thisNode = { key: path.concat([key]), value: prop.value }; switch (prop.value.type) { case "ArrayExpression":case "ArrayPattern": if (!onlyLeafs) result.push(thisNode); for (var i = 0; i < prop.value.elements.length; i++) { var el = prop.value.elements[i]; helpers.objPropertiesAsList(el, path.concat([key, i]), onlyLeafs, result); } break; case "ObjectExpression":case "ObjectPattern": if (!onlyLeafs) result.push(thisNode); helpers.objPropertiesAsList(prop.value, path.concat([key]), onlyLeafs, result); break; case "AssignmentPattern": if (!onlyLeafs) result.push(thisNode); helpers.objPropertiesAsList(prop.left, path.concat([key]), onlyLeafs, result); break; default: result.push(thisNode); } } } catch (err) { _didIteratorError6 = true; _iteratorError6 = err; } finally { try { if (!_iteratorNormalCompletion6 && _iterator6.return) { _iterator6.return(); } } finally { if (_didIteratorError6) { throw _iteratorError6; } } } return result; }, isDeclaration: function isDeclaration(node) { return node.type === "FunctionDeclaration" || node.type === "VariableDeclaration" || node.type === "ClassDeclaration"; } }; // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- var knownGlobals = ["true", "false", "null", "undefined", "arguments", "Object", "Function", "Array", "Number", "parseFloat", "parseInt", "Infinity", "NaN", "Boolean", "String", "Symbol", "Date", "Promise", "RegExp", "Error", "EvalError", "RangeError", "ReferenceError", "SyntaxError", "TypeError", "URIError", "JSON", "Math", "console", "ArrayBuffer", "Uint8Array", "Int8Array", "Uint16Array", "Int16Array", "Uint32Array", "Int32Array", "Float32Array", "Float64Array", "Uint8ClampedArray", "DataView", "Map", "Set", "WeakMap", "WeakSet", "Proxy", "Reflect", "decodeURI", "decodeURIComponent", "encodeURI", "encodeURIComponent", "escape", "unescape", "eval", "isFinite", "isNaN", "Intl", "navigator", "window", "document", "Blob", "setTimeout", "clearTimeout", "setInterval", "clearInterval", "requestAnimationFrame", "cancelAnimationFrame", "btoa", "atob", "sessionStorage", "localStorage", "$world", "lively"]; function scopes(parsed) { var vis = new ScopeVisitor(), scope = vis.newScope(parsed, null); vis.accept(parsed, scope, []); return scope; } function nodesAtIndex(parsed, index) { return withMozillaAstDo(parsed, [], function (next, node, found) { if (node.start <= index && index <= node.end) { found.push(node);next(); } return found; }); } function scopesAtIndex(parsed, index) { return lively_lang.tree.filter(scopes(parsed), function (scope) { var n = scope.node; var start = n.start, end = n.end; if (n.type === 'FunctionDeclaration') { start = n.params.length ? n.params[0].start : n.body.start; end = n.body.end; } return start <= index && index <= end; }, function (s) { return s.subScopes; }); } function scopeAtIndex(parsed, index) { return lively_lang.arr.last(scopesAtIndex(parsed, index)); } function scopesAtPos(pos, parsed) { // DEPRECATED // FIXME "scopes" should actually not referer to a node but to a scope // object, see exports.scopes! return nodesAt$1(pos, parsed).filter(function (node) { return node.type === 'Program' || node.type === 'FunctionDeclaration' || node.type === 'FunctionExpression'; }); } function nodesInScopeOf(node) { // DEPRECATED // FIXME "scopes" should actually not referer to a node but to a scope // object, see exports.scopes! return withMozillaAstDo(node, { root: node, result: [] }, function (next, node, state) { state.result.push(node); if (node !== state.root && (node.type === 'Program' || node.type === 'FunctionDeclaration' || node.type === 'FunctionExpression')) return state; next(); return state; }).result; } function declarationsOfScope(scope, includeOuter) { var result = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : []; // returns Identifier nodes if (includeOuter && scope.node.id && scope.node.id.name) result.push(scope.node.id); helpers.declIds(scope.params, result); for (var i = 0; i < scope.funcDecls.length; i++) { var id = scope.funcDecls[i].id; if (id) result.push(id); } helpers.varDeclIds(scope, result); result.push.apply(result, toConsumableArray(scope.catches)); for (var i = 0; i < scope.classDecls.length; i++) { var id = scope.classDecls[i].id; if (id) result.push(id); } result.push.apply(result, toConsumableArray(scope.importSpecifiers)); return result; } function declarationsWithIdsOfScope(scope) { // returns a list of pairs [(DeclarationNode,IdentifierNode)] var bareIds = helpers.declIds(scope.params).concat(scope.catches), declNodes = (scope.node.id && scope.node.id.name ? [scope.node] : []).concat(scope.funcDecls.filter(function (ea) { return ea.id; })).concat(scope.classDecls.filter(function (ea) { return ea.id; })); return bareIds.map(function (ea) { return [ea, ea]; }).concat(declNodes.map(function (ea) { return [ea, ea.id]; })).concat(helpers.varDecls(scope)).concat(scope.importSpecifiers.map(function (im) { return [statementOf(scope.node, im), im]; })); } function _declaredVarNames(scope, useComments) { var result = []; var _iteratorNormalCompletion7 = true; var _didIteratorError7 = false; var _iteratorError7 = undefined; try { for (var _iterator7 = declarationsOfScope(scope, true)[Symbol.iterator](), _step7; !(_iteratorNormalCompletion7 = (_step7 = _iterator7.next()).done); _iteratorNormalCompletion7 = true) { var decl = _step7.value; result.push(decl.name); } } catch (err) { _didIteratorError7 = true; _iteratorError7 = err; } finally { try { if (!_iteratorNormalCompletion7 && _iterator7.return) { _iterator7.return(); } } finally { if (_didIteratorError7) { throw _iteratorError7; } } } if (useComments) { _findJsLintGlobalDeclarations(scope.node.type === 'Program' ? scope.node : scope.node.body, result); } return result; } var globalDeclRe = /^\s*global\s*/; function _findJsLintGlobalDeclarations(node) { var result = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; if (!node || !node.comments) return result; var _iteratorNormalCompletion8 = true; var _didIteratorError8 = false; var _iteratorError8 = undefined; try { for (var _iterator8 = node.comments[Symbol.iterator](), _step8; !(_iteratorNormalCompletion8 = (_step8 = _iterator8.next()).done); _iteratorNormalCompletion8 = true) { var comment = _step8.value; var text = comment.text.trim(); if (!text.startsWith("global")) continue; var _iteratorNormalCompletion9 = true; var _didIteratorError9 = false; var _iteratorError9 = undefined; try { for (var _iterator9 = text.replace(globalDeclRe, '').split(',')[Symbol.iterator](), _step9; !(_iteratorNormalCompletion9 = (_step9 = _iterator9.next()).done); _iteratorNormalCompletion9 = true) { var globalDecl = _step9.value; result.push(globalDecl.trim()); } } catch (err) { _didIteratorError9 = true; _iteratorError9 = err; } finally { try { if (!_iteratorNormalCompletion9 && _iterator9.return) { _iterator9.return(); } } finally { if (_didIteratorError9) { throw _iteratorError9; } } } } } catch (err) { _didIteratorError8 = true; _iteratorError8 = err; } finally { try { if (!_iteratorNormalCompletion8 && _iterator8.return) { _iterator8.return(); } } finally { if (_didIteratorError8) { throw _iteratorError8; } } } return result; } function topLevelFuncDecls(parsed) { return FindToplevelFuncDeclVisitor.run(parsed); } function resolveReference(ref, scopePath) { if (scopePath.length == 0) return [null, null]; var _scopePath = toArray(scopePath), scope = _scopePath[0], outer = _scopePath.slice(1); var decls = scope.decls || declarationsWithIdsOfScope(scope); scope.decls = decls; var decl = decls.find(function (_ref) { var _ref2 = slicedToArray(_ref, 2), _ = _ref2[0], id = _ref2[1]; return id.name == ref; }); return decl || resolveReference(ref, outer); } function resolveReferences(scope) { function rec(scope, outerScopes) { var path = [scope].concat(outerScopes); scope.refs.forEach(function (ref) { var _resolveReference = resolveReference(ref.name, path), _resolveReference2 = slicedToArray(_resolveReference, 2), decl = _resolveReference2[0], id = _resolveReference2[1]; map.set(ref, { decl: decl, declId: id, ref: ref }); }); scope.subScopes.forEach(function (s) { return rec(s, path); }); } if (scope.referencesResolvedSafely) return scope; var map = scope.resolvedRefMap || (scope.resolvedRefMap = new Map()); rec(scope, []); scope.referencesResolvedSafely = true; return scope; } function refWithDeclAt(pos, scope) { var _iteratorNormalCompletion10 = true; var _didIteratorError10 = false; var _iteratorError10 = undefined; try { for (var _iterator10 = scope.resolvedRefMap.values()[Symbol.iterator](), _step10; !(_iteratorNormalCompletion10 = (_step10 = _iterator10.next()).done); _iteratorNormalCompletion10 = true) { var ref = _step10.value; var _ref$ref = ref.ref, start = _ref$ref.start, end = _ref$ref.end; if (start <= pos && pos <= end) return ref; } } catch (err) { _didIteratorError10 = true; _iteratorError10 = err; } finally { try { if (!_iteratorNormalCompletion10 && _iterator10.return) { _iterator10.return(); } } finally { if (_didIteratorError10) { throw _iteratorError10; } } } } function topLevelDeclsAndRefs(parsed, options) { options = options || {}; options.withComments = true; if (typeof parsed === "string") parsed = parse(parsed, options); var scope = scopes(parsed), useComments = !!options.jslintGlobalComment, declared = _declaredVarNames(scope, useComments), refs = scope.refs.concat(lively_lang.arr.flatten(scope.subScopes.map(findUndeclaredReferences))), undeclared = lively_lang.arr.withoutAll(refs.map(function (ea) { return ea.name; }), declared); return { scope: scope, varDecls: scope.varDecls, funcDecls: scope.funcDecls.filter(function (ea) { return ea.id; }), classDecls: scope.classDecls.filter(function (ea) { return ea.id; }), declaredNames: declared, undeclaredNames: undeclared, refs: refs, thisRefs: scope.thisRefs // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- };function findUndeclaredReferences(scope) { var names = _declaredVarNames(scope, useComments); return scope.subScopes.map(findUndeclaredReferences).reduce(function (refs, ea) { return refs.concat(ea); }, scope.refs).filter(function (ref) { return names.indexOf(ref.name) === -1; }); } } function findGlobalVarRefs(parsed, options) { var topLevel = topLevelDeclsAndRefs(parsed, options), noGlobals = topLevel.declaredNames.concat(knownGlobals); return topLevel.refs.filter(function (ea) { return noGlobals.indexOf(ea.name) === -1; }); } function findNodesIncludingLines(parsed, code, lines, options) { if (!code && !parsed) throw new Error("Need at least ast or code"); code = code ? code : stringify(parsed); parsed = parsed && parsed.loc ? parsed : parse(code, { locations: true }); return withMozillaAstDo(parsed, [], function (next, node, found) { if (lines.every(function (line) { return lively_lang.num.between(line, node.loc.start.line, node.loc.end.line); })) { lively_lang.arr.pushIfNotIncluded(found, node);next(); } return found; }); } function __varDeclIdsFor(scope, name) { var result = []; var _iteratorNormalCompletion11 = true; var _didIteratorError11 = false; var _iteratorError11 = undefined; try { for (var _iterator11 = scope.params[Symbol.iterator](), _step11; !(_iteratorNormalCompletion11 = (_step11 = _iterator11.next()).done); _iteratorNormalCompletion11 = true) { var ea = _step11.value; if (ea.name === name) result.push(ea); } } catch (err) { _didIteratorError11 = true; _iteratorError11 = err; } finally { try { if (!_iteratorNormalCompletion11 && _iterator11.return) { _iterator11.return(); } } finally { if (_didIteratorError11) { throw _iteratorError11; } } } var _iteratorNormalCompletion12 = true; var _didIteratorError12 = false; var _iteratorError12 = undefined; try { for (var _iterator12 = scope.funcDecls[Symbol.iterator](), _step12; !(_iteratorNormalCompletion12 = (_step12 = _iterator12.next()).done); _iteratorNormalCompletion12 = true) { var ea = _step12.value; if (ea.id && ea.id.name === name) result.push(ea.id); } } catch (err) { _didIteratorError12 = true; _iteratorError12 = err; } finally { try { if (!_iteratorNormalCompletion12 && _iterator12.return) { _iterator12.return(); } } finally { if (_didIteratorError12) { throw _iteratorError12; } } } var _iteratorNormalCompletion13 = true; var _didIteratorError13 = false; var _iteratorError13 = undefined; try { for (var _iterator13 = scope.classDecls[Symbol.iterator](), _step13; !(_iteratorNormalCompletion13 = (_step13 = _iterator13.next()).done); _iteratorNormalCompletion13 = true) { var ea = _step13.value; if (ea.id && ea.id.name === name) result.push(ea.id); } } catch (err) { _didIteratorError13 = true; _iteratorError13 = err; } finally { try { if (!_iteratorNormalCompletion13 && _iterator13.return) { _iterator13.return(); } } finally { if (_didIteratorError13) { throw _iteratorError13; } } } var _iteratorNormalCompletion14 = true; var _didIteratorError14 = false; var _iteratorError14 = undefined; try { for (var _iterator14 = scope.importSpecifiers[Symbol.iterator](), _step14; !(_iteratorNormalCompletion14 = (_step14 = _iterator14.next()).done); _iteratorNormalCompletion14 = true) { var ea = _step14.value; if (ea.name === name) result.push(ea); } } catch (err) { _didIteratorError14 = true; _iteratorError14 = err; } finally { try { if (!_iteratorNormalCompletion14 && _iterator14.return) { _iterator14.return(); } } finally { if (_didIteratorError14) { throw _iteratorError14; } } } var _iteratorNormalCompletion15 = true; var _didIteratorError15 = false; var _iteratorError15 = undefined; try { for (var _iterator15 = helpers.varDeclIds(scope)[Symbol.iterator](), _step15; !(_iteratorNormalCompletion15 = (_step15 = _iterator15.next()).done); _iteratorNormalCompletion15 = true) { var ea = _step15.value; if (ea.name === name) result.push(ea); } } catch (err) { _didIteratorError15 = true; _iteratorError15 = err; } finally { try { if (!_iteratorNormalCompletion15 && _iterator15.return) { _iterator15.return(); } } finally { if (_didIteratorError15) { throw _iteratorError15; } } } return result; } function findReferencesAndDeclsInScope(scope, name) { var _result$decls; var startingScope = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; var result = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : { refs: [], decls: [] }; if (name === "this") { var _result$refs; (_result$refs = result.refs).push.apply(_result$refs, toConsumableArray(scope.thisRefs)); return result; } var decls = __varDeclIdsFor(scope, name); if (!startingScope && decls.length) return result; // name shadowed in sub-scope var _iteratorNormalCompletion16 = true; var _didIteratorError16 = false; var _iteratorError16 = undefined; try { for (var _iterator16 = scope.refs[Symbol.iterator](), _step16; !(_iteratorNormalCompletion16 = (_step16 = _iterator16.next()).done); _iteratorNormalCompletion16 = true) { var ref = _step16.value; if (ref.name === name) result.refs.push(ref); } } catch (err) { _didIteratorError16 = true; _iteratorError16 = err; } finally { try { if (!_iteratorNormalCompletion16 && _iterator16.return) { _iterator16.return(); } } finally { if (_didIteratorError16) { throw _iteratorError16; } } } (_result$decls = result.decls).push.apply(_result$decls, toConsumableArray(decls)); var _iteratorNormalCompletion17 = true; var _didIteratorError17 = false; var _iteratorError17 = undefined; try { for (var _iterator17 = scope.subScopes[Symbol.iterator](), _step17; !(_iteratorNormalCompletion17 = (_step17 = _iterator17.next()).done); _iteratorNormalCompletion17 = true) { var subScope = _step17.value; findReferencesAndDeclsInScope(subScope, name, false, result); } } catch (err) { _didIteratorError17 = true; _iteratorError17 = err; } finally { try { if (!_iteratorNormalCompletion17 && _iterator17.return) { _iterator17.return(); } } finally { if (_didIteratorError17) { throw _iteratorError17; } } } return result; } function findDeclarationClosestToIndex(parsed, name, index) { var found = null; lively_lang.arr.detect(scopesAtIndex(parsed, index).reverse(), function (scope) { var decls = declarationsOfScope(scope, true), idx = lively_lang.arr.pluck(decls, 'name').indexOf(name); if (idx === -1) return false; found = decls[idx];return true; }); return found; } function nodesAt$1(pos, ast) { ast = typeof ast === 'string' ? parse(ast) : ast; return acorn.walk.findNodesIncluding(ast, pos); } var _stmtTypes = ["EmptyStatement", "BlockStatement", "ExpressionStatement", "IfStatement", "BreakStatement", "ContinueStatement", "WithStatement", "ReturnStatement", "ThrowStatement", "TryStatement", "WhileStatement", "DoWhileStatement", "ForStatement", "ForInStatement", "ForOfStatement", "DebuggerStatement", "FunctionDeclaration", "VariableDeclaration", "ClassDeclaration", "ImportDeclaration", "ImportDeclaration", "ExportNamedDeclaration", "ExportDefaultDeclaration", "ExportAllDeclaration"]; function statementOf(parsed, node, options) { // Find the statement that a target node is in. Example: // let source be "var x = 1; x + 1;" and we are looking for the // Identifier "x" in "x+1;". The second statement is what will be found. var nodes = nodesAt$1(node.start, parsed), found = nodes.reverse().find(function (node) { return lively_lang.arr.include(_stmtTypes, node.type); }); if (options && options.asPath) { var v = new Visitor(), foundPath = void 0; v.accept = lively_lang.fun.wrap(v.accept, function (proceed, node, state, path) { if (node === found) { foundPath = path;throw new Error("stop search"); } return proceed(node, state, path); }); try { v.accept(parsed, {}, []); } catch (e) {} return foundPath; } return found; } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- // imports and exports // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- function imports(scope) { // like import "fooo"; var imports = [], stmts = scope.node.body || []; for (var i = 0; i < stmts.length; i++) { var stmt = stmts[i]; if (stmt.type !== "ImportDeclaration") continue; if (stmt.specifiers.length === 0) { imports.push({ local: null, imported: null, fromModule: stmt.source.value, node: stmt }); continue; } // like import { x as y } from "fooo"; import * as x from "fooo"; import x from "fooo"; var from = stmt.source ? stmt.source.value : "unknown module"; imports.push.apply(imports, toConsumableArray(stmt.specifiers.map(function (importSpec) { var imported; if (importSpec.type === "ImportNamespaceSpecifier") imported = "*";else if (importSpec.type === "ImportDefaultSpecifier") imported = "default";else if (importSpec.type === "ImportSpecifier") imported = importSpec.imported.name;else imported = null; return { local: importSpec.local ? importSpec.local.name : null, imported: imported, fromModule: from, node: stmt }; }))); } return imports; } function exports$1(scope) { var resolve = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; if (resolve) resolveReferences(scope); var exports = []; var _iteratorNormalCompletion18 = true; var _didIteratorError18 = false; var _iteratorError18 = undefined; try { var _loop = function _loop() { var node = _step18.value; exportsStmt = statementOf(scope.node, node); if (!exportsStmt) return "continue"; from = exportsStmt.source ? exportsStmt.source.value : null; if (exportsStmt.type === "ExportAllDeclaration") { exports.push({ local: null, exported: "*", imported: "*", fromModule: from, node: node, type: "all" }); return "continue"; } if (exportsStmt.type === "ExportDefaultDeclaration") { if (helpers.isDeclaration(exportsStmt.declaration)) { exports.push({ local: exportsStmt.declaration.id ? exportsStmt.declaration.id.name : null, exported: "default", type: exportsStmt.declaration.type === "FunctionDeclaration" ? "function" : exportsStmt.declaration.type === "ClassDeclaration" ? "class" : null, fromModule: null, node: node, decl: exportsStmt.declaration, declId: exportsStmt.declaration.id }); return "continue"; } if (exportsStmt.declaration.type === "Identifier") { var _ref3 = scope.resolvedRefMap.get(exportsStmt.declaration) || {}; decl = _ref3.decl; declId = _ref3.declId; exports.push({ local: exportsStmt.declaration.name, exported: "default", fromModule: null, node: node, type: "id", decl: decl, declId: declId }); return "continue"; } // exportsStmt.declaration is an expression exports.push({ local: null, exported: "default", fromModule: null, node: node, type: "expr", decl: exportsStmt.declaration, declId: exportsStmt.declaration }); return "continue"; } if (exportsStmt.specifiers && exportsStmt.specifiers.length) { exports.push.apply(exports, toConsumableArray(exportsStmt.specifiers.map(function (exportSpec) { var decl, declId; if (from) { // "export { x as y } from 'foo'" is the only case where export // creates a (non-local) declaration itself decl = node;declId = exportSpec.exported; } else if (exportSpec.local) { var resolved = scope.resolvedRefMap.get(exportSpec.local); decl = resolved ? resolved.decl : null; declId = resolved ? resolved.declId : null; } return { local: !from && exportSpec.local ? exportSpec.local.name : null, exported: exportSpec.exported ? exportSpec.exported.name : null, imported: from && exportSpec.local ? exportSpec.local.name : null, fromModule: from || null, type: "id", node: node, decl: decl, declId: declId }; }))); return "continue"; } if (exportsStmt.declaration && exportsStmt.declaration.declarations) { exports.push.apply(exports, toConsumableArray(exportsStmt.declaration.declarations.map(function (decl) { return { local: decl.id ? decl.id.name : "default", exported: decl.id ? decl.id.name : "default", type: exportsStmt.declaration.kind, fromModule: null, node: node, decl: decl, declId: decl.id }; }))); return "continue"; } if (exportsStmt.declaration) { exports.push({ local: exportsStmt.declaration.id ? exportsStmt.declaration.id.name : "default", exported: exportsStmt.declaration.id ? exportsStmt.declaration.id.name : "default", type: exportsStmt.declaration.type === "FunctionDeclaration" ? "function" : exportsStmt.declaration.type === "ClassDeclaration" ? "class" : null, fromModule: null, node: node, decl: exportsStmt.declaration, declId: exportsStmt.declaration.id }); return "continue"; } }; for (var _iterator18 = scope.exportDecls[Symbol.iterator](), _step18; !(_iteratorNormalCompletion18 = (_step18 = _iterator18.next()).done); _iteratorNormalCompletion18 = true) { var exportsStmt; var from; var decl, declId; var _ret = _loop(); if (_ret === "continue") continue; } } catch (err) { _didIteratorError18 = true; _iteratorError18 = err; } finally { try { if (!_iteratorNormalCompletion18 && _iterator18.return) { _iterator18.return(); } } finally { if (_didIteratorError18) { throw _iteratorError18; } } } return lively_lang.arr.uniqBy(exports, function (a, b) { return a.local == b.local && a.exported == b.exported && a.fromModule == b.fromModule; }); } var query = Object.freeze({ helpers: helpers, knownGlobals: knownGlobals, scopes: scopes, nodesAtIndex: nodesAtIndex, scopesAtIndex: scopesAtIndex, scopeAtIndex: scopeAtIndex, scopesAtPos: scopesAtPos, nodesInScopeOf: nodesInScopeOf, declarationsOfScope: declarationsOfScope, _declaredVarNames: _declaredVarNames, _findJsLintGlobalDeclarations: _findJsLintGlobalDeclarations, topLevelDeclsAndRefs: topLevelDeclsAndRefs, topLevelFuncDecls: topLevelFuncDecls, findGlobalVarRefs: findGlobalVarRefs, findNodesIncludingLines: findNodesIncludingLines, findReferencesAndDeclsInScope: findReferencesAndDeclsInScope, findDeclarationClosestToIndex: findDeclarationClosestToIndex, nodesAt: nodesAt$1, statementOf: statementOf, resolveReferences: resolveReferences, refWithDeclAt: refWithDeclAt, imports: imports, exports: exports$1 }); var ObjectSpreadTransformer = function (_Visitor) { inherits(ObjectSpreadTransformer, _Visitor); function ObjectSpreadTransformer() { classCallCheck(this, ObjectSpreadTransformer); return possibleConstructorReturn(this, (ObjectSpreadTransformer.__proto__ || Object.getPrototypeOf(ObjectSpreadTransformer)).apply(this, arguments)); } createClass(ObjectSpreadTransformer, [{ key: "accept", value: function accept(node, state, path) { if (node.type === "ObjectExpression") { node = this.transformSpreadElement(node); } return get(ObjectSpreadTransformer.prototype.__proto__ || Object.getPrototypeOf(ObjectSpreadTransformer.prototype), "accept", this).call(this, node, state, path); } }, { key: "transformSpreadElement", value: function transformSpreadElement(node) { var currentGroup = [], propGroups = [currentGroup]; node.properties.forEach(function (prop$$1) { if (prop$$1.type !== "SpreadElement") currentGroup.push(prop$$1);else { propGroups.push(prop$$1); currentGroup = []; propGroups.push(currentGroup); } }); if (propGroups.length === 1) return node; if (!currentGroup.length) propGroups.pop(); return funcCall.apply(undefined, [member("Object", "assign")].concat(toConsumableArray(propGroups.map(function (group) { return group.type === "SpreadElement" ? group.argument : { properties: group, type: 'ObjectExpression' }; })))); } }]); return ObjectSpreadTransformer; }(Visitor); function objectSpreadTransform(parsed) { // "var x = {y, ...z}" => "var x = Object.assign({ y }, z);" return new ObjectSpreadTransformer().accept(parsed, {}, []); } /*global process, global, exports*/ function _node2string(node) { return node.source || stringify(node); } function _findIndentAt(s, pos) { var bol = lively_lang.string.peekLeft(s, pos, /\s+$/), indent = typeof bol === 'number' ? s.slice(bol, pos) : ''; if (indent[0] === '\n') indent = indent.slice(1); return indent; } function _applyChanges(changes, source) { for (var i = 0; i < changes.length; i++) { var change = changes[i]; if (change.type === 'del') { source = source.slice(0, change.pos) + source.slice(change.pos + change.length); } else if (change.type === 'add') { source = source.slice(0, change.pos) + change.string + source.slice(change.pos); } else { throw new Error('Unexpected change ' + lively_lang.obj.inspect(change)); } } return source; } function _compareNodesForReplacement(nodeA, nodeB) { // equals if (nodeA.start === nodeB.start && nodeA.end === nodeB.end) return 0; // a "left" of b if (nodeA.end <= nodeB.start) return -1; // a "right" of b if (nodeA.start >= nodeB.end) return 1; // a contains b if (nodeA.start <= nodeB.start && nodeA.end >= nodeB.end) return 1; // b contains a if (nodeB.start <= nodeA.start && nodeB.end >= nodeA.end) return -1; throw new Error('Comparing nodes'); } function replaceNode(target, replacementFunc, sourceOrChanges) { // parameters: // - target: ast node // - replacementFunc that gets this node and its source snippet // handed and should produce a new ast node or source code. // - sourceOrChanges: If its a string -- the source code to rewrite // If its and object -- {changes: ARRAY, source: STRING} var sourceChanges = (typeof sourceOrChanges === "undefined" ? "undefined" : _typeof(sourceOrChanges)) === 'object' ? sourceOrChanges : { changes: [], source: sourceOrChanges }, insideChangedBefore = false, pos = sourceChanges.changes.reduce(function (pos, change) { // fixup the start and end indices of target using the del/add // changes already applied if (pos.end < change.pos) return pos; var isInFront = change.pos < pos.start; insideChangedBefore = insideChangedBefore || change.pos >= pos.start && change.pos <= pos.end; if (change.type === 'add') return { start: isInFront ? pos.start + change.string.length : pos.start, end: pos.end + change.string.length }; if (change.type === 'del') return { start: isInFront ? pos.start - change.length : pos.start, end: pos.end - change.length }; throw new Error('Cannot deal with change ' + lively_lang.obj.inspect(change)); }, { start: target.start, end: target.end }); var source = sourceChanges.source, replacement = replacementFunc(target, source.slice(pos.start, pos.end), insideChangedBefore), replacementSource = typeof replacement === "string" ? replacement : Array.isArray(replacement) ? replacement.map(_node2string).join('\n' + _findIndentAt(source, pos.start)) : replacementSource = _node2string(replacement); var changes = [{ type: 'del', pos: pos.start, length: pos.end - pos.start }, { type: 'add', pos: pos.start, string: replacementSource }]; return { changes: sourceChanges.changes.concat(changes), source: _applyChanges(changes, source) }; } function replaceNodes(targetAndReplacementFuncs, sourceOrChanges) { // replace multiple AST nodes, order rewriting from inside out and // top to bottom so that nodes to rewrite can overlap or be contained // in each other var sorted = targetAndReplacementFuncs.sort(function (a, b) { return _compareNodesForReplacement(a.target, b.target); }), sourceChanges = (typeof sourceOrChanges === "undefined" ? "undefined" : _typeof(sourceOrChanges)) === 'object' ? sourceOrChanges : { changes: [], source: sourceOrChanges }; for (var i = 0; i < sorted.length; i++) { var _sorted$i = sorted[i], target = _sorted$i.target, replacementFunc = _sorted$i.replacementFunc; sourceChanges = replaceNode(target, replacementFunc, sourceChanges); } return sourceChanges; } function replace(astOrSource, targetNode, replacementFunc, options) { // replaces targetNode in astOrSource with what replacementFunc returns // (one or multiple ast nodes) // Example: // var ast = exports.parse('foo.bar("hello");') // exports.transform.replace( // ast, ast.body[0].expression, // function(node, source) { // return {type: "CallExpression", // callee: {name: node.arguments[0].value, type: "Identifier"}, // arguments: [{value: "world", type: "Literal"}] // } // }); // => { // source: "hello('world');", // changes: [{pos: 0,length: 16,type: "del"},{pos: 0,string: "hello('world')",type: "add"}] // } var parsed = (typeof astOrSource === "undefined" ? "undefined" : _typeof(astOrSource)) === 'object' ? astOrSource : null, source = typeof astOrSource === 'string' ? astOrSource : parsed.source || _node2string(parsed); return replaceNode(targetNode, replacementFunc, source); } function __findVarDecls(scope) { var varDecls = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; varDecls.push.apply(varDecls, toConsumableArray(scope.varDecls)); var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = scope.subScopes[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var subScope = _step.value; __findVarDecls(subScope, varDecls); } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } return varDecls; } function oneDeclaratorPerVarDecl(astOrSource) { // exports.transform.oneDeclaratorPerVarDecl( // "var x = 3, y = (function() { var y = 3, x = 2; })(); ").source var parsed = (typeof astOrSource === "undefined" ? "undefined" : _typeof(astOrSource)) === 'object' ? astOrSource : parse(astOrSource), source = typeof astOrSource === 'string' ? astOrSource : parsed.source || _node2string(parsed), scope = scopes(parsed), varDecls = __findVarDecls(scope); var targetsAndReplacements = []; var _iteratorNormalCompletion2 = true; var _didIteratorError2 = false; var _iteratorError2 = undefined; try { for (var _iterator2 = varDecls[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { var decl = _step2.value; targetsAndReplacements.push({ target: decl, replacementFunc: function replacementFunc(declNode, s, wasChanged) { if (wasChanged) { // reparse node if necessary, e.g. if init was changed before like in // var x = (function() { var y = ... })(); declNode = parse(s).body[0]; } return declNode.declarations.map(function (ea) { return { type: "VariableDeclaration", kind: "var", declarations: [ea] }; }); } }); } } catch (err) { _didIteratorError2 = true; _iteratorError2 = err; } finally { try { if (!_iteratorNormalCompletion2 && _iterator2.return) { _iterator2.return(); } } finally { if (_didIteratorError2) { throw _iteratorError2; } } } return replaceNodes(targetsAndReplacements, source); } function oneDeclaratorForVarsInDestructoring(astOrSource) { var parsed = (typeof astOrSource === "undefined" ? "undefined" : _typeof(astOrSource)) === 'object' ? astOrSource : parse(astOrSource), source = typeof astOrSource === 'string' ? astOrSource : parsed.source || _node2string(parsed), scope = scopes(parsed), varDecls = __findVarDecls(scope), targetsAndReplacements = []; var _iteratorNormalCompletion3 = true; var _didIteratorError3 = false; var _iteratorError3 = undefined; try { for (var _iterator3 = varDecls[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) { var decl = _step3.value; targetsAndReplacements.push({ target: decl, replacementFunc: function replacementFunc(declNode, s, wasChanged) { if (wasChanged) { // reparse node if necessary, e.g. if init was changed before like in // var x = (function() { var y = ... })(); declNode = parse(s).body[0]; } var nodes = []; var _iteratorNormalCompletion4 = true; var _didIteratorError4 = false; var _iteratorError4 = undefined; try { for (var _iterator4 = declNode.declarations[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) { var _declNode = _step4.value; var extractedId = { type: "Identifier", name: "__temp" }, extractedInit = { type: "VariableDeclaration", kind: "var", declarations: [{ type: "VariableDeclarator", id: extractedId, init: _declNode.init }] }; nodes.push(extractedInit); var _iteratorNormalCompletion5 = true; var _didIteratorError5 = false; var _iteratorError5 = undefined; try { for (var _iterator5 = helpers.objPropertiesAsList(_declNode.id, [], false)[Symbol.iterator](), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) { var _ref2 = _step5.value; var keyPath = _ref2.key; nodes.push(varDecl(keyPath[keyPath.length - 2], memberChain.apply(undefined, [extractedId.name].concat(toConsumableArray(keyPath))), "var")); } } catch (err) { _didIteratorError5 = true; _iteratorError5 = err; } finally { try { if (!_iteratorNormalCompletion5 && _iterator5.return) { _iterator5.return(); } } finally { if (_didIteratorError5) { throw _iteratorError5; } } } } } catch (err) { _didIteratorError4 = true; _iteratorError4 = err; } finally { try { if (!_iteratorNormalCompletion4 && _iterator4.return) { _iterator4.return(); } } finally { if (_didIteratorError4) { throw _iteratorError4; } } } return nodes; } }); } } catch (err) { _didIteratorError3 = true; _iteratorError3 = err; } finally { try { if (!_iteratorNormalCompletion3 && _iterator3.return) { _iterator3.return(); } } finally { if (_didIteratorError3) { throw _iteratorError3; } } } return replaceNodes(targetsAndReplacements, source); } function returnLastStatement(source, opts) { opts = opts || {}; var parsed = parse(source, opts), last = lively_lang.arr.last(parsed.body); if (last.type !== "ExpressionStatement") return opts.asAST ? parsed : source; parsed.body.splice(parsed.body.length - 1, 1, returnStmt(last.expression)); return opts.asAST ? parsed : stringify(parsed); } function wrapInFunction(code, opts) { opts = opts || {}; var transformed = returnLastStatement(code, opts); return opts.asAST ? program(funcExpr.apply(undefined, [{ id: opts.id || undefined }, []].concat(toConsumableArray(transformed.body)))) : "function" + (opts.id ? " " + opts.id : "") + "() {\n" + transformed + "\n}"; } function wrapInStartEndCall(parsed, options) { // Wraps a piece of code into two function calls: One before the first // statement and one after the last. Also wraps the entire thing into a try / // catch block. The end call gets the result of the last statement (if it is // something that returns a value, i.e. an expression) passed as the second // argument. If an error occurs the end function is called with an error as // first parameter // Why? This allows to easily track execution of code, especially for // asynchronus / await code! // Example: // stringify(wrapInStartEndCall("var y = x + 23; y")) // // generates code // try { // __start_execution(); // __lvVarRecorder.y = x + 23; // return __end_execution(null, __lvVarRecorder.y); // } catch (err) { // return __end_execution(err, undefined); // } if (typeof parsed === "string") parsed = parse(parsed); options = options || {}; var isProgram = parsed.type === "Program", startFuncNode = options.startFuncNode || id("__start_execution"), endFuncNode = options.endFuncNode || id("__end_execution"), funcDecls = topLevelFuncDecls(parsed), innerBody = parsed.body, outerBody = []; // 1. Hoist func decls outside the actual eval start - end code. The async / // generator transforms require this! funcDecls.forEach(function (_ref3) { var node = _ref3.node, path = _ref3.path; lively_lang.Path(path).set(parsed, exprStmt(node.id)); outerBody.push(node); }); // 2. add start-eval call innerBody.unshift(exprStmt(funcCall(startFuncNode))); // 3. if last statement is an expression, transform it so we can pass it to // the end-eval call, replacing the original expression. If it's a // non-expression we record undefined as the eval result var last = lively_lang.arr.last(innerBody); if (last.type === "ExpressionStatement") { innerBody.pop(); innerBody.push(exprStmt(funcCall(endFuncNode, id("null"), last.expression))); } else if (last.type === "VariableDeclaration" && lively_lang.arr.last(last.declarations).id.type === "Identifier") { innerBody.push(exprStmt(funcCall(endFuncNode, id("null"), lively_lang.arr.last(last.declarations).id))); } else { innerBody.push(exprStmt(funcCall(endFuncNode, id("null"), id("undefined")))); } // 4. Wrap that stuff in a try stmt outerBody.push(tryStmt.apply(undefined, ["err", [exprStmt(funcCall(endFuncNode, id("err"), id("undefined")))]].concat(toConsumableArray(innerBody)))); return isProgram ? program.apply(undefined, outerBody) : block$1.apply(undefined, outerBody); } var isProbablySingleExpressionRe = /^\s*(\{|function\s*\()/; function transformSingleExpression(code) { // evaling certain expressions such as single functions or object // literals will fail or not work as intended. When the code being // evaluated consists just out of a single expression we will wrap it in // parens to allow for those cases // Example: // transformSingleExpression("{foo: 23}") // => "({foo: 23})" if (!isProbablySingleExpressionRe.test(code) || code.split("\n").length > 30) return code; try { var parsed = fuzzyParse(code); if (parsed.body.length === 1 && (parsed.body[0].type === 'FunctionDeclaration' || parsed.body[0].type === 'BlockStatement' && parsed.body[0].body[0].type === 'LabeledStatement')) { code = '(' + code.replace(/;\s*$/, '') + ')'; } } catch (e) { if (typeof $world !== "undefined") $world.logError(e);else console.error("Eval preprocess error: %s", e.stack || e); } return code; } var transform = Object.freeze({ replaceNode: replaceNode, replaceNodes: replaceNodes, replace: replace, _compareNodesForReplacement: _compareNodesForReplacement, oneDeclaratorPerVarDecl: oneDeclaratorPerVarDecl, oneDeclaratorForVarsInDestructoring: oneDeclaratorForVarsInDestructoring, returnLastStatement: returnLastStatement, wrapInFunction: wrapInFunction, wrapInStartEndCall: wrapInStartEndCall, transformSingleExpression: transformSingleExpression, objectSpreadTransform: objectSpreadTransform }); /*global process, global, exports*/ function getCommentPrecedingNode(parsed, node) { var statementPath = statementOf(parsed, node, { asPath: true }), blockPath = statementPath.slice(0, -2), block = lively_lang.Path(blockPath).get(parsed); return !block.comments || !block.comments.length ? null : lively_lang.chain(extractComments(parsed)).reversed().detect(function (ea) { return ea.followingNode === node; }).value(); } function extractComments(astOrCode, optCode) { var parsed = typeof astOrCode === "string" ? parse(astOrCode, { withComments: true }) : astOrCode, code = optCode ? optCode : typeof astOrCode === "string" ? astOrCode : stringify(astOrCode), parsedComments = lively_lang.arr.sortBy(commentsWithPathsAndNodes(parsed), function (c) { return c.comment.start; }); return parsedComments.map(function (c, i) { // 1. a method comment like "x: function() {\n//foo\n ...}"? if (isInObjectMethod(c)) { return lively_lang.obj.merge([c, c.comment, { type: 'method', comment: c.comment.text }, methodAttributesOf(c)]); } if (isInComputedMethod(c)) { return lively_lang.obj.merge([c, c.comment, { type: 'method', comment: c.comment.text }, computedMethodAttributesOf(c)]); } // 2. function statement comment like "function foo() {\n//foo\n ...}"? if (isInFunctionStatement(c)) { return lively_lang.obj.merge([c, c.comment, { type: 'function', comment: c.comment.text }, functionAttributesOf(c)]); } // 3. assigned method like "foo.bar = function(x) {/*comment*/};" if (isInAssignedMethod(c)) { return lively_lang.obj.merge([c, c.comment, { type: 'method', comment: c.comment.text }, methodAttributesOfAssignment(c)]); } // 4. comment preceding another node? var followingNode = followingNodeOf(c); if (!followingNode) return lively_lang.obj.merge([c, c.comment, { followingNode: followingNode }, unknownComment(c)]); // is there another comment in front of the node> var followingComment = parsedComments[i + 1]; if (followingComment && followingComment.comment.start <= followingNode.start) return lively_lang.obj.merge([c, c.comment, { followingNode: followingNode }, unknownComment(c)]); // 3. an obj var comment like "// foo\nvar obj = {...}"? if (isSingleObjVarDeclaration(followingNode)) { return lively_lang.obj.merge([c, c.comment, { followingNode: followingNode }, { type: 'object', comment: c.comment.text }, objAttributesOf(followingNode)]); } // 4. Is it a simple var declaration like "// foo\nvar obj = 23"? if (isSingleVarDeclaration(followingNode)) { return lively_lang.obj.merge([c, c.comment, { followingNode: followingNode }, { type: 'var', comment: c.comment.text }, objAttributesOf(followingNode)]); } return lively_lang.obj.merge([c, c.comment, { followingNode: followingNode }, unknownComment(c)]); }); // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- function commentsWithPathsAndNodes(parsed) { var comments = [], v = new Visitor(); v.accept = lively_lang.fun.wrap(v.accept, function (proceed, node, state, path) { if (node.comments) { lively_lang.arr.pushAll(comments, node.comments.map(function (comment) { return { path: path, comment: comment, node: node }; })); } return proceed(node, state, path); }); v.accept(parsed, comments, []); return comments; } function followingNodeOf(comment) { return lively_lang.arr.detect(comment.node.body, function (node) { return node.start > comment.comment.end; }); } function unknownComment(comment) { return { type: "unknown", comment: comment.comment.text }; } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- function isInFunctionStatement(comment) { var node = lively_lang.Path(comment.path.slice(0, -1)).get(parsed); return node && node.type === "FunctionDeclaration"; } function functionAttributesOf(comment) { var funcNode = lively_lang.Path(comment.path.slice(0, -1)).get(parsed), name = funcNode.id ? funcNode.id.name : ""; return { name: name, args: lively_lang.arr.pluck(funcNode.params, "name") }; } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- function isInObjectMethod(comment) { return lively_lang.arr.equals(comment.path.slice(-2), ["value", "body"]); // obj expr } function isInAssignedMethod(comment) { return lively_lang.arr.equals(comment.path.slice(-2), ["right", "body"]); // asignment } function methodAttributesOf(comment) { var methodNode = lively_lang.Path(comment.path.slice(0, -2)).get(parsed), name = methodNode.key ? methodNode.key.name : ""; // if it's someting like "var obj = {foo: function() {...}};" var p = comment.path.slice(), objectName = ""; while (p.length && lively_lang.arr.last(p) !== 'init') { p.pop(); }if (p.length) { objectName = lively_lang.Path(p.slice(0, -1).concat(["id", "name"])).get(parsed); } // if it's someting like "exports.obj = {foo: function() {...}};" if (lively_lang.string.startsWith(objectName, ""; } if (!name) { // if it is an object member function pathToProp = comment.path.slice(0, -2); propertyNode = lively_lang.Path(pathToProp).get(parsed); if (propertyNode && propertyNode.type === "Property") { args = lively_lang.arr.pluck(propertyNode.value.params, "name"); name = propertyNode.key ? propertyNode.key.name : ""; } } if (!name) { name = ""; args = []; pathToProp = comment.path; } // if it's someting like "var obj = {foo: function() {...}};" var p = lively_lang.arr.clone(pathToProp); var objectName = ""; while (p.length && lively_lang.arr.last(p) !== 'init') { p.pop(); }if (p.length) { objectName = lively_lang.Path(p.slice(0, -1).concat(["id", "name"])).get(parsed); } // if it's someting like "exports.obj = {foo: function() {...}};" if (lively_lang.string.startsWith(objectName, " 5) { // lively.debugNextMethodCall(lively.ast.CodeCategorizer, "findDecls"); decls = findDecls(argFunc, options); } else { decls = findDecls(lively_lang.Path("expression.callee").get(node), options); } var parent = { node: node, name: lively_lang.Path("expression.callee.id.name").get(node) }; decls.forEach(function (decl) { return decl.parent || (decl.parent = parent); }); return decls; } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- // helpers // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- function unwrapExport(node) { return (node.type === "ExportNamedDeclaration" || node.type === "ExportDefaultDeclaration") && node.declaration ? node.declaration : node; } function objectKeyValsAsDefs(objectExpression, parent) { return objectExpression.properties.map(function (node) { return { name: node.key.name || node.key.value, type: node.value.type === "FunctionExpression" ? "method" : "property", node: node, parent: parent }; }); } function isFunctionWrapper(node) { return lively_lang.Path("expression.type").get(node) === "CallExpression" && lively_lang.Path("expression.callee.type").get(node) === "FunctionExpression"; } function withVarDeclIds(varNode) { return varNode.declarations.map(function (declNode) { if (!declNode.source && declNode.init) declNode.source = declNode.id.name + " = " + declNode.init.source; return { node: declNode, id: declNode.id }; }); } var codeCategorizer = Object.freeze({ findDecls: findDecls }); // ignore-in-doc // As defined in the Ecmascript standard (http://www.ecma-international.org/ecma-262/5.1/#sec-7.6) // JS identifiers can consist out of several unicode character classes. // The code below was generated using the MIT licensed CSET library, see http://inimino.org/~inimino/blog/javascript_cset var isValidIdentifierRe = /^(?!(?:do|if|in|for|let|new|try|var|case|default|else|enum|eval|false|null|this|true|void|with|break|catch|class|const|super|throw|while|yield|delete|export|import|public|return|static|switch|typeof|extends|finally|package|private|continue|debugger|function|arguments|interface|protected|implements|instanceof)$)[$A-Z\_a-z\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc][$A-Z\_a-z\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc0-9\u0300-\u036f\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u0669\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u06f0-\u06f9\u0711\u0730-\u074a\u07a6-\u07b0\u07c0-\u07c9\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u08e4-\u08fe\u0900-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09cb-\u09cd\u09d7\u09e2\u09e3\u09e6-\u09ef\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c3e-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0ce6-\u0cef\u0d02\u0d03\u0d3e-\u0d44\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0d62\u0d63\u0d66-\u0d6f\u0d82\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0e50-\u0e59\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e\u0f3f\u0f71-\u0f84\u0f86\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102b-\u103e\u1040-\u1049\u1056-\u1059\u105e-\u1060\u1062-\u1064\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b4-\u17d3\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u18a9\u1920-\u192b\u1930-\u193b\u1946-\u194f\u19b0-\u19c0\u19c8\u19c9\u19d0-\u19d9\u1a17-\u1a1b\u1a55-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1b00-\u1b04\u1b34-\u1b44\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1b82\u1ba1-\u1bad\u1bb0-\u1bb9\u1be6-\u1bf3\u1c24-\u1c37\u1c40-\u1c49\u1c50-\u1c59\u1cd0-\u1cd2\u1cd4-\u1ce8\u1ced\u1cf2-\u1cf4\u1dc0-\u1de6\u1dfc-\u1dff\u200c\u200d\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua620-\ua629\ua66f\ua674-\ua67d\ua69f\ua6f0\ua6f1\ua802\ua806\ua80b\ua823-\ua827\ua880\ua881\ua8b4-\ua8c4\ua8d0-\ua8d9\ua8e0-\ua8f1\ua900-\ua909\ua926-\ua92d\ua947-\ua953\ua980-\ua983\ua9b3-\ua9c0\ua9d0-\ua9d9\uaa29-\uaa36\uaa43\uaa4c\uaa4d\uaa50-\uaa59\uaa7b\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uaaeb-\uaaef\uaaf5\uaaf6\uabe3-\uabea\uabec\uabed\uabf0-\uabf9\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f]*$/; function isValidIdentifier(string$$1) { return isValidIdentifierRe.test(string$$1); } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- // serialization extension for ast nodes var Node = parse("").constructor; Object.defineProperty(Node.prototype, "__serialize__", { configurable: true, value: function value() { return { __expr__: "(" + JSON.stringify(this) + ")" }; } }); exports.escodegen = es; exports.acorn = acorn; exports.query = query; exports.transform = transform; exports.comments = comments; exports.categorizer = codeCategorizer; exports.stringify = stringify; exports.nodes = nodes; exports.isValidIdentifier = isValidIdentifier; exports.BaseVisitor = Visitor; exports.withMozillaAstDo = withMozillaAstDo; exports.printAst = printAst; exports.compareAst = compareAst; exports.pathToNode = pathToNode; exports.rematchAstWithSource = rematchAstWithSource; exports.ReplaceManyVisitor = ReplaceManyVisitor; exports.ReplaceVisitor = ReplaceVisitor; exports.parse = parse; exports.parseFunction = parseFunction; exports.fuzzyParse = fuzzyParse; }((this.lively.ast = this.lively.ast || {}),lively.lang,GLOBAL.escodegen,acorn)); }).call(GLOBAL); if (typeof module !== "undefined" && module.exports) module.exports = GLOBAL.lively.ast; if (__define_suckz__) { GLOBAL.define = __define_suckz__; } })(); // INLINED END /Users/user/git/lively.vm/node_modules/lively.ast/dist/lively.ast.js // INLINED /Users/user/git/lively.vm/node_modules/lively.classes/dist/lively.classes.js ;(function() { var GLOBAL = typeof window !== "undefined" ? window : typeof global!=="undefined" ? global : typeof self!=="undefined" ? self : this; if (typeof lively.lang === "undefined") GLOBAL.livey.lang = {}; })(); (function() { var GLOBAL = typeof window !== "undefined" ? window : typeof global!=="undefined" ? global : typeof self!=="undefined" ? self : this; this.lively = this.lively || {}; (function (exports,lively_lang,lively_ast) { 'use strict'; var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj$$1) { return typeof obj$$1; } : function (obj$$1) { return obj$$1 && typeof Symbol === "function" && obj$$1.constructor === Symbol && obj$$1 !== Symbol.prototype ? "symbol" : typeof obj$$1; }; 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 defineProperty = function (obj$$1, key, value) { if (key in obj$$1) { Object.defineProperty(obj$$1, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj$$1[key] = value; } return obj$$1; }; var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var get = function get(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(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 inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }; var possibleConstructorReturn = function (self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }; var set = function set(object, property, value, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent !== null) { set(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); } }; // compactness // types -> fabrik // serialization, obscure references // debugging, more usful inspector // change system -> synchronization, serialization, debugging // initialization order, dependencies (ex. btn => label => submoprhs needed) // declaratively configuring objects // propertySettings: { // valueStoreProperty: STRING|SYMBOL - optional, defaults to _state. This is where the // actual values of the properties will be stored by default // defaultGetter: FUNCTION(STRING) - default getter to be used // defaultSetter: FUNCTION(STRING, VALUE) - default setter to be used // } // // ???????????? // propertyDescriptorCacheKey: STRING|SYMBOL - where the result of // initializeProperties() should go // ???????????? // properties: // {STRING: DESCRIPTOR, ...} // properties are merged in the proto chain // // descriptor: { // get: FUNCTION - optional // set: FUNCTION - optional // defaultValue: OBJECT - optional // initialize: FUNCTION - optional, function that when present should // produce a value for the property. Run after object creation // autoSetter: BOOL - optional, true if not specified // usePropertyStore: BOOL - optional, true if not specified. // priority: NUMBER - optional, true if not specified. // before: [STRING] - optional, list of property names that depend on // the descriptor's property and that should be // initialized / sorted / ... *after* // it. Think of it as a constraint: "this property // needs to run before that property" // after: [STRING] - optional, list of property names that this property depends on // internal: BOOL - optional, if specified marks property as meant for // internal housekeeping. At this point this is only used // documentation and debugging purposes, it won't affect // how the property works // } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- var defaultPropertiesKey = "properties"; var propertiesAndSettingsCacheSym = Symbol.for("lively.classes-properties-and-settings"); var defaultPropertySettings = { defaultSetter: null, defaultGetter: null, valueStoreProperty: "_state" }; function hasManagedProperties(klass) { return klass.hasOwnProperty(defaultPropertiesKey); } function prepareClassForManagedPropertiesAfterCreation(klass) { if (!hasManagedProperties(klass)) return; var _propertiesAndSetting = propertiesAndSettingsInHierarchyOf(klass), properties = _propertiesAndSetting.properties, propertySettings = _propertiesAndSetting.propertySettings; klass[propertiesAndSettingsCacheSym] = { properties: properties, propertySettings: propertySettings }; if (!properties || (typeof properties === "undefined" ? "undefined" : _typeof(properties)) !== "object") { console.warn("Class " + klass.name + " indicates it has managed properties but its " + ("properties accessor (" + defaultPropertiesKey + ") does not return ") + "a valid property descriptor map"); return; } prepareClassForProperties(klass, propertySettings, properties); } function prepareClassForProperties(klass, propertySettings, properties) { ensurePropertyInitializer(klass); var valueStoreProperty = propertySettings.valueStoreProperty, defaultGetter = propertySettings.defaultGetter, defaultSetter = propertySettings.defaultSetter, myProto = klass.prototype, keys = Object.keys(properties); keys.forEach(function (key) { var descriptor = properties[key]; // ... define a getter to the property for the outside world... var hasGetter = myProto.hasOwnProperty(key) && myProto.__lookupGetter__(key); if (!hasGetter) { var getter = descriptor.get || typeof defaultGetter === "function" && function () { return defaultGetter.call(this, key); } || function () { return this[valueStoreProperty][key]; }; myProto.__defineGetter__(key, getter); } // ...define a setter if necessary var hasSetter = myProto.hasOwnProperty(key) && myProto.__lookupSetter__(key); if (!hasSetter) { var descrHasSetter = descriptor.hasOwnProperty("set"), setterNeeded = descrHasSetter || !descriptor.readOnly; if (setterNeeded) { var setter = descriptor.set || typeof defaultSetter === "function" && function (val) { defaultSetter.call(this, key, val); } || function (val) { this[valueStoreProperty][key] = val; }; myProto.__defineSetter__(key, setter); } } }); } function ensurePropertyInitializer(klass) { // when we inherit from "conventional classes" those don't have an // initializer method. We install a stub that calls the superclass function // itself Object.defineProperty(klass.prototype, "propertiesAndPropertySettings", { enumerable: false, configurable: true, writable: true, value: function value() { var klass = this.constructor; return klass[propertiesAndSettingsCacheSym] || propertiesAndSettingsInHierarchyOf(klass); } }); Object.defineProperty(klass.prototype, "initializeProperties", { enumerable: false, configurable: true, writable: true, value: function value(values) { var _propertiesAndPropert = this.propertiesAndPropertySettings(), properties = _propertiesAndPropert.properties, propertySettings = _propertiesAndPropert.propertySettings; prepareInstanceForProperties(this, propertySettings, properties, values); return this; } }); } function propertiesAndSettingsInHierarchyOf(klass) { // walks class proto chain var propertySettings = _extends({}, defaultPropertySettings), properties = {}, allPropSettings = lively_lang.obj.valuesInPropertyHierarchy(klass, "propertySettings"), allProps = lively_lang.obj.valuesInPropertyHierarchy(klass, "properties"); for (var i = 0; i < allPropSettings.length; i++) { var current = allPropSettings[i]; current && (typeof current === "undefined" ? "undefined" : _typeof(current)) === "object" && Object.assign(propertySettings, current); } for (var i = 0; i < allProps.length; i++) { var _current = allProps[i]; if ((typeof _current === "undefined" ? "undefined" : _typeof(_current)) !== "object") { console.error("[initializeProperties] " + klass + " encountered property declaration " + ("that is not a JS object: " + _current)); continue; } // "deep" merge for (var name in _current) { if (!properties.hasOwnProperty(name)) properties[name] = _current[name];else Object.assign(properties[name], _current[name]); } } return { properties: properties, propertySettings: propertySettings }; } function prepareInstanceForProperties(instance, propertySettings, properties, values) { var valueStoreProperty = propertySettings.valueStoreProperty, sortedKeys = lively_lang.obj.sortKeysWithBeforeAndAfterConstraints(properties), propsNeedingInitialize = [], initActions = {}; // 1. this[valueStoreProperty] is were the actual values will be stored if (!instance.hasOwnProperty(valueStoreProperty)) instance[valueStoreProperty] = {}; for (var i = 0; i < sortedKeys.length; i++) { var key = sortedKeys[i], descriptor = properties[key]; var derived = descriptor.derived, foldable = !!descriptor.foldable, defaultValue = descriptor.hasOwnProperty("defaultValue") ? descriptor.defaultValue : undefined; if (Array.isArray(defaultValue)) defaultValue = defaultValue.slice(); if (!derived && !foldable) instance[valueStoreProperty][key] = defaultValue; var initAction = void 0; if (descriptor.hasOwnProperty("initialize")) { initAction = initActions[key] = { initialize: defaultValue }; propsNeedingInitialize.push(key); } else if (derived && defaultValue !== undefined) { initAction = initActions[key] = { derived: defaultValue }; propsNeedingInitialize.push(key); } else if (foldable && defaultValue !== undefined) { initAction = initActions[key] = { folded: defaultValue }; propsNeedingInitialize.push(key); } if (values && key in values) { if (descriptor.readOnly) { console.warn("Trying to initialize read-only property " + key + " in " + instance + ", " + "skipping setting value"); } else { if (!initAction) { initAction = initActions[key] = {}; propsNeedingInitialize.push(key); } initAction.value = values[key]; } } } // 2. Run init code for properties // and if we have values we will initialize the properties from it. Values // is expected to be a JS object mapping property names to property values for (var i = 0; i < propsNeedingInitialize.length; i++) { var _key = propsNeedingInitialize[i], actions = initActions[_key], hasValue = actions.hasOwnProperty("value"); // if we have an initialize function we call it either with the value from // values or with the defaultValue if (actions.hasOwnProperty("initialize")) { var value = hasValue ? actions.value : actions.initialize; properties[_key].initialize.call(instance, value); if (hasValue) instance[_key] = actions.value; } // if we have a derived property we will call the setter with the default // value or the value from values else if (actions.hasOwnProperty("derived")) { instance[_key] = hasValue ? actions.value : actions.derived; } else if (actions.hasOwnProperty("folded")) { instance[_key] = hasValue ? actions.value : actions.folded; } // if we only have the value from values we simply call the setter with it else if (hasValue) { instance[_key] = actions.value; } } } var initializeSymbol = Symbol.for("lively-instance-initialize"); var instanceRestorerSymbol = Symbol.for("lively-instance-restorer"); var superclassSymbol = Symbol.for("lively-instance-superclass"); var moduleMetaSymbol = Symbol.for("lively-module-meta"); var objMetaSymbol = Symbol.for("lively-object-meta"); var moduleSubscribeToToplevelChangesSym = Symbol.for("lively-klass-changes-subscriber"); var constructorArgMatcher = /\([^\\)]*\)/; var defaultPropertyDescriptorForGetterSetter = { enumerable: false, configurable: true }; var defaultPropertyDescriptorForValue = { enumerable: false, configurable: true, writable: true }; var setPrototypeOf = typeof Object.setPrototypeOf === "function" ? function (obj$$1, proto) { return Object.setPrototypeOf(obj$$1, proto); } : function (obj$$1, proto) { return obj$$1.__proto__ = proto; }; function adoptObject(object, newClass) { // change the class of object to newClass if (newClass === object.constructor) return; object.constructor = newClass; setPrototypeOf(object, newClass.prototype); } function setSuperclass(klass, superclassOrSpec) { // define klass.prototype, klass.prototype[constructor], klass[superclassSymbol] var superclass = !superclassOrSpec ? Object : typeof superclassOrSpec === "function" ? superclassOrSpec : superclassOrSpec.value ? superclassOrSpec.value : Object; var existingSuperclass = klass && klass[superclassSymbol]; // set the superclass if necessary and set prototype if (!existingSuperclass || existingSuperclass !== superclass) { ensureInitializeStub(superclass); klass[superclassSymbol] = superclass; setPrototypeOf(klass.prototype, superclass.prototype); if (superclass !== Object) setPrototypeOf(klass, superclass); } return superclass; } function installValueDescriptor(object, klass, descr) { descr = Object.assign(descr, defaultPropertyDescriptorForValue); descr.value.displayName = descr.key; if (descr.needsDeclaringClass) { var orig = descr.value.originalFunction || descr.value; descr.value = Object.assign(function declaring_class_wrapper() /*args*/{ return orig.call.apply(orig, [this, klass].concat(Array.prototype.slice.call(arguments))); }, { originalFunction: orig, toString: function toString() { return orig.toString(); }, displayName: descr.key }); } Object.defineProperty(object, descr.key, descr); } function installGetterSetterDescriptor(klass, descr) { descr = Object.assign(descr, defaultPropertyDescriptorForGetterSetter); Object.defineProperty(klass, descr.key, descr); } function installMethods(klass, instanceMethods, classMethods) { // install methods from two lists (static + instance) of {key, value} or // {key, get/set} descriptors classMethods && classMethods.forEach(function (ea) { ea.value ? installValueDescriptor(klass, klass, ea) : installGetterSetterDescriptor(klass, ea); }); instanceMethods && instanceMethods.forEach(function (ea) { ea.value ? installValueDescriptor(klass.prototype, klass, ea) : installGetterSetterDescriptor(klass.prototype, ea); }); // 4. define initializer method, in our class system the constructor is // generic and re-directs to the initializer method. This way we can change // the constructor without loosing the identity of the class if (!klass.prototype[initializeSymbol]) { Object.defineProperty(klass.prototype, initializeSymbol, { enumerable: false, configurable: true, writable: true, value: function value() {} }); klass.prototype[initializeSymbol].isDefaultInitializer = true; klass.prototype[initializeSymbol].displayName = "lively-initialize"; } else { if (Object.getOwnPropertySymbols(klass.prototype).includes(initializeSymbol)) { if (klass.prototype[initializeSymbol].isDefaultInitializer) { if (klass[superclassSymbol].prototype[initializeSymbol]) { delete klass.prototype[initializeSymbol]; } } } } // 5. undefine properties that were removed form class definition var instanceMethodsInClass = instanceMethods.map(function (m) { return m.key; }).concat(["constructor", "arguments", "caller"]), instanceAttributes = Object.getOwnPropertyNames(klass.prototype); for (var i = 0; i < instanceAttributes.length; i++) { var name = instanceAttributes[i]; if (!instanceMethodsInClass.includes(name)) delete klass.prototype[name]; } var classMethodsInClass = classMethods.map(function (m) { return m.key; }).concat(["length", "name", "prototype", "arguments", "caller"]), classAttributes = Object.getOwnPropertyNames(klass); for (var _i = 0; _i < classAttributes.length; _i++) { var _name = classAttributes[_i]; if (!classMethodsInClass.includes(_name)) delete klass[_name]; } } function ensureInitializeStub(superclass) { // when we inherit from "conventional classes" those don't have an // initializer method. We install a stub that calls the superclass function // itself if (superclass === Object || superclass.prototype[initializeSymbol]) return; Object.defineProperty(superclass.prototype, initializeSymbol, { enumerable: false, configurable: true, writable: true, value: function value() /*args*/{ superclass.apply(this, arguments); } }); superclass.prototype[initializeSymbol].displayName = "lively-initialize-stub"; } function initializeClass(constructorFunc, superclassSpec) { var instanceMethods = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : []; var classMethods = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : []; var classHolder = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {}; var currentModule = arguments[5]; var sourceLoc = arguments[6]; // Given a `classHolder` object as "environment", will try to find a "class" // (JS constructor function) inside it. If no class is found it will create a // new costructor function object and will attach the methods to it. If a class // is found it will be modified. // This is being used as the compile target for es6 class syntax by the // lively.ast capturing / transform logic // Example: // var Foo = function(superclass) { // function Foo() {} // return initializeClass(Foo, superclass, [{key: "m", value: function m() { return 23 }}]) // }(); // new Foo().m() // => 23 // 1. create a new constructor function if necessary, re-use an exisiting if the // classHolder object has it var className = constructorFunc.name, klass = className && classHolder.hasOwnProperty(className) && classHolder[className], existingSuperclass = klass && klass[superclassSymbol]; if (!klass || typeof klass !== "function" || !existingSuperclass) klass = constructorFunc; // 2. set the superclass if necessary and set prototype var superclass = setSuperclass(klass, superclassSpec); // 3. Install methods installMethods(klass, instanceMethods, classMethods); klass[objMetaSymbol] = sourceLoc; // 4. If we have a `currentModule` instance (from lively.modules/src/module.js) // then we also store some meta data about the module. This allows us to // (de)serialize class instances in lively.serializer if (currentModule) { var p = currentModule.package(); var prevMeta = klass[moduleMetaSymbol]; var t = Date.now(); klass[moduleMetaSymbol] = { package: p ? { name: p.name, version: p.version } : {}, pathInPackage: p ? currentModule.pathInPackage() : currentModule.id, lastChange: prevMeta && prevMeta.lastChange && t <= prevMeta.lastChange ? prevMeta.lastChange + 1 : t, lastSuperclassChange: 0 // if we have a module, we can listen to toplevel changes of it in case the // superclass binding changes. With that we can keep our class up-to-date // even if the superclass binding changes. This is especially useful for // situations where modules have a circular dependency and classes in modules // won't get defined correctly when loaded first. See // https://github.com/LivelyKernel/lively.modules/issues/27 for more details };if (superclassSpec && superclassSpec.referencedAs) { if (klass.hasOwnProperty(moduleSubscribeToToplevelChangesSym)) { currentModule.unsubscribeFromToplevelDefinitionChanges(klass[moduleSubscribeToToplevelChangesSym]); } klass[moduleSubscribeToToplevelChangesSym] = currentModule.subscribeToToplevelDefinitionChanges(function (name, val) { if (name !== superclassSpec.referencedAs) return; // console.log(`class ${className}: new superclass ${name} ${name !== superclassSpec.referencedAs ? '(' + superclassSpec.referencedAs + ')' : ''} was defined via module bindings`) // Only run through the (expensive) updates if superclass really has changes var superMeta = val && val[moduleMetaSymbol], myMeta = klass[moduleMetaSymbol]; if (superMeta) { if (superMeta.lastChange === myMeta.lastSuperclassChange) return; myMeta.lastSuperclassChange = superMeta.lastChange; } setSuperclass(klass, val); installMethods(klass, instanceMethods, classMethods); prepareClassForManagedPropertiesAfterCreation(klass); }); } } // 6. Add a toString method for the class to allows us to see its constructor arguments klass.toString = function () { var constructorArgs = String(this.prototype[initializeSymbol]).match(constructorArgMatcher), className = this.name, superclass = this[superclassSymbol]; return "class " + className + " " + (superclass ? "extends " + superclass.name : "") + " {\n" + (" constructor" + (constructorArgs ? constructorArgs[0] : "()") + " { /*...*/ }") + "\n}"; }; // 7. If the class allows managed properties (auto getters/setters etc., see // managed-properties.js) then setup those prepareClassForManagedPropertiesAfterCreation(klass); return klass; } initializeClass._get = function _get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); return parent === null ? undefined : _get(parent, property, receiver); } if ("value" in desc) return desc.value; var getter = desc.get; return getter === undefined ? undefined : getter.call(receiver); }; initializeClass._set = function _set(object, property, value, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent !== null) _set(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 runtime = Object.freeze({ initializeSymbol: initializeSymbol, instanceRestorerSymbol: instanceRestorerSymbol, superclassSymbol: superclassSymbol, moduleMetaSymbol: moduleMetaSymbol, objMetaSymbol: objMetaSymbol, moduleSubscribeToToplevelChangesSym: moduleSubscribeToToplevelChangesSym, setPrototypeOf: setPrototypeOf, adoptObject: adoptObject, setSuperclass: setSuperclass, initializeClass: initializeClass }); var assign = lively_ast.nodes.assign; var member = lively_ast.nodes.member; var id = lively_ast.nodes.id; var exprStmt = lively_ast.nodes.exprStmt; var funcCall = lively_ast.nodes.funcCall; var literal = lively_ast.nodes.literal; var objectLiteral = lively_ast.nodes.objectLiteral; var varDecl = lively_ast.nodes.varDecl; var funcExpr = lively_ast.nodes.funcExpr; var returnStmt = lively_ast.nodes.returnStmt; var binaryExpr = lively_ast.nodes.binaryExpr; var ifStmt = lively_ast.nodes.ifStmt; var block = lively_ast.nodes.block; function isFunctionNode(node) { return node.type === "ArrowFunctionExpression" || node.type === "FunctionExpression" || node.type === "FunctionDeclaration"; } var firstIdRe = /^[^_a-z]/i; var trailingIdRe = /[^_a-z0-9]/ig; function ensureIdentifier(name) { return name.replace(firstIdRe, "_").replace(trailingIdRe, "_"); } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- function constructorTemplate(name) { // Creates a function like // function CLASS() { // var firstArg = arguments[0]; // if (firstArg && firstArg[Symbol.for("lively-instance-restorer")]) { // // for deserializing instances just do nothing // } else { // // automatically call the initialize method // this[Symbol.for("lively-instance-initialize")].apply(this, arguments); // } // } return funcExpr({ id: name ? id(name) : null }, ["__first_arg__"], ifStmt(binaryExpr(id("__first_arg__"), "&&", member("__first_arg__", funcCall(member("Symbol", "for"), literal("lively-instance-restorer")), true)), block(), block(exprStmt(funcCall(member(member("this", funcCall(member("Symbol", "for"), literal("lively-instance-initialize")), true), "apply"), id("this"), id("arguments")))))); } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- var isTransformedClassVarDeclSymbol = Symbol(); var methodKindSymbol = Symbol(); var tempLivelyClassVar = "__lively_class__"; var tempLivelyClassHolderVar = "__lively_classholder__"; var ClassReplaceVisitor = function (_Visitor) { inherits(ClassReplaceVisitor, _Visitor); function ClassReplaceVisitor() { classCallCheck(this, ClassReplaceVisitor); return possibleConstructorReturn(this, (ClassReplaceVisitor.__proto__ || Object.getPrototypeOf(ClassReplaceVisitor)).apply(this, arguments)); } createClass(ClassReplaceVisitor, [{ key: "accept", value: function accept(node, state, path) { if (isFunctionNode(node)) { state = _extends({}, state, { classHolder: objectLiteral([]), currentMethod: node[methodKindSymbol] ? node : state.currentMethod }); } if (node.type === "ClassExpression" || node.type === "ClassDeclaration") node = replaceClass(node, state, path, state.options); if (node.type === "Super") node = replaceSuper(node, state, path, state.options); if (node.type === "MemberExpression" && node.object && node.object.type === "Super") node = replaceSuperGetter(node, state, path, state.options); if (node.type === "AssignmentExpression" && node.left.type === "MemberExpression" && node.left.object.type === "Super") node = replaceSuperSetter(node, state, path, state.options); if (node.type === "CallExpression" && node.callee.type === "Super") node = replaceDirectSuperCall(node, state, path, state.options); if (node.type === "CallExpression" && node.callee.object && node.callee.object.type === "Super") node = replaceSuperMethodCall(node, state, path, state.options); node = get(ClassReplaceVisitor.prototype.__proto__ || Object.getPrototypeOf(ClassReplaceVisitor.prototype), "accept", this).call(this, node, state, path); if (node.type === "ExportDefaultDeclaration") return splitExportDefaultWithClass(node, state, path, state.options); return node; } }], [{ key: "run", value: function run(parsed, options) { var v = new this(), classHolder = options.classHolder || objectLiteral([]); return v.accept(parsed, { options: options, classHolder: classHolder }, []); } }]); return ClassReplaceVisitor; }(lively_ast.BaseVisitor); function replaceSuper(node, state, path, options) { // just super console.assert(node.type === "Super"); var currentMethod = state.currentMethod; if (!currentMethod) { console.warn("[lively.classes] Trying to transform es6 class but got super call outside a method! " + lively_ast.stringify(node) + " in " + path.join(".")); // return node; } var _path$slice = path.slice(-2), _path$slice2 = slicedToArray(_path$slice, 2), parentReferencedAs = _path$slice2[0], referencedAs = _path$slice2[1]; if (parentReferencedAs === 'callee' && referencedAs === 'object' || referencedAs === 'callee') return node; // deal with this in replaceSuperCall var methodHolder = currentMethod && currentMethod[methodKindSymbol] === "static" ? funcCall(member("Object", "getPrototypeOf"), id(tempLivelyClassVar)) : funcCall(member("Object", "getPrototypeOf"), member(id(tempLivelyClassVar), "prototype")); return methodHolder; } // parse("class Foo extends Bar { get x() { return super.x; }}").body[0] function replaceSuperMethodCall(node, state, path, options) { // like super.foo() console.assert(node.type === "CallExpression"); console.assert(node.callee.object.type === "Super"); return funcCall.apply(undefined, [member(funcCall(member(options.functionNode, "_get"), replaceSuper(node.callee.object, state, path.concat(["callee", "object"]), options), literal(node.callee.property.value || node.callee.property.name), id("this")), "call"), id("this")].concat(toConsumableArray(node.arguments))); } function replaceDirectSuperCall(node, state, path, options) { // like super() console.assert(node.type === "CallExpression"); console.assert(node.callee.type === "Super"); return funcCall.apply(undefined, [member(funcCall(member(options.functionNode, "_get"), replaceSuper(node.callee, state, path.concat(["callee"]), options), funcCall(member("Symbol", "for"), literal("lively-instance-initialize")), id("this")), "call"), id("this")].concat(toConsumableArray(node.arguments))); } function replaceSuperGetter(node, state, path, options) { console.assert(node.type === "MemberExpression"); console.assert(node.object.type === "Super"); return funcCall(member(options.functionNode, "_get"), replaceSuper(node.object, state, path.concat(["object"]), options), literal(node.property.value || node.property.name), id("this")); } function replaceSuperSetter(node, state, path, options) { console.assert(node.type === "AssignmentExpression"); console.assert(node.left.object.type === "Super"); return funcCall(member(options.functionNode, "_set"), replaceSuper(node.left.object, state, path.concat(["left", "object"]), options), literal(node.left.property.value || node.left.property.name), node.right, id("this")); } function replaceClass(node, state, path, options) { console.assert(node.type === "ClassDeclaration" || node.type === "ClassExpression"); var body = node.body.body, superClass = node.superClass, classId = node.id, type = node.type, start = node.start, end = node.end, instanceProps = id("undefined"), classProps = id("undefined"), className = classId ? classId.name : "anonymous_class", evalId = options.evalId, sourceAccessorName = options.sourceAccessorName, loc = node["x-lively-object-meta"] || { start: start, end: end }; if (body.length) { var _body$reduce = body.reduce(function (props, propNode) { var decl, key = propNode.key, kind = propNode.kind, value = propNode.value, classSide = propNode.static; if (key.type !== "Literal" && key.type !== "Identifier") { console.warn("Unexpected key in classToFunctionTransform! " + JSON.stringify(key)); } if (kind === "method") { // The name is just for debugging purposes when it appears in // native debuggers. We have to be careful about it b/c it shadows // outer functions / vars, something that is totally not apparent for a user // of the class syntax. That's the reason for making it a little cryptic var methodId = id(className + "_" + ensureIdentifier(key.name || key.value) + "_"), _props = ["key", literal(key.name || key.value), "value", _extends({}, value, defineProperty({ id: methodId }, methodKindSymbol, classSide ? "static" : "proto"))]; decl = objectLiteral(_props); } else if (kind === "get" || kind === "set") { decl = objectLiteral(["key", literal(key.name || key.value), kind, Object.assign({}, value, defineProperty({ id: id(kind) }, methodKindSymbol, classSide ? "static" : "proto"))]); } else if (kind === "constructor") { var _props2 = ["key", funcCall(member("Symbol", "for"), literal("lively-instance-initialize")), "value", _extends({}, value, defineProperty({ id: id(className + "_initialize_") }, methodKindSymbol, "proto"))]; decl = objectLiteral(_props2); } else { console.warn("[lively.classes] classToFunctionTransform encountered unknown class property with kind " + kind + ", ignoring it, " + JSON.stringify(propNode)); } (classSide ? props.clazz : props.inst).push(decl); return props; }, { inst: [], clazz: [] }), inst = _body$reduce.inst, clazz = _body$reduce.clazz; if (inst.length) instanceProps = { type: "ArrayExpression", elements: inst }; if (clazz.length) classProps = { type: "ArrayExpression", elements: clazz }; } var scope = options.scope, superClassReferencedAs, superClassRef; if (superClass && options.currentModuleAccessor) { if (options.classHolder === superClass.object) { superClassRef = superClass; superClassReferencedAs = superClass.property.name; } else { var found = scope && scope.resolvedRefMap && scope.resolvedRefMap.get(superClass), isTopLevel = found && found.decl && scope.decls && scope.decls.find(function (_ref) { var _ref2 = slicedToArray(_ref, 1), decl = _ref2[0]; return decl === found.decl; }); if (isTopLevel) { superClassRef = superClass; superClassReferencedAs = superClass.name; } } } var superClassSpec = superClassRef ? objectLiteral(["referencedAs", literal(superClassReferencedAs), "value", superClassRef]) : superClass || id("undefined"); // For persistent storage and retrieval of pre-existing classes in "classHolder" object var useClassHolder = classId && type === "ClassDeclaration"; var locKeyVals = ["start", literal(loc.start), "end", literal(loc.end)]; if (typeof evalId !== "undefined") locKeyVals.push("evalId", literal(evalId)); if (sourceAccessorName) locKeyVals.push("moduleSource", lively_ast.nodes.id(sourceAccessorName)); var locNode = objectLiteral(locKeyVals); var classCreator = funcCall(funcExpr({}, ["superclass"], varDecl(tempLivelyClassHolderVar, state.classHolder), varDecl(tempLivelyClassVar, useClassHolder ? { type: "ConditionalExpression", test: binaryExpr(funcCall(member(tempLivelyClassHolderVar, "hasOwnProperty"), literal(classId.name)), "&&", binaryExpr({ argument: member(tempLivelyClassHolderVar, classId), operator: "typeof", prefix: true, type: "UnaryExpression" }, "===", literal("function"))), consequent: member(tempLivelyClassHolderVar, classId), alternate: assign(member(tempLivelyClassHolderVar, classId), constructorTemplate(classId.name)) } : classId ? constructorTemplate(classId.name) : constructorTemplate(null)), returnStmt(funcCall(options.functionNode, id(tempLivelyClassVar), id("superclass"), instanceProps, classProps, id(tempLivelyClassHolderVar), options.currentModuleAccessor || id("undefined"), locNode))), superClassSpec); if (type === "ClassExpression") return classCreator; var result = classCreator; if (options.declarationWrapper && state.classHolder === options.classHolder /*i.e. toplevel*/) result = funcCall(options.declarationWrapper, literal(classId.name), literal("class"), result, options.classHolder, locNode); // since it is a declaration and we removed the class construct we need to add a var-decl result = varDecl(classId, result, "var"); result[isTransformedClassVarDeclSymbol] = true; return result; } function splitExportDefaultWithClass(node, classHolder, path, options) { return !node.declaration || !node.declaration[isTransformedClassVarDeclSymbol] ? node : [node.declaration, { declaration: node.declaration.declarations[0].id, type: "ExportDefaultDeclaration" }]; } // var opts = {classHolder: {type: "Identifier", name: "_rec"}, functionNode: {type: "Identifier", name: "createOrExtendClass"}}; // stringify(classToFunctionTransform(parse("class Foo extends Bar {m() { super.m(); }}"), opts)) // stringify(classToFunctionTransform(parse("class Foo extends Bar {m() { super.m(arguments[1]); }}"), opts)) // stringify(classToFunctionTransform(parse("class Foo {constructor() {}}"), opts)) function classToFunctionTransform(sourceOrAst, options) { // required: options = {functionNode, classHolder} // From // class Foo extends SuperFoo { m() { return 2 + super.m() }} // produces something like // createOrExtend({}, {referencedAs: "SuperFoo", value: SuperFoo}, "Foo2", [{ // key: "m", // value: function m() { // return 2 + this.constructor[superclassSymbol].prototype.m.call(this); // } // }]) // console.log(typeof sourceOrAst === "string" ? sourceOrAst : stringify(sourceOrAst)) var parsed = typeof sourceOrAst === "string" ? lively_ast.parse(sourceOrAst) : sourceOrAst; options.scope = lively_ast.query.resolveReferences(lively_ast.query.scopes(parsed)); var replaced = ClassReplaceVisitor.run(parsed, options); return replaced; } exports.runtime = runtime; exports.classToFunctionTransform = classToFunctionTransform; }((this.lively.classes = this.lively.classes || {}),lively.lang,lively.ast)); if (typeof module !== "undefined" && module.exports) module.exports = GLOBAL.lively.classes; })(); // INLINED END /Users/user/git/lively.vm/node_modules/lively.classes/dist/lively.classes.js // INLINED /Users/user/git/lively.vm/node_modules/lively.source-transform/dist/lively.source-transform.js ;(function() { var GLOBAL = typeof window !== "undefined" ? window : typeof global!=="undefined" ? global : typeof self!=="undefined" ? self : this; if (typeof lively.lang === "undefined") GLOBAL.livey.lang = {}; })(); (function() { var GLOBAL = typeof window !== "undefined" ? window : typeof global!=="undefined" ? global : typeof self!=="undefined" ? self : this; this.lively = this.lively || {}; (function (exports,lively_lang,lively_classes,lively_ast) { 'use strict'; var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var get = function get(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(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 = function set(object, property, value, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent !== null) { set(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 toConsumableArray = function (arr$$1) { if (Array.isArray(arr$$1)) { for (var i = 0, arr2 = Array(arr$$1.length); i < arr$$1.length; i++) arr2[i] = arr$$1[i]; return arr2; } else { return Array.from(arr$$1); } }; var member = lively_ast.nodes.member; var prop = lively_ast.nodes.prop; var varDecl = lively_ast.nodes.varDecl; var assign = lively_ast.nodes.assign; var id = lively_ast.nodes.id; var literal = lively_ast.nodes.literal; var exprStmt = lively_ast.nodes.exprStmt; var conditional = lively_ast.nodes.conditional; var binaryExpr = lively_ast.nodes.binaryExpr; var funcCall = lively_ast.nodes.funcCall; var topLevelDeclsAndRefs = lively_ast.query.topLevelDeclsAndRefs; var queryHelpers = lively_ast.query.helpers; function rewriteToCaptureTopLevelVariables(parsed, assignToObj, options) { /* replaces var and function declarations with assignment statements. * Example: stringify( rewriteToCaptureTopLevelVariables2( parse("var x = 3, y = 2, z = 4"), {name: "A", type: "Identifier"}, ['z'])); // => "A.x = 3; A.y = 2; z = 4" */ if (!assignToObj) assignToObj = { type: "Identifier", name: "__rec" }; options = _extends({ ignoreUndeclaredExcept: null, includeRefs: null, excludeRefs: options && options.exclude || [], includeDecls: null, excludeDecls: options && options.exclude || [], recordDefRanges: false, es6ExportFuncId: null, es6ImportFuncId: null, captureObj: assignToObj, moduleExportFunc: { name: options && options.es6ExportFuncId || "_moduleExport", type: "Identifier" }, moduleImportFunc: { name: options && options.es6ImportFuncId || "_moduleImport", type: "Identifier" }, declarationWrapper: undefined, classToFunction: options && options.hasOwnProperty("classToFunction") ? options.classToFunction : { classHolder: assignToObj, functionNode: { type: "Identifier", name: "_createOrExtendClass" }, declarationWrapper: options && options.declarationWrapper, evalId: options && options.evalId, sourceAccessorName: options && options.sourceAccessorName } }, options); var rewritten = parsed; // "ignoreUndeclaredExcept" is null if we want to capture all globals in the toplevel scope // if it is a list of names we will capture all refs with those names if (options.ignoreUndeclaredExcept) { var topLevel = topLevelDeclsAndRefs(parsed); options.excludeRefs = lively_lang.arr.withoutAll(topLevel.undeclaredNames, options.ignoreUndeclaredExcept).concat(options.excludeRefs); options.excludeDecls = lively_lang.arr.withoutAll(topLevel.undeclaredNames, options.ignoreUndeclaredExcept).concat(options.excludeDecls); } options.excludeRefs = options.excludeRefs.concat(options.captureObj.name); options.excludeDecls = options.excludeDecls.concat(options.captureObj.name); // 1. def ranges so that we know at which source code positions the // definitions are var defRanges = options.recordDefRanges ? computeDefRanges(rewritten, options) : null; // 2. find those var declarations that should not be rewritten. we // currently ignore var declarations in for loops and the error parameter // declaration in catch clauses. Also es6 import / export declaration need // a special treatment // DO NOT rewrite exports like "export { foo as bar }" => "export { _rec.foo as bar }" // as this is not valid syntax. Instead we add a var declaration using the // recorder as init for those exports later options.excludeRefs = options.excludeRefs.concat(additionalIgnoredRefs(parsed, options)); options.excludeDecls = options.excludeDecls.concat(additionalIgnoredDecls(parsed, options)); rewritten = fixDefaultAsyncFunctionExportForRegeneratorBug(rewritten, options); // 3. if the es6ExportFuncId options is defined we rewrite the es6 form into an // obj assignment, converting es6 code to es5 using the extra // options.moduleExportFunc and options.moduleImportFunc as capture / sources if (options.es6ExportFuncId) { options.excludeRefs.push(options.es6ExportFuncId); options.excludeRefs.push(options.es6ImportFuncId); rewritten = es6ModuleTransforms(rewritten, options); } // 4. make all references declared in the toplevel scope into property // reads of captureObj // Example "var foo = 3; 99 + foo;" -> "var foo = 3; 99 + Global.foo;" rewritten = replaceRefs(rewritten, options); // 5.a turn var declarations into assignments to captureObj // Example: "var foo = 3; 99 + foo;" -> "Global.foo = 3; 99 + foo;" // if declarationWrapper is requested: // "var foo = 3;" -> "Global.foo = _define(3, 'foo', _rec, 'var');" rewritten = replaceVarDecls(rewritten, options); // 5.b record class declarations // Example: "class Foo {}" -> "class Foo {}; Global.Foo = Foo;" // if declarationWrapper is requested: // "class Foo {}" -> "Global.Foo = _define(class Foo {});" rewritten = replaceClassDecls(rewritten, options); rewritten = splitExportDeclarations(rewritten, options); // 6. es6 export declaration are left untouched but a capturing assignment // is added after the export so that we get the value: // "export var x = 23;" => "export var x = 23; Global.x = x;" rewritten = insertCapturesForExportDeclarations(rewritten, options); // 7. es6 import declaration are left untouched but a capturing assignment // is added after the import so that we get the value: // "import x from './some-es6-module.js';" => // "import x from './some-es6-module.js';\n_rec.x = x;" rewritten = insertCapturesForImportDeclarations(rewritten, options); // 8. Since variable declarations like "var x = 23" were transformed to sth // like "_rex.x = 23" exports can't simply reference vars anymore and // "export { _rec.x }" is invalid syntax. So in front of those exports we add // var decls manually rewritten = insertDeclarationsForExports(rewritten, options); // 9. assignments for function declarations in the top level scope are // put in front of everything else to mirror the func hoisting: // "return bar(); function bar() { return 23 }" -> // "Global.bar = bar; return bar(); function bar() { return 23 }" // if declarationWrapper is requested: // "Global.bar = _define(bar, 'bar', _rec, 'function'); function bar() {}" rewritten = putFunctionDeclsInFront(rewritten, options); return rewritten; } function rewriteToRegisterModuleToCaptureSetters(parsed, assignToObj, options) { // for rewriting the setters part in code like // ```js // System.register(["a.js"], function (_export, _context) { // var a, _rec; // return { // setters: [function(foo_a_js) { a = foo_a_js.x }], // execute: function () { _rec.x = 23 + _rec.a; } // }; // }); // ``` // This allows us to capture (and potentially re-export) imports and their // changes without actively running the module again. options = _extends({ captureObj: assignToObj || { type: "Identifier", name: "__rec" }, exclude: [], declarationWrapper: undefined }, options); var registerCall = lively_lang.Path("body.0.expression").get(parsed); if (registerCall.callee.object.name !== "System") throw new Error("rewriteToRegisterModuleToCaptureSetters: input doesn't seem to be a System.register call: " + lively_ast.stringify(parsed).slice(0, 300) + "..."); if (registerCall.callee.property.name !== "register") throw new Error("rewriteToRegisterModuleToCaptureSetters: input doesn't seem to be a System.register call: " + lively_ast.stringify(parsed).slice(0, 300) + "..."); var registerBody = lively_lang.Path("arguments.1.body.body").get(registerCall), registerReturn = lively_lang.arr.last(registerBody); if (registerReturn.type !== "ReturnStatement") throw new Error("rewriteToRegisterModuleToCaptureSetters: input doesn't seem to be a System.register call, at return statement: " + lively_ast.stringify(parsed).slice(0, 300) + "..."); var setters = registerReturn.argument.properties.find(function (prop) { return prop.key.name === "setters"; }); if (!setters) throw new Error("rewriteToRegisterModuleToCaptureSetters: input doesn't seem to be a System.register call, at finding setters: " + lively_ast.stringify(parsed).slice(0, 300) + "..."); var execute = registerReturn.argument.properties.find(function (prop) { return prop.key.name === "execute"; }); if (!execute) throw new Error("rewriteToRegisterModuleToCaptureSetters: input doesn't seem to be a System.register call, at finding execute: " + lively_ast.stringify(parsed).slice(0, 300) + "..."); // in each setter function: intercept the assignments to local vars and inject capture object setters.value.elements.forEach(function (funcExpr) { return funcExpr.body.body = funcExpr.body.body.map(function (stmt) { if (stmt.type !== "ExpressionStatement" || stmt.expression.type !== "AssignmentExpression" || stmt.expression.left.type !== "Identifier" || lively_lang.arr.include(options.exclude, stmt.expression.left.name)) return stmt; var id = stmt.expression.left, rhs = options.declarationWrapper ? declarationWrapperCall(options.declarationWrapper, null, literal(id.name), literal("var"), stmt.expression, options.captureObj, options) : stmt.expression; return exprStmt(assign(member(options.captureObj, id), rhs)); }); }); var captureInitialize = execute.value.body.body.find(function (stmt) { return stmt.type === "ExpressionStatement" && stmt.expression.type == "AssignmentExpression" && stmt.expression.left.name === options.captureObj.name; }); if (!captureInitialize) captureInitialize = execute.value.body.body.find(function (stmt) { return stmt.type === "VariableDeclaration" && stmt.declarations[0].id && stmt.declarations[0].id.name === options.captureObj.name; }); if (captureInitialize) { lively_lang.arr.remove(execute.value.body.body, captureInitialize); lively_lang.arr.pushAt(registerBody, captureInitialize, registerBody.length - 1); } if (options.sourceAccessorName) { var origSourceInitialize = execute.value.body.body.find(function (stmt) { return stmt.type === "ExpressionStatement" && stmt.expression.type == "AssignmentExpression" && stmt.expression.left.name === options.sourceAccessorName; }); if (!origSourceInitialize) origSourceInitialize = execute.value.body.body.find(function (stmt) { return stmt.type === "VariableDeclaration" && stmt.declarations[0].id && stmt.declarations[0].id.name === options.sourceAccessorName; }); if (origSourceInitialize) { lively_lang.arr.remove(execute.value.body.body, origSourceInitialize); lively_lang.arr.pushAt(registerBody, origSourceInitialize, registerBody.length - 1); } } return parsed; } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- // replacement helpers function replaceRefs(parsed, options) { var topLevel = topLevelDeclsAndRefs(parsed), refsToReplace = topLevel.refs.filter(function (ref) { return shouldRefBeCaptured(ref, topLevel, options); }), locallyIgnored = []; var replaced = lively_ast.ReplaceVisitor.run(parsed, function (node, path) { // cs 2016/06/27, 1a4661 // ensure keys of shorthand properties are not renamed while capturing if (node.type === "Property" && refsToReplace.includes(node.key) && node.shorthand) return prop(id(node.key.name), node.value); // don't replace var refs in expressions such as "export { x }" or "export var x;" // We make sure that those var references are defined in insertDeclarationsForExports() if (node.type === "ExportNamedDeclaration") { var declaration = node.declaration, specifiers = node.specifiers; if (declaration) { if (declaration.id) locallyIgnored.push(declaration.id);else if (declaration.declarations) locallyIgnored.push.apply(locallyIgnored, toConsumableArray(declaration.declarations.map(function (_ref) { var id = _ref.id; return id; }))); } specifiers && specifiers.forEach(function (_ref2) { var local = _ref2.local; return locallyIgnored.push(local); }); return node; } // declaration wrapper function for assignments // "a = 3" => "a = _define('a', 'assignment', 3, _rec)" if (node.type === "AssignmentExpression" && refsToReplace.includes(node.left) && options.declarationWrapper) return _extends({}, node, { right: declarationWrapperCall(options.declarationWrapper, null, literal(node.left.name), literal("assignment"), node.right, options.captureObj, options) }); return node; }); return lively_ast.ReplaceVisitor.run(replaced, function (node, path, parent) { return refsToReplace.includes(node) && !locallyIgnored.includes(node) ? member(options.captureObj, node) : node; }); } function replaceVarDecls(parsed, options) { // rewrites var declarations so that they can be captured by // `options.captureObj`. // For normal vars we will do a transform like // "var x = 23;" => "_rec.x = 23"; // For patterns (destructuring assignments) we will create assignments for // all properties that are being destructured, creating helper vars as needed // "var {x: [y]} = foo" => "var _1 = foo; var _1$x = _1.x; __rec.y = _1$x[0];" var topLevel = topLevelDeclsAndRefs(parsed); return lively_ast.ReplaceManyVisitor.run(parsed, function (node) { if (!topLevel.varDecls.includes(node) || node.declarations.every(function (decl) { return !shouldDeclBeCaptured(decl, options); })) return node; var replaced = []; for (var i = 0; i < node.declarations.length; i++) { var decl = node.declarations[i]; if (!shouldDeclBeCaptured(decl, options)) { replaced.push({ type: "VariableDeclaration", kind: node.kind || "var", declarations: [decl] }); continue; } var init = decl.init || { operator: "||", type: "LogicalExpression", left: { computed: false, object: options.captureObj, property: decl.id, type: "MemberExpression" }, right: { name: "undefined", type: "Identifier" } }; var initWrapped = options.declarationWrapper && decl.id.name ? declarationWrapperCall(options.declarationWrapper, decl, literal(decl.id.name), literal(node.kind), init, options.captureObj, options) : init; // Here we create the object pattern / destructuring replacements if (decl.id.type.includes("Pattern")) { var declRootName = generateUniqueName(topLevel.declaredNames, "destructured_1"), declRoot = { type: "Identifier", name: declRootName }, state = { parent: declRoot, declaredNames: topLevel.declaredNames }, extractions = transformPattern(decl.id, state).map(function (decl) { return decl[annotationSym] && decl[annotationSym].capture ? assignExpr(options.captureObj, decl.declarations[0].id, options.declarationWrapper ? declarationWrapperCall(options.declarationWrapper, null, literal(decl.declarations[0].id.name), literal(node.kind), decl.declarations[0].init, options.captureObj, options) : decl.declarations[0].init, false) : decl; }); topLevel.declaredNames.push(declRootName); replaced.push.apply(replaced, toConsumableArray([varDecl(declRoot, initWrapped, node.kind)].concat(extractions))); continue; } // This is rewriting normal vars replaced.push(assignExpr(options.captureObj, decl.id, initWrapped, false)); } return replaced; }); } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- // naming // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- function generateUniqueName(declaredNames, hint) { var unique = hint, n = 1; while (declaredNames.indexOf(unique) > -1) { if (n > 1000) throw new Error("Endless loop searching for unique variable " + unique); unique = unique.replace(/_[0-9]+$|$/, "_" + ++n); } return unique; } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- // exclude / include helpers // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- function additionalIgnoredDecls(parsed, options) { var topLevel = topLevelDeclsAndRefs(parsed), ignoreDecls = []; for (var i = 0; i < topLevel.scope.varDecls.length; i++) { var decl = topLevel.scope.varDecls[i], path = lively_lang.Path(topLevel.scope.varDeclPaths[i]), parent = path.slice(0, -1).get(parsed); if (parent.type === "ForStatement" || parent.type === "ForInStatement" || parent.type === "ForOfStatement" || parent.type === "ExportNamedDeclaration") ignoreDecls.push.apply(ignoreDecls, toConsumableArray(decl.declarations)); } return topLevel.scope.catches.map(function (ea) { return ea.name; }).concat(ignoreDecls.map(function (ea) { return ea.id.name; })); } function additionalIgnoredRefs(parsed, options) { // FIXME rk 2016-05-11: in shouldRefBeCaptured we now also test for import // decls, this should somehow be consolidated with this function and with the // fact that naming based ignores aren't good enough... var topLevel = topLevelDeclsAndRefs(parsed); var ignoreDecls = []; for (var i = 0; i < topLevel.scope.varDecls.length; i++) { var decl = topLevel.scope.varDecls[i], path = lively_lang.Path(topLevel.scope.varDeclPaths[i]), parent = path.slice(0, -1).get(parsed); if (parent.type === "ForStatement" || parent.type === "ForInStatement" || parent.type === "ForOfStatement") ignoreDecls.push.apply(ignoreDecls, toConsumableArray(decl.declarations)); } return topLevel.scope.catches.map(function (ea) { return ea.name; }).concat(queryHelpers.declIds(ignoreDecls.map(function (ea) { return ea.id; })).map(function (ea) { return ea.name; })); } function shouldDeclBeCaptured(decl, options) { return options.excludeDecls.indexOf(decl.id.name) === -1 && (!options.includeDecls || options.includeDecls.indexOf(decl.id.name) > -1); } function shouldRefBeCaptured(ref, toplevel, options) { if (toplevel.scope.importSpecifiers.includes(ref)) return false; for (var i = 0; i < toplevel.scope.exportDecls.length; i++) { var ea = toplevel.scope.exportDecls[i]; if (ea.declarations && ea.declarations.includes(ref)) return false; if (ea.declaration === ref) return false; } if (options.excludeRefs.includes(ref.name)) return false; if (options.includeRefs && !options.includeRefs.includes(ref.name)) return false; return true; } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- // capturing specific code // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- function replaceClassDecls(parsed, options) { if (options.classToFunction) return lively_classes.classToFunctionTransform(parsed, options.classToFunction); var topLevel = topLevelDeclsAndRefs(parsed); if (!topLevel.classDecls.length) return parsed; for (var i = parsed.body.length - 1; i >= 0; i--) { var stmt = parsed.body[i]; if (topLevel.classDecls.includes(stmt)) parsed.body.splice(i + 1, 0, assignExpr(options.captureObj, stmt.id, stmt.id, false)); } return parsed; } function splitExportDeclarations(parsed, options) { var stmts = parsed.body, newNodes = parsed.body = []; for (var i = 0; i < stmts.length; i++) { var stmt = stmts[i]; if (stmt.type !== "ExportNamedDeclaration" || !stmt.declaration || stmt.declaration.type !== "VariableDeclaration" || stmt.declaration.declarations.length <= 1) { newNodes.push(stmt);continue; } var decls = stmt.declaration.declarations; for (var j = 0; j < decls.length; j++) { newNodes.push({ type: "ExportNamedDeclaration", specifiers: [], declaration: varDecl(decls[j].id, decls[j].init, stmt.declaration.kind) }); } } return parsed; } function insertCapturesForExportDeclarations(parsed, options) { var body = []; for (var i = 0; i < parsed.body.length; i++) { var stmt = parsed.body[i]; body.push(stmt); // ExportNamedDeclaration can have specifieres = refs, those should already // be captured. Only focus on export declarations and only those // declarations that are no refs, i.e. // ignore: "export default x;" // capture: "export default function foo () {};", "export var x = 23, y = 3;" if (stmt.type !== "ExportNamedDeclaration" && stmt.type !== "ExportDefaultDeclaration" || !stmt.declaration) { /*...*/ } else if (stmt.declaration.declarations) { body.push.apply(body, toConsumableArray(stmt.declaration.declarations.map(function (decl) { var assignVal = decl.id; if (options.declarationWrapper) { var alreadyWrapped = decl.init.callee && decl.init.callee.name === options.declarationWrapper.name; if (!alreadyWrapped) assignVal = declarationWrapperCall(options.declarationWrapper, decl, literal(decl.id.name), literal("assignment"), decl.id, options.captureObj, options); } return assignExpr(options.captureObj, decl.id, assignVal, false); }))); } else if (stmt.declaration.type === "FunctionDeclaration") { /*handled by function rewriter as last step*/ } else if (stmt.declaration.type === "ClassDeclaration") { body.push(assignExpr(options.captureObj, stmt.declaration.id, stmt.declaration.id, false)); } } parsed.body = body; return parsed; } function insertCapturesForImportDeclarations(parsed, options) { parsed.body = parsed.body.reduce(function (stmts, stmt) { return stmts.concat(stmt.type !== "ImportDeclaration" || !stmt.specifiers.length ? [stmt] : [stmt].concat(stmt.specifiers.map(function (specifier) { return assignExpr(options.captureObj, specifier.local, specifier.local, false); }))); }, []); return parsed; } function insertDeclarationsForExports(parsed, options) { var topLevel = topLevelDeclsAndRefs(parsed), body = []; for (var i = 0; i < parsed.body.length; i++) { var stmt = parsed.body[i]; if (stmt.type === "ExportDefaultDeclaration" && stmt.declaration && stmt.declaration.type.indexOf("Declaration") === -1) { body = body.concat([varDeclOrAssignment(parsed, { type: "VariableDeclarator", id: stmt.declaration, init: member(options.captureObj, stmt.declaration) }), stmt]); } else if (stmt.type !== "ExportNamedDeclaration" || !stmt.specifiers.length || stmt.source) { body.push(stmt); } else { body = body.concat(stmt.specifiers.map(function (specifier) { return lively_lang.arr.include(topLevel.declaredNames, specifier.local.name) ? null : varDeclOrAssignment(parsed, { type: "VariableDeclarator", id: specifier.local, init: member(options.captureObj, specifier.local) }); }).filter(Boolean)).concat(stmt); } } parsed.body = body; return parsed; } function fixDefaultAsyncFunctionExportForRegeneratorBug(parsed, options) { // rk 2016-06-02: see https://github.com/LivelyKernel/lively.modules/issues/9 // FIXME this needs to be removed as soon as the cause for the issue is fixed var body = []; for (var i = 0; i < parsed.body.length; i++) { var stmt = parsed.body[i]; if (stmt.type === "ExportDefaultDeclaration" && stmt.declaration.type === "FunctionDeclaration" && stmt.declaration.id && stmt.declaration.async) { body.push(stmt.declaration); stmt.declaration = { type: "Identifier", name: stmt.declaration.id.name }; } body.push(stmt); } parsed.body = body; return parsed; } function es6ModuleTransforms(parsed, options) { parsed.body = parsed.body.reduce(function (stmts, stmt) { var nodes$$1; if (stmt.type === "ExportNamedDeclaration") { if (stmt.source) { var key = moduleId = stmt.source; nodes$$1 = stmt.specifiers.map(function (specifier) { return { type: "ExpressionStatement", expression: exportFromImport({ type: "Literal", value: specifier.exported.name }, { type: "Literal", value: specifier.local.name }, moduleId, options.moduleExportFunc, options.moduleImportFunc) }; }); } else if (stmt.declaration) { var decls = stmt.declaration.declarations; if (!decls) { // func decl or class nodes$$1 = [stmt.declaration].concat(exportCallStmt(options.moduleExportFunc, stmt.declaration.id.name, stmt.declaration.id)); } else { nodes$$1 = decls.map(function (decl) { options.excludeDecls.push(decl.id); return varDecl(decl.id, assignExpr(options.captureObj, decl.id, options.declarationWrapper ? declarationWrapperCall(options.declarationWrapper, null, literal(decl.id.name), literal(stmt.declaration.kind), decl, options.captureObj, options) : decl.init, false), stmt.declaration.kind); }).concat(decls.map(function (decl) { return exportCallStmt(options.moduleExportFunc, decl.id.name, decl.id); })); } } else { nodes$$1 = stmt.specifiers.map(function (specifier) { return exportCallStmt(options.moduleExportFunc, specifier.exported.name, shouldDeclBeCaptured({ id: specifier.local }, options) ? member(options.captureObj, specifier.local) : specifier.local); }); } } else if (stmt.type === "ExportDefaultDeclaration") { if (stmt.declaration && stmt.declaration.id) { nodes$$1 = [stmt.declaration].concat(exportCallStmt(options.moduleExportFunc, "default", stmt.declaration.id)); } else { nodes$$1 = [exportCallStmt(options.moduleExportFunc, "default", stmt.declaration)]; } } else if (stmt.type === "ExportAllDeclaration") { var key = { name: options.es6ExportFuncId + "__iterator__", type: "Identifier" }, moduleId = stmt.source; nodes$$1 = [{ type: "ForInStatement", body: { type: "ExpressionStatement", expression: exportFromImport(key, key, moduleId, options.moduleExportFunc, options.moduleImportFunc) }, left: { type: "VariableDeclaration", kind: "var", declarations: [{ type: "VariableDeclarator", id: key, init: null }] }, right: importCall(null, moduleId, options.moduleImportFunc) }]; options.excludeRefs.push(key.name); options.excludeDecls.push(key.name); } else if (stmt.type === "ImportDeclaration") { nodes$$1 = stmt.specifiers.length ? stmt.specifiers.map(function (specifier) { var local = specifier.local, imported = specifier.type === "ImportSpecifier" && specifier.imported.name || specifier.type === "ImportDefaultSpecifier" && "default" || null; return varDeclAndImportCall(parsed, local, imported || null, stmt.source, options.moduleImportFunc); }) : importCallStmt(null, stmt.source, options.moduleImportFunc); } else nodes$$1 = [stmt]; return stmts.concat(nodes$$1); }, []); return parsed; } function putFunctionDeclsInFront(parsed, options) { var scope = topLevelDeclsAndRefs(parsed).scope, funcDecls = scope.funcDecls; if (!funcDecls.length) return parsed; var putInFront = []; for (var i = funcDecls.length; i--;) { var decl = funcDecls[i]; if (!shouldDeclBeCaptured(decl, options)) continue; var parentPath = scope.funcDeclPaths[i].slice(0, -1), // ge the parent so we can replace the original function: parent = lively_lang.Path(parentPath).get(scope.node), funcId = { type: "Identifier", name: decl.id.name }, // what we capture: init = options.declarationWrapper ? declarationWrapperCall(options.declarationWrapper, decl, literal(funcId.name), literal("function"), funcId, options.captureObj, options) : funcId, declFront = _extends({}, decl); if (Array.isArray(parent)) { // If the parent is a body array we remove the original func decl from it // and replace it with a reference to the function parent.splice(parent.indexOf(decl), 1, exprStmt(decl.id)); } else if (parent.type === "ExportNamedDeclaration") { // If the function is exported we change the export declaration into a reference var parentIndexInBody = scope.node.body.indexOf(parent); if (parentIndexInBody > -1) { scope.node.body.splice(parentIndexInBody, 1, { type: "ExportNamedDeclaration", specifiers: [{ type: "ExportSpecifier", exported: decl.id, local: decl.id }] }); } } else if (parent.type === "ExportDefaultDeclaration") { parent.declaration = decl.id; } else {} // ??? just leave it alone... // decl.type = "EmptyStatement"; // hoist the function to the front, also it's capture putInFront.unshift(assignExpr(options.captureObj, funcId, init, false)); putInFront.unshift(declFront); } parsed.body = putInFront.concat(parsed.body); return parsed; } function computeDefRanges(parsed, options) { var topLevel = topLevelDeclsAndRefs(parsed); return lively_lang.chain(topLevel.scope.varDecls).pluck("declarations").flatten().value().concat(topLevel.scope.funcDecls).reduce(function (defs, decl) { if (!defs[decl.id.name]) defs[decl.id.name] = []; defs[decl.id.name].push({ type: decl.type, start: decl.start, end: decl.end }); return defs; }, {}); } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- // capturing oobject patters / destructuring // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- var annotationSym = Symbol("lively.ast-destructuring-transform"); function transformPattern(pattern, transformState) { // For transforming destructuring expressions into plain vars and member access. // Takes a var or argument pattern node (of type ArrayPattern or // ObjectPattern) and transforms it into a set of var declarations that will // "pull out" the nested properties // Example: // var parsed = parse("var [{b: {c: [a]}}] = foo;"); // var state = {parent: {type: "Identifier", name: "arg"}, declaredNames: ["foo"]} // transformPattern(parsed.body[0].declarations[0].id, state).map(stringify).join("\n"); // // => "var arg$0 = arg[0];\n" // // + "var arg$0$b = arg$0.b;\n" // // + "var arg$0$b$c = arg$0$b.c;\n" // // + "var a = arg$0$b$c[0];" return pattern.type === "ArrayPattern" ? transformArrayPattern(pattern, transformState) : pattern.type === "ObjectPattern" ? transformObjectPattern(pattern, transformState) : []; } function transformArrayPattern(pattern, transformState) { var declaredNames = transformState.declaredNames, p = annotationSym, transformed = []; for (var i = 0; i < pattern.elements.length; i++) { var el = pattern.elements[i]; // like [a] if (el.type === "Identifier") { var decl = varDecl(el, member(transformState.parent, id(i), true)); decl[p] = { capture: true }; transformed.push(decl); // like [...foo] } else if (el.type === "RestElement") { var decl = varDecl(el.argument, { type: "CallExpression", arguments: [{ type: "Literal", value: i }], callee: member(transformState.parent, id("slice"), false) }); decl[p] = { capture: true }; transformed.push(decl); } else if (el.type == "AssignmentPattern") { // like [x = 23] var decl = varDecl(el.left /*id*/ , conditional(binaryExpr(member(transformState.parent, id(i), true), "===", id("undefined")), el.right, member(transformState.parent, id(i), true))); decl[p] = { capture: true }; transformed.push(decl); // like [{x}] } else { var helperVarId = id(generateUniqueName(declaredNames, transformState.parent.name + "$" + i)), helperVar = varDecl(helperVarId, member(transformState.parent, i)); // helperVar[p] = {capture: true}; declaredNames.push(helperVarId.name); transformed.push(helperVar); transformed.push.apply(transformed, toConsumableArray(transformPattern(el, { parent: helperVarId, declaredNames: declaredNames }))); } } return transformed; } function transformObjectPattern(pattern, transformState) { var declaredNames = transformState.declaredNames, p = annotationSym, transformed = []; for (var i = 0; i < pattern.properties.length; i++) { var prop = pattern.properties[i]; if (prop.value.type == "Identifier") { // like {x: y} var decl = varDecl(prop.value, member(transformState.parent, prop.key)); decl[p] = { capture: true }; transformed.push(decl); } else if (prop.value.type == "AssignmentPattern") { // like {x = 23} var decl = varDecl(prop.value.left /*id*/ , conditional(binaryExpr(member(transformState.parent, prop.key), "===", id("undefined")), prop.value.right, member(transformState.parent, prop.key))); decl[p] = { capture: true }; transformed.push(decl); } else { // like {x: {z}} or {x: [a]} var helperVarId = id(generateUniqueName(declaredNames, transformState.parent.name + "$" + prop.key.name)), helperVar = varDecl(helperVarId, member(transformState.parent, prop.key)); helperVar[p] = { capture: false }; declaredNames.push(helperVarId.name); transformed.push.apply(transformed, toConsumableArray([helperVar].concat(transformPattern(prop.value, { parent: helperVarId, declaredNames: declaredNames })))); } } return transformed; } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- // code generation helpers // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- function varDeclOrAssignment(parsed, declarator, kind) { var topLevel = topLevelDeclsAndRefs(parsed), name = declarator.id.name; return topLevel.declaredNames.indexOf(name) > -1 ? // only create a new declaration if necessary exprStmt(assign(declarator.id, declarator.init)) : { declarations: [declarator], kind: kind || "var", type: "VariableDeclaration" }; } function assignExpr(assignee, propId, value, computed) { return exprStmt(assign(member(assignee, propId, computed), value || id("undefined"))); } function exportFromImport(keyLeft, keyRight, moduleId, moduleExportFunc, moduleImportFunc) { return exportCall(moduleExportFunc, keyLeft, importCall(keyRight, moduleId, moduleImportFunc)); } function varDeclAndImportCall(parsed, localId, imported, moduleSource, moduleImportFunc) { // return varDeclOrAssignment(parsed, { // type: "VariableDeclarator", // id: localId, // init: importCall(imported, moduleSource, moduleImportFunc) // }); return varDecl(localId, importCall(imported, moduleSource, moduleImportFunc)); } function importCall(imported, moduleSource, moduleImportFunc) { if (typeof imported === "string") imported = literal(imported); return { arguments: [moduleSource].concat(imported || []), callee: moduleImportFunc, type: "CallExpression" }; } function importCallStmt(imported, moduleSource, moduleImportFunc) { return exprStmt(importCall(imported, moduleSource, moduleImportFunc)); } function exportCall(exportFunc, local, exportedObj) { if (typeof local === "string") local = literal(local); exportedObj = lively_lang.obj.deepCopy(exportedObj); return funcCall(exportFunc, local, exportedObj); } function exportCallStmt(exportFunc, local, exportedObj) { return exprStmt(exportCall(exportFunc, local, exportedObj)); } function declarationWrapperCall(declarationWrapperNode, declNode, varNameLiteral, varKindLiteral, valueNode, recorder, options) { if (declNode) { // here we pass compile-time meta data into the runtime var keyVals = []; var addMeta = false; if (declNode["x-lively-object-meta"]) { var _declNode$xLivelyOb = declNode["x-lively-object-meta"], start = _declNode$xLivelyOb.start, end = _declNode$xLivelyOb.end, evalId = _declNode$xLivelyOb.evalId, sourceAccessorName = _declNode$xLivelyOb.sourceAccessorName; addMeta = true; keyVals.push("start", lively_ast.nodes.literal(start), "end", lively_ast.nodes.literal(end)); } if (evalId === undefined && options.hasOwnProperty("evalId")) { evalId = options.evalId; addMeta = true; } if (sourceAccessorName === undefined && options.hasOwnProperty("sourceAccessorName")) { sourceAccessorName = options.sourceAccessorName; addMeta = true; } if (evalId !== undefined) keyVals.push("evalId", lively_ast.nodes.literal(evalId)); if (sourceAccessorName) keyVals.push("moduleSource", lively_ast.nodes.id(sourceAccessorName)); if (addMeta) { return funcCall(declarationWrapperNode, varNameLiteral, varKindLiteral, valueNode, recorder, lively_ast.nodes.objectLiteral(keyVals) /*meta node*/); } } return funcCall(declarationWrapperNode, varNameLiteral, varKindLiteral, valueNode, recorder); } var capturing = Object.freeze({ rewriteToCaptureTopLevelVariables: rewriteToCaptureTopLevelVariables, rewriteToRegisterModuleToCaptureSetters: rewriteToRegisterModuleToCaptureSetters }); function stringifyFunctionWithoutToplevelRecorder(funcOrSourceOrAst) { var varRecorderName = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "__lvVarRecorder"; // stringifyFunctionWithoutToplevelRecorder((x) => hello + x) // => x => hello + x // instead of String((x) => hello + x) // => x => __lvVarRecorder.hello + x // when run in toplevel scope if (typeof funcOrSourceOrAst === "function") funcOrSourceOrAst = String(funcOrSourceOrAst); var parsed = typeof funcOrSourceOrAst === "string" ? lively_ast.parseFunction(funcOrSourceOrAst) : funcOrSourceOrAst, replaced = lively_ast.ReplaceVisitor.run(parsed, function (node) { var isVarRecorderMember = node.type === "MemberExpression" && node.object.type === "Identifier" && node.object.name === varRecorderName; return isVarRecorderMember ? node.property : node; }); return lively_ast.stringify(replaced); } exports.capturing = capturing; exports.stringifyFunctionWithoutToplevelRecorder = stringifyFunctionWithoutToplevelRecorder; }((this.lively.sourceTransform = this.lively.sourceTransform || {}),lively.lang,lively.classes,lively.ast)); if (typeof module !== "undefined" && module.exports) module.exports = GLOBAL.lively.sourceTransform; })(); // INLINED END /Users/user/git/lively.vm/node_modules/lively.source-transform/dist/lively.source-transform.js (function() { var GLOBAL = typeof window !== "undefined" ? window : typeof global!=="undefined" ? global : typeof self!=="undefined" ? self : this; this.lively = this.lively || {}; (function (exports,lively_lang,lively_ast,lively_sourceTransform,lively_classes,lively_notifications) { 'use strict'; var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj$$1) { return typeof obj$$1; } : function (obj$$1) { return obj$$1 && typeof Symbol === "function" && obj$$1.constructor === Symbol && obj$$1 !== Symbol.prototype ? "symbol" : typeof obj$$1; }; var asyncToGenerator = function (fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }; 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 defineProperty = function (obj$$1, key, value) { if (key in obj$$1) { Object.defineProperty(obj$$1, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj$$1[key] = value; } return obj$$1; }; var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; 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 inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }; var possibleConstructorReturn = function (self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }; var set = function set(object, property, value, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent !== null) { set(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$$1, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr$$1[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$$1, i) { if (Array.isArray(arr$$1)) { return arr$$1; } else if (Symbol.iterator in Object(arr$$1)) { return sliceIterator(arr$$1, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); var toConsumableArray = function (arr$$1) { if (Array.isArray(arr$$1)) { for (var i = 0, arr2 = Array(arr$$1.length); i < arr$$1.length; i++) arr2[i] = arr$$1[i]; return arr2; } else { return Array.from(arr$$1); } }; /*global System,global,Global,self,Node,ImageData*/ function getGlobal() { if (typeof System !== "undefined") return System.global; if (typeof window !== "undefined") return window; if (typeof global !== "undefined") return global; if (typeof Global !== "undefined") return Global; if (typeof self !== "undefined") return self; return function () { return this; }(); } function signatureOf(name, func) { var source = String(func), match = source.match(/function\s*[a-zA-Z0-9_$]*\s*\(([^\)]*)\)/), params = match && match[1] || ''; return name + '(' + params + ')'; } function pluck(list, prop) { return list.map(function (ea) { return ea[prop]; }); } var knownSymbols = function () { return Object.getOwnPropertyNames(Symbol).filter(function (ea) { return _typeof(Symbol[ea]) === "symbol"; }).reduce(function (map, ea) { return map.set(Symbol[ea], "Symbol." + ea); }, new Map()); }(); var symMatcher = /^Symbol\((.*)\)$/; function printSymbol(sym) { if (Symbol.keyFor(sym)) return "Symbol.for(\"" + Symbol.keyFor(sym) + "\")"; if (knownSymbols.get(sym)) return knownSymbols.get(sym); var matched = String(sym).match(symMatcher); return String(sym); } function safeToString(value) { if (!value) return String(value); if (Array.isArray(value)) return "[" + value.map(safeToString).join(",") + "]"; if ((typeof value === "undefined" ? "undefined" : _typeof(value)) === "symbol") return printSymbol(value); try { return String(value); } catch (e) { throw new Error("Cannot print object: " + e.stack); } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- function printEvalResult(evalResult) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var value = evalResult.value, isError = evalResult.isError, isPromise = evalResult.isPromise, promisedValue = evalResult.promisedValue, promiseStatus = evalResult.promiseStatus; if (isError || value instanceof Error) { var err = value, stringified = String(err), stack = err.stack || ""; if (stack && err.message !== err.stack) { stack = String(stack); var errInStackIdx = stack.indexOf(stringified); if (errInStackIdx === 0) stack = stack.slice(stringified.length); stringified += "\n" + stack; } return stringified; } if (isPromise) { var status = lively_lang.string.print(promiseStatus), printed = promiseStatus === "pending" ? undefined : printEvalResult({ value: promisedValue }, options); return "Promise({status: " + status + ", " + (value === undefined ? "" : "value: " + printed) + "})"; } if (value instanceof Promise) return 'Promise({status: "unknown"})'; if (options.inspect) return printInspectEvalValue(value, options.inspectDepth || 2); // options.asString return String(value); } var printInspectEvalValue = function () { var itSym = typeof Symbol !== "undefined" && Symbol.iterator, maxIterLength = 10, maxStringLength = 100, maxNumberOfKeys = 100, maxNumberOfLines = 1000; return printInspect; function printInspect(object, maxDepth) { if ((typeof maxDepth === "undefined" ? "undefined" : _typeof(maxDepth)) === "object") maxDepth = maxDepth.maxDepth || 2; if (!object) return String(object); if (typeof object === "string") { var mark = object.includes("\n") ? "`" : '"'; object = object.split('\n').slice(0, maxNumberOfLines).join('\n'); return mark + object + mark; } if (object instanceof Error) return object.stack || safeToString(object); if (!lively_lang.obj.isObject(object)) return safeToString(object); try { var inspected = lively_lang.obj.inspect(object, { customPrinter: inspectPrinter, maxNumberOfKeys: maxNumberOfKeys, maxDepth: maxDepth, printFunctionSource: true }); } catch (e) {} // return inspected; return inspected === "{}" ? safeToString(object) : inspected; } function printIterable(val, ignore) { var isIterable = typeof val !== "string" && !Array.isArray(val) && itSym && typeof val[itSym] === "function"; if (!isIterable) return ignore; var hasEntries = typeof val.entries === "function", it = hasEntries ? val.entries() : val[itSym](), values = [], open = hasEntries ? "{" : "[", close = hasEntries ? "}" : "]", name = val.constructor && val.constructor.name || "Iterable"; for (var i = 0, next; i < maxIterLength; i++) { next = it.next(); if (next.done) break; values.push(next.value); } var printed = values.map(function (ea) { return hasEntries ? String(ea[0]) + ": " + String(ea[1]) : printInspect(ea, 2); }).join(", "); return name + "(" + open + printed + close + ")"; } function inspectPrinter(val, ignore, continueInspectFn) { if (!val) return ignore; if ((typeof val === "undefined" ? "undefined" : _typeof(val)) === "symbol") return printSymbol(val); if (typeof val === "string") return lively_lang.string.print(lively_lang.string.truncate(val, maxStringLength)); if (val.isMorph) return safeToString(val); if (val instanceof Promise) return "Promise()"; if (typeof Node !== "undefined" && val instanceof Node) return safeToString(val); if (typeof ImageData !== "undefined" && val instanceof ImageData) return safeToString(val); var length = val.length || val.byteLength; if (length !== undefined && length > maxIterLength && val.slice) { var printed = typeof val === "string" || val.byteLength ? safeToString(val.slice(0, maxIterLength)) : val.slice(0, maxIterLength).map(continueInspectFn); return "[" + printed + ",...]"; } var iterablePrinted = printIterable(val, ignore); if (iterablePrinted !== ignore) return iterablePrinted; return ignore; } }(); /*global require, __dirname*/ // helper function getObjectForCompletion(evalFunc, stringToEval) { var startLetters = ''; return Promise.resolve().then(function () { // thenDo = function(err, obj, startLetters) var idx = stringToEval.lastIndexOf('.'); if (idx >= 0) { startLetters = stringToEval.slice(idx + 1); stringToEval = stringToEval.slice(0, idx); } else { startLetters = stringToEval; stringToEval = '(typeof window === "undefined" ? global : window)'; } return evalFunc(stringToEval); }).then(function (evalResult) { return { evalResult: evalResult, startLetters: startLetters, code: stringToEval }; }); } function propertyExtract(excludes, obj$$1, extractor) { return Object.getOwnPropertyNames(obj$$1).concat(Object.getOwnPropertySymbols(obj$$1).map(printSymbol)).filter(function (key) { return excludes.indexOf(key) === -1; }).map(extractor).filter(function (ea) { return !!ea; }).sort(function (a, b) { return a.name < b.name ? -1 : a.name > b.name ? 1 : 0; }); } function getMethodsOf(excludes, obj$$1) { return propertyExtract(excludes, obj$$1, function (key) { if (obj$$1.__lookupGetter__ && obj$$1.__lookupGetter__(key) || typeof obj$$1[key] !== 'function') return null; return { name: key, completion: signatureOf(key, obj$$1[key]) }; }); } function getAttributesOf(excludes, obj$$1) { return propertyExtract(excludes, obj$$1, function (key) { if (obj$$1.__lookupGetter__ && !obj$$1.__lookupGetter__(key) && typeof obj$$1[key] === 'function') return null; return { name: key, completion: key }; }); } function getProtoChain(obj$$1) { var protos = [], proto = obj$$1; while (obj$$1) { protos.push(obj$$1);obj$$1 = obj$$1.__proto__; } return protos; } function getDescriptorOf(originalObj, proto) { function shorten(s, len) { if (s.length > len) s = s.slice(0, len) + '...'; return s.replace(/\n/g, '').replace(/\s+/g, ' '); } if (originalObj === proto) { if (typeof originalObj !== 'function') return shorten(safeToString(originalObj), 50); var funcString = originalObj.toString(), body = shorten(funcString.slice(funcString.indexOf('{') + 1, funcString.lastIndexOf('}')), 50); return signatureOf(originalObj.displayName || originalObj.name || 'function', originalObj) + ' {' + body + '}'; } var klass = proto.hasOwnProperty('constructor') && proto.constructor; if (!klass) return 'prototype'; if (typeof klass.type === 'string' && klass.type.length) return shorten(klass.type, 50); if (typeof klass.name === 'string' && klass.name.length) return shorten(klass.name, 50); return "anonymous class"; } function descriptorsOfObjAndProtoProperties(obj$$1) { var excludes = [], completions = getProtoChain(obj$$1).map(function (proto) { var descr = getDescriptorOf(obj$$1, proto), methodsAndAttributes = getMethodsOf(excludes, proto).concat(getAttributesOf(excludes, proto)); excludes = excludes.concat(pluck(methodsAndAttributes, 'name')); return [descr, pluck(methodsAndAttributes, 'completion')]; }); return completions; } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- // the main deal function getCompletions(evalFunc, string$$1, thenDo) { // thendo = function(err, completions/*ARRAY*/) // eval string and for the resulting object find attributes and methods, // grouped by its prototype / class chain // if string is something like "foo().bar.baz" then treat "baz" as start // letters = filter for properties of foo().bar // ("foo().bar.baz." for props of the result of the complete string) var promise$$1 = getObjectForCompletion(evalFunc, string$$1).then(function (evalResultAndStartLetters) { var evalResult = evalResultAndStartLetters.evalResult, value = evalResult && evalResult.isEvalResult ? evalResult.value : evalResult, result = { completions: descriptorsOfObjAndProtoProperties(value), startLetters: evalResultAndStartLetters.startLetters, code: evalResultAndStartLetters.code }; if (evalResult && evalResult.isPromise) { if (evalResult.promiseStatus === "fulfilled") result.promiseResolvedCompletions = descriptorsOfObjAndProtoProperties(evalResult.promisedValue);else if (evalResult.promiseStatus === "rejected") result.promiseRejectedCompletions = descriptorsOfObjAndProtoProperties(evalResult.promisedValue); } return result; }); if (typeof thenDo === "function") { promise$$1.then(function (result) { return thenDo(null, result); }).catch(function (err) { return thenDo(err); }); } return promise$$1; } var completions = Object.freeze({ getObjectForCompletion: getObjectForCompletion, getCompletions: getCompletions }); var id = lively_ast.nodes.id; var literal = lively_ast.nodes.literal; var member = lively_ast.nodes.member; var defaultDeclarationWrapperName = "lively.capturing-declaration-wrapper"; var defaultClassToFunctionConverterName = "initializeES6ClassForLively"; function processInlineCodeTransformOptions(parsed, options) { if (!parsed.comments) return options; var livelyComment = parsed.comments.find(function (ea) { return ea.text.startsWith("lively.vm "); }); if (!livelyComment) return options; try { var inlineOptions = eval("inlineOptions = {" + livelyComment.text.slice("lively.vm ".length) + "};"); return Object.assign(options, inlineOptions); } catch (err) { return options; } } function evalCodeTransform(code, options) { // variable declaration and references in the the source code get // transformed so that they are bound to `varRecorderName` aren't local // state. THis makes it possible to capture eval results, e.g. for // inspection, watching and recording changes, workspace vars, and // incrementally evaluating var declarations and having values bound later. // 1. Allow evaluation of function expressions and object literals code = lively_ast.transform.transformSingleExpression(code); var parsed = lively_ast.parse(code, { withComments: true }); options = processInlineCodeTransformOptions(parsed, options); // 2. Annotate definitions with code location. This is being used by the // function-wrapper-source transform. var _query$topLevelDeclsA = lively_ast.query.topLevelDeclsAndRefs(parsed), classDecls = _query$topLevelDeclsA.classDecls, funcDecls = _query$topLevelDeclsA.funcDecls, varDecls = _query$topLevelDeclsA.varDecls, annotation = {}; if (options.hasOwnProperty("evalId")) annotation.evalId = options.evalId; if (options.sourceAccessorName) annotation.sourceAccessorName = options.sourceAccessorName; [].concat(toConsumableArray(classDecls), toConsumableArray(funcDecls)).forEach(function (node) { return node["x-lively-object-meta"] = _extends({}, annotation, { start: node.start, end: node.end }); }); varDecls.forEach(function (node) { return node.declarations.forEach(function (decl) { return decl["x-lively-object-meta"] = _extends({}, annotation, { start: decl.start, end: decl.end }); }); }); // transforming experimental ES features into accepted es6 form... parsed = lively_ast.transform.objectSpreadTransform(parsed); // 3. capture top level vars into topLevelVarRecorder "environment" if (!options.topLevelVarRecorder && options.topLevelVarRecorderName) { var G = getGlobal(); if (options.topLevelVarRecorderName === "GLOBAL") { // "magic" options.topLevelVarRecorder = getGlobal(); } else { options.topLevelVarRecorder = lively_lang.Path(options.topLevelVarRecorderName).get(G); } } if (options.topLevelVarRecorder) { // capture and wrap logic var blacklist = (options.dontTransform || []).concat(["arguments"]), undeclaredToTransform = !!options.recordGlobals ? null /*all*/ : lively_lang.arr.withoutAll(Object.keys(options.topLevelVarRecorder), blacklist), varRecorder = id(options.varRecorderName || '__lvVarRecorder'), es6ClassToFunctionOptions = undefined; if (options.declarationWrapperName || typeof options.declarationCallback === "function") { // 2.1 declare a function that wraps all definitions, i.e. all var // decls, functions, classes etc that get captured will be wrapped in this // function. This allows to define some behavior that is run whenever // variables get initialized or changed as well as transform values. // The parameters passed are: // name, kind, value, recorder // Note that the return value of declarationCallback is used as the // actual value in the code being executed. This allows to transform the // value as necessary but also means that declarationCallback needs to // return sth meaningful! var declarationWrapperName = options.declarationWrapperName || defaultDeclarationWrapperName; options.declarationWrapper = member(id(options.varRecorderName || '__lvVarRecorder'), literal(declarationWrapperName), true); if (options.declarationCallback) options.topLevelVarRecorder[declarationWrapperName] = options.declarationCallback; } var transformES6Classes = options.hasOwnProperty("transformES6Classes") ? options.transformES6Classes : true; if (transformES6Classes) { // Class declarations and expressions are converted into a function call // to `createOrExtendClass`, a helper that will produce (or extend an // existing) constructor function in a way that allows us to redefine // methods and properties of the class while keeping the class object // identical if (!(defaultClassToFunctionConverterName in options.topLevelVarRecorder)) options.topLevelVarRecorder[defaultClassToFunctionConverterName] = lively_classes.runtime.initializeClass; es6ClassToFunctionOptions = { currentModuleAccessor: options.currentModuleAccessor, classHolder: varRecorder, functionNode: member(varRecorder, defaultClassToFunctionConverterName), declarationWrapper: options.declarationWrapper, evalId: options.evalId, sourceAccessorName: options.sourceAccessorName }; } // 3.2 Here we call out to the actual code transformation that installs the captured top level vars parsed = lively_sourceTransform.capturing.rewriteToCaptureTopLevelVariables(parsed, varRecorder, { es6ImportFuncId: options.es6ImportFuncId, es6ExportFuncId: options.es6ExportFuncId, ignoreUndeclaredExcept: undeclaredToTransform, exclude: blacklist, declarationWrapper: options.declarationWrapper || undefined, classToFunction: es6ClassToFunctionOptions, evalId: options.evalId, sourceAccessorName: options.sourceAccessorName, keepTopLevelVarDecls: options.keepTopLevelVarDecls }); } if (options.wrapInStartEndCall) { parsed = lively_ast.transform.wrapInStartEndCall(parsed, { startFuncNode: options.startFuncNode, endFuncNode: options.endFuncNode }); } var result = lively_ast.stringify(parsed); if (options.sourceURL) result += "\n//# sourceURL=" + options.sourceURL.replace(/\s/g, "_"); return result; } function evalCodeTransformOfSystemRegisterSetters(code) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; if (!options.topLevelVarRecorder) return code; if (typeof options.declarationCallback === "function" || options.declarationWrapperName) { var declarationWrapperName = options.declarationWrapperName || defaultDeclarationWrapperName; options.declarationWrapper = member(id(options.varRecorderName), literal(declarationWrapperName), true); if (options.declarationCallback) options.topLevelVarRecorder[declarationWrapperName] = options.declarationCallback; } var parsed = lively_ast.parse(code), blacklist = (options.dontTransform || []).concat(["arguments"]), undeclaredToTransform = !!options.recordGlobals ? null /*all*/ : lively_lang.arr.withoutAll(Object.keys(options.topLevelVarRecorder), blacklist), result = lively_sourceTransform.capturing.rewriteToRegisterModuleToCaptureSetters(parsed, id(options.varRecorderName || '__lvVarRecorder'), _extends({ exclude: blacklist }, options)); return lively_ast.stringify(result); } /*global: global, System*/ // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- // options // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- var defaultTopLevelVarRecorderName = '__lvVarRecorder'; var startEvalFunctionName = "lively.vm-on-eval-start"; var endEvalFunctionName = "lively.vm-on-eval-end"; function _normalizeEvalOptions(opts) { if (!opts) opts = {}; opts = _extends({ targetModule: null, sourceURL: opts.targetModule, runtime: null, context: getGlobal(), varRecorderName: defaultTopLevelVarRecorderName, dontTransform: [], // blacklist vars recordGlobals: null, returnPromise: true, promiseTimeout: 200, waitForPromise: true, wrapInStartEndCall: false, onStartEval: null, onEndEval: null }, opts); if (opts.targetModule) { var moduleEnv = opts.runtime && opts.runtime.modules && opts.runtime.modules[opts.targetModule]; if (moduleEnv) opts = Object.assign(opts, moduleEnv); } if (opts.wrapInStartEndCall) { opts.startFuncNode = { type: "MemberExpression", object: { type: "Identifier", name: opts.varRecorderName }, property: { type: "Literal", value: startEvalFunctionName }, computed: true }; opts.endFuncNode = { type: "MemberExpression", object: { type: "Identifier", name: opts.varRecorderName }, property: { type: "Literal", value: endEvalFunctionName }, computed: true }; } return opts; } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- // eval // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- function _eval(__lvEvalStatement, __lvVarRecorder /*needed as arg for capturing*/, __lvOriginalCode) { return eval(__lvEvalStatement); } function runEval$1(code, options, thenDo) { // The main function where all eval options are configured. // options can be: { // runtime: { // modules: {[MODULENAME: PerModuleOptions]} // } // } // or directly, PerModuleOptions = { // varRecorderName: STRING, // default is '__lvVarRecorder' // topLevelVarRecorder: OBJECT, // context: OBJECT, // sourceURL: STRING, // recordGlobals: BOOLEAN, // also transform free vars? default is false // transpiler: FUNCTION(source, options) // for transforming the source after the lively xfm // wrapInStartEndCall: BOOLEAN // onStartEval: FUNCTION()?, // onEndEval: FUNCTION(err, value)? // note: we pass in the value of last expr, not EvalResult! // } if (typeof options === 'function' && arguments.length === 2) { thenDo = options;options = null; } var result = new EvalResult(), returnedError, returnedValue, onEvalEndError, onEvalEndValue, onEvalStartCalled = false, onEvalEndCalled = false; options = _normalizeEvalOptions(options); // 1. In case we rewrite the code with on-start and on-end calls we prepare // the environment with actual function handlers that will get called once // the code is evaluated var evalDone = lively_lang.promise.deferred(), recorder = options.topLevelVarRecorder || getGlobal(), originalSource = code; if (options.wrapInStartEndCall) { if (recorder[startEvalFunctionName]) console.warn(result.addWarning("startEvalFunctionName " + startEvalFunctionName + " already exists in recorder!")); if (recorder[endEvalFunctionName]) console.warn(result.addWarning("endEvalFunctionName " + endEvalFunctionName + " already exists in recorder!")); recorder[startEvalFunctionName] = function () { if (onEvalStartCalled) { console.warn(result.addWarning("onEvalStartCalled multiple times!"));return; } onEvalStartCalled = true; if (typeof options.onStartEval === "function") options.onStartEval(); }; recorder[endEvalFunctionName] = function (err, value) { if (onEvalEndCalled) { console.warn(result.addWarning("onEvalEndCalled multiple times!"));return; } onEvalEndCalled = true; finishEval(err, value, result, options, recorder, evalDone, thenDo); }; } // 2. Transform the code to capture top-level variables, inject function calls, ... try { code = evalCodeTransform(code, options); if (options.header) code = options.header + code; if (options.footer) code = code + options.footer; if (options.transpiler) code = options.transpiler(code, options.transpilerOptions); // console.log(code); } catch (e) { console.warn(result.addWarning("lively.vm evalCodeTransform not working: " + e)); } // 3. Now really run eval! try { typeof $world !== "undefined" && $world.get('log') && ($world.get('log').textString = code); returnedValue = _eval.call(options.context, code, options.topLevelVarRecorder, options.originalSource || originalSource); } catch (e) { returnedError = e; } // 4. Wrapping up: if we inject a on-eval-end call we let it handle the // wrap-up, otherwise we firectly call finishEval() if (options.wrapInStartEndCall) { if (returnedError && !onEvalEndCalled) recorder[endEvalFunctionName](returnedError, undefined); } else { finishEval(returnedError, returnedError || returnedValue, result, options, recorder, evalDone, thenDo); } return options.sync ? result : evalDone.promise; } function finishEval(err, value, result, options, recorder, evalDone, thenDo) { // 5. Here we end the evaluation. Note that if we are in sync mode we cannot // use any Promise since promises always run on next tick. That's why we have // to slightly duplicate the finish logic... if (options.wrapInStartEndCall) { delete recorder[startEvalFunctionName]; delete recorder[endEvalFunctionName]; } if (err) { result.isError = true;result.value = err; } else result.value = value; if (result.value instanceof Promise) result.isPromise = true; if (options.sync) { result.processSync(options); if (typeof options.onEndEval === "function") options.onEndEval(err, value); } else { result.process(options).then(function () { typeof thenDo === "function" && thenDo(null, result); typeof options.onEndEval === "function" && options.onEndEval(err, value); return result; }, function (err) { typeof thenDo === "function" && thenDo(err, undefined); typeof options.onEndEval === "function" && options.onEndEval(err, undefined); return result; }).then(evalDone.resolve, evalDone.reject); } } function syncEval$1(string$$1, options) { // See #runEval for options. // Although the defaul eval is synchronous we assume that the general // evaluation might not return immediatelly. This makes is possible to // change the evaluation backend, e.g. to be a remotely attached runtime options = Object.assign(options || {}, { sync: true }); return runEval$1(string$$1, options); } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- // EvalResult // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- var EvalResult = function () { function EvalResult() { classCallCheck(this, EvalResult); this.isEvalResult = true; this.value = undefined; this.warnings = []; this.isError = false; this.isPromise = false; this.promisedValue = undefined; this.promiseStatus = "unknown"; } createClass(EvalResult, [{ key: "addWarning", value: function addWarning(warn) { this.warnings.push(warn);return warn; } }, { key: "printed", value: function printed() { var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; this.value = printEvalResult(this, options); } }, { key: "processSync", value: function processSync(options) { if (options.inspect || options.asString) this.value = this.print(this.value, options); return this; } }, { key: "process", value: function process(options) { var result = this; if (result.isPromise && options.waitForPromise) { return tryToWaitForPromise(result, options.promiseTimeout).then(function () { if (options.inspect || options.asString) result.printed(options); return result; }); } if (options.inspect || options.asString) result.printed(options); return Promise.resolve(result); } }]); return EvalResult; }(); function tryToWaitForPromise(evalResult, timeoutMs) { console.assert(evalResult.isPromise, "no promise in tryToWaitForPromise???"); var timeout = {}, timeoutP = new Promise(function (resolve) { return setTimeout(resolve, timeoutMs, timeout); }); return Promise.race([timeoutP, evalResult.value]).then(function (resolved) { return Object.assign(evalResult, resolved !== timeout ? { promiseStatus: "fulfilled", promisedValue: resolved } : { promiseStatus: "pending" }); }).catch(function (rejected) { return Object.assign(evalResult, { promiseStatus: "rejected", promisedValue: rejected }); }); } var funcCall = lively_ast.nodes.funcCall; var member$1 = lively_ast.nodes.member; var literal$1 = lively_ast.nodes.literal; // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- // load support function ensureImportsAreImported(System, code, parentModule) { // FIXME do we have to do a reparse? We should be able to get the ast from // the rewriter... var body = lively_ast.parse(code).body, imports = body.filter(function (node) { return node.type === "ImportDeclaration"; }); return Promise.all(imports.map(function (node) { return System.normalize(node.source.value, parentModule).then(function (fullName) { return System.get(fullName) || System.import(fullName); }); })).catch(function (err) { console.error("Error ensuring imports: " + err.message);throw err; }); } function hasUnimportedImports(System, code, parentModule) { var body = lively.ast.parse(code).body, imports = body.filter(function (node) { return node.type === "ImportDeclaration"; }), importedModules = lively_lang.arr.uniq(imports.map(function (ea) { return ea.source.value; })).filter(Boolean), unloadedImports = importedModules.filter(function (ea) { return !System.get(System.decanonicalize(ea, parentModule)); }); return unloadedImports.length > 0; } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- // transpiler to make es next work function babelTranspilerForAsyncAwaitCode(System, babel, filename, env) { // The function wrapper is needed b/c we need toplevel awaits and babel // converts "this" => "undefined" for modules return function (source, options) { options = Object.assign({ sourceMap: undefined, // 'inline' || true || false inputSourceMap: undefined, filename: filename, code: true, ast: false }, options); var sourceForBabel = "(async function(__rec) {\n" + source + "\n}).call(this);", transpiled = babel.transform(sourceForBabel, options).code; transpiled = transpiled.replace(/\}\)\.call\(undefined\);$/, "}).call(this)"); return transpiled; }; } function babelPluginTranspilerForAsyncAwaitCode(System, babelWrapper, filename, env) { // The function wrapper is needed b/c we need toplevel awaits and babel // converts "this" => "undefined" for modules return function (source, options) { var babelOptions = System.babelOptions || {}, presets = []; presets.push(babelWrapper.presetES2015); if (babelOptions.stage3) presets.push({ plugins: babelWrapper.pluginsStage3 }); if (babelOptions.stage2) presets.push({ plugins: babelWrapper.pluginsStage2 }); if (babelOptions.stage1) presets.push({ plugins: babelWrapper.pluginsStage1 }); options = Object.assign({ sourceMap: undefined, // 'inline' || true || false inputSourceMap: undefined, filename: filename, babelrc: false, // plugins: plugins, presets: presets, moduleIds: false, code: true, ast: false }, options); var sourceForBabel = "(async function(__rec) {\n" + source + "\n}).call(this);", transpiled = babelWrapper.babel.transform(sourceForBabel, options).code; transpiled = transpiled.replace(/\}\)\.call\(undefined\);$/, "}).call(this)"); return transpiled; }; } function getEs6Transpiler(System, options, env) { if (options.transpiler) return options.transpiler; if (!options.es6Transpile) return null; if (System.transpiler === "babel") { var babel = System.global[System.transpiler] || System.get(System.decanonicalize(System.transpiler)); return babel ? babelTranspilerForAsyncAwaitCode(System, babel, options.targetModule, env) : System.import(System.transpiler).then(function (babel) { return babelTranspilerForAsyncAwaitCode(System, babel, options.targetModule, env); }); } if (System.transpiler === "plugin-babel") { var babelPluginPath = System.decanonicalize("plugin-babel"), babelPath = babelPluginPath.split("/").slice(0, -1).concat("systemjs-babel-browser.js").join("/"), babelPlugin = System.get(babelPath); return babelPlugin ? babelPluginTranspilerForAsyncAwaitCode(System, babelPlugin, options.targetModule, env) : System.import(babelPath).then(function (babelPlugin) { return babelPluginTranspilerForAsyncAwaitCode(System, babelPlugin, options.targetModule, env); }); } if (System.transpiler === "lively.transpiler") { var Transpiler = System.get(System.decanonicalize("lively.transpiler")).default, transpiler = new Transpiler(System, options.targetModule, env); return function (source, options) { return transpiler.transpileDoit(source, options); }; } throw new Error("Sorry, currently only babel is supported as es6 transpiler for runEval!"); } function runEval$2(System, code, options) { options = _extends({ targetModule: null, parentModule: null, es6Transpile: true, transpiler: null, // function with params: source, options transpilerOptions: null, format: "esm" }, options); var defaultSourceAccessorName = "__lvOriginalCode"; var originalSource = code; System.debug && console.log("[lively.module] runEval: " + code.slice(0, 100).replace(/\n/mg, " ") + "..."); var _options = options, format = _options.format, targetModule = _options.targetModule, parentModule = _options.parentModule; targetModule = System.decanonicalize(targetModule || "*scratch*", parentModule); options.targetModule = targetModule; if (format) { var meta = System.getConfig().meta[targetModule]; if (!meta) meta = {}; if (!meta[targetModule]) meta[targetModule] = {}; if (!meta[targetModule].format) { meta[targetModule].format = format; System.config(meta); } } var module = System.get("@lively-env").moduleEnv(targetModule), recorder = module.recorder, recorderName = module.recorderName, dontTransform = module.dontTransform, transpiler = getEs6Transpiler(System, options, module), header = "var _moduleExport = " + recorderName + "._moduleExport,\n" + (" _moduleImport = " + recorderName + "._moduleImport;\n"); options = _extends({ waitForPromise: true, sync: false, evalId: options.evalId || module.nextEvalId(), sourceAccessorName: (options.hasOwnProperty("embedOriginalCode") ? options.embedOriginalCode : true) ? defaultSourceAccessorName : undefined, originalSource: originalSource }, options, { header: header, recordGlobals: true, dontTransform: dontTransform, varRecorderName: recorderName, topLevelVarRecorder: recorder, sourceURL: options.sourceURL || options.targetModule, context: options.context || recorder, wrapInStartEndCall: true, // for async / await eval support es6ExportFuncId: "_moduleExport", es6ImportFuncId: "_moduleImport", transpiler: transpiler, declarationWrapperName: module.varDefinitionCallbackName, currentModuleAccessor: funcCall(member$1(funcCall(member$1(member$1("__lvVarRecorder", "System"), "get"), literal$1("@lively-env")), "moduleEnv"), literal$1(options.targetModule)) }); // delay eval to ensure imports if (!options.sync && !options.importsEnsured && hasUnimportedImports(System, code, targetModule)) { return ensureImportsAreImported(System, code, targetModule).then(function () { return runEval$2(System, originalSource, _extends({}, options, { importsEnsured: true })); }); } // delay eval to ensure SystemJS module record if (!module.record()) { if (!options.sync && !options._moduleImported) return System.import(targetModule).catch(function (err) { return null; }).then(function () { return runEval$2(System, originalSource, _extends({}, options, { _moduleImported: true })); }); module.ensureRecord(); // so we can record dependent modules } // delay eval to ensure transpiler is loaded if (options.es6Transpile && options.transpiler instanceof Promise) { if (!options.sync && !options._transpilerLoaded) { return options.transpiler.catch(function (err) { return console.error(err); }).then(function (transpiler) { return runEval$2(System, originalSource, _extends({}, options, { transpiler: transpiler, _transpilerLoaded: true })); }); } else { console.warn("[lively.vm] sync eval requested but transpiler is not yet loaded, will continue without transpilation!"); options.transpiler = null; } } System.debug && console.log("[lively.module] runEval in module " + targetModule + " started"); lively_notifications.emit("lively.vm/doitrequest", { code: originalSource, waitForPromise: options.waitForPromise, targetModule: options.targetModule }, Date.now(), System); System.get("@lively-env").evaluationStart(targetModule); var result = runEval$1(code, options); return options.sync ? evalEnd(System, originalSource, options, result) : Promise.resolve(result).then(function (result) { return evalEnd(System, originalSource, options, result); }); } function evalEnd(System, code, options, result) { System.get("@lively-env").evaluationEnd(options.targetModule); System.debug && console.log("[lively.module] runEval in module " + options.targetModule + " done"); lively_notifications.emit("lively.vm/doitresult", { code: code, result: result, waitForPromise: options.waitForPromise, targetModule: options.targetModule }, Date.now(), System); return result; } /*global System,location*/ var EvalStrategy = function () { function EvalStrategy() { classCallCheck(this, EvalStrategy); } createClass(EvalStrategy, [{ key: "runEval", value: function () { var _ref = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(source, options) { return regeneratorRuntime.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: return _context.abrupt("return", Promise.reject("runEval(source, options) not yet implemented for " + this.constructor.name)); case 1: case "end": return _context.stop(); } } }, _callee, this); })); function runEval(_x, _x2) { return _ref.apply(this, arguments); } return runEval; }() }, { key: "keysOfObject", value: function () { var _ref2 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee2(prefix, options) { return regeneratorRuntime.wrap(function _callee2$(_context2) { while (1) { switch (_context2.prev = _context2.next) { case 0: return _context2.abrupt("return", Promise.reject("keysOfObject(prefix, options) not yet implemented for " + this.constructor.name)); case 1: case "end": return _context2.stop(); } } }, _callee2, this); })); function keysOfObject(_x3, _x4) { return _ref2.apply(this, arguments); } return keysOfObject; }() }]); return EvalStrategy; }(); var SimpleEvalStrategy = function (_EvalStrategy) { inherits(SimpleEvalStrategy, _EvalStrategy); function SimpleEvalStrategy() { classCallCheck(this, SimpleEvalStrategy); return possibleConstructorReturn(this, (SimpleEvalStrategy.__proto__ || Object.getPrototypeOf(SimpleEvalStrategy)).apply(this, arguments)); } createClass(SimpleEvalStrategy, [{ key: "runEval", value: function () { var _ref3 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee3(source, options) { return regeneratorRuntime.wrap(function _callee3$(_context3) { while (1) { switch (_context3.prev = _context3.next) { case 0: return _context3.abrupt("return", Promise.resolve().then(function () { try { return Promise.resolve({ value: eval(source) }); } catch (err) { return { isError: true, value: err }; } })); case 1: case "end": return _context3.stop(); } } }, _callee3, this); })); function runEval(_x5, _x6) { return _ref3.apply(this, arguments); } return runEval; }() }, { key: "keysOfObject", value: function () { var _ref4 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee4(prefix, options) { var _this2 = this; var result; return regeneratorRuntime.wrap(function _callee4$(_context4) { while (1) { switch (_context4.prev = _context4.next) { case 0: _context4.next = 2; return lively.vm.completions.getCompletions(function (code) { return _this2.runEval(code, options); }, prefix); case 2: result = _context4.sent; return _context4.abrupt("return", { completions: result.completions, prefix: result.startLetters }); case 4: case "end": return _context4.stop(); } } }, _callee4, this); })); function keysOfObject(_x7, _x8) { return _ref4.apply(this, arguments); } return keysOfObject; }() }]); return SimpleEvalStrategy; }(EvalStrategy); var LivelyVmEvalStrategy = function (_EvalStrategy2) { inherits(LivelyVmEvalStrategy, _EvalStrategy2); function LivelyVmEvalStrategy() { classCallCheck(this, LivelyVmEvalStrategy); return possibleConstructorReturn(this, (LivelyVmEvalStrategy.__proto__ || Object.getPrototypeOf(LivelyVmEvalStrategy)).apply(this, arguments)); } createClass(LivelyVmEvalStrategy, [{ key: "normalizeOptions", value: function normalizeOptions(options) { if (!options.targetModule) throw new Error("runEval called but options.targetModule not specified!"); return Object.assign({ sourceURL: options.targetModule + "_doit_" + Date.now() }, options); } }, { key: "runEval", value: function () { var _ref5 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee5(source, options) { var System; return regeneratorRuntime.wrap(function _callee5$(_context5) { while (1) { switch (_context5.prev = _context5.next) { case 0: options = this.normalizeOptions(options); System = options.System || lively.modules.System; System.config({ meta: defineProperty({}, options.targetModule, { format: "esm" }) }); return _context5.abrupt("return", lively.vm.runEval(source, options)); case 4: case "end": return _context5.stop(); } } }, _callee5, this); })); function runEval(_x9, _x10) { return _ref5.apply(this, arguments); } return runEval; }() }, { key: "keysOfObject", value: function () { var _ref6 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee6(prefix, options) { var result; return regeneratorRuntime.wrap(function _callee6$(_context6) { while (1) { switch (_context6.prev = _context6.next) { case 0: _context6.next = 2; return lively.vm.completions.getCompletions(function (code) { return lively.vm.runEval(code, options); }, prefix); case 2: result = _context6.sent; return _context6.abrupt("return", { completions: result.completions, prefix: result.startLetters }); case 4: case "end": return _context6.stop(); } } }, _callee6, this); })); function keysOfObject(_x11, _x12) { return _ref6.apply(this, arguments); } return keysOfObject; }() }]); return LivelyVmEvalStrategy; }(EvalStrategy); var RemoteEvalStrategy = function (_LivelyVmEvalStrategy) { inherits(RemoteEvalStrategy, _LivelyVmEvalStrategy); function RemoteEvalStrategy() { classCallCheck(this, RemoteEvalStrategy); return possibleConstructorReturn(this, (RemoteEvalStrategy.__proto__ || Object.getPrototypeOf(RemoteEvalStrategy)).apply(this, arguments)); } createClass(RemoteEvalStrategy, [{ key: "sourceForRemote", value: function sourceForRemote(action, arg, options) { var contextFetch = lively_lang.obj.isString(options.context) ? options.context : false; options = lively_lang.obj.dissoc(options, ["systemInterface", "System", "context"]); return "\n(function() {\n var arg = " + JSON.stringify(arg) + ",\n options = " + JSON.stringify(options) + ";\n if (typeof lively === \"undefined\" || !lively.vm) {\n return Promise.resolve({\n isEvalResult: true,\n isError: true,\n value: 'lively.vm not available!'\n });\n }\n var hasSystem = typeof System !== \"undefined\"\n options.context = " + contextFetch + "\n if (!options.context) {\n options.context = hasSystem\n ? System.global\n : typeof window !== \"undefined\"\n ? window\n : typeof global !== \"undefined\"\n ? global\n : typeof self !== \"undefined\" ? self : this;\n }\n function evalFunction(source, options) {\n if (hasSystem) {\n var conf = {meta: {}}; conf.meta[options.targetModule] = {format: \"esm\"};\n System.config(conf);\n } else {\n options = Object.assign({topLevelVarRecorderName: \"GLOBAL\"}, options);\n delete options.targetModule;\n }\n return lively.vm.runEval(source, options);\n }\n function keysOfObjectFunction(prefix, options) {\n return lively.vm.completions.getCompletions(code => evalFunction(code, options), prefix)\n .then(result => ({isEvalResult: true, completions: result.completions, prefix: result.startLetters}));\n }\n return " + (action === "eval" ? "evalFunction" : "keysOfObjectFunction") + "(arg, options)\n .catch(err => ({isEvalResult: true, isError: true, value: String(err.stack || err)}));\n})();\n"; } }, { key: "runEval", value: function () { var _ref7 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee7(source, options) { return regeneratorRuntime.wrap(function _callee7$(_context7) { while (1) { switch (_context7.prev = _context7.next) { case 0: return _context7.abrupt("return", this.remoteEval(this.sourceForRemote("eval", source, options), options)); case 1: case "end": return _context7.stop(); } } }, _callee7, this); })); function runEval(_x13, _x14) { return _ref7.apply(this, arguments); } return runEval; }() }, { key: "keysOfObject", value: function () { var _ref8 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee8(prefix, options) { return regeneratorRuntime.wrap(function _callee8$(_context8) { while (1) { switch (_context8.prev = _context8.next) { case 0: return _context8.abrupt("return", this.remoteEval(this.sourceForRemote("keysOfObject", prefix, options), options)); case 1: case "end": return _context8.stop(); } } }, _callee8, this); })); function keysOfObject(_x15, _x16) { return _ref8.apply(this, arguments); } return keysOfObject; }() }, { key: "remoteEval", value: function () { var _ref9 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee9(source, options) { var result; return regeneratorRuntime.wrap(function _callee9$(_context9) { while (1) { switch (_context9.prev = _context9.next) { case 0: _context9.prev = 0; _context9.next = 3; return this.basicRemoteEval(source, options); case 3: result = _context9.sent; return _context9.abrupt("return", typeof result === "string" ? JSON.parse(result) : result); case 7: _context9.prev = 7; _context9.t0 = _context9["catch"](0); return _context9.abrupt("return", { isError: true, value: "Remote eval failed: " + (result || _context9.t0) }); case 10: case "end": return _context9.stop(); } } }, _callee9, this, [[0, 7]]); })); function remoteEval(_x17, _x18) { return _ref9.apply(this, arguments); } return remoteEval; }() }, { key: "basicRemoteEval", value: function () { var _ref10 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee10(source, options) { return regeneratorRuntime.wrap(function _callee10$(_context10) { while (1) { switch (_context10.prev = _context10.next) { case 0: throw new Error("Not yet implemented"); case 1: case "end": return _context10.stop(); } } }, _callee10, this); })); function basicRemoteEval(_x19, _x20) { return _ref10.apply(this, arguments); } return basicRemoteEval; }() }]); return RemoteEvalStrategy; }(LivelyVmEvalStrategy); var HttpEvalStrategy = function (_RemoteEvalStrategy) { inherits(HttpEvalStrategy, _RemoteEvalStrategy); createClass(HttpEvalStrategy, null, [{ key: "defaultURL", get: function get() { return "http://localhost:3000/lively"; } }]); function HttpEvalStrategy(url) { classCallCheck(this, HttpEvalStrategy); var _this5 = possibleConstructorReturn(this, (HttpEvalStrategy.__proto__ || Object.getPrototypeOf(HttpEvalStrategy)).call(this)); _this5.url = url || _this5.constructor.defaultURL; return _this5; } createClass(HttpEvalStrategy, [{ key: "normalizeOptions", value: function normalizeOptions(options) { options = get$1(HttpEvalStrategy.prototype.__proto__ || Object.getPrototypeOf(HttpEvalStrategy.prototype), "normalizeOptions", this).call(this, options); return Object.assign({ serverEvalURL: this.url }, options, { context: null }); } }, { key: "basicRemoteEval", value: function () { var _ref11 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee11(source, options) { var method; return regeneratorRuntime.wrap(function _callee11$(_context11) { while (1) { switch (_context11.prev = _context11.next) { case 0: options = this.normalizeOptions(options); method = "basicRemoteEval_" + (System.get("@system-env").node ? "node" : "web"); _context11.next = 4; return this[method]({ method: "POST", body: source }, options.serverEvalURL); case 4: return _context11.abrupt("return", _context11.sent); case 5: case "end": return _context11.stop(); } } }, _callee11, this); })); function basicRemoteEval(_x21, _x22) { return _ref11.apply(this, arguments); } return basicRemoteEval; }() }, { key: "basicRemoteEval_web", value: function () { var _ref12 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee12(payload, url) { var _ref13, _ref14, domain, loc, crossDomain, res; return regeneratorRuntime.wrap(function _callee12$(_context12) { while (1) { switch (_context12.prev = _context12.next) { case 0: _ref13 = url.match(/[^:]+:\/\/[^\/]+/) || [url], _ref14 = slicedToArray(_ref13, 1), domain = _ref14[0], loc = void 0, crossDomain = void 0; // fixme: this should be replaced by accessing the location // in a canonical way if (System.get("@system-env").worker) loc = window.location;else { loc = document.location; } crossDomain = loc.origin !== domain; if (crossDomain) { // use lively.server proxy plugin payload.headers = _extends({}, payload.headers, { 'pragma': 'no-cache', 'cache-control': 'no-cache', "x-lively-proxy-request": url }); url = loc.origin; } _context12.prev = 4; _context12.next = 7; return window.fetch(url, payload); case 7: res = _context12.sent; _context12.next = 13; break; case 10: _context12.prev = 10; _context12.t0 = _context12["catch"](4); throw new Error("Cannot reach server at " + url + ": " + _context12.t0.message); case 13: if (res.ok) { _context12.next = 15; break; } throw new Error("Server at " + url + ": " + res.statusText); case 15: return _context12.abrupt("return", res.text()); case 16: case "end": return _context12.stop(); } } }, _callee12, this, [[4, 10]]); })); function basicRemoteEval_web(_x23, _x24) { return _ref12.apply(this, arguments); } return basicRemoteEval_web; }() }, { key: "basicRemoteEval_node", value: function () { var _ref15 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee13(payload, url) { var urlParse, http, opts; return regeneratorRuntime.wrap(function _callee13$(_context13) { while (1) { switch (_context13.prev = _context13.next) { case 0: urlParse = System._nodeRequire("url").parse, http = System._nodeRequire(url.startsWith("https:") ? "https" : "http"), opts = Object.assign({ method: payload.method || "GET" }, urlParse(url)); return _context13.abrupt("return", new Promise(function (resolve, reject) { var request = http.request(opts, function (res) { res.setEncoding('utf8'); var data = ""; res.on('data', function (chunk) { return data += chunk; }); res.on('end', function () { return resolve(data); }); res.on('error', function (err) { return reject(err); }); }); request.on('error', function (err) { return reject(err); }); request.end(payload.body); })); case 2: case "end": return _context13.stop(); } } }, _callee13, this); })); function basicRemoteEval_node(_x25, _x26) { return _ref15.apply(this, arguments); } return basicRemoteEval_node; }() }]); return HttpEvalStrategy; }(RemoteEvalStrategy); var L2LEvalStrategy = function (_RemoteEvalStrategy2) { inherits(L2LEvalStrategy, _RemoteEvalStrategy2); function L2LEvalStrategy(l2lClient, targetId) { classCallCheck(this, L2LEvalStrategy); var _this6 = possibleConstructorReturn(this, (L2LEvalStrategy.__proto__ || Object.getPrototypeOf(L2LEvalStrategy)).call(this)); _this6.l2lClient = l2lClient; _this6.targetId = targetId; return _this6; } createClass(L2LEvalStrategy, [{ key: "basicRemoteEval", value: function () { var _ref16 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee14(source, options) { var l2lClient, targetId, _ref17, evalResult; return regeneratorRuntime.wrap(function _callee14$(_context14) { while (1) { switch (_context14.prev = _context14.next) { case 0: l2lClient = this.l2lClient; targetId = this.targetId; _context14.next = 4; return new Promise(function (resolve, reject) { return l2lClient.sendTo(targetId, "remote-eval", { source: source }, resolve); }); case 4: _ref17 = _context14.sent; evalResult = _ref17.data; if (evalResult && evalResult.value && evalResult.value.isEvalResult) evalResult = evalResult.value; return _context14.abrupt("return", evalResult); case 8: case "end": return _context14.stop(); } } }, _callee14, this); })); function basicRemoteEval(_x27, _x28) { return _ref16.apply(this, arguments); } return basicRemoteEval; }() }]); return L2LEvalStrategy; }(RemoteEvalStrategy); var evalStrategies = Object.freeze({ RemoteEvalStrategy: RemoteEvalStrategy, EvalStrategy: EvalStrategy, SimpleEvalStrategy: SimpleEvalStrategy, LivelyVmEvalStrategy: LivelyVmEvalStrategy, HttpEvalStrategy: HttpEvalStrategy, L2LEvalStrategy: L2LEvalStrategy }); function runEval$$1(code, options) { var _options = options = _extends({ format: "esm", System: null, targetModule: null }, options), format = _options.format, S = _options.System, targetModule = _options.targetModule; if (!S && typeof System !== "undefined") S = System; if (!S && targetModule) { return Promise.reject(new Error("options to runEval have targetModule but cannot find system loader!")); } return targetModule && ["esm", "es6", "register"].includes(format) ? runEval$2(S, code, options) : runEval$1(code, options); } function syncEval$$1(code, options) { return syncEval$1(code, options); } exports.completions = completions; exports.runEval = runEval$$1; exports.syncEval = syncEval$$1; exports.evalStrategies = evalStrategies; exports.defaultTopLevelVarRecorderName = defaultTopLevelVarRecorderName; exports.defaultClassToFunctionConverterName = defaultClassToFunctionConverterName; exports.evalCodeTransform = evalCodeTransform; exports.evalCodeTransformOfSystemRegisterSetters = evalCodeTransformOfSystemRegisterSetters; }((this.lively.vm = this.lively.vm || {}),lively.lang,lively.ast,lively.sourceTransform,lively.classes,lively.notifications)); if (typeof module !== "undefined" && module.exports) module.exports = GLOBAL.lively.vm; })();