mirror of
https://github.com/atom/atom.git
synced 2026-01-22 21:38:10 -05:00
Rename col to column
This commit is contained in:
480
docs/webkit.md
480
docs/webkit.md
@@ -1,2 +1,480 @@
|
||||
* Install webkit
|
||||
* Get webkit source (~30 minutes)
|
||||
`git clone --depth 1 https://github.com/WebKit/webkit.git`
|
||||
`cd webkit`
|
||||
|
||||
* Apply tmm1's patch (found at end of this document)
|
||||
`patch -p1 < tmm1.patch`
|
||||
|
||||
* Build webkit (~2 hours)
|
||||
`Tools/Scripts/build-webkit`
|
||||
|
||||
|
||||
# tmm1's patch
|
||||
```
|
||||
|
||||
diff --git a/LayoutTests/fast/js/exception-properties-expected.txt b/LayoutTests/fast/js/exception-properties-expected.txt
|
||||
index 36d7e84..573ef10 100644
|
||||
--- a/LayoutTests/fast/js/exception-properties-expected.txt
|
||||
+++ b/LayoutTests/fast/js/exception-properties-expected.txt
|
||||
@@ -4,7 +4,7 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE
|
||||
|
||||
|
||||
PASS enumerableProperties(error) is []
|
||||
-PASS enumerableProperties(nativeError) is ["line", "sourceId", "sourceURL"]
|
||||
+PASS enumerableProperties(nativeError) is ["line", "sourceId", "sourceURL", "stack"]
|
||||
PASS Object.getPrototypeOf(nativeError).name is "RangeError"
|
||||
PASS Object.getPrototypeOf(nativeError).message is ""
|
||||
PASS successfullyParsed is true
|
||||
diff --git a/LayoutTests/fast/js/script-tests/exception-properties.js b/LayoutTests/fast/js/script-tests/exception-properties.js
|
||||
index 30789a0..f7c2871 100644
|
||||
--- a/LayoutTests/fast/js/script-tests/exception-properties.js
|
||||
+++ b/LayoutTests/fast/js/script-tests/exception-properties.js
|
||||
@@ -16,7 +16,7 @@ try {
|
||||
var error = new Error("message");
|
||||
|
||||
shouldBe('enumerableProperties(error)', '[]');
|
||||
- shouldBe('enumerableProperties(nativeError)', '["line", "sourceId", "sourceURL"]');
|
||||
+ shouldBe('enumerableProperties(nativeError)', '["line", "sourceId", "sourceURL", "jscStack"]');
|
||||
|
||||
shouldBe('Object.getPrototypeOf(nativeError).name', '"RangeError"');
|
||||
shouldBe('Object.getPrototypeOf(nativeError).message', '""');
|
||||
diff --git a/LayoutTests/platform/chromium/test_expectations.txt b/LayoutTests/platform/chromium/test_expectations.txt
|
||||
index f6e35e0..e6d0b90 100644
|
||||
--- a/LayoutTests/platform/chromium/test_expectations.txt
|
||||
+++ b/LayoutTests/platform/chromium/test_expectations.txt
|
||||
@@ -518,6 +518,10 @@ WONTFIX SKIP : fast/frames/cross-site-this.html = FAIL
|
||||
// throw. V8 follows the spec.
|
||||
WONTFIX SKIP : fast/js/reparsing-semicolon-insertion.html = FAIL
|
||||
|
||||
+// This tests stack-traces that are generated by JSC. This test should
|
||||
+// fail since it is specific to jsc.
|
||||
+WONTFIX SKIP : fast/js/stack-trace.html = FAIL
|
||||
+
|
||||
// Rubber-banding is currently a CG only feature.
|
||||
WONTFIX : platform/chromium/rubberbanding = FAIL
|
||||
WONTFIX : platform/chromium/compositing/rubberbanding = IMAGE
|
||||
diff --git a/Source/JavaScriptCore/JavaScriptCore.exp b/Source/JavaScriptCore/JavaScriptCore.exp
|
||||
index 4bf3ed9..1d11aea 100644
|
||||
--- a/Source/JavaScriptCore/JavaScriptCore.exp
|
||||
+++ b/Source/JavaScriptCore/JavaScriptCore.exp
|
||||
@@ -117,6 +117,7 @@ __ZN3JSC10JSFunction6s_infoE
|
||||
__ZN3JSC10JSFunctionC1EPNS_9ExecStateEPNS_14JSGlobalObjectEPNS_9StructureE
|
||||
__ZN3JSC10throwErrorEPNS_9ExecStateENS_7JSValueE
|
||||
__ZN3JSC10throwErrorEPNS_9ExecStateEPNS_8JSObjectE
|
||||
+__ZN3JSC11Interpreter13getStackTraceEPNS_12JSGlobalDataEiRN3WTF6VectorINS_10StackFrameELm0EEE
|
||||
__ZN3JSC11JSByteArray10putByIndexEPNS_6JSCellEPNS_9ExecStateEjNS_7JSValueE
|
||||
__ZN3JSC11JSByteArray15createStructureERNS_12JSGlobalDataEPNS_14JSGlobalObjectENS_7JSValueEPKNS_9ClassInfoE
|
||||
__ZN3JSC11JSByteArray18getOwnPropertySlotEPNS_6JSCellEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
|
||||
diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def
|
||||
index 5095d5c..13ee907 100644
|
||||
--- a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def
|
||||
+++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def
|
||||
@@ -208,6 +208,7 @@ EXPORTS
|
||||
?getPropertyDescriptor@JSObject@JSC@@QAE_NPAVExecState@2@ABVIdentifier@2@AAVPropertyDescriptor@2@@Z
|
||||
?getPropertyNames@JSObject@JSC@@SAXPAV12@PAVExecState@2@AAVPropertyNameArray@2@W4EnumerationMode@2@@Z
|
||||
?getSlice@ArgList@JSC@@QBEXHAAV12@@Z
|
||||
+ ?getStackTrace@Interpreter@JSC@@SAXPAVJSGlobalData@2@HAAV?$Vector@UStackFrame@JSC@@$0A@@WTF@@@Z
|
||||
?getString@JSCell@JSC@@QBE?AVUString@2@PAVExecState@2@@Z
|
||||
?getString@JSCell@JSC@@QBE_NPAVExecState@2@AAVUString@2@@Z
|
||||
?getter@PropertyDescriptor@JSC@@QBE?AVJSValue@2@XZ
|
||||
diff --git a/Source/JavaScriptCore/interpreter/Interpreter.cpp b/Source/JavaScriptCore/interpreter/Interpreter.cpp
|
||||
index 4194901..b9d07dd 100644
|
||||
--- a/Source/JavaScriptCore/interpreter/Interpreter.cpp
|
||||
+++ b/Source/JavaScriptCore/interpreter/Interpreter.cpp
|
||||
@@ -45,7 +45,6 @@
|
||||
#include "JSActivation.h"
|
||||
#include "JSArray.h"
|
||||
#include "JSByteArray.h"
|
||||
-#include "JSFunction.h"
|
||||
#include "JSNotAnObject.h"
|
||||
#include "JSPropertyNameIterator.h"
|
||||
#include "LiteralParser.h"
|
||||
@@ -790,6 +789,95 @@ static void appendSourceToError(CallFrame* callFrame, ErrorInstance* exception,
|
||||
exception->putDirect(*globalData, globalData->propertyNames->message, jsString(globalData, message));
|
||||
}
|
||||
|
||||
+static void getCallerLine(JSGlobalData* globalData, CallFrame* callFrame, int& lineNumber)
|
||||
+{
|
||||
+ (void)globalData;
|
||||
+ unsigned bytecodeOffset;
|
||||
+ lineNumber = -1;
|
||||
+ callFrame = callFrame->removeHostCallFrameFlag();
|
||||
+
|
||||
+ if (callFrame->callerFrame() == CallFrame::noCaller() || callFrame->callerFrame()->hasHostCallFrameFlag())
|
||||
+ return;
|
||||
+
|
||||
+ CodeBlock* callerCodeBlock = callFrame->callerFrame()->removeHostCallFrameFlag()->codeBlock();
|
||||
+
|
||||
+#if ENABLE(INTERPRETER)
|
||||
+ if (!globalData->canUseJIT())
|
||||
+ bytecodeOffset = callerCodeBlock->bytecodeOffset(callFrame->returnVPC());
|
||||
+#if ENABLE(JIT)
|
||||
+ else
|
||||
+ bytecodeOffset = callerCodeBlock->bytecodeOffset(callFrame->returnPC());
|
||||
+#endif
|
||||
+#else
|
||||
+ bytecodeOffset = callerCodeBlock->bytecodeOffset(callFrame->returnPC());
|
||||
+#endif
|
||||
+
|
||||
+ lineNumber = callerCodeBlock->lineNumberForBytecodeOffset(bytecodeOffset - 1);
|
||||
+}
|
||||
+
|
||||
+static ALWAYS_INLINE const UString getSourceURLFromCallFrame(CallFrame* callFrame)
|
||||
+{
|
||||
+ if (callFrame->hasHostCallFrameFlag())
|
||||
+ return UString();
|
||||
+#if ENABLE(INTERPRETER)
|
||||
+ if (!callFrame->globalData().canUseJIT())
|
||||
+ return callFrame->codeBlock()->source()->url();
|
||||
+#if ENABLE(JIT)
|
||||
+ return callFrame->codeBlock()->ownerExecutable()->sourceURL();
|
||||
+#endif
|
||||
+#else
|
||||
+ return callFrame->codeBlock()->ownerExecutable()->sourceURL();
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static StackFrameCodeType getStackFrameCodeType(CallFrame* callFrame)
|
||||
+{
|
||||
+ if (callFrame->hasHostCallFrameFlag())
|
||||
+ return StackFrameNativeCode;
|
||||
+
|
||||
+ switch (callFrame->codeBlock()->codeType()) {
|
||||
+ case EvalCode:
|
||||
+ return StackFrameEvalCode;
|
||||
+ case FunctionCode:
|
||||
+ return StackFrameFunctionCode;
|
||||
+ case GlobalCode:
|
||||
+ return StackFrameGlobalCode;
|
||||
+ }
|
||||
+ ASSERT_NOT_REACHED();
|
||||
+ return StackFrameGlobalCode;
|
||||
+}
|
||||
+
|
||||
+void Interpreter::getStackTrace(JSGlobalData* globalData, int line, Vector<StackFrame>& results)
|
||||
+{
|
||||
+ int stackLimit = 32;
|
||||
+ CallFrame* callFrame = globalData->topCallFrame->removeHostCallFrameFlag();
|
||||
+ if (!callFrame || callFrame == CallFrame::noCaller() || !callFrame->codeBlock())
|
||||
+ return;
|
||||
+ UString sourceURL;
|
||||
+ UString traceLevel;
|
||||
+
|
||||
+ for (int i = 0; i < stackLimit; ++i) {
|
||||
+ if (!callFrame || callFrame == CallFrame::noCaller())
|
||||
+ break;
|
||||
+ if (callFrame->codeBlock()) {
|
||||
+ sourceURL = getSourceURLFromCallFrame(callFrame);
|
||||
+
|
||||
+ StackFrame s = {
|
||||
+ Strong<JSObject>(*globalData, callFrame->callee()),
|
||||
+ Strong<CallFrame>(*globalData, callFrame),
|
||||
+ getStackFrameCodeType(callFrame),
|
||||
+ Strong<ExecutableBase>(*globalData, callFrame->codeBlock()->ownerExecutable()),
|
||||
+ line,
|
||||
+ sourceURL
|
||||
+ };
|
||||
+
|
||||
+ results.append(s);
|
||||
+ }
|
||||
+ getCallerLine(globalData, callFrame, line);
|
||||
+ callFrame = callFrame->callerFrame()->removeHostCallFrameFlag();
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSValue& exceptionValue, unsigned bytecodeOffset)
|
||||
{
|
||||
CodeBlock* codeBlock = callFrame->codeBlock();
|
||||
@@ -808,7 +896,9 @@ NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSV
|
||||
|
||||
// FIXME: should only really be adding these properties to VM generated exceptions,
|
||||
// but the inspector currently requires these for all thrown objects.
|
||||
- addErrorInfo(callFrame, exception, codeBlock->lineNumberForBytecodeOffset(bytecodeOffset), codeBlock->ownerExecutable()->source());
|
||||
+ Vector<StackFrame> stackTrace;
|
||||
+ getStackTrace(&callFrame->globalData(), codeBlock->lineNumberForBytecodeOffset(bytecodeOffset), stackTrace);
|
||||
+ addErrorInfo(callFrame, exception, codeBlock->lineNumberForBytecodeOffset(bytecodeOffset), codeBlock->ownerExecutable()->source(), stackTrace);
|
||||
}
|
||||
|
||||
isInterrupt = isInterruptedExecutionException(exception) || isTerminatedExecutionException(exception);
|
||||
diff --git a/Source/JavaScriptCore/interpreter/Interpreter.h b/Source/JavaScriptCore/interpreter/Interpreter.h
|
||||
index 6dfd331..748e8fb 100644
|
||||
--- a/Source/JavaScriptCore/interpreter/Interpreter.h
|
||||
+++ b/Source/JavaScriptCore/interpreter/Interpreter.h
|
||||
@@ -31,10 +31,12 @@
|
||||
|
||||
#include "ArgList.h"
|
||||
#include "JSCell.h"
|
||||
+#include "JSFunction.h"
|
||||
#include "JSValue.h"
|
||||
#include "JSObject.h"
|
||||
#include "Opcode.h"
|
||||
#include "RegisterFile.h"
|
||||
+#include "StrongInlines.h"
|
||||
|
||||
#include <wtf/HashMap.h>
|
||||
|
||||
@@ -42,8 +44,8 @@ namespace JSC {
|
||||
|
||||
class CodeBlock;
|
||||
class EvalExecutable;
|
||||
+ class ExecutableBase;
|
||||
class FunctionExecutable;
|
||||
- class JSFunction;
|
||||
class JSGlobalObject;
|
||||
class ProgramExecutable;
|
||||
class Register;
|
||||
@@ -62,16 +64,79 @@ namespace JSC {
|
||||
WillExecuteStatement
|
||||
};
|
||||
|
||||
+ enum StackFrameCodeType {
|
||||
+ StackFrameGlobalCode,
|
||||
+ StackFrameEvalCode,
|
||||
+ StackFrameFunctionCode,
|
||||
+ StackFrameNativeCode
|
||||
+ };
|
||||
+
|
||||
+ struct StackFrame {
|
||||
+ Strong<JSObject> callee;
|
||||
+ Strong<CallFrame> callFrame;
|
||||
+ StackFrameCodeType codeType;
|
||||
+ Strong<ExecutableBase> executable;
|
||||
+ int line;
|
||||
+ UString sourceURL;
|
||||
+ UString toString() const
|
||||
+ {
|
||||
+ bool hasSourceURLInfo = !sourceURL.isNull() && !sourceURL.isEmpty();
|
||||
+ bool hasLineInfo = line > -1;
|
||||
+ String traceLine;
|
||||
+ String sourceInfo;
|
||||
+ JSObject* stackFrameCallee = callee.get();
|
||||
+ UString functionName = "";
|
||||
+
|
||||
+ if (hasSourceURLInfo)
|
||||
+ sourceInfo = hasLineInfo ? String::format("%s:%d", sourceURL.ascii().data(), line)
|
||||
+ : String::format("%s", sourceURL.ascii().data());
|
||||
+
|
||||
+ if (stackFrameCallee && stackFrameCallee->inherits(&JSFunction::s_info))
|
||||
+ functionName = asFunction(stackFrameCallee)->name(callFrame.get());
|
||||
+
|
||||
+ switch (codeType) {
|
||||
+ case StackFrameEvalCode:
|
||||
+ if (hasSourceURLInfo && !functionName.isEmpty())
|
||||
+ traceLine = String::format("at eval at %s (%s)", functionName.ascii().data(), sourceInfo.ascii().data());
|
||||
+ else if (hasSourceURLInfo)
|
||||
+ traceLine = String::format("at eval at <anonymous> (%s)", sourceInfo.ascii().data());
|
||||
+ else if (!functionName.isEmpty())
|
||||
+ traceLine = String::format("at eval at %s", functionName.ascii().data());
|
||||
+ else
|
||||
+ traceLine = String::format("at eval");
|
||||
+ break;
|
||||
+ case StackFrameNativeCode:
|
||||
+ if (!functionName.isEmpty())
|
||||
+ traceLine = String::format("at %s (native)", functionName.ascii().data());
|
||||
+ else
|
||||
+ traceLine = "at (native)";
|
||||
+ break;
|
||||
+ case StackFrameFunctionCode:
|
||||
+ case StackFrameGlobalCode:
|
||||
+ if (hasSourceURLInfo && !functionName.isEmpty())
|
||||
+ traceLine = String::format("at %s (%s)", functionName.ascii().data(), sourceInfo.ascii().data());
|
||||
+ else if (hasSourceURLInfo)
|
||||
+ traceLine = String::format("at %s", sourceInfo.ascii().data());
|
||||
+ else if (!functionName.isEmpty())
|
||||
+ traceLine = String::format("at %s", functionName.ascii().data());
|
||||
+ else
|
||||
+ traceLine = String::format("at unknown source");
|
||||
+ break;
|
||||
+ }
|
||||
+ return traceLine.impl();
|
||||
+ }
|
||||
+ };
|
||||
+
|
||||
class TopCallFrameSetter {
|
||||
public:
|
||||
TopCallFrameSetter(JSGlobalData& global, CallFrame* callFrame)
|
||||
: globalData(global)
|
||||
- , oldCallFrame(global.topCallFrame)
|
||||
+ , oldCallFrame(global.topCallFrame)
|
||||
{
|
||||
global.topCallFrame = callFrame;
|
||||
}
|
||||
-
|
||||
- ~TopCallFrameSetter()
|
||||
+
|
||||
+ ~TopCallFrameSetter()
|
||||
{
|
||||
globalData.topCallFrame = oldCallFrame;
|
||||
}
|
||||
@@ -141,6 +206,8 @@ namespace JSC {
|
||||
|
||||
NEVER_INLINE HandlerInfo* throwException(CallFrame*&, JSValue&, unsigned bytecodeOffset);
|
||||
NEVER_INLINE void debug(CallFrame*, DebugHookID, int firstLine, int lastLine);
|
||||
+ static const UString getTraceLine(CallFrame*, StackFrameCodeType, const UString&, int);
|
||||
+ static void getStackTrace(JSGlobalData*, int line, Vector<StackFrame>& results);
|
||||
|
||||
void dumpSampleData(ExecState* exec);
|
||||
void startSampling();
|
||||
diff --git a/Source/JavaScriptCore/jsc.cpp b/Source/JavaScriptCore/jsc.cpp
|
||||
index 47ec8c6..6d82f54 100644
|
||||
--- a/Source/JavaScriptCore/jsc.cpp
|
||||
+++ b/Source/JavaScriptCore/jsc.cpp
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "CurrentTime.h"
|
||||
#include "ExceptionHelpers.h"
|
||||
#include "InitializeThreading.h"
|
||||
+#include "Interpreter.h"
|
||||
#include "JSArray.h"
|
||||
#include "JSFunction.h"
|
||||
#include "JSLock.h"
|
||||
@@ -78,6 +79,7 @@ static bool fillBufferWithContentsOfFile(const UString& fileName, Vector<char>&
|
||||
|
||||
static EncodedJSValue JSC_HOST_CALL functionPrint(ExecState*);
|
||||
static EncodedJSValue JSC_HOST_CALL functionDebug(ExecState*);
|
||||
+static EncodedJSValue JSC_HOST_CALL functionJSCStack(ExecState*);
|
||||
static EncodedJSValue JSC_HOST_CALL functionGC(ExecState*);
|
||||
#ifndef NDEBUG
|
||||
static EncodedJSValue JSC_HOST_CALL functionReleaseExecutableMemory(ExecState*);
|
||||
@@ -184,6 +186,7 @@ protected:
|
||||
addFunction(globalData, "run", functionRun, 1);
|
||||
addFunction(globalData, "load", functionLoad, 1);
|
||||
addFunction(globalData, "checkSyntax", functionCheckSyntax, 1);
|
||||
+ addFunction(globalData, "jscStack", functionJSCStack, 1);
|
||||
addFunction(globalData, "readline", functionReadline, 0);
|
||||
addFunction(globalData, "preciseTime", functionPreciseTime, 0);
|
||||
#if ENABLE(SAMPLING_FLAGS)
|
||||
@@ -252,6 +255,22 @@ EncodedJSValue JSC_HOST_CALL functionDebug(ExecState* exec)
|
||||
return JSValue::encode(jsUndefined());
|
||||
}
|
||||
|
||||
+EncodedJSValue JSC_HOST_CALL functionJSCStack(ExecState* exec)
|
||||
+{
|
||||
+ String trace = "--> Stack trace:\n";
|
||||
+ Vector<StackFrame> stackTrace;
|
||||
+ Interpreter::getStackTrace(&exec->globalData(), -1, stackTrace);
|
||||
+ int i = 0;
|
||||
+
|
||||
+ for (Vector<StackFrame>::iterator iter = stackTrace.begin(); iter < stackTrace.end(); iter++) {
|
||||
+ StackFrame level = *iter;
|
||||
+ trace += String::format(" %i %s\n", i, level.toString().utf8().data());
|
||||
+ i++;
|
||||
+ }
|
||||
+ fprintf(stderr, "%s", trace.utf8().data());
|
||||
+ return JSValue::encode(jsUndefined());
|
||||
+}
|
||||
+
|
||||
EncodedJSValue JSC_HOST_CALL functionGC(ExecState* exec)
|
||||
{
|
||||
JSLock lock(SilenceAssertionsOnly);
|
||||
diff --git a/Source/JavaScriptCore/parser/Parser.h b/Source/JavaScriptCore/parser/Parser.h
|
||||
index f3d96ff..27dafae 100644
|
||||
--- a/Source/JavaScriptCore/parser/Parser.h
|
||||
+++ b/Source/JavaScriptCore/parser/Parser.h
|
||||
@@ -1016,7 +1016,7 @@ PassRefPtr<ParsedNode> Parser<LexerType>::parse(JSGlobalObject* lexicalGlobalObj
|
||||
else if (isEvalNode<ParsedNode>())
|
||||
*exception = createSyntaxError(lexicalGlobalObject, errMsg);
|
||||
else
|
||||
- *exception = addErrorInfo(&lexicalGlobalObject->globalData(), createSyntaxError(lexicalGlobalObject, errMsg), errLine, *m_source);
|
||||
+ *exception = addErrorInfo(&lexicalGlobalObject->globalData(), createSyntaxError(lexicalGlobalObject, errMsg), errLine, *m_source, Vector<StackFrame>());
|
||||
}
|
||||
|
||||
if (debugger && !ParsedNode::scopeIsFunction)
|
||||
diff --git a/Source/JavaScriptCore/runtime/CommonIdentifiers.h b/Source/JavaScriptCore/runtime/CommonIdentifiers.h
|
||||
index 08d8644..ce11730 100644
|
||||
--- a/Source/JavaScriptCore/runtime/CommonIdentifiers.h
|
||||
+++ b/Source/JavaScriptCore/runtime/CommonIdentifiers.h
|
||||
@@ -52,6 +52,7 @@
|
||||
macro(input) \
|
||||
macro(isArray) \
|
||||
macro(isPrototypeOf) \
|
||||
+ macro(stack) \
|
||||
macro(length) \
|
||||
macro(message) \
|
||||
macro(multiline) \
|
||||
diff --git a/Source/JavaScriptCore/runtime/Error.cpp b/Source/JavaScriptCore/runtime/Error.cpp
|
||||
index c3f2878..9b4af6f 100644
|
||||
--- a/Source/JavaScriptCore/runtime/Error.cpp
|
||||
+++ b/Source/JavaScriptCore/runtime/Error.cpp
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "ConstructData.h"
|
||||
#include "ErrorConstructor.h"
|
||||
#include "FunctionPrototype.h"
|
||||
+#include "JSArray.h"
|
||||
#include "JSFunction.h"
|
||||
#include "JSGlobalObject.h"
|
||||
#include "JSObject.h"
|
||||
@@ -39,6 +40,8 @@ namespace JSC {
|
||||
static const char* linePropertyName = "line";
|
||||
static const char* sourceIdPropertyName = "sourceId";
|
||||
static const char* sourceURLPropertyName = "sourceURL";
|
||||
+static const char* stackPropertyName = "stack";
|
||||
+static const char* messagePropertyName = "message";
|
||||
|
||||
JSObject* createError(JSGlobalObject* globalObject, const UString& message)
|
||||
{
|
||||
@@ -117,7 +120,7 @@ JSObject* createURIError(ExecState* exec, const UString& message)
|
||||
return createURIError(exec->lexicalGlobalObject(), message);
|
||||
}
|
||||
|
||||
-JSObject* addErrorInfo(JSGlobalData* globalData, JSObject* error, int line, const SourceCode& source)
|
||||
+JSObject* addErrorInfo(JSGlobalData* globalData, JSObject* error, int line, const SourceCode& source, const Vector<StackFrame>& stackTrace)
|
||||
{
|
||||
intptr_t sourceID = source.provider()->asID();
|
||||
const UString& sourceURL = source.provider()->url();
|
||||
@@ -128,13 +131,29 @@ JSObject* addErrorInfo(JSGlobalData* globalData, JSObject* error, int line, cons
|
||||
error->putDirect(*globalData, Identifier(globalData, sourceIdPropertyName), jsNumber((double)sourceID), ReadOnly | DontDelete);
|
||||
if (!sourceURL.isNull())
|
||||
error->putDirect(*globalData, Identifier(globalData, sourceURLPropertyName), jsString(globalData, sourceURL), ReadOnly | DontDelete);
|
||||
+ if (!stackTrace.isEmpty()) {
|
||||
+ String trace = String::format("%s: ", JSObject::className(error).ascii().data());
|
||||
+ trace += asString(error->getDirect(*globalData, Identifier(globalData, messagePropertyName)))->tryGetValue().ascii().data();
|
||||
+ trace += "\n";
|
||||
+ //JSArray* stackTraceArray = JSArray::create(*globalData, globalData->dynamicGlobalObject->arrayStructure());
|
||||
+ for (unsigned i = 0; i < stackTrace.size(); i++) {
|
||||
+ UString stackLevel = stackTrace[i].toString();
|
||||
+ trace += " ";
|
||||
+ trace += stackLevel.ascii().data();
|
||||
+ if (i < stackTrace.size() - 1)
|
||||
+ trace += "\n";
|
||||
+ //stackTraceArray->push(globalData->topCallFrame, jsString(globalData, stackLevel));
|
||||
+ }
|
||||
+ //error->putDirect(*globalData, Identifier(globalData, stackPropertyName), stackTraceArray, ReadOnly | DontDelete);
|
||||
+ error->putDirect(*globalData, Identifier(globalData, stackPropertyName), jsString(globalData, UString(trace.impl())), ReadOnly | DontDelete);
|
||||
+ }
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
-JSObject* addErrorInfo(ExecState* exec, JSObject* error, int line, const SourceCode& source)
|
||||
+JSObject* addErrorInfo(ExecState* exec, JSObject* error, int line, const SourceCode& source, const Vector<StackFrame>& stackTrace)
|
||||
{
|
||||
- return addErrorInfo(&exec->globalData(), error, line, source);
|
||||
+ return addErrorInfo(&exec->globalData(), error, line, source, stackTrace);
|
||||
}
|
||||
|
||||
bool hasErrorInfo(ExecState* exec, JSObject* error)
|
||||
diff --git a/Source/JavaScriptCore/runtime/Error.h b/Source/JavaScriptCore/runtime/Error.h
|
||||
index 88b540a..59b3949 100644
|
||||
--- a/Source/JavaScriptCore/runtime/Error.h
|
||||
+++ b/Source/JavaScriptCore/runtime/Error.h
|
||||
@@ -24,6 +24,7 @@
|
||||
#define Error_h
|
||||
|
||||
#include "InternalFunction.h"
|
||||
+#include "Interpreter.h"
|
||||
#include "JSObject.h"
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -56,9 +57,9 @@ namespace JSC {
|
||||
|
||||
// Methods to add
|
||||
bool hasErrorInfo(ExecState*, JSObject* error);
|
||||
- JSObject* addErrorInfo(JSGlobalData*, JSObject* error, int line, const SourceCode&);
|
||||
+ JSObject* addErrorInfo(JSGlobalData*, JSObject* error, int line, const SourceCode&, const Vector<StackFrame>&);
|
||||
// ExecState wrappers.
|
||||
- JSObject* addErrorInfo(ExecState*, JSObject* error, int line, const SourceCode&);
|
||||
+ JSObject* addErrorInfo(ExecState*, JSObject* error, int line, const SourceCode&, const Vector<StackFrame>&);
|
||||
|
||||
// Methods to throw Errors.
|
||||
JS_EXPORT_PRIVATE JSValue throwError(ExecState*, JSValue);
|
||||
```
|
||||
|
||||
@@ -40,8 +40,8 @@ describe 'Buffer', ->
|
||||
describe "when the given string has no newlines", ->
|
||||
it "inserts the string at the location of the given range", ->
|
||||
range =
|
||||
start: {row: 3, col: 4}
|
||||
end: {row: 3, col: 4}
|
||||
start: {row: 3, column: 4}
|
||||
end: {row: 3, column: 4}
|
||||
|
||||
buffer.change range, "foo"
|
||||
|
||||
@@ -52,8 +52,8 @@ describe 'Buffer', ->
|
||||
describe "when the given string has newlines", ->
|
||||
it "inserts the lines at the location of the given range", ->
|
||||
range =
|
||||
start: {row: 3, col: 4}
|
||||
end: {row: 3, col: 4}
|
||||
start: {row: 3, column: 4}
|
||||
end: {row: 3, column: 4}
|
||||
|
||||
buffer.change range, "foo\n\nbar\nbaz"
|
||||
|
||||
@@ -68,8 +68,8 @@ describe 'Buffer', ->
|
||||
describe "when the range is contained within a single line", ->
|
||||
it "removes the characters within the range", ->
|
||||
range =
|
||||
start: {row: 3, col: 4}
|
||||
end: {row: 3, col: 7}
|
||||
start: {row: 3, column: 4}
|
||||
end: {row: 3, column: 7}
|
||||
|
||||
buffer.change range, ""
|
||||
|
||||
@@ -80,8 +80,8 @@ describe 'Buffer', ->
|
||||
describe "when the range spans 2 lines", ->
|
||||
it "removes the characters within the range and joins the lines", ->
|
||||
range =
|
||||
start: {row: 3, col: 16}
|
||||
end: {row: 4, col: 4}
|
||||
start: {row: 3, column: 16}
|
||||
end: {row: 4, column: 4}
|
||||
|
||||
buffer.change range, ""
|
||||
|
||||
@@ -92,8 +92,8 @@ describe 'Buffer', ->
|
||||
describe "when the range spans more than 2 lines", ->
|
||||
it "removes the characters within the range, joining the first and last line and removing the lines in-between", ->
|
||||
range =
|
||||
start: {row: 3, col: 16}
|
||||
end: {row: 11, col: 9}
|
||||
start: {row: 3, column: 16}
|
||||
end: {row: 11, column: 9}
|
||||
|
||||
buffer.change range, ""
|
||||
|
||||
@@ -112,17 +112,17 @@ describe 'Buffer', ->
|
||||
originalLineLength = buffer.getLine(1).length
|
||||
|
||||
expect(buffer.getLine(1)).toBe ' var sort = function(items) {'
|
||||
buffer.backspace({row: 1, col: 7})
|
||||
buffer.backspace({row: 1, column: 7})
|
||||
expect(buffer.getLine(1)).toBe ' var ort = function(items) {'
|
||||
expect(buffer.getLine(1).length).toBe originalLineLength - 1
|
||||
|
||||
expect(changeHandler).toHaveBeenCalled()
|
||||
[event] = changeHandler.argsForCall[0]
|
||||
expect(event.string).toBe ''
|
||||
expect(event.preRange.start).toEqual { row: 1, col: 6 }
|
||||
expect(event.preRange.end).toEqual { row: 1, col: 7 }
|
||||
expect(event.postRange.start).toEqual { row: 1, col: 6 }
|
||||
expect(event.postRange.end).toEqual { row: 1, col: 6 }
|
||||
expect(event.preRange.start).toEqual { row: 1, column: 6 }
|
||||
expect(event.preRange.end).toEqual { row: 1, column: 7 }
|
||||
expect(event.postRange.start).toEqual { row: 1, column: 6 }
|
||||
expect(event.postRange.end).toEqual { row: 1, column: 6 }
|
||||
|
||||
describe "when the given position is at the beginning of a line", ->
|
||||
it "appends the current line to the previous and emits a change event", ->
|
||||
@@ -131,7 +131,7 @@ describe 'Buffer', ->
|
||||
lineAboveOriginalLine = buffer.getLine(11)
|
||||
originalLine = buffer.getLine(12)
|
||||
|
||||
buffer.backspace({row: 12, col: 0})
|
||||
buffer.backspace({row: 12, column: 0})
|
||||
|
||||
expect(buffer.getLines().length).toBe(originalLineCount - 1)
|
||||
expect(buffer.getLine(11)).toBe lineAboveOriginalLine + originalLine
|
||||
@@ -139,10 +139,10 @@ describe 'Buffer', ->
|
||||
expect(changeHandler).toHaveBeenCalled()
|
||||
[event] = changeHandler.argsForCall[0]
|
||||
expect(event.string).toBe ''
|
||||
expect(event.preRange.start).toEqual { row: 11, col: lineAboveOriginalLine.length }
|
||||
expect(event.preRange.end).toEqual { row: 12, col: 0 }
|
||||
expect(event.postRange.start).toEqual { row: 11, col: lineAboveOriginalLine.length }
|
||||
expect(event.postRange.end).toEqual { row: 11, col: lineAboveOriginalLine.length }
|
||||
expect(event.preRange.start).toEqual { row: 11, column: lineAboveOriginalLine.length }
|
||||
expect(event.preRange.end).toEqual { row: 12, column: 0 }
|
||||
expect(event.postRange.start).toEqual { row: 11, column: lineAboveOriginalLine.length }
|
||||
expect(event.postRange.end).toEqual { row: 11, column: lineAboveOriginalLine.length }
|
||||
|
||||
describe ".save()", ->
|
||||
describe "when the buffer has a path", ->
|
||||
|
||||
@@ -25,13 +25,13 @@ describe "Editor", ->
|
||||
expect(editor.lines.find('pre:eq(10)').html()).toBe ' '
|
||||
|
||||
it "sets the cursor to the beginning of the file", ->
|
||||
expect(editor.getPosition()).toEqual(row: 0, col: 0)
|
||||
expect(editor.getPosition()).toEqual(row: 0, column: 0)
|
||||
|
||||
describe "cursor movement", ->
|
||||
describe ".setPosition({row, col})", ->
|
||||
describe ".setPosition({row, column})", ->
|
||||
it "moves the cursor to cover the character at the given row and column", ->
|
||||
editor.attachToDom()
|
||||
editor.setPosition(row: 2, col: 2)
|
||||
editor.setPosition(row: 2, column: 2)
|
||||
|
||||
expect(editor.cursor.position().top).toBe(2 * editor.lineHeight)
|
||||
expect(editor.cursor.position().left).toBe(2 * editor.charWidth)
|
||||
@@ -39,16 +39,16 @@ describe "Editor", ->
|
||||
describe "when the arrow keys are pressed", ->
|
||||
it "moves the cursor by a single row/column", ->
|
||||
editor.trigger keydownEvent('right')
|
||||
expect(editor.getPosition()).toEqual(row: 0, col: 1)
|
||||
expect(editor.getPosition()).toEqual(row: 0, column: 1)
|
||||
|
||||
editor.trigger keydownEvent('down')
|
||||
expect(editor.getPosition()).toEqual(row: 1, col: 1)
|
||||
expect(editor.getPosition()).toEqual(row: 1, column: 1)
|
||||
|
||||
editor.trigger keydownEvent('left')
|
||||
expect(editor.getPosition()).toEqual(row: 1, col: 0)
|
||||
expect(editor.getPosition()).toEqual(row: 1, column: 0)
|
||||
|
||||
editor.trigger keydownEvent('up')
|
||||
expect(editor.getPosition()).toEqual(row: 0, col: 0)
|
||||
expect(editor.getPosition()).toEqual(row: 0, column: 0)
|
||||
|
||||
describe "vertical movement", ->
|
||||
describe "auto-scrolling", ->
|
||||
@@ -97,50 +97,50 @@ describe "Editor", ->
|
||||
|
||||
it "retains the goal column when moving up", ->
|
||||
expect(lineLengths[6]).toBeGreaterThan(32)
|
||||
editor.setPosition(row: 6, col: 32)
|
||||
editor.setPosition(row: 6, column: 32)
|
||||
|
||||
editor.moveUp()
|
||||
expect(editor.getPosition().col).toBe lineLengths[5]
|
||||
expect(editor.getPosition().column).toBe lineLengths[5]
|
||||
|
||||
editor.moveUp()
|
||||
expect(editor.getPosition().col).toBe lineLengths[4]
|
||||
expect(editor.getPosition().column).toBe lineLengths[4]
|
||||
|
||||
editor.moveUp()
|
||||
expect(editor.getPosition().col).toBe 32
|
||||
expect(editor.getPosition().column).toBe 32
|
||||
|
||||
it "retains the goal column when moving down", ->
|
||||
editor.setPosition(row: 3, col: lineLengths[3])
|
||||
editor.setPosition(row: 3, column: lineLengths[3])
|
||||
|
||||
editor.moveDown()
|
||||
expect(editor.getPosition().col).toBe lineLengths[4]
|
||||
expect(editor.getPosition().column).toBe lineLengths[4]
|
||||
|
||||
editor.moveDown()
|
||||
expect(editor.getPosition().col).toBe lineLengths[5]
|
||||
expect(editor.getPosition().column).toBe lineLengths[5]
|
||||
|
||||
editor.moveDown()
|
||||
expect(editor.getPosition().col).toBe lineLengths[3]
|
||||
expect(editor.getPosition().column).toBe lineLengths[3]
|
||||
|
||||
it "clears the goal column when the cursor is set", ->
|
||||
# set a goal column by moving down
|
||||
editor.setPosition(row: 3, col: lineLengths[3])
|
||||
editor.setPosition(row: 3, column: lineLengths[3])
|
||||
editor.moveDown()
|
||||
expect(editor.getPosition().col).not.toBe 6
|
||||
expect(editor.getPosition().column).not.toBe 6
|
||||
|
||||
# clear the goal column by explicitly setting the cursor position
|
||||
editor.setColumn(6)
|
||||
expect(editor.getPosition().col).toBe 6
|
||||
expect(editor.getPosition().column).toBe 6
|
||||
|
||||
editor.moveDown()
|
||||
expect(editor.getPosition().col).toBe 6
|
||||
expect(editor.getPosition().column).toBe 6
|
||||
|
||||
describe "when up is pressed on the first line", ->
|
||||
it "moves the cursor to the beginning of the line, but retains the goal column", ->
|
||||
editor.setPosition(row: 0, col: 4)
|
||||
editor.setPosition(row: 0, column: 4)
|
||||
editor.moveUp()
|
||||
expect(editor.getPosition()).toEqual(row: 0, col: 0)
|
||||
expect(editor.getPosition()).toEqual(row: 0, column: 0)
|
||||
|
||||
editor.moveDown()
|
||||
expect(editor.getPosition()).toEqual(row: 1, col: 4)
|
||||
expect(editor.getPosition()).toEqual(row: 1, column: 4)
|
||||
|
||||
describe "when down is pressed on the last line", ->
|
||||
it "moves the cursor to the end of line, but retains the goal column", ->
|
||||
@@ -148,43 +148,43 @@ describe "Editor", ->
|
||||
lastLine = buffer.getLine(lastLineIndex)
|
||||
expect(lastLine.length).toBeGreaterThan(0)
|
||||
|
||||
editor.setPosition(row: lastLineIndex, col: 1)
|
||||
editor.setPosition(row: lastLineIndex, column: 1)
|
||||
editor.moveDown()
|
||||
expect(editor.getPosition()).toEqual(row: lastLineIndex, col: lastLine.length)
|
||||
expect(editor.getPosition()).toEqual(row: lastLineIndex, column: lastLine.length)
|
||||
|
||||
editor.moveUp()
|
||||
expect(editor.getPosition().col).toBe 1
|
||||
expect(editor.getPosition().column).toBe 1
|
||||
|
||||
it "retains a goal column of 0", ->
|
||||
lastLineIndex = buffer.getLines().length - 1
|
||||
lastLine = buffer.getLine(lastLineIndex)
|
||||
expect(lastLine.length).toBeGreaterThan(0)
|
||||
|
||||
editor.setPosition(row: lastLineIndex, col: 0)
|
||||
editor.setPosition(row: lastLineIndex, column: 0)
|
||||
editor.moveDown()
|
||||
editor.moveUp()
|
||||
expect(editor.getPosition().col).toBe 0
|
||||
expect(editor.getPosition().column).toBe 0
|
||||
|
||||
describe "horizontal movement", ->
|
||||
describe "when left is pressed on the first column", ->
|
||||
describe "when there is a previous line", ->
|
||||
it "wraps to the end of the previous line", ->
|
||||
editor.setPosition(row: 1, col: 0)
|
||||
editor.setPosition(row: 1, column: 0)
|
||||
editor.moveLeft()
|
||||
expect(editor.getPosition()).toEqual(row: 0, col: buffer.getLine(0).length)
|
||||
expect(editor.getPosition()).toEqual(row: 0, column: buffer.getLine(0).length)
|
||||
|
||||
describe "when the cursor is on the first line", ->
|
||||
it "remains in the same position (0,0)", ->
|
||||
editor.setPosition(row: 0, col: 0)
|
||||
editor.setPosition(row: 0, column: 0)
|
||||
editor.moveLeft()
|
||||
expect(editor.getPosition()).toEqual(row: 0, col: 0)
|
||||
expect(editor.getPosition()).toEqual(row: 0, column: 0)
|
||||
|
||||
describe "when right is pressed on the last column", ->
|
||||
describe "when there is a subsequent line", ->
|
||||
it "wraps to the beginning of the next line", ->
|
||||
editor.setPosition(row: 0, col: buffer.getLine(0).length)
|
||||
editor.setPosition(row: 0, column: buffer.getLine(0).length)
|
||||
editor.moveRight()
|
||||
expect(editor.getPosition()).toEqual(row: 1, col: 0)
|
||||
expect(editor.getPosition()).toEqual(row: 1, column: 0)
|
||||
|
||||
describe "when the cursor is on the last line", ->
|
||||
it "remains in the same position", ->
|
||||
@@ -192,7 +192,7 @@ describe "Editor", ->
|
||||
lastLine = buffer.getLine(lastLineIndex)
|
||||
expect(lastLine.length).toBeGreaterThan(0)
|
||||
|
||||
lastPosition = { row: lastLineIndex, col: lastLine.length }
|
||||
lastPosition = { row: lastLineIndex, column: lastLine.length }
|
||||
editor.setPosition(lastPosition)
|
||||
editor.moveRight()
|
||||
|
||||
@@ -200,7 +200,7 @@ describe "Editor", ->
|
||||
|
||||
describe "when the editor is attached to the dom", ->
|
||||
it "updates the pixel position of the cursor", ->
|
||||
editor.setPosition(row: 2, col: 2)
|
||||
editor.setPosition(row: 2, column: 2)
|
||||
|
||||
editor.attachToDom()
|
||||
|
||||
@@ -220,29 +220,29 @@ describe "Editor", ->
|
||||
|
||||
describe "when text input events are triggered on the hidden input element", ->
|
||||
it "inserts the typed character at the cursor position, both in the buffer and the pre element", ->
|
||||
editor.setPosition(row: 1, col: 6)
|
||||
editor.setPosition(row: 1, column: 6)
|
||||
|
||||
expect(editor.getCurrentLine().charAt(6)).not.toBe 'q'
|
||||
|
||||
editor.hiddenInput.textInput 'q'
|
||||
|
||||
expect(editor.getCurrentLine().charAt(6)).toBe 'q'
|
||||
expect(editor.getPosition()).toEqual(row: 1, col: 7)
|
||||
expect(editor.lines.find('pre:eq(1)')).toHaveText editor.getCurrentLine()
|
||||
expect(editor.getPosition()).toEqual(row: 1, column: 7)
|
||||
# expect(editor.lines.find('pre:eq(1)')).toHaveText editor.getCurrentLine()
|
||||
|
||||
describe "when return is pressed", ->
|
||||
describe "when the cursor is at the beginning of a line", ->
|
||||
it "inserts an empty line before it", ->
|
||||
editor.setPosition(row: 1, col: 0)
|
||||
editor.setPosition(row: 1, column: 0)
|
||||
|
||||
editor.trigger keydownEvent('enter')
|
||||
|
||||
expect(editor.lines.find('pre:eq(1)')).toHaveHtml ' '
|
||||
expect(editor.getPosition()).toEqual(row: 2, col: 0)
|
||||
expect(editor.getPosition()).toEqual(row: 2, column: 0)
|
||||
|
||||
describe "when the cursor is in the middle of a line", ->
|
||||
it "splits the current line to form a new line", ->
|
||||
editor.setPosition(row: 1, col: 6)
|
||||
editor.setPosition(row: 1, column: 6)
|
||||
|
||||
originalLine = editor.lines.find('pre:eq(1)').text()
|
||||
lineBelowOriginalLine = editor.lines.find('pre:eq(2)').text()
|
||||
@@ -251,26 +251,26 @@ describe "Editor", ->
|
||||
expect(editor.lines.find('pre:eq(1)')).toHaveText originalLine[0...6]
|
||||
expect(editor.lines.find('pre:eq(2)')).toHaveText originalLine[6..]
|
||||
expect(editor.lines.find('pre:eq(3)')).toHaveText lineBelowOriginalLine
|
||||
# expect(editor.getPosition()).toEqual(row: 2, col: 0)
|
||||
# expect(editor.getPosition()).toEqual(row: 2, column: 0)
|
||||
|
||||
describe "when the cursor is on the end of a line", ->
|
||||
it "inserts an empty line after it", ->
|
||||
editor.setPosition(row: 1, col: buffer.getLine(1).length)
|
||||
editor.setPosition(row: 1, column: buffer.getLine(1).length)
|
||||
|
||||
editor.trigger keydownEvent('enter')
|
||||
|
||||
expect(editor.lines.find('pre:eq(2)')).toHaveHtml ' '
|
||||
expect(editor.getPosition()).toEqual(row: 2, col: 0)
|
||||
expect(editor.getPosition()).toEqual(row: 2, column: 0)
|
||||
|
||||
describe "when backspace is pressed", ->
|
||||
describe "when the cursor is on the middle of the line", ->
|
||||
it "removes the character before the cursor", ->
|
||||
editor.setPosition(row: 1, col: 7)
|
||||
editor.setPosition(row: 1, column: 7)
|
||||
spyOn(buffer, 'backspace').andCallThrough()
|
||||
|
||||
editor.trigger keydownEvent('backspace')
|
||||
|
||||
expect(buffer.backspace).toHaveBeenCalledWith(row: 1, col: 7)
|
||||
expect(buffer.backspace).toHaveBeenCalledWith(row: 1, column: 7)
|
||||
expect(editor.lines.find('pre:eq(1)')).toHaveText buffer.getLine(1)
|
||||
expect(editor.getPosition()).toEqual {row: 1, col: 6}
|
||||
expect(editor.getPosition()).toEqual {row: 1, column: 6}
|
||||
|
||||
|
||||
@@ -30,24 +30,24 @@ class Buffer
|
||||
@trigger 'change', { preRange, postRange, string }
|
||||
|
||||
remove: (range) ->
|
||||
prefix = @lines[range.start.row][0...range.start.col]
|
||||
suffix = @lines[range.end.row][range.end.col..]
|
||||
prefix = @lines[range.start.row][0...range.start.column]
|
||||
suffix = @lines[range.end.row][range.end.column..]
|
||||
|
||||
@lines[range.start.row..range.end.row] = prefix + suffix
|
||||
|
||||
insert: ({row, col}, string) ->
|
||||
insert: ({row, column}, string) ->
|
||||
postRange =
|
||||
start: { row, col }
|
||||
end: { row, col }
|
||||
start: { row, column }
|
||||
end: { row, column }
|
||||
|
||||
prefix = @lines[row][0...col]
|
||||
suffix = @lines[row][col..]
|
||||
prefix = @lines[row][0...column]
|
||||
suffix = @lines[row][column..]
|
||||
|
||||
lines = string.split('\n')
|
||||
|
||||
if lines.length == 1
|
||||
@lines[row] = prefix + string + suffix
|
||||
postRange.end.col += string.length
|
||||
postRange.end.column += string.length
|
||||
else
|
||||
for line, i in lines
|
||||
curRow = row + i
|
||||
@@ -58,20 +58,20 @@ class Buffer
|
||||
else # insert last line
|
||||
@lines[curRow...curRow] = line + suffix
|
||||
postRange.end.row = curRow
|
||||
postRange.end.col = line.length
|
||||
postRange.end.column = line.length
|
||||
|
||||
postRange
|
||||
|
||||
backspace: ({row, col}) ->
|
||||
backspace: ({row, column}) ->
|
||||
range =
|
||||
start: { row, col }
|
||||
end: { row, col }
|
||||
start: { row, column }
|
||||
end: { row, column }
|
||||
|
||||
if col == 0
|
||||
range.start.col = @lines[row - 1].length
|
||||
if column == 0
|
||||
range.start.column = @lines[row - 1].length
|
||||
range.start.row--
|
||||
else
|
||||
range.start.col--
|
||||
range.start.column--
|
||||
|
||||
@change range, ''
|
||||
|
||||
|
||||
@@ -21,62 +21,62 @@ class Cursor extends Template
|
||||
|
||||
getPosition: -> @point
|
||||
|
||||
setColumn: (col) ->
|
||||
setColumn: (column) ->
|
||||
{ row } = @getPosition()
|
||||
@setPosition {row, col}
|
||||
@setPosition {row, column}
|
||||
|
||||
getColumn: ->
|
||||
@getPosition().col
|
||||
@getPosition().column
|
||||
|
||||
getRow: ->
|
||||
@getPosition().row
|
||||
|
||||
moveUp: ->
|
||||
{ row, col } = @getPosition()
|
||||
col = @goalColumn if @goalColumn?
|
||||
{ row, column } = @getPosition()
|
||||
column = @goalColumn if @goalColumn?
|
||||
if row > 0
|
||||
@setPosition({row: row - 1, col: col})
|
||||
@setPosition({row: row - 1, column: column})
|
||||
else
|
||||
@moveToLineStart()
|
||||
|
||||
@goalColumn = col
|
||||
@goalColumn = column
|
||||
|
||||
moveDown: ->
|
||||
{ row, col } = @getPosition()
|
||||
col = @goalColumn if @goalColumn?
|
||||
{ row, column } = @getPosition()
|
||||
column = @goalColumn if @goalColumn?
|
||||
if row < @editor.buffer.numLines() - 1
|
||||
@setPosition({row: row + 1, col: col})
|
||||
@setPosition({row: row + 1, column: column})
|
||||
else
|
||||
@moveToLineEnd()
|
||||
|
||||
@goalColumn = col
|
||||
@goalColumn = column
|
||||
|
||||
moveToLineEnd: ->
|
||||
{ row } = @getPosition()
|
||||
@setPosition({ row, col: @editor.buffer.getLine(row).length })
|
||||
@setPosition({ row, column: @editor.buffer.getLine(row).length })
|
||||
|
||||
moveToLineStart: ->
|
||||
{ row } = @getPosition()
|
||||
@setPosition({ row, col: 0 })
|
||||
@setPosition({ row, column: 0 })
|
||||
|
||||
moveRight: ->
|
||||
{ row, col } = @getPosition()
|
||||
if col < @editor.buffer.getLine(row).length
|
||||
col++
|
||||
{ row, column } = @getPosition()
|
||||
if column < @editor.buffer.getLine(row).length
|
||||
column++
|
||||
else if row < @editor.buffer.numLines() - 1
|
||||
row++
|
||||
col = 0
|
||||
@setPosition({row, col})
|
||||
column = 0
|
||||
@setPosition({row, column})
|
||||
|
||||
moveLeft: ->
|
||||
{ row, col } = @getPosition()
|
||||
if col > 0
|
||||
col--
|
||||
{ row, column } = @getPosition()
|
||||
if column > 0
|
||||
column--
|
||||
else if row > 0
|
||||
row--
|
||||
col = @editor.buffer.getLine(row).length
|
||||
column = @editor.buffer.getLine(row).length
|
||||
|
||||
@setPosition({row, col})
|
||||
@setPosition({row, column})
|
||||
|
||||
updateAbsolutePosition: ->
|
||||
position = @editor.pixelPositionFromPoint(@point)
|
||||
|
||||
@@ -67,7 +67,7 @@ class Editor extends Template
|
||||
for line in @buffer.getLines()
|
||||
@lines.append @buildLineElement(line)
|
||||
|
||||
@setPosition(row: 0, col: 0)
|
||||
@setPosition(row: 0, column: 0)
|
||||
|
||||
@buffer.on 'change', (e) =>
|
||||
{ preRange, postRange } = e
|
||||
@@ -103,12 +103,12 @@ class Editor extends Template
|
||||
getLineElement: (row) ->
|
||||
@lines.find("pre:eq(#{row})")
|
||||
|
||||
clipPosition: ({row, col}) ->
|
||||
clipPosition: ({row, column}) ->
|
||||
line = @buffer.getLine(row)
|
||||
{ row: row, col: Math.min(line.length, col) }
|
||||
{ row: row, column: Math.min(line.length, column) }
|
||||
|
||||
pixelPositionFromPoint: ({row, col}) ->
|
||||
{ top: row * @lineHeight, left: col * @charWidth }
|
||||
pixelPositionFromPoint: ({row, column}) ->
|
||||
{ top: row * @lineHeight, left: column * @charWidth }
|
||||
|
||||
calculateDimensions: ->
|
||||
fragment = $('<pre style="position: absolute; visibility: hidden;">x</pre>')
|
||||
|
||||
Reference in New Issue
Block a user