| "no use strict"; |
| ;(function(window) { |
| if (typeof window.window != "undefined" && window.document) |
| return; |
| if (window.require && window.define) |
| return; |
| |
| window.console = function() { |
| var msgs = Array.prototype.slice.call(arguments, 0); |
| postMessage({type: "log", data: msgs}); |
| }; |
| window.console.error = |
| window.console.warn = |
| window.console.log = |
| window.console.trace = window.console; |
| |
| window.window = window; |
| window.ace = window; |
| |
| window.onerror = function(message, file, line, col, err) { |
| postMessage({type: "error", data: { |
| message: message, |
| data: err.data, |
| file: file, |
| line: line, |
| col: col, |
| stack: err.stack |
| }}); |
| }; |
| |
| window.normalizeModule = function(parentId, moduleName) { |
| // normalize plugin requires |
| if (moduleName.indexOf("!") !== -1) { |
| var chunks = moduleName.split("!"); |
| return window.normalizeModule(parentId, chunks[0]) + "!" + window.normalizeModule(parentId, chunks[1]); |
| } |
| // normalize relative requires |
| if (moduleName.charAt(0) == ".") { |
| var base = parentId.split("/").slice(0, -1).join("/"); |
| moduleName = (base ? base + "/" : "") + moduleName; |
| |
| while (moduleName.indexOf(".") !== -1 && previous != moduleName) { |
| var previous = moduleName; |
| moduleName = moduleName.replace(/^\.\//, "").replace(/\/\.\//, "/").replace(/[^\/]+\/\.\.\//, ""); |
| } |
| } |
| |
| return moduleName; |
| }; |
| |
| window.require = function require(parentId, id) { |
| if (!id) { |
| id = parentId; |
| parentId = null; |
| } |
| if (!id.charAt) |
| throw new Error("worker.js require() accepts only (parentId, id) as arguments"); |
| |
| id = window.normalizeModule(parentId, id); |
| |
| var module = window.require.modules[id]; |
| if (module) { |
| if (!module.initialized) { |
| module.initialized = true; |
| module.exports = module.factory().exports; |
| } |
| return module.exports; |
| } |
| |
| if (!window.require.tlns) |
| return console.log("unable to load " + id); |
| |
| var path = resolveModuleId(id, window.require.tlns); |
| if (path.slice(-3) != ".js") path += ".js"; |
| |
| window.require.id = id; |
| window.require.modules[id] = {}; // prevent infinite loop on broken modules |
| importScripts(path); |
| return window.require(parentId, id); |
| }; |
| function resolveModuleId(id, paths) { |
| var testPath = id, tail = ""; |
| while (testPath) { |
| var alias = paths[testPath]; |
| if (typeof alias == "string") { |
| return alias + tail; |
| } else if (alias) { |
| return alias.location.replace(/\/*$/, "/") + (tail || alias.main || alias.name); |
| } else if (alias === false) { |
| return ""; |
| } |
| var i = testPath.lastIndexOf("/"); |
| if (i === -1) break; |
| tail = testPath.substr(i) + tail; |
| testPath = testPath.slice(0, i); |
| } |
| return id; |
| } |
| window.require.modules = {}; |
| window.require.tlns = {}; |
| |
| window.define = function(id, deps, factory) { |
| if (arguments.length == 2) { |
| factory = deps; |
| if (typeof id != "string") { |
| deps = id; |
| id = window.require.id; |
| } |
| } else if (arguments.length == 1) { |
| factory = id; |
| deps = []; |
| id = window.require.id; |
| } |
| |
| if (typeof factory != "function") { |
| window.require.modules[id] = { |
| exports: factory, |
| initialized: true |
| }; |
| return; |
| } |
| |
| if (!deps.length) |
| // If there is no dependencies, we inject "require", "exports" and |
| // "module" as dependencies, to provide CommonJS compatibility. |
| deps = ["require", "exports", "module"]; |
| |
| var req = function(childId) { |
| return window.require(id, childId); |
| }; |
| |
| window.require.modules[id] = { |
| exports: {}, |
| factory: function() { |
| var module = this; |
| var returnExports = factory.apply(this, deps.map(function(dep) { |
| switch (dep) { |
| // Because "require", "exports" and "module" aren't actual |
| // dependencies, we must handle them seperately. |
| case "require": return req; |
| case "exports": return module.exports; |
| case "module": return module; |
| // But for all other dependencies, we can just go ahead and |
| // require them. |
| default: return req(dep); |
| } |
| })); |
| if (returnExports) |
| module.exports = returnExports; |
| return module; |
| } |
| }; |
| }; |
| window.define.amd = {}; |
| require.tlns = {}; |
| window.initBaseUrls = function initBaseUrls(topLevelNamespaces) { |
| for (var i in topLevelNamespaces) |
| require.tlns[i] = topLevelNamespaces[i]; |
| }; |
| |
| window.initSender = function initSender() { |
| |
| var EventEmitter = window.require("ace/lib/event_emitter").EventEmitter; |
| var oop = window.require("ace/lib/oop"); |
| |
| var Sender = function() {}; |
| |
| (function() { |
| |
| oop.implement(this, EventEmitter); |
| |
| this.callback = function(data, callbackId) { |
| postMessage({ |
| type: "call", |
| id: callbackId, |
| data: data |
| }); |
| }; |
| |
| this.emit = function(name, data) { |
| postMessage({ |
| type: "event", |
| name: name, |
| data: data |
| }); |
| }; |
| |
| }).call(Sender.prototype); |
| |
| return new Sender(); |
| }; |
| |
| var main = window.main = null; |
| var sender = window.sender = null; |
| |
| window.onmessage = function(e) { |
| var msg = e.data; |
| if (msg.event && sender) { |
| sender._signal(msg.event, msg.data); |
| } |
| else if (msg.command) { |
| if (main[msg.command]) |
| main[msg.command].apply(main, msg.args); |
| else if (window[msg.command]) |
| window[msg.command].apply(window, msg.args); |
| else |
| throw new Error("Unknown command:" + msg.command); |
| } |
| else if (msg.init) { |
| window.initBaseUrls(msg.tlns); |
| require("ace/lib/es5-shim"); |
| sender = window.sender = window.initSender(); |
| var clazz = require(msg.module)[msg.classname]; |
| main = window.main = new clazz(sender); |
| } |
| }; |
| })(this); |
| |
| define("ace/lib/oop",["require","exports","module"], function(require, exports, module) { |
| "use strict"; |
| |
| exports.inherits = function(ctor, superCtor) { |
| ctor.super_ = superCtor; |
| ctor.prototype = Object.create(superCtor.prototype, { |
| constructor: { |
| value: ctor, |
| enumerable: false, |
| writable: true, |
| configurable: true |
| } |
| }); |
| }; |
| |
| exports.mixin = function(obj, mixin) { |
| for (var key in mixin) { |
| obj[key] = mixin[key]; |
| } |
| return obj; |
| }; |
| |
| exports.implement = function(proto, mixin) { |
| exports.mixin(proto, mixin); |
| }; |
| |
| }); |
| |
| define("ace/range",["require","exports","module"], function(require, exports, module) { |
| "use strict"; |
| var comparePoints = function(p1, p2) { |
| return p1.row - p2.row || p1.column - p2.column; |
| }; |
| var Range = function(startRow, startColumn, endRow, endColumn) { |
| this.start = { |
| row: startRow, |
| column: startColumn |
| }; |
| |
| this.end = { |
| row: endRow, |
| column: endColumn |
| }; |
| }; |
| |
| (function() { |
| this.isEqual = function(range) { |
| return this.start.row === range.start.row && |
| this.end.row === range.end.row && |
| this.start.column === range.start.column && |
| this.end.column === range.end.column; |
| }; |
| this.toString = function() { |
| return ("Range: [" + this.start.row + "/" + this.start.column + |
| "] -> [" + this.end.row + "/" + this.end.column + "]"); |
| }; |
| |
| this.contains = function(row, column) { |
| return this.compare(row, column) == 0; |
| }; |
| this.compareRange = function(range) { |
| var cmp, |
| end = range.end, |
| start = range.start; |
| |
| cmp = this.compare(end.row, end.column); |
| if (cmp == 1) { |
| cmp = this.compare(start.row, start.column); |
| if (cmp == 1) { |
| return 2; |
| } else if (cmp == 0) { |
| return 1; |
| } else { |
| return 0; |
| } |
| } else if (cmp == -1) { |
| return -2; |
| } else { |
| cmp = this.compare(start.row, start.column); |
| if (cmp == -1) { |
| return -1; |
| } else if (cmp == 1) { |
| return 42; |
| } else { |
| return 0; |
| } |
| } |
| }; |
| this.comparePoint = function(p) { |
| return this.compare(p.row, p.column); |
| }; |
| this.containsRange = function(range) { |
| return this.comparePoint(range.start) == 0 && this.comparePoint(range.end) == 0; |
| }; |
| this.intersects = function(range) { |
| var cmp = this.compareRange(range); |
| return (cmp == -1 || cmp == 0 || cmp == 1); |
| }; |
| this.isEnd = function(row, column) { |
| return this.end.row == row && this.end.column == column; |
| }; |
| this.isStart = function(row, column) { |
| return this.start.row == row && this.start.column == column; |
| }; |
| this.setStart = function(row, column) { |
| if (typeof row == "object") { |
| this.start.column = row.column; |
| this.start.row = row.row; |
| } else { |
| this.start.row = row; |
| this.start.column = column; |
| } |
| }; |
| this.setEnd = function(row, column) { |
| if (typeof row == "object") { |
| this.end.column = row.column; |
| this.end.row = row.row; |
| } else { |
| this.end.row = row; |
| this.end.column = column; |
| } |
| }; |
| this.inside = function(row, column) { |
| if (this.compare(row, column) == 0) { |
| if (this.isEnd(row, column) || this.isStart(row, column)) { |
| return false; |
| } else { |
| return true; |
| } |
| } |
| return false; |
| }; |
| this.insideStart = function(row, column) { |
| if (this.compare(row, column) == 0) { |
| if (this.isEnd(row, column)) { |
| return false; |
| } else { |
| return true; |
| } |
| } |
| return false; |
| }; |
| this.insideEnd = function(row, column) { |
| if (this.compare(row, column) == 0) { |
| if (this.isStart(row, column)) { |
| return false; |
| } else { |
| return true; |
| } |
| } |
| return false; |
| }; |
| this.compare = function(row, column) { |
| if (!this.isMultiLine()) { |
| if (row === this.start.row) { |
| return column < this.start.column ? -1 : (column > this.end.column ? 1 : 0); |
| }; |
| } |
| |
| if (row < this.start.row) |
| return -1; |
| |
| if (row > this.end.row) |
| return 1; |
| |
| if (this.start.row === row) |
| return column >= this.start.column ? 0 : -1; |
| |
| if (this.end.row === row) |
| return column <= this.end.column ? 0 : 1; |
| |
| return 0; |
| }; |
| this.compareStart = function(row, column) { |
| if (this.start.row == row && this.start.column == column) { |
| return -1; |
| } else { |
| return this.compare(row, column); |
| } |
| }; |
| this.compareEnd = function(row, column) { |
| if (this.end.row == row && this.end.column == column) { |
| return 1; |
| } else { |
| return this.compare(row, column); |
| } |
| }; |
| this.compareInside = function(row, column) { |
| if (this.end.row == row && this.end.column == column) { |
| return 1; |
| } else if (this.start.row == row && this.start.column == column) { |
| return -1; |
| } else { |
| return this.compare(row, column); |
| } |
| }; |
| this.clipRows = function(firstRow, lastRow) { |
| if (this.end.row > lastRow) |
| var end = {row: lastRow + 1, column: 0}; |
| else if (this.end.row < firstRow) |
| var end = {row: firstRow, column: 0}; |
| |
| if (this.start.row > lastRow) |
| var start = {row: lastRow + 1, column: 0}; |
| else if (this.start.row < firstRow) |
| var start = {row: firstRow, column: 0}; |
| |
| return Range.fromPoints(start || this.start, end || this.end); |
| }; |
| this.extend = function(row, column) { |
| var cmp = this.compare(row, column); |
| |
| if (cmp == 0) |
| return this; |
| else if (cmp == -1) |
| var start = {row: row, column: column}; |
| else |
| var end = {row: row, column: column}; |
| |
| return Range.fromPoints(start || this.start, end || this.end); |
| }; |
| |
| this.isEmpty = function() { |
| return (this.start.row === this.end.row && this.start.column === this.end.column); |
| }; |
| this.isMultiLine = function() { |
| return (this.start.row !== this.end.row); |
| }; |
| this.clone = function() { |
| return Range.fromPoints(this.start, this.end); |
| }; |
| this.collapseRows = function() { |
| if (this.end.column == 0) |
| return new Range(this.start.row, 0, Math.max(this.start.row, this.end.row-1), 0) |
| else |
| return new Range(this.start.row, 0, this.end.row, 0) |
| }; |
| this.toScreenRange = function(session) { |
| var screenPosStart = session.documentToScreenPosition(this.start); |
| var screenPosEnd = session.documentToScreenPosition(this.end); |
| |
| return new Range( |
| screenPosStart.row, screenPosStart.column, |
| screenPosEnd.row, screenPosEnd.column |
| ); |
| }; |
| this.moveBy = function(row, column) { |
| this.start.row += row; |
| this.start.column += column; |
| this.end.row += row; |
| this.end.column += column; |
| }; |
| |
| }).call(Range.prototype); |
| Range.fromPoints = function(start, end) { |
| return new Range(start.row, start.column, end.row, end.column); |
| }; |
| Range.comparePoints = comparePoints; |
| |
| Range.comparePoints = function(p1, p2) { |
| return p1.row - p2.row || p1.column - p2.column; |
| }; |
| |
| |
| exports.Range = Range; |
| }); |
| |
| define("ace/apply_delta",["require","exports","module"], function(require, exports, module) { |
| "use strict"; |
| |
| function throwDeltaError(delta, errorText){ |
| console.log("Invalid Delta:", delta); |
| throw "Invalid Delta: " + errorText; |
| } |
| |
| function positionInDocument(docLines, position) { |
| return position.row >= 0 && position.row < docLines.length && |
| position.column >= 0 && position.column <= docLines[position.row].length; |
| } |
| |
| function validateDelta(docLines, delta) { |
| if (delta.action != "insert" && delta.action != "remove") |
| throwDeltaError(delta, "delta.action must be 'insert' or 'remove'"); |
| if (!(delta.lines instanceof Array)) |
| throwDeltaError(delta, "delta.lines must be an Array"); |
| if (!delta.start || !delta.end) |
| throwDeltaError(delta, "delta.start/end must be an present"); |
| var start = delta.start; |
| if (!positionInDocument(docLines, delta.start)) |
| throwDeltaError(delta, "delta.start must be contained in document"); |
| var end = delta.end; |
| if (delta.action == "remove" && !positionInDocument(docLines, end)) |
| throwDeltaError(delta, "delta.end must contained in document for 'remove' actions"); |
| var numRangeRows = end.row - start.row; |
| var numRangeLastLineChars = (end.column - (numRangeRows == 0 ? start.column : 0)); |
| if (numRangeRows != delta.lines.length - 1 || delta.lines[numRangeRows].length != numRangeLastLineChars) |
| throwDeltaError(delta, "delta.range must match delta lines"); |
| } |
| |
| exports.applyDelta = function(docLines, delta, doNotValidate) { |
| |
| var row = delta.start.row; |
| var startColumn = delta.start.column; |
| var line = docLines[row] || ""; |
| switch (delta.action) { |
| case "insert": |
| var lines = delta.lines; |
| if (lines.length === 1) { |
| docLines[row] = line.substring(0, startColumn) + delta.lines[0] + line.substring(startColumn); |
| } else { |
| var args = [row, 1].concat(delta.lines); |
| docLines.splice.apply(docLines, args); |
| docLines[row] = line.substring(0, startColumn) + docLines[row]; |
| docLines[row + delta.lines.length - 1] += line.substring(startColumn); |
| } |
| break; |
| case "remove": |
| var endColumn = delta.end.column; |
| var endRow = delta.end.row; |
| if (row === endRow) { |
| docLines[row] = line.substring(0, startColumn) + line.substring(endColumn); |
| } else { |
| docLines.splice( |
| row, endRow - row + 1, |
| line.substring(0, startColumn) + docLines[endRow].substring(endColumn) |
| ); |
| } |
| break; |
| } |
| } |
| }); |
| |
| define("ace/lib/event_emitter",["require","exports","module"], function(require, exports, module) { |
| "use strict"; |
| |
| var EventEmitter = {}; |
| var stopPropagation = function() { this.propagationStopped = true; }; |
| var preventDefault = function() { this.defaultPrevented = true; }; |
| |
| EventEmitter._emit = |
| EventEmitter._dispatchEvent = function(eventName, e) { |
| this._eventRegistry || (this._eventRegistry = {}); |
| this._defaultHandlers || (this._defaultHandlers = {}); |
| |
| var listeners = this._eventRegistry[eventName] || []; |
| var defaultHandler = this._defaultHandlers[eventName]; |
| if (!listeners.length && !defaultHandler) |
| return; |
| |
| if (typeof e != "object" || !e) |
| e = {}; |
| |
| if (!e.type) |
| e.type = eventName; |
| if (!e.stopPropagation) |
| e.stopPropagation = stopPropagation; |
| if (!e.preventDefault) |
| e.preventDefault = preventDefault; |
| |
| listeners = listeners.slice(); |
| for (var i=0; i<listeners.length; i++) { |
| listeners[i](e, this); |
| if (e.propagationStopped) |
| break; |
| } |
| |
| if (defaultHandler && !e.defaultPrevented) |
| return defaultHandler(e, this); |
| }; |
| |
| |
| EventEmitter._signal = function(eventName, e) { |
| var listeners = (this._eventRegistry || {})[eventName]; |
| if (!listeners) |
| return; |
| listeners = listeners.slice(); |
| for (var i=0; i<listeners.length; i++) |
| listeners[i](e, this); |
| }; |
| |
| EventEmitter.once = function(eventName, callback) { |
| var _self = this; |
| callback && this.addEventListener(eventName, function newCallback() { |
| _self.removeEventListener(eventName, newCallback); |
| callback.apply(null, arguments); |
| }); |
| }; |
| |
| |
| EventEmitter.setDefaultHandler = function(eventName, callback) { |
| var handlers = this._defaultHandlers |
| if (!handlers) |
| handlers = this._defaultHandlers = {_disabled_: {}}; |
| |
| if (handlers[eventName]) { |
| var old = handlers[eventName]; |
| var disabled = handlers._disabled_[eventName]; |
| if (!disabled) |
| handlers._disabled_[eventName] = disabled = []; |
| disabled.push(old); |
| var i = disabled.indexOf(callback); |
| if (i != -1) |
| disabled.splice(i, 1); |
| } |
| handlers[eventName] = callback; |
| }; |
| EventEmitter.removeDefaultHandler = function(eventName, callback) { |
| var handlers = this._defaultHandlers |
| if (!handlers) |
| return; |
| var disabled = handlers._disabled_[eventName]; |
| |
| if (handlers[eventName] == callback) { |
| var old = handlers[eventName]; |
| if (disabled) |
| this.setDefaultHandler(eventName, disabled.pop()); |
| } else if (disabled) { |
| var i = disabled.indexOf(callback); |
| if (i != -1) |
| disabled.splice(i, 1); |
| } |
| }; |
| |
| EventEmitter.on = |
| EventEmitter.addEventListener = function(eventName, callback, capturing) { |
| this._eventRegistry = this._eventRegistry || {}; |
| |
| var listeners = this._eventRegistry[eventName]; |
| if (!listeners) |
| listeners = this._eventRegistry[eventName] = []; |
| |
| if (listeners.indexOf(callback) == -1) |
| listeners[capturing ? "unshift" : "push"](callback); |
| return callback; |
| }; |
| |
| EventEmitter.off = |
| EventEmitter.removeListener = |
| EventEmitter.removeEventListener = function(eventName, callback) { |
| this._eventRegistry = this._eventRegistry || {}; |
| |
| var listeners = this._eventRegistry[eventName]; |
| if (!listeners) |
| return; |
| |
| var index = listeners.indexOf(callback); |
| if (index !== -1) |
| listeners.splice(index, 1); |
| }; |
| |
| EventEmitter.removeAllListeners = function(eventName) { |
| if (this._eventRegistry) this._eventRegistry[eventName] = []; |
| }; |
| |
| exports.EventEmitter = EventEmitter; |
| |
| }); |
| |
| define("ace/anchor",["require","exports","module","ace/lib/oop","ace/lib/event_emitter"], function(require, exports, module) { |
| "use strict"; |
| |
| var oop = require("./lib/oop"); |
| var EventEmitter = require("./lib/event_emitter").EventEmitter; |
| |
| var Anchor = exports.Anchor = function(doc, row, column) { |
| this.$onChange = this.onChange.bind(this); |
| this.attach(doc); |
| |
| if (typeof column == "undefined") |
| this.setPosition(row.row, row.column); |
| else |
| this.setPosition(row, column); |
| }; |
| |
| (function() { |
| |
| oop.implement(this, EventEmitter); |
| this.getPosition = function() { |
| return this.$clipPositionToDocument(this.row, this.column); |
| }; |
| this.getDocument = function() { |
| return this.document; |
| }; |
| this.$insertRight = false; |
| this.onChange = function(delta) { |
| if (delta.start.row == delta.end.row && delta.start.row != this.row) |
| return; |
| |
| if (delta.start.row > this.row) |
| return; |
| |
| var point = $getTransformedPoint(delta, {row: this.row, column: this.column}, this.$insertRight); |
| this.setPosition(point.row, point.column, true); |
| }; |
| |
| function $pointsInOrder(point1, point2, equalPointsInOrder) { |
| var bColIsAfter = equalPointsInOrder ? point1.column <= point2.column : point1.column < point2.column; |
| return (point1.row < point2.row) || (point1.row == point2.row && bColIsAfter); |
| } |
| |
| function $getTransformedPoint(delta, point, moveIfEqual) { |
| var deltaIsInsert = delta.action == "insert"; |
| var deltaRowShift = (deltaIsInsert ? 1 : -1) * (delta.end.row - delta.start.row); |
| var deltaColShift = (deltaIsInsert ? 1 : -1) * (delta.end.column - delta.start.column); |
| var deltaStart = delta.start; |
| var deltaEnd = deltaIsInsert ? deltaStart : delta.end; // Collapse insert range. |
| if ($pointsInOrder(point, deltaStart, moveIfEqual)) { |
| return { |
| row: point.row, |
| column: point.column |
| }; |
| } |
| if ($pointsInOrder(deltaEnd, point, !moveIfEqual)) { |
| return { |
| row: point.row + deltaRowShift, |
| column: point.column + (point.row == deltaEnd.row ? deltaColShift : 0) |
| }; |
| } |
| |
| return { |
| row: deltaStart.row, |
| column: deltaStart.column |
| }; |
| } |
| this.setPosition = function(row, column, noClip) { |
| var pos; |
| if (noClip) { |
| pos = { |
| row: row, |
| column: column |
| }; |
| } else { |
| pos = this.$clipPositionToDocument(row, column); |
| } |
| |
| if (this.row == pos.row && this.column == pos.column) |
| return; |
| |
| var old = { |
| row: this.row, |
| column: this.column |
| }; |
| |
| this.row = pos.row; |
| this.column = pos.column; |
| this._signal("change", { |
| old: old, |
| value: pos |
| }); |
| }; |
| this.detach = function() { |
| this.document.removeEventListener("change", this.$onChange); |
| }; |
| this.attach = function(doc) { |
| this.document = doc || this.document; |
| this.document.on("change", this.$onChange); |
| }; |
| this.$clipPositionToDocument = function(row, column) { |
| var pos = {}; |
| |
| if (row >= this.document.getLength()) { |
| pos.row = Math.max(0, this.document.getLength() - 1); |
| pos.column = this.document.getLine(pos.row).length; |
| } |
| else if (row < 0) { |
| pos.row = 0; |
| pos.column = 0; |
| } |
| else { |
| pos.row = row; |
| pos.column = Math.min(this.document.getLine(pos.row).length, Math.max(0, column)); |
| } |
| |
| if (column < 0) |
| pos.column = 0; |
| |
| return pos; |
| }; |
| |
| }).call(Anchor.prototype); |
| |
| }); |
| |
| define("ace/document",["require","exports","module","ace/lib/oop","ace/apply_delta","ace/lib/event_emitter","ace/range","ace/anchor"], function(require, exports, module) { |
| "use strict"; |
| |
| var oop = require("./lib/oop"); |
| var applyDelta = require("./apply_delta").applyDelta; |
| var EventEmitter = require("./lib/event_emitter").EventEmitter; |
| var Range = require("./range").Range; |
| var Anchor = require("./anchor").Anchor; |
| |
| var Document = function(textOrLines) { |
| this.$lines = [""]; |
| if (textOrLines.length === 0) { |
| this.$lines = [""]; |
| } else if (Array.isArray(textOrLines)) { |
| this.insertMergedLines({row: 0, column: 0}, textOrLines); |
| } else { |
| this.insert({row: 0, column:0}, textOrLines); |
| } |
| }; |
| |
| (function() { |
| |
| oop.implement(this, EventEmitter); |
| this.setValue = function(text) { |
| var len = this.getLength() - 1; |
| this.remove(new Range(0, 0, len, this.getLine(len).length)); |
| this.insert({row: 0, column: 0}, text); |
| }; |
| this.getValue = function() { |
| return this.getAllLines().join(this.getNewLineCharacter()); |
| }; |
| this.createAnchor = function(row, column) { |
| return new Anchor(this, row, column); |
| }; |
| if ("aaa".split(/a/).length === 0) { |
| this.$split = function(text) { |
| return text.replace(/\r\n|\r/g, "\n").split("\n"); |
| }; |
| } else { |
| this.$split = function(text) { |
| return text.split(/\r\n|\r|\n/); |
| }; |
| } |
| |
| |
| this.$detectNewLine = function(text) { |
| var match = text.match(/^.*?(\r\n|\r|\n)/m); |
| this.$autoNewLine = match ? match[1] : "\n"; |
| this._signal("changeNewLineMode"); |
| }; |
| this.getNewLineCharacter = function() { |
| switch (this.$newLineMode) { |
| case "windows": |
| return "\r\n"; |
| case "unix": |
| return "\n"; |
| default: |
| return this.$autoNewLine || "\n"; |
| } |
| }; |
| |
| this.$autoNewLine = ""; |
| this.$newLineMode = "auto"; |
| this.setNewLineMode = function(newLineMode) { |
| if (this.$newLineMode === newLineMode) |
| return; |
| |
| this.$newLineMode = newLineMode; |
| this._signal("changeNewLineMode"); |
| }; |
| this.getNewLineMode = function() { |
| return this.$newLineMode; |
| }; |
| this.isNewLine = function(text) { |
| return (text == "\r\n" || text == "\r" || text == "\n"); |
| }; |
| this.getLine = function(row) { |
| return this.$lines[row] || ""; |
| }; |
| this.getLines = function(firstRow, lastRow) { |
| return this.$lines.slice(firstRow, lastRow + 1); |
| }; |
| this.getAllLines = function() { |
| return this.getLines(0, this.getLength()); |
| }; |
| this.getLength = function() { |
| return this.$lines.length; |
| }; |
| this.getTextRange = function(range) { |
| return this.getLinesForRange(range).join(this.getNewLineCharacter()); |
| }; |
| this.getLinesForRange = function(range) { |
| var lines; |
| if (range.start.row === range.end.row) { |
| lines = [this.getLine(range.start.row).substring(range.start.column, range.end.column)]; |
| } else { |
| lines = this.getLines(range.start.row, range.end.row); |
| lines[0] = (lines[0] || "").substring(range.start.column); |
| var l = lines.length - 1; |
| if (range.end.row - range.start.row == l) |
| lines[l] = lines[l].substring(0, range.end.column); |
| } |
| return lines; |
| }; |
| this.insertLines = function(row, lines) { |
| console.warn("Use of document.insertLines is deprecated. Use the insertFullLines method instead."); |
| return this.insertFullLines(row, lines); |
| }; |
| this.removeLines = function(firstRow, lastRow) { |
| console.warn("Use of document.removeLines is deprecated. Use the removeFullLines method instead."); |
| return this.removeFullLines(firstRow, lastRow); |
| }; |
| this.insertNewLine = function(position) { |
| console.warn("Use of document.insertNewLine is deprecated. Use insertMergedLines(position, [\'\', \'\']) instead."); |
| return this.insertMergedLines(position, ["", ""]); |
| }; |
| this.insert = function(position, text) { |
| if (this.getLength() <= 1) |
| this.$detectNewLine(text); |
| |
| return this.insertMergedLines(position, this.$split(text)); |
| }; |
| this.insertInLine = function(position, text) { |
| var start = this.clippedPos(position.row, position.column); |
| var end = this.pos(position.row, position.column + text.length); |
| |
| this.applyDelta({ |
| start: start, |
| end: end, |
| action: "insert", |
| lines: [text] |
| }, true); |
| |
| return this.clonePos(end); |
| }; |
| |
| this.clippedPos = function(row, column) { |
| var length = this.getLength(); |
| if (row === undefined) { |
| row = length; |
| } else if (row < 0) { |
| row = 0; |
| } else if (row >= length) { |
| row = length - 1; |
| column = undefined; |
| } |
| var line = this.getLine(row); |
| if (column == undefined) |
| column = line.length; |
| column = Math.min(Math.max(column, 0), line.length); |
| return {row: row, column: column}; |
| }; |
| |
| this.clonePos = function(pos) { |
| return {row: pos.row, column: pos.column}; |
| }; |
| |
| this.pos = function(row, column) { |
| return {row: row, column: column}; |
| }; |
| |
| this.$clipPosition = function(position) { |
| var length = this.getLength(); |
| if (position.row >= length) { |
| position.row = Math.max(0, length - 1); |
| position.column = this.getLine(length - 1).length; |
| } else { |
| position.row = Math.max(0, position.row); |
| position.column = Math.min(Math.max(position.column, 0), this.getLine(position.row).length); |
| } |
| return position; |
| }; |
| this.insertFullLines = function(row, lines) { |
| row = Math.min(Math.max(row, 0), this.getLength()); |
| var column = 0; |
| if (row < this.getLength()) { |
| lines = lines.concat([""]); |
| column = 0; |
| } else { |
| lines = [""].concat(lines); |
| row--; |
| column = this.$lines[row].length; |
| } |
| this.insertMergedLines({row: row, column: column}, lines); |
| }; |
| this.insertMergedLines = function(position, lines) { |
| var start = this.clippedPos(position.row, position.column); |
| var end = { |
| row: start.row + lines.length - 1, |
| column: (lines.length == 1 ? start.column : 0) + lines[lines.length - 1].length |
| }; |
| |
| this.applyDelta({ |
| start: start, |
| end: end, |
| action: "insert", |
| lines: lines |
| }); |
| |
| return this.clonePos(end); |
| }; |
| this.remove = function(range) { |
| var start = this.clippedPos(range.start.row, range.start.column); |
| var end = this.clippedPos(range.end.row, range.end.column); |
| this.applyDelta({ |
| start: start, |
| end: end, |
| action: "remove", |
| lines: this.getLinesForRange({start: start, end: end}) |
| }); |
| return this.clonePos(start); |
| }; |
| this.removeInLine = function(row, startColumn, endColumn) { |
| var start = this.clippedPos(row, startColumn); |
| var end = this.clippedPos(row, endColumn); |
| |
| this.applyDelta({ |
| start: start, |
| end: end, |
| action: "remove", |
| lines: this.getLinesForRange({start: start, end: end}) |
| }, true); |
| |
| return this.clonePos(start); |
| }; |
| this.removeFullLines = function(firstRow, lastRow) { |
| firstRow = Math.min(Math.max(0, firstRow), this.getLength() - 1); |
| lastRow = Math.min(Math.max(0, lastRow ), this.getLength() - 1); |
| var deleteFirstNewLine = lastRow == this.getLength() - 1 && firstRow > 0; |
| var deleteLastNewLine = lastRow < this.getLength() - 1; |
| var startRow = ( deleteFirstNewLine ? firstRow - 1 : firstRow ); |
| var startCol = ( deleteFirstNewLine ? this.getLine(startRow).length : 0 ); |
| var endRow = ( deleteLastNewLine ? lastRow + 1 : lastRow ); |
| var endCol = ( deleteLastNewLine ? 0 : this.getLine(endRow).length ); |
| var range = new Range(startRow, startCol, endRow, endCol); |
| var deletedLines = this.$lines.slice(firstRow, lastRow + 1); |
| |
| this.applyDelta({ |
| start: range.start, |
| end: range.end, |
| action: "remove", |
| lines: this.getLinesForRange(range) |
| }); |
| return deletedLines; |
| }; |
| this.removeNewLine = function(row) { |
| if (row < this.getLength() - 1 && row >= 0) { |
| this.applyDelta({ |
| start: this.pos(row, this.getLine(row).length), |
| end: this.pos(row + 1, 0), |
| action: "remove", |
| lines: ["", ""] |
| }); |
| } |
| }; |
| this.replace = function(range, text) { |
| if (!range instanceof Range) |
| range = Range.fromPoints(range.start, range.end); |
| if (text.length === 0 && range.isEmpty()) |
| return range.start; |
| if (text == this.getTextRange(range)) |
| return range.end; |
| |
| this.remove(range); |
| var end; |
| if (text) { |
| end = this.insert(range.start, text); |
| } |
| else { |
| end = range.start; |
| } |
| |
| return end; |
| }; |
| this.applyDeltas = function(deltas) { |
| for (var i=0; i<deltas.length; i++) { |
| this.applyDelta(deltas[i]); |
| } |
| }; |
| this.revertDeltas = function(deltas) { |
| for (var i=deltas.length-1; i>=0; i--) { |
| this.revertDelta(deltas[i]); |
| } |
| }; |
| this.applyDelta = function(delta, doNotValidate) { |
| var isInsert = delta.action == "insert"; |
| if (isInsert ? delta.lines.length <= 1 && !delta.lines[0] |
| : !Range.comparePoints(delta.start, delta.end)) { |
| return; |
| } |
| |
| if (isInsert && delta.lines.length > 20000) |
| this.$splitAndapplyLargeDelta(delta, 20000); |
| applyDelta(this.$lines, delta, doNotValidate); |
| this._signal("change", delta); |
| }; |
| |
| this.$splitAndapplyLargeDelta = function(delta, MAX) { |
| var lines = delta.lines; |
| var l = lines.length; |
| var row = delta.start.row; |
| var column = delta.start.column; |
| var from = 0, to = 0; |
| do { |
| from = to; |
| to += MAX - 1; |
| var chunk = lines.slice(from, to); |
| if (to > l) { |
| delta.lines = chunk; |
| delta.start.row = row + from; |
| delta.start.column = column; |
| break; |
| } |
| chunk.push(""); |
| this.applyDelta({ |
| start: this.pos(row + from, column), |
| end: this.pos(row + to, column = 0), |
| action: delta.action, |
| lines: chunk |
| }, true); |
| } while(true); |
| }; |
| this.revertDelta = function(delta) { |
| this.applyDelta({ |
| start: this.clonePos(delta.start), |
| end: this.clonePos(delta.end), |
| action: (delta.action == "insert" ? "remove" : "insert"), |
| lines: delta.lines.slice() |
| }); |
| }; |
| this.indexToPosition = function(index, startRow) { |
| var lines = this.$lines || this.getAllLines(); |
| var newlineLength = this.getNewLineCharacter().length; |
| for (var i = startRow || 0, l = lines.length; i < l; i++) { |
| index -= lines[i].length + newlineLength; |
| if (index < 0) |
| return {row: i, column: index + lines[i].length + newlineLength}; |
| } |
| return {row: l-1, column: lines[l-1].length}; |
| }; |
| this.positionToIndex = function(pos, startRow) { |
| var lines = this.$lines || this.getAllLines(); |
| var newlineLength = this.getNewLineCharacter().length; |
| var index = 0; |
| var row = Math.min(pos.row, lines.length); |
| for (var i = startRow || 0; i < row; ++i) |
| index += lines[i].length + newlineLength; |
| |
| return index + pos.column; |
| }; |
| |
| }).call(Document.prototype); |
| |
| exports.Document = Document; |
| }); |
| |
| define("ace/lib/lang",["require","exports","module"], function(require, exports, module) { |
| "use strict"; |
| |
| exports.last = function(a) { |
| return a[a.length - 1]; |
| }; |
| |
| exports.stringReverse = function(string) { |
| return string.split("").reverse().join(""); |
| }; |
| |
| exports.stringRepeat = function (string, count) { |
| var result = ''; |
| while (count > 0) { |
| if (count & 1) |
| result += string; |
| |
| if (count >>= 1) |
| string += string; |
| } |
| return result; |
| }; |
| |
| var trimBeginRegexp = /^\s\s*/; |
| var trimEndRegexp = /\s\s*$/; |
| |
| exports.stringTrimLeft = function (string) { |
| return string.replace(trimBeginRegexp, ''); |
| }; |
| |
| exports.stringTrimRight = function (string) { |
| return string.replace(trimEndRegexp, ''); |
| }; |
| |
| exports.copyObject = function(obj) { |
| var copy = {}; |
| for (var key in obj) { |
| copy[key] = obj[key]; |
| } |
| return copy; |
| }; |
| |
| exports.copyArray = function(array){ |
| var copy = []; |
| for (var i=0, l=array.length; i<l; i++) { |
| if (array[i] && typeof array[i] == "object") |
| copy[i] = this.copyObject( array[i] ); |
| else |
| copy[i] = array[i]; |
| } |
| return copy; |
| }; |
| |
| exports.deepCopy = function deepCopy(obj) { |
| if (typeof obj !== "object" || !obj) |
| return obj; |
| var copy; |
| if (Array.isArray(obj)) { |
| copy = []; |
| for (var key = 0; key < obj.length; key++) { |
| copy[key] = deepCopy(obj[key]); |
| } |
| return copy; |
| } |
| var cons = obj.constructor; |
| if (cons === RegExp) |
| return obj; |
| |
| copy = cons(); |
| for (var key in obj) { |
| copy[key] = deepCopy(obj[key]); |
| } |
| return copy; |
| }; |
| |
| exports.arrayToMap = function(arr) { |
| var map = {}; |
| for (var i=0; i<arr.length; i++) { |
| map[arr[i]] = 1; |
| } |
| return map; |
| |
| }; |
| |
| exports.createMap = function(props) { |
| var map = Object.create(null); |
| for (var i in props) { |
| map[i] = props[i]; |
| } |
| return map; |
| }; |
| exports.arrayRemove = function(array, value) { |
| for (var i = 0; i <= array.length; i++) { |
| if (value === array[i]) { |
| array.splice(i, 1); |
| } |
| } |
| }; |
| |
| exports.escapeRegExp = function(str) { |
| return str.replace(/([.*+?^${}()|[\]\/\\])/g, '\\$1'); |
| }; |
| |
| exports.escapeHTML = function(str) { |
| return str.replace(/&/g, "&").replace(/"/g, """).replace(/'/g, "'").replace(/</g, "<"); |
| }; |
| |
| exports.getMatchOffsets = function(string, regExp) { |
| var matches = []; |
| |
| string.replace(regExp, function(str) { |
| matches.push({ |
| offset: arguments[arguments.length-2], |
| length: str.length |
| }); |
| }); |
| |
| return matches; |
| }; |
| exports.deferredCall = function(fcn) { |
| var timer = null; |
| var callback = function() { |
| timer = null; |
| fcn(); |
| }; |
| |
| var deferred = function(timeout) { |
| deferred.cancel(); |
| timer = setTimeout(callback, timeout || 0); |
| return deferred; |
| }; |
| |
| deferred.schedule = deferred; |
| |
| deferred.call = function() { |
| this.cancel(); |
| fcn(); |
| return deferred; |
| }; |
| |
| deferred.cancel = function() { |
| clearTimeout(timer); |
| timer = null; |
| return deferred; |
| }; |
| |
| deferred.isPending = function() { |
| return timer; |
| }; |
| |
| return deferred; |
| }; |
| |
| |
| exports.delayedCall = function(fcn, defaultTimeout) { |
| var timer = null; |
| var callback = function() { |
| timer = null; |
| fcn(); |
| }; |
| |
| var _self = function(timeout) { |
| if (timer == null) |
| timer = setTimeout(callback, timeout || defaultTimeout); |
| }; |
| |
| _self.delay = function(timeout) { |
| timer && clearTimeout(timer); |
| timer = setTimeout(callback, timeout || defaultTimeout); |
| }; |
| _self.schedule = _self; |
| |
| _self.call = function() { |
| this.cancel(); |
| fcn(); |
| }; |
| |
| _self.cancel = function() { |
| timer && clearTimeout(timer); |
| timer = null; |
| }; |
| |
| _self.isPending = function() { |
| return timer; |
| }; |
| |
| return _self; |
| }; |
| }); |
| |
| define("ace/worker/mirror",["require","exports","module","ace/range","ace/document","ace/lib/lang"], function(require, exports, module) { |
| "use strict"; |
| |
| var Range = require("../range").Range; |
| var Document = require("../document").Document; |
| var lang = require("../lib/lang"); |
| |
| var Mirror = exports.Mirror = function(sender) { |
| this.sender = sender; |
| var doc = this.doc = new Document(""); |
| |
| var deferredUpdate = this.deferredUpdate = lang.delayedCall(this.onUpdate.bind(this)); |
| |
| var _self = this; |
| sender.on("change", function(e) { |
| var data = e.data; |
| if (data[0].start) { |
| doc.applyDeltas(data); |
| } else { |
| for (var i = 0; i < data.length; i += 2) { |
| if (Array.isArray(data[i+1])) { |
| var d = {action: "insert", start: data[i], lines: data[i+1]}; |
| } else { |
| var d = {action: "remove", start: data[i], end: data[i+1]}; |
| } |
| doc.applyDelta(d, true); |
| } |
| } |
| if (_self.$timeout) |
| return deferredUpdate.schedule(_self.$timeout); |
| _self.onUpdate(); |
| }); |
| }; |
| |
| (function() { |
| |
| this.$timeout = 500; |
| |
| this.setTimeout = function(timeout) { |
| this.$timeout = timeout; |
| }; |
| |
| this.setValue = function(value) { |
| this.doc.setValue(value); |
| this.deferredUpdate.schedule(this.$timeout); |
| }; |
| |
| this.getValue = function(callbackId) { |
| this.sender.callback(this.doc.getValue(), callbackId); |
| }; |
| |
| this.onUpdate = function() { |
| }; |
| |
| this.isPending = function() { |
| return this.deferredUpdate.isPending(); |
| }; |
| |
| }).call(Mirror.prototype); |
| |
| }); |
| |
| define("ace/mode/lua/luaparse",["require","exports","module"], function(require, exports, module) { |
| |
| (function (root, name, factory) { |
| factory(exports) |
| }(this, 'luaparse', function (exports) { |
| 'use strict'; |
| |
| exports.version = '0.1.4'; |
| |
| var input, options, length; |
| var defaultOptions = exports.defaultOptions = { |
| wait: false |
| , comments: true |
| , scope: false |
| , locations: false |
| , ranges: false |
| }; |
| |
| var EOF = 1, StringLiteral = 2, Keyword = 4, Identifier = 8 |
| , NumericLiteral = 16, Punctuator = 32, BooleanLiteral = 64 |
| , NilLiteral = 128, VarargLiteral = 256; |
| |
| exports.tokenTypes = { EOF: EOF, StringLiteral: StringLiteral |
| , Keyword: Keyword, Identifier: Identifier, NumericLiteral: NumericLiteral |
| , Punctuator: Punctuator, BooleanLiteral: BooleanLiteral |
| , NilLiteral: NilLiteral, VarargLiteral: VarargLiteral |
| }; |
| |
| var errors = exports.errors = { |
| unexpected: 'Unexpected %1 \'%2\' near \'%3\'' |
| , expected: '\'%1\' expected near \'%2\'' |
| , expectedToken: '%1 expected near \'%2\'' |
| , unfinishedString: 'unfinished string near \'%1\'' |
| , malformedNumber: 'malformed number near \'%1\'' |
| }; |
| |
| var ast = exports.ast = { |
| labelStatement: function(label) { |
| return { |
| type: 'LabelStatement' |
| , label: label |
| }; |
| } |
| |
| , breakStatement: function() { |
| return { |
| type: 'BreakStatement' |
| }; |
| } |
| |
| , gotoStatement: function(label) { |
| return { |
| type: 'GotoStatement' |
| , label: label |
| }; |
| } |
| |
| , returnStatement: function(args) { |
| return { |
| type: 'ReturnStatement' |
| , 'arguments': args |
| }; |
| } |
| |
| , ifStatement: function(clauses) { |
| return { |
| type: 'IfStatement' |
| , clauses: clauses |
| }; |
| } |
| , ifClause: function(condition, body) { |
| return { |
| type: 'IfClause' |
| , condition: condition |
| , body: body |
| }; |
| } |
| , elseifClause: function(condition, body) { |
| return { |
| type: 'ElseifClause' |
| , condition: condition |
| , body: body |
| }; |
| } |
| , elseClause: function(body) { |
| return { |
| type: 'ElseClause' |
| , body: body |
| }; |
| } |
| |
| , whileStatement: function(condition, body) { |
| return { |
| type: 'WhileStatement' |
| , condition: condition |
| , body: body |
| }; |
| } |
| |
| , doStatement: function(body) { |
| return { |
| type: 'DoStatement' |
| , body: body |
| }; |
| } |
| |
| , repeatStatement: function(condition, body) { |
| return { |
| type: 'RepeatStatement' |
| , condition: condition |
| , body: body |
| }; |
| } |
| |
| , localStatement: function(variables, init) { |
| return { |
| type: 'LocalStatement' |
| , variables: variables |
| , init: init |
| }; |
| } |
| |
| , assignmentStatement: function(variables, init) { |
| return { |
| type: 'AssignmentStatement' |
| , variables: variables |
| , init: init |
| }; |
| } |
| |
| , callStatement: function(expression) { |
| return { |
| type: 'CallStatement' |
| , expression: expression |
| }; |
| } |
| |
| , functionStatement: function(identifier, parameters, isLocal, body) { |
| return { |
| type: 'FunctionDeclaration' |
| , identifier: identifier |
| , isLocal: isLocal |
| , parameters: parameters |
| , body: body |
| }; |
| } |
| |
| , forNumericStatement: function(variable, start, end, step, body) { |
| return { |
| type: 'ForNumericStatement' |
| , variable: variable |
| , start: start |
| , end: end |
| , step: step |
| , body: body |
| }; |
| } |
| |
| , forGenericStatement: function(variables, iterators, body) { |
| return { |
| type: 'ForGenericStatement' |
| , variables: variables |
| , iterators: iterators |
| , body: body |
| }; |
| } |
| |
| , chunk: function(body) { |
| return { |
| type: 'Chunk' |
| , body: body |
| }; |
| } |
| |
| , identifier: function(name) { |
| return { |
| type: 'Identifier' |
| , name: name |
| }; |
| } |
| |
| , literal: function(type, value, raw) { |
| type = (type === StringLiteral) ? 'StringLiteral' |
| : (type === NumericLiteral) ? 'NumericLiteral' |
| : (type === BooleanLiteral) ? 'BooleanLiteral' |
| : (type === NilLiteral) ? 'NilLiteral' |
| : 'VarargLiteral'; |
| |
| return { |
| type: type |
| , value: value |
| , raw: raw |
| }; |
| } |
| |
| , tableKey: function(key, value) { |
| return { |
| type: 'TableKey' |
| , key: key |
| , value: value |
| }; |
| } |
| , tableKeyString: function(key, value) { |
| return { |
| type: 'TableKeyString' |
| , key: key |
| , value: value |
| }; |
| } |
| , tableValue: function(value) { |
| return { |
| type: 'TableValue' |
| , value: value |
| }; |
| } |
| |
| |
| , tableConstructorExpression: function(fields) { |
| return { |
| type: 'TableConstructorExpression' |
| , fields: fields |
| }; |
| } |
| , binaryExpression: function(operator, left, right) { |
| var type = ('and' === operator || 'or' === operator) ? |
| 'LogicalExpression' : |
| 'BinaryExpression'; |
| |
| return { |
| type: type |
| , operator: operator |
| , left: left |
| , right: right |
| }; |
| } |
| , unaryExpression: function(operator, argument) { |
| return { |
| type: 'UnaryExpression' |
| , operator: operator |
| , argument: argument |
| }; |
| } |
| , memberExpression: function(base, indexer, identifier) { |
| return { |
| type: 'MemberExpression' |
| , indexer: indexer |
| , identifier: identifier |
| , base: base |
| }; |
| } |
| |
| , indexExpression: function(base, index) { |
| return { |
| type: 'IndexExpression' |
| , base: base |
| , index: index |
| }; |
| } |
| |
| , callExpression: function(base, args) { |
| return { |
| type: 'CallExpression' |
| , base: base |
| , 'arguments': args |
| }; |
| } |
| |
| , tableCallExpression: function(base, args) { |
| return { |
| type: 'TableCallExpression' |
| , base: base |
| , 'arguments': args |
| }; |
| } |
| |
| , stringCallExpression: function(base, argument) { |
| return { |
| type: 'StringCallExpression' |
| , base: base |
| , argument: argument |
| }; |
| } |
| |
| , comment: function(value, raw) { |
| return { |
| type: 'Comment' |
| , value: value |
| , raw: raw |
| }; |
| } |
| }; |
| |
| function finishNode(node) { |
| if (trackLocations) { |
| var location = locations.pop(); |
| location.complete(); |
| if (options.locations) node.loc = location.loc; |
| if (options.ranges) node.range = location.range; |
| } |
| return node; |
| } |
| |
| var slice = Array.prototype.slice |
| , toString = Object.prototype.toString |
| , indexOf = function indexOf(array, element) { |
| for (var i = 0, length = array.length; i < length; i++) { |
| if (array[i] === element) return i; |
| } |
| return -1; |
| }; |
| |
| function indexOfObject(array, property, element) { |
| for (var i = 0, length = array.length; i < length; i++) { |
| if (array[i][property] === element) return i; |
| } |
| return -1; |
| } |
| |
| function sprintf(format) { |
| var args = slice.call(arguments, 1); |
| format = format.replace(/%(\d)/g, function (match, index) { |
| return '' + args[index - 1] || ''; |
| }); |
| return format; |
| } |
| |
| function extend() { |
| var args = slice.call(arguments) |
| , dest = {} |
| , src, prop; |
| |
| for (var i = 0, length = args.length; i < length; i++) { |
| src = args[i]; |
| for (prop in src) if (src.hasOwnProperty(prop)) { |
| dest[prop] = src[prop]; |
| } |
| } |
| return dest; |
| } |
| |
| function raise(token) { |
| var message = sprintf.apply(null, slice.call(arguments, 1)) |
| , error, col; |
| |
| if ('undefined' !== typeof token.line) { |
| col = token.range[0] - token.lineStart; |
| error = new SyntaxError(sprintf('[%1:%2] %3', token.line, col, message)); |
| error.line = token.line; |
| error.index = token.range[0]; |
| error.column = col; |
| } else { |
| col = index - lineStart + 1; |
| error = new SyntaxError(sprintf('[%1:%2] %3', line, col, message)); |
| error.index = index; |
| error.line = line; |
| error.column = col; |
| } |
| throw error; |
| } |
| |
| function raiseUnexpectedToken(type, token) { |
| raise(token, errors.expectedToken, type, token.value); |
| } |
| |
| function unexpected(found, near) { |
| if ('undefined' === typeof near) near = lookahead.value; |
| if ('undefined' !== typeof found.type) { |
| var type; |
| switch (found.type) { |
| case StringLiteral: type = 'string'; break; |
| case Keyword: type = 'keyword'; break; |
| case Identifier: type = 'identifier'; break; |
| case NumericLiteral: type = 'number'; break; |
| case Punctuator: type = 'symbol'; break; |
| case BooleanLiteral: type = 'boolean'; break; |
| case NilLiteral: |
| return raise(found, errors.unexpected, 'symbol', 'nil', near); |
| } |
| return raise(found, errors.unexpected, type, found.value, near); |
| } |
| return raise(found, errors.unexpected, 'symbol', found, near); |
| } |
| |
| var index |
| , token |
| , previousToken |
| , lookahead |
| , comments |
| , tokenStart |
| , line |
| , lineStart; |
| |
| exports.lex = lex; |
| |
| function lex() { |
| skipWhiteSpace(); |
| while (45 === input.charCodeAt(index) && |
| 45 === input.charCodeAt(index + 1)) { |
| scanComment(); |
| skipWhiteSpace(); |
| } |
| if (index >= length) return { |
| type : EOF |
| , value: '<eof>' |
| , line: line |
| , lineStart: lineStart |
| , range: [index, index] |
| }; |
| |
| var charCode = input.charCodeAt(index) |
| , next = input.charCodeAt(index + 1); |
| tokenStart = index; |
| if (isIdentifierStart(charCode)) return scanIdentifierOrKeyword(); |
| |
| switch (charCode) { |
| case 39: case 34: // '" |
| return scanStringLiteral(); |
| case 48: case 49: case 50: case 51: case 52: case 53: |
| case 54: case 55: case 56: case 57: |
| return scanNumericLiteral(); |
| |
| case 46: // . |
| if (isDecDigit(next)) return scanNumericLiteral(); |
| if (46 === next) { |
| if (46 === input.charCodeAt(index + 2)) return scanVarargLiteral(); |
| return scanPunctuator('..'); |
| } |
| return scanPunctuator('.'); |
| |
| case 61: // = |
| if (61 === next) return scanPunctuator('=='); |
| return scanPunctuator('='); |
| |
| case 62: // > |
| if (61 === next) return scanPunctuator('>='); |
| return scanPunctuator('>'); |
| |
| case 60: // < |
| if (61 === next) return scanPunctuator('<='); |
| return scanPunctuator('<'); |
| |
| case 126: // ~ |
| if (61 === next) return scanPunctuator('~='); |
| return raise({}, errors.expected, '=', '~'); |
| |
| case 58: // : |
| if (58 === next) return scanPunctuator('::'); |
| return scanPunctuator(':'); |
| |
| case 91: // [ |
| if (91 === next || 61 === next) return scanLongStringLiteral(); |
| return scanPunctuator('['); |
| case 42: case 47: case 94: case 37: case 44: case 123: case 125: |
| case 93: case 40: case 41: case 59: case 35: case 45: case 43: |
| return scanPunctuator(input.charAt(index)); |
| } |
| |
| return unexpected(input.charAt(index)); |
| } |
| |
| function skipWhiteSpace() { |
| while (index < length) { |
| var charCode = input.charCodeAt(index); |
| if (isWhiteSpace(charCode)) { |
| index++; |
| } else if (isLineTerminator(charCode)) { |
| line++; |
| lineStart = ++index; |
| } else { |
| break; |
| } |
| } |
| } |
| |
| function scanIdentifierOrKeyword() { |
| var value, type; |
| while (isIdentifierPart(input.charCodeAt(++index))); |
| value = input.slice(tokenStart, index); |
| if (isKeyword(value)) { |
| type = Keyword; |
| } else if ('true' === value || 'false' === value) { |
| type = BooleanLiteral; |
| value = ('true' === value); |
| } else if ('nil' === value) { |
| type = NilLiteral; |
| value = null; |
| } else { |
| type = Identifier; |
| } |
| |
| return { |
| type: type |
| , value: value |
| , line: line |
| , lineStart: lineStart |
| , range: [tokenStart, index] |
| }; |
| } |
| |
| function scanPunctuator(value) { |
| index += value.length; |
| return { |
| type: Punctuator |
| , value: value |
| , line: line |
| , lineStart: lineStart |
| , range: [tokenStart, index] |
| }; |
| } |
| |
| function scanVarargLiteral() { |
| index += 3; |
| return { |
| type: VarargLiteral |
| , value: '...' |
| , line: line |
| , lineStart: lineStart |
| , range: [tokenStart, index] |
| }; |
| } |
| |
| function scanStringLiteral() { |
| var delimiter = input.charCodeAt(index++) |
| , stringStart = index |
| , string = '' |
| , charCode; |
| |
| while (index < length) { |
| charCode = input.charCodeAt(index++); |
| if (delimiter === charCode) break; |
| if (92 === charCode) { // \ |
| string += input.slice(stringStart, index - 1) + readEscapeSequence(); |
| stringStart = index; |
| } |
| else if (index >= length || isLineTerminator(charCode)) { |
| string += input.slice(stringStart, index - 1); |
| raise({}, errors.unfinishedString, string + String.fromCharCode(charCode)); |
| } |
| } |
| string += input.slice(stringStart, index - 1); |
| |
| return { |
| type: StringLiteral |
| , value: string |
| , line: line |
| , lineStart: lineStart |
| , range: [tokenStart, index] |
| }; |
| } |
| |
| function scanLongStringLiteral() { |
| var string = readLongString(); |
| if (false === string) raise(token, errors.expected, '[', token.value); |
| |
| return { |
| type: StringLiteral |
| , value: string |
| , line: line |
| , lineStart: lineStart |
| , range: [tokenStart, index] |
| }; |
| } |
| |
| function scanNumericLiteral() { |
| var character = input.charAt(index) |
| , next = input.charAt(index + 1); |
| |
| var value = ('0' === character && 'xX'.indexOf(next || null) >= 0) ? |
| readHexLiteral() : readDecLiteral(); |
| |
| return { |
| type: NumericLiteral |
| , value: value |
| , line: line |
| , lineStart: lineStart |
| , range: [tokenStart, index] |
| }; |
| } |
| |
| function readHexLiteral() { |
| var fraction = 0 // defaults to 0 as it gets summed |
| , binaryExponent = 1 // defaults to 1 as it gets multiplied |
| , binarySign = 1 // positive |
| , digit, fractionStart, exponentStart, digitStart; |
| |
| digitStart = index += 2; // Skip 0x part |
| if (!isHexDigit(input.charCodeAt(index))) |
| raise({}, errors.malformedNumber, input.slice(tokenStart, index)); |
| |
| while (isHexDigit(input.charCodeAt(index))) index++; |
| digit = parseInt(input.slice(digitStart, index), 16); |
| if ('.' === input.charAt(index)) { |
| fractionStart = ++index; |
| |
| while (isHexDigit(input.charCodeAt(index))) index++; |
| fraction = input.slice(fractionStart, index); |
| fraction = (fractionStart === index) ? 0 |
| : parseInt(fraction, 16) / Math.pow(16, index - fractionStart); |
| } |
| if ('pP'.indexOf(input.charAt(index) || null) >= 0) { |
| index++; |
| if ('+-'.indexOf(input.charAt(index) || null) >= 0) |
| binarySign = ('+' === input.charAt(index++)) ? 1 : -1; |
| |
| exponentStart = index; |
| if (!isDecDigit(input.charCodeAt(index))) |
| raise({}, errors.malformedNumber, input.slice(tokenStart, index)); |
| |
| while (isDecDigit(input.charCodeAt(index))) index++; |
| binaryExponent = input.slice(exponentStart, index); |
| binaryExponent = Math.pow(2, binaryExponent * binarySign); |
| } |
| |
| return (digit + fraction) * binaryExponent; |
| } |
| |
| function readDecLiteral() { |
| while (isDecDigit(input.charCodeAt(index))) index++; |
| if ('.' === input.charAt(index)) { |
| index++; |
| while (isDecDigit(input.charCodeAt(index))) index++; |
| } |
| if ('eE'.indexOf(input.charAt(index) || null) >= 0) { |
| index++; |
| if ('+-'.indexOf(input.charAt(index) || null) >= 0) index++; |
| if (!isDecDigit(input.charCodeAt(index))) |
| raise({}, errors.malformedNumber, input.slice(tokenStart, index)); |
| |
| while (isDecDigit(input.charCodeAt(index))) index++; |
| } |
| |
| return parseFloat(input.slice(tokenStart, index)); |
| } |
| |
| function readEscapeSequence() { |
| var sequenceStart = index; |
| switch (input.charAt(index)) { |
| case 'n': index++; return '\n'; |
| case 'r': index++; return '\r'; |
| case 't': index++; return '\t'; |
| case 'v': index++; return '\x0B'; |
| case 'b': index++; return '\b'; |
| case 'f': index++; return '\f'; |
| case 'z': index++; skipWhiteSpace(); return ''; |
| case 'x': |
| if (isHexDigit(input.charCodeAt(index + 1)) && |
| isHexDigit(input.charCodeAt(index + 2))) { |
| index += 3; |
| return '\\' + input.slice(sequenceStart, index); |
| } |
| return '\\' + input.charAt(index++); |
| default: |
| if (isDecDigit(input.charCodeAt(index))) { |
| while (isDecDigit(input.charCodeAt(++index))); |
| return '\\' + input.slice(sequenceStart, index); |
| } |
| return input.charAt(index++); |
| } |
| } |
| |
| function scanComment() { |
| tokenStart = index; |
| index += 2; // -- |
| |
| var character = input.charAt(index) |
| , content = '' |
| , isLong = false |
| , commentStart = index |
| , lineStartComment = lineStart |
| , lineComment = line; |
| |
| if ('[' === character) { |
| content = readLongString(); |
| if (false === content) content = character; |
| else isLong = true; |
| } |
| if (!isLong) { |
| while (index < length) { |
| if (isLineTerminator(input.charCodeAt(index))) break; |
| index++; |
| } |
| if (options.comments) content = input.slice(commentStart, index); |
| } |
| |
| if (options.comments) { |
| var node = ast.comment(content, input.slice(tokenStart, index)); |
| if (options.locations) { |
| node.loc = { |
| start: { line: lineComment, column: tokenStart - lineStartComment } |
| , end: { line: line, column: index - lineStart } |
| }; |
| } |
| if (options.ranges) { |
| node.range = [tokenStart, index]; |
| } |
| comments.push(node); |
| } |
| } |
| |
| function readLongString() { |
| var level = 0 |
| , content = '' |
| , terminator = false |
| , character, stringStart; |
| |
| index++; // [ |
| while ('=' === input.charAt(index + level)) level++; |
| if ('[' !== input.charAt(index + level)) return false; |
| |
| index += level + 1; |
| if (isLineTerminator(input.charCodeAt(index))) { |
| line++; |
| lineStart = index++; |
| } |
| |
| stringStart = index; |
| while (index < length) { |
| character = input.charAt(index++); |
| if (isLineTerminator(character.charCodeAt(0))) { |
| line++; |
| lineStart = index; |
| } |
| if (']' === character) { |
| terminator = true; |
| for (var i = 0; i < level; i++) { |
| if ('=' !== input.charAt(index + i)) terminator = false; |
| } |
| if (']' !== input.charAt(index + level)) terminator = false; |
| } |
| if (terminator) break; |
| } |
| content += input.slice(stringStart, index - 1); |
| index += level + 1; |
| |
| return content; |
| } |
| |
| function next() { |
| previousToken = token; |
| token = lookahead; |
| lookahead = lex(); |
| } |
| |
| function consume(value) { |
| if (value === token.value) { |
| next(); |
| return true; |
| } |
| return false; |
| } |
| |
| function expect(value) { |
| if (value === token.value) next(); |
| else raise(token, errors.expected, value, token.value); |
| } |
| |
| function isWhiteSpace(charCode) { |
| return 9 === charCode || 32 === charCode || 0xB === charCode || 0xC === charCode; |
| } |
| |
| function isLineTerminator(charCode) { |
| return 10 === charCode || 13 === charCode; |
| } |
| |
| function isDecDigit(charCode) { |
| return charCode >= 48 && charCode <= 57; |
| } |
| |
| function isHexDigit(charCode) { |
| return (charCode >= 48 && charCode <= 57) || (charCode >= 97 && charCode <= 102) || (charCode >= 65 && charCode <= 70); |
| } |
| |
| function isIdentifierStart(charCode) { |
| return (charCode >= 65 && charCode <= 90) || (charCode >= 97 && charCode <= 122) || 95 === charCode; |
| } |
| |
| function isIdentifierPart(charCode) { |
| return (charCode >= 65 && charCode <= 90) || (charCode >= 97 && charCode <= 122) || 95 === charCode || (charCode >= 48 && charCode <= 57); |
| } |
| |
| function isKeyword(id) { |
| switch (id.length) { |
| case 2: |
| return 'do' === id || 'if' === id || 'in' === id || 'or' === id; |
| case 3: |
| return 'and' === id || 'end' === id || 'for' === id || 'not' === id; |
| case 4: |
| return 'else' === id || 'goto' === id || 'then' === id; |
| case 5: |
| return 'break' === id || 'local' === id || 'until' === id || 'while' === id; |
| case 6: |
| return 'elseif' === id || 'repeat' === id || 'return' === id; |
| case 8: |
| return 'function' === id; |
| } |
| return false; |
| } |
| |
| function isUnary(token) { |
| if (Punctuator === token.type) return '#-'.indexOf(token.value) >= 0; |
| if (Keyword === token.type) return 'not' === token.value; |
| return false; |
| } |
| function isCallExpression(expression) { |
| switch (expression.type) { |
| case 'CallExpression': |
| case 'TableCallExpression': |
| case 'StringCallExpression': |
| return true; |
| } |
| return false; |
| } |
| |
| function isBlockFollow(token) { |
| if (EOF === token.type) return true; |
| if (Keyword !== token.type) return false; |
| switch (token.value) { |
| case 'else': case 'elseif': |
| case 'end': case 'until': |
| return true; |
| default: |
| return false; |
| } |
| } |
| var scopes |
| , scopeDepth |
| , globals; |
| function createScope() { |
| scopes.push(Array.apply(null, scopes[scopeDepth++])); |
| } |
| function exitScope() { |
| scopes.pop(); |
| scopeDepth--; |
| } |
| function scopeIdentifierName(name) { |
| if (-1 !== indexOf(scopes[scopeDepth], name)) return; |
| scopes[scopeDepth].push(name); |
| } |
| function scopeIdentifier(node) { |
| scopeIdentifierName(node.name); |
| attachScope(node, true); |
| } |
| function attachScope(node, isLocal) { |
| if (!isLocal && -1 === indexOfObject(globals, 'name', node.name)) |
| globals.push(node); |
| |
| node.isLocal = isLocal; |
| } |
| function scopeHasName(name) { |
| return (-1 !== indexOf(scopes[scopeDepth], name)); |
| } |
| |
| var locations = [] |
| , trackLocations; |
| |
| function createLocationMarker() { |
| return new Marker(token); |
| } |
| |
| function Marker(token) { |
| if (options.locations) { |
| this.loc = { |
| start: { |
| line: token.line |
| , column: token.range[0] - token.lineStart |
| } |
| , end: { |
| line: 0 |
| , column: 0 |
| } |
| }; |
| } |
| if (options.ranges) this.range = [token.range[0], 0]; |
| } |
| Marker.prototype.complete = function() { |
| if (options.locations) { |
| this.loc.end.line = previousToken.line; |
| this.loc.end.column = previousToken.range[1] - previousToken.lineStart; |
| } |
| if (options.ranges) { |
| this.range[1] = previousToken.range[1]; |
| } |
| }; |
| function markLocation() { |
| if (trackLocations) locations.push(createLocationMarker()); |
| } |
| function pushLocation(marker) { |
| if (trackLocations) locations.push(marker); |
| } |
| |
| function parseChunk() { |
| next(); |
| markLocation(); |
| var body = parseBlock(); |
| if (EOF !== token.type) unexpected(token); |
| if (trackLocations && !body.length) previousToken = token; |
| return finishNode(ast.chunk(body)); |
| } |
| |
| function parseBlock(terminator) { |
| var block = [] |
| , statement; |
| if (options.scope) createScope(); |
| |
| while (!isBlockFollow(token)) { |
| if ('return' === token.value) { |
| block.push(parseStatement()); |
| break; |
| } |
| statement = parseStatement(); |
| if (statement) block.push(statement); |
| } |
| |
| if (options.scope) exitScope(); |
| return block; |
| } |
| |
| function parseStatement() { |
| markLocation(); |
| if (Keyword === token.type) { |
| switch (token.value) { |
| case 'local': next(); return parseLocalStatement(); |
| case 'if': next(); return parseIfStatement(); |
| case 'return': next(); return parseReturnStatement(); |
| case 'function': next(); |
| var name = parseFunctionName(); |
| return parseFunctionDeclaration(name); |
| case 'while': next(); return parseWhileStatement(); |
| case 'for': next(); return parseForStatement(); |
| case 'repeat': next(); return parseRepeatStatement(); |
| case 'break': next(); return parseBreakStatement(); |
| case 'do': next(); return parseDoStatement(); |
| case 'goto': next(); return parseGotoStatement(); |
| } |
| } |
| |
| if (Punctuator === token.type) { |
| if (consume('::')) return parseLabelStatement(); |
| } |
| if (trackLocations) locations.pop(); |
| if (consume(';')) return; |
| |
| return parseAssignmentOrCallStatement(); |
| } |
| |
| function parseLabelStatement() { |
| var name = token.value |
| , label = parseIdentifier(); |
| |
| if (options.scope) { |
| scopeIdentifierName('::' + name + '::'); |
| attachScope(label, true); |
| } |
| |
| expect('::'); |
| return finishNode(ast.labelStatement(label)); |
| } |
| |
| function parseBreakStatement() { |
| return finishNode(ast.breakStatement()); |
| } |
| |
| function parseGotoStatement() { |
| var name = token.value |
| , label = parseIdentifier(); |
| |
| if (options.scope) label.isLabel = scopeHasName('::' + name + '::'); |
| return finishNode(ast.gotoStatement(label)); |
| } |
| |
| function parseDoStatement() { |
| var body = parseBlock(); |
| expect('end'); |
| return finishNode(ast.doStatement(body)); |
| } |
| |
| function parseWhileStatement() { |
| var condition = parseExpectedExpression(); |
| expect('do'); |
| var body = parseBlock(); |
| expect('end'); |
| return finishNode(ast.whileStatement(condition, body)); |
| } |
| |
| function parseRepeatStatement() { |
| var body = parseBlock(); |
| expect('until'); |
| var condition = parseExpectedExpression(); |
| return finishNode(ast.repeatStatement(condition, body)); |
| } |
| |
| function parseReturnStatement() { |
| var expressions = []; |
| |
| if ('end' !== token.value) { |
| var expression = parseExpression(); |
| if (null != expression) expressions.push(expression); |
| while (consume(',')) { |
| expression = parseExpectedExpression(); |
| expressions.push(expression); |
| } |
| consume(';'); // grammar tells us ; is optional here. |
| } |
| return finishNode(ast.returnStatement(expressions)); |
| } |
| |
| function parseIfStatement() { |
| var clauses = [] |
| , condition |
| , body |
| , marker; |
| if (trackLocations) { |
| marker = locations[locations.length - 1]; |
| locations.push(marker); |
| } |
| condition = parseExpectedExpression(); |
| expect('then'); |
| body = parseBlock(); |
| clauses.push(finishNode(ast.ifClause(condition, body))); |
| |
| if (trackLocations) marker = createLocationMarker(); |
| while (consume('elseif')) { |
| pushLocation(marker); |
| condition = parseExpectedExpression(); |
| expect('then'); |
| body = parseBlock(); |
| clauses.push(finishNode(ast.elseifClause(condition, body))); |
| if (trackLocations) marker = createLocationMarker(); |
| } |
| |
| if (consume('else')) { |
| if (trackLocations) { |
| marker = new Marker(previousToken); |
| locations.push(marker); |
| } |
| body = parseBlock(); |
| clauses.push(finishNode(ast.elseClause(body))); |
| } |
| |
| expect('end'); |
| return finishNode(ast.ifStatement(clauses)); |
| } |
| |
| function parseForStatement() { |
| var variable = parseIdentifier() |
| , body; |
| if (options.scope) scopeIdentifier(variable); |
| if (consume('=')) { |
| var start = parseExpectedExpression(); |
| expect(','); |
| var end = parseExpectedExpression(); |
| var step = consume(',') ? parseExpectedExpression() : null; |
| |
| expect('do'); |
| body = parseBlock(); |
| expect('end'); |
| |
| return finishNode(ast.forNumericStatement(variable, start, end, step, body)); |
| } |
| else { |
| var variables = [variable]; |
| while (consume(',')) { |
| variable = parseIdentifier(); |
| if (options.scope) scopeIdentifier(variable); |
| variables.push(variable); |
| } |
| expect('in'); |
| var iterators = []; |
| do { |
| var expression = parseExpectedExpression(); |
| iterators.push(expression); |
| } while (consume(',')); |
| |
| expect('do'); |
| body = parseBlock(); |
| expect('end'); |
| |
| return finishNode(ast.forGenericStatement(variables, iterators, body)); |
| } |
| } |
| |
| function parseLocalStatement() { |
| var name; |
| |
| if (Identifier === token.type) { |
| var variables = [] |
| , init = []; |
| |
| do { |
| name = parseIdentifier(); |
| |
| variables.push(name); |
| } while (consume(',')); |
| |
| if (consume('=')) { |
| do { |
| var expression = parseExpectedExpression(); |
| init.push(expression); |
| } while (consume(',')); |
| } |
| if (options.scope) { |
| for (var i = 0, l = variables.length; i < l; i++) { |
| scopeIdentifier(variables[i]); |
| } |
| } |
| |
| return finishNode(ast.localStatement(variables, init)); |
| } |
| if (consume('function')) { |
| name = parseIdentifier(); |
| if (options.scope) scopeIdentifier(name); |
| return parseFunctionDeclaration(name, true); |
| } else { |
| raiseUnexpectedToken('<name>', token); |
| } |
| } |
| |
| function parseAssignmentOrCallStatement() { |
| var previous = token |
| , expression, marker; |
| |
| if (trackLocations) marker = createLocationMarker(); |
| expression = parsePrefixExpression(); |
| |
| if (null == expression) return unexpected(token); |
| if (',='.indexOf(token.value) >= 0) { |
| var variables = [expression] |
| , init = [] |
| , exp; |
| |
| while (consume(',')) { |
| exp = parsePrefixExpression(); |
| if (null == exp) raiseUnexpectedToken('<expression>', token); |
| variables.push(exp); |
| } |
| expect('='); |
| do { |
| exp = parseExpectedExpression(); |
| init.push(exp); |
| } while (consume(',')); |
| |
| pushLocation(marker); |
| return finishNode(ast.assignmentStatement(variables, init)); |
| } |
| if (isCallExpression(expression)) { |
| pushLocation(marker); |
| return finishNode(ast.callStatement(expression)); |
| } |
| return unexpected(previous); |
| } |
| |
| function parseIdentifier() { |
| markLocation(); |
| var identifier = token.value; |
| if (Identifier !== token.type) raiseUnexpectedToken('<name>', token); |
| next(); |
| return finishNode(ast.identifier(identifier)); |
| } |
| |
| function parseFunctionDeclaration(name, isLocal) { |
| var parameters = []; |
| expect('('); |
| if (!consume(')')) { |
| while (true) { |
| if (Identifier === token.type) { |
| var parameter = parseIdentifier(); |
| if (options.scope) scopeIdentifier(parameter); |
| |
| parameters.push(parameter); |
| |
| if (consume(',')) continue; |
| else if (consume(')')) break; |
| } |
| else if (VarargLiteral === token.type) { |
| parameters.push(parsePrimaryExpression()); |
| expect(')'); |
| break; |
| } else { |
| raiseUnexpectedToken('<name> or \'...\'', token); |
| } |
| } |
| } |
| |
| var body = parseBlock(); |
| expect('end'); |
| |
| isLocal = isLocal || false; |
| return finishNode(ast.functionStatement(name, parameters, isLocal, body)); |
| } |
| |
| function parseFunctionName() { |
| var base, name, marker; |
| |
| if (trackLocations) marker = createLocationMarker(); |
| base = parseIdentifier(); |
| |
| if (options.scope) attachScope(base, false); |
| |
| while (consume('.')) { |
| pushLocation(marker); |
| name = parseIdentifier(); |
| if (options.scope) attachScope(name, false); |
| base = finishNode(ast.memberExpression(base, '.', name)); |
| } |
| |
| if (consume(':')) { |
| pushLocation(marker); |
| name = parseIdentifier(); |
| if (options.scope) attachScope(name, false); |
| base = finishNode(ast.memberExpression(base, ':', name)); |
| } |
| |
| return base; |
| } |
| |
| function parseTableConstructor() { |
| var fields = [] |
| , key, value; |
| |
| while (true) { |
| markLocation(); |
| if (Punctuator === token.type && consume('[')) { |
| key = parseExpectedExpression(); |
| expect(']'); |
| expect('='); |
| value = parseExpectedExpression(); |
| fields.push(finishNode(ast.tableKey(key, value))); |
| } else if (Identifier === token.type) { |
| key = parseExpectedExpression(); |
| if (consume('=')) { |
| value = parseExpectedExpression(); |
| fields.push(finishNode(ast.tableKeyString(key, value))); |
| } else { |
| fields.push(finishNode(ast.tableValue(key))); |
| } |
| } else { |
| if (null == (value = parseExpression())) { |
| locations.pop(); |
| break; |
| } |
| fields.push(finishNode(ast.tableValue(value))); |
| } |
| if (',;'.indexOf(token.value) >= 0) { |
| next(); |
| continue; |
| } |
| if ('}' === token.value) break; |
| } |
| expect('}'); |
| return finishNode(ast.tableConstructorExpression(fields)); |
| } |
| |
| function parseExpression() { |
| var expression = parseSubExpression(0); |
| return expression; |
| } |
| |
| function parseExpectedExpression() { |
| var expression = parseExpression(); |
| if (null == expression) raiseUnexpectedToken('<expression>', token); |
| else return expression; |
| } |
| |
| function binaryPrecedence(operator) { |
| var charCode = operator.charCodeAt(0) |
| , length = operator.length; |
| |
| if (1 === length) { |
| switch (charCode) { |
| case 94: return 10; // ^ |
| case 42: case 47: case 37: return 7; // * / % |
| case 43: case 45: return 6; // + - |
| case 60: case 62: return 3; // < > |
| } |
| } else if (2 === length) { |
| switch (charCode) { |
| case 46: return 5; // .. |
| case 60: case 62: case 61: case 126: return 3; // <= >= == ~= |
| case 111: return 1; // or |
| } |
| } else if (97 === charCode && 'and' === operator) return 2; |
| return 0; |
| } |
| |
| function parseSubExpression(minPrecedence) { |
| var operator = token.value |
| , expression, marker; |
| |
| if (trackLocations) marker = createLocationMarker(); |
| if (isUnary(token)) { |
| markLocation(); |
| next(); |
| var argument = parseSubExpression(8); |
| if (argument == null) raiseUnexpectedToken('<expression>', token); |
| expression = finishNode(ast.unaryExpression(operator, argument)); |
| } |
| if (null == expression) { |
| expression = parsePrimaryExpression(); |
| if (null == expression) { |
| expression = parsePrefixExpression(); |
| } |
| } |
| if (null == expression) return null; |
| |
| var precedence; |
| while (true) { |
| operator = token.value; |
| |
| precedence = (Punctuator === token.type || Keyword === token.type) ? |
| binaryPrecedence(operator) : 0; |
| |
| if (precedence === 0 || precedence <= minPrecedence) break; |
| if ('^' === operator || '..' === operator) precedence--; |
| next(); |
| var right = parseSubExpression(precedence); |
| if (null == right) raiseUnexpectedToken('<expression>', token); |
| if (trackLocations) locations.push(marker); |
| expression = finishNode(ast.binaryExpression(operator, expression, right)); |
| |
| } |
| return expression; |
| } |
| |
| function parsePrefixExpression() { |
| var base, name, marker |
| , isLocal; |
| |
| if (trackLocations) marker = createLocationMarker(); |
| if (Identifier === token.type) { |
| name = token.value; |
| base = parseIdentifier(); |
| if (options.scope) attachScope(base, isLocal = scopeHasName(name)); |
| } else if (consume('(')) { |
| base = parseExpectedExpression(); |
| expect(')'); |
| if (options.scope) isLocal = base.isLocal; |
| } else { |
| return null; |
| } |
| var expression, identifier; |
| while (true) { |
| if (Punctuator === token.type) { |
| switch (token.value) { |
| case '[': |
| pushLocation(marker); |
| next(); |
| expression = parseExpectedExpression(); |
| base = finishNode(ast.indexExpression(base, expression)); |
| expect(']'); |
| break; |
| case '.': |
| pushLocation(marker); |
| next(); |
| identifier = parseIdentifier(); |
| if (options.scope) attachScope(identifier, isLocal); |
| base = finishNode(ast.memberExpression(base, '.', identifier)); |
| break; |
| case ':': |
| pushLocation(marker); |
| next(); |
| identifier = parseIdentifier(); |
| if (options.scope) attachScope(identifier, isLocal); |
| base = finishNode(ast.memberExpression(base, ':', identifier)); |
| pushLocation(marker); |
| base = parseCallExpression(base); |
| break; |
| case '(': case '{': // args |
| pushLocation(marker); |
| base = parseCallExpression(base); |
| break; |
| default: |
| return base; |
| } |
| } else if (StringLiteral === token.type) { |
| pushLocation(marker); |
| base = parseCallExpression(base); |
| } else { |
| break; |
| } |
| } |
| |
| return base; |
| } |
| |
| function parseCallExpression(base) { |
| if (Punctuator === token.type) { |
| switch (token.value) { |
| case '(': |
| next(); |
| var expressions = []; |
| var expression = parseExpression(); |
| if (null != expression) expressions.push(expression); |
| while (consume(',')) { |
| expression = parseExpectedExpression(); |
| expressions.push(expression); |
| } |
| |
| expect(')'); |
| return finishNode(ast.callExpression(base, expressions)); |
| |
| case '{': |
| markLocation(); |
| next(); |
| var table = parseTableConstructor(); |
| return finishNode(ast.tableCallExpression(base, table)); |
| } |
| } else if (StringLiteral === token.type) { |
| return finishNode(ast.stringCallExpression(base, parsePrimaryExpression())); |
| } |
| |
| raiseUnexpectedToken('function arguments', token); |
| } |
| |
| function parsePrimaryExpression() { |
| var literals = StringLiteral | NumericLiteral | BooleanLiteral | NilLiteral | VarargLiteral |
| , value = token.value |
| , type = token.type |
| , marker; |
| |
| if (trackLocations) marker = createLocationMarker(); |
| |
| if (type & literals) { |
| pushLocation(marker); |
| var raw = input.slice(token.range[0], token.range[1]); |
| next(); |
| return finishNode(ast.literal(type, value, raw)); |
| } else if (Keyword === type && 'function' === value) { |
| pushLocation(marker); |
| next(); |
| return parseFunctionDeclaration(null); |
| } else if (consume('{')) { |
| pushLocation(marker); |
| return parseTableConstructor(); |
| } |
| } |
| |
| exports.parse = parse; |
| |
| function parse(_input, _options) { |
| if ('undefined' === typeof _options && 'object' === typeof _input) { |
| _options = _input; |
| _input = undefined; |
| } |
| if (!_options) _options = {}; |
| |
| input = _input || ''; |
| options = extend(defaultOptions, _options); |
| index = 0; |
| line = 1; |
| lineStart = 0; |
| length = input.length; |
| scopes = [[]]; |
| scopeDepth = 0; |
| globals = []; |
| locations = []; |
| |
| if (options.comments) comments = []; |
| if (!options.wait) return end(); |
| return exports; |
| } |
| exports.write = write; |
| |
| function write(_input) { |
| input += String(_input); |
| length = input.length; |
| return exports; |
| } |
| exports.end = end; |
| |
| function end(_input) { |
| if ('undefined' !== typeof _input) write(_input); |
| |
| length = input.length; |
| trackLocations = options.locations || options.ranges; |
| lookahead = lex(); |
| |
| var chunk = parseChunk(); |
| if (options.comments) chunk.comments = comments; |
| if (options.scope) chunk.globals = globals; |
| |
| if (locations.length > 0) |
| throw new Error('Location tracking failed. This is most likely a bug in luaparse'); |
| |
| return chunk; |
| } |
| |
| })); |
| |
| }); |
| |
| define("ace/mode/lua_worker",["require","exports","module","ace/lib/oop","ace/worker/mirror","ace/mode/lua/luaparse"], function(require, exports, module) { |
| "use strict"; |
| |
| var oop = require("../lib/oop"); |
| var Mirror = require("../worker/mirror").Mirror; |
| var luaparse = require("../mode/lua/luaparse"); |
| |
| var Worker = exports.Worker = function(sender) { |
| Mirror.call(this, sender); |
| this.setTimeout(500); |
| }; |
| |
| oop.inherits(Worker, Mirror); |
| |
| (function() { |
| |
| this.onUpdate = function() { |
| var value = this.doc.getValue(); |
| var errors = []; |
| try { |
| luaparse.parse(value); |
| } catch(e) { |
| if (e instanceof SyntaxError) { |
| errors.push({ |
| row: e.line - 1, |
| column: e.column, |
| text: e.message, |
| type: "error" |
| }); |
| } |
| } |
| this.sender.emit("annotate", errors); |
| }; |
| |
| }).call(Worker.prototype); |
| |
| }); |
| |
| define("ace/lib/es5-shim",["require","exports","module"], function(require, exports, module) { |
| |
| function Empty() {} |
| |
| if (!Function.prototype.bind) { |
| Function.prototype.bind = function bind(that) { // .length is 1 |
| var target = this; |
| if (typeof target != "function") { |
| throw new TypeError("Function.prototype.bind called on incompatible " + target); |
| } |
| var args = slice.call(arguments, 1); // for normal call |
| var bound = function () { |
| |
| if (this instanceof bound) { |
| |
| var result = target.apply( |
| this, |
| args.concat(slice.call(arguments)) |
| ); |
| if (Object(result) === result) { |
| return result; |
| } |
| return this; |
| |
| } else { |
| return target.apply( |
| that, |
| args.concat(slice.call(arguments)) |
| ); |
| |
| } |
| |
| }; |
| if(target.prototype) { |
| Empty.prototype = target.prototype; |
| bound.prototype = new Empty(); |
| Empty.prototype = null; |
| } |
| return bound; |
| }; |
| } |
| var call = Function.prototype.call; |
| var prototypeOfArray = Array.prototype; |
| var prototypeOfObject = Object.prototype; |
| var slice = prototypeOfArray.slice; |
| var _toString = call.bind(prototypeOfObject.toString); |
| var owns = call.bind(prototypeOfObject.hasOwnProperty); |
| var defineGetter; |
| var defineSetter; |
| var lookupGetter; |
| var lookupSetter; |
| var supportsAccessors; |
| if ((supportsAccessors = owns(prototypeOfObject, "__defineGetter__"))) { |
| defineGetter = call.bind(prototypeOfObject.__defineGetter__); |
| defineSetter = call.bind(prototypeOfObject.__defineSetter__); |
| lookupGetter = call.bind(prototypeOfObject.__lookupGetter__); |
| lookupSetter = call.bind(prototypeOfObject.__lookupSetter__); |
| } |
| if ([1,2].splice(0).length != 2) { |
| if(function() { // test IE < 9 to splice bug - see issue #138 |
| function makeArray(l) { |
| var a = new Array(l+2); |
| a[0] = a[1] = 0; |
| return a; |
| } |
| var array = [], lengthBefore; |
| |
| array.splice.apply(array, makeArray(20)); |
| array.splice.apply(array, makeArray(26)); |
| |
| lengthBefore = array.length; //46 |
| array.splice(5, 0, "XXX"); // add one element |
| |
| lengthBefore + 1 == array.length |
| |
| if (lengthBefore + 1 == array.length) { |
| return true;// has right splice implementation without bugs |
| } |
| }()) {//IE 6/7 |
| var array_splice = Array.prototype.splice; |
| Array.prototype.splice = function(start, deleteCount) { |
| if (!arguments.length) { |
| return []; |
| } else { |
| return array_splice.apply(this, [ |
| start === void 0 ? 0 : start, |
| deleteCount === void 0 ? (this.length - start) : deleteCount |
| ].concat(slice.call(arguments, 2))) |
| } |
| }; |
| } else {//IE8 |
| Array.prototype.splice = function(pos, removeCount){ |
| var length = this.length; |
| if (pos > 0) { |
| if (pos > length) |
| pos = length; |
| } else if (pos == void 0) { |
| pos = 0; |
| } else if (pos < 0) { |
| pos = Math.max(length + pos, 0); |
| } |
| |
| if (!(pos+removeCount < length)) |
| removeCount = length - pos; |
| |
| var removed = this.slice(pos, pos+removeCount); |
| var insert = slice.call(arguments, 2); |
| var add = insert.length; |
| if (pos === length) { |
| if (add) { |
| this.push.apply(this, insert); |
| } |
| } else { |
| var remove = Math.min(removeCount, length - pos); |
| var tailOldPos = pos + remove; |
| var tailNewPos = tailOldPos + add - remove; |
| var tailCount = length - tailOldPos; |
| var lengthAfterRemove = length - remove; |
| |
| if (tailNewPos < tailOldPos) { // case A |
| for (var i = 0; i < tailCount; ++i) { |
| this[tailNewPos+i] = this[tailOldPos+i]; |
| } |
| } else if (tailNewPos > tailOldPos) { // case B |
| for (i = tailCount; i--; ) { |
| this[tailNewPos+i] = this[tailOldPos+i]; |
| } |
| } // else, add == remove (nothing to do) |
| |
| if (add && pos === lengthAfterRemove) { |
| this.length = lengthAfterRemove; // truncate array |
| this.push.apply(this, insert); |
| } else { |
| this.length = lengthAfterRemove + add; // reserves space |
| for (i = 0; i < add; ++i) { |
| this[pos+i] = insert[i]; |
| } |
| } |
| } |
| return removed; |
| }; |
| } |
| } |
| if (!Array.isArray) { |
| Array.isArray = function isArray(obj) { |
| return _toString(obj) == "[object Array]"; |
| }; |
| } |
| var boxedString = Object("a"), |
| splitString = boxedString[0] != "a" || !(0 in boxedString); |
| |
| if (!Array.prototype.forEach) { |
| Array.prototype.forEach = function forEach(fun /*, thisp*/) { |
| var object = toObject(this), |
| self = splitString && _toString(this) == "[object String]" ? |
| this.split("") : |
| object, |
| thisp = arguments[1], |
| i = -1, |
| length = self.length >>> 0; |
| if (_toString(fun) != "[object Function]") { |
| throw new TypeError(); // TODO message |
| } |
| |
| while (++i < length) { |
| if (i in self) { |
| fun.call(thisp, self[i], i, object); |
| } |
| } |
| }; |
| } |
| if (!Array.prototype.map) { |
| Array.prototype.map = function map(fun /*, thisp*/) { |
| var object = toObject(this), |
| self = splitString && _toString(this) == "[object String]" ? |
| this.split("") : |
| object, |
| length = self.length >>> 0, |
| result = Array(length), |
| thisp = arguments[1]; |
| if (_toString(fun) != "[object Function]") { |
| throw new TypeError(fun + " is not a function"); |
| } |
| |
| for (var i = 0; i < length; i++) { |
| if (i in self) |
| result[i] = fun.call(thisp, self[i], i, object); |
| } |
| return result; |
| }; |
| } |
| if (!Array.prototype.filter) { |
| Array.prototype.filter = function filter(fun /*, thisp */) { |
| var object = toObject(this), |
| self = splitString && _toString(this) == "[object String]" ? |
| this.split("") : |
| object, |
| length = self.length >>> 0, |
| result = [], |
| value, |
| thisp = arguments[1]; |
| if (_toString(fun) != "[object Function]") { |
| throw new TypeError(fun + " is not a function"); |
| } |
| |
| for (var i = 0; i < length; i++) { |
| if (i in self) { |
| value = self[i]; |
| if (fun.call(thisp, value, i, object)) { |
| result.push(value); |
| } |
| } |
| } |
| return result; |
| }; |
| } |
| if (!Array.prototype.every) { |
| Array.prototype.every = function every(fun /*, thisp */) { |
| var object = toObject(this), |
| self = splitString && _toString(this) == "[object String]" ? |
| this.split("") : |
| object, |
| length = self.length >>> 0, |
| thisp = arguments[1]; |
| if (_toString(fun) != "[object Function]") { |
| throw new TypeError(fun + " is not a function"); |
| } |
| |
| for (var i = 0; i < length; i++) { |
| if (i in self && !fun.call(thisp, self[i], i, object)) { |
| return false; |
| } |
| } |
| return true; |
| }; |
| } |
| if (!Array.prototype.some) { |
| Array.prototype.some = function some(fun /*, thisp */) { |
| var object = toObject(this), |
| self = splitString && _toString(this) == "[object String]" ? |
| this.split("") : |
| object, |
| length = self.length >>> 0, |
| thisp = arguments[1]; |
| if (_toString(fun) != "[object Function]") { |
| throw new TypeError(fun + " is not a function"); |
| } |
| |
| for (var i = 0; i < length; i++) { |
| if (i in self && fun.call(thisp, self[i], i, object)) { |
| return true; |
| } |
| } |
| return false; |
| }; |
| } |
| if (!Array.prototype.reduce) { |
| Array.prototype.reduce = function reduce(fun /*, initial*/) { |
| var object = toObject(this), |
| self = splitString && _toString(this) == "[object String]" ? |
| this.split("") : |
| object, |
| length = self.length >>> 0; |
| if (_toString(fun) != "[object Function]") { |
| throw new TypeError(fun + " is not a function"); |
| } |
| if (!length && arguments.length == 1) { |
| throw new TypeError("reduce of empty array with no initial value"); |
| } |
| |
| var i = 0; |
| var result; |
| if (arguments.length >= 2) { |
| result = arguments[1]; |
| } else { |
| do { |
| if (i in self) { |
| result = self[i++]; |
| break; |
| } |
| if (++i >= length) { |
| throw new TypeError("reduce of empty array with no initial value"); |
| } |
| } while (true); |
| } |
| |
| for (; i < length; i++) { |
| if (i in self) { |
| result = fun.call(void 0, result, self[i], i, object); |
| } |
| } |
| |
| return result; |
| }; |
| } |
| if (!Array.prototype.reduceRight) { |
| Array.prototype.reduceRight = function reduceRight(fun /*, initial*/) { |
| var object = toObject(this), |
| self = splitString && _toString(this) == "[object String]" ? |
| this.split("") : |
| object, |
| length = self.length >>> 0; |
| if (_toString(fun) != "[object Function]") { |
| throw new TypeError(fun + " is not a function"); |
| } |
| if (!length && arguments.length == 1) { |
| throw new TypeError("reduceRight of empty array with no initial value"); |
| } |
| |
| var result, i = length - 1; |
| if (arguments.length >= 2) { |
| result = arguments[1]; |
| } else { |
| do { |
| if (i in self) { |
| result = self[i--]; |
| break; |
| } |
| if (--i < 0) { |
| throw new TypeError("reduceRight of empty array with no initial value"); |
| } |
| } while (true); |
| } |
| |
| do { |
| if (i in this) { |
| result = fun.call(void 0, result, self[i], i, object); |
| } |
| } while (i--); |
| |
| return result; |
| }; |
| } |
| if (!Array.prototype.indexOf || ([0, 1].indexOf(1, 2) != -1)) { |
| Array.prototype.indexOf = function indexOf(sought /*, fromIndex */ ) { |
| var self = splitString && _toString(this) == "[object String]" ? |
| this.split("") : |
| toObject(this), |
| length = self.length >>> 0; |
| |
| if (!length) { |
| return -1; |
| } |
| |
| var i = 0; |
| if (arguments.length > 1) { |
| i = toInteger(arguments[1]); |
| } |
| i = i >= 0 ? i : Math.max(0, length + i); |
| for (; i < length; i++) { |
| if (i in self && self[i] === sought) { |
| return i; |
| } |
| } |
| return -1; |
| }; |
| } |
| if (!Array.prototype.lastIndexOf || ([0, 1].lastIndexOf(0, -3) != -1)) { |
| Array.prototype.lastIndexOf = function lastIndexOf(sought /*, fromIndex */) { |
| var self = splitString && _toString(this) == "[object String]" ? |
| this.split("") : |
| toObject(this), |
| length = self.length >>> 0; |
| |
| if (!length) { |
| return -1; |
| } |
| var i = length - 1; |
| if (arguments.length > 1) { |
| i = Math.min(i, toInteger(arguments[1])); |
| } |
| i = i >= 0 ? i : length - Math.abs(i); |
| for (; i >= 0; i--) { |
| if (i in self && sought === self[i]) { |
| return i; |
| } |
| } |
| return -1; |
| }; |
| } |
| if (!Object.getPrototypeOf) { |
| Object.getPrototypeOf = function getPrototypeOf(object) { |
| return object.__proto__ || ( |
| object.constructor ? |
| object.constructor.prototype : |
| prototypeOfObject |
| ); |
| }; |
| } |
| if (!Object.getOwnPropertyDescriptor) { |
| var ERR_NON_OBJECT = "Object.getOwnPropertyDescriptor called on a " + |
| "non-object: "; |
| Object.getOwnPropertyDescriptor = function getOwnPropertyDescriptor(object, property) { |
| if ((typeof object != "object" && typeof object != "function") || object === null) |
| throw new TypeError(ERR_NON_OBJECT + object); |
| if (!owns(object, property)) |
| return; |
| |
| var descriptor, getter, setter; |
| descriptor = { enumerable: true, configurable: true }; |
| if (supportsAccessors) { |
| var prototype = object.__proto__; |
| object.__proto__ = prototypeOfObject; |
| |
| var getter = lookupGetter(object, property); |
| var setter = lookupSetter(object, property); |
| object.__proto__ = prototype; |
| |
| if (getter || setter) { |
| if (getter) descriptor.get = getter; |
| if (setter) descriptor.set = setter; |
| return descriptor; |
| } |
| } |
| descriptor.value = object[property]; |
| return descriptor; |
| }; |
| } |
| if (!Object.getOwnPropertyNames) { |
| Object.getOwnPropertyNames = function getOwnPropertyNames(object) { |
| return Object.keys(object); |
| }; |
| } |
| if (!Object.create) { |
| var createEmpty; |
| if (Object.prototype.__proto__ === null) { |
| createEmpty = function () { |
| return { "__proto__": null }; |
| }; |
| } else { |
| createEmpty = function () { |
| var empty = {}; |
| for (var i in empty) |
| empty[i] = null; |
| empty.constructor = |
| empty.hasOwnProperty = |
| empty.propertyIsEnumerable = |
| empty.isPrototypeOf = |
| empty.toLocaleString = |
| empty.toString = |
| empty.valueOf = |
| empty.__proto__ = null; |
| return empty; |
| } |
| } |
| |
| Object.create = function create(prototype, properties) { |
| var object; |
| if (prototype === null) { |
| object = createEmpty(); |
| } else { |
| if (typeof prototype != "object") |
| throw new TypeError("typeof prototype["+(typeof prototype)+"] != 'object'"); |
| var Type = function () {}; |
| Type.prototype = prototype; |
| object = new Type(); |
| object.__proto__ = prototype; |
| } |
| if (properties !== void 0) |
| Object.defineProperties(object, properties); |
| return object; |
| }; |
| } |
| |
| function doesDefinePropertyWork(object) { |
| try { |
| Object.defineProperty(object, "sentinel", {}); |
| return "sentinel" in object; |
| } catch (exception) { |
| } |
| } |
| if (Object.defineProperty) { |
| var definePropertyWorksOnObject = doesDefinePropertyWork({}); |
| var definePropertyWorksOnDom = typeof document == "undefined" || |
| doesDefinePropertyWork(document.createElement("div")); |
| if (!definePropertyWorksOnObject || !definePropertyWorksOnDom) { |
| var definePropertyFallback = Object.defineProperty; |
| } |
| } |
| |
| if (!Object.defineProperty || definePropertyFallback) { |
| var ERR_NON_OBJECT_DESCRIPTOR = "Property description must be an object: "; |
| var ERR_NON_OBJECT_TARGET = "Object.defineProperty called on non-object: " |
| var ERR_ACCESSORS_NOT_SUPPORTED = "getters & setters can not be defined " + |
| "on this javascript engine"; |
| |
| Object.defineProperty = function defineProperty(object, property, descriptor) { |
| if ((typeof object != "object" && typeof object != "function") || object === null) |
| throw new TypeError(ERR_NON_OBJECT_TARGET + object); |
| if ((typeof descriptor != "object" && typeof descriptor != "function") || descriptor === null) |
| throw new TypeError(ERR_NON_OBJECT_DESCRIPTOR + descriptor); |
| if (definePropertyFallback) { |
| try { |
| return definePropertyFallback.call(Object, object, property, descriptor); |
| } catch (exception) { |
| } |
| } |
| if (owns(descriptor, "value")) { |
| |
| if (supportsAccessors && (lookupGetter(object, property) || |
| lookupSetter(object, property))) |
| { |
| var prototype = object.__proto__; |
| object.__proto__ = prototypeOfObject; |
| delete object[property]; |
| object[property] = descriptor.value; |
| object.__proto__ = prototype; |
| } else { |
| object[property] = descriptor.value; |
| } |
| } else { |
| if (!supportsAccessors) |
| throw new TypeError(ERR_ACCESSORS_NOT_SUPPORTED); |
| if (owns(descriptor, "get")) |
| defineGetter(object, property, descriptor.get); |
| if (owns(descriptor, "set")) |
| defineSetter(object, property, descriptor.set); |
| } |
| |
| return object; |
| }; |
| } |
| if (!Object.defineProperties) { |
| Object.defineProperties = function defineProperties(object, properties) { |
| for (var property in properties) { |
| if (owns(properties, property)) |
| Object.defineProperty(object, property, properties[property]); |
| } |
| return object; |
| }; |
| } |
| if (!Object.seal) { |
| Object.seal = function seal(object) { |
| return object; |
| }; |
| } |
| if (!Object.freeze) { |
| Object.freeze = function freeze(object) { |
| return object; |
| }; |
| } |
| try { |
| Object.freeze(function () {}); |
| } catch (exception) { |
| Object.freeze = (function freeze(freezeObject) { |
| return function freeze(object) { |
| if (typeof object == "function") { |
| return object; |
| } else { |
| return freezeObject(object); |
| } |
| }; |
| })(Object.freeze); |
| } |
| if (!Object.preventExtensions) { |
| Object.preventExtensions = function preventExtensions(object) { |
| return object; |
| }; |
| } |
| if (!Object.isSealed) { |
| Object.isSealed = function isSealed(object) { |
| return false; |
| }; |
| } |
| if (!Object.isFrozen) { |
| Object.isFrozen = function isFrozen(object) { |
| return false; |
| }; |
| } |
| if (!Object.isExtensible) { |
| Object.isExtensible = function isExtensible(object) { |
| if (Object(object) === object) { |
| throw new TypeError(); // TODO message |
| } |
| var name = ''; |
| while (owns(object, name)) { |
| name += '?'; |
| } |
| object[name] = true; |
| var returnValue = owns(object, name); |
| delete object[name]; |
| return returnValue; |
| }; |
| } |
| if (!Object.keys) { |
| var hasDontEnumBug = true, |
| dontEnums = [ |
| "toString", |
| "toLocaleString", |
| "valueOf", |
| "hasOwnProperty", |
| "isPrototypeOf", |
| "propertyIsEnumerable", |
| "constructor" |
| ], |
| dontEnumsLength = dontEnums.length; |
| |
| for (var key in {"toString": null}) { |
| hasDontEnumBug = false; |
| } |
| |
| Object.keys = function keys(object) { |
| |
| if ( |
| (typeof object != "object" && typeof object != "function") || |
| object === null |
| ) { |
| throw new TypeError("Object.keys called on a non-object"); |
| } |
| |
| var keys = []; |
| for (var name in object) { |
| if (owns(object, name)) { |
| keys.push(name); |
| } |
| } |
| |
| if (hasDontEnumBug) { |
| for (var i = 0, ii = dontEnumsLength; i < ii; i++) { |
| var dontEnum = dontEnums[i]; |
| if (owns(object, dontEnum)) { |
| keys.push(dontEnum); |
| } |
| } |
| } |
| return keys; |
| }; |
| |
| } |
| if (!Date.now) { |
| Date.now = function now() { |
| return new Date().getTime(); |
| }; |
| } |
| var ws = "\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003" + |
| "\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028" + |
| "\u2029\uFEFF"; |
| if (!String.prototype.trim || ws.trim()) { |
| ws = "[" + ws + "]"; |
| var trimBeginRegexp = new RegExp("^" + ws + ws + "*"), |
| trimEndRegexp = new RegExp(ws + ws + "*$"); |
| String.prototype.trim = function trim() { |
| return String(this).replace(trimBeginRegexp, "").replace(trimEndRegexp, ""); |
| }; |
| } |
| |
| function toInteger(n) { |
| n = +n; |
| if (n !== n) { // isNaN |
| n = 0; |
| } else if (n !== 0 && n !== (1/0) && n !== -(1/0)) { |
| n = (n > 0 || -1) * Math.floor(Math.abs(n)); |
| } |
| return n; |
| } |
| |
| function isPrimitive(input) { |
| var type = typeof input; |
| return ( |
| input === null || |
| type === "undefined" || |
| type === "boolean" || |
| type === "number" || |
| type === "string" |
| ); |
| } |
| |
| function toPrimitive(input) { |
| var val, valueOf, toString; |
| if (isPrimitive(input)) { |
| return input; |
| } |
| valueOf = input.valueOf; |
| if (typeof valueOf === "function") { |
| val = valueOf.call(input); |
| if (isPrimitive(val)) { |
| return val; |
| } |
| } |
| toString = input.toString; |
| if (typeof toString === "function") { |
| val = toString.call(input); |
| if (isPrimitive(val)) { |
| return val; |
| } |
| } |
| throw new TypeError(); |
| } |
| var toObject = function (o) { |
| if (o == null) { // this matches both null and undefined |
| throw new TypeError("can't convert "+o+" to object"); |
| } |
| return Object(o); |
| }; |
| |
| }); |