lively.vm
Version:
Controlled JavaScript code execution and instrumentation.
1,481 lines (1,233 loc) • 66.4 kB
JavaScript
(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 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 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(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(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(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(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(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({