/** * Constructor * * @param msg exception message * @param cause exception cause */ protected NashornException(final String msg, final Throwable cause) { super(msg, cause == null ? null : cause); // This is not so pretty - but it gets the job done. Note that the stack // trace has been already filled by "fillInStackTrace" call from // Throwable // constructor and so we don't pay additional cost for it. // Hard luck - no column number info this.column = -1; // Find the first JavaScript frame by walking and set file, line from it // Usually, we should be able to find it in just few frames depth. for (final StackTraceElement ste : getStackTrace()) { if (ECMAErrors.isScriptFrame(ste)) { // Whatever here is compiled from JavaScript code this.fileName = ste.getFileName(); this.line = ste.getLineNumber(); return; } } this.fileName = null; this.line = 0; }
/** * Returns array javascript stack frames from the given exception object. * * @param exception exception from which stack frames are retrieved and filtered * @return array of javascript stack frames */ public static StackTraceElement[] getScriptFrames(final Throwable exception) { final StackTraceElement[] frames = exception.getStackTrace(); final List<StackTraceElement> filtered = new ArrayList<>(); for (final StackTraceElement st : frames) { if (ECMAErrors.isScriptFrame(st)) { final String className = "<" + st.getFileName() + ">"; String methodName = st.getMethodName(); if (methodName.equals(CompilerConstants.PROGRAM.symbolName())) { methodName = "<program>"; } if (methodName.contains(CompilerConstants.ANON_FUNCTION_PREFIX.symbolName())) { methodName = "<anonymous>"; } filtered.add(new StackTraceElement(className, methodName, st.getFileName(), st.getLineNumber())); } } return filtered.toArray(new StackTraceElement[filtered.size()]); }
/** * Returns array javascript stack frames from the given exception object. * * @param exception exception from which stack frames are retrieved and filtered * @return array of javascript stack frames */ public static StackTraceElement[] getScriptFrames(final Throwable exception) { final StackTraceElement[] frames = exception.getStackTrace(); final List<StackTraceElement> filtered = new ArrayList<>(); for (final StackTraceElement st : frames) { if (ECMAErrors.isScriptFrame(st)) { final String className = "<" + st.getFileName() + ">"; String methodName = st.getMethodName(); if (methodName.equals(CompilerConstants.PROGRAM.symbolName())) { methodName = "<program>"; } else { methodName = stripMethodName(methodName); } filtered.add(new StackTraceElement(className, methodName, st.getFileName(), st.getLineNumber())); } } return filtered.toArray(new StackTraceElement[0]); }
/** * Returns array javascript stack frames from the given exception object. * * @param exception exception from which stack frames are retrieved and filtered * @return array of javascript stack frames */ public static StackTraceElement[] getScriptFrames(final Throwable exception) { final StackTraceElement[] frames = exception.getStackTrace(); final List<StackTraceElement> filtered = new ArrayList<>(); for (final StackTraceElement st : frames) { if (ECMAErrors.isScriptFrame(st)) { final String className = "<" + st.getFileName() + ">"; String methodName = st.getMethodName(); if (methodName.equals(CompilerConstants.PROGRAM.symbolName())) { methodName = "<program>"; } else { methodName = stripMethodName(methodName); } filtered.add(new StackTraceElement(className, methodName, st.getFileName(), st.getLineNumber())); } } return filtered.toArray(new StackTraceElement[filtered.size()]); }
/** * Returns array javascript stack frames from the given exception object. * * @param exception exception from which stack frames are retrieved and filtered * @return array of javascript stack frames */ public static StackTraceElement[] getScriptFrames(final Throwable exception) { final StackTraceElement[] frames = exception.getStackTrace(); final List<StackTraceElement> filtered = new ArrayList<>(); for (final StackTraceElement st : frames) { if (ECMAErrors.isScriptFrame(st)) { final String className = "<" + st.getFileName() + ">"; String methodName = st.getMethodName(); if (methodName.equals(CompilerConstants.RUN_SCRIPT.symbolName())) { methodName = "<program>"; } filtered.add(new StackTraceElement(className, methodName, st.getFileName(), st.getLineNumber())); } } return filtered.toArray(new StackTraceElement[filtered.size()]); }
@Override public GuardedInvocation getGuardedInvocation(final LinkRequest linkRequest, final LinkerServices linkerServices) throws Exception { final LinkRequest request = linkRequest.withoutRuntimeContext(); // Nashorn has no runtime context final Object self = request.getReceiver(); if (self.getClass() != StaticClass.class) { return null; } final Class<?> receiverClass = ((StaticClass) self).getRepresentedClass(); Bootstrap.checkReflectionAccess(receiverClass, true); final CallSiteDescriptor desc = request.getCallSiteDescriptor(); // We intercept "new" on StaticClass instances to provide additional capabilities if ("new".equals(desc.getNameToken(CallSiteDescriptor.OPERATOR))) { if (! Modifier.isPublic(receiverClass.getModifiers())) { throw ECMAErrors.typeError("new.on.nonpublic.javatype", receiverClass.getName()); } // make sure new is on accessible Class Context.checkPackageAccess(receiverClass); // Is the class abstract? (This includes interfaces.) if (NashornLinker.isAbstractClass(receiverClass)) { // Change this link request into a link request on the adapter class. final Object[] args = request.getArguments(); args[0] = JavaAdapterFactory.getAdapterClassFor(new Class<?>[] { receiverClass }, null, linkRequest.getCallSiteDescriptor().getLookup()); final LinkRequest adapterRequest = request.replaceArguments(request.getCallSiteDescriptor(), args); final GuardedInvocation gi = checkNullConstructor(delegate(linkerServices, adapterRequest), receiverClass); // Finally, modify the guard to test for the original abstract class. return gi.replaceMethods(gi.getInvocation(), Guards.getIdentityGuard(self)); } // If the class was not abstract, just delegate linking to the standard StaticClass linker. Make an // additional check to ensure we have a constructor. We could just fall through to the next "return" // statement, except we also insert a call to checkNullConstructor() which throws an ECMAScript TypeError // with a more intuitive message when no suitable constructor is found. return checkNullConstructor(delegate(linkerServices, request), receiverClass); } // In case this was not a "new" operation, just delegate to the the standard StaticClass linker. return delegate(linkerServices, request); }
private void checkConstAssignment(final IdentNode ident) { // Check for reassignment of constant final Symbol symbol = ident.getSymbol(); if (symbol.isConst()) { throwParserException(ECMAErrors.getMessage("syntax.error.assign.constant", symbol.getName()), ident); } }
private void throwUnprotectedSwitchError(final VarNode varNode) { // Block scoped declarations in switch statements without explicit blocks should be declared // in a common block that contains all the case clauses. We cannot support this without a // fundamental rewrite of how switch statements are handled (case nodes contain blocks and are // directly contained by switch node). As a temporary solution we throw a reference error here. final String msg = ECMAErrors.getMessage("syntax.error.unprotected.switch.declaration", varNode.isLet() ? "let" : "const"); throwParserException(msg, varNode); }
private void ensureLineAndFileName() { if (lineAndFileNameUnknown) { for (final StackTraceElement ste : getStackTrace()) { if (ECMAErrors.isScriptFrame(ste)) { // Whatever here is compiled from JavaScript code fileName = ste.getFileName(); line = ste.getLineNumber(); return; } } lineAndFileNameUnknown = false; } }
private void throwNotImplementedYet(final String msgId, final Node node) { final long token = node.getToken(); final int line = source.getLine(node.getStart()); final int column = source.getColumn(node.getStart()); final String message = ECMAErrors.getMessage("unimplemented." + msgId); final String formatted = ErrorManager.format(message, source, line, column, token); throw new RuntimeException(formatted); }
ECMAException typeError() { return ECMAErrors.typeError("extend." + outcome, classList); }
private static GuardedInvocation checkNullConstructor(final GuardedInvocation ctorInvocation, final Class<?> receiverClass) { if(ctorInvocation == null) { throw ECMAErrors.typeError("no.constructor.matches.args", receiverClass.getName()); } return ctorInvocation; }
private ParserException syntaxError(final int start, final String reason) { final String message = ECMAErrors.getMessage("syntax.error.invalid.json", reason); return error(message, start); }
ECMAException typeError() { return ECMAErrors.typeError(cause, "extend." + outcome, messageArgs); }
@Override public GuardedInvocation getGuardedInvocation(final LinkRequest request, final LinkerServices linkerServices) throws Exception { final Object self = request.getReceiver(); if (self == null || self.getClass() != StaticClass.class) { return null; } final Class<?> receiverClass = ((StaticClass) self).getRepresentedClass(); Bootstrap.checkReflectionAccess(receiverClass, true); final CallSiteDescriptor desc = request.getCallSiteDescriptor(); // We intercept "new" on StaticClass instances to provide additional capabilities if (NamedOperation.getBaseOperation(desc.getOperation()) == StandardOperation.NEW) { if (! Modifier.isPublic(receiverClass.getModifiers())) { throw ECMAErrors.typeError("new.on.nonpublic.javatype", receiverClass.getName()); } // make sure new is on accessible Class Context.checkPackageAccess(receiverClass); // Is the class abstract? (This includes interfaces.) if (NashornLinker.isAbstractClass(receiverClass)) { // Change this link request into a link request on the adapter class. final Object[] args = request.getArguments(); final MethodHandles.Lookup lookup = NashornCallSiteDescriptor.getLookupInternal(request.getCallSiteDescriptor()); args[0] = JavaAdapterFactory.getAdapterClassFor(new Class<?>[] { receiverClass }, null, lookup); final LinkRequest adapterRequest = request.replaceArguments(request.getCallSiteDescriptor(), args); final GuardedInvocation gi = checkNullConstructor(delegate(linkerServices, adapterRequest), receiverClass); // Finally, modify the guard to test for the original abstract class. return gi.replaceMethods(gi.getInvocation(), Guards.getIdentityGuard(self)); } // If the class was not abstract, just delegate linking to the standard StaticClass linker. Make an // additional check to ensure we have a constructor. We could just fall through to the next "return" // statement, except we also insert a call to checkNullConstructor() which throws an ECMAScript TypeError // with a more intuitive message when no suitable constructor is found. return checkNullConstructor(delegate(linkerServices, request), receiverClass); } // In case this was not a "new" operation, just delegate to the the standard StaticClass linker. return delegate(linkerServices, request); }